diff --git a/.gitignore b/.gitignore index 8072807c..89c66054 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,8 @@ -## Ignore Visual Studio temporary files, build results, and +## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore -# Delphi and C# transformer -/Src/Delphi/Common/IPC/Generated Pascal/ -/Src/Net/Generated Xipc Classes/ - -/Src/Net/Apps/Gui/Gui/App.config - # User-specific files *.suo *.user @@ -48,6 +42,9 @@ TestResult.xml [Rr]eleasePS/ dlldata.c +# Benchmark Results +BenchmarkDotNet.Artifacts/ + # .NET Core project.lock.json project.fragment.lock.json @@ -154,7 +151,7 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings +# Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj @@ -189,6 +186,7 @@ AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt +*.appx # Visual Studio cache files # files ending in .cache can be ignored @@ -284,6 +282,9 @@ __pycache__/ # tools/** # !tools/packages.config +# Tabs Studio +*.tss + # Telerik's JustMock configuration file *.jmconfig @@ -292,75 +293,3 @@ __pycache__/ *.btm.cs *.odx.cs *.xsd.cs - -.vs/ - -# Uncomment these types if you want even more clean repository. But be careful. -# It can make harm to an existing project source. Read explanations below. -# -# Resource files are binaries containing manifest, project icon and version info. -# They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. -*.res -# -# Type library file (binary). In old Delphi versions it should be stored. -# Since Delphi 2009 it is produced from .ridl file and can safely be ignored. -*.tlb -# -# Diagram Portfolio file. Used by the diagram editor up to Delphi 7. -# Uncomment this if you are not using diagrams or use newer Delphi version. -#*.ddp -# -# Visual LiveBindings file. Added in Delphi XE2. -# Uncomment this if you are not using LiveBindings Designer. -#*.vlb -# -# Deployment Manager configuration file for your project. Added in Delphi XE2. -# Uncomment this if it is not mobile development and you do not use remote debug feature. -#*.deployproj -# -# C++ object files produced when C/C++ Output file generation is configured. -# Uncomment this if you are not using external objects (zlib library for example). -#*.obj -# - -# Delphi compiler-generated binaries (safe to delete) -*.exe -*.dll -*.bpl -*.bpi -*.dcp -*.so -*.apk -*.drc -*.map -*.dres -*.rsm -*.tds -*.dcu -*.lib -*.a -*.o -*.ocx - -# Delphi autogenerated files (duplicated info) -*.cfg -*.hpp -*Resource.rc - -# Delphi local files (user-specific info) -*.local -*.identcache -*.projdata -*.tvsconfig -*.dsk - -# Delphi history and backups -__history/ -__recovery/ -*.~* - -# Castalia statistics file (since XE7 Castalia is distributed with Delphi) -*.stat - -# Boss dependency manager vendor folder https://github.com/HashLoad/boss -modules/ diff --git a/ExtendedWPFToolkitSolution/Libs/READ_ME.txt b/ExtendedWPFToolkitSolution/Libs/READ_ME.txt new file mode 100644 index 00000000..973d2375 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Libs/READ_ME.txt @@ -0,0 +1,2 @@ +The file Xceed.Wpf.Samples.SampleData.dll has been created from Xceed.Silverlight.Samples.SampleData.dll of the Silverlight ListBox. +Only the Silverlight has been changed to Wpf. \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/BusyIndicator/BusyIndicator.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/BusyIndicator/BusyIndicator.xaml deleted file mode 100644 index a43fa9e1..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/BusyIndicator/BusyIndicator.xaml +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Collapsed - - - - - - - Collapsed - - - - - - - - - - - Visible - - - - - - - Visible - - - - - - - - - - - - - True - - - - - - - - - - - False - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckListBox/Implementation/CheckListBoxCheckedChangedEventArgs.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckListBox/Implementation/CheckListBoxCheckedChangedEventArgs.cs deleted file mode 100644 index 7450379c..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckListBox/Implementation/CheckListBoxCheckedChangedEventArgs.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Windows; - -namespace Microsoft.Windows.Controls -{ - public delegate void CheckListBoxCheckedChangedEventHandler(object sender, CheckListBoxCheckedChangedEventArgs e); - public class CheckListBoxCheckedChangedEventArgs : RoutedEventArgs - { - public object Item { get; private set; } - - public CheckListBoxCheckedChangedEventArgs(RoutedEvent routedEvent, object source, object item) - : base(routedEvent, source) - { - Item = item; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckListBox/Implementation/CheckListBoxItem.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckListBox/Implementation/CheckListBoxItem.cs deleted file mode 100644 index 1993c7ca..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckListBox/Implementation/CheckListBoxItem.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -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 System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using System.Windows.Controls.Primitives; - -namespace Microsoft.Windows.Controls -{ - public class CheckListBoxItem : ContentControl - { - static CheckListBoxItem() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckListBoxItem), new FrameworkPropertyMetadata(typeof(CheckListBoxItem))); - } - - public CheckListBoxItem() - { - AddHandler(Mouse.MouseDownEvent, new MouseButtonEventHandler(CheckListBoxItem_MouseDown)); - } - - #region Properties - - public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof(bool), typeof(CheckListBoxItem), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsSelectedChanged)); - public bool IsChecked - { - get { return (bool)GetValue(IsCheckedProperty); } - set { SetValue(IsCheckedProperty, value); } - } - - private static void OnIsSelectedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) - { - CheckListBoxItem checkListBoxItem = o as CheckListBoxItem; - if (checkListBoxItem != null) - checkListBoxItem.OnIsSelectedChanged((bool)e.OldValue, (bool)e.NewValue); - } - - protected virtual void OnIsSelectedChanged(bool oldValue, bool newValue) - { - if (newValue) - RaiseSelectionChangedEvent(new RoutedEventArgs(CheckListBox.CheckedEvent, this)); - else - RaiseSelectionChangedEvent(new RoutedEventArgs(CheckListBox.UncheckedEvent, this)); - } - - #endregion //Properties - - #region Events - - public static readonly RoutedEvent SelectedEvent = CheckListBox.CheckedEvent.AddOwner(typeof(CheckListBoxItem)); - public static readonly RoutedEvent UnselectedEvent = CheckListBox.UncheckedEvent.AddOwner(typeof(CheckListBoxItem)); - - #endregion - - #region Event Hanlders - - void CheckListBoxItem_MouseDown(object sender, MouseButtonEventArgs e) - { - IsChecked = !IsChecked; - } - - #endregion //Event Hanlders - - #region Methods - - private void RaiseSelectionChangedEvent(RoutedEventArgs e) - { - base.RaiseEvent(e); - } - - #endregion //Methods - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.xaml deleted file mode 100644 index 45bcc828..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.xaml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/Implementation/VisualStates.ChildWindow.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/Implementation/VisualStates.ChildWindow.cs deleted file mode 100644 index eb3a4ea9..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/Implementation/VisualStates.ChildWindow.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Microsoft.Windows.Controls -{ - internal static partial class VisualStates - { - /// - /// Window State group name. - /// - public const string WindowStatesGroup = "WindowStatesGroup"; - - /// - /// Open state name for ChildWindow. - /// - public const string Open = "Open"; - - /// - /// Closed state name for ChildWindow. - /// - public const string Closed = "Closed"; - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.xaml deleted file mode 100644 index 7b07bb77..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.xaml +++ /dev/null @@ -1,367 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorSpectrumSlider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorSpectrumSlider.cs deleted file mode 100644 index c4eac2d8..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorSpectrumSlider.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Shapes; - -namespace Microsoft.Windows.Controls -{ - internal class ColorSpectrumSlider : Slider - { - #region Private Members - - private Rectangle _spectrumDisplay; - private LinearGradientBrush _pickerBrush; - - #endregion //Private Members - - #region Constructors - - static ColorSpectrumSlider() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorSpectrumSlider), new FrameworkPropertyMetadata(typeof(ColorSpectrumSlider))); - } - - #endregion //Constructors - - #region Dependency Properties - - public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorSpectrumSlider), new PropertyMetadata(System.Windows.Media.Colors.Transparent)); - public Color SelectedColor - { - get { return (Color)GetValue(SelectedColorProperty); } - set { SetValue(SelectedColorProperty, value); } - } - - #endregion //Dependency Properties - - #region Base Class Overrides - - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - - _spectrumDisplay = (Rectangle)GetTemplateChild("PART_SpectrumDisplay"); - CreateSpectrum(); - OnValueChanged(Double.NaN, Value); - } - - protected override void OnValueChanged(double oldValue, double newValue) - { - base.OnValueChanged(oldValue, newValue); - - Color color = ColorUtilities.ConvertHsvToRgb(360 - newValue, 1, 1); - SelectedColor = color; - } - - #endregion //Base Class Overrides - - #region Methods - - private void CreateSpectrum() - { - _pickerBrush = new LinearGradientBrush(); - _pickerBrush.StartPoint = new Point(0.5, 0); - _pickerBrush.EndPoint = new Point(0.5, 1); - _pickerBrush.ColorInterpolationMode = ColorInterpolationMode.SRgbLinearInterpolation; - - List colorsList = ColorUtilities.GenerateHsvSpectrum(); - - double stopIncrement = (double)1 / colorsList.Count; - - int i; - for (i = 0; i < colorsList.Count; i++) - { - _pickerBrush.GradientStops.Add(new GradientStop(colorsList[i], i * stopIncrement)); - } - - _pickerBrush.GradientStops[i - 1].Offset = 1.0; - _spectrumDisplay.Fill = _pickerBrush; - } - - #endregion //Methods - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/HsvColor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/HsvColor.cs deleted file mode 100644 index eed5c3bd..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/HsvColor.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace Microsoft.Windows.Controls -{ - internal struct HsvColor - { - public double H; - public double S; - public double V; - - public HsvColor(double h, double s, double v) - { - H = h; - S = s; - V = v; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Themes/Generic.xaml deleted file mode 100644 index 9f6dac6a..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Themes/Generic.xaml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MessageBox/MessageBox.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MessageBox/MessageBox.xaml deleted file mode 100644 index 7223ba9c..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MessageBox/MessageBox.xaml +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Resources.Designer.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Resources.Designer.cs deleted file mode 100644 index 8917394e..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.261 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Xceed.Wpf.Toolkit.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Xceed.Wpf.Toolkit.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Resources.resx b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Resources.resx deleted file mode 100644 index ffecec85..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Settings.Designer.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Settings.Designer.cs deleted file mode 100644 index 6ec402eb..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.261 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Xceed.Wpf.Toolkit.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Settings.settings b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Settings.settings deleted file mode 100644 index 8f2fd95d..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Attributes/TypeEditorAttribute.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Attributes/TypeEditorAttribute.cs deleted file mode 100644 index 26bbd28f..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Attributes/TypeEditorAttribute.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace Microsoft.Windows.Controls.PropertyGrid.Attributes -{ - public class TypeEditorAttribute : Attribute - { - public Type Type { get; set; } - - public TypeEditorAttribute(Type type) - { - var valueSourceInterface = type.GetInterface("Microsoft.Windows.Controls.PropertyGrid.Editors.ITypeEditor"); - if (valueSourceInterface == null) - throw new ArgumentException("Type must implement the ITypeEditor interface.", "type"); - - Type = type; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/CheckBoxEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/CheckBoxEditorProvider.cs deleted file mode 100644 index 4d80b084..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/CheckBoxEditorProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows; - -namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders -{ - public class CheckBoxEditorProvider : ITypeEditorProvider - { - CheckBox _checkbox; - - public CheckBoxEditorProvider() - { - _checkbox = new CheckBox(); - _checkbox.Margin = new Thickness(2, 0, 0, 0); - } - - public void Initialize(PropertyItem propertyItem) - { - ResolveBinding(propertyItem); - } - - public FrameworkElement ResolveEditor() - { - return _checkbox; - } - - private void ResolveBinding(PropertyItem property) - { - var binding = new Binding(property.Name); - binding.Source = property.Instance; - binding.ValidatesOnExceptions = true; - binding.ValidatesOnDataErrors = true; - - if (property.IsWriteable) - binding.Mode = BindingMode.TwoWay; - else - binding.Mode = BindingMode.OneWay; - - BindingOperations.SetBinding(_checkbox, CheckBox.IsCheckedProperty, binding); - } - - - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/EnumComboBoxEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/EnumComboBoxEditorProvider.cs deleted file mode 100644 index 17301263..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/EnumComboBoxEditorProvider.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows.Controls; -using System.Windows; -using System.Windows.Data; -using System.Reflection; - -namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders -{ - public class EnumComboBoxEditorProvider : ITypeEditorProvider - { - ComboBox _comboBox; - - public EnumComboBoxEditorProvider() - { - _comboBox = new ComboBox(); - } - - public void Initialize(PropertyItem propertyItem) - { - ResolveBinding(propertyItem); - SetItemsSource(propertyItem); - } - - public FrameworkElement ResolveEditor() - { - return _comboBox; - } - - private void ResolveBinding(PropertyItem property) - { - var binding = new Binding(property.Name); - binding.Source = property.Instance; - binding.ValidatesOnExceptions = true; - binding.ValidatesOnDataErrors = true; - - if (property.IsWriteable) - binding.Mode = BindingMode.TwoWay; - else - binding.Mode = BindingMode.OneWay; - - BindingOperations.SetBinding(_comboBox, ComboBox.SelectedItemProperty, binding); - } - - private void SetItemsSource(PropertyItem property) - { - _comboBox.ItemsSource = GetValues(property.PropertyType); - } - - public static object[] GetValues(Type enumType) - { - List values = new List(); - - var fields = from field in enumType.GetFields() - where field.IsLiteral - select field; - - foreach (FieldInfo field in fields) - { - values.Add(field.GetValue(enumType)); - } - - return values.ToArray(); - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/FontComboBoxEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/FontComboBoxEditorProvider.cs deleted file mode 100644 index a6c06394..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/FontComboBoxEditorProvider.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Windows.Controls; -using System.Windows; -using System.Windows.Data; -using System.Windows.Media; - -namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders -{ - public class FontComboBoxEditorProvider : ITypeEditorProvider - { - ComboBox _comboBox; - - public FontComboBoxEditorProvider() - { - _comboBox = new ComboBox(); - } - - public void Initialize(PropertyItem propertyItem) - { - ResolveBinding(propertyItem); - SetItemsSource(propertyItem); - } - - public FrameworkElement ResolveEditor() - { - return _comboBox; - } - - private void ResolveBinding(PropertyItem property) - { - var binding = new Binding(property.Name); - binding.Source = property.Instance; - binding.ValidatesOnExceptions = true; - binding.ValidatesOnDataErrors = true; - - if (property.IsWriteable) - binding.Mode = BindingMode.TwoWay; - else - binding.Mode = BindingMode.OneWay; - - BindingOperations.SetBinding(_comboBox, ComboBox.SelectedItemProperty, binding); - } - - private void SetItemsSource(PropertyItem property) - { - if (property.PropertyType == typeof(FontFamily)) - { - List fonts = new List(); - fonts.Add(new FontFamily("Arial")); - fonts.Add(new FontFamily("Courier New")); - fonts.Add(new FontFamily("Times New Roman")); - fonts.Add(new FontFamily("Batang")); - fonts.Add(new FontFamily("BatangChe")); - fonts.Add(new FontFamily("DFKai-SB")); - fonts.Add(new FontFamily("Dotum")); - fonts.Add(new FontFamily("DutumChe")); - fonts.Add(new FontFamily("FangSong")); - fonts.Add(new FontFamily("GulimChe")); - fonts.Add(new FontFamily("Gungsuh")); - fonts.Add(new FontFamily("GungsuhChe")); - fonts.Add(new FontFamily("KaiTi")); - fonts.Add(new FontFamily("Malgun Gothic")); - fonts.Add(new FontFamily("Meiryo")); - fonts.Add(new FontFamily("Microsoft JhengHei")); - fonts.Add(new FontFamily("Microsoft YaHei")); - fonts.Add(new FontFamily("MingLiU")); - fonts.Add(new FontFamily("MingLiu_HKSCS")); - fonts.Add(new FontFamily("MingLiu_HKSCS-ExtB")); - fonts.Add(new FontFamily("MingLiu-ExtB")); - _comboBox.ItemsSource = fonts; - } - else if (property.PropertyType == typeof(FontWeight)) - { - List list = new List() - { - FontWeights.Black, FontWeights.Bold, FontWeights.ExtraBlack, FontWeights.ExtraBold, - FontWeights.ExtraLight, FontWeights.Light, FontWeights.Medium, FontWeights.Normal, FontWeights.SemiBold, - FontWeights.Thin - }; - _comboBox.ItemsSource = list; - } - else if (property.PropertyType == typeof(FontStyle)) - { - List list = new List() - { - FontStyles.Italic, - FontStyles.Normal - }; - _comboBox.ItemsSource = list; - } - else if (property.PropertyType == typeof(FontStretch)) - { - List list = new List() - { - FontStretches.Condensed, - FontStretches.Expanded, - FontStretches.ExtraCondensed, - FontStretches.ExtraExpanded, - FontStretches.Normal, - FontStretches.SemiCondensed, - FontStretches.SemiExpanded, - FontStretches.UltraCondensed, - FontStretches.UltraExpanded - }; - _comboBox.ItemsSource = list; - } - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/ITypeEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/ITypeEditorProvider.cs deleted file mode 100644 index 5c629e96..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/ITypeEditorProvider.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Windows; - -namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders -{ - interface ITypeEditorProvider - { - void Initialize(PropertyItem propertyItem); - FrameworkElement ResolveEditor(); - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/NumericUpDownEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/NumericUpDownEditorProvider.cs deleted file mode 100644 index 8dd8a3d6..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/NumericUpDownEditorProvider.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Windows.Data; -using System.Windows; - -namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders -{ - public class NumericUpDownEditorProvider : ITypeEditorProvider - { - NumericUpDown _numericUpDown; - - public NumericUpDownEditorProvider() - { - _numericUpDown = new NumericUpDown(); - } - - public void Initialize(PropertyItem propertyItem) - { - ResolveBinding(propertyItem); - } - - public FrameworkElement ResolveEditor() - { - return _numericUpDown; - } - - private void ResolveBinding(PropertyItem property) - { - var binding = new Binding(property.Name); - binding.Source = property.Instance; - binding.ValidatesOnExceptions = true; - binding.ValidatesOnDataErrors = true; - - if (property.IsWriteable) - binding.Mode = BindingMode.TwoWay; - else - binding.Mode = BindingMode.OneWay; - - BindingOperations.SetBinding(_numericUpDown, NumericUpDown.ValueProperty, binding); - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/TextBoxEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/TextBoxEditorProvider.cs deleted file mode 100644 index c475713d..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/TextBoxEditorProvider.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows; - -namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders -{ - public class TextBoxEditorProvider : ITypeEditorProvider - { - FrameworkElement _editor; - - public TextBoxEditorProvider() - { - _editor = new TextBox(); - } - - public void Initialize(PropertyItem propertyItem) - { - ResolveBinding(propertyItem); - } - - public FrameworkElement ResolveEditor() - { - return _editor; - } - - private void ResolveBinding(PropertyItem property) - { - var binding = new Binding(property.Name); - binding.Source = property.Instance; - binding.ValidatesOnExceptions = true; - binding.ValidatesOnDataErrors = true; - - if (property.IsWriteable) - binding.Mode = BindingMode.TwoWay; - else - binding.Mode = BindingMode.OneWay; - - BindingOperations.SetBinding(_editor, TextBox.TextProperty, binding); - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DateTimeUpDownEditor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DateTimeUpDownEditor.cs deleted file mode 100644 index 1aafa787..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DateTimeUpDownEditor.cs +++ /dev/null @@ -1,33 +0,0 @@ -/************************************************************************ - - Extended WPF Toolkit - - Copyright (C) 2010-2012 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - This program can be provided to you by Xceed Software Inc. under a - proprietary commercial license agreement for use in non-Open Source - projects. The commercial version of Extended WPF Toolkit also includes - priority technical support, commercial updates, and many additional - useful WPF controls if you license Xceed Business Suite for WPF. - - Visit http://xceed.com and follow @datagrid on Twitter. - - **********************************************************************/ - -namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors -{ - public class DateTimeUpDownEditor : TypeEditor - { - protected override void SetControlProperties() - { - Editor.BorderThickness = new System.Windows.Thickness( 0 ); - } - protected override void SetValueDependencyProperty() - { - ValueProperty = DateTimeUpDown.ValueProperty; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DecimalUpDownEditor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DecimalUpDownEditor.cs deleted file mode 100644 index b778bcfc..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DecimalUpDownEditor.cs +++ /dev/null @@ -1,34 +0,0 @@ -/************************************************************************ - - Extended WPF Toolkit - - Copyright (C) 2010-2012 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - This program can be provided to you by Xceed Software Inc. under a - proprietary commercial license agreement for use in non-Open Source - projects. The commercial version of Extended WPF Toolkit also includes - priority technical support, commercial updates, and many additional - useful WPF controls if you license Xceed Business Suite for WPF. - - Visit http://xceed.com and follow @datagrid on Twitter. - - **********************************************************************/ - -namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors -{ - public class DecimalUpDownEditor : TypeEditor - { - protected override void SetControlProperties() - { - Editor.BorderThickness = new System.Windows.Thickness( 0 ); - } - - protected override void SetValueDependencyProperty() - { - ValueProperty = DecimalUpDown.ValueProperty; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DoubleUpDownEditor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DoubleUpDownEditor.cs deleted file mode 100644 index ce2b6ded..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DoubleUpDownEditor.cs +++ /dev/null @@ -1,34 +0,0 @@ -/************************************************************************ - - Extended WPF Toolkit - - Copyright (C) 2010-2012 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - This program can be provided to you by Xceed Software Inc. under a - proprietary commercial license agreement for use in non-Open Source - projects. The commercial version of Extended WPF Toolkit also includes - priority technical support, commercial updates, and many additional - useful WPF controls if you license Xceed Business Suite for WPF. - - Visit http://xceed.com and follow @datagrid on Twitter. - - **********************************************************************/ - -namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors -{ - public class DoubleUpDownEditor : TypeEditor - { - protected override void SetControlProperties() - { - Editor.BorderThickness = new System.Windows.Thickness( 0 ); - } - - protected override void SetValueDependencyProperty() - { - ValueProperty = DoubleUpDown.ValueProperty; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/IntegerUpDownEditor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/IntegerUpDownEditor.cs deleted file mode 100644 index 6d4c6491..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/IntegerUpDownEditor.cs +++ /dev/null @@ -1,33 +0,0 @@ -/************************************************************************ - - Extended WPF Toolkit - - Copyright (C) 2010-2012 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - This program can be provided to you by Xceed Software Inc. under a - proprietary commercial license agreement for use in non-Open Source - projects. The commercial version of Extended WPF Toolkit also includes - priority technical support, commercial updates, and many additional - useful WPF controls if you license Xceed Business Suite for WPF. - - Visit http://xceed.com and follow @datagrid on Twitter. - - **********************************************************************/ - -namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors -{ - public class IntegerUpDownEditor : TypeEditor - { - protected override void SetControlProperties() - { - Editor.BorderThickness = new System.Windows.Thickness( 0 ); - } - protected override void SetValueDependencyProperty() - { - ValueProperty = IntegerUpDown.ValueProperty; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/NumericUpDownEditor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/NumericUpDownEditor.cs deleted file mode 100644 index 283106bd..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/NumericUpDownEditor.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace Microsoft.Windows.Controls.PropertyGrid.Editors -{ - public class NumericUpDownEditor : TypeEditor - { - protected override void SetValueDependencyProperty() - { - ValueProperty = NumericUpDown.ValueProperty; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/IEditorDefinition.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/IEditorDefinition.cs deleted file mode 100644 index 5d8c0039..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/IEditorDefinition.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Windows; - -namespace Microsoft.Windows.Controls.PropertyGrid -{ - public interface IEditorDefinition - { - DataTemplate EditorTemplate { get; set; } - PropertyDefinitionCollection PropertiesDefinitions { get; set; } - Type TargetType { get; set; } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCategoryItem.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCategoryItem.cs deleted file mode 100644 index 27089598..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCategoryItem.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Windows.Controls; -using System.Windows; - -namespace Microsoft.Windows.Controls.PropertyGrid -{ - public class PropertyCategoryItem : Control - { - public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register("Category", typeof(string), typeof(PropertyCategoryItem), new UIPropertyMetadata(String.Empty, new PropertyChangedCallback(OnCategoryChanged), new CoerceValueCallback(OnCoerceCategory))); - - private static object OnCoerceCategory(DependencyObject o, object value) - { - PropertyCategoryItem propertyCategoryItem = o as PropertyCategoryItem; - if (propertyCategoryItem != null) - return propertyCategoryItem.OnCoerceCategory((string)value); - else - return value; - } - - private static void OnCategoryChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) - { - PropertyCategoryItem propertyCategoryItem = o as PropertyCategoryItem; - if (propertyCategoryItem != null) - propertyCategoryItem.OnCategoryChanged((string)e.OldValue, (string)e.NewValue); - } - - protected virtual string OnCoerceCategory(string value) - { - // TODO: Keep the proposed value within the desired range. - return value; - } - - protected virtual void OnCategoryChanged(string oldValue, string newValue) - { - // TODO: Add your property changed side-effects. Descendants can override as well. - } - - public string Category - { - // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property! - get - { - return (string)GetValue(CategoryProperty); - } - set - { - SetValue(CategoryProperty, value); - } - } - - - private List _Properties = new List(); - public List Properties - { - get - { - return _Properties; - } - set - { - _Properties = value; - } - } - - - static PropertyCategoryItem() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyCategoryItem), new FrameworkPropertyMetadata(typeof(PropertyCategoryItem))); - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbar.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbar.xaml deleted file mode 100644 index 314e9102..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbar.xaml +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbar.xaml.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbar.xaml.cs deleted file mode 100644 index a0cfef85..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbar.xaml.cs +++ /dev/null @@ -1,148 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; -using System.Windows.Media; -using System.Windows.Controls.Primitives; - -namespace Microsoft.Windows.Controls.Formatting -{ - /// - /// Interaction logic for FormatToolbar.xaml - /// - public partial class FormatToolbar : UserControl - { - #region Properties - - public static readonly DependencyProperty RichTextBoxProperty = DependencyProperty.Register("RichTextBox", typeof(RichTextBox), typeof(FormatToolbar)); - public RichTextBox RichTextBox - { - get { return (RichTextBox)GetValue(RichTextBoxProperty); } - set { SetValue(RichTextBoxProperty, value); } - } - - public double[] FontSizes - { - get - { - return new double[] { - 3.0, 4.0, 5.0, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, - 10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 15.0, - 16.0, 17.0, 18.0, 19.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0, - 32.0, 34.0, 36.0, 38.0, 40.0, 44.0, 48.0, 52.0, 56.0, 60.0, 64.0, 68.0, 72.0, 76.0, - 80.0, 88.0, 96.0, 104.0, 112.0, 120.0, 128.0, 136.0, 144.0 - }; - } - } - - #endregion - - #region Constructors - - public FormatToolbar(RichTextBox richTextBox) - { - InitializeComponent(); - Loaded += FormatToolbar_Loaded; - RichTextBox = richTextBox; - RichTextBox.SelectionChanged += RichTextBox_SelectionChanged; - } - - #endregion //Constructors - - #region Event Hanlders - - void FormatToolbar_Loaded(object sender, RoutedEventArgs e) - { - _cmbFontFamilies.ItemsSource = System.Windows.Media.Fonts.SystemFontFamilies; - _cmbFontSizes.ItemsSource = FontSizes; - } - - private void FontFamily_SelectionChanged(object sender, SelectionChangedEventArgs e) - { - if (e.AddedItems.Count == 0) - return; - - FontFamily editValue = (FontFamily)e.AddedItems[0]; - ApplyPropertyValueToSelectedText(TextElement.FontFamilyProperty, editValue); - } - - private void FontSize_SelectionChanged(object sender, SelectionChangedEventArgs e) - { - if (e.AddedItems.Count == 0) - return; - - ApplyPropertyValueToSelectedText(TextElement.FontSizeProperty, e.AddedItems[0]); - } - - void RichTextBox_SelectionChanged(object sender, RoutedEventArgs e) - { - UpdateVisualState(); - } - - private void DragWidget_DragDelta(object sender, DragDeltaEventArgs e) - { - ProcessMove(e); - } - - #endregion //Event Hanlders - - #region Methods - - private void UpdateVisualState() - { - UpdateToggleButtonState(); - UpdateSelectedFontFamily(); - UpdateSelectedFontSize(); - } - - private void UpdateToggleButtonState() - { - UpdateItemCheckedState(_btnBold, TextElement.FontWeightProperty, FontWeights.Bold); - UpdateItemCheckedState(_btnItalic, TextElement.FontStyleProperty, FontStyles.Italic); - UpdateItemCheckedState(_btnUnderline, Inline.TextDecorationsProperty, TextDecorations.Underline); - - UpdateItemCheckedState(_btnAlignLeft, Paragraph.TextAlignmentProperty, TextAlignment.Left); - UpdateItemCheckedState(_btnAlignCenter, Paragraph.TextAlignmentProperty, TextAlignment.Center); - UpdateItemCheckedState(_btnAlignRight, Paragraph.TextAlignmentProperty, TextAlignment.Right); - } - - void UpdateItemCheckedState(ToggleButton button, DependencyProperty formattingProperty, object expectedValue) - { - object currentValue = RichTextBox.Selection.GetPropertyValue(formattingProperty); - button.IsChecked = (currentValue == DependencyProperty.UnsetValue) ? false : currentValue != null && currentValue.Equals(expectedValue); - } - - private void UpdateSelectedFontFamily() - { - object value = RichTextBox.Selection.GetPropertyValue(TextElement.FontFamilyProperty); - FontFamily currentFontFamily = (FontFamily)((value == DependencyProperty.UnsetValue) ? null : value); - if (currentFontFamily != null) - { - _cmbFontFamilies.SelectedItem = currentFontFamily; - } - } - - private void UpdateSelectedFontSize() - { - object value = RichTextBox.Selection.GetPropertyValue(TextElement.FontSizeProperty); - _cmbFontSizes.SelectedValue = (value == DependencyProperty.UnsetValue) ? null : value; - } - - void ApplyPropertyValueToSelectedText(DependencyProperty formattingProperty, object value) - { - if (value == null) - return; - - RichTextBox.Selection.ApplyPropertyValue(formattingProperty, value); - } - - private void ProcessMove(DragDeltaEventArgs e) - { - AdornerLayer layer = AdornerLayer.GetAdornerLayer(RichTextBox); - UIElementAdorner adorner = layer.GetAdorners(RichTextBox)[0] as UIElementAdorner; - adorner.SetOffsets(adorner.OffsetLeft + e.HorizontalChange, adorner.OffsetTop + e.VerticalChange); - } - - #endregion //Methods - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbarManager.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbarManager.cs deleted file mode 100644 index 295e419a..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/FormatToolbarManager.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Windows.Controls; -using System.Windows.Documents; -using System.Windows; - -namespace Microsoft.Windows.Controls.Formatting -{ - internal class FormatToolbarManager - { - RichTextBox _richTextBox; - readonly UIElementAdorner _adorner; - FormatToolbar toolbar; - - bool AdornerIsVisible - { - get { return _adorner.Visibility == Visibility.Visible; } - } - - public FormatToolbarManager(RichTextBox richTextBox) - { - _richTextBox = richTextBox; - _adorner = new UIElementAdorner(richTextBox); - toolbar = new FormatToolbar(richTextBox); - AttachToRichtextBox(); - } - - private void AttachToRichtextBox() - { - _richTextBox.Selection.Changed += Selection_Changed; - } - - void Selection_Changed(object sender, EventArgs e) - { - TextRange selectedText = new TextRange(_richTextBox.Selection.Start, _richTextBox.Selection.End); - if (selectedText.Text.Length > 0) - { - VerifyAdorner(); - } - else - { - HideAdorner(); - } - } - - //TODO: refactor - void VerifyAdorner() - { - VerifyAdornerLayer(); - - Control adorningEditor = toolbar; - _adorner.Child = adorningEditor; - _adorner.Visibility = Visibility.Visible; - - Rect wordBoundary = _richTextBox.Selection.End.GetPositionAtOffset(0, LogicalDirection.Backward).GetCharacterRect(LogicalDirection.Backward); - - double left = wordBoundary.X; - double top = (wordBoundary.Y + wordBoundary.Height) - toolbar.ActualHeight; - - //top boundary - if (top < 0) - { - top = wordBoundary.Y + wordBoundary.Height; - } - - //right boundary - if (left + toolbar.ActualWidth > _richTextBox.ActualWidth - 20) - { - left = left - toolbar.ActualWidth; - top = wordBoundary.Y + wordBoundary.Height + 5; - } - - //bottom boundary - if (top + toolbar.ActualHeight > _richTextBox.ActualHeight - 20) - { - top = wordBoundary.Y - (toolbar.ActualHeight + wordBoundary.Height); - } - - _adorner.SetOffsets(left, top); - } - - /// - /// Ensures that the adorner is in the adorner layer. - /// - /// True if the adorner is in the adorner layer, else false. - bool VerifyAdornerLayer() - { - if (_adorner.Parent != null) - return true; - - AdornerLayer layer = AdornerLayer.GetAdornerLayer(_richTextBox); - if (layer == null) - return false; - - layer.Add(_adorner); - return true; - } - - void HideAdorner() - { - if (this.AdornerIsVisible) - { - _adorner.Visibility = Visibility.Collapsed; - _adorner.Child = null; - } - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Bold16.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Bold16.png deleted file mode 100644 index 8fb36a1a..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Bold16.png and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/CenterAlign16.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/CenterAlign16.png deleted file mode 100644 index 1030a021..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/CenterAlign16.png and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Italic16.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Italic16.png deleted file mode 100644 index 8259a9e1..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Italic16.png and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/JustifyAlign16.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/JustifyAlign16.png deleted file mode 100644 index c5499bce..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/JustifyAlign16.png and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/LeftAlign16.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/LeftAlign16.png deleted file mode 100644 index 51dffb73..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/LeftAlign16.png and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/RightAlign16.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/RightAlign16.png deleted file mode 100644 index cb8e400a..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/RightAlign16.png and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Underline16.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Underline16.png deleted file mode 100644 index 72689482..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/FormatToolbar/Images/Underline16.png and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Aero/Buttons.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Aero/Buttons.xaml deleted file mode 100644 index 30d4977f..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Aero/Buttons.xaml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Common/Generic_Common.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Common/Generic_Common.xaml deleted file mode 100644 index cb7d3894..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Common/Generic_Common.xaml +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Images/delete8.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Images/delete8.png deleted file mode 100644 index 153a6c82..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Images/delete8.png and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/Token.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/Token.cs deleted file mode 100644 index ade47fde..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/Token.cs +++ /dev/null @@ -1,55 +0,0 @@ -/************************************************************************ - - Extended WPF Toolkit - - Copyright (C) 2010-2012 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - This program can be provided to you by Xceed Software Inc. under a - proprietary commercial license agreement for use in non-Open Source - projects. The commercial version of Extended WPF Toolkit also includes - priority technical support, commercial updates, and many additional - useful WPF controls if you license Xceed Business Suite for WPF. - - Visit http://xceed.com and follow @datagrid on Twitter. - - **********************************************************************/ - -using System; - -namespace Xceed.Wpf.Toolkit -{ - internal class Token - { - public string Delimiter - { - get; - private set; - } - public object Item - { - get; - set; - } - - private string _tokenKey; - public string TokenKey - { - get - { - return _tokenKey; - } - set - { - _tokenKey = String.Format( "{0}{1}", value, Delimiter ); - } - } - - public Token( string delimiter ) - { - Delimiter = delimiter; - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenItem.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenItem.cs deleted file mode 100644 index d38202b5..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenItem.cs +++ /dev/null @@ -1,45 +0,0 @@ -/************************************************************************ - - Extended WPF Toolkit - - Copyright (C) 2010-2012 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - This program can be provided to you by Xceed Software Inc. under a - proprietary commercial license agreement for use in non-Open Source - projects. The commercial version of Extended WPF Toolkit also includes - priority technical support, commercial updates, and many additional - useful WPF controls if you license Xceed Business Suite for WPF. - - Visit http://xceed.com and follow @datagrid on Twitter. - - **********************************************************************/ - -using System.Windows; -using System.Windows.Controls; - -namespace Xceed.Wpf.Toolkit -{ - public class TokenItem : ContentControl - { - static TokenItem() - { - DefaultStyleKeyProperty.OverrideMetadata( typeof( TokenItem ), new FrameworkPropertyMetadata( typeof( TokenItem ) ) ); - } - - public static readonly DependencyProperty TokenKeyProperty = DependencyProperty.Register( "TokenKey", typeof( string ), typeof( TokenItem ), new UIPropertyMetadata( null ) ); - public string TokenKey - { - get - { - return ( string )GetValue( TokenKeyProperty ); - } - set - { - SetValue( TokenKeyProperty, value ); - } - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBox.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBox.cs deleted file mode 100644 index 9ddd586a..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBox.cs +++ /dev/null @@ -1,394 +0,0 @@ -/************************************************************************ - - Extended WPF Toolkit - - Copyright (C) 2010-2012 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - This program can be provided to you by Xceed Software Inc. under a - proprietary commercial license agreement for use in non-Open Source - projects. The commercial version of Extended WPF Toolkit also includes - priority technical support, commercial updates, and many additional - useful WPF controls if you license Xceed Business Suite for WPF. - - Visit http://xceed.com and follow @datagrid on Twitter. - - **********************************************************************/ - -//Based of the code written by Pavan Podila -//http://blog.pixelingene.com/2010/10/tokenizing-control-convert-text-to-tokens/ - -using System; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; -using System.Windows.Input; - -namespace Xceed.Wpf.Toolkit -{ - public class TokenizedTextBox : ItemsControl - { - #region Members - - private System.Windows.Controls.RichTextBox _rtb = null; - private bool _surpressTextChanged = false; - private bool _surpressTextChangedEvent = false; - - #endregion //Members - - #region Properties - - public static readonly DependencyProperty SearchMemberPathProperty = DependencyProperty.Register( "SearchMemberPath", typeof( string ), typeof( TokenizedTextBox ), new UIPropertyMetadata( String.Empty ) ); - public string SearchMemberPath - { - get - { - return ( string )GetValue( SearchMemberPathProperty ); - } - set - { - SetValue( SearchMemberPathProperty, value ); - } - } - - public static readonly DependencyProperty TokenDelimiterProperty = DependencyProperty.Register( "TokenDelimiter", typeof( string ), typeof( TokenizedTextBox ), new UIPropertyMetadata( ";" ) ); - public string TokenDelimiter - { - get - { - return ( string )GetValue( TokenDelimiterProperty ); - } - set - { - SetValue( TokenDelimiterProperty, value ); - } - } - - public static readonly DependencyProperty TokenTemplateProperty = DependencyProperty.Register( "TokenTemplate", typeof( DataTemplate ), typeof( TokenizedTextBox ), new UIPropertyMetadata( null ) ); - public DataTemplate TokenTemplate - { - get - { - return ( DataTemplate )GetValue( TokenTemplateProperty ); - } - set - { - SetValue( TokenTemplateProperty, value ); - } - } - - #region Text - - public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof( string ), typeof( TokenizedTextBox ), new UIPropertyMetadata( null, OnTextChanged ) ); - public string Text - { - get - { - return ( string )GetValue( TextProperty ); - } - set - { - SetValue( TextProperty, value ); - } - } - - private static void OnTextChanged( DependencyObject o, DependencyPropertyChangedEventArgs e ) - { - TokenizedTextBox tokenizedTextBox = o as TokenizedTextBox; - if( tokenizedTextBox != null ) - tokenizedTextBox.OnTextChanged( ( string )e.OldValue, ( string )e.NewValue ); - } - - protected virtual void OnTextChanged( string oldValue, string newValue ) - { - if( _rtb == null || _surpressTextChanged ) - return; - - //TODO: when text changes update tokens - } - - #endregion //Text - - public static readonly DependencyProperty ValueMemberPathProperty = DependencyProperty.Register( "ValueMemberPath", typeof( string ), typeof( TokenizedTextBox ), new UIPropertyMetadata( String.Empty ) ); - public string ValueMemberPath - { - get - { - return ( string )GetValue( ValueMemberPathProperty ); - } - set - { - SetValue( ValueMemberPathProperty, value ); - } - } - - - #endregion //Properties - - #region Constructors - - static TokenizedTextBox() - { - DefaultStyleKeyProperty.OverrideMetadata( typeof( TokenizedTextBox ), new FrameworkPropertyMetadata( typeof( TokenizedTextBox ) ) ); - } - - public TokenizedTextBox() - { - CommandBindings.Add( new CommandBinding( TokenizedTextBoxCommands.Delete, DeleteToken ) ); - } - - #endregion //Constructors - - #region Base Class Overrides - - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - - if( _rtb != null ) - { - _rtb.TextChanged -= RichTextBox_TextChanged; - _rtb.PreviewKeyDown -= RichTextBox_PreviewKeyDown; - } - _rtb = GetTemplateChild( "PART_ContentHost" ) as System.Windows.Controls.RichTextBox; - if( _rtb != null ) - { - _rtb.TextChanged += RichTextBox_TextChanged; - _rtb.PreviewKeyDown += RichTextBox_PreviewKeyDown; - } - - InitializeTokensFromText(); - } - - #endregion //Base Class Overrides - - #region Event Handlers - - private void RichTextBox_TextChanged( object sender, TextChangedEventArgs e ) - { - if( _surpressTextChangedEvent ) - return; - - var text = _rtb.CaretPosition.GetTextInRun( LogicalDirection.Backward ); - var token = ResolveToken( text ); - if( token != null ) - { - ReplaceTextWithToken( text.Trim(), token ); - } - } - - void RichTextBox_PreviewKeyDown( object sender, KeyEventArgs e ) - { - InlineUIContainer container = null; - - if( e.Key == Key.Back ) - { - container = _rtb.CaretPosition.GetAdjacentElement( LogicalDirection.Backward ) as InlineUIContainer; - } - else if( e.Key == Key.Delete ) - { - //if the selected text is a blank space, I will assume that a token item is selected. - //if a token item is selected, we need to move the caret position to the left of the element so we can grab the InlineUIContainer - if( _rtb.Selection.Text == " " ) - { - TextPointer moveTo = _rtb.CaretPosition.GetNextInsertionPosition( LogicalDirection.Backward ); - _rtb.CaretPosition = moveTo; - } - - //the cursor is to the left of a token item - container = _rtb.CaretPosition.GetAdjacentElement( LogicalDirection.Forward ) as InlineUIContainer; - } - - //if the container is not null that means we have something to delete - if( container != null ) - { - var token = ( container as InlineUIContainer ).Child as TokenItem; - if( token != null ) - { - SetTextInternal( Text.Replace( token.TokenKey, "" ) ); - } - } - } - - #endregion //Event Handlers - - #region Methods - - private void InitializeTokensFromText() - { - if( !String.IsNullOrEmpty( Text ) ) - { - string[] tokenKeys = Text.Split( new string[] { TokenDelimiter }, StringSplitOptions.RemoveEmptyEntries ); - foreach( string tokenKey in tokenKeys ) - { - var para = _rtb.CaretPosition.Paragraph; - var token = new Token( TokenDelimiter ) - { - TokenKey = tokenKey, - Item = ResolveItemByTokenKey( tokenKey ) - }; - para.Inlines.Add( CreateTokenContainer( token ) ); - } - } - } - - private Token ResolveToken( string text ) - { - if( text.EndsWith( TokenDelimiter ) ) - return ResolveTokenBySearchMemberPath( text.Substring( 0, text.Length - 1 ).Trim() ); - - return null; - } - - private Token ResolveTokenBySearchMemberPath( string searchText ) - { - //create a new token and default the settings to the search text - var token = new Token( TokenDelimiter ) - { - TokenKey = searchText, - Item = searchText - }; - - if( ItemsSource != null ) - { - foreach( object item in ItemsSource ) - { - var searchProperty = item.GetType().GetProperty( SearchMemberPath ); - if( searchProperty != null ) - { - var searchValue = searchProperty.GetValue( item, null ); - if( searchText.Equals( searchValue.ToString(), StringComparison.InvariantCultureIgnoreCase ) ) - { - var valueProperty = item.GetType().GetProperty( ValueMemberPath ); - if( valueProperty != null ) - token.TokenKey = valueProperty.GetValue( item, null ).ToString(); - - token.Item = item; - break; - } - } - } - } - - return token; - } - - private object ResolveItemByTokenKey( string tokenKey ) - { - if( ItemsSource != null ) - { - foreach( object item in ItemsSource ) - { - var property = item.GetType().GetProperty( ValueMemberPath ); - if( property != null ) - { - var value = property.GetValue( item, null ); - if( tokenKey.Equals( value.ToString(), StringComparison.InvariantCultureIgnoreCase ) ) - return item; - } - } - } - - return tokenKey; - } - - private void ReplaceTextWithToken( string inputText, Token token ) - { - _surpressTextChangedEvent = true; - - var para = _rtb.CaretPosition.Paragraph; - - var matchedRun = para.Inlines.FirstOrDefault( inline => - { - var run = inline as Run; - return ( run != null && run.Text.EndsWith( inputText ) ); - } ) as Run; - - if( matchedRun != null ) // Found a Run that matched the inputText - { - var tokenContainer = CreateTokenContainer( token ); - para.Inlines.InsertBefore( matchedRun, tokenContainer ); - - // Remove only if the Text in the Run is the same as inputText, else split up - if( matchedRun.Text == inputText ) - { - para.Inlines.Remove( matchedRun ); - } - else // Split up - { - var index = matchedRun.Text.IndexOf( inputText ) + inputText.Length; - var tailEnd = new Run( matchedRun.Text.Substring( index ) ); - para.Inlines.InsertAfter( matchedRun, tailEnd ); - para.Inlines.Remove( matchedRun ); - } - - //now append the Text with the token key - SetTextInternal( Text + token.TokenKey ); - } - - _surpressTextChangedEvent = false; - } - - private InlineUIContainer CreateTokenContainer( Token token ) - { - return new InlineUIContainer( CreateTokenItem( token ) ) - { - BaselineAlignment = BaselineAlignment.Center - }; - } - - private TokenItem CreateTokenItem( Token token ) - { - object item = token.Item; - - var tokenItem = new TokenItem() - { - TokenKey = token.TokenKey, - Content = item, - ContentTemplate = TokenTemplate - }; - - if( TokenTemplate == null ) - { - //if no template was supplied let's try to get a value from the object using the DisplayMemberPath - if( !String.IsNullOrEmpty( DisplayMemberPath ) ) - { - var property = item.GetType().GetProperty( DisplayMemberPath ); - if( property != null ) - { - var value = property.GetValue( item, null ); - if( value != null ) - tokenItem.Content = value; - } - } - } - - return tokenItem; - } - - private void DeleteToken( object sender, ExecutedRoutedEventArgs e ) - { - var para = _rtb.CaretPosition.Paragraph; - - Inline inlineToRemove = para.Inlines.Where( inline => inline is InlineUIContainer && ( ( inline as InlineUIContainer ).Child as TokenItem ).TokenKey.Equals( e.Parameter ) ).FirstOrDefault(); - - if( inlineToRemove != null ) - para.Inlines.Remove( inlineToRemove ); - - //update Text to remove delimited value - SetTextInternal( Text.Replace( e.Parameter.ToString(), "" ) ); - } - - private void SetTextInternal( string text ) - { - _surpressTextChanged = true; - Text = text; - _surpressTextChanged = false; - } - - #endregion //Methods - } -} \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBoxCommands.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBoxCommands.cs deleted file mode 100644 index a6c4a5a4..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBoxCommands.cs +++ /dev/null @@ -1,36 +0,0 @@ -/************************************************************************ - - Extended WPF Toolkit - - Copyright (C) 2010-2012 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - This program can be provided to you by Xceed Software Inc. under a - proprietary commercial license agreement for use in non-Open Source - projects. The commercial version of Extended WPF Toolkit also includes - priority technical support, commercial updates, and many additional - useful WPF controls if you license Xceed Business Suite for WPF. - - Visit http://xceed.com and follow @datagrid on Twitter. - - **********************************************************************/ - -using System.Windows.Input; - -namespace Xceed.Wpf.Toolkit -{ - public static class TokenizedTextBoxCommands - { - private static RoutedCommand _deleteCommand = new RoutedCommand(); - - public static RoutedCommand Delete - { - get - { - return _deleteCommand; - } - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Themes/Generic.xaml deleted file mode 100644 index 1270e6d1..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Themes/Generic.xaml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj.vspscc b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj.vspscc deleted file mode 100644 index feffdeca..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj.vspscc +++ /dev/null @@ -1,10 +0,0 @@ -"" -{ -"FILE_VERSION" = "9237" -"ENLISTMENT_CHOICE" = "NEVER" -"PROJECT_FILE_RELATIVE_PATH" = "" -"NUMBER_OF_EXCLUDED_FILES" = "0" -"ORIGINAL_PROJECT_FILE_PATH" = "" -"NUMBER_OF_NESTED_PROJECTS" = "0" -"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/sn.pfx b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/sn.pfx deleted file mode 100644 index 0f441ed9..00000000 Binary files a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/sn.pfx and /dev/null differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/AssemblyVersionInfo.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/AssemblyVersionInfo.cs index 8b8ce9d3..c6ea985d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/AssemblyVersionInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/AssemblyVersionInfo.cs @@ -14,12 +14,14 @@ ***********************************************************************************/ +#pragma warning disable 0436 [assembly: System.Reflection.AssemblyVersion( _XceedVersionInfo.Version )] +#pragma warning restore 0436 internal static class _XceedVersionInfo { [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] - public const string BaseVersion = "2.0"; + public const string BaseVersion = "3.4"; [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] public const string Version = BaseVersion + ".0.0"; diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Brushes.xaml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Brushes.xaml index 92601940..3606e3ee 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Brushes.xaml +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Brushes.xaml @@ -20,7 +20,7 @@ - @@ -29,13 +29,13 @@ - - - @@ -44,11 +44,11 @@ - - @@ -57,7 +57,7 @@ - @@ -66,28 +66,28 @@ - - - - - - - - @@ -95,57 +95,41 @@ - - - - - - + - + - - @@ -154,18 +138,18 @@ - - - - - diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Properties/AssemblyInfo.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Properties/AssemblyInfo.cs index d35c3872..46576551 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Properties/AssemblyInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Properties/AssemblyInfo.cs @@ -25,12 +25,12 @@ using System; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle( "Xceed Extended WPF Toolkit - AvalonDock Aero Theme" )] +[assembly: AssemblyTitle( "Xceed Toolkit for WPF - AvalonDock Aero Theme" )] [assembly: AssemblyDescription( "This assembly implements the Aero Theme for the AvalonDock layout system." )] [assembly: AssemblyCompany( "Xceed Software Inc." )] -[assembly: AssemblyProduct( "Xceed Extended WPF Toolkit - AvalonDock" )] -[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2007-2013" )] +[assembly: AssemblyProduct( "Xceed Toolkit for WPF - AvalonDock" )] +[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2007-2017" )] diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Theme.xaml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Theme.xaml index d0505cfa..0bbf9bac 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Theme.xaml +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/Theme.xaml @@ -14,1301 +14,1780 @@ **********************************************************************************--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Debug/GeneratedInternalTypeHelper.g.i.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Debug/GeneratedInternalTypeHelper.g.i.cs new file mode 100644 index 00000000..136dd1ba --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Debug/GeneratedInternalTypeHelper.g.i.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace XamlGeneratedNamespace { + + + /// + /// GeneratedInternalTypeHelper + /// + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed class GeneratedInternalTypeHelper : System.Windows.Markup.InternalTypeHelper { + + /// + /// CreateInstance + /// + protected override object CreateInstance(System.Type type, System.Globalization.CultureInfo culture) { + return System.Activator.CreateInstance(type, ((System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic) + | (System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.CreateInstance)), null, null, culture); + } + + /// + /// GetPropertyValue + /// + protected override object GetPropertyValue(System.Reflection.PropertyInfo propertyInfo, object target, System.Globalization.CultureInfo culture) { + return propertyInfo.GetValue(target, System.Reflection.BindingFlags.Default, null, null, culture); + } + + /// + /// SetPropertyValue + /// + protected override void SetPropertyValue(System.Reflection.PropertyInfo propertyInfo, object target, object value, System.Globalization.CultureInfo culture) { + propertyInfo.SetValue(target, value, System.Reflection.BindingFlags.Default, null, null, culture); + } + + /// + /// CreateDelegate + /// + protected override System.Delegate CreateDelegate(System.Type delegateType, object target, string handler) { + return ((System.Delegate)(target.GetType().InvokeMember("_CreateDelegate", (System.Reflection.BindingFlags.InvokeMethod + | (System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)), null, target, new object[] { + delegateType, + handler}, null))); + } + + /// + /// AddEventHandler + /// + protected override void AddEventHandler(System.Reflection.EventInfo eventInfo, object target, System.Delegate handler) { + eventInfo.AddEventHandler(target, handler); + } + } +} + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Brushes.baml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Brushes.baml new file mode 100644 index 00000000..f2fc70fd Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Brushes.baml differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/GeneratedInternalTypeHelper.g.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/GeneratedInternalTypeHelper.g.cs new file mode 100644 index 00000000..c65238fb --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/GeneratedInternalTypeHelper.g.cs @@ -0,0 +1,2 @@ + + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/GeneratedInternalTypeHelper.g.i.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/GeneratedInternalTypeHelper.g.i.cs new file mode 100644 index 00000000..136dd1ba --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/GeneratedInternalTypeHelper.g.i.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace XamlGeneratedNamespace { + + + /// + /// GeneratedInternalTypeHelper + /// + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed class GeneratedInternalTypeHelper : System.Windows.Markup.InternalTypeHelper { + + /// + /// CreateInstance + /// + protected override object CreateInstance(System.Type type, System.Globalization.CultureInfo culture) { + return System.Activator.CreateInstance(type, ((System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic) + | (System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.CreateInstance)), null, null, culture); + } + + /// + /// GetPropertyValue + /// + protected override object GetPropertyValue(System.Reflection.PropertyInfo propertyInfo, object target, System.Globalization.CultureInfo culture) { + return propertyInfo.GetValue(target, System.Reflection.BindingFlags.Default, null, null, culture); + } + + /// + /// SetPropertyValue + /// + protected override void SetPropertyValue(System.Reflection.PropertyInfo propertyInfo, object target, object value, System.Globalization.CultureInfo culture) { + propertyInfo.SetValue(target, value, System.Reflection.BindingFlags.Default, null, null, culture); + } + + /// + /// CreateDelegate + /// + protected override System.Delegate CreateDelegate(System.Type delegateType, object target, string handler) { + return ((System.Delegate)(target.GetType().InvokeMember("_CreateDelegate", (System.Reflection.BindingFlags.InvokeMethod + | (System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)), null, target, new object[] { + delegateType, + handler}, null))); + } + + /// + /// AddEventHandler + /// + protected override void AddEventHandler(System.Reflection.EventInfo eventInfo, object target, System.Delegate handler) { + eventInfo.AddEventHandler(target, handler); + } + } +} + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Theme.baml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Theme.baml new file mode 100644 index 00000000..7558b5b0 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Theme.baml differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero.csproj.FileListAbsolute.txt b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero.csproj.FileListAbsolute.txt new file mode 100644 index 00000000..38d68938 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero.csproj.FileListAbsolute.txt @@ -0,0 +1,23 @@ +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\Xceed.Wpf.AvalonDock.Themes.Aero.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\Xceed.Wpf.AvalonDock.Themes.Aero.pdb +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\Xceed.Wpf.AvalonDock.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\Xceed.Wpf.AvalonDock.pdb +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\de\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\es\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\fr\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\hu\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\it\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\pt-BR\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\ro\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\ru\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\sv\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\bin\Release\zh-Hans\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\Xceed.Wpf.AvalonDock.Themes.Aero.csprojResolveAssemblyReference.cache +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\GeneratedInternalTypeHelper.g.cs +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\Xceed.Wpf.AvalonDock.Themes.Aero_MarkupCompile.cache +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\Xceed.Wpf.AvalonDock.Themes.Aero_MarkupCompile.lref +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\Brushes.baml +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\Theme.baml +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\Xceed.Wpf.AvalonDock.Themes.Aero.g.resources +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\Xceed.Wpf.AvalonDock.Themes.Aero.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\Xceed.Wpf.AvalonDock.Themes.Aero.pdb diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero.g.resources b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero.g.resources new file mode 100644 index 00000000..9216728b Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero.g.resources differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero_MarkupCompile.lref b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero_MarkupCompile.lref new file mode 100644 index 00000000..556f4e24 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/obj/Release/Xceed.Wpf.AvalonDock.Themes.Aero_MarkupCompile.lref @@ -0,0 +1,5 @@ +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\obj\Release\GeneratedInternalTypeHelper.g.cs + +FD:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\Brushes.xaml;; +FD:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Aero\Theme.xaml;; + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/AssemblyVersionInfo.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/AssemblyVersionInfo.cs index 8b8ce9d3..c6ea985d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/AssemblyVersionInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/AssemblyVersionInfo.cs @@ -14,12 +14,14 @@ ***********************************************************************************/ +#pragma warning disable 0436 [assembly: System.Reflection.AssemblyVersion( _XceedVersionInfo.Version )] +#pragma warning restore 0436 internal static class _XceedVersionInfo { [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] - public const string BaseVersion = "2.0"; + public const string BaseVersion = "3.4"; [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] public const string Version = BaseVersion + ".0.0"; diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Properties/AssemblyInfo.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Properties/AssemblyInfo.cs index 3e3cb295..8491c6ba 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Properties/AssemblyInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Properties/AssemblyInfo.cs @@ -25,12 +25,12 @@ using System; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle( "Xceed Extended WPF Toolkit - AvalonDock Metro Theme" )] +[assembly: AssemblyTitle( "Xceed Toolkit for WPF - AvalonDock Metro Theme" )] [assembly: AssemblyDescription( "This assembly implements the Metro Theme for the AvalonDock layout system." )] [assembly: AssemblyCompany( "Xceed Software Inc." )] -[assembly: AssemblyProduct( "Xceed Extended WPF Toolkit - AvalonDock" )] -[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2007-2013" )] +[assembly: AssemblyProduct( "Xceed Toolkit for WPF - AvalonDock" )] +[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2007-2017" )] diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Theme.xaml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Theme.xaml index d2571e84..1027b5d7 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Theme.xaml +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Theme.xaml @@ -14,1365 +14,1850 @@ **********************************************************************************--> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + Grid.Column="1" + Grid.Row="1" /> + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Brushes.baml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Brushes.baml new file mode 100644 index 00000000..f9a94fe5 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Brushes.baml differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Theme.baml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Theme.baml new file mode 100644 index 00000000..7c3c5841 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Theme.baml differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro.csproj.FileListAbsolute.txt b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro.csproj.FileListAbsolute.txt new file mode 100644 index 00000000..0c30339b --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro.csproj.FileListAbsolute.txt @@ -0,0 +1,22 @@ +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\Xceed.Wpf.AvalonDock.Themes.Metro.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\Xceed.Wpf.AvalonDock.Themes.Metro.pdb +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\Xceed.Wpf.AvalonDock.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\Xceed.Wpf.AvalonDock.pdb +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\de\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\es\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\fr\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\hu\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\it\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\pt-BR\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\ro\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\ru\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\sv\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\bin\Release\zh-Hans\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\obj\Release\Xceed.Wpf.AvalonDock.Themes.Metro.csprojResolveAssemblyReference.cache +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\obj\Release\Brushes.baml +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\obj\Release\Xceed.Wpf.AvalonDock.Themes.Metro_MarkupCompile.cache +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\obj\Release\Xceed.Wpf.AvalonDock.Themes.Metro_MarkupCompile.lref +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\obj\Release\Theme.baml +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\obj\Release\Xceed.Wpf.AvalonDock.Themes.Metro.g.resources +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\obj\Release\Xceed.Wpf.AvalonDock.Themes.Metro.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\obj\Release\Xceed.Wpf.AvalonDock.Themes.Metro.pdb diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro.g.resources b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro.g.resources new file mode 100644 index 00000000..9f250192 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro.g.resources differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro_MarkupCompile.lref b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro_MarkupCompile.lref new file mode 100644 index 00000000..a99d42b4 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/obj/Release/Xceed.Wpf.AvalonDock.Themes.Metro_MarkupCompile.lref @@ -0,0 +1,4 @@ + + +FD:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.Metro\Theme.xaml;; + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/AssemblyVersionInfo.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/AssemblyVersionInfo.cs index 8b8ce9d3..c6ea985d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/AssemblyVersionInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/AssemblyVersionInfo.cs @@ -14,12 +14,14 @@ ***********************************************************************************/ +#pragma warning disable 0436 [assembly: System.Reflection.AssemblyVersion( _XceedVersionInfo.Version )] +#pragma warning restore 0436 internal static class _XceedVersionInfo { [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] - public const string BaseVersion = "2.0"; + public const string BaseVersion = "3.4"; [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] public const string Version = BaseVersion + ".0.0"; diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/Properties/AssemblyInfo.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/Properties/AssemblyInfo.cs index d6b46f84..096508e0 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/Properties/AssemblyInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/Properties/AssemblyInfo.cs @@ -25,12 +25,12 @@ using System; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle( "Xceed Extended WPF Toolkit - AvalonDock" )] +[assembly: AssemblyTitle( "Xceed Toolkit for WPF - AvalonDock VS2010 Theme" )] [assembly: AssemblyDescription( "This assembly implements the VS2010 Theme for the AvalonDock layout system." )] [assembly: AssemblyCompany( "Xceed Software Inc." )] -[assembly: AssemblyProduct( "Xceed Extended WPF Toolkit - AvalonDock" )] -[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2007-2013" )] +[assembly: AssemblyProduct( "Xceed Toolkit for WPF - AvalonDock" )] +[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2007-2017" )] // Setting ComVisible to false makes the types in this assembly not visible diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/Theme.xaml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/Theme.xaml index f137f888..d7d484db 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/Theme.xaml +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/Theme.xaml @@ -14,1415 +14,1987 @@ **********************************************************************************--> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + Grid.Column="1" + Grid.Row="1" /> + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Brushes.baml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Brushes.baml new file mode 100644 index 00000000..140e78f6 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Brushes.baml differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Theme.baml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Theme.baml new file mode 100644 index 00000000..c7159e9f Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Theme.baml differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010.csproj.FileListAbsolute.txt b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010.csproj.FileListAbsolute.txt new file mode 100644 index 00000000..1b504512 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010.csproj.FileListAbsolute.txt @@ -0,0 +1,22 @@ +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\Xceed.Wpf.AvalonDock.Themes.VS2010.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\Xceed.Wpf.AvalonDock.Themes.VS2010.pdb +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\Xceed.Wpf.AvalonDock.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\Xceed.Wpf.AvalonDock.pdb +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\de\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\es\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\fr\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\hu\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\it\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\pt-BR\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\ro\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\ru\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\sv\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\bin\Release\zh-Hans\Xceed.Wpf.AvalonDock.resources.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\obj\Release\Xceed.Wpf.AvalonDock.Themes.VS2010.csprojResolveAssemblyReference.cache +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\obj\Release\Brushes.baml +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\obj\Release\Xceed.Wpf.AvalonDock.Themes.VS2010_MarkupCompile.cache +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\obj\Release\Xceed.Wpf.AvalonDock.Themes.VS2010_MarkupCompile.lref +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\obj\Release\Theme.baml +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\obj\Release\Xceed.Wpf.AvalonDock.Themes.VS2010.g.resources +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\obj\Release\Xceed.Wpf.AvalonDock.Themes.VS2010.dll +D:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\obj\Release\Xceed.Wpf.AvalonDock.Themes.VS2010.pdb diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010.g.resources b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010.g.resources new file mode 100644 index 00000000..91044a8c Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010.g.resources differ diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010_MarkupCompile.lref b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010_MarkupCompile.lref new file mode 100644 index 00000000..5885ecd8 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/obj/Release/Xceed.Wpf.AvalonDock.Themes.VS2010_MarkupCompile.lref @@ -0,0 +1,4 @@ + + +FD:\Dev\ExtendedWPFToolkit\Release\3.4.0\OpenSource\Generated\Src\Xceed.Wpf.AvalonDock.Themes.VS2010\Theme.xaml;; + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/AssemblyVersionInfo.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/AssemblyVersionInfo.cs index 8b8ce9d3..c6ea985d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/AssemblyVersionInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/AssemblyVersionInfo.cs @@ -14,12 +14,14 @@ ***********************************************************************************/ +#pragma warning disable 0436 [assembly: System.Reflection.AssemblyVersion( _XceedVersionInfo.Version )] +#pragma warning restore 0436 internal static class _XceedVersionInfo { [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] - public const string BaseVersion = "2.0"; + public const string BaseVersion = "3.4"; [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] public const string Version = BaseVersion + ".0.0"; diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Commands/RelayCommand.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Commands/RelayCommand.cs index c82ac802..8be365f9 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Commands/RelayCommand.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Commands/RelayCommand.cs @@ -15,57 +15,60 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Input; namespace Xceed.Wpf.AvalonDock.Commands { - internal class RelayCommand : ICommand - { - #region Fields - - readonly Action _execute; - readonly Predicate _canExecute; + internal class RelayCommand : ICommand + { + #region Fields - #endregion // Fields + private readonly Action _execute; + private readonly Predicate _canExecute; - #region Constructors + #endregion // Fields - public RelayCommand(Action execute) - : this(execute, null) - { - } + #region Constructors - public RelayCommand(Action execute, Predicate canExecute) - { - if (execute == null) - throw new ArgumentNullException("execute"); + public RelayCommand( Action execute ) + : this( execute, null ) + { + } - _execute = execute; - _canExecute = canExecute; - } - #endregion // Constructors + public RelayCommand( Action execute, Predicate canExecute ) + { + if( execute == null ) + throw new ArgumentNullException( "execute" ); - #region ICommand Members + _execute = execute; + _canExecute = canExecute; + } + #endregion // Constructors - public bool CanExecute(object parameter) - { - return _canExecute == null ? true : _canExecute(parameter); - } + #region ICommand Members - public event EventHandler CanExecuteChanged - { - add { CommandManager.RequerySuggested += value; } - remove { CommandManager.RequerySuggested -= value; } - } + public bool CanExecute( object parameter ) + { + return _canExecute == null ? true : _canExecute( parameter ); + } - public void Execute(object parameter) - { - _execute(parameter); - } + public event EventHandler CanExecuteChanged + { + add + { + CommandManager.RequerySuggested += value; + } + remove + { + CommandManager.RequerySuggested -= value; + } + } - #endregion // ICommand Members + public void Execute( object parameter ) + { + _execute( parameter ); } + + #endregion // ICommand Members + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneControlOverlayArea.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneControlOverlayArea.cs index 90274cc6..89586bc8 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneControlOverlayArea.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneControlOverlayArea.cs @@ -14,30 +14,33 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; -using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class AnchorablePaneControlOverlayArea : OverlayArea - { - internal AnchorablePaneControlOverlayArea( - IOverlayWindow overlayWindow, - LayoutAnchorablePaneControl anchorablePaneControl) - : base(overlayWindow) - { + public class AnchorablePaneControlOverlayArea : OverlayArea + { + #region Members + + private LayoutAnchorablePaneControl _anchorablePaneControl; + + #endregion - _anchorablePaneControl = anchorablePaneControl; - base.SetScreenDetectionArea(new Rect( - _anchorablePaneControl.PointToScreenDPI(new Point()), - _anchorablePaneControl.TransformActualSizeToAncestor())); + #region constructors - } + internal AnchorablePaneControlOverlayArea( + IOverlayWindow overlayWindow, + LayoutAnchorablePaneControl anchorablePaneControl ) + : base( overlayWindow ) + { + + _anchorablePaneControl = anchorablePaneControl; + base.SetScreenDetectionArea( new Rect( + _anchorablePaneControl.PointToScreenDPI( new Point() ), + _anchorablePaneControl.TransformActualSizeToAncestor() ) ); - LayoutAnchorablePaneControl _anchorablePaneControl; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneDropTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneDropTarget.cs index a17a47c4..75e83b10 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneDropTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneDropTarget.cs @@ -14,323 +14,330 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - internal class AnchorablePaneDropTarget : DropTarget + internal class AnchorablePaneDropTarget : DropTarget + { + #region Members + + private LayoutAnchorablePaneControl _targetPane; + int _tabIndex = -1; + + #endregion + + #region Constructors + + internal AnchorablePaneDropTarget( LayoutAnchorablePaneControl paneControl, Rect detectionRect, DropTargetType type ) + : base( paneControl, detectionRect, type ) { - internal AnchorablePaneDropTarget(LayoutAnchorablePaneControl paneControl, Rect detectionRect, DropTargetType type) - : base(paneControl, detectionRect, type) - { - _targetPane = paneControl; - } + _targetPane = paneControl; + } - internal AnchorablePaneDropTarget(LayoutAnchorablePaneControl paneControl, Rect detectionRect, DropTargetType type, int tabIndex) - : base(paneControl, detectionRect, type) - { - _targetPane = paneControl; - _tabIndex = tabIndex; - } + internal AnchorablePaneDropTarget( LayoutAnchorablePaneControl paneControl, Rect detectionRect, DropTargetType type, int tabIndex ) + : base( paneControl, detectionRect, type ) + { + _targetPane = paneControl; + _tabIndex = tabIndex; + } + #endregion - LayoutAnchorablePaneControl _targetPane; + #region Overrides - int _tabIndex = -1; + protected override void Drop( LayoutAnchorableFloatingWindow floatingWindow ) + { + ILayoutAnchorablePane targetModel = _targetPane.Model as ILayoutAnchorablePane; + LayoutAnchorable anchorableActive = floatingWindow.Descendents().OfType().FirstOrDefault(); + + switch( Type ) + { + case DropTargetType.AnchorablePaneDockBottom: + #region DropTargetType.AnchorablePaneDockBottom + { + var parentModel = targetModel.Parent as ILayoutGroup; + var parentModelOrientable = targetModel.Parent as ILayoutOrientableGroup; + int insertToIndex = parentModel.IndexOfChild( targetModel ); + + if( parentModelOrientable.Orientation != System.Windows.Controls.Orientation.Vertical && + parentModel.ChildrenCount == 1 ) + parentModelOrientable.Orientation = System.Windows.Controls.Orientation.Vertical; + + if( parentModelOrientable.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + if( layoutAnchorablePaneGroup != null && + ( layoutAnchorablePaneGroup.Children.Count == 1 || + layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Vertical ) ) + { + var anchorablesToMove = layoutAnchorablePaneGroup.Children.ToArray(); + for( int i = 0; i < anchorablesToMove.Length; i++ ) + parentModel.InsertChildAt( insertToIndex + 1 + i, anchorablesToMove[ i ] ); + } + else + parentModel.InsertChildAt( insertToIndex + 1, floatingWindow.RootPanel ); + } + else + { + var targetModelAsPositionableElement = targetModel as ILayoutPositionableElement; + var newOrientedPanel = new LayoutAnchorablePaneGroup() + { + Orientation = System.Windows.Controls.Orientation.Vertical, + DockWidth = targetModelAsPositionableElement.DockWidth, + DockHeight = targetModelAsPositionableElement.DockHeight, + }; + + parentModel.InsertChildAt( insertToIndex, newOrientedPanel ); + newOrientedPanel.Children.Add( targetModel ); + newOrientedPanel.Children.Add( floatingWindow.RootPanel ); + + } + } + break; + #endregion + case DropTargetType.AnchorablePaneDockTop: + #region DropTargetType.AnchorablePaneDockTop + { + var parentModel = targetModel.Parent as ILayoutGroup; + var parentModelOrientable = targetModel.Parent as ILayoutOrientableGroup; + int insertToIndex = parentModel.IndexOfChild( targetModel ); + + if( parentModelOrientable.Orientation != System.Windows.Controls.Orientation.Vertical && + parentModel.ChildrenCount == 1 ) + parentModelOrientable.Orientation = System.Windows.Controls.Orientation.Vertical; + + if( parentModelOrientable.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + if( layoutAnchorablePaneGroup != null && + ( layoutAnchorablePaneGroup.Children.Count == 1 || + layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Vertical ) ) + { + var anchorablesToMove = layoutAnchorablePaneGroup.Children.ToArray(); + for( int i = 0; i < anchorablesToMove.Length; i++ ) + parentModel.InsertChildAt( insertToIndex + i, anchorablesToMove[ i ] ); + } + else + parentModel.InsertChildAt( insertToIndex, floatingWindow.RootPanel ); + } + else + { + var targetModelAsPositionableElement = targetModel as ILayoutPositionableElement; + var newOrientedPanel = new LayoutAnchorablePaneGroup() + { + Orientation = System.Windows.Controls.Orientation.Vertical, + DockWidth = targetModelAsPositionableElement.DockWidth, + DockHeight = targetModelAsPositionableElement.DockHeight, + }; + + parentModel.InsertChildAt( insertToIndex, newOrientedPanel ); + //the floating window must be added after the target modal as it could be raise a CollectGarbage call + newOrientedPanel.Children.Add( targetModel ); + newOrientedPanel.Children.Insert( 0, floatingWindow.RootPanel ); - protected override void Drop(LayoutAnchorableFloatingWindow floatingWindow) - { - ILayoutAnchorablePane targetModel = _targetPane.Model as ILayoutAnchorablePane; - LayoutAnchorable anchorableActive = floatingWindow.Descendents().OfType().FirstOrDefault(); + } + } + break; + #endregion + case DropTargetType.AnchorablePaneDockLeft: + #region DropTargetType.AnchorablePaneDockLeft + { + var parentModel = targetModel.Parent as ILayoutGroup; + var parentModelOrientable = targetModel.Parent as ILayoutOrientableGroup; + int insertToIndex = parentModel.IndexOfChild( targetModel ); + + if( parentModelOrientable.Orientation != System.Windows.Controls.Orientation.Horizontal && + parentModel.ChildrenCount == 1 ) + parentModelOrientable.Orientation = System.Windows.Controls.Orientation.Horizontal; + + if( parentModelOrientable.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + if( layoutAnchorablePaneGroup != null && + ( layoutAnchorablePaneGroup.Children.Count == 1 || + layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Horizontal ) ) + { + var anchorablesToMove = layoutAnchorablePaneGroup.Children.ToArray(); + for( int i = 0; i < anchorablesToMove.Length; i++ ) + parentModel.InsertChildAt( insertToIndex + i, anchorablesToMove[ i ] ); + } + else + parentModel.InsertChildAt( insertToIndex, floatingWindow.RootPanel ); + } + else + { + var targetModelAsPositionableElement = targetModel as ILayoutPositionableElement; + var newOrientedPanel = new LayoutAnchorablePaneGroup() + { + Orientation = System.Windows.Controls.Orientation.Horizontal, + DockWidth = targetModelAsPositionableElement.DockWidth, + DockHeight = targetModelAsPositionableElement.DockHeight, + }; + + parentModel.InsertChildAt( insertToIndex, newOrientedPanel ); + //the floating window must be added after the target modal as it could be raise a CollectGarbage call + newOrientedPanel.Children.Add( targetModel ); + newOrientedPanel.Children.Insert( 0, floatingWindow.RootPanel ); - switch (Type) + } + } + break; + #endregion + case DropTargetType.AnchorablePaneDockRight: + #region DropTargetType.AnchorablePaneDockRight + { + var parentModel = targetModel.Parent as ILayoutGroup; + var parentModelOrientable = targetModel.Parent as ILayoutOrientableGroup; + int insertToIndex = parentModel.IndexOfChild( targetModel ); + + if( parentModelOrientable.Orientation != System.Windows.Controls.Orientation.Horizontal && + parentModel.ChildrenCount == 1 ) + parentModelOrientable.Orientation = System.Windows.Controls.Orientation.Horizontal; + + if( parentModelOrientable.Orientation == System.Windows.Controls.Orientation.Horizontal ) { - case DropTargetType.AnchorablePaneDockBottom: - #region DropTargetType.AnchorablePaneDockBottom - { - var parentModel = targetModel.Parent as ILayoutGroup; - var parentModelOrientable = targetModel.Parent as ILayoutOrientableGroup; - int insertToIndex = parentModel.IndexOfChild(targetModel); - - if (parentModelOrientable.Orientation != System.Windows.Controls.Orientation.Vertical && - parentModel.ChildrenCount == 1) - parentModelOrientable.Orientation = System.Windows.Controls.Orientation.Vertical; - - if (parentModelOrientable.Orientation == System.Windows.Controls.Orientation.Vertical) - { - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - if (layoutAnchorablePaneGroup != null && - (layoutAnchorablePaneGroup.Children.Count == 1 || - layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Vertical)) - { - var anchorablesToMove = layoutAnchorablePaneGroup.Children.ToArray(); - for (int i = 0; i < anchorablesToMove.Length; i++) - parentModel.InsertChildAt(insertToIndex + 1 + i, anchorablesToMove[i]); - } - else - parentModel.InsertChildAt(insertToIndex + 1, floatingWindow.RootPanel); - } - else - { - var targetModelAsPositionableElement = targetModel as ILayoutPositionableElement; - var newOrientedPanel = new LayoutAnchorablePaneGroup() - { - Orientation = System.Windows.Controls.Orientation.Vertical, - DockWidth = targetModelAsPositionableElement.DockWidth, - DockHeight = targetModelAsPositionableElement.DockHeight, - }; - - parentModel.InsertChildAt(insertToIndex, newOrientedPanel); - newOrientedPanel.Children.Add(targetModel); - newOrientedPanel.Children.Add(floatingWindow.RootPanel); - - } - } - break; - #endregion - case DropTargetType.AnchorablePaneDockTop: - #region DropTargetType.AnchorablePaneDockTop - { - var parentModel = targetModel.Parent as ILayoutGroup; - var parentModelOrientable = targetModel.Parent as ILayoutOrientableGroup; - int insertToIndex = parentModel.IndexOfChild(targetModel); - - if (parentModelOrientable.Orientation != System.Windows.Controls.Orientation.Vertical && - parentModel.ChildrenCount == 1) - parentModelOrientable.Orientation = System.Windows.Controls.Orientation.Vertical; - - if (parentModelOrientable.Orientation == System.Windows.Controls.Orientation.Vertical) - { - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - if (layoutAnchorablePaneGroup != null && - (layoutAnchorablePaneGroup.Children.Count == 1 || - layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Vertical)) - { - var anchorablesToMove = layoutAnchorablePaneGroup.Children.ToArray(); - for (int i = 0; i < anchorablesToMove.Length; i++) - parentModel.InsertChildAt(insertToIndex + i, anchorablesToMove[i]); - } - else - parentModel.InsertChildAt(insertToIndex, floatingWindow.RootPanel); - } - else - { - var targetModelAsPositionableElement = targetModel as ILayoutPositionableElement; - var newOrientedPanel = new LayoutAnchorablePaneGroup() - { - Orientation = System.Windows.Controls.Orientation.Vertical, - DockWidth = targetModelAsPositionableElement.DockWidth, - DockHeight = targetModelAsPositionableElement.DockHeight, - }; - - parentModel.InsertChildAt(insertToIndex, newOrientedPanel); - //the floating window must be added after the target modal as it could be raise a CollectGarbage call - newOrientedPanel.Children.Add(targetModel); - newOrientedPanel.Children.Insert(0, floatingWindow.RootPanel); - - } - } - break; - #endregion - case DropTargetType.AnchorablePaneDockLeft: - #region DropTargetType.AnchorablePaneDockLeft - { - var parentModel = targetModel.Parent as ILayoutGroup; - var parentModelOrientable = targetModel.Parent as ILayoutOrientableGroup; - int insertToIndex = parentModel.IndexOfChild(targetModel); - - if (parentModelOrientable.Orientation != System.Windows.Controls.Orientation.Horizontal && - parentModel.ChildrenCount == 1) - parentModelOrientable.Orientation = System.Windows.Controls.Orientation.Horizontal; - - if (parentModelOrientable.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - if (layoutAnchorablePaneGroup != null && - (layoutAnchorablePaneGroup.Children.Count == 1 || - layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Horizontal)) - { - var anchorablesToMove = layoutAnchorablePaneGroup.Children.ToArray(); - for (int i = 0; i < anchorablesToMove.Length; i++) - parentModel.InsertChildAt(insertToIndex + i, anchorablesToMove[i]); - } - else - parentModel.InsertChildAt(insertToIndex, floatingWindow.RootPanel); - } - else - { - var targetModelAsPositionableElement = targetModel as ILayoutPositionableElement; - var newOrientedPanel = new LayoutAnchorablePaneGroup() - { - Orientation = System.Windows.Controls.Orientation.Horizontal, - DockWidth = targetModelAsPositionableElement.DockWidth, - DockHeight = targetModelAsPositionableElement.DockHeight, - }; - - parentModel.InsertChildAt(insertToIndex, newOrientedPanel); - //the floating window must be added after the target modal as it could be raise a CollectGarbage call - newOrientedPanel.Children.Add(targetModel); - newOrientedPanel.Children.Insert(0, floatingWindow.RootPanel); - - } - } - break; - #endregion - case DropTargetType.AnchorablePaneDockRight: - #region DropTargetType.AnchorablePaneDockRight - { - var parentModel = targetModel.Parent as ILayoutGroup; - var parentModelOrientable = targetModel.Parent as ILayoutOrientableGroup; - int insertToIndex = parentModel.IndexOfChild(targetModel); - - if (parentModelOrientable.Orientation != System.Windows.Controls.Orientation.Horizontal && - parentModel.ChildrenCount == 1) - parentModelOrientable.Orientation = System.Windows.Controls.Orientation.Horizontal; - - if (parentModelOrientable.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - if (layoutAnchorablePaneGroup != null && - (layoutAnchorablePaneGroup.Children.Count == 1 || - layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Horizontal)) - { - var anchorablesToMove = layoutAnchorablePaneGroup.Children.ToArray(); - for (int i = 0; i < anchorablesToMove.Length; i++) - parentModel.InsertChildAt(insertToIndex + 1 + i, anchorablesToMove[i]); - } - else - parentModel.InsertChildAt(insertToIndex + 1, floatingWindow.RootPanel); - } - else - { - var targetModelAsPositionableElement = targetModel as ILayoutPositionableElement; - var newOrientedPanel = new LayoutAnchorablePaneGroup() - { - Orientation = System.Windows.Controls.Orientation.Horizontal, - DockWidth = targetModelAsPositionableElement.DockWidth, - DockHeight = targetModelAsPositionableElement.DockHeight, - }; - - parentModel.InsertChildAt(insertToIndex, newOrientedPanel); - newOrientedPanel.Children.Add(targetModel); - newOrientedPanel.Children.Add(floatingWindow.RootPanel); - - } - } - break; - #endregion - - - case DropTargetType.AnchorablePaneDockInside: - #region DropTargetType.AnchorablePaneDockInside - { - var paneModel = targetModel as LayoutAnchorablePane; - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - - int i = _tabIndex == -1 ? 0 : _tabIndex; - foreach (var anchorableToImport in - layoutAnchorablePaneGroup.Descendents().OfType().ToArray()) - { - paneModel.Children.Insert(i, anchorableToImport); - i++; - } - - } - break; - #endregion + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + if( layoutAnchorablePaneGroup != null && + ( layoutAnchorablePaneGroup.Children.Count == 1 || + layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Horizontal ) ) + { + var anchorablesToMove = layoutAnchorablePaneGroup.Children.ToArray(); + for( int i = 0; i < anchorablesToMove.Length; i++ ) + parentModel.InsertChildAt( insertToIndex + 1 + i, anchorablesToMove[ i ] ); + } + else + parentModel.InsertChildAt( insertToIndex + 1, floatingWindow.RootPanel ); + } + else + { + var targetModelAsPositionableElement = targetModel as ILayoutPositionableElement; + var newOrientedPanel = new LayoutAnchorablePaneGroup() + { + Orientation = System.Windows.Controls.Orientation.Horizontal, + DockWidth = targetModelAsPositionableElement.DockWidth, + DockHeight = targetModelAsPositionableElement.DockHeight, + }; + + parentModel.InsertChildAt( insertToIndex, newOrientedPanel ); + newOrientedPanel.Children.Add( targetModel ); + newOrientedPanel.Children.Add( floatingWindow.RootPanel ); + + } + } + break; + #endregion + + case DropTargetType.AnchorablePaneDockInside: + #region DropTargetType.AnchorablePaneDockInside + { + var paneModel = targetModel as LayoutAnchorablePane; + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + int i = _tabIndex == -1 ? 0 : _tabIndex; + foreach( var anchorableToImport in + layoutAnchorablePaneGroup.Descendents().OfType().ToArray() ) + { + paneModel.Children.Insert( i, anchorableToImport ); + i++; } - anchorableActive.IsActive = true; + } + break; + #endregion + - base.Drop(floatingWindow); - } + } - public override System.Windows.Media.Geometry GetPreviewPath(OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel) - { - //var anchorablePaneDropTarget = target as AnchorablePaneDropTarget; - var anchorableFloatingWindowModel = floatingWindowModel as LayoutAnchorableFloatingWindow; - var layoutAnchorablePane = anchorableFloatingWindowModel.RootPanel as ILayoutPositionableElement; - var layoutAnchorablePaneWithActualSize = anchorableFloatingWindowModel.RootPanel as ILayoutPositionableElementWithActualSize; + anchorableActive.IsActive = true; + + base.Drop( floatingWindow ); + } - switch (Type) + public override System.Windows.Media.Geometry GetPreviewPath( OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel ) + { + //var anchorablePaneDropTarget = target as AnchorablePaneDropTarget; + var anchorableFloatingWindowModel = floatingWindowModel as LayoutAnchorableFloatingWindow; + var layoutAnchorablePane = anchorableFloatingWindowModel.RootPanel as ILayoutPositionableElement; + var layoutAnchorablePaneWithActualSize = anchorableFloatingWindowModel.RootPanel as ILayoutPositionableElementWithActualSize; + + switch( Type ) + { + case DropTargetType.AnchorablePaneDockBottom: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + + targetScreenRect.Offset( 0.0, targetScreenRect.Height / 2.0 ); + targetScreenRect.Height /= 2.0; + + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.AnchorablePaneDockTop: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + + targetScreenRect.Height /= 2.0; + + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.AnchorablePaneDockLeft: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + + targetScreenRect.Width /= 2.0; + + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.AnchorablePaneDockRight: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + + targetScreenRect.Offset( targetScreenRect.Width / 2.0, 0.0 ); + targetScreenRect.Width /= 2.0; + + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.AnchorablePaneDockInside: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + + if( _tabIndex == -1 ) + { + return new RectangleGeometry( targetScreenRect ); + } + else { - case DropTargetType.AnchorablePaneDockBottom: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - - targetScreenRect.Offset(0.0, targetScreenRect.Height / 2.0); - targetScreenRect.Height /= 2.0; - - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.AnchorablePaneDockTop: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - - targetScreenRect.Height /= 2.0; - - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.AnchorablePaneDockLeft: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - - targetScreenRect.Width /= 2.0; - - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.AnchorablePaneDockRight: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - - targetScreenRect.Offset(targetScreenRect.Width / 2.0, 0.0); - targetScreenRect.Width /= 2.0; - - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.AnchorablePaneDockInside: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - - if (_tabIndex == -1) - { - return new RectangleGeometry(targetScreenRect); - } - else - { - var translatedDetectionRect = new Rect(DetectionRects[0].TopLeft, DetectionRects[0].BottomRight); - translatedDetectionRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - var pathFigure = new PathFigure(); - pathFigure.StartPoint = targetScreenRect.TopLeft; - pathFigure.Segments.Add(new LineSegment() { Point = new Point(targetScreenRect.Left, translatedDetectionRect.Top) }); - pathFigure.Segments.Add(new LineSegment() { Point = translatedDetectionRect.TopLeft }); - pathFigure.Segments.Add(new LineSegment() { Point = translatedDetectionRect.BottomLeft }); - pathFigure.Segments.Add(new LineSegment() { Point = translatedDetectionRect.BottomRight }); - pathFigure.Segments.Add(new LineSegment() { Point = translatedDetectionRect.TopRight }); - pathFigure.Segments.Add(new LineSegment() { Point = new Point(targetScreenRect.Right, translatedDetectionRect.Top) }); - pathFigure.Segments.Add(new LineSegment() { Point = targetScreenRect.TopRight }); - pathFigure.IsClosed = true; - pathFigure.IsFilled = true; - pathFigure.Freeze(); - return new PathGeometry(new PathFigure[] { pathFigure }); - } - } + var translatedDetectionRect = new Rect( DetectionRects[ 0 ].TopLeft, DetectionRects[ 0 ].BottomRight ); + translatedDetectionRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + var pathFigure = new PathFigure(); + pathFigure.StartPoint = targetScreenRect.TopLeft; + pathFigure.Segments.Add( new LineSegment() { Point = new Point( targetScreenRect.Left, translatedDetectionRect.Top ) } ); + pathFigure.Segments.Add( new LineSegment() { Point = translatedDetectionRect.TopLeft } ); + pathFigure.Segments.Add( new LineSegment() { Point = translatedDetectionRect.BottomLeft } ); + pathFigure.Segments.Add( new LineSegment() { Point = translatedDetectionRect.BottomRight } ); + pathFigure.Segments.Add( new LineSegment() { Point = translatedDetectionRect.TopRight } ); + pathFigure.Segments.Add( new LineSegment() { Point = new Point( targetScreenRect.Right, translatedDetectionRect.Top ) } ); + pathFigure.Segments.Add( new LineSegment() { Point = targetScreenRect.TopRight } ); + pathFigure.IsClosed = true; + pathFigure.IsFilled = true; + pathFigure.Freeze(); + return new PathGeometry( new PathFigure[] { pathFigure } ); } + } + } - return null; - } + return null; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneTabPanel.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneTabPanel.cs index c4c4787e..00ee5fff 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneTabPanel.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneTabPanel.cs @@ -15,93 +15,98 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class AnchorablePaneTabPanel : Panel + public class AnchorablePaneTabPanel : Panel + { + #region Constructors + + public AnchorablePaneTabPanel() + { + this.FlowDirection = System.Windows.FlowDirection.LeftToRight; + } + + #endregion + + #region Overrides + + protected override Size MeasureOverride( Size availableSize ) { - public AnchorablePaneTabPanel() + double totWidth = 0; + double maxHeight = 0; + var visibleChildren = Children.Cast().Where( ch => ch.Visibility != System.Windows.Visibility.Collapsed ); + foreach( FrameworkElement child in visibleChildren ) + { + child.Measure( new Size( double.PositiveInfinity, availableSize.Height ) ); + totWidth += child.DesiredSize.Width; + maxHeight = Math.Max( maxHeight, child.DesiredSize.Height ); + } + + if( totWidth > availableSize.Width ) + { + double childFinalDesideredWidth = availableSize.Width / visibleChildren.Count(); + foreach( FrameworkElement child in visibleChildren ) { - FlowDirection = System.Windows.FlowDirection.LeftToRight; + child.Measure( new Size( childFinalDesideredWidth, availableSize.Height ) ); } + } + + return new Size( Math.Min( availableSize.Width, totWidth ), maxHeight ); + } + + protected override Size ArrangeOverride( Size finalSize ) + { + var visibleChildren = Children.Cast().Where( ch => ch.Visibility != System.Windows.Visibility.Collapsed ); - protected override Size MeasureOverride(Size availableSize) + double finalWidth = finalSize.Width; + double desideredWidth = visibleChildren.Sum( ch => ch.DesiredSize.Width ); + double offsetX = 0.0; + + if( finalWidth > desideredWidth ) + { + foreach( FrameworkElement child in visibleChildren ) { - double totWidth = 0; - double maxHeight = 0; - var visibleChildren = Children.Cast().Where(ch => ch.Visibility != System.Windows.Visibility.Collapsed); - foreach (FrameworkElement child in visibleChildren) - { - child.Measure(new Size(double.PositiveInfinity, availableSize.Height)); - totWidth += child.DesiredSize.Width; - maxHeight = Math.Max(maxHeight, child.DesiredSize.Height); - } - - if (totWidth > availableSize.Width) - { - double childFinalDesideredWidth = availableSize.Width / visibleChildren.Count(); - foreach (FrameworkElement child in visibleChildren) - { - child.Measure(new Size(childFinalDesideredWidth, availableSize.Height)); - } - } - - return new Size(Math.Min(availableSize.Width, totWidth), maxHeight); - } + double childFinalWidth = child.DesiredSize.Width; + child.Arrange( new Rect( offsetX, 0, childFinalWidth, finalSize.Height ) ); - protected override Size ArrangeOverride(Size finalSize) + offsetX += childFinalWidth; + } + } + else + { + double childFinalWidth = finalWidth / visibleChildren.Count(); + foreach( FrameworkElement child in visibleChildren ) { - var visibleChildren = Children.Cast().Where(ch => ch.Visibility != System.Windows.Visibility.Collapsed); - - - double finalWidth = finalSize.Width; - double desideredWidth = visibleChildren.Sum(ch => ch.DesiredSize.Width); - double offsetX = 0.0; - - if (finalWidth > desideredWidth) - { - foreach (FrameworkElement child in visibleChildren) - { - double childFinalWidth = child.DesiredSize.Width ; - child.Arrange(new Rect(offsetX, 0, childFinalWidth, finalSize.Height)); - - offsetX += childFinalWidth; - } - } - else - { - double childFinalWidth = finalWidth / visibleChildren.Count(); - foreach (FrameworkElement child in visibleChildren) - { - child.Arrange(new Rect(offsetX, 0, childFinalWidth, finalSize.Height)); - - offsetX += childFinalWidth; - } - } - - return finalSize; + child.Arrange( new Rect( offsetX, 0, childFinalWidth, finalSize.Height ) ); + + offsetX += childFinalWidth; } + } - protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e) - { - if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && - LayoutAnchorableTabItem.IsDraggingItem()) - { - var contentModel = LayoutAnchorableTabItem.GetDraggingItem().Model as LayoutAnchorable; - var manager = contentModel.Root.Manager; - LayoutAnchorableTabItem.ResetDraggingItem(); + return finalSize; + } - manager.StartDraggingFloatingWindowForContent(contentModel); - } + protected override void OnMouseLeave( System.Windows.Input.MouseEventArgs e ) + { + if( e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && + LayoutAnchorableTabItem.IsDraggingItem() ) + { + var contentModel = LayoutAnchorableTabItem.GetDraggingItem().Model as LayoutAnchorable; + var manager = contentModel.Root.Manager; + LayoutAnchorableTabItem.ResetDraggingItem(); - base.OnMouseLeave(e); - } + manager.StartDraggingFloatingWindowForContent( contentModel ); + } + + base.OnMouseLeave( e ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneTitle.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneTitle.cs index bf11271b..a4c5c481 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneTitle.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AnchorablePaneTitle.cs @@ -14,10 +14,7 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using System.Windows.Input; @@ -25,165 +22,191 @@ using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { + public class AnchorablePaneTitle : Control + { + #region Members - public class AnchorablePaneTitle : Control + private bool _isMouseDown = false; + + #endregion + + #region Constructors + + static AnchorablePaneTitle() { - static AnchorablePaneTitle() - { - IsHitTestVisibleProperty.OverrideMetadata(typeof(AnchorablePaneTitle), new FrameworkPropertyMetadata(true)); - FocusableProperty.OverrideMetadata(typeof(AnchorablePaneTitle), new FrameworkPropertyMetadata(false)); - DefaultStyleKeyProperty.OverrideMetadata(typeof(AnchorablePaneTitle), new FrameworkPropertyMetadata(typeof(AnchorablePaneTitle))); - } + IsHitTestVisibleProperty.OverrideMetadata( typeof( AnchorablePaneTitle ), new FrameworkPropertyMetadata( true ) ); + FocusableProperty.OverrideMetadata( typeof( AnchorablePaneTitle ), new FrameworkPropertyMetadata( false ) ); + DefaultStyleKeyProperty.OverrideMetadata( typeof( AnchorablePaneTitle ), new FrameworkPropertyMetadata( typeof( AnchorablePaneTitle ) ) ); + } + public AnchorablePaneTitle() + { + } - public AnchorablePaneTitle() - { + #endregion - } + #region Properties - #region Model + #region Model - /// - /// Model Dependency Property - /// - public static readonly DependencyProperty ModelProperty = - DependencyProperty.Register("Model", typeof(LayoutAnchorable), typeof(AnchorablePaneTitle), - new FrameworkPropertyMetadata((LayoutAnchorable)null, new PropertyChangedCallback(_OnModelChanged))); + /// + /// Model Dependency Property + /// + public static readonly DependencyProperty ModelProperty = DependencyProperty.Register( "Model", typeof( LayoutAnchorable ), typeof( AnchorablePaneTitle ), + new FrameworkPropertyMetadata( ( LayoutAnchorable )null, new PropertyChangedCallback( _OnModelChanged ) ) ); - /// - /// Gets or sets the Model property. This dependency property - /// indicates model attached to this view. - /// - public LayoutAnchorable Model - { - get { return (LayoutAnchorable)GetValue(ModelProperty); } - set { SetValue(ModelProperty, value); } - } + /// + /// Gets or sets the Model property. This dependency property + /// indicates model attached to this view. + /// + public LayoutAnchorable Model + { + get + { + return ( LayoutAnchorable )GetValue( ModelProperty ); + } + set + { + SetValue( ModelProperty, value ); + } + } - static void _OnModelChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) - { - ((AnchorablePaneTitle)sender).OnModelChanged(e); - } + private static void _OnModelChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e ) + { + ( ( AnchorablePaneTitle )sender ).OnModelChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the Model property. - /// - protected virtual void OnModelChanged(DependencyPropertyChangedEventArgs e) - { - if (Model != null) - SetLayoutItem(Model.Root.Manager.GetLayoutItemFromModel(Model)); - else - SetLayoutItem(null); - } + /// + /// Provides derived classes an opportunity to handle changes to the Model property. + /// + protected virtual void OnModelChanged( DependencyPropertyChangedEventArgs e ) + { + if( Model != null ) + { + this.SetLayoutItem( Model.Root.Manager.GetLayoutItemFromModel( Model ) ); + } + else + { + this.SetLayoutItem( null ); + } + } - #endregion + #endregion + #region LayoutItem - #region LayoutItem + /// + /// LayoutItem Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey LayoutItemPropertyKey = DependencyProperty.RegisterReadOnly( "LayoutItem", typeof( LayoutItem ), typeof( AnchorablePaneTitle ), + new FrameworkPropertyMetadata( ( LayoutItem )null ) ); - /// - /// LayoutItem Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey LayoutItemPropertyKey - = DependencyProperty.RegisterReadOnly("LayoutItem", typeof(LayoutItem), typeof(AnchorablePaneTitle), - new FrameworkPropertyMetadata((LayoutItem)null)); + public static readonly DependencyProperty LayoutItemProperty = LayoutItemPropertyKey.DependencyProperty; - public static readonly DependencyProperty LayoutItemProperty - = LayoutItemPropertyKey.DependencyProperty; + /// + /// Gets the LayoutItem property. This dependency property + /// indicates the LayoutItem attached to this tag item. + /// + public LayoutItem LayoutItem + { + get + { + return ( LayoutItem )GetValue( LayoutItemProperty ); + } + } - /// - /// Gets the LayoutItem property. This dependency property - /// indicates the LayoutItem attached to this tag item. - /// - public LayoutItem LayoutItem - { - get { return (LayoutItem)GetValue(LayoutItemProperty); } - } + /// + /// Provides a secure method for setting the LayoutItem property. + /// This dependency property indicates the LayoutItem attached to this tag item. + /// + /// The new value for the property. + protected void SetLayoutItem( LayoutItem value ) + { + this.SetValue( LayoutItemPropertyKey, value ); + } - /// - /// Provides a secure method for setting the LayoutItem property. - /// This dependency property indicates the LayoutItem attached to this tag item. - /// - /// The new value for the property. - protected void SetLayoutItem(LayoutItem value) - { - SetValue(LayoutItemPropertyKey, value); - } + #endregion - #endregion + #endregion + #region Overrides - private void OnHide() - { - Model.Hide(); - } + protected override void OnMouseMove( System.Windows.Input.MouseEventArgs e ) + { + if( e.LeftButton != MouseButtonState.Pressed ) + { + _isMouseDown = false; + } - private void OnToggleAutoHide() - { - Model.ToggleAutoHide(); - } + base.OnMouseMove( e ); + } - protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e) + protected override void OnMouseLeave( System.Windows.Input.MouseEventArgs e ) + { + base.OnMouseLeave( e ); + + if( _isMouseDown && e.LeftButton == MouseButtonState.Pressed ) + { + var pane = this.FindVisualAncestor(); + if( pane != null ) { - if (e.LeftButton != MouseButtonState.Pressed) - { - _isMouseDown = false; - } + var paneModel = pane.Model as LayoutAnchorablePane; + var manager = paneModel.Root.Manager; - base.OnMouseMove(e); + manager.StartDraggingFloatingWindowForPane( paneModel ); } + } - protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e) - { - base.OnMouseLeave(e); - - if (_isMouseDown && e.LeftButton == MouseButtonState.Pressed) - { - var pane = this.FindVisualAncestor(); - if (pane != null) - { - var paneModel = pane.Model as LayoutAnchorablePane; - var manager = paneModel.Root.Manager; + _isMouseDown = false; + } - manager.StartDraggingFloatingWindowForPane(paneModel); - } - } + protected override void OnMouseLeftButtonDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseLeftButtonDown( e ); - _isMouseDown = false; + if( !e.Handled ) + { + bool attachFloatingWindow = false; + var parentFloatingWindow = Model.FindParent(); + if( parentFloatingWindow != null ) + { + attachFloatingWindow = parentFloatingWindow.Descendents().OfType().Count() == 1; } - bool _isMouseDown = false; - protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) + if( attachFloatingWindow ) { - base.OnMouseLeftButtonDown(e); - - if (!e.Handled) - { - bool attachFloatingWindow = false; - var parentFloatingWindow = Model.FindParent(); - if (parentFloatingWindow != null) - { - attachFloatingWindow = parentFloatingWindow.Descendents().OfType().Count() == 1; - } - - if (attachFloatingWindow) - { - //the pane is hosted inside a floating window that contains only an anchorable pane so drag the floating window itself - var floatingWndControl = Model.Root.Manager.FloatingWindows.Single(fwc => fwc.Model == parentFloatingWindow); - floatingWndControl.AttachDrag(false); - } - else - _isMouseDown = true;//normal drag - } + //the pane is hosted inside a floating window that contains only an anchorable pane so drag the floating window itself + var floatingWndControl = Model.Root.Manager.FloatingWindows.Single( fwc => fwc.Model == parentFloatingWindow ); + floatingWndControl.AttachDrag( false ); } + else + _isMouseDown = true;//normal drag + } + } - protected override void OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e) - { - _isMouseDown = false; - base.OnMouseLeftButtonUp(e); + protected override void OnMouseLeftButtonUp( System.Windows.Input.MouseButtonEventArgs e ) + { + _isMouseDown = false; + base.OnMouseLeftButtonUp( e ); - if (Model != null) - Model.IsActive = true;//FocusElementManager.SetFocusOnLastElement(Model); - } + if( Model != null ) + Model.IsActive = true;//FocusElementManager.SetFocusOnLastElement(Model); } + + #endregion + + #region Private Methods + + private void OnHide() + { + this.Model.Hide(); + } + + private void OnToggleAutoHide() + { + this.Model.ToggleAutoHide(); + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AutoHideWindowManager.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AutoHideWindowManager.cs index d589bb15..33260c23 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AutoHideWindowManager.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/AutoHideWindowManager.cs @@ -15,76 +15,82 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Threading; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - class AutoHideWindowManager + internal class AutoHideWindowManager + { + #region Members + + private DockingManager _manager; + private WeakReference _currentAutohiddenAnchor = null; + private DispatcherTimer _closeTimer = null; + + #endregion + + #region Constructors + + internal AutoHideWindowManager( DockingManager manager ) + { + _manager = manager; + this.SetupCloseTimer(); + } + + #endregion + + #region Private Methods + + public void ShowAutoHideWindow( LayoutAnchorControl anchor ) + { + if( _currentAutohiddenAnchor.GetValueOrDefault() != anchor ) + { + StopCloseTimer(); + _currentAutohiddenAnchor = new WeakReference( anchor ); + _manager.AutoHideWindow.Show( anchor ); + StartCloseTimer(); + } + } + + public void HideAutoWindow( LayoutAnchorControl anchor = null ) + { + if( anchor == null || + anchor == _currentAutohiddenAnchor.GetValueOrDefault() ) + { + StopCloseTimer(); + } + else + System.Diagnostics.Debug.Assert( false ); + } + + private void SetupCloseTimer() { - DockingManager _manager; - - internal AutoHideWindowManager(DockingManager manager) - { - _manager = manager; - SetupCloseTimer(); - } - - - WeakReference _currentAutohiddenAnchor = null; - - public void ShowAutoHideWindow(LayoutAnchorControl anchor) - { - if(_currentAutohiddenAnchor.GetValueOrDefault() != anchor) - { - StopCloseTimer(); - _currentAutohiddenAnchor = new WeakReference(anchor); - _manager.AutoHideWindow.Show(anchor); - StartCloseTimer(); - } - } - - public void HideAutoWindow(LayoutAnchorControl anchor = null) - { - if (anchor == null || - anchor == _currentAutohiddenAnchor.GetValueOrDefault()) - { - StopCloseTimer(); - } - else - System.Diagnostics.Debug.Assert(false); - } - - DispatcherTimer _closeTimer = null; - void SetupCloseTimer() - { - _closeTimer = new DispatcherTimer(DispatcherPriority.Background); - _closeTimer.Interval = TimeSpan.FromMilliseconds(1500); - _closeTimer.Tick += (s, e) => - { - if (_manager.AutoHideWindow.IsWin32MouseOver || - ((LayoutAnchorable)_manager.AutoHideWindow.Model).IsActive || - _manager.AutoHideWindow.IsResizing) - return; - - StopCloseTimer(); - }; - } - - void StartCloseTimer() - { - _closeTimer.Start(); - - } - - void StopCloseTimer() - { - _closeTimer.Stop(); - _manager.AutoHideWindow.Hide(); - _currentAutohiddenAnchor = null; - } + _closeTimer = new DispatcherTimer( DispatcherPriority.Background ); + _closeTimer.Interval = TimeSpan.FromMilliseconds( 1500 ); + _closeTimer.Tick += ( s, e ) => + { + if( _manager.AutoHideWindow.IsWin32MouseOver || + ( ( LayoutAnchorable )_manager.AutoHideWindow.Model ).IsActive || + _manager.AutoHideWindow.IsResizing ) + return; + + StopCloseTimer(); + }; } + + private void StartCloseTimer() + { + _closeTimer.Start(); + } + + private void StopCloseTimer() + { + _closeTimer.Stop(); + _manager.AutoHideWindow.Hide(); + _currentAutohiddenAnchor = null; + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/BindingHelper.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/BindingHelper.cs index e04049e1..b31b35b7 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/BindingHelper.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/BindingHelper.cs @@ -15,9 +15,6 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; using System.ComponentModel; using System.Windows.Data; @@ -25,31 +22,35 @@ using System.Windows.Threading; namespace Xceed.Wpf.AvalonDock.Controls { - class BindingHelper + internal class BindingHelper + { + #region Methods + + public static void RebindInactiveBindings( DependencyObject dependencyObject ) { - public static void RebindInactiveBindings(DependencyObject dependencyObject) + foreach( PropertyDescriptor property in TypeDescriptor.GetProperties( dependencyObject.GetType() ) ) + { + var dpd = DependencyPropertyDescriptor.FromProperty( property ); + if( dpd != null ) { - foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(dependencyObject.GetType())) + BindingExpressionBase binding = BindingOperations.GetBindingExpressionBase( dependencyObject, dpd.DependencyProperty ); + if( binding != null ) + { + //if (property.Name == "DataContext" || binding.HasError || binding.Status != BindingStatus.Active) { - var dpd = DependencyPropertyDescriptor.FromProperty(property); - if (dpd != null) - { - BindingExpressionBase binding = BindingOperations.GetBindingExpressionBase(dependencyObject, dpd.DependencyProperty); - if (binding != null) - { - //if (property.Name == "DataContext" || binding.HasError || binding.Status != BindingStatus.Active) - { - // Ensure that no pending calls are in the dispatcher queue - Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.SystemIdle, (Action)delegate - { - // Remove and add the binding to re-trigger the binding error - dependencyObject.ClearValue(dpd.DependencyProperty); - BindingOperations.SetBinding(dependencyObject, dpd.DependencyProperty, binding.ParentBindingBase); - }); - } - } - } + // Ensure that no pending calls are in the dispatcher queue + Dispatcher.CurrentDispatcher.BeginInvoke( DispatcherPriority.SystemIdle, ( Action )delegate + { + // Remove and add the binding to re-trigger the binding error + dependencyObject.ClearValue( dpd.DependencyProperty ); + BindingOperations.SetBinding( dependencyObject, dpd.DependencyProperty, binding.ParentBindingBase ); + } ); } + } } + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/ContextMenuEx.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/ContextMenuEx.cs index 3bffa602..c5d9274e 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/ContextMenuEx.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/ContextMenuEx.cs @@ -14,39 +14,39 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows.Data; -using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - public class ContextMenuEx : ContextMenu - { - static ContextMenuEx() - { - } + public class ContextMenuEx : ContextMenu + { + #region Constructors - public ContextMenuEx() - { + static ContextMenuEx() + { + } - } + public ContextMenuEx() + { + } - protected override System.Windows.DependencyObject GetContainerForItemOverride() - { - return new MenuItemEx(); - } + #endregion - protected override void OnOpened(System.Windows.RoutedEventArgs e) - { - BindingOperations.GetBindingExpression(this, ItemsSourceProperty).UpdateTarget(); + #region Overrides - base.OnOpened(e); - } + protected override System.Windows.DependencyObject GetContainerForItemOverride() + { + return new MenuItemEx(); + } + protected override void OnOpened( System.Windows.RoutedEventArgs e ) + { + BindingOperations.GetBindingExpression( this, ItemsSourceProperty ).UpdateTarget(); + base.OnOpened( e ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DockingManagerDropTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DockingManagerDropTarget.cs index ab773a3f..415cdf49 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DockingManagerDropTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DockingManagerDropTarget.cs @@ -15,234 +15,245 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - internal class DockingManagerDropTarget : DropTarget + internal class DockingManagerDropTarget : DropTarget + { + #region Members + + private DockingManager _manager; + + #endregion + + #region Constructors + + internal DockingManagerDropTarget( DockingManager manager, Rect detectionRect, DropTargetType type ) + : base( manager, detectionRect, type ) { - internal DockingManagerDropTarget(DockingManager manager, Rect detectionRect, DropTargetType type) - : base(manager, detectionRect, type) - { - _manager = manager; - } + _manager = manager; + } + + #endregion - DockingManager _manager; + #region Overrides - protected override void Drop(LayoutAnchorableFloatingWindow floatingWindow) - { - switch (Type) + protected override void Drop( LayoutAnchorableFloatingWindow floatingWindow ) + { + switch( Type ) + { + case DropTargetType.DockingManagerDockLeft: + #region DropTargetType.DockingManagerDockLeft + { + if( _manager.Layout.RootPanel.Orientation != System.Windows.Controls.Orientation.Horizontal && + _manager.Layout.RootPanel.Children.Count == 1 ) + _manager.Layout.RootPanel.Orientation = System.Windows.Controls.Orientation.Horizontal; + + if( _manager.Layout.RootPanel.Orientation == System.Windows.Controls.Orientation.Horizontal ) { - case DropTargetType.DockingManagerDockLeft: - #region DropTargetType.DockingManagerDockLeft - { - if (_manager.Layout.RootPanel.Orientation != System.Windows.Controls.Orientation.Horizontal && - _manager.Layout.RootPanel.Children.Count == 1) - _manager.Layout.RootPanel.Orientation = System.Windows.Controls.Orientation.Horizontal; - - if (_manager.Layout.RootPanel.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - if (layoutAnchorablePaneGroup != null && - layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - var childrenToTransfer = layoutAnchorablePaneGroup.Children.ToArray(); - for (int i = 0; i < childrenToTransfer.Length; i++) - _manager.Layout.RootPanel.Children.Insert(i, childrenToTransfer[i]); - } - else - _manager.Layout.RootPanel.Children.Insert(0, floatingWindow.RootPanel); - } - else - { - var newOrientedPanel = new LayoutPanel() - { - Orientation = System.Windows.Controls.Orientation.Horizontal - }; - - newOrientedPanel.Children.Add(floatingWindow.RootPanel); - newOrientedPanel.Children.Add(_manager.Layout.RootPanel); - - _manager.Layout.RootPanel = newOrientedPanel; - } - } - break; - #endregion - case DropTargetType.DockingManagerDockRight: - #region DropTargetType.DockingManagerDockRight - { - if (_manager.Layout.RootPanel.Orientation != System.Windows.Controls.Orientation.Horizontal && - _manager.Layout.RootPanel.Children.Count == 1) - _manager.Layout.RootPanel.Orientation = System.Windows.Controls.Orientation.Horizontal; - - if (_manager.Layout.RootPanel.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - if (layoutAnchorablePaneGroup != null && - layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - var childrenToTransfer = layoutAnchorablePaneGroup.Children.ToArray(); - for (int i = 0; i < childrenToTransfer.Length; i++) - _manager.Layout.RootPanel.Children.Add(childrenToTransfer[i]); - } - else - _manager.Layout.RootPanel.Children.Add(floatingWindow.RootPanel); - } - else - { - var newOrientedPanel = new LayoutPanel() - { - Orientation = System.Windows.Controls.Orientation.Horizontal - }; - - newOrientedPanel.Children.Add(_manager.Layout.RootPanel); - newOrientedPanel.Children.Add(floatingWindow.RootPanel); - - _manager.Layout.RootPanel = newOrientedPanel; - } - } - break; - #endregion - case DropTargetType.DockingManagerDockTop: - #region DropTargetType.DockingManagerDockTop - { - if (_manager.Layout.RootPanel.Orientation != System.Windows.Controls.Orientation.Vertical && - _manager.Layout.RootPanel.Children.Count == 1) - _manager.Layout.RootPanel.Orientation = System.Windows.Controls.Orientation.Vertical; - - if (_manager.Layout.RootPanel.Orientation == System.Windows.Controls.Orientation.Vertical) - { - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - if (layoutAnchorablePaneGroup != null && - layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Vertical) - { - var childrenToTransfer = layoutAnchorablePaneGroup.Children.ToArray(); - for (int i = 0; i < childrenToTransfer.Length; i++) - _manager.Layout.RootPanel.Children.Insert(i, childrenToTransfer[i]); - } - else - _manager.Layout.RootPanel.Children.Insert(0, floatingWindow.RootPanel); - } - else - { - var newOrientedPanel = new LayoutPanel() - { - Orientation = System.Windows.Controls.Orientation.Vertical - }; - - newOrientedPanel.Children.Add(floatingWindow.RootPanel); - newOrientedPanel.Children.Add(_manager.Layout.RootPanel); - - _manager.Layout.RootPanel = newOrientedPanel; - } - } - break; - #endregion - case DropTargetType.DockingManagerDockBottom: - #region DropTargetType.DockingManagerDockBottom - { - if (_manager.Layout.RootPanel.Orientation != System.Windows.Controls.Orientation.Vertical && - _manager.Layout.RootPanel.Children.Count == 1) - _manager.Layout.RootPanel.Orientation = System.Windows.Controls.Orientation.Vertical; - - if (_manager.Layout.RootPanel.Orientation == System.Windows.Controls.Orientation.Vertical) - { - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - if (layoutAnchorablePaneGroup != null && - layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Vertical) - { - var childrenToTransfer = layoutAnchorablePaneGroup.Children.ToArray(); - for (int i = 0; i < childrenToTransfer.Length; i++) - _manager.Layout.RootPanel.Children.Add(childrenToTransfer[i]); - - } - else - _manager.Layout.RootPanel.Children.Add(floatingWindow.RootPanel); - } - else - { - var newOrientedPanel = new LayoutPanel() - { - Orientation = System.Windows.Controls.Orientation.Vertical - }; - - newOrientedPanel.Children.Add(_manager.Layout.RootPanel); - newOrientedPanel.Children.Add(floatingWindow.RootPanel); - - _manager.Layout.RootPanel = newOrientedPanel; - } - } - break; - #endregion + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + if( layoutAnchorablePaneGroup != null && + layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + var childrenToTransfer = layoutAnchorablePaneGroup.Children.ToArray(); + for( int i = 0; i < childrenToTransfer.Length; i++ ) + _manager.Layout.RootPanel.Children.Insert( i, childrenToTransfer[ i ] ); + } + else + _manager.Layout.RootPanel.Children.Insert( 0, floatingWindow.RootPanel ); } + else + { + var newOrientedPanel = new LayoutPanel() + { + Orientation = System.Windows.Controls.Orientation.Horizontal + }; + newOrientedPanel.Children.Add( floatingWindow.RootPanel ); + newOrientedPanel.Children.Add( _manager.Layout.RootPanel ); - base.Drop(floatingWindow); - } + _manager.Layout.RootPanel = newOrientedPanel; + } + } + break; + #endregion + case DropTargetType.DockingManagerDockRight: + #region DropTargetType.DockingManagerDockRight + { + if( _manager.Layout.RootPanel.Orientation != System.Windows.Controls.Orientation.Horizontal && + _manager.Layout.RootPanel.Children.Count == 1 ) + _manager.Layout.RootPanel.Orientation = System.Windows.Controls.Orientation.Horizontal; + + if( _manager.Layout.RootPanel.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + if( layoutAnchorablePaneGroup != null && + layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + var childrenToTransfer = layoutAnchorablePaneGroup.Children.ToArray(); + for( int i = 0; i < childrenToTransfer.Length; i++ ) + _manager.Layout.RootPanel.Children.Add( childrenToTransfer[ i ] ); + } + else + _manager.Layout.RootPanel.Children.Add( floatingWindow.RootPanel ); + } + else + { + var newOrientedPanel = new LayoutPanel() + { + Orientation = System.Windows.Controls.Orientation.Horizontal + }; - public override System.Windows.Media.Geometry GetPreviewPath(OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel) - { - var anchorableFloatingWindowModel = floatingWindowModel as LayoutAnchorableFloatingWindow; - var layoutAnchorablePane = anchorableFloatingWindowModel.RootPanel as ILayoutPositionableElement; - var layoutAnchorablePaneWithActualSize = anchorableFloatingWindowModel.RootPanel as ILayoutPositionableElementWithActualSize; + newOrientedPanel.Children.Add( floatingWindow.RootPanel ); + newOrientedPanel.Children.Insert( 0, _manager.Layout.RootPanel ); - var targetScreenRect = TargetElement.GetScreenArea(); - switch (Type) + _manager.Layout.RootPanel = newOrientedPanel; + } + } + break; + #endregion + case DropTargetType.DockingManagerDockTop: + #region DropTargetType.DockingManagerDockTop + { + if( _manager.Layout.RootPanel.Orientation != System.Windows.Controls.Orientation.Vertical && + _manager.Layout.RootPanel.Children.Count == 1 ) + _manager.Layout.RootPanel.Orientation = System.Windows.Controls.Orientation.Vertical; + + if( _manager.Layout.RootPanel.Orientation == System.Windows.Controls.Orientation.Vertical ) { - case DropTargetType.DockingManagerDockLeft: - { - var desideredWidth = layoutAnchorablePane.DockWidth.IsAbsolute ? layoutAnchorablePane.DockWidth.Value : layoutAnchorablePaneWithActualSize.ActualWidth; - var previewBoxRect = new Rect( - targetScreenRect.Left - overlayWindow.Left, - targetScreenRect.Top - overlayWindow.Top, - Math.Min(desideredWidth, targetScreenRect.Width / 2.0), - targetScreenRect.Height); - - return new RectangleGeometry(previewBoxRect); - } - case DropTargetType.DockingManagerDockTop: - { - var desideredHeight = layoutAnchorablePane.DockHeight.IsAbsolute ? layoutAnchorablePane.DockHeight.Value : layoutAnchorablePaneWithActualSize.ActualHeight; - var previewBoxRect = new Rect( - targetScreenRect.Left - overlayWindow.Left, - targetScreenRect.Top - overlayWindow.Top, - targetScreenRect.Width, - Math.Min(desideredHeight, targetScreenRect.Height / 2.0)); - - return new RectangleGeometry(previewBoxRect); - } - case DropTargetType.DockingManagerDockRight: - { - var desideredWidth = layoutAnchorablePane.DockWidth.IsAbsolute ? layoutAnchorablePane.DockWidth.Value : layoutAnchorablePaneWithActualSize.ActualWidth; - var previewBoxRect = new Rect( - targetScreenRect.Right - overlayWindow.Left - Math.Min(desideredWidth, targetScreenRect.Width / 2.0), - targetScreenRect.Top - overlayWindow.Top, - Math.Min(desideredWidth, targetScreenRect.Width / 2.0), - targetScreenRect.Height); - - return new RectangleGeometry(previewBoxRect); - } - case DropTargetType.DockingManagerDockBottom: - { - var desideredHeight = layoutAnchorablePane.DockHeight.IsAbsolute ? layoutAnchorablePane.DockHeight.Value : layoutAnchorablePaneWithActualSize.ActualHeight; - var previewBoxRect = new Rect( - targetScreenRect.Left - overlayWindow.Left, - targetScreenRect.Bottom - overlayWindow.Top - Math.Min(desideredHeight, targetScreenRect.Height / 2.0), - targetScreenRect.Width, - Math.Min(desideredHeight, targetScreenRect.Height / 2.0)); - - return new RectangleGeometry(previewBoxRect); - } + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + if( layoutAnchorablePaneGroup != null && + layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + var childrenToTransfer = layoutAnchorablePaneGroup.Children.ToArray(); + for( int i = 0; i < childrenToTransfer.Length; i++ ) + _manager.Layout.RootPanel.Children.Insert( i, childrenToTransfer[ i ] ); + } + else + _manager.Layout.RootPanel.Children.Insert( 0, floatingWindow.RootPanel ); } + else + { + var newOrientedPanel = new LayoutPanel() + { + Orientation = System.Windows.Controls.Orientation.Vertical + }; + newOrientedPanel.Children.Add( floatingWindow.RootPanel ); + newOrientedPanel.Children.Add( _manager.Layout.RootPanel ); - throw new InvalidOperationException(); - } + _manager.Layout.RootPanel = newOrientedPanel; + } + } + break; + #endregion + case DropTargetType.DockingManagerDockBottom: + #region DropTargetType.DockingManagerDockBottom + { + if( _manager.Layout.RootPanel.Orientation != System.Windows.Controls.Orientation.Vertical && + _manager.Layout.RootPanel.Children.Count == 1 ) + _manager.Layout.RootPanel.Orientation = System.Windows.Controls.Orientation.Vertical; + + if( _manager.Layout.RootPanel.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + if( layoutAnchorablePaneGroup != null && + layoutAnchorablePaneGroup.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + var childrenToTransfer = layoutAnchorablePaneGroup.Children.ToArray(); + for( int i = 0; i < childrenToTransfer.Length; i++ ) + _manager.Layout.RootPanel.Children.Add( childrenToTransfer[ i ] ); + + } + else + _manager.Layout.RootPanel.Children.Add( floatingWindow.RootPanel ); + } + else + { + var newOrientedPanel = new LayoutPanel() + { + Orientation = System.Windows.Controls.Orientation.Vertical + }; + + newOrientedPanel.Children.Add( floatingWindow.RootPanel ); + newOrientedPanel.Children.Insert( 0, _manager.Layout.RootPanel ); + + _manager.Layout.RootPanel = newOrientedPanel; + } + } + break; + #endregion + } + + + base.Drop( floatingWindow ); + } + + public override System.Windows.Media.Geometry GetPreviewPath( OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel ) + { + var anchorableFloatingWindowModel = floatingWindowModel as LayoutAnchorableFloatingWindow; + var layoutAnchorablePane = anchorableFloatingWindowModel.RootPanel as ILayoutPositionableElement; + var layoutAnchorablePaneWithActualSize = anchorableFloatingWindowModel.RootPanel as ILayoutPositionableElementWithActualSize; + + var targetScreenRect = TargetElement.GetScreenArea(); + + switch( Type ) + { + case DropTargetType.DockingManagerDockLeft: + { + var desideredWidth = layoutAnchorablePane.DockWidth.IsAbsolute ? layoutAnchorablePane.DockWidth.Value : layoutAnchorablePaneWithActualSize.ActualWidth; + var previewBoxRect = new Rect( + targetScreenRect.Left - overlayWindow.Left, + targetScreenRect.Top - overlayWindow.Top, + Math.Min( desideredWidth, targetScreenRect.Width / 2.0 ), + targetScreenRect.Height ); + + return new RectangleGeometry( previewBoxRect ); + } + case DropTargetType.DockingManagerDockTop: + { + var desideredHeight = layoutAnchorablePane.DockHeight.IsAbsolute ? layoutAnchorablePane.DockHeight.Value : layoutAnchorablePaneWithActualSize.ActualHeight; + var previewBoxRect = new Rect( + targetScreenRect.Left - overlayWindow.Left, + targetScreenRect.Top - overlayWindow.Top, + targetScreenRect.Width, + Math.Min( desideredHeight, targetScreenRect.Height / 2.0 ) ); + + return new RectangleGeometry( previewBoxRect ); + } + case DropTargetType.DockingManagerDockRight: + { + var desideredWidth = layoutAnchorablePane.DockWidth.IsAbsolute ? layoutAnchorablePane.DockWidth.Value : layoutAnchorablePaneWithActualSize.ActualWidth; + var previewBoxRect = new Rect( + targetScreenRect.Right - overlayWindow.Left - Math.Min( desideredWidth, targetScreenRect.Width / 2.0 ), + targetScreenRect.Top - overlayWindow.Top, + Math.Min( desideredWidth, targetScreenRect.Width / 2.0 ), + targetScreenRect.Height ); + + return new RectangleGeometry( previewBoxRect ); + } + case DropTargetType.DockingManagerDockBottom: + { + var desideredHeight = layoutAnchorablePane.DockHeight.IsAbsolute ? layoutAnchorablePane.DockHeight.Value : layoutAnchorablePaneWithActualSize.ActualHeight; + var previewBoxRect = new Rect( + targetScreenRect.Left - overlayWindow.Left, + targetScreenRect.Bottom - overlayWindow.Top - Math.Min( desideredHeight, targetScreenRect.Height / 2.0 ), + targetScreenRect.Width, + Math.Min( desideredHeight, targetScreenRect.Height / 2.0 ) ); + + return new RectangleGeometry( previewBoxRect ); + } + } + + + throw new InvalidOperationException(); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DockingManagerOverlayArea.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DockingManagerOverlayArea.cs index 0192c7fe..90091192 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DockingManagerOverlayArea.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DockingManagerOverlayArea.cs @@ -14,27 +14,30 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - public class DockingManagerOverlayArea : OverlayArea - { - internal DockingManagerOverlayArea(IOverlayWindow overlayWindow, DockingManager manager) - : base(overlayWindow) - { - _manager = manager; + public class DockingManagerOverlayArea : OverlayArea + { + #region Members + + private DockingManager _manager; - base.SetScreenDetectionArea(new Rect( - _manager.PointToScreenDPI(new Point()), - _manager.TransformActualSizeToAncestor())); - } + #endregion - DockingManager _manager; + #region Constructors + internal DockingManagerOverlayArea( IOverlayWindow overlayWindow, DockingManager manager ) + : base( overlayWindow ) + { + _manager = manager; + + base.SetScreenDetectionArea( new Rect( + _manager.PointToScreenDPI( new Point() ), + _manager.TransformActualSizeToAncestor() ) ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneControlOverlayArea.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneControlOverlayArea.cs index 0069ae84..6f427b03 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneControlOverlayArea.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneControlOverlayArea.cs @@ -14,31 +14,29 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - public class DocumentPaneControlOverlayArea : OverlayArea - { - + public class DocumentPaneControlOverlayArea : OverlayArea + { + #region Members - internal DocumentPaneControlOverlayArea( - IOverlayWindow overlayWindow, - LayoutDocumentPaneControl documentPaneControl) - : base(overlayWindow) - { - _documentPaneControl = documentPaneControl; - base.SetScreenDetectionArea(new Rect( - _documentPaneControl.PointToScreenDPI(new Point()), - _documentPaneControl.TransformActualSizeToAncestor())); - } + private LayoutDocumentPaneControl _documentPaneControl; - LayoutDocumentPaneControl _documentPaneControl; + #endregion + #region Constructors + internal DocumentPaneControlOverlayArea( + IOverlayWindow overlayWindow, + LayoutDocumentPaneControl documentPaneControl ) + : base( overlayWindow ) + { + _documentPaneControl = documentPaneControl; + base.SetScreenDetectionArea( new Rect( _documentPaneControl.PointToScreenDPI( new Point() ), _documentPaneControl.TransformActualSizeToAncestor() ) ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneDropAsAnchorableTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneDropAsAnchorableTarget.cs index fbe700c7..5d86257d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneDropAsAnchorableTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneDropAsAnchorableTarget.cs @@ -15,263 +15,271 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; -using System.Diagnostics; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - internal class DocumentPaneDropAsAnchorableTarget : DropTarget - { - internal DocumentPaneDropAsAnchorableTarget(LayoutDocumentPaneControl paneControl, Rect detectionRect, DropTargetType type) - : base(paneControl, detectionRect, type) - { - _targetPane = paneControl; - } + internal class DocumentPaneDropAsAnchorableTarget : DropTarget + { + #region Members - internal DocumentPaneDropAsAnchorableTarget(LayoutDocumentPaneControl paneControl, Rect detectionRect, DropTargetType type, int tabIndex) - : base(paneControl, detectionRect, type) - { - _targetPane = paneControl; - _tabIndex = tabIndex; - } + private LayoutDocumentPaneControl _targetPane; + int _tabIndex = -1; + #endregion - LayoutDocumentPaneControl _targetPane; + #region Constructors - int _tabIndex = -1; + internal DocumentPaneDropAsAnchorableTarget( LayoutDocumentPaneControl paneControl, Rect detectionRect, DropTargetType type ) + : base( paneControl, detectionRect, type ) + { + _targetPane = paneControl; + } - protected override void Drop(LayoutAnchorableFloatingWindow floatingWindow) - { - ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; - LayoutDocumentPaneGroup parentGroup; - LayoutPanel parentGroupPanel; - FindParentLayoutDocumentPane(targetModel, out parentGroup, out parentGroupPanel); + internal DocumentPaneDropAsAnchorableTarget( LayoutDocumentPaneControl paneControl, Rect detectionRect, DropTargetType type, int tabIndex ) + : base( paneControl, detectionRect, type ) + { + _targetPane = paneControl; + _tabIndex = tabIndex; + } - switch (Type) - { - case DropTargetType.DocumentPaneDockAsAnchorableBottom: - #region DropTargetType.DocumentPaneDockAsAnchorableBottom - { - if (parentGroupPanel != null && - parentGroupPanel.ChildrenCount == 1) - parentGroupPanel.Orientation = System.Windows.Controls.Orientation.Vertical; - - if (parentGroupPanel != null && - parentGroupPanel.Orientation == System.Windows.Controls.Orientation.Vertical) - { - parentGroupPanel.Children.Insert( - parentGroupPanel.IndexOfChild(parentGroup != null ? parentGroup : targetModel) + 1, - floatingWindow.RootPanel); - } - else if (parentGroupPanel != null) - { - var newParentPanel = new LayoutPanel() { Orientation = System.Windows.Controls.Orientation.Vertical }; - parentGroupPanel.ReplaceChild(parentGroup != null ? parentGroup : targetModel, newParentPanel); - newParentPanel.Children.Add(parentGroup != null ? parentGroup : targetModel); - newParentPanel.Children.Add(floatingWindow.RootPanel); - } - else - { - throw new NotImplementedException(); - } - - - } - break; - #endregion - case DropTargetType.DocumentPaneDockAsAnchorableTop: - #region DropTargetType.DocumentPaneDockAsAnchorableTop - { - if (parentGroupPanel != null && - parentGroupPanel.ChildrenCount == 1) - parentGroupPanel.Orientation = System.Windows.Controls.Orientation.Vertical; - - if (parentGroupPanel != null && - parentGroupPanel.Orientation == System.Windows.Controls.Orientation.Vertical) - { - parentGroupPanel.Children.Insert( - parentGroupPanel.IndexOfChild(parentGroup != null ? parentGroup : targetModel), - floatingWindow.RootPanel); - } - else if (parentGroupPanel != null) - { - var newParentPanel = new LayoutPanel() { Orientation = System.Windows.Controls.Orientation.Vertical }; - parentGroupPanel.ReplaceChild(parentGroup != null ? parentGroup : targetModel, newParentPanel); - newParentPanel.Children.Add(parentGroup != null ? parentGroup : targetModel); - newParentPanel.Children.Insert(0, floatingWindow.RootPanel); - } - else - { - throw new NotImplementedException(); - } - - } - break; - #endregion - case DropTargetType.DocumentPaneDockAsAnchorableLeft: - #region DropTargetType.DocumentPaneDockAsAnchorableLeft - { - if (parentGroupPanel != null && - parentGroupPanel.ChildrenCount == 1) - parentGroupPanel.Orientation = System.Windows.Controls.Orientation.Horizontal; - - if (parentGroupPanel != null && - parentGroupPanel.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - parentGroupPanel.Children.Insert( - parentGroupPanel.IndexOfChild(parentGroup != null ? parentGroup : targetModel), - floatingWindow.RootPanel); - } - else if (parentGroupPanel != null) - { - var newParentPanel = new LayoutPanel() { Orientation = System.Windows.Controls.Orientation.Horizontal }; - parentGroupPanel.ReplaceChild(parentGroup != null ? parentGroup : targetModel, newParentPanel); - newParentPanel.Children.Add(parentGroup != null ? parentGroup : targetModel); - newParentPanel.Children.Insert(0, floatingWindow.RootPanel); - } - else - { - throw new NotImplementedException(); - } - } - break; - #endregion - case DropTargetType.DocumentPaneDockAsAnchorableRight: - #region DropTargetType.DocumentPaneDockAsAnchorableRight - { - if (parentGroupPanel != null && - parentGroupPanel.ChildrenCount == 1) - parentGroupPanel.Orientation = System.Windows.Controls.Orientation.Horizontal; - - if (parentGroupPanel != null && - parentGroupPanel.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - parentGroupPanel.Children.Insert( - parentGroupPanel.IndexOfChild(parentGroup != null ? parentGroup : targetModel) + 1, - floatingWindow.RootPanel); - } - else if (parentGroupPanel != null) - { - var newParentPanel = new LayoutPanel() { Orientation = System.Windows.Controls.Orientation.Horizontal }; - parentGroupPanel.ReplaceChild(parentGroup != null ? parentGroup : targetModel, newParentPanel); - newParentPanel.Children.Add(parentGroup != null ? parentGroup : targetModel); - newParentPanel.Children.Add(floatingWindow.RootPanel); - } - else - { - throw new NotImplementedException(); - } - } - break; - #endregion - } + #endregion - base.Drop(floatingWindow); - } + #region Overrides - public override System.Windows.Media.Geometry GetPreviewPath(OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel) - { - Rect targetScreenRect; - ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; - var manager = targetModel.Root.Manager; - - //ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; - LayoutDocumentPaneGroup parentGroup; - LayoutPanel parentGroupPanel; - if (!FindParentLayoutDocumentPane(targetModel, out parentGroup, out parentGroupPanel)) - return null; - - //if (targetModel.Parent is LayoutDocumentPaneGroup) - //{ - // var parentGroup = targetModel.Parent as LayoutDocumentPaneGroup; - // var documentPaneGroupControl = manager.FindLogicalChildren().First(d => d.Model == parentGroup); - // targetScreenRect = documentPaneGroupControl.GetScreenArea(); - //} - //else - //{ - // var documentPaneControl = manager.FindLogicalChildren().First(d => d.Model == targetModel); - // targetScreenRect = documentPaneControl.GetScreenArea(); - //} - - //var parentPanel = targetModel.FindParent(); - var documentPaneControl = manager.FindLogicalChildren().OfType().First(d => parentGroup != null ? d.Model == parentGroup : d.Model == parentGroupPanel) as FrameworkElement; - targetScreenRect = documentPaneControl.GetScreenArea(); - - switch (Type) + protected override void Drop( LayoutAnchorableFloatingWindow floatingWindow ) + { + ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; + LayoutDocumentPaneGroup parentGroup; + LayoutPanel parentGroupPanel; + FindParentLayoutDocumentPane( targetModel, out parentGroup, out parentGroupPanel ); + + switch( Type ) + { + case DropTargetType.DocumentPaneDockAsAnchorableBottom: + #region DropTargetType.DocumentPaneDockAsAnchorableBottom + { + if( parentGroupPanel != null && + parentGroupPanel.ChildrenCount == 1 ) + parentGroupPanel.Orientation = System.Windows.Controls.Orientation.Vertical; + + if( parentGroupPanel != null && + parentGroupPanel.Orientation == System.Windows.Controls.Orientation.Vertical ) { - case DropTargetType.DocumentPaneDockAsAnchorableBottom: - { - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - targetScreenRect.Offset(0.0, targetScreenRect.Height - targetScreenRect.Height / 3.0); - targetScreenRect.Height /= 3.0; - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.DocumentPaneDockAsAnchorableTop: - { - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - targetScreenRect.Height /= 3.0; - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.DocumentPaneDockAsAnchorableRight: - { - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - targetScreenRect.Offset(targetScreenRect.Width - targetScreenRect.Width / 3.0, 0.0); - targetScreenRect.Width /= 3.0; - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.DocumentPaneDockAsAnchorableLeft: - { - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - targetScreenRect.Width /= 3.0; - return new RectangleGeometry(targetScreenRect); - } + parentGroupPanel.Children.Insert( + parentGroupPanel.IndexOfChild( parentGroup != null ? parentGroup : targetModel ) + 1, + floatingWindow.RootPanel ); + } + else if( parentGroupPanel != null ) + { + var newParentPanel = new LayoutPanel() { Orientation = System.Windows.Controls.Orientation.Vertical }; + parentGroupPanel.ReplaceChild( parentGroup != null ? parentGroup : targetModel, newParentPanel ); + newParentPanel.Children.Add( parentGroup != null ? parentGroup : targetModel ); + newParentPanel.Children.Add( floatingWindow.RootPanel ); + } + else + { + throw new NotImplementedException(); } - - return null; - } - - bool FindParentLayoutDocumentPane(ILayoutDocumentPane documentPane, out LayoutDocumentPaneGroup containerPaneGroup, out LayoutPanel containerPanel) - { - containerPaneGroup = null; - containerPanel = null; + } + break; + #endregion + case DropTargetType.DocumentPaneDockAsAnchorableTop: + #region DropTargetType.DocumentPaneDockAsAnchorableTop + { + if( parentGroupPanel != null && + parentGroupPanel.ChildrenCount == 1 ) + parentGroupPanel.Orientation = System.Windows.Controls.Orientation.Vertical; - if (documentPane.Parent is LayoutPanel) + if( parentGroupPanel != null && + parentGroupPanel.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + parentGroupPanel.Children.Insert( + parentGroupPanel.IndexOfChild( parentGroup != null ? parentGroup : targetModel ), + floatingWindow.RootPanel ); + } + else if( parentGroupPanel != null ) { - containerPaneGroup = null; - containerPanel = documentPane.Parent as LayoutPanel; - return true; + var newParentPanel = new LayoutPanel() { Orientation = System.Windows.Controls.Orientation.Vertical }; + parentGroupPanel.ReplaceChild( parentGroup != null ? parentGroup : targetModel, newParentPanel ); + newParentPanel.Children.Add( parentGroup != null ? parentGroup : targetModel ); + newParentPanel.Children.Insert( 0, floatingWindow.RootPanel ); } - else if (documentPane.Parent is LayoutDocumentPaneGroup) + else { - var currentDocumentPaneGroup = documentPane.Parent as LayoutDocumentPaneGroup; - while (!(currentDocumentPaneGroup.Parent is LayoutPanel)) - { - currentDocumentPaneGroup = currentDocumentPaneGroup.Parent as LayoutDocumentPaneGroup; + throw new NotImplementedException(); + } - if (currentDocumentPaneGroup == null) - break; - } + } + break; + #endregion + case DropTargetType.DocumentPaneDockAsAnchorableLeft: + #region DropTargetType.DocumentPaneDockAsAnchorableLeft + { + if( parentGroupPanel != null && + parentGroupPanel.ChildrenCount == 1 ) + parentGroupPanel.Orientation = System.Windows.Controls.Orientation.Horizontal; + + if( parentGroupPanel != null && + parentGroupPanel.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + parentGroupPanel.Children.Insert( + parentGroupPanel.IndexOfChild( parentGroup != null ? parentGroup : targetModel ), + floatingWindow.RootPanel ); + } + else if( parentGroupPanel != null ) + { + var newParentPanel = new LayoutPanel() { Orientation = System.Windows.Controls.Orientation.Horizontal }; + parentGroupPanel.ReplaceChild( parentGroup != null ? parentGroup : targetModel, newParentPanel ); + newParentPanel.Children.Add( parentGroup != null ? parentGroup : targetModel ); + newParentPanel.Children.Insert( 0, floatingWindow.RootPanel ); + } + else + { + throw new NotImplementedException(); + } + } + break; + #endregion + case DropTargetType.DocumentPaneDockAsAnchorableRight: + #region DropTargetType.DocumentPaneDockAsAnchorableRight + { + if( parentGroupPanel != null && + parentGroupPanel.ChildrenCount == 1 ) + parentGroupPanel.Orientation = System.Windows.Controls.Orientation.Horizontal; + + if( parentGroupPanel != null && + parentGroupPanel.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + parentGroupPanel.Children.Insert( + parentGroupPanel.IndexOfChild( parentGroup != null ? parentGroup : targetModel ) + 1, + floatingWindow.RootPanel ); + } + else if( parentGroupPanel != null ) + { + var newParentPanel = new LayoutPanel() { Orientation = System.Windows.Controls.Orientation.Horizontal }; + parentGroupPanel.ReplaceChild( parentGroup != null ? parentGroup : targetModel, newParentPanel ); + newParentPanel.Children.Add( parentGroup != null ? parentGroup : targetModel ); + newParentPanel.Children.Add( floatingWindow.RootPanel ); + } + else + { + throw new NotImplementedException(); + } + } + break; + #endregion + } - if (currentDocumentPaneGroup == null) - return false; + base.Drop( floatingWindow ); + } - containerPaneGroup = currentDocumentPaneGroup; - containerPanel = currentDocumentPaneGroup.Parent as LayoutPanel; - return true; - } + public override System.Windows.Media.Geometry GetPreviewPath( OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel ) + { + Rect targetScreenRect; + ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; + var manager = targetModel.Root.Manager; + + //ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; + LayoutDocumentPaneGroup parentGroup; + LayoutPanel parentGroupPanel; + if( !FindParentLayoutDocumentPane( targetModel, out parentGroup, out parentGroupPanel ) ) + return null; + + //if (targetModel.Parent is LayoutDocumentPaneGroup) + //{ + // var parentGroup = targetModel.Parent as LayoutDocumentPaneGroup; + // var documentPaneGroupControl = manager.FindLogicalChildren().First(d => d.Model == parentGroup); + // targetScreenRect = documentPaneGroupControl.GetScreenArea(); + //} + //else + //{ + // var documentPaneControl = manager.FindLogicalChildren().First(d => d.Model == targetModel); + // targetScreenRect = documentPaneControl.GetScreenArea(); + //} + + //var parentPanel = targetModel.FindParent(); + var documentPaneControl = manager.FindLogicalChildren().OfType().First( d => parentGroup != null ? d.Model == parentGroup : d.Model == parentGroupPanel ) as FrameworkElement; + targetScreenRect = documentPaneControl.GetScreenArea(); + + switch( Type ) + { + case DropTargetType.DocumentPaneDockAsAnchorableBottom: + { + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + targetScreenRect.Offset( 0.0, targetScreenRect.Height - targetScreenRect.Height / 3.0 ); + targetScreenRect.Height /= 3.0; + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.DocumentPaneDockAsAnchorableTop: + { + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + targetScreenRect.Height /= 3.0; + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.DocumentPaneDockAsAnchorableRight: + { + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + targetScreenRect.Offset( targetScreenRect.Width - targetScreenRect.Width / 3.0, 0.0 ); + targetScreenRect.Width /= 3.0; + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.DocumentPaneDockAsAnchorableLeft: + { + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + targetScreenRect.Width /= 3.0; + return new RectangleGeometry( targetScreenRect ); + } + } + + return null; + } - return false; + #endregion + #region Private Methods + private bool FindParentLayoutDocumentPane( ILayoutDocumentPane documentPane, out LayoutDocumentPaneGroup containerPaneGroup, out LayoutPanel containerPanel ) + { + containerPaneGroup = null; + containerPanel = null; + + if( documentPane.Parent is LayoutPanel ) + { + containerPaneGroup = null; + containerPanel = documentPane.Parent as LayoutPanel; + return true; + } + else if( documentPane.Parent is LayoutDocumentPaneGroup ) + { + var currentDocumentPaneGroup = documentPane.Parent as LayoutDocumentPaneGroup; + while( !( currentDocumentPaneGroup.Parent is LayoutPanel ) ) + { + currentDocumentPaneGroup = currentDocumentPaneGroup.Parent as LayoutDocumentPaneGroup; + if( currentDocumentPaneGroup == null ) + break; } + if( currentDocumentPaneGroup == null ) + return false; + + containerPaneGroup = currentDocumentPaneGroup; + containerPanel = currentDocumentPaneGroup.Parent as LayoutPanel; + return true; + } + + return false; + + + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneDropTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneDropTarget.cs index 5fce23d0..2df4f018 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneDropTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneDropTarget.cs @@ -14,461 +14,500 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; -using System.Diagnostics; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - internal class DocumentPaneDropTarget : DropTarget + internal class DocumentPaneDropTarget : DropTarget + { + #region Members + + private LayoutDocumentPaneControl _targetPane; + private int _tabIndex = -1; + + #endregion + + #region Constructors + + internal DocumentPaneDropTarget( LayoutDocumentPaneControl paneControl, Rect detectionRect, DropTargetType type ) + : base( paneControl, detectionRect, type ) { - internal DocumentPaneDropTarget(LayoutDocumentPaneControl paneControl, Rect detectionRect, DropTargetType type) - : base(paneControl, detectionRect, type) - { - _targetPane = paneControl; - } + _targetPane = paneControl; + } + + internal DocumentPaneDropTarget( LayoutDocumentPaneControl paneControl, Rect detectionRect, DropTargetType type, int tabIndex ) + : base( paneControl, detectionRect, type ) + { + _targetPane = paneControl; + _tabIndex = tabIndex; + } + + #endregion + + #region Overrides + + protected override void Drop( LayoutDocumentFloatingWindow floatingWindow ) + { + ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; + + switch( Type ) + { + case DropTargetType.DocumentPaneDockBottom: + #region DropTargetType.DocumentPaneDockBottom + { + var newLayoutDocumentPane = new LayoutDocumentPane( floatingWindow.RootDocument ); + var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; + + if( parentModel == null ) + { + var parentContainer = targetModel.Parent as ILayoutContainer; + var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; + parentContainer.ReplaceChild( targetModel, newParentModel ); + newParentModel.Children.Add( targetModel as LayoutDocumentPane ); + newParentModel.Children.Add( newLayoutDocumentPane ); + } + else + { + var manager = parentModel.Root.Manager; + if( !manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + parentModel.Orientation = System.Windows.Controls.Orientation.Vertical; + int targetPaneIndex = parentModel.IndexOfChild( targetModel ); + parentModel.Children.Insert( targetPaneIndex + 1, newLayoutDocumentPane ); + } + else + { + LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); + newChildGroup.Orientation = System.Windows.Controls.Orientation.Vertical; + parentModel.ReplaceChild( targetModel, newChildGroup ); + newChildGroup.Children.Add( targetModel ); + newChildGroup.Children.Add( newLayoutDocumentPane ); + } + + } + } + break; + #endregion + case DropTargetType.DocumentPaneDockTop: + #region DropTargetType.DocumentPaneDockTop + { + var newLayoutDocumentPane = new LayoutDocumentPane( floatingWindow.RootDocument ); + var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; + + if( parentModel == null ) + { + var parentContainer = targetModel.Parent as ILayoutContainer; + var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; + parentContainer.ReplaceChild( targetModel, newParentModel ); + newParentModel.Children.Add( targetModel as LayoutDocumentPane ); + newParentModel.Children.Insert( 0, newLayoutDocumentPane ); + } + else + { + var manager = parentModel.Root.Manager; + if( !manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + parentModel.Orientation = System.Windows.Controls.Orientation.Vertical; + int targetPaneIndex = parentModel.IndexOfChild( targetModel ); + parentModel.Children.Insert( targetPaneIndex, newLayoutDocumentPane ); + } + else + { + LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); + newChildGroup.Orientation = System.Windows.Controls.Orientation.Vertical; + parentModel.ReplaceChild( targetModel, newChildGroup ); + newChildGroup.Children.Add( newLayoutDocumentPane ); + newChildGroup.Children.Add( targetModel ); + } + + } + } + break; + #endregion + case DropTargetType.DocumentPaneDockLeft: + #region DropTargetType.DocumentPaneDockLeft + { + var newLayoutDocumentPane = new LayoutDocumentPane( floatingWindow.RootDocument ); + var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; + + if( parentModel == null ) + { + var parentContainer = targetModel.Parent as ILayoutContainer; + var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; + parentContainer.ReplaceChild( targetModel, newParentModel ); + newParentModel.Children.Add( targetModel ); + newParentModel.Children.Insert( 0, newLayoutDocumentPane ); + } + else + { + var manager = parentModel.Root.Manager; + if( !manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + parentModel.Orientation = System.Windows.Controls.Orientation.Horizontal; + int targetPaneIndex = parentModel.IndexOfChild( targetModel ); + parentModel.Children.Insert( targetPaneIndex, newLayoutDocumentPane ); + } + else + { + LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); + newChildGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; + parentModel.ReplaceChild( targetModel, newChildGroup ); + newChildGroup.Children.Add( newLayoutDocumentPane ); + newChildGroup.Children.Add( targetModel ); + } + } + } + break; + #endregion + case DropTargetType.DocumentPaneDockRight: + #region DropTargetType.DocumentPaneDockRight + { + var newLayoutDocumentPane = new LayoutDocumentPane( floatingWindow.RootDocument ); + var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; + + if( parentModel == null ) + { + var parentContainer = targetModel.Parent as ILayoutContainer; + var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; + parentContainer.ReplaceChild( targetModel, newParentModel ); + newParentModel.Children.Add( targetModel as LayoutDocumentPane ); + newParentModel.Children.Add( newLayoutDocumentPane ); + } + else + { + var manager = parentModel.Root.Manager; + if( !manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + parentModel.Orientation = System.Windows.Controls.Orientation.Horizontal; + int targetPaneIndex = parentModel.IndexOfChild( targetModel ); + parentModel.Children.Insert( targetPaneIndex + 1, newLayoutDocumentPane ); + } + else + { + LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); + newChildGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; + parentModel.ReplaceChild( targetModel, newChildGroup ); + newChildGroup.Children.Add( targetModel ); + newChildGroup.Children.Add( newLayoutDocumentPane ); + } + + } + } + break; + #endregion + + case DropTargetType.DocumentPaneDockInside: + #region DropTargetType.DocumentPaneDockInside + { + var paneModel = targetModel as LayoutDocumentPane; + var sourceModel = floatingWindow.RootDocument; + + int i = 0; + if( _tabIndex != -1 ) + { + i = _tabIndex; + } + else + { + var previousIndex = 0; + var previousContainer = ( ( ILayoutPreviousContainer )sourceModel ).PreviousContainer; + if( object.ReferenceEquals( previousContainer, targetModel ) && ( sourceModel.PreviousContainerIndex != -1 ) ) + { + previousIndex = sourceModel.PreviousContainerIndex; + } + + i = previousIndex; + } + sourceModel.IsActive = false; + paneModel.Children.Insert( i, sourceModel ); + sourceModel.IsActive = true; + } + break; + #endregion - internal DocumentPaneDropTarget(LayoutDocumentPaneControl paneControl, Rect detectionRect, DropTargetType type, int tabIndex) - : base(paneControl, detectionRect, type) - { - _targetPane = paneControl; - _tabIndex = tabIndex; - } + } - LayoutDocumentPaneControl _targetPane; + base.Drop( floatingWindow ); + } - int _tabIndex = -1; + protected override void Drop( LayoutAnchorableFloatingWindow floatingWindow ) + { + ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; - protected override void Drop(LayoutDocumentFloatingWindow floatingWindow) - { - ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; + switch( Type ) + { + case DropTargetType.DocumentPaneDockBottom: + #region DropTargetType.DocumentPaneDockBottom + { + var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; + var newLayoutDocumentPane = new LayoutDocumentPane(); - switch (Type) + if( parentModel == null ) + { + var parentContainer = targetModel.Parent as ILayoutContainer; + var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; + parentContainer.ReplaceChild( targetModel, newParentModel ); + newParentModel.Children.Add( targetModel as LayoutDocumentPane ); + newParentModel.Children.Add( newLayoutDocumentPane ); + } + else { - case DropTargetType.DocumentPaneDockBottom: - #region DropTargetType.DocumentPaneDockBottom - { - var newLayoutDocumentPane = new LayoutDocumentPane(floatingWindow.RootDocument); - var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; - - if (parentModel == null) - { - var parentContainer = targetModel.Parent as ILayoutContainer; - var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical}; - parentContainer.ReplaceChild(targetModel, newParentModel); - newParentModel.Children.Add(targetModel as LayoutDocumentPane); - newParentModel.Children.Add(newLayoutDocumentPane); - } - else - { - var manager = parentModel.Root.Manager; - if (!manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Vertical) - { - parentModel.Orientation = System.Windows.Controls.Orientation.Vertical; - int targetPaneIndex = parentModel.IndexOfChild(targetModel); - parentModel.Children.Insert(targetPaneIndex + 1, newLayoutDocumentPane); - } - else - { - LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); - newChildGroup.Orientation = System.Windows.Controls.Orientation.Vertical; - parentModel.ReplaceChild(targetModel, newChildGroup); - newChildGroup.Children.Add(targetModel); - newChildGroup.Children.Add(newLayoutDocumentPane); - } - - } - } - break; - #endregion - case DropTargetType.DocumentPaneDockTop: - #region DropTargetType.DocumentPaneDockTop - { - var newLayoutDocumentPane = new LayoutDocumentPane(floatingWindow.RootDocument); - var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; - - if (parentModel == null) - { - var parentContainer = targetModel.Parent as ILayoutContainer; - var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; - parentContainer.ReplaceChild(targetModel, newParentModel); - newParentModel.Children.Add(targetModel as LayoutDocumentPane); - newParentModel.Children.Insert(0, newLayoutDocumentPane); - } - else - { - var manager = parentModel.Root.Manager; - if (!manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Vertical) - { - parentModel.Orientation = System.Windows.Controls.Orientation.Vertical; - int targetPaneIndex = parentModel.IndexOfChild(targetModel); - parentModel.Children.Insert(targetPaneIndex, newLayoutDocumentPane); - } - else - { - LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); - newChildGroup.Orientation = System.Windows.Controls.Orientation.Vertical; - parentModel.ReplaceChild(targetModel, newChildGroup); - newChildGroup.Children.Add(newLayoutDocumentPane); - newChildGroup.Children.Add(targetModel); - } - - } - } - break; - #endregion - case DropTargetType.DocumentPaneDockLeft: - #region DropTargetType.DocumentPaneDockLeft - { - var newLayoutDocumentPane = new LayoutDocumentPane(floatingWindow.RootDocument); - var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; - - if (parentModel == null) - { - var parentContainer = targetModel.Parent as ILayoutContainer; - var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; - parentContainer.ReplaceChild(targetModel, newParentModel); - newParentModel.Children.Add(targetModel); - newParentModel.Children.Insert(0, newLayoutDocumentPane); - } - else - { - var manager = parentModel.Root.Manager; - if (!manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - parentModel.Orientation = System.Windows.Controls.Orientation.Horizontal; - int targetPaneIndex = parentModel.IndexOfChild(targetModel); - parentModel.Children.Insert(targetPaneIndex, newLayoutDocumentPane); - } - else - { - LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); - newChildGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; - parentModel.ReplaceChild(targetModel, newChildGroup); - newChildGroup.Children.Add(newLayoutDocumentPane); - newChildGroup.Children.Add(targetModel); - } - } - } - break; - #endregion - case DropTargetType.DocumentPaneDockRight: - #region DropTargetType.DocumentPaneDockRight - { - var newLayoutDocumentPane = new LayoutDocumentPane(floatingWindow.RootDocument); - var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; - - if (parentModel == null) - { - var parentContainer = targetModel.Parent as ILayoutContainer; - var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; - parentContainer.ReplaceChild(targetModel, newParentModel); - newParentModel.Children.Add(targetModel as LayoutDocumentPane); - newParentModel.Children.Add(newLayoutDocumentPane); - } - else - { - var manager = parentModel.Root.Manager; - if (!manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - parentModel.Orientation = System.Windows.Controls.Orientation.Horizontal; - int targetPaneIndex = parentModel.IndexOfChild(targetModel); - parentModel.Children.Insert(targetPaneIndex + 1, newLayoutDocumentPane); - } - else - { - LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); - newChildGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; - parentModel.ReplaceChild(targetModel, newChildGroup); - newChildGroup.Children.Add(targetModel); - newChildGroup.Children.Add(newLayoutDocumentPane); - } - - } - } - break; - #endregion - - case DropTargetType.DocumentPaneDockInside: - #region DropTargetType.DocumentPaneDockInside - { - var paneModel = targetModel as LayoutDocumentPane; - var sourceModel = floatingWindow.RootDocument; - - int i = _tabIndex == -1 ? 0 : _tabIndex; - sourceModel.IsActive = false; - paneModel.Children.Insert(i, sourceModel); - sourceModel.IsActive = true; - } - break; - #endregion + var manager = parentModel.Root.Manager; + if( !manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + parentModel.Orientation = System.Windows.Controls.Orientation.Vertical; + int targetPaneIndex = parentModel.IndexOfChild( targetModel ); + parentModel.Children.Insert( targetPaneIndex + 1, newLayoutDocumentPane ); + } + else + { + LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); + newChildGroup.Orientation = System.Windows.Controls.Orientation.Vertical; + parentModel.ReplaceChild( targetModel, newChildGroup ); + newChildGroup.Children.Add( targetModel ); + newChildGroup.Children.Add( newLayoutDocumentPane ); + } + } + foreach( var cntToTransfer in floatingWindow.RootPanel.Descendents().OfType().ToArray() ) + newLayoutDocumentPane.Children.Add( cntToTransfer ); + } + break; + #endregion + case DropTargetType.DocumentPaneDockTop: + #region DropTargetType.DocumentPaneDockTop + { + var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; + var newLayoutDocumentPane = new LayoutDocumentPane(); + + if( parentModel == null ) + { + var parentContainer = targetModel.Parent as ILayoutContainer; + var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; + parentContainer.ReplaceChild( targetModel, newParentModel ); + newParentModel.Children.Add( newLayoutDocumentPane ); + newParentModel.Children.Add( targetModel as LayoutDocumentPane ); + } + else + { + var manager = parentModel.Root.Manager; + if( !manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Vertical ) + { + parentModel.Orientation = System.Windows.Controls.Orientation.Vertical; + int targetPaneIndex = parentModel.IndexOfChild( targetModel ); + parentModel.Children.Insert( targetPaneIndex, newLayoutDocumentPane ); + } + else + { + LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); + newChildGroup.Orientation = System.Windows.Controls.Orientation.Vertical; + parentModel.ReplaceChild( targetModel, newChildGroup ); + newChildGroup.Children.Add( newLayoutDocumentPane ); + newChildGroup.Children.Add( targetModel ); + } } - base.Drop(floatingWindow); - } + foreach( var cntToTransfer in floatingWindow.RootPanel.Descendents().OfType().ToArray() ) + newLayoutDocumentPane.Children.Add( cntToTransfer ); - protected override void Drop(LayoutAnchorableFloatingWindow floatingWindow) - { - ILayoutDocumentPane targetModel = _targetPane.Model as ILayoutDocumentPane; + } + break; + #endregion + case DropTargetType.DocumentPaneDockLeft: + #region DropTargetType.DocumentPaneDockLeft + { + var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; + var newLayoutDocumentPane = new LayoutDocumentPane(); - switch (Type) + if( parentModel == null ) { - case DropTargetType.DocumentPaneDockBottom: - #region DropTargetType.DocumentPaneDockBottom - { - var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; - var newLayoutDocumentPane = new LayoutDocumentPane(); - - if (parentModel == null) - { - var parentContainer = targetModel.Parent as ILayoutContainer; - var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; - parentContainer.ReplaceChild(targetModel, newParentModel); - newParentModel.Children.Add(targetModel as LayoutDocumentPane); - newParentModel.Children.Add(newLayoutDocumentPane); - } - else - { - var manager = parentModel.Root.Manager; - if (!manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Vertical) - { - parentModel.Orientation = System.Windows.Controls.Orientation.Vertical; - int targetPaneIndex = parentModel.IndexOfChild(targetModel); - parentModel.Children.Insert(targetPaneIndex + 1, newLayoutDocumentPane); - } - else - { - LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); - newChildGroup.Orientation = System.Windows.Controls.Orientation.Vertical; - parentModel.ReplaceChild(targetModel, newChildGroup); - newChildGroup.Children.Add(targetModel); - newChildGroup.Children.Add(newLayoutDocumentPane); - } - } - - foreach (var cntToTransfer in floatingWindow.RootPanel.Descendents().OfType().ToArray()) - newLayoutDocumentPane.Children.Add(cntToTransfer); - - } - break; - #endregion - case DropTargetType.DocumentPaneDockTop: - #region DropTargetType.DocumentPaneDockTop - { - var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; - var newLayoutDocumentPane = new LayoutDocumentPane(); - - if (parentModel == null) - { - var parentContainer = targetModel.Parent as ILayoutContainer; - var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; - parentContainer.ReplaceChild(targetModel, newParentModel); - newParentModel.Children.Add(newLayoutDocumentPane); - newParentModel.Children.Add(targetModel as LayoutDocumentPane); - } - else - { - var manager = parentModel.Root.Manager; - if (!manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Vertical) - { - parentModel.Orientation = System.Windows.Controls.Orientation.Vertical; - int targetPaneIndex = parentModel.IndexOfChild(targetModel); - parentModel.Children.Insert(targetPaneIndex, newLayoutDocumentPane); - } - else - { - LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); - newChildGroup.Orientation = System.Windows.Controls.Orientation.Vertical; - parentModel.ReplaceChild(targetModel, newChildGroup); - newChildGroup.Children.Add(newLayoutDocumentPane); - newChildGroup.Children.Add(targetModel); - } - } - - foreach (var cntToTransfer in floatingWindow.RootPanel.Descendents().OfType().ToArray()) - newLayoutDocumentPane.Children.Add(cntToTransfer); - - } - break; - #endregion - case DropTargetType.DocumentPaneDockLeft: - #region DropTargetType.DocumentPaneDockLeft - { - var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; - var newLayoutDocumentPane = new LayoutDocumentPane(); - - if (parentModel == null) - { - var parentContainer = targetModel.Parent as ILayoutContainer; - var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; - parentContainer.ReplaceChild(targetModel, newParentModel); - newParentModel.Children.Add(newLayoutDocumentPane); - newParentModel.Children.Add(targetModel as LayoutDocumentPane); - } - else - { - var manager = parentModel.Root.Manager; - if (!manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - parentModel.Orientation = System.Windows.Controls.Orientation.Horizontal; - int targetPaneIndex = parentModel.IndexOfChild(targetModel); - parentModel.Children.Insert(targetPaneIndex, newLayoutDocumentPane); - } - else - { - LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); - newChildGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; - parentModel.ReplaceChild(targetModel, newChildGroup); - newChildGroup.Children.Add(newLayoutDocumentPane); - newChildGroup.Children.Add(targetModel); - } - - } - - foreach (var cntToTransfer in floatingWindow.RootPanel.Descendents().OfType().ToArray()) - newLayoutDocumentPane.Children.Add(cntToTransfer); - - } - break; - #endregion - case DropTargetType.DocumentPaneDockRight: - #region DropTargetType.DocumentPaneDockRight - { - var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; - var newLayoutDocumentPane = new LayoutDocumentPane(); - - if (parentModel == null) - { - var parentContainer = targetModel.Parent as ILayoutContainer; - var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; - parentContainer.ReplaceChild(targetModel, newParentModel); - newParentModel.Children.Add(targetModel as LayoutDocumentPane); - newParentModel.Children.Add(newLayoutDocumentPane); - } - else - { - var manager = parentModel.Root.Manager; - if (!manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Horizontal) - { - parentModel.Orientation = System.Windows.Controls.Orientation.Horizontal; - int targetPaneIndex = parentModel.IndexOfChild(targetModel); - parentModel.Children.Insert(targetPaneIndex + 1, newLayoutDocumentPane); - } - else - { - LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); - newChildGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; - parentModel.ReplaceChild(targetModel, newChildGroup); - newChildGroup.Children.Add(targetModel); - newChildGroup.Children.Add(newLayoutDocumentPane); - } - } - - foreach (var cntToTransfer in floatingWindow.RootPanel.Descendents().OfType().ToArray()) - newLayoutDocumentPane.Children.Add(cntToTransfer); - - } - break; - #endregion - case DropTargetType.DocumentPaneDockInside: - #region DropTargetType.DocumentPaneDockInside - { - var paneModel = targetModel as LayoutDocumentPane; - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - - int i = _tabIndex == -1 ? 0 : _tabIndex; - LayoutAnchorable anchorableToActivate = null; - foreach (var anchorableToImport in layoutAnchorablePaneGroup.Descendents().OfType().ToArray()) - { - paneModel.Children.Insert(i, anchorableToImport); - i++; - anchorableToActivate = anchorableToImport; - } - - anchorableToActivate.IsActive = true; - } - break; - #endregion + var parentContainer = targetModel.Parent as ILayoutContainer; + var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; + parentContainer.ReplaceChild( targetModel, newParentModel ); + newParentModel.Children.Add( newLayoutDocumentPane ); + newParentModel.Children.Add( targetModel as LayoutDocumentPane ); } + else + { + var manager = parentModel.Root.Manager; + if( !manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + parentModel.Orientation = System.Windows.Controls.Orientation.Horizontal; + int targetPaneIndex = parentModel.IndexOfChild( targetModel ); + parentModel.Children.Insert( targetPaneIndex, newLayoutDocumentPane ); + } + else + { + LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); + newChildGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; + parentModel.ReplaceChild( targetModel, newChildGroup ); + newChildGroup.Children.Add( newLayoutDocumentPane ); + newChildGroup.Children.Add( targetModel ); + } + + } + + foreach( var cntToTransfer in floatingWindow.RootPanel.Descendents().OfType().ToArray() ) + newLayoutDocumentPane.Children.Add( cntToTransfer ); - base.Drop(floatingWindow); - } + } + break; + #endregion + case DropTargetType.DocumentPaneDockRight: + #region DropTargetType.DocumentPaneDockRight + { + var parentModel = targetModel.Parent as LayoutDocumentPaneGroup; + var newLayoutDocumentPane = new LayoutDocumentPane(); - public override System.Windows.Media.Geometry GetPreviewPath(OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel) - { - switch (Type) + if( parentModel == null ) { - case DropTargetType.DocumentPaneDockInside: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - - if (_tabIndex == -1) - { - return new RectangleGeometry(targetScreenRect); - } - else - { - var translatedDetectionRect = new Rect(DetectionRects[0].TopLeft, DetectionRects[0].BottomRight); - translatedDetectionRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - - var pathFigure = new PathFigure(); - pathFigure.StartPoint = targetScreenRect.BottomRight; - pathFigure.Segments.Add(new LineSegment() { Point = new Point(targetScreenRect.Right, translatedDetectionRect.Bottom) }); - pathFigure.Segments.Add(new LineSegment() { Point = translatedDetectionRect.BottomRight }); - pathFigure.Segments.Add(new LineSegment() { Point = translatedDetectionRect.TopRight }); - pathFigure.Segments.Add(new LineSegment() { Point = translatedDetectionRect.TopLeft }); - pathFigure.Segments.Add(new LineSegment() { Point = translatedDetectionRect.BottomLeft }); - pathFigure.Segments.Add(new LineSegment() { Point = new Point(targetScreenRect.Left, translatedDetectionRect.Bottom) }); - pathFigure.Segments.Add(new LineSegment() { Point = targetScreenRect.BottomLeft }); - pathFigure.IsClosed = true; - pathFigure.IsFilled = true; - pathFigure.Freeze(); - return new PathGeometry(new PathFigure[] { pathFigure }); - } - } - case DropTargetType.DocumentPaneDockBottom: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - targetScreenRect.Offset(0.0, targetScreenRect.Height / 2.0); - targetScreenRect.Height /= 2.0; - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.DocumentPaneDockTop: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - targetScreenRect.Height /= 2.0; - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.DocumentPaneDockLeft: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - targetScreenRect.Width /= 2.0; - return new RectangleGeometry(targetScreenRect); - } - case DropTargetType.DocumentPaneDockRight: - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - targetScreenRect.Offset(targetScreenRect.Width / 2.0, 0.0); - targetScreenRect.Width /= 2.0; - return new RectangleGeometry(targetScreenRect); - } + var parentContainer = targetModel.Parent as ILayoutContainer; + var newParentModel = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; + parentContainer.ReplaceChild( targetModel, newParentModel ); + newParentModel.Children.Add( targetModel as LayoutDocumentPane ); + newParentModel.Children.Add( newLayoutDocumentPane ); + } + else + { + var manager = parentModel.Root.Manager; + if( !manager.AllowMixedOrientation || parentModel.Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + parentModel.Orientation = System.Windows.Controls.Orientation.Horizontal; + int targetPaneIndex = parentModel.IndexOfChild( targetModel ); + parentModel.Children.Insert( targetPaneIndex + 1, newLayoutDocumentPane ); + } + else + { + LayoutDocumentPaneGroup newChildGroup = new LayoutDocumentPaneGroup(); + newChildGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; + parentModel.ReplaceChild( targetModel, newChildGroup ); + newChildGroup.Children.Add( targetModel ); + newChildGroup.Children.Add( newLayoutDocumentPane ); + } + } + + foreach( var cntToTransfer in floatingWindow.RootPanel.Descendents().OfType().ToArray() ) + newLayoutDocumentPane.Children.Add( cntToTransfer ); + + } + break; + #endregion + case DropTargetType.DocumentPaneDockInside: + #region DropTargetType.DocumentPaneDockInside + { + var paneModel = targetModel as LayoutDocumentPane; + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + + bool checkPreviousContainer = true; + int i = 0; + if( _tabIndex != -1 ) + { + i = _tabIndex; + checkPreviousContainer = false; + } + LayoutAnchorable anchorableToActivate = null; + + foreach( var anchorableToImport in layoutAnchorablePaneGroup.Descendents().OfType().ToArray() ) + { + if( checkPreviousContainer ) + { + var previousContainer = ( ( ILayoutPreviousContainer )anchorableToImport ).PreviousContainer; + if( object.ReferenceEquals( previousContainer, targetModel ) && ( anchorableToImport.PreviousContainerIndex != -1 ) ) + { + i = anchorableToImport.PreviousContainerIndex; + } + checkPreviousContainer = false; + } + + anchorableToImport.SetCanCloseInternal( true ); + + paneModel.Children.Insert( i, anchorableToImport ); + i++; + anchorableToActivate = anchorableToImport; } - return null; - } + anchorableToActivate.IsActive = true; + } + break; + #endregion + } + base.Drop( floatingWindow ); } + + public override System.Windows.Media.Geometry GetPreviewPath( OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel ) + { + switch( Type ) + { + case DropTargetType.DocumentPaneDockInside: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + + if( _tabIndex == -1 ) + { + return new RectangleGeometry( targetScreenRect ); + } + else + { + var translatedDetectionRect = new Rect( DetectionRects[ 0 ].TopLeft, DetectionRects[ 0 ].BottomRight ); + translatedDetectionRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + + var pathFigure = new PathFigure(); + pathFigure.StartPoint = targetScreenRect.BottomRight; + pathFigure.Segments.Add( new LineSegment() { Point = new Point( targetScreenRect.Right, translatedDetectionRect.Bottom ) } ); + pathFigure.Segments.Add( new LineSegment() { Point = translatedDetectionRect.BottomRight } ); + pathFigure.Segments.Add( new LineSegment() { Point = translatedDetectionRect.TopRight } ); + pathFigure.Segments.Add( new LineSegment() { Point = translatedDetectionRect.TopLeft } ); + pathFigure.Segments.Add( new LineSegment() { Point = translatedDetectionRect.BottomLeft } ); + pathFigure.Segments.Add( new LineSegment() { Point = new Point( targetScreenRect.Left, translatedDetectionRect.Bottom ) } ); + pathFigure.Segments.Add( new LineSegment() { Point = targetScreenRect.BottomLeft } ); + pathFigure.IsClosed = true; + pathFigure.IsFilled = true; + pathFigure.Freeze(); + return new PathGeometry( new PathFigure[] { pathFigure } ); + } + } + case DropTargetType.DocumentPaneDockBottom: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + targetScreenRect.Offset( 0.0, targetScreenRect.Height / 2.0 ); + targetScreenRect.Height /= 2.0; + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.DocumentPaneDockTop: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + targetScreenRect.Height /= 2.0; + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.DocumentPaneDockLeft: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + targetScreenRect.Width /= 2.0; + return new RectangleGeometry( targetScreenRect ); + } + case DropTargetType.DocumentPaneDockRight: + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + targetScreenRect.Offset( targetScreenRect.Width / 2.0, 0.0 ); + targetScreenRect.Width /= 2.0; + return new RectangleGeometry( targetScreenRect ); + } + } + + return null; + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneGroupDropTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneGroupDropTarget.cs index 91eb732e..85812499 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneGroupDropTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneGroupDropTarget.cs @@ -14,92 +14,101 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; -using System.Diagnostics; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - internal class DocumentPaneGroupDropTarget : DropTarget + internal class DocumentPaneGroupDropTarget : DropTarget + { + #region Constructors + + internal DocumentPaneGroupDropTarget( LayoutDocumentPaneGroupControl paneControl, Rect detectionRect, DropTargetType type ) + : base( paneControl, detectionRect, type ) { - internal DocumentPaneGroupDropTarget(LayoutDocumentPaneGroupControl paneControl, Rect detectionRect, DropTargetType type) - : base(paneControl, detectionRect, type) - { - _targetPane = paneControl; - } + _targetPane = paneControl; + } - LayoutDocumentPaneGroupControl _targetPane; + #endregion - protected override void Drop(LayoutDocumentFloatingWindow floatingWindow) - { - ILayoutPane targetModel = _targetPane.Model as ILayoutPane; + #region Members - switch (Type) - { - case DropTargetType.DocumentPaneGroupDockInside: - #region DropTargetType.DocumentPaneGroupDockInside - { - var paneGroupModel = targetModel as LayoutDocumentPaneGroup; - var paneModel = paneGroupModel.Children[0] as LayoutDocumentPane; - var sourceModel = floatingWindow.RootDocument; - - paneModel.Children.Insert(0, sourceModel); - } - break; - #endregion - } - base.Drop(floatingWindow); - } + private LayoutDocumentPaneGroupControl _targetPane; - protected override void Drop(LayoutAnchorableFloatingWindow floatingWindow) - { - ILayoutPane targetModel = _targetPane.Model as ILayoutPane; + #endregion - switch (Type) - { - case DropTargetType.DocumentPaneGroupDockInside: - #region DropTargetType.DocumentPaneGroupDockInside - { - var paneGroupModel = targetModel as LayoutDocumentPaneGroup; - var paneModel = paneGroupModel.Children[0] as LayoutDocumentPane; - var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; - - int i = 0; - foreach (var anchorableToImport in layoutAnchorablePaneGroup.Descendents().OfType().ToArray()) - { - paneModel.Children.Insert(i, anchorableToImport); - i++; - } - } - break; - #endregion - } + #region Overrides - base.Drop(floatingWindow); - } + protected override void Drop( LayoutDocumentFloatingWindow floatingWindow ) + { + ILayoutPane targetModel = _targetPane.Model as ILayoutPane; + + switch( Type ) + { + case DropTargetType.DocumentPaneGroupDockInside: + #region DropTargetType.DocumentPaneGroupDockInside + { + var paneGroupModel = targetModel as LayoutDocumentPaneGroup; + var paneModel = paneGroupModel.Children[ 0 ] as LayoutDocumentPane; + var sourceModel = floatingWindow.RootDocument; + + paneModel.Children.Insert( 0, sourceModel ); + } + break; + #endregion + } + base.Drop( floatingWindow ); + } - public override System.Windows.Media.Geometry GetPreviewPath(OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel) - { - switch (Type) + protected override void Drop( LayoutAnchorableFloatingWindow floatingWindow ) + { + ILayoutPane targetModel = _targetPane.Model as ILayoutPane; + + switch( Type ) + { + case DropTargetType.DocumentPaneGroupDockInside: + #region DropTargetType.DocumentPaneGroupDockInside + { + var paneGroupModel = targetModel as LayoutDocumentPaneGroup; + var paneModel = paneGroupModel.Children[ 0 ] as LayoutDocumentPane; + var layoutAnchorablePaneGroup = floatingWindow.RootPanel as LayoutAnchorablePaneGroup; + + int i = 0; + foreach( var anchorableToImport in layoutAnchorablePaneGroup.Descendents().OfType().ToArray() ) { - case DropTargetType.DocumentPaneGroupDockInside: - #region DropTargetType.DocumentPaneGroupDockInside - { - var targetScreenRect = TargetElement.GetScreenArea(); - targetScreenRect.Offset(-overlayWindow.Left, -overlayWindow.Top); - - return new RectangleGeometry(targetScreenRect); - } - #endregion + anchorableToImport.SetCanCloseInternal( true ); + + paneModel.Children.Insert( i, anchorableToImport ); + i++; } + } + break; + #endregion + } - return null; - } + base.Drop( floatingWindow ); + } + public override System.Windows.Media.Geometry GetPreviewPath( OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindowModel ) + { + switch( Type ) + { + case DropTargetType.DocumentPaneGroupDockInside: + #region DropTargetType.DocumentPaneGroupDockInside + { + var targetScreenRect = TargetElement.GetScreenArea(); + targetScreenRect.Offset( -overlayWindow.Left, -overlayWindow.Top ); + + return new RectangleGeometry( targetScreenRect ); + } + #endregion + } + + return null; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneTabPanel.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneTabPanel.cs index 76e032d2..1bacd43e 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneTabPanel.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DocumentPaneTabPanel.cs @@ -15,94 +15,97 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class DocumentPaneTabPanel : Panel + public class DocumentPaneTabPanel : Panel + { + #region Constructors + + public DocumentPaneTabPanel() { - public DocumentPaneTabPanel() - { - FlowDirection = System.Windows.FlowDirection.LeftToRight; - } + this.FlowDirection = System.Windows.FlowDirection.LeftToRight; + } - protected override Size MeasureOverride(Size availableSize) - { - var visibleChildren = Children.Cast().Where(ch => ch.Visibility != System.Windows.Visibility.Collapsed); + #endregion - Size desideredSize = new Size(); - foreach (FrameworkElement child in Children) - { - child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); - desideredSize.Width += child.DesiredSize.Width; + #region Overrides - desideredSize.Height = Math.Max(desideredSize.Height, child.DesiredSize.Height); - } + protected override Size MeasureOverride( Size availableSize ) + { + var visibleChildren = Children.Cast().Where( ch => ch.Visibility != System.Windows.Visibility.Collapsed ); - return new Size(Math.Min(desideredSize.Width, availableSize.Width), desideredSize.Height); - } + Size desideredSize = new Size(); + foreach( FrameworkElement child in Children ) + { + child.Measure( new Size( double.PositiveInfinity, double.PositiveInfinity ) ); + desideredSize.Width += child.DesiredSize.Width; + + desideredSize.Height = Math.Max( desideredSize.Height, child.DesiredSize.Height ); + } + + return new Size( Math.Min( desideredSize.Width, availableSize.Width ), desideredSize.Height ); + } - protected override Size ArrangeOverride(Size finalSize) + protected override Size ArrangeOverride( Size finalSize ) + { + var visibleChildren = Children.Cast().Where( ch => ch.Visibility != System.Windows.Visibility.Collapsed ); + var offset = 0.0; + var skipAllOthers = false; + foreach( TabItem doc in visibleChildren ) + { + var layoutContent = doc.Content as LayoutContent; + if( skipAllOthers || offset + doc.DesiredSize.Width > finalSize.Width ) { - restart: - var visibleChildren = Children.Cast().Where(ch => ch.Visibility != System.Windows.Visibility.Collapsed); - double offset = 0.0; - bool skipAllOthers = false; - foreach (TabItem doc in visibleChildren) + if( layoutContent.IsSelected && !doc.IsVisible ) + { + var parentContainer = layoutContent.Parent as ILayoutContainer; + var parentSelector = layoutContent.Parent as ILayoutContentSelector; + var parentPane = layoutContent.Parent as ILayoutPane; + int contentIndex = parentSelector.IndexOf( layoutContent ); + if( contentIndex > 0 && + parentContainer.ChildrenCount > 1 ) { - var layoutContent = doc.Content as LayoutContent; - if (skipAllOthers || offset + doc.DesiredSize.Width > finalSize.Width) - { - if (layoutContent.IsSelected) - { - var parentContainer = layoutContent.Parent as ILayoutContainer; - var parentSelector = layoutContent.Parent as ILayoutContentSelector; - var parentPane = layoutContent.Parent as ILayoutPane; - int contentIndex = parentSelector.IndexOf(layoutContent); - if (contentIndex > 0 && - parentContainer.ChildrenCount > 1) - { - parentPane.MoveChild(contentIndex, 0); - parentSelector.SelectedContentIndex = 0; - goto restart; - } - } - doc.Visibility = System.Windows.Visibility.Hidden; - skipAllOthers = true; - } - else - { - doc.Visibility = System.Windows.Visibility.Visible; - doc.Arrange(new Rect(offset, 0.0, doc.DesiredSize.Width, finalSize.Height)); - offset += doc.ActualWidth + doc.Margin.Left + doc.Margin.Right; - } + parentPane.MoveChild( contentIndex, 0 ); + parentSelector.SelectedContentIndex = 0; + return ArrangeOverride( finalSize ); } - - return finalSize; - + } + doc.Visibility = System.Windows.Visibility.Hidden; + skipAllOthers = true; + } + else + { + doc.Visibility = System.Windows.Visibility.Visible; + doc.Arrange( new Rect( offset, 0.0, doc.DesiredSize.Width, finalSize.Height ) ); + offset += doc.ActualWidth + doc.Margin.Left + doc.Margin.Right; } + } + return finalSize; + } - protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e) - { - //if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && - // LayoutDocumentTabItem.IsDraggingItem()) - //{ - // var contentModel = LayoutDocumentTabItem.GetDraggingItem().Model; - // var manager = contentModel.Root.Manager; - // LayoutDocumentTabItem.ResetDraggingItem(); - // System.Diagnostics.Trace.WriteLine("OnMouseLeave()"); + protected override void OnMouseLeave( System.Windows.Input.MouseEventArgs e ) + { + //if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && + // LayoutDocumentTabItem.IsDraggingItem()) + //{ + // var contentModel = LayoutDocumentTabItem.GetDraggingItem().Model; + // var manager = contentModel.Root.Manager; + // LayoutDocumentTabItem.ResetDraggingItem(); + // System.Diagnostics.Trace.WriteLine("OnMouseLeave()"); - // manager.StartDraggingFloatingWindowForContent(contentModel); - //} + // manager.StartDraggingFloatingWindowForContent(contentModel); + //} - base.OnMouseLeave(e); - } + base.OnMouseLeave( e ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DragService.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DragService.cs index 78b22a19..cec01131 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DragService.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DragService.cs @@ -14,88 +14,81 @@ ***********************************************************************************/ -using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Windows.Input; using System.Windows; -using System.Diagnostics; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - class DragService - { - DockingManager _manager; - LayoutFloatingWindowControl _floatingWindow; - - public DragService(LayoutFloatingWindowControl floatingWindow) - { - _floatingWindow = floatingWindow; - _manager = floatingWindow.Model.Root.Manager; - - - GetOverlayWindowHosts(); - } - - List _overlayWindowHosts = new List(); - void GetOverlayWindowHosts() - { - _overlayWindowHosts.AddRange(_manager.GetFloatingWindowsByZOrder().OfType().Where(fw => fw != _floatingWindow && fw.IsVisible)); - _overlayWindowHosts.Add(_manager); - } - - IOverlayWindowHost _currentHost; - IOverlayWindow _currentWindow; - List _currentWindowAreas = new List(); - IDropTarget _currentDropTarget; - - public void UpdateMouseLocation(Point dragPosition) - { - if (!_floatingWindow.Model.Root.ActiveContent.CanDock) return; - - var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow; - - var newHost = _overlayWindowHosts.FirstOrDefault(oh => oh.HitTest(dragPosition)); - - if (_currentHost != null || _currentHost != newHost) - { - //is mouse still inside current overlay window host? - if ((_currentHost != null && !_currentHost.HitTest(dragPosition)) || - _currentHost != newHost) - { - //esit drop target - if (_currentDropTarget != null) - _currentWindow.DragLeave(_currentDropTarget); - _currentDropTarget = null; - - //exit area - _currentWindowAreas.ForEach(a => - _currentWindow.DragLeave(a)); - _currentWindowAreas.Clear(); - - //hide current overlay window - if (_currentWindow != null) - _currentWindow.DragLeave(_floatingWindow); - if (_currentHost != null) - _currentHost.HideOverlayWindow(); - _currentHost = null; - } - - if (_currentHost != newHost) - { - _currentHost = newHost; - _currentWindow = _currentHost.ShowOverlayWindow(_floatingWindow); - _currentWindow.DragEnter(_floatingWindow); - } - } - - if (_currentHost == null) + internal class DragService + { + #region Members + + private DockingManager _manager; + private LayoutFloatingWindowControl _floatingWindow; + private List _overlayWindowHosts = new List(); + private IOverlayWindowHost _currentHost; + private IOverlayWindow _currentWindow; + private List _currentWindowAreas = new List(); + private IDropTarget _currentDropTarget; + + #endregion + + #region Public Methods + + public DragService(LayoutFloatingWindowControl floatingWindow) + { + _floatingWindow = floatingWindow; + _manager = floatingWindow.Model.Root.Manager; + + + GetOverlayWindowHosts(); + } + + public void UpdateMouseLocation(Point dragPosition) + { + if (!_floatingWindow.Model.Root.ActiveContent.CanDock) return; + + var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow; + + var newHost = _overlayWindowHosts.FirstOrDefault(oh => oh.HitTest(dragPosition)); + + if (_currentHost != null || _currentHost != newHost) + { + //is mouse still inside current overlay window host? + if ((_currentHost != null && !_currentHost.HitTest(dragPosition)) || + _currentHost != newHost) + { + //esit drop target + if (_currentDropTarget != null) + _currentWindow.DragLeave(_currentDropTarget); + _currentDropTarget = null; + + //exit area + _currentWindowAreas.ForEach(a => + _currentWindow.DragLeave(a)); + _currentWindowAreas.Clear(); + + //hide current overlay window + if (_currentWindow != null) + _currentWindow.DragLeave(_floatingWindow); + if (_currentHost != null) + _currentHost.HideOverlayWindow(); + _currentHost = null; + } + + if (_currentHost != newHost) + { + _currentHost = newHost; + _currentWindow = _currentHost.ShowOverlayWindow(_floatingWindow); + _currentWindow.DragEnter(_floatingWindow); + } + } + else if (_currentHost == null) { - Debug.WriteLine("Zero Dock Areas"); - - if(_manager.Parent is DockingManager) + // there are no dock areas + if (_manager.Parent is DockingManager) { _manager = _manager.Parent as DockingManager; GetOverlayWindowHosts(); @@ -105,100 +98,116 @@ namespace Xceed.Wpf.AvalonDock.Controls return; } - if (_currentDropTarget != null && - !_currentDropTarget.HitTest(dragPosition)) - { - _currentWindow.DragLeave(_currentDropTarget); - _currentDropTarget = null; - } - - List areasToRemove = new List(); - _currentWindowAreas.ForEach(a => - { - //is mouse still inside this area? - if (!a.DetectionRect.Contains(dragPosition)) - { - _currentWindow.DragLeave(a); - areasToRemove.Add(a); - } - }); - - areasToRemove.ForEach(a => - _currentWindowAreas.Remove(a)); - - - var areasToAdd = - _currentHost.GetDropAreas(_floatingWindow).Where(cw => !_currentWindowAreas.Contains(cw) && cw.DetectionRect.Contains(dragPosition)).ToList(); - - _currentWindowAreas.AddRange(areasToAdd); - - areasToAdd.ForEach(a => - _currentWindow.DragEnter(a)); - - if (_currentDropTarget == null) - { - _currentWindowAreas.ForEach(wa => - { - if (_currentDropTarget != null) - return; - - _currentDropTarget = _currentWindow.GetTargets().FirstOrDefault(dt => dt.HitTest(dragPosition)); - if (_currentDropTarget != null) - { - _currentWindow.DragEnter(_currentDropTarget); - return; - } - }); - } - - } - - public void Drop(Point dropLocation, out bool dropHandled) - { - dropHandled = false; - - UpdateMouseLocation(dropLocation); - - var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow; - var root = floatingWindowModel.Root; - - if (_currentHost != null) - _currentHost.HideOverlayWindow(); - - if (_currentDropTarget != null) - { - _currentWindow.DragDrop(_currentDropTarget); - root.CollectGarbage(); - dropHandled = true; - } - - - _currentWindowAreas.ForEach(a => _currentWindow.DragLeave(a)); - - if (_currentDropTarget != null) - _currentWindow.DragLeave(_currentDropTarget); - if (_currentWindow != null) - _currentWindow.DragLeave(_floatingWindow); - _currentWindow = null; - - _currentHost = null; - } - - internal void Abort() - { - var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow; - - if(_currentWindow != null) - _currentWindowAreas.ForEach(a => _currentWindow.DragLeave(a)); - - if (_currentDropTarget != null) - _currentWindow.DragLeave(_currentDropTarget); - if (_currentWindow != null) - _currentWindow.DragLeave(_floatingWindow); - _currentWindow = null; - if (_currentHost != null) - _currentHost.HideOverlayWindow(); - _currentHost = null; - } - } + if (_currentDropTarget != null && + !_currentDropTarget.HitTest(dragPosition)) + { + _currentWindow.DragLeave(_currentDropTarget); + _currentDropTarget = null; + } + + List areasToRemove = new List(); + _currentWindowAreas.ForEach(a => + { + //is mouse still inside this area? + if (!a.DetectionRect.Contains(dragPosition)) + { + _currentWindow.DragLeave(a); + areasToRemove.Add(a); + } + }); + + areasToRemove.ForEach(a => + _currentWindowAreas.Remove(a)); + + + var areasToAdd = + _currentHost.GetDropAreas(_floatingWindow).Where(cw => !_currentWindowAreas.Contains(cw) && cw.DetectionRect.Contains(dragPosition)).ToList(); + + _currentWindowAreas.AddRange(areasToAdd); + + areasToAdd.ForEach(a => + _currentWindow.DragEnter(a)); + + if (_currentDropTarget == null) + { + _currentWindowAreas.ForEach(wa => + { + if (_currentDropTarget != null) + return; + + _currentDropTarget = _currentWindow.GetTargets().FirstOrDefault(dt => dt.HitTest(dragPosition)); + if (_currentDropTarget != null) + { + _currentWindow.DragEnter(_currentDropTarget); + return; + } + }); + } + + } + + public void Drop(Point dropLocation, out bool dropHandled) + { + dropHandled = false; + + UpdateMouseLocation(dropLocation); + + var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow; + var root = floatingWindowModel.Root; + + if (_currentHost != null) + _currentHost.HideOverlayWindow(); + + if (_currentDropTarget != null) + { + _currentWindow.DragDrop(_currentDropTarget); + root.CollectGarbage(); + dropHandled = true; + } + + + _currentWindowAreas.ForEach(a => _currentWindow.DragLeave(a)); + + if (_currentDropTarget != null) + _currentWindow.DragLeave(_currentDropTarget); + if (_currentWindow != null) + _currentWindow.DragLeave(_floatingWindow); + _currentWindow = null; + + _currentHost = null; + } + + #endregion + + #region Internal Methods + + internal void Abort() + { + var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow; + + if (_currentWindow != null) + _currentWindowAreas.ForEach(a => _currentWindow.DragLeave(a)); + + if (_currentDropTarget != null) + _currentWindow.DragLeave(_currentDropTarget); + if (_currentWindow != null) + _currentWindow.DragLeave(_floatingWindow); + _currentWindow = null; + if (_currentHost != null) + _currentHost.HideOverlayWindow(); + _currentHost = null; + } + + #endregion + + #region Private Methods + + private void GetOverlayWindowHosts() + { + _overlayWindowHosts.AddRange(_manager.GetFloatingWindowsByZOrder().OfType().Where(fw => fw != _floatingWindow && fw.IsVisible)); + _overlayWindowHosts.Add(_manager); + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropArea.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropArea.cs index f5f998c5..7cc2f647 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropArea.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropArea.cs @@ -14,64 +14,78 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - public enum DropAreaType + public enum DropAreaType + { + DockingManager, + DocumentPane, + DocumentPaneGroup, + AnchorablePane, + } + + + public interface IDropArea + { + Rect DetectionRect { - DockingManager, + get; + } + DropAreaType Type + { + get; + } + } - DocumentPane, + public class DropArea : IDropArea where T : FrameworkElement + { + #region Members - DocumentPaneGroup, + private Rect _detectionRect; + private DropAreaType _type; + private T _element; - AnchorablePane, + #endregion + #region Constructors + + internal DropArea( T areaElement, DropAreaType type ) + { + _element = areaElement; + _detectionRect = areaElement.GetScreenArea(); + _type = type; } + #endregion - public interface IDropArea + #region Properties + + public Rect DetectionRect { - Rect DetectionRect { get; } - DropAreaType Type { get; } - } + get + { + return _detectionRect; + } + } - public class DropArea : IDropArea where T : FrameworkElement + public DropAreaType Type { - internal DropArea(T areaElement, DropAreaType type) - { - _element = areaElement; - _detectionRect = areaElement.GetScreenArea(); - _type = type; - } - - Rect _detectionRect; - - public Rect DetectionRect - { - get { return _detectionRect; } - } - - DropAreaType _type; - - public DropAreaType Type - { - get { return _type; } - } - - T _element; - public T AreaElement - { - get - { - return _element; - } - } + get + { + return _type; + } + } + public T AreaElement + { + get + { + return _element; + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropDownButton.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropDownButton.cs index 4805d012..e4ae9a12 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropDownButton.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropDownButton.cs @@ -14,115 +14,136 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Controls.Primitives; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; -using System.Diagnostics; namespace Xceed.Wpf.AvalonDock.Controls { - public class DropDownButton : ToggleButton + public class DropDownButton : ToggleButton + { + #region Constructors + + public DropDownButton() { - public DropDownButton() - { - this.Unloaded += new RoutedEventHandler(DropDownButton_Unloaded); - } - - - #region DropDownContextMenu - - /// - /// DropDownContextMenu Dependency Property - /// - public static readonly DependencyProperty DropDownContextMenuProperty = - DependencyProperty.Register("DropDownContextMenu", typeof(ContextMenu), typeof(DropDownButton), - new FrameworkPropertyMetadata((ContextMenu)null, - new PropertyChangedCallback(OnDropDownContextMenuChanged))); - - /// - /// Gets or sets the DropDownContextMenu property. This dependency property - /// indicates drop down menu to show up when user click on an anchorable menu pin. - /// - public ContextMenu DropDownContextMenu - { - get { return (ContextMenu)GetValue(DropDownContextMenuProperty); } - set { SetValue(DropDownContextMenuProperty, value); } - } - - /// - /// Handles changes to the DropDownContextMenu property. - /// - private static void OnDropDownContextMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DropDownButton)d).OnDropDownContextMenuChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DropDownContextMenu property. - /// - protected virtual void OnDropDownContextMenuChanged(DependencyPropertyChangedEventArgs e) - { - var oldContextMenu = e.OldValue as ContextMenu; - if (oldContextMenu != null && IsChecked.GetValueOrDefault()) - oldContextMenu.Closed -= new RoutedEventHandler(OnContextMenuClosed); - } - - #endregion - - #region DropDownContextMenuDataContext - - /// - /// DropDownContextMenuDataContext Dependency Property - /// - public static readonly DependencyProperty DropDownContextMenuDataContextProperty = - DependencyProperty.Register("DropDownContextMenuDataContext", typeof(object), typeof(DropDownButton), - new FrameworkPropertyMetadata((object)null)); - - /// - /// Gets or sets the DropDownContextMenuDataContext property. This dependency property - /// indicates data context to set for drop down context menu. - /// - public object DropDownContextMenuDataContext - { - get { return (object)GetValue(DropDownContextMenuDataContextProperty); } - set { SetValue(DropDownContextMenuDataContextProperty, value); } - } - - #endregion - - protected override void OnClick() - { - if (DropDownContextMenu != null) - { - //IsChecked = true; - DropDownContextMenu.PlacementTarget = this; - DropDownContextMenu.Placement = PlacementMode.Bottom; - DropDownContextMenu.DataContext = DropDownContextMenuDataContext; - DropDownContextMenu.Closed += new RoutedEventHandler(OnContextMenuClosed); - DropDownContextMenu.IsOpen = true; - } - - base.OnClick(); - } - - void OnContextMenuClosed(object sender, RoutedEventArgs e) - { - //Debug.Assert(IsChecked.GetValueOrDefault()); - var ctxMenu = sender as ContextMenu; - ctxMenu.Closed -= new RoutedEventHandler(OnContextMenuClosed); - IsChecked = false; - } - - void DropDownButton_Unloaded(object sender, RoutedEventArgs e) - { - DropDownContextMenu = null; - } + this.Unloaded += new RoutedEventHandler( DropDownButton_Unloaded ); + } + + #endregion + + #region Properties + + #region DropDownContextMenu + /// + /// DropDownContextMenu Dependency Property + /// + public static readonly DependencyProperty DropDownContextMenuProperty = DependencyProperty.Register( "DropDownContextMenu", typeof( ContextMenu ), typeof( DropDownButton ), + new FrameworkPropertyMetadata( ( ContextMenu )null, new PropertyChangedCallback( OnDropDownContextMenuChanged ) ) ); + /// + /// Gets or sets the DropDownContextMenu property. This dependency property + /// indicates drop down menu to show up when user click on an anchorable menu pin. + /// + public ContextMenu DropDownContextMenu + { + get + { + return ( ContextMenu )GetValue( DropDownContextMenuProperty ); + } + set + { + SetValue( DropDownContextMenuProperty, value ); + } + } + + /// + /// Handles changes to the DropDownContextMenu property. + /// + private static void OnDropDownContextMenuChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DropDownButton )d ).OnDropDownContextMenuChanged( e ); } + + /// + /// Provides derived classes an opportunity to handle changes to the DropDownContextMenu property. + /// + protected virtual void OnDropDownContextMenuChanged( DependencyPropertyChangedEventArgs e ) + { + var oldContextMenu = e.OldValue as ContextMenu; + if( oldContextMenu != null && IsChecked.GetValueOrDefault() ) + oldContextMenu.Closed -= new RoutedEventHandler( OnContextMenuClosed ); + } + + #endregion + + #region DropDownContextMenuDataContext + + /// + /// DropDownContextMenuDataContext Dependency Property + /// + public static readonly DependencyProperty DropDownContextMenuDataContextProperty = DependencyProperty.Register( "DropDownContextMenuDataContext", typeof( object ), typeof( DropDownButton ), + new FrameworkPropertyMetadata( ( object )null ) ); + + /// + /// Gets or sets the DropDownContextMenuDataContext property. This dependency property + /// indicates data context to set for drop down context menu. + /// + public object DropDownContextMenuDataContext + { + get + { + return ( object )GetValue( DropDownContextMenuDataContextProperty ); + } + set + { + SetValue( DropDownContextMenuDataContextProperty, value ); + } + } + + #endregion + + #endregion + + #region Overrides + + protected override void OnClick() + { + if( DropDownContextMenu != null ) + { + //IsChecked = true; + DropDownContextMenu.PlacementTarget = this; + DropDownContextMenu.Placement = PlacementMode.Bottom; + DropDownContextMenu.DataContext = DropDownContextMenuDataContext; + DropDownContextMenu.Closed += new RoutedEventHandler( OnContextMenuClosed ); + DropDownContextMenu.IsOpen = true; + } + + base.OnClick(); + } + + #endregion + + #region Private Methods + + private void OnContextMenuClosed( object sender, RoutedEventArgs e ) + { + //Debug.Assert(IsChecked.GetValueOrDefault()); + var ctxMenu = sender as ContextMenu; + ctxMenu.Closed -= new RoutedEventHandler( OnContextMenuClosed ); + IsChecked = false; + } + + private void DropDownButton_Unloaded( object sender, RoutedEventArgs e ) + { + // When changing theme, Unloaded event is called, erasing the DropDownContextMenu. + // Prevent this on theme changes. + if( this.IsLoaded ) + { + DropDownContextMenu = null; + } + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropDownControlArea.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropDownControlArea.cs index 01aa6b29..ee848287 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropDownControlArea.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropDownControlArea.cs @@ -14,105 +14,116 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; -using System.Windows.Media; -using System.Windows.Input; -using System.Diagnostics; namespace Xceed.Wpf.AvalonDock.Controls { - public class DropDownControlArea : UserControl + public class DropDownControlArea : UserControl + { + #region Constructors + + //static DropDownControlArea() + //{ + // //IsHitTestVisibleProperty.OverrideMetadata(typeof(DropDownControlArea), new FrameworkPropertyMetadata(true)); + //} + + public DropDownControlArea() { - //static DropDownControlArea() - //{ - // //IsHitTestVisibleProperty.OverrideMetadata(typeof(DropDownControlArea), new FrameworkPropertyMetadata(true)); - //} + } - public DropDownControlArea() - { + #endregion - } + #region Properties - #region DropDownContextMenu + #region DropDownContextMenu - /// - /// DropDownContextMenu Dependency Property - /// - public static readonly DependencyProperty DropDownContextMenuProperty = - DependencyProperty.Register("DropDownContextMenu", typeof(ContextMenu), typeof(DropDownControlArea), - new FrameworkPropertyMetadata((ContextMenu)null)); + /// + /// DropDownContextMenu Dependency Property + /// + public static readonly DependencyProperty DropDownContextMenuProperty = DependencyProperty.Register( "DropDownContextMenu", typeof( ContextMenu ), typeof( DropDownControlArea ), + new FrameworkPropertyMetadata( ( ContextMenu )null ) ); - /// - /// Gets or sets the DropDownContextMenu property. This dependency property - /// indicates context menu to show when a right click is detected over the area occpied by the control. - /// - public ContextMenu DropDownContextMenu - { - get { return (ContextMenu)GetValue(DropDownContextMenuProperty); } - set { SetValue(DropDownContextMenuProperty, value); } - } + /// + /// Gets or sets the DropDownContextMenu property. This dependency property + /// indicates context menu to show when a right click is detected over the area occpied by the control. + /// + public ContextMenu DropDownContextMenu + { + get + { + return ( ContextMenu )GetValue( DropDownContextMenuProperty ); + } + set + { + SetValue( DropDownContextMenuProperty, value ); + } + } - #endregion + #endregion - #region DropDownContextMenuDataContext + #region DropDownContextMenuDataContext - /// - /// DropDownContextMenuDataContext Dependency Property - /// - public static readonly DependencyProperty DropDownContextMenuDataContextProperty = - DependencyProperty.Register("DropDownContextMenuDataContext", typeof(object), typeof(DropDownControlArea), - new FrameworkPropertyMetadata((object)null)); + /// + /// DropDownContextMenuDataContext Dependency Property + /// + public static readonly DependencyProperty DropDownContextMenuDataContextProperty = DependencyProperty.Register( "DropDownContextMenuDataContext", typeof( object ), typeof( DropDownControlArea ), + new FrameworkPropertyMetadata( ( object )null ) ); - /// - /// Gets or sets the DropDownContextMenuDataContext property. This dependency property - /// indicates data context to attach when context menu is shown. - /// - public object DropDownContextMenuDataContext - { - get { return (object)GetValue(DropDownContextMenuDataContextProperty); } - set { SetValue(DropDownContextMenuDataContextProperty, value); } - } + /// + /// Gets or sets the DropDownContextMenuDataContext property. This dependency property + /// indicates data context to attach when context menu is shown. + /// + public object DropDownContextMenuDataContext + { + get + { + return ( object )GetValue( DropDownContextMenuDataContextProperty ); + } + set + { + SetValue( DropDownContextMenuDataContextProperty, value ); + } + } - #endregion + #endregion - protected override void OnMouseRightButtonDown(System.Windows.Input.MouseButtonEventArgs e) - { - base.OnMouseRightButtonDown(e); + #endregion + #region Overrides - } + protected override void OnMouseRightButtonDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseRightButtonDown( e ); + } + + protected override void OnPreviewMouseRightButtonUp( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnPreviewMouseRightButtonUp( e ); - protected override void OnPreviewMouseRightButtonUp(System.Windows.Input.MouseButtonEventArgs e) + if( !e.Handled ) + { + if( DropDownContextMenu != null ) { - base.OnPreviewMouseRightButtonUp(e); - - if (!e.Handled) - { - if (DropDownContextMenu != null) - { - DropDownContextMenu.PlacementTarget = null; - DropDownContextMenu.Placement = PlacementMode.MousePoint; - DropDownContextMenu.DataContext = DropDownContextMenuDataContext; - DropDownContextMenu.IsOpen = true; - // e.Handled = true; - } - } + DropDownContextMenu.PlacementTarget = null; + DropDownContextMenu.Placement = PlacementMode.MousePoint; + DropDownContextMenu.DataContext = DropDownContextMenuDataContext; + DropDownContextMenu.IsOpen = true; + // e.Handled = true; } + } + } + //protected override System.Windows.Media.HitTestResult HitTestCore(System.Windows.Media.PointHitTestParameters hitTestParameters) + //{ + // var hitResult = base.HitTestCore(hitTestParameters); + // if (hitResult == null) + // return new PointHitTestResult(this, hitTestParameters.HitPoint); - //protected override System.Windows.Media.HitTestResult HitTestCore(System.Windows.Media.PointHitTestParameters hitTestParameters) - //{ - // var hitResult = base.HitTestCore(hitTestParameters); - // if (hitResult == null) - // return new PointHitTestResult(this, hitTestParameters.HitPoint); + // return hitResult; + //} - // return hitResult; - //} - } + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTarget.cs index d0f42b48..5177c483 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTarget.cs @@ -17,7 +17,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; using Xceed.Wpf.AvalonDock.Layout; @@ -25,91 +24,117 @@ using System.Windows.Threading; namespace Xceed.Wpf.AvalonDock.Controls { - internal abstract class DropTarget : DropTargetBase, IDropTarget where T : FrameworkElement - { - protected DropTarget(T targetElement, Rect detectionRect, DropTargetType type) - { - _targetElement = targetElement; - _detectionRect = new Rect[] { detectionRect }; - _type = type; - } + internal abstract class DropTarget : DropTargetBase, IDropTarget where T : FrameworkElement + { + #region Members - protected DropTarget(T targetElement, IEnumerable detectionRects, DropTargetType type) - { - _targetElement = targetElement; - _detectionRect = detectionRects.ToArray(); - _type = type; - } + private Rect[] _detectionRect; + private T _targetElement; + private DropTargetType _type; - Rect[] _detectionRect; + #endregion - public Rect[] DetectionRects - { - get { return _detectionRect; } - } + #region Constructors + protected DropTarget( T targetElement, Rect detectionRect, DropTargetType type ) + { + _targetElement = targetElement; + _detectionRect = new Rect[] { detectionRect }; + _type = type; + } - T _targetElement; - public T TargetElement - { - get { return _targetElement; } - } + protected DropTarget( T targetElement, IEnumerable detectionRects, DropTargetType type ) + { + _targetElement = targetElement; + _detectionRect = detectionRects.ToArray(); + _type = type; + } - DropTargetType _type; + #endregion - public DropTargetType Type - { - get { return _type; } - } + #region Properties - protected virtual void Drop(LayoutAnchorableFloatingWindow floatingWindow) - { } + public Rect[] DetectionRects + { + get + { + return _detectionRect; + } + } - protected virtual void Drop(LayoutDocumentFloatingWindow floatingWindow) - { } + public T TargetElement + { + get + { + return _targetElement; + } + } + public DropTargetType Type + { + get + { + return _type; + } + } - public void Drop(LayoutFloatingWindow floatingWindow) - { - var root = floatingWindow.Root; - var currentActiveContent = floatingWindow.Root.ActiveContent; - var fwAsAnchorable = floatingWindow as LayoutAnchorableFloatingWindow; + #endregion - if (fwAsAnchorable != null) - { - this.Drop(fwAsAnchorable); - } - else - { - var fwAsDocument = floatingWindow as LayoutDocumentFloatingWindow; - this.Drop(fwAsDocument); - } + #region Overrides - Dispatcher.BeginInvoke(new Action(() => - { - currentActiveContent.IsSelected = false; - currentActiveContent.IsActive = false; - currentActiveContent.IsActive = true; - }), DispatcherPriority.Background); - } + protected virtual void Drop( LayoutAnchorableFloatingWindow floatingWindow ) + { + } - public virtual bool HitTest(Point dragPoint) - { - return _detectionRect.Any(dr => dr.Contains(dragPoint)); - } + protected virtual void Drop( LayoutDocumentFloatingWindow floatingWindow ) + { + } - public abstract Geometry GetPreviewPath(OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindow); + #endregion + #region Public Methods + public void Drop( LayoutFloatingWindow floatingWindow ) + { + var root = floatingWindow.Root; + var currentActiveContent = floatingWindow.Root.ActiveContent; + var fwAsAnchorable = floatingWindow as LayoutAnchorableFloatingWindow; + + if( fwAsAnchorable != null ) + { + this.Drop( fwAsAnchorable ); + } + else + { + var fwAsDocument = floatingWindow as LayoutDocumentFloatingWindow; + this.Drop( fwAsDocument ); + } + + Dispatcher.BeginInvoke( new Action( () => + { + currentActiveContent.IsSelected = false; + currentActiveContent.IsActive = false; + currentActiveContent.IsActive = true; + } ), DispatcherPriority.Background ); + } - public void DragEnter() - { - SetIsDraggingOver(TargetElement, true); - } + public virtual bool HitTest( Point dragPoint ) + { + return _detectionRect.Any( dr => dr.Contains( dragPoint ) ); + } - public void DragLeave() - { - SetIsDraggingOver(TargetElement, false); - } + public abstract Geometry GetPreviewPath( OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindow ); + + public void DragEnter() + { + SetIsDraggingOver( TargetElement, true ); + } + + public void DragLeave() + { + SetIsDraggingOver( TargetElement, false ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTargetBase.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTargetBase.cs index fa793370..b19b3a77 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTargetBase.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTargetBase.cs @@ -14,43 +14,42 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - abstract class DropTargetBase : DependencyObject + abstract class DropTargetBase : DependencyObject + { + #region Properties + + #region IsDraggingOver + + /// + /// IsDraggingOver Attached Dependency Property + /// + public static readonly DependencyProperty IsDraggingOverProperty = DependencyProperty.RegisterAttached( "IsDraggingOver", typeof( bool ), typeof( DropTargetBase ), + new FrameworkPropertyMetadata( ( bool )false ) ); + + /// + /// Gets the IsDraggingOver property. This dependency property + /// indicates if user is dragging a window over the target element. + /// + public static bool GetIsDraggingOver( DependencyObject d ) { - #region IsDraggingOver - - /// - /// IsDraggingOver Attached Dependency Property - /// - public static readonly DependencyProperty IsDraggingOverProperty = - DependencyProperty.RegisterAttached("IsDraggingOver", typeof(bool), typeof(DropTargetBase), - new FrameworkPropertyMetadata((bool)false)); - - /// - /// Gets the IsDraggingOver property. This dependency property - /// indicates if user is dragging a window over the target element. - /// - public static bool GetIsDraggingOver(DependencyObject d) - { - return (bool)d.GetValue(IsDraggingOverProperty); - } - - /// - /// Sets the IsDraggingOver property. This dependency property - /// indicates if user is dragging away a window from the target element. - /// - public static void SetIsDraggingOver(DependencyObject d, bool value) - { - d.SetValue(IsDraggingOverProperty, value); - } - - #endregion + return ( bool )d.GetValue( IsDraggingOverProperty ); } + + /// + /// Sets the IsDraggingOver property. This dependency property + /// indicates if user is dragging away a window from the target element. + /// + public static void SetIsDraggingOver( DependencyObject d, bool value ) + { + d.SetValue( IsDraggingOverProperty, value ); + } + + #endregion + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTargetType.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTargetType.cs index 67839074..20226c1d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTargetType.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/DropTargetType.cs @@ -14,37 +14,32 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Controls { - public enum DropTargetType - { - DockingManagerDockLeft, - DockingManagerDockTop, - DockingManagerDockRight, - DockingManagerDockBottom, - - DocumentPaneDockLeft, - DocumentPaneDockTop, - DocumentPaneDockRight, - DocumentPaneDockBottom, - DocumentPaneDockInside, - - DocumentPaneGroupDockInside, - - AnchorablePaneDockLeft, - AnchorablePaneDockTop, - AnchorablePaneDockRight, - AnchorablePaneDockBottom, - AnchorablePaneDockInside, - - DocumentPaneDockAsAnchorableLeft, - DocumentPaneDockAsAnchorableTop, - DocumentPaneDockAsAnchorableRight, - DocumentPaneDockAsAnchorableBottom, - } + public enum DropTargetType + { + DockingManagerDockLeft, + DockingManagerDockTop, + DockingManagerDockRight, + DockingManagerDockBottom, + + DocumentPaneDockLeft, + DocumentPaneDockTop, + DocumentPaneDockRight, + DocumentPaneDockBottom, + DocumentPaneDockInside, + + DocumentPaneGroupDockInside, + + AnchorablePaneDockLeft, + AnchorablePaneDockTop, + AnchorablePaneDockRight, + AnchorablePaneDockBottom, + AnchorablePaneDockInside, + + DocumentPaneDockAsAnchorableLeft, + DocumentPaneDockAsAnchorableTop, + DocumentPaneDockAsAnchorableRight, + DocumentPaneDockAsAnchorableBottom, + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Extentions.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Extentions.cs index 4d4fc5c6..6d62cd8b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Extentions.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Extentions.cs @@ -14,107 +14,103 @@ ***********************************************************************************/ -using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; using System.Windows.Media.Media3D; -using System.Runtime.InteropServices; namespace Xceed.Wpf.AvalonDock.Controls { - public static class Extentions + public static class Extentions + { + public static IEnumerable FindVisualChildren( this DependencyObject depObj ) where T : DependencyObject { - public static IEnumerable FindVisualChildren(this DependencyObject depObj) where T : DependencyObject + if( depObj != null ) + { + for( int i = 0; i < VisualTreeHelper.GetChildrenCount( depObj ); i++ ) { - if (depObj != null) - { - for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) - { - DependencyObject child = VisualTreeHelper.GetChild(depObj, i); - if (child != null && child is T) - { - yield return (T)child; - } - - foreach (T childOfChild in FindVisualChildren(child)) - { - yield return childOfChild; - } - } - } + DependencyObject child = VisualTreeHelper.GetChild( depObj, i ); + if( child != null && child is T ) + { + yield return ( T )child; + } + + foreach( T childOfChild in FindVisualChildren( child ) ) + { + yield return childOfChild; + } } + } + } - public static IEnumerable FindLogicalChildren(this DependencyObject depObj) where T : DependencyObject + public static IEnumerable FindLogicalChildren( this DependencyObject depObj ) where T : DependencyObject + { + if( depObj != null ) + { + foreach( DependencyObject child in LogicalTreeHelper.GetChildren( depObj ).OfType() ) { - if (depObj != null) - { - foreach (DependencyObject child in LogicalTreeHelper.GetChildren(depObj).OfType()) - { - if (child != null && child is T) - { - yield return (T)child; - } - - foreach (T childOfChild in FindLogicalChildren(child)) - { - yield return childOfChild; - } - } - } + if( child != null && child is T ) + { + yield return ( T )child; + } + + foreach( T childOfChild in FindLogicalChildren( child ) ) + { + yield return childOfChild; + } } + } + } - public static DependencyObject FindVisualTreeRoot(this DependencyObject initial) - { - DependencyObject current = initial; - DependencyObject result = initial; - - while (current != null) - { - result = current; - if (current is Visual || current is Visual3D) - { - current = VisualTreeHelper.GetParent(current); - } - else - { - // If we're in Logical Land then we must walk - // up the logical tree until we find a - // Visual/Visual3D to get us back to Visual Land. - current = LogicalTreeHelper.GetParent(current); - } - } - - return result; - } + public static DependencyObject FindVisualTreeRoot( this DependencyObject initial ) + { + DependencyObject current = initial; + DependencyObject result = initial; - public static T FindVisualAncestor(this DependencyObject dependencyObject) where T : class + while( current != null ) + { + result = current; + if( current is Visual || current is Visual3D ) { - DependencyObject target = dependencyObject; - do - { - target = VisualTreeHelper.GetParent(target); - } - while (target != null && !(target is T)); - return target as T; + current = VisualTreeHelper.GetParent( current ); } - - public static T FindLogicalAncestor(this DependencyObject dependencyObject) where T : class + else { - DependencyObject target = dependencyObject; - do - { - var current = target; - target = LogicalTreeHelper.GetParent(target); - if (target == null) - target = VisualTreeHelper.GetParent(current); - - } - while (target != null && !(target is T)); - return target as T; + // If we're in Logical Land then we must walk + // up the logical tree until we find a + // Visual/Visual3D to get us back to Visual Land. + current = LogicalTreeHelper.GetParent( current ); } + } + return result; + } + + public static T FindVisualAncestor( this DependencyObject dependencyObject ) where T : class + { + DependencyObject target = dependencyObject; + do + { + target = VisualTreeHelper.GetParent( target ); + } + while( target != null && !( target is T ) ); + return target as T; + } + + public static T FindLogicalAncestor( this DependencyObject dependencyObject ) where T : class + { + DependencyObject target = dependencyObject; + do + { + var current = target; + target = LogicalTreeHelper.GetParent( target ); + if( target == null ) + target = VisualTreeHelper.GetParent( current ); + + } + while( target != null && !( target is T ) ); + return target as T; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FocusElementManager.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FocusElementManager.cs index f76541b7..11d388bc 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FocusElementManager.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FocusElementManager.cs @@ -17,7 +17,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Input; using System.Windows.Interop; using System.Windows; @@ -28,245 +27,246 @@ using System.Windows.Threading; namespace Xceed.Wpf.AvalonDock.Controls { - internal static class FocusElementManager - { - #region Focus Management - static List _managers = new List(); - internal static void SetupFocusManagement(DockingManager manager) - { - if (_managers.Count == 0) - { - //InputManager.Current.EnterMenuMode += new EventHandler(InputManager_EnterMenuMode); - //InputManager.Current.LeaveMenuMode += new EventHandler(InputManager_LeaveMenuMode); - _windowHandler = new WindowHookHandler(); - _windowHandler.FocusChanged += new EventHandler(WindowFocusChanging); - //_windowHandler.Activate += new EventHandler(WindowActivating); - _windowHandler.Attach(); - - if (Application.Current != null) - Application.Current.Exit += new ExitEventHandler(Current_Exit); - } + internal static class FocusElementManager + { + #region Member - manager.PreviewGotKeyboardFocus += new KeyboardFocusChangedEventHandler(manager_PreviewGotKeyboardFocus); - _managers.Add(manager); - } - - internal static void FinalizeFocusManagement(DockingManager manager) - { - manager.PreviewGotKeyboardFocus -= new KeyboardFocusChangedEventHandler(manager_PreviewGotKeyboardFocus); - _managers.Remove(manager); + private static List _managers = new List(); + private static FullWeakDictionary _modelFocusedElement = new FullWeakDictionary(); + private static WeakDictionary _modelFocusedWindowHandle = new WeakDictionary(); + private static WeakReference _lastFocusedElement; + private static WindowHookHandler _windowHandler = null; + private static DispatcherOperation _setFocusAsyncOperation; + private static WeakReference _lastFocusedElementBeforeEnterMenuMode = null; - if (_managers.Count == 0) - { - //InputManager.Current.EnterMenuMode -= new EventHandler(InputManager_EnterMenuMode); - //InputManager.Current.LeaveMenuMode -= new EventHandler(InputManager_LeaveMenuMode); - if (_windowHandler != null) - { - _windowHandler.FocusChanged -= new EventHandler(WindowFocusChanging); - //_windowHandler.Activate -= new EventHandler(WindowActivating); - _windowHandler.Detach(); - _windowHandler = null; - } - } + #endregion - } + #region Internal Methods - private static void Current_Exit(object sender, ExitEventArgs e) - { - Application.Current.Exit -= new ExitEventHandler(Current_Exit); - if (_windowHandler != null) - { - _windowHandler.FocusChanged -= new EventHandler(WindowFocusChanging); - //_windowHandler.Activate -= new EventHandler(WindowActivating); - _windowHandler.Detach(); - _windowHandler = null; - } - } + internal static void SetupFocusManagement( DockingManager manager ) + { + if( _managers.Count == 0 ) + { + //InputManager.Current.EnterMenuMode += new EventHandler(InputManager_EnterMenuMode); + //InputManager.Current.LeaveMenuMode += new EventHandler(InputManager_LeaveMenuMode); + _windowHandler = new WindowHookHandler(); + _windowHandler.FocusChanged += new EventHandler( WindowFocusChanging ); + //_windowHandler.Activate += new EventHandler(WindowActivating); + _windowHandler.Attach(); + + if( Application.Current != null ) + Application.Current.Exit += new ExitEventHandler( Current_Exit ); + } + + manager.PreviewGotKeyboardFocus += new KeyboardFocusChangedEventHandler( manager_PreviewGotKeyboardFocus ); + _managers.Add( manager ); + } - static void manager_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) + internal static void FinalizeFocusManagement( DockingManager manager ) + { + manager.PreviewGotKeyboardFocus -= new KeyboardFocusChangedEventHandler( manager_PreviewGotKeyboardFocus ); + _managers.Remove( manager ); + + if( _managers.Count == 0 ) + { + //InputManager.Current.EnterMenuMode -= new EventHandler(InputManager_EnterMenuMode); + //InputManager.Current.LeaveMenuMode -= new EventHandler(InputManager_LeaveMenuMode); + if( _windowHandler != null ) { - var focusedElement = e.NewFocus as Visual; - if (focusedElement != null && - !(focusedElement is LayoutAnchorableTabItem || focusedElement is LayoutDocumentTabItem)) - { - var parentAnchorable = focusedElement.FindVisualAncestor(); - if (parentAnchorable != null) - { - _modelFocusedElement[parentAnchorable.Model] = e.NewFocus; - } - else - { - var parentDocument = focusedElement.FindVisualAncestor(); - if (parentDocument != null) - { - _modelFocusedElement[parentDocument.Model] = e.NewFocus; - } - } - } + _windowHandler.FocusChanged -= new EventHandler( WindowFocusChanging ); + //_windowHandler.Activate -= new EventHandler(WindowActivating); + _windowHandler.Detach(); + _windowHandler = null; } + } - static FullWeakDictionary _modelFocusedElement = new FullWeakDictionary(); - static WeakDictionary _modelFocusedWindowHandle = new WeakDictionary(); + } - /// - /// Get the input element that was focused before user left the layout element - /// - /// Element to look for - /// Input element - internal static IInputElement GetLastFocusedElement(ILayoutElement model) - { - IInputElement objectWithFocus; - if (_modelFocusedElement.GetValue(model, out objectWithFocus)) - return objectWithFocus; + /// + /// Get the input element that was focused before user left the layout element + /// + /// Element to look for + /// Input element + internal static IInputElement GetLastFocusedElement( ILayoutElement model ) + { + IInputElement objectWithFocus; + if( _modelFocusedElement.GetValue( model, out objectWithFocus ) ) + return objectWithFocus; - return null; - } + return null; + } - /// - /// Get the last window handle focused before user left the element passed as argument - /// - /// - /// - internal static IntPtr GetLastWindowHandle(ILayoutElement model) - { - IntPtr handleWithFocus; - if (_modelFocusedWindowHandle.GetValue(model, out handleWithFocus)) - return handleWithFocus; + /// + /// Get the last window handle focused before user left the element passed as argument + /// + /// + /// + internal static IntPtr GetLastWindowHandle( ILayoutElement model ) + { + IntPtr handleWithFocus; + if( _modelFocusedWindowHandle.GetValue( model, out handleWithFocus ) ) + return handleWithFocus; - return IntPtr.Zero; - } - static WeakReference _lastFocusedElement; + return IntPtr.Zero; + } - /// - /// Given a layout element tries to set the focus of the keyword where it was before user moved to another element - /// - /// - internal static void SetFocusOnLastElement(ILayoutElement model) - { - bool focused = false; - IInputElement objectToFocus; - if (_modelFocusedElement.GetValue(model, out objectToFocus)) - { - focused = objectToFocus == Keyboard.Focus(objectToFocus); - } + /// + /// Given a layout element tries to set the focus of the keyword where it was before user moved to another element + /// + /// + internal static void SetFocusOnLastElement( ILayoutElement model ) + { + bool focused = false; + IInputElement objectToFocus; + if( _modelFocusedElement.GetValue( model, out objectToFocus ) ) + { + focused = objectToFocus == Keyboard.Focus( objectToFocus ); + } - IntPtr handleToFocus; - if (_modelFocusedWindowHandle.GetValue(model, out handleToFocus)) - focused = IntPtr.Zero != Win32Helper.SetFocus(handleToFocus); + IntPtr handleToFocus; + if( _modelFocusedWindowHandle.GetValue( model, out handleToFocus ) ) + focused = IntPtr.Zero != Win32Helper.SetFocus( handleToFocus ); - Trace.WriteLine( string.Format( "SetFocusOnLastElement(focused={0}, model={1}, element={2})", focused, model, handleToFocus == IntPtr.Zero ? ( objectToFocus == null ? "" : objectToFocus.ToString() ) : handleToFocus.ToString() ) ); - if (focused) - { - _lastFocusedElement = new WeakReference(model); - } + if( focused ) + { + _lastFocusedElement = new WeakReference( model ); + } - } + } - static WindowHookHandler _windowHandler = null; + #endregion - static void WindowFocusChanging(object sender, FocusChangeEventArgs e) - { - foreach (var manager in _managers) - { - var hostContainingFocusedHandle = manager.FindLogicalChildren().FirstOrDefault(hw => Win32Helper.IsChild(hw.Handle, e.GotFocusWinHandle)); - - if (hostContainingFocusedHandle != null) - { - var parentAnchorable = hostContainingFocusedHandle.FindVisualAncestor(); - if (parentAnchorable != null) - { - _modelFocusedWindowHandle[parentAnchorable.Model] = e.GotFocusWinHandle; - if (parentAnchorable.Model != null) - parentAnchorable.Model.IsActive = true; - } - else - { - var parentDocument = hostContainingFocusedHandle.FindVisualAncestor(); - if (parentDocument != null) - { - _modelFocusedWindowHandle[parentDocument.Model] = e.GotFocusWinHandle; - if (parentDocument.Model != null) - parentDocument.Model.IsActive = true; - } - } - } + #region Private Methods + private static void Current_Exit( object sender, ExitEventArgs e ) + { + Application.Current.Exit -= new ExitEventHandler( Current_Exit ); + if( _windowHandler != null ) + { + _windowHandler.FocusChanged -= new EventHandler( WindowFocusChanging ); + //_windowHandler.Activate -= new EventHandler(WindowActivating); + _windowHandler.Detach(); + _windowHandler = null; + } + } - } + private static void manager_PreviewGotKeyboardFocus( object sender, KeyboardFocusChangedEventArgs e ) + { + var focusedElement = e.NewFocus as Visual; + if( focusedElement != null && + !( focusedElement is LayoutAnchorableTabItem || focusedElement is LayoutDocumentTabItem ) ) + //Avoid tracking focus for elements like this + { + var parentAnchorable = focusedElement.FindVisualAncestor(); + if( parentAnchorable != null ) + { + _modelFocusedElement[ parentAnchorable.Model ] = e.NewFocus; + } + else + { + var parentDocument = focusedElement.FindVisualAncestor(); + if( parentDocument != null ) + { + _modelFocusedElement[ parentDocument.Model ] = e.NewFocus; + } } + } + } - static DispatcherOperation _setFocusAsyncOperation; + private static void WindowFocusChanging( object sender, FocusChangeEventArgs e ) + { + foreach( var manager in _managers ) + { + var hostContainingFocusedHandle = manager.FindLogicalChildren().FirstOrDefault( hw => Win32Helper.IsChild( hw.Handle, e.GotFocusWinHandle ) ); - static void WindowActivating(object sender, WindowActivateEventArgs e) + if( hostContainingFocusedHandle != null ) { - Trace.WriteLine("WindowActivating"); - - if (Keyboard.FocusedElement == null && - _lastFocusedElement != null && - _lastFocusedElement.IsAlive) + var parentAnchorable = hostContainingFocusedHandle.FindVisualAncestor(); + if( parentAnchorable != null ) + { + _modelFocusedWindowHandle[ parentAnchorable.Model ] = e.GotFocusWinHandle; + if( parentAnchorable.Model != null ) + parentAnchorable.Model.IsActive = true; + } + else + { + var parentDocument = hostContainingFocusedHandle.FindVisualAncestor(); + if( parentDocument != null ) { - var elementToSetFocus = _lastFocusedElement.Target as ILayoutElement; - if (elementToSetFocus != null) - { - var manager = elementToSetFocus.Root.Manager; - if (manager == null) - return; - - IntPtr parentHwnd; - if (!manager.GetParentWindowHandle(out parentHwnd)) - return; - - if (e.HwndActivating != parentHwnd) - return; - - _setFocusAsyncOperation = Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => - { - try - { - SetFocusOnLastElement(elementToSetFocus); - } - finally - { - _setFocusAsyncOperation = null; - } - }), DispatcherPriority.Background); - } + _modelFocusedWindowHandle[ parentDocument.Model ] = e.GotFocusWinHandle; + if( parentDocument.Model != null ) + parentDocument.Model.IsActive = true; } + } } + } + } - - static WeakReference _lastFocusedElementBeforeEnterMenuMode = null; - static void InputManager_EnterMenuMode(object sender, EventArgs e) + private static void WindowActivating( object sender, WindowActivateEventArgs e ) + { + if( Keyboard.FocusedElement == null && + _lastFocusedElement != null && + _lastFocusedElement.IsAlive ) + { + var elementToSetFocus = _lastFocusedElement.Target as ILayoutElement; + if( elementToSetFocus != null ) { - if (Keyboard.FocusedElement == null) - return; + var manager = elementToSetFocus.Root.Manager; + if( manager == null ) + return; + + IntPtr parentHwnd; + if( !manager.GetParentWindowHandle( out parentHwnd ) ) + return; - var lastfocusDepObj = Keyboard.FocusedElement as DependencyObject; - if (lastfocusDepObj.FindLogicalAncestor() == null) + if( e.HwndActivating != parentHwnd ) + return; + + _setFocusAsyncOperation = Dispatcher.CurrentDispatcher.BeginInvoke( new Action( () => + { + try { - _lastFocusedElementBeforeEnterMenuMode = null; - return; + SetFocusOnLastElement( elementToSetFocus ); } - - _lastFocusedElementBeforeEnterMenuMode = new WeakReference(Keyboard.FocusedElement); - } - static void InputManager_LeaveMenuMode(object sender, EventArgs e) - { - if (_lastFocusedElementBeforeEnterMenuMode != null && - _lastFocusedElementBeforeEnterMenuMode.IsAlive) + finally { - var lastFocusedInputElement = _lastFocusedElementBeforeEnterMenuMode.GetValueOrDefault(); - if (lastFocusedInputElement != null) - { - if (lastFocusedInputElement != Keyboard.Focus(lastFocusedInputElement)) - Debug.WriteLine("Unable to activate the element"); - } + _setFocusAsyncOperation = null; } + } ), DispatcherPriority.Input ); } + } + } + + private static void InputManager_EnterMenuMode( object sender, EventArgs e ) + { + if( Keyboard.FocusedElement == null ) + return; - #endregion + var lastfocusDepObj = Keyboard.FocusedElement as DependencyObject; + if( lastfocusDepObj.FindLogicalAncestor() == null ) + { + _lastFocusedElementBeforeEnterMenuMode = null; + return; + } + _lastFocusedElementBeforeEnterMenuMode = new WeakReference( Keyboard.FocusedElement ); + } + private static void InputManager_LeaveMenuMode( object sender, EventArgs e ) + { + if( _lastFocusedElementBeforeEnterMenuMode != null && + _lastFocusedElementBeforeEnterMenuMode.IsAlive ) + { + var lastFocusedInputElement = _lastFocusedElementBeforeEnterMenuMode.GetValueOrDefault(); + if( lastFocusedInputElement != null ) + { + if( lastFocusedInputElement != Keyboard.Focus( lastFocusedInputElement ) ) + Debug.WriteLine( "Unable to activate the element" ); + } + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FullWeakDictionary.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FullWeakDictionary.cs index 4fbf4b60..c483acfa 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FullWeakDictionary.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FullWeakDictionary.cs @@ -16,91 +16,101 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Controls { - class FullWeakDictionary where K : class + internal class FullWeakDictionary where K : class + { + #region Members + + private List _keys = new List(); + private List _values = new List(); + + #endregion + + #region Constructors + + public FullWeakDictionary() { - public FullWeakDictionary() - {} + } - List _keys = new List(); - List _values = new List(); + #endregion - public V this[K key] - { - get - { - V valueToReturn; - if (!GetValue(key, out valueToReturn)) - throw new ArgumentException(); - return valueToReturn; - } - set - { - SetValue(key, value); - } - } + #region Public Methods - public bool ContainsKey(K key) - { - CollectGarbage(); - return -1 != _keys.FindIndex(k => k.GetValueOrDefault() == key); - } + public V this[ K key ] + { + get + { + V valueToReturn; + if( !GetValue( key, out valueToReturn ) ) + throw new ArgumentException(); + return valueToReturn; + } + set + { + SetValue( key, value ); + } + } - public void SetValue(K key, V value) - { - CollectGarbage(); - int vIndex = _keys.FindIndex(k => k.GetValueOrDefault() == key); - if (vIndex > -1) - _values[vIndex] = new WeakReference(value); - else - { - _values.Add(new WeakReference(value)); - _keys.Add(new WeakReference(key)); - } - } + public bool ContainsKey( K key ) + { + CollectGarbage(); + return -1 != _keys.FindIndex( k => k.GetValueOrDefault() == key ); + } - public bool GetValue(K key, out V value) - { - CollectGarbage(); - int vIndex = _keys.FindIndex(k => k.GetValueOrDefault() == key); - value = default(V); - if (vIndex == -1) - return false; - value = _values[vIndex].GetValueOrDefault(); - return true; - } + public void SetValue( K key, V value ) + { + CollectGarbage(); + int vIndex = _keys.FindIndex( k => k.GetValueOrDefault() == key ); + if( vIndex > -1 ) + _values[ vIndex ] = new WeakReference( value ); + else + { + _values.Add( new WeakReference( value ) ); + _keys.Add( new WeakReference( key ) ); + } + } + public bool GetValue( K key, out V value ) + { + CollectGarbage(); + int vIndex = _keys.FindIndex( k => k.GetValueOrDefault() == key ); + value = default( V ); + if( vIndex == -1 ) + return false; + value = _values[ vIndex ].GetValueOrDefault(); + return true; + } - void CollectGarbage() - { - int vIndex = 0; - - do - { - vIndex = _keys.FindIndex(vIndex, k => !k.IsAlive); - if (vIndex >= 0) - { - _keys.RemoveAt(vIndex); - _values.RemoveAt(vIndex); - } - } - while (vIndex >= 0); - - vIndex = 0; - do - { - vIndex = _values.FindIndex(vIndex, v => !v.IsAlive); - if (vIndex >= 0) - { - _values.RemoveAt(vIndex); - _keys.RemoveAt(vIndex); - } - } - while (vIndex >= 0); + void CollectGarbage() + { + int vIndex = 0; + + do + { + vIndex = _keys.FindIndex( vIndex, k => !k.IsAlive ); + if( vIndex >= 0 ) + { + _keys.RemoveAt( vIndex ); + _values.RemoveAt( vIndex ); } + } + while( vIndex >= 0 ); + + vIndex = 0; + do + { + vIndex = _values.FindIndex( vIndex, v => !v.IsAlive ); + if( vIndex >= 0 ) + { + _values.RemoveAt( vIndex ); + _keys.RemoveAt( vIndex ); + } + } + while( vIndex >= 0 ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IDropTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IDropTarget.cs index a437a10f..2610304b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IDropTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IDropTarget.cs @@ -14,28 +14,35 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - internal interface IDropTarget + internal interface IDropTarget + { + #region Properties + + DropTargetType Type { - Geometry GetPreviewPath(OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindow); + get; + } - bool HitTest(Point dragPoint); + #endregion - DropTargetType Type { get; } + #region Methods - void Drop(LayoutFloatingWindow floatingWindow); + Geometry GetPreviewPath( OverlayWindow overlayWindow, LayoutFloatingWindow floatingWindow ); - void DragEnter(); + bool HitTest( Point dragPoint ); - void DragLeave(); - } + void Drop( LayoutFloatingWindow floatingWindow ); + + void DragEnter(); + + void DragLeave(); + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindow.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindow.cs index 1eba29e8..e623f12c 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindow.cs @@ -14,25 +14,22 @@ ***********************************************************************************/ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Controls { - internal interface IOverlayWindow - { - IEnumerable GetTargets(); + internal interface IOverlayWindow + { + IEnumerable GetTargets(); - void DragEnter(LayoutFloatingWindowControl floatingWindow); - void DragLeave(LayoutFloatingWindowControl floatingWindow); + void DragEnter( LayoutFloatingWindowControl floatingWindow ); + void DragLeave( LayoutFloatingWindowControl floatingWindow ); - void DragEnter(IDropArea area); - void DragLeave(IDropArea area); + void DragEnter( IDropArea area ); + void DragLeave( IDropArea area ); - void DragEnter(IDropTarget target); - void DragLeave(IDropTarget target); - void DragDrop(IDropTarget target); - } + void DragEnter( IDropTarget target ); + void DragLeave( IDropTarget target ); + void DragDrop( IDropTarget target ); + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowArea.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowArea.cs index fcafbf1b..22331abb 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowArea.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowArea.cs @@ -14,16 +14,15 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - internal interface IOverlayWindowArea + internal interface IOverlayWindowArea + { + Rect ScreenDetectionArea { - Rect ScreenDetectionArea { get; } + get; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowDropTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowDropTarget.cs index aca2dba6..450519c6 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowDropTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowDropTarget.cs @@ -14,18 +14,20 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - interface IOverlayWindowDropTarget + interface IOverlayWindowDropTarget + { + Rect ScreenDetectionArea { - Rect ScreenDetectionArea { get; } + get; + } - OverlayWindowDropTargetType Type { get; } + OverlayWindowDropTargetType Type + { + get; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowHost.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowHost.cs index f32ecffa..9e58e7a5 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowHost.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/IOverlayWindowHost.cs @@ -14,24 +14,32 @@ ***********************************************************************************/ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - internal interface IOverlayWindowHost + internal interface IOverlayWindowHost + { + #region Properties + + DockingManager Manager { - bool HitTest(Point dragPoint); + get; + } - IOverlayWindow ShowOverlayWindow(LayoutFloatingWindowControl draggingWindow); + #endregion - void HideOverlayWindow(); + #region Methods - IEnumerable GetDropAreas(LayoutFloatingWindowControl draggingWindow); + bool HitTest( Point dragPoint ); - DockingManager Manager { get; } - } + IOverlayWindow ShowOverlayWindow( LayoutFloatingWindowControl draggingWindow ); + + void HideOverlayWindow(); + + IEnumerable GetDropAreas( LayoutFloatingWindowControl draggingWindow ); + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorControl.cs index 0ab9d523..5b318242 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorControl.cs @@ -15,9 +15,6 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; using System.Windows.Controls; using Xceed.Wpf.AvalonDock.Layout; @@ -25,50 +22,144 @@ using System.Windows.Threading; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorControl : Control, ILayoutControl + public class LayoutAnchorControl : Control, ILayoutControl + { + #region Members + + private LayoutAnchorable _model; + private DispatcherTimer _openUpTimer = null; + private DispatcherTimer _clickGracePeriodTimer = null; + private bool _inGracePeriod = false; + private bool _manuallyOpened = false; + + #endregion + + #region Constructors + + static LayoutAnchorControl() { - static LayoutAnchorControl() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAnchorControl), new FrameworkPropertyMetadata(typeof(LayoutAnchorControl))); - Control.IsHitTestVisibleProperty.AddOwner(typeof(LayoutAnchorControl), new FrameworkPropertyMetadata(true)); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutAnchorControl ), new FrameworkPropertyMetadata( typeof( LayoutAnchorControl ) ) ); + Control.IsHitTestVisibleProperty.AddOwner( typeof( LayoutAnchorControl ), new FrameworkPropertyMetadata( true ) ); + } + internal LayoutAnchorControl( LayoutAnchorable model ) + { + _model = model; + _model.IsActiveChanged += new EventHandler( _model_IsActiveChanged ); + _model.IsSelectedChanged += new EventHandler( _model_IsSelectedChanged ); - internal LayoutAnchorControl(LayoutAnchorable model) - { - _model = model; - _model.IsActiveChanged += new EventHandler(_model_IsActiveChanged); - _model.IsSelectedChanged += new EventHandler(_model_IsSelectedChanged); + SetSide( _model.FindParent().Side ); + } - SetSide(_model.FindParent().Side); - } + #endregion - void _model_IsSelectedChanged(object sender, EventArgs e) - { - if (!_model.IsAutoHidden) - _model.IsSelectedChanged -= new EventHandler(_model_IsSelectedChanged); - else if (_model.IsSelected) + #region Properties + + #region Model + + public ILayoutElement Model + { + get + { + return _model; + } + } + + #endregion + + #region Side + + /// + /// Side Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey SidePropertyKey = DependencyProperty.RegisterReadOnly( "Side", typeof( AnchorSide ), typeof( LayoutAnchorControl ), + new FrameworkPropertyMetadata( ( AnchorSide )AnchorSide.Left ) ); + + public static readonly DependencyProperty SideProperty = SidePropertyKey.DependencyProperty; + + /// + /// Gets the Side property. This dependency property + /// indicates the anchor side of the control. + /// + public AnchorSide Side + { + get + { + return ( AnchorSide )GetValue( SideProperty ); + } + } + + /// + /// Provides a secure method for setting the Side property. + /// This dependency property indicates the anchor side of the control. + /// + /// The new value for the property. + protected void SetSide( AnchorSide value ) + { + SetValue( SidePropertyKey, value ); + } + + #endregion + + #endregion + + #region Private Methods + + private void _model_IsSelectedChanged( object sender, EventArgs e ) + { + if( !_model.IsAutoHidden ) + _model.IsSelectedChanged -= new EventHandler( _model_IsSelectedChanged ); + else if( _model.IsSelected ) + { + _model.Root.Manager.ShowAutoHideWindow( this ); + _model.IsSelected = false; + } + } + + private void _model_IsActiveChanged( object sender, EventArgs e ) + { + if( !_model.IsAutoHidden ) + _model.IsActiveChanged -= new EventHandler( _model_IsActiveChanged ); + else if( _model.IsActive ) + _model.Root.Manager.ShowAutoHideWindow( this ); + } + + private void _openUpTimer_Tick( object sender, EventArgs e ) + { + _openUpTimer.Tick -= new EventHandler( _openUpTimer_Tick ); + _openUpTimer.Stop(); + _openUpTimer = null; + _model.Root.Manager.ShowAutoHideWindow( this ); + + if (!_manuallyOpened) { - _model.Root.Manager.ShowAutoHideWindow(this); - _model.IsSelected = false; + _clickGracePeriodTimer = new DispatcherTimer(DispatcherPriority.ApplicationIdle); + _clickGracePeriodTimer.Interval = TimeSpan.FromMilliseconds(1000); + _inGracePeriod = true; + _clickGracePeriodTimer.Tick += new EventHandler(_clickGracePeriodTimer_Tick); + _clickGracePeriodTimer.Start(); } + + _manuallyOpened = false; } - void _model_IsActiveChanged(object sender, EventArgs e) + private void _clickGracePeriodTimer_Tick(object sender, EventArgs e) { - if (!_model.IsAutoHidden) - _model.IsActiveChanged -= new EventHandler(_model_IsActiveChanged); - else if (_model.IsActive) - _model.Root.Manager.ShowAutoHideWindow(this); + StopGraceTimer(); } - LayoutAnchorable _model; - - public ILayoutElement Model + private void StopGraceTimer() { - get { return _model; } + _clickGracePeriodTimer.Tick -= new EventHandler(_clickGracePeriodTimer_Tick); + _clickGracePeriodTimer.Stop(); + _clickGracePeriodTimer = null; + _inGracePeriod = false; } + #endregion + + #region Overrides + //protected override void OnVisualParentChanged(DependencyObject oldParent) //{ // base.OnVisualParentChanged(oldParent); @@ -98,41 +189,31 @@ namespace Xceed.Wpf.AvalonDock.Controls // } //} - - protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e) - { - base.OnMouseDown(e); + protected override void OnMouseDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseDown( e ); if (!e.Handled) { - if (_model.Root.Manager.AutoHideWindow.Visibility != Visibility.Visible) - { + if (_model.Root.Manager.AutoHideWindow.Visibility != Visibility.Visible) + { _model.Root.Manager.ShowAutoHideWindow(this); - _model.IsActive = true; - _manuallyOpened = true; - } - else - { - if (!_inGracePeriod) - { - _model.Root.Manager.HideAutoHideWindow(this); - } - } + _model.IsActive = true; + _manuallyOpened = true; + } + else + { + if (!_inGracePeriod) + { + _model.Root.Manager.HideAutoHideWindow(this); + } + } } } - - DispatcherTimer _openUpTimer = null; - - DispatcherTimer _clickGracePeriodTimer = null; - - bool _inGracePeriod = false; - - bool _manuallyOpened = false; - - protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e) - { - base.OnMouseEnter(e); + protected override void OnMouseEnter( System.Windows.Input.MouseEventArgs e ) + { + base.OnMouseEnter( e ); if (!e.Handled) { @@ -143,83 +224,18 @@ namespace Xceed.Wpf.AvalonDock.Controls } } - void _openUpTimer_Tick(object sender, EventArgs e) - { - _openUpTimer.Tick -= new EventHandler(_openUpTimer_Tick); - _openUpTimer.Stop(); - _openUpTimer = null; - _model.Root.Manager.ShowAutoHideWindow(this); - - if (!_manuallyOpened) - { - _clickGracePeriodTimer = new DispatcherTimer(DispatcherPriority.ApplicationIdle); - _clickGracePeriodTimer.Interval = TimeSpan.FromMilliseconds(1000); - _inGracePeriod = true; - _clickGracePeriodTimer.Tick += new EventHandler(_clickGracePeriodTimer_Tick); - _clickGracePeriodTimer.Start(); - } - - _manuallyOpened = false; - } - - void _clickGracePeriodTimer_Tick(object sender, EventArgs e) - { - StopGraceTimer(); - } - - void StopGraceTimer() - { - _clickGracePeriodTimer.Tick -= new EventHandler(_clickGracePeriodTimer_Tick); - _clickGracePeriodTimer.Stop(); - _clickGracePeriodTimer = null; - _inGracePeriod = false; - } - - protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e) - { - if (_openUpTimer != null) - { - _openUpTimer.Tick -= new EventHandler(_openUpTimer_Tick); - _openUpTimer.Stop(); - _openUpTimer = null; - } - base.OnMouseLeave(e); - } - - - #region Side - - /// - /// Side Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey SidePropertyKey - = DependencyProperty.RegisterReadOnly("Side", typeof(AnchorSide), typeof(LayoutAnchorControl), - new FrameworkPropertyMetadata((AnchorSide)AnchorSide.Left)); - - public static readonly DependencyProperty SideProperty - = SidePropertyKey.DependencyProperty; - - /// - /// Gets the Side property. This dependency property - /// indicates the anchor side of the control. - /// - public AnchorSide Side - { - get { return (AnchorSide)GetValue(SideProperty); } - } - - /// - /// Provides a secure method for setting the Side property. - /// This dependency property indicates the anchor side of the control. - /// - /// The new value for the property. - protected void SetSide(AnchorSide value) - { - SetValue(SidePropertyKey, value); - } - - #endregion + protected override void OnMouseLeave( System.Windows.Input.MouseEventArgs e ) + { + if( _openUpTimer != null ) + { + _openUpTimer.Tick -= new EventHandler( _openUpTimer_Tick ); + _openUpTimer.Stop(); + _openUpTimer = null; + } + base.OnMouseLeave( e ); + } - } + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorGroupControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorGroupControl.cs index d8829b63..bea7877c 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorGroupControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorGroupControl.cs @@ -14,10 +14,7 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Controls; using System.Collections.ObjectModel; using Xceed.Wpf.AvalonDock.Layout; @@ -25,75 +22,95 @@ using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorGroupControl : Control, ILayoutControl + public class LayoutAnchorGroupControl : Control, ILayoutControl + { + #region Members + + private ObservableCollection _childViews = new ObservableCollection(); + private LayoutAnchorGroup _model; + + #endregion + + #region Constructors + + static LayoutAnchorGroupControl() { - static LayoutAnchorGroupControl() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAnchorGroupControl), new FrameworkPropertyMetadata(typeof(LayoutAnchorGroupControl))); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutAnchorGroupControl ), new FrameworkPropertyMetadata( typeof( LayoutAnchorGroupControl ) ) ); + } + internal LayoutAnchorGroupControl( LayoutAnchorGroup model ) + { + _model = model; + CreateChildrenViews(); - internal LayoutAnchorGroupControl(LayoutAnchorGroup model) - { - _model = model; - CreateChildrenViews(); + _model.Children.CollectionChanged += ( s, e ) => OnModelChildrenCollectionChanged( e ); + } - _model.Children.CollectionChanged += (s, e) => OnModelChildrenCollectionChanged(e); - } + #endregion - private void CreateChildrenViews() - { - var manager = _model.Root.Manager; - foreach (var childModel in _model.Children) - { - _childViews.Add(new LayoutAnchorControl(childModel) { Template = manager.AnchorTemplate }); - } - } + #region Properties - private void OnModelChildrenCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) - { - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) - { - if (e.OldItems != null) - { - { - foreach (var childModel in e.OldItems) - _childViews.Remove(_childViews.First(cv => cv.Model == childModel)); - } - } - } - - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset) - _childViews.Clear(); - - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) - { - if (e.NewItems != null) - { - var manager = _model.Root.Manager; - int insertIndex = e.NewStartingIndex; - foreach (LayoutAnchorable childModel in e.NewItems) - { - _childViews.Insert(insertIndex++, new LayoutAnchorControl(childModel) { Template = manager.AnchorTemplate }); - } - } - } - } + public ObservableCollection Children + { + get + { + return _childViews; + } + } + + public ILayoutElement Model + { + get + { + return _model; + } + } - ObservableCollection _childViews = new ObservableCollection(); + #endregion - public ObservableCollection Children + #region Private Methods + + private void CreateChildrenViews() + { + var manager = _model.Root.Manager; + foreach( var childModel in _model.Children ) + { + _childViews.Add( new LayoutAnchorControl( childModel ) { Template = manager.AnchorTemplate } ); + } + } + + private void OnModelChildrenCollectionChanged( System.Collections.Specialized.NotifyCollectionChangedEventArgs e ) + { + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) + { + if( e.OldItems != null ) { - get { return _childViews; } + { + foreach( var childModel in e.OldItems ) + _childViews.Remove( _childViews.First( cv => cv.Model == childModel ) ); + } } + } + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset ) + _childViews.Clear(); - LayoutAnchorGroup _model; - public ILayoutElement Model + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) + { + if( e.NewItems != null ) { - get { return _model; } + var manager = _model.Root.Manager; + int insertIndex = e.NewStartingIndex; + foreach( LayoutAnchorable childModel in e.NewItems ) + { + _childViews.Insert( insertIndex++, new LayoutAnchorControl( childModel ) { Template = manager.AnchorTemplate } ); + } } + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorSideControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorSideControl.cs index 3a3b4f2b..76b8e207 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorSideControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorSideControl.cs @@ -15,9 +15,7 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using System.Collections.ObjectModel; @@ -25,228 +23,265 @@ using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorSideControl : Control, ILayoutControl + public class LayoutAnchorSideControl : Control, ILayoutControl + { + #region Members + + private LayoutAnchorSide _model = null; + private ObservableCollection _childViews = new ObservableCollection(); + + + #endregion + + #region Constructors + + static LayoutAnchorSideControl() { - static LayoutAnchorSideControl() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAnchorSideControl), new FrameworkPropertyMetadata(typeof(LayoutAnchorSideControl))); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutAnchorSideControl ), new FrameworkPropertyMetadata( typeof( LayoutAnchorSideControl ) ) ); + } + internal LayoutAnchorSideControl( LayoutAnchorSide model ) + { + if( model == null ) + throw new ArgumentNullException( "model" ); - internal LayoutAnchorSideControl(LayoutAnchorSide model) - { - if (model == null) - throw new ArgumentNullException("model"); + _model = model; - _model = model; + CreateChildrenViews(); - CreateChildrenViews(); + _model.Children.CollectionChanged += ( s, e ) => OnModelChildrenCollectionChanged( e ); - _model.Children.CollectionChanged += (s, e) => OnModelChildrenCollectionChanged(e); + UpdateSide(); + } - UpdateSide(); - } + #endregion - private void CreateChildrenViews() - { - var manager = _model.Root.Manager; - foreach (var childModel in _model.Children) - { - _childViews.Add(manager.CreateUIElementForModel(childModel) as LayoutAnchorGroupControl); - } - } + #region Properties - private void OnModelChildrenCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) - { - if (e.OldItems != null && - (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)) - { - foreach (var childModel in e.OldItems) - _childViews.Remove(_childViews.First(cv => cv.Model == childModel)); - } - - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset) - _childViews.Clear(); - - if (e.NewItems != null && - (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)) - { - var manager = _model.Root.Manager; - int insertIndex = e.NewStartingIndex; - foreach (LayoutAnchorGroup childModel in e.NewItems) - { - _childViews.Insert(insertIndex++, manager.CreateUIElementForModel(childModel) as LayoutAnchorGroupControl); - } - } - } + #region Model - LayoutAnchorSide _model = null; - public ILayoutElement Model - { - get { return _model; } - } + public ILayoutElement Model + { + get + { + return _model; + } + } - ObservableCollection _childViews = new ObservableCollection(); + #endregion - public ObservableCollection Children - { - get { return _childViews; } - } + #region Children - void UpdateSide() - { - switch (_model.Side) - { - case AnchorSide.Left: - SetIsLeftSide(true); - break; - case AnchorSide.Top: - SetIsTopSide(true); - break; - case AnchorSide.Right: - SetIsRightSide(true); - break; - case AnchorSide.Bottom: - SetIsBottomSide(true); - break; - } - } + public ObservableCollection Children + { + get + { + return _childViews; + } + } - #region IsLeftSide + #endregion - /// - /// IsLeftSide Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey IsLeftSidePropertyKey - = DependencyProperty.RegisterReadOnly("IsLeftSide", typeof(bool), typeof(LayoutAnchorSideControl), - new FrameworkPropertyMetadata((bool)false)); + #region IsLeftSide - public static readonly DependencyProperty IsLeftSideProperty - = IsLeftSidePropertyKey.DependencyProperty; + /// + /// IsLeftSide Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey IsLeftSidePropertyKey = DependencyProperty.RegisterReadOnly( "IsLeftSide", typeof( bool ), typeof( LayoutAnchorSideControl ), + new FrameworkPropertyMetadata( ( bool )false ) ); - /// - /// Gets the IsLeftSide property. This dependency property - /// indicates this control is anchored to left side. - /// - public bool IsLeftSide - { - get { return (bool)GetValue(IsLeftSideProperty); } - } + public static readonly DependencyProperty IsLeftSideProperty = IsLeftSidePropertyKey.DependencyProperty; - /// - /// Provides a secure method for setting the IsLeftSide property. - /// This dependency property indicates this control is anchored to left side. - /// - /// The new value for the property. - protected void SetIsLeftSide(bool value) - { - SetValue(IsLeftSidePropertyKey, value); - } + /// + /// Gets the IsLeftSide property. This dependency property + /// indicates this control is anchored to left side. + /// + public bool IsLeftSide + { + get + { + return ( bool )GetValue( IsLeftSideProperty ); + } + } - #endregion + /// + /// Provides a secure method for setting the IsLeftSide property. + /// This dependency property indicates this control is anchored to left side. + /// + /// The new value for the property. + protected void SetIsLeftSide( bool value ) + { + SetValue( IsLeftSidePropertyKey, value ); + } - #region IsTopSide + #endregion - /// - /// IsTopSide Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey IsTopSidePropertyKey - = DependencyProperty.RegisterReadOnly("IsTopSide", typeof(bool), typeof(LayoutAnchorSideControl), - new FrameworkPropertyMetadata((bool)false)); + #region IsTopSide - public static readonly DependencyProperty IsTopSideProperty - = IsTopSidePropertyKey.DependencyProperty; + /// + /// IsTopSide Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey IsTopSidePropertyKey = DependencyProperty.RegisterReadOnly( "IsTopSide", typeof( bool ), typeof( LayoutAnchorSideControl ), + new FrameworkPropertyMetadata( ( bool )false ) ); - /// - /// Gets the IsTopSide property. This dependency property - /// indicates this control is anchored to top side. - /// - public bool IsTopSide - { - get { return (bool)GetValue(IsTopSideProperty); } - } + public static readonly DependencyProperty IsTopSideProperty = IsTopSidePropertyKey.DependencyProperty; - /// - /// Provides a secure method for setting the IsTopSide property. - /// This dependency property indicates this control is anchored to top side. - /// - /// The new value for the property. - protected void SetIsTopSide(bool value) - { - SetValue(IsTopSidePropertyKey, value); - } + /// + /// Gets the IsTopSide property. This dependency property + /// indicates this control is anchored to top side. + /// + public bool IsTopSide + { + get + { + return ( bool )GetValue( IsTopSideProperty ); + } + } - #endregion + /// + /// Provides a secure method for setting the IsTopSide property. + /// This dependency property indicates this control is anchored to top side. + /// + /// The new value for the property. + protected void SetIsTopSide( bool value ) + { + SetValue( IsTopSidePropertyKey, value ); + } - #region IsRightSide + #endregion - /// - /// IsRightSide Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey IsRightSidePropertyKey - = DependencyProperty.RegisterReadOnly("IsRightSide", typeof(bool), typeof(LayoutAnchorSideControl), - new FrameworkPropertyMetadata((bool)false)); + #region IsRightSide - public static readonly DependencyProperty IsRightSideProperty - = IsRightSidePropertyKey.DependencyProperty; + /// + /// IsRightSide Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey IsRightSidePropertyKey = DependencyProperty.RegisterReadOnly( "IsRightSide", typeof( bool ), typeof( LayoutAnchorSideControl ), + new FrameworkPropertyMetadata( ( bool )false ) ); - /// - /// Gets the IsRightSide property. This dependency property - /// indicates this control is anchored to right side. - /// - public bool IsRightSide - { - get { return (bool)GetValue(IsRightSideProperty); } - } + public static readonly DependencyProperty IsRightSideProperty = IsRightSidePropertyKey.DependencyProperty; - /// - /// Provides a secure method for setting the IsRightSide property. - /// This dependency property indicates this control is anchored to right side. - /// - /// The new value for the property. - protected void SetIsRightSide(bool value) - { - SetValue(IsRightSidePropertyKey, value); - } + /// + /// Gets the IsRightSide property. This dependency property + /// indicates this control is anchored to right side. + /// + public bool IsRightSide + { + get + { + return ( bool )GetValue( IsRightSideProperty ); + } + } - #endregion + /// + /// Provides a secure method for setting the IsRightSide property. + /// This dependency property indicates this control is anchored to right side. + /// + /// The new value for the property. + protected void SetIsRightSide( bool value ) + { + SetValue( IsRightSidePropertyKey, value ); + } - #region IsBottomSide + #endregion - /// - /// IsBottomSide Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey IsBottomSidePropertyKey - = DependencyProperty.RegisterReadOnly("IsBottomSide", typeof(bool), typeof(LayoutAnchorSideControl), - new FrameworkPropertyMetadata((bool)false)); + #region IsBottomSide - public static readonly DependencyProperty IsBottomSideProperty - = IsBottomSidePropertyKey.DependencyProperty; + /// + /// IsBottomSide Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey IsBottomSidePropertyKey = DependencyProperty.RegisterReadOnly( "IsBottomSide", typeof( bool ), typeof( LayoutAnchorSideControl ), + new FrameworkPropertyMetadata( ( bool )false ) ); - /// - /// Gets the IsBottomSide property. This dependency property - /// indicates if this panel is anchored to bottom side. - /// - public bool IsBottomSide - { - get { return (bool)GetValue(IsBottomSideProperty); } - } + public static readonly DependencyProperty IsBottomSideProperty = IsBottomSidePropertyKey.DependencyProperty; - /// - /// Provides a secure method for setting the IsBottomSide property. - /// This dependency property indicates if this panel is anchored to bottom side. - /// - /// The new value for the property. - protected void SetIsBottomSide(bool value) - { - SetValue(IsBottomSidePropertyKey, value); - } + /// + /// Gets the IsBottomSide property. This dependency property + /// indicates if this panel is anchored to bottom side. + /// + public bool IsBottomSide + { + get + { + return ( bool )GetValue( IsBottomSideProperty ); + } + } + + /// + /// Provides a secure method for setting the IsBottomSide property. + /// This dependency property indicates if this panel is anchored to bottom side. + /// + /// The new value for the property. + protected void SetIsBottomSide( bool value ) + { + SetValue( IsBottomSidePropertyKey, value ); + } + + #endregion + + #endregion + + #region Overrides + + + #endregion - #endregion + #region Private Methods + private void CreateChildrenViews() + { + var manager = _model.Root.Manager; + foreach( var childModel in _model.Children ) + { + _childViews.Add( manager.CreateUIElementForModel( childModel ) as LayoutAnchorGroupControl ); + } + } + private void OnModelChildrenCollectionChanged( System.Collections.Specialized.NotifyCollectionChangedEventArgs e ) + { + if( e.OldItems != null && + ( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) ) + { + foreach( var childModel in e.OldItems ) + _childViews.Remove( _childViews.First( cv => cv.Model == childModel ) ); + } + + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset ) + _childViews.Clear(); + + if( e.NewItems != null && + ( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) ) + { + var manager = _model.Root.Manager; + int insertIndex = e.NewStartingIndex; + foreach( LayoutAnchorGroup childModel in e.NewItems ) + { + _childViews.Insert( insertIndex++, manager.CreateUIElementForModel( childModel ) as LayoutAnchorGroupControl ); + } + } } + + private void UpdateSide() + { + switch( _model.Side ) + { + case AnchorSide.Left: + SetIsLeftSide( true ); + break; + case AnchorSide.Top: + SetIsTopSide( true ); + break; + case AnchorSide.Right: + SetIsRightSide( true ); + break; + case AnchorSide.Bottom: + SetIsBottomSide( true ); + break; + } + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableControl.cs index 2752a01d..80ebc8b8 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableControl.cs @@ -14,121 +14,149 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -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 System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorableControl : Control + public class LayoutAnchorableControl : Control + { + #region Constructors + + static LayoutAnchorableControl() { - static LayoutAnchorableControl() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAnchorableControl), new FrameworkPropertyMetadata(typeof(LayoutAnchorableControl))); - FocusableProperty.OverrideMetadata(typeof(LayoutAnchorableControl), new FrameworkPropertyMetadata(false)); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutAnchorableControl ), new FrameworkPropertyMetadata( typeof( LayoutAnchorableControl ) ) ); + FocusableProperty.OverrideMetadata( typeof( LayoutAnchorableControl ), new FrameworkPropertyMetadata( false ) ); + } - public LayoutAnchorableControl() - { - //SetBinding(FlowDirectionProperty, new Binding("Model.Root.Manager.FlowDirection") { Source = this }); - } + public LayoutAnchorableControl() + { + //SetBinding(FlowDirectionProperty, new Binding("Model.Root.Manager.FlowDirection") { Source = this }); + } + #endregion - #region Model + #region Properties - /// - /// Model Dependency Property - /// - public static readonly DependencyProperty ModelProperty = - DependencyProperty.Register("Model", typeof(LayoutAnchorable), typeof(LayoutAnchorableControl), - new FrameworkPropertyMetadata((LayoutAnchorable)null, - new PropertyChangedCallback(OnModelChanged))); + #region Model - /// - /// Gets or sets the Model property. This dependency property - /// indicates the model attached to this view. - /// - public LayoutAnchorable Model - { - get { return (LayoutAnchorable)GetValue(ModelProperty); } - set { SetValue(ModelProperty, value); } - } + /// + /// Model Dependency Property + /// + public static readonly DependencyProperty ModelProperty = DependencyProperty.Register( "Model", typeof( LayoutAnchorable ), typeof( LayoutAnchorableControl ), + new FrameworkPropertyMetadata( ( LayoutAnchorable )null, new PropertyChangedCallback( OnModelChanged ) ) ); - /// - /// Handles changes to the Model property. - /// - private static void OnModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutAnchorableControl)d).OnModelChanged(e); - } + /// + /// Gets or sets the Model property. This dependency property + /// indicates the model attached to this view. + /// + public LayoutAnchorable Model + { + get + { + return ( LayoutAnchorable )GetValue( ModelProperty ); + } + set + { + SetValue( ModelProperty, value ); + } + } - /// - /// Provides derived classes an opportunity to handle changes to the Model property. - /// - protected virtual void OnModelChanged(DependencyPropertyChangedEventArgs e) + /// + /// Handles changes to the Model property. + /// + private static void OnModelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutAnchorableControl )d ).OnModelChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the Model property. + /// + protected virtual void OnModelChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.OldValue != null ) + { + ( ( LayoutContent )e.OldValue ).PropertyChanged -= Model_PropertyChanged; + } + + if( Model != null ) + { + Model.PropertyChanged += Model_PropertyChanged; + SetLayoutItem( Model.Root.Manager.GetLayoutItemFromModel( Model ) ); + } + else + SetLayoutItem( null ); + } + + private void Model_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e ) + { + if( e.PropertyName == "IsEnabled" ) + { + if( Model != null ) { - if (Model != null) - SetLayoutItem(Model.Root.Manager.GetLayoutItemFromModel(Model)); - else - SetLayoutItem(null); + IsEnabled = Model.IsEnabled; + if( !IsEnabled && Model.IsActive ) + { + if( ( Model.Parent != null ) && ( Model.Parent is LayoutAnchorablePane ) ) + { + ( ( LayoutAnchorablePane )Model.Parent ).SetNextSelectedIndex(); + } + } } + } + } - #endregion + #endregion - #region LayoutItem + #region LayoutItem - /// - /// LayoutItem Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey LayoutItemPropertyKey - = DependencyProperty.RegisterReadOnly("LayoutItem", typeof(LayoutItem), typeof(LayoutAnchorableControl), - new FrameworkPropertyMetadata((LayoutItem)null)); + /// + /// LayoutItem Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey LayoutItemPropertyKey = DependencyProperty.RegisterReadOnly( "LayoutItem", typeof( LayoutItem ), typeof( LayoutAnchorableControl ), + new FrameworkPropertyMetadata( ( LayoutItem )null ) ); - public static readonly DependencyProperty LayoutItemProperty - = LayoutItemPropertyKey.DependencyProperty; + public static readonly DependencyProperty LayoutItemProperty = LayoutItemPropertyKey.DependencyProperty; - /// - /// Gets the LayoutItem property. This dependency property - /// indicates the LayoutItem attached to this tag item. - /// - public LayoutItem LayoutItem - { - get { return (LayoutItem)GetValue(LayoutItemProperty); } - } + /// + /// Gets the LayoutItem property. This dependency property + /// indicates the LayoutItem attached to this tag item. + /// + public LayoutItem LayoutItem + { + get + { + return ( LayoutItem )GetValue( LayoutItemProperty ); + } + } - /// - /// Provides a secure method for setting the LayoutItem property. - /// This dependency property indicates the LayoutItem attached to this tag item. - /// - /// The new value for the property. - protected void SetLayoutItem(LayoutItem value) - { - SetValue(LayoutItemPropertyKey, value); - } + /// + /// Provides a secure method for setting the LayoutItem property. + /// This dependency property indicates the LayoutItem attached to this tag item. + /// + /// The new value for the property. + protected void SetLayoutItem( LayoutItem value ) + { + SetValue( LayoutItemPropertyKey, value ); + } - #endregion + #endregion + #endregion - protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e) - { - if (Model != null) - Model.IsActive = true; + #region Overrides - base.OnGotKeyboardFocus(e); - } + protected override void OnGotKeyboardFocus( System.Windows.Input.KeyboardFocusChangedEventArgs e ) + { + if( Model != null ) + Model.IsActive = true; + base.OnGotKeyboardFocus( e ); + } - } + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs index 487685d1..9df3da5e 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs @@ -17,344 +17,428 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; -using System.Runtime.InteropServices; -using System.Windows.Interop; -using System.Windows.Controls; using System.Windows.Data; -using System.Windows.Media; using System.Windows.Input; using Xceed.Wpf.AvalonDock.Layout; using Xceed.Wpf.AvalonDock.Converters; -using System.Diagnostics; using System.Windows.Controls.Primitives; using Xceed.Wpf.AvalonDock.Commands; using Microsoft.Windows.Shell; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorableFloatingWindowControl : LayoutFloatingWindowControl, IOverlayWindowHost + public class LayoutAnchorableFloatingWindowControl : LayoutFloatingWindowControl, IOverlayWindowHost + { + #region Members + + private LayoutAnchorableFloatingWindow _model; + private OverlayWindow _overlayWindow = null; + private List _dropAreas = null; + + #endregion + + #region Constructors + + static LayoutAnchorableFloatingWindowControl() { - static LayoutAnchorableFloatingWindowControl() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAnchorableFloatingWindowControl), new FrameworkPropertyMetadata(typeof(LayoutAnchorableFloatingWindowControl))); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutAnchorableFloatingWindowControl ), new FrameworkPropertyMetadata( typeof( LayoutAnchorableFloatingWindowControl ) ) ); + } + internal LayoutAnchorableFloatingWindowControl( LayoutAnchorableFloatingWindow model ) + : base( model ) + { + _model = model; + HideWindowCommand = new RelayCommand( ( p ) => OnExecuteHideWindowCommand( p ), ( p ) => CanExecuteHideWindowCommand( p ) ); + CloseWindowCommand = new RelayCommand( ( p ) => OnExecuteCloseWindowCommand( p ), ( p ) => CanExecuteCloseWindowCommand( p ) ); + UpdateThemeResources(); + } - internal LayoutAnchorableFloatingWindowControl(LayoutAnchorableFloatingWindow model) - :base(model) - { - _model = model; - HideWindowCommand = new RelayCommand((p) => OnExecuteHideWindowCommand(p), (p) => CanExecuteHideWindowCommand(p)); - } + #endregion - internal override void UpdateThemeResources( Xceed.Wpf.AvalonDock.Themes.Theme oldTheme = null ) - { - if (Application.Current != null) - return; + #region Properties - base.UpdateThemeResources(oldTheme); + #region SingleContentLayoutItem - if (_overlayWindow != null) - _overlayWindow.UpdateThemeResources(oldTheme); - } + /// + /// SingleContentLayoutItem Dependency Property + /// + public static readonly DependencyProperty SingleContentLayoutItemProperty = DependencyProperty.Register( "SingleContentLayoutItem", typeof( LayoutItem ), typeof( LayoutAnchorableFloatingWindowControl ), + new FrameworkPropertyMetadata( ( LayoutItem )null, new PropertyChangedCallback( OnSingleContentLayoutItemChanged ) ) ); - LayoutAnchorableFloatingWindow _model; + /// + /// Gets or sets the SingleContentLayoutItem property. This dependency property + /// indicates the layout item of the selected content when is shown a single anchorable pane. + /// + public LayoutItem SingleContentLayoutItem + { + get + { + return ( LayoutItem )GetValue( SingleContentLayoutItemProperty ); + } + set + { + SetValue( SingleContentLayoutItemProperty, value ); + } + } - public override ILayoutElement Model - { - get { return _model; } - } + /// + /// Handles changes to the SingleContentLayoutItem property. + /// + private static void OnSingleContentLayoutItemChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutAnchorableFloatingWindowControl )d ).OnSingleContentLayoutItemChanged( e ); + } - #region SingleContentLayoutItem - - /// - /// SingleContentLayoutItem Dependency Property - /// - public static readonly DependencyProperty SingleContentLayoutItemProperty = - DependencyProperty.Register("SingleContentLayoutItem", typeof(LayoutItem), typeof(LayoutAnchorableFloatingWindowControl), - new FrameworkPropertyMetadata((LayoutItem)null, - new PropertyChangedCallback(OnSingleContentLayoutItemChanged))); - - /// - /// Gets or sets the SingleContentLayoutItem property. This dependency property - /// indicates the layout item of the selected content when is shown a single anchorable pane. - /// - public LayoutItem SingleContentLayoutItem - { - get { return (LayoutItem)GetValue(SingleContentLayoutItemProperty); } - set { SetValue(SingleContentLayoutItemProperty, value); } - } + /// + /// Provides derived classes an opportunity to handle changes to the SingleContentLayoutItem property. + /// + protected virtual void OnSingleContentLayoutItemChanged( DependencyPropertyChangedEventArgs e ) + { + } - /// - /// Handles changes to the SingleContentLayoutItem property. - /// - private static void OnSingleContentLayoutItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutAnchorableFloatingWindowControl)d).OnSingleContentLayoutItemChanged(e); - } + #endregion + + #endregion + + #region Overrides + + public override ILayoutElement Model + { + get + { + return _model; + } + } - /// - /// Provides derived classes an opportunity to handle changes to the SingleContentLayoutItem property. - /// - protected virtual void OnSingleContentLayoutItemChanged(DependencyPropertyChangedEventArgs e) + protected override void OnInitialized( EventArgs e ) + { + base.OnInitialized( e ); + + var manager = _model.Root.Manager; + + Content = manager.CreateUIElementForModel( _model.RootPanel ); + + //SetBinding(VisibilityProperty, new Binding("IsVisible") { Source = _model, Converter = new BoolToVisibilityConverter(), Mode = BindingMode.OneWay, ConverterParameter = Visibility.Hidden }); + + //Issue: http://avalondock.codeplex.com/workitem/15036 + IsVisibleChanged += ( s, args ) => + { + var visibilityBinding = GetBindingExpression( VisibilityProperty ); + if( IsVisible && ( visibilityBinding == null ) ) { + SetBinding( VisibilityProperty, new Binding( "IsVisible" ) { Source = _model, Converter = new BoolToVisibilityConverter(), Mode = BindingMode.OneWay, ConverterParameter = Visibility.Hidden } ); } + }; - #endregion + SetBinding( SingleContentLayoutItemProperty, new Binding( "Model.SinglePane.SelectedContent" ) { Source = this, Converter = new LayoutItemFromLayoutModelConverter() } ); + _model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( _model_PropertyChanged ); + } + protected override void OnClosed( EventArgs e ) + { + var root = Model.Root; + root.Manager.RemoveFloatingWindow( this ); + root.CollectGarbage(); + if( _overlayWindow != null ) + { + _overlayWindow.Close(); + _overlayWindow = null; + } + + base.OnClosed( e ); + + if( !CloseInitiatedByUser ) + { + root.FloatingWindows.Remove( _model ); + } + + _model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler( _model_PropertyChanged ); + } - protected override void OnInitialized(EventArgs e) - { - base.OnInitialized(e); + protected override void OnClosing( System.ComponentModel.CancelEventArgs e ) + { + if( CloseInitiatedByUser && !KeepContentVisibleOnClose ) + { + e.Cancel = true; + _model.Descendents().OfType().ToArray().ForEach( ( a ) => a.Hide() ); + } - var manager = _model.Root.Manager; + base.OnClosing( e ); + } - Content = manager.CreateUIElementForModel(_model.RootPanel); + protected override IntPtr FilterMessage( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled ) + { + switch( msg ) + { + case Win32Helper.WM_NCLBUTTONDOWN: //Left button down on title -> start dragging over docking manager + if( wParam.ToInt32() == Win32Helper.HT_CAPTION ) + { + _model.Descendents().OfType().First( p => p.ChildrenCount > 0 && p.SelectedContent != null ).SelectedContent.IsActive = true; + handled = true; + } + break; + case Win32Helper.WM_NCRBUTTONUP: + if( wParam.ToInt32() == Win32Helper.HT_CAPTION ) + { + if( OpenContextMenu() ) + handled = true; + + if( _model.Root.Manager.ShowSystemMenu ) + WindowChrome.GetWindowChrome( this ).ShowSystemMenu = !handled; + else + WindowChrome.GetWindowChrome( this ).ShowSystemMenu = false; + } + break; + + } + + return base.FilterMessage( hwnd, msg, wParam, lParam, ref handled ); + } - //SetBinding(VisibilityProperty, new Binding("IsVisible") { Source = _model, Converter = new BoolToVisibilityConverter(), Mode = BindingMode.OneWay, ConverterParameter = Visibility.Hidden }); + internal override void UpdateThemeResources( Xceed.Wpf.AvalonDock.Themes.Theme oldTheme = null ) + { + if (Application.Current != null) + return; - //Issue: http://avalondock.codeplex.com/workitem/15036 - IsVisibleChanged += (s, args) => - { - var visibilityBinding = GetBindingExpression(VisibilityProperty); - if (IsVisible && (visibilityBinding == null)) - { - SetBinding(VisibilityProperty, new Binding("IsVisible") { Source = _model, Converter = new BoolToVisibilityConverter(), Mode = BindingMode.OneWay, ConverterParameter = Visibility.Hidden }); - } - }; + base.UpdateThemeResources( oldTheme ); - SetBinding(SingleContentLayoutItemProperty, new Binding("Model.SinglePane.SelectedContent") { Source = this, Converter = new LayoutItemFromLayoutModelConverter() }); + if( _overlayWindow != null ) + { + _overlayWindow.UpdateThemeResources( oldTheme ); + } + } - _model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged); - } + #endregion + #region Private Methods - void _model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) - { - if (e.PropertyName == "RootPanel" && - _model.RootPanel == null) - { - InternalClose(); - } - } + private void _model_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e ) + { + if( e.PropertyName == "RootPanel" && + _model.RootPanel == null ) + { + InternalClose(); + } + } + private void CreateOverlayWindow() + { + if( _overlayWindow == null ) + _overlayWindow = new OverlayWindow( this ); + Rect rectWindow = new Rect( this.PointToScreenDPIWithoutFlowDirection( new Point() ), this.TransformActualSizeToAncestor() ); + _overlayWindow.Left = rectWindow.Left; + _overlayWindow.Top = rectWindow.Top; + _overlayWindow.Width = rectWindow.Width; + _overlayWindow.Height = rectWindow.Height; + } - bool IOverlayWindowHost.HitTest(Point dragPoint) - { - if (!this.IsVisible) return false; - Rect detectionRect = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor()); - return detectionRect.Contains(dragPoint); - } + private bool OpenContextMenu() + { + var ctxMenu = _model.Root.Manager.AnchorableContextMenu; + if( ctxMenu != null && SingleContentLayoutItem != null ) + { + ctxMenu.PlacementTarget = null; + ctxMenu.Placement = PlacementMode.MousePoint; + ctxMenu.DataContext = SingleContentLayoutItem; + ctxMenu.IsOpen = true; + return true; + } + + return false; + } - DockingManager IOverlayWindowHost.Manager - { - get { return _model.Root.Manager; } - } + private bool IsContextMenuOpen() + { + var ctxMenu = _model.Root.Manager.AnchorableContextMenu; + if( ctxMenu != null && SingleContentLayoutItem != null ) + { + return ctxMenu.IsOpen; + } - OverlayWindow _overlayWindow = null; - void CreateOverlayWindow() - { - if (_overlayWindow == null) - _overlayWindow = new OverlayWindow(this); - Rect rectWindow = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor()); - _overlayWindow.Left = rectWindow.Left; - _overlayWindow.Top = rectWindow.Top; - _overlayWindow.Width = rectWindow.Width; - _overlayWindow.Height = rectWindow.Height; - } + return false; + } - IOverlayWindow IOverlayWindowHost.ShowOverlayWindow(LayoutFloatingWindowControl draggingWindow) - { - CreateOverlayWindow(); - _overlayWindow.Owner = draggingWindow; - _overlayWindow.EnableDropTargets(); - _overlayWindow.Show(); + #endregion - return _overlayWindow; - } + #region Commands - void IOverlayWindowHost.HideOverlayWindow() - { - _dropAreas = null; - if (_overlayWindow != null) - { - _overlayWindow.Owner = null; - _overlayWindow.HideDropTargets(); - } - } + #region HideWindowCommand - List _dropAreas = null; - IEnumerable IOverlayWindowHost.GetDropAreas(LayoutFloatingWindowControl draggingWindow) - { - if (_dropAreas != null) - return _dropAreas; - - _dropAreas = new List(); - - if (draggingWindow.Model is LayoutDocumentFloatingWindow) - return _dropAreas; - - var rootVisual = (Content as FloatingWindowContentHost).RootVisual; - - foreach (var areaHost in rootVisual.FindVisualChildren()) - { - _dropAreas.Add(new DropArea( - areaHost, - DropAreaType.AnchorablePane)); - } - foreach (var areaHost in rootVisual.FindVisualChildren()) - { - _dropAreas.Add(new DropArea( - areaHost, - DropAreaType.DocumentPane)); - } - - return _dropAreas; - } + public ICommand HideWindowCommand + { + get; + private set; + } - protected override void OnClosed(EventArgs e) - { - var root = Model.Root; - root.Manager.RemoveFloatingWindow(this); - root.CollectGarbage(); - if (_overlayWindow != null) - { - _overlayWindow.Close(); - _overlayWindow = null; - } - - base.OnClosed(e); - - if (!CloseInitiatedByUser) - { - root.FloatingWindows.Remove(_model); - } - - _model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged); - } + private bool CanExecuteHideWindowCommand( object parameter ) + { + if( Model == null ) + return false; - protected override void OnClosing(System.ComponentModel.CancelEventArgs e) - { - if (CloseInitiatedByUser && !KeepContentVisibleOnClose) - { - e.Cancel = true; - _model.Descendents().OfType().ToArray().ForEach((a) => a.Hide()); - } + var root = Model.Root; + if( root == null ) + return false; - base.OnClosing(e); - } + var manager = root.Manager; + if( manager == null ) + return false; - protected override IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + bool canExecute = false; + foreach( var anchorable in this.Model.Descendents().OfType().ToArray() ) + { + if( !anchorable.CanHide ) { - switch (msg) - { - case Win32Helper.WM_NCLBUTTONDOWN: //Left button down on title -> start dragging over docking manager - if (wParam.ToInt32() == Win32Helper.HT_CAPTION) - { - _model.Descendents().OfType().First(p => p.ChildrenCount > 0 && p.SelectedContent != null).SelectedContent.IsActive = true; - handled = true; - } - break; - case Win32Helper.WM_NCRBUTTONUP: - if (wParam.ToInt32() == Win32Helper.HT_CAPTION) - { - if (OpenContextMenu()) - handled = true; - - if (_model.Root.Manager.ShowSystemMenu) - WindowChrome.GetWindowChrome(this).ShowSystemMenu = !handled; - else - WindowChrome.GetWindowChrome(this).ShowSystemMenu = false; - } - break; - - } - - return base.FilterMessage(hwnd, msg, wParam, lParam, ref handled); + canExecute = false; + break; } - bool OpenContextMenu() + var anchorableLayoutItem = manager.GetLayoutItemFromModel( anchorable ) as LayoutAnchorableItem; + if( anchorableLayoutItem == null || + anchorableLayoutItem.HideCommand == null || + !anchorableLayoutItem.HideCommand.CanExecute( parameter ) ) { - var ctxMenu = _model.Root.Manager.AnchorableContextMenu; - if (ctxMenu != null && SingleContentLayoutItem != null) - { - ctxMenu.PlacementTarget = null; - ctxMenu.Placement = PlacementMode.MousePoint; - ctxMenu.DataContext = SingleContentLayoutItem; - ctxMenu.IsOpen = true; - return true; - } - - return false; + canExecute = false; + break; } - bool IsContextMenuOpen() - { - var ctxMenu = _model.Root.Manager.AnchorableContextMenu; - if (ctxMenu != null && SingleContentLayoutItem != null) - { - return ctxMenu.IsOpen; - } + canExecute = true; + } - return false; - } + return canExecute; + } - #region HideWindowCommand - public ICommand HideWindowCommand - { - get; - private set; - } + private void OnExecuteHideWindowCommand( object parameter ) + { + var manager = Model.Root.Manager; + foreach( var anchorable in this.Model.Descendents().OfType().ToArray() ) + { + var anchorableLayoutItem = manager.GetLayoutItemFromModel( anchorable ) as LayoutAnchorableItem; + anchorableLayoutItem.HideCommand.Execute( parameter ); + } + } + #endregion + + #region CloseWindowCommand + public ICommand CloseWindowCommand + { + get; + private set; + } + + private bool CanExecuteCloseWindowCommand( object parameter ) + { + if( Model == null ) + return false; + + var root = Model.Root; + if( root == null ) + return false; - private bool CanExecuteHideWindowCommand(object parameter) + var manager = root.Manager; + if( manager == null ) + return false; + + bool canExecute = false; + foreach( var anchorable in this.Model.Descendents().OfType().ToArray() ) + { + if( !anchorable.CanClose ) { - if (Model == null) - return false; - - var root = Model.Root; - if (root == null) - return false; - - var manager = root.Manager; - if (manager == null) - return false; - - bool canExecute = false; - foreach (var anchorable in this.Model.Descendents().OfType().ToArray()) - { - if (!anchorable.CanHide) - { - canExecute = false; - break; - } - - var anchorableLayoutItem = manager.GetLayoutItemFromModel(anchorable) as LayoutAnchorableItem; - if (anchorableLayoutItem == null || - anchorableLayoutItem.HideCommand == null || - !anchorableLayoutItem.HideCommand.CanExecute(parameter)) - { - canExecute = false; - break; - } - - canExecute = true; - } - - return canExecute; + canExecute = false; + break; } - private void OnExecuteHideWindowCommand(object parameter) + var anchorableLayoutItem = manager.GetLayoutItemFromModel( anchorable ) as LayoutAnchorableItem; + if( anchorableLayoutItem == null || + anchorableLayoutItem.CloseCommand == null || + !anchorableLayoutItem.CloseCommand.CanExecute( parameter ) ) { - var manager = Model.Root.Manager; - foreach (var anchorable in this.Model.Descendents().OfType().ToArray()) - { - var anchorableLayoutItem = manager.GetLayoutItemFromModel(anchorable) as LayoutAnchorableItem; - anchorableLayoutItem.CloseCommand.Execute(parameter); - } + canExecute = false; + break; } - #endregion + + canExecute = true; + } + + return canExecute; + } + + private void OnExecuteCloseWindowCommand( object parameter ) + { + var manager = Model.Root.Manager; + foreach( var anchorable in this.Model.Descendents().OfType().ToArray() ) + { + var anchorableLayoutItem = manager.GetLayoutItemFromModel( anchorable ) as LayoutAnchorableItem; + anchorableLayoutItem.CloseCommand.Execute( parameter ); + } + } + + #endregion + + #endregion + + #region IOverlayWindowHost + + bool IOverlayWindowHost.HitTest( Point dragPoint ) + { + Rect detectionRect = new Rect( this.PointToScreenDPIWithoutFlowDirection( new Point() ), this.TransformActualSizeToAncestor() ); + return detectionRect.Contains( dragPoint ); } + + DockingManager IOverlayWindowHost.Manager + { + get + { + return _model.Root.Manager; + } + } + + IOverlayWindow IOverlayWindowHost.ShowOverlayWindow( LayoutFloatingWindowControl draggingWindow ) + { + CreateOverlayWindow(); + _overlayWindow.Owner = draggingWindow; + _overlayWindow.EnableDropTargets(); + _overlayWindow.Show(); + + return _overlayWindow; + } + + void IOverlayWindowHost.HideOverlayWindow() + { + _dropAreas = null; + _overlayWindow.Owner = null; + _overlayWindow.HideDropTargets(); + } + + IEnumerable IOverlayWindowHost.GetDropAreas( LayoutFloatingWindowControl draggingWindow ) + { + if( _dropAreas != null ) + return _dropAreas; + + _dropAreas = new List(); + + if( draggingWindow.Model is LayoutDocumentFloatingWindow ) + return _dropAreas; + + var rootVisual = ( Content as FloatingWindowContentHost ).RootVisual; + + foreach( var areaHost in rootVisual.FindVisualChildren() ) + { + _dropAreas.Add( new DropArea( + areaHost, + DropAreaType.AnchorablePane ) ); + } + foreach( var areaHost in rootVisual.FindVisualChildren() ) + { + _dropAreas.Add( new DropArea( + areaHost, + DropAreaType.DocumentPane ) ); + } + + return _dropAreas; + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableItem.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableItem.cs index e5260bc2..7a8a6047 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableItem.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableItem.cs @@ -15,9 +15,6 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using Xceed.Wpf.AvalonDock.Layout; using System.Windows.Input; using System.Windows; @@ -26,242 +23,204 @@ using System.Windows.Data; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorableItem : LayoutItem - { - LayoutAnchorable _anchorable; - internal LayoutAnchorableItem() - { + public class LayoutAnchorableItem : LayoutItem + { + #region Members - } + private LayoutAnchorable _anchorable; + private ICommand _defaultHideCommand; + private ICommand _defaultAutoHideCommand; + private ICommand _defaultDockCommand; + private ReentrantFlag _visibilityReentrantFlag = new ReentrantFlag(); - internal override void Attach(LayoutContent model) - { - _anchorable = model as LayoutAnchorable; - _anchorable.IsVisibleChanged += new EventHandler(_anchorable_IsVisibleChanged); + #endregion - base.Attach(model); - } + #region Constructors - internal override void Detach() - { - _anchorable.IsVisibleChanged -= new EventHandler(_anchorable_IsVisibleChanged); - _anchorable = null; - base.Detach(); - } + internal LayoutAnchorableItem() + { + } - protected override void Close() - { - var dockingManager = _anchorable.Root.Manager; - dockingManager._ExecuteCloseCommand(_anchorable); - } + #endregion - ICommand _defaultHideCommand; - ICommand _defaultAutoHideCommand; - ICommand _defaultDockCommand; + #region Properties - protected override void InitDefaultCommands() - { - _defaultHideCommand = new RelayCommand((p) => ExecuteHideCommand(p), (p) => CanExecuteHideCommand(p)); - _defaultAutoHideCommand = new RelayCommand((p) => ExecuteAutoHideCommand(p), (p) => CanExecuteAutoHideCommand(p)); - _defaultDockCommand = new RelayCommand((p) => ExecuteDockCommand(p), (p) => CanExecuteDockCommand(p)); + #region HideCommand - base.InitDefaultCommands(); - } + /// + /// HideCommand Dependency Property + /// + public static readonly DependencyProperty HideCommandProperty = DependencyProperty.Register( "HideCommand", typeof( ICommand ), typeof( LayoutAnchorableItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnHideCommandChanged ), new CoerceValueCallback( CoerceHideCommandValue ) ) ); - protected override void ClearDefaultBindings() - { - if (HideCommand == _defaultHideCommand) - BindingOperations.ClearBinding(this, HideCommandProperty); - if (AutoHideCommand == _defaultAutoHideCommand) - BindingOperations.ClearBinding(this, AutoHideCommandProperty); - if (DockCommand == _defaultDockCommand) - BindingOperations.ClearBinding(this, DockCommandProperty); - - base.ClearDefaultBindings(); - } + /// + /// Gets or sets the HideCommand property. This dependency property + /// indicates the command to execute when an anchorable is hidden. + /// + public ICommand HideCommand + { + get + { + return ( ICommand )GetValue( HideCommandProperty ); + } + set + { + SetValue( HideCommandProperty, value ); + } + } - protected override void SetDefaultBindings() - { - if (HideCommand == null) - HideCommand = _defaultHideCommand; - if (AutoHideCommand == null) - AutoHideCommand = _defaultAutoHideCommand; - if (DockCommand == null) - DockCommand = _defaultDockCommand; - - Visibility = _anchorable.IsVisible ? Visibility.Visible : System.Windows.Visibility.Hidden; - base.SetDefaultBindings(); - } + /// + /// Handles changes to the HideCommand property. + /// + private static void OnHideCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutAnchorableItem )d ).OnHideCommandChanged( e ); + } + /// + /// Provides derived classes an opportunity to handle changes to the HideCommand property. + /// + protected virtual void OnHideCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - #region HideCommand + /// + /// Coerces the HideCommand value. + /// + private static object CoerceHideCommandValue( DependencyObject d, object value ) + { + return value; + } - /// - /// HideCommand Dependency Property - /// - public static readonly DependencyProperty HideCommandProperty = - DependencyProperty.Register("HideCommand", typeof(ICommand), typeof(LayoutAnchorableItem), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnHideCommandChanged), - new CoerceValueCallback(CoerceHideCommandValue))); + private bool CanExecuteHideCommand( object parameter ) + { + if( LayoutElement == null ) + return false; + return _anchorable.CanHide; + } - /// - /// Gets or sets the HideCommand property. This dependency property - /// indicates the command to execute when an anchorable is hidden. - /// - public ICommand HideCommand - { - get { return (ICommand)GetValue(HideCommandProperty); } - set { SetValue(HideCommandProperty, value); } - } + private void ExecuteHideCommand( object parameter ) + { + if( _anchorable != null && _anchorable.Root != null && _anchorable.Root.Manager != null ) + _anchorable.Root.Manager._ExecuteHideCommand( _anchorable ); + } - /// - /// Handles changes to the HideCommand property. - /// - private static void OnHideCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutAnchorableItem)d).OnHideCommandChanged(e); - } + #endregion - /// - /// Provides derived classes an opportunity to handle changes to the HideCommand property. - /// - protected virtual void OnHideCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + #region AutoHideCommand - /// - /// Coerces the HideCommand value. - /// - private static object CoerceHideCommandValue(DependencyObject d, object value) - { - return value; - } + /// + /// AutoHideCommand Dependency Property + /// + public static readonly DependencyProperty AutoHideCommandProperty = DependencyProperty.Register( "AutoHideCommand", typeof( ICommand ), typeof( LayoutAnchorableItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnAutoHideCommandChanged ), new CoerceValueCallback( CoerceAutoHideCommandValue ) ) ); + /// + /// Gets or sets the AutoHideCommand property. This dependency property + /// indicates the command to execute when user click the auto hide button. + /// + /// By default this command toggles auto hide state for an anchorable. + public ICommand AutoHideCommand + { + get + { + return ( ICommand )GetValue( AutoHideCommandProperty ); + } + set + { + SetValue( AutoHideCommandProperty, value ); + } + } - private bool CanExecuteHideCommand(object parameter) - { - if (LayoutElement == null) - return false; - return _anchorable.CanHide; - } + /// + /// Handles changes to the AutoHideCommand property. + /// + private static void OnAutoHideCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutAnchorableItem )d ).OnAutoHideCommandChanged( e ); + } - private void ExecuteHideCommand(object parameter) - { - if (_anchorable != null && _anchorable.Root != null && _anchorable.Root.Manager != null) - _anchorable.Root.Manager._ExecuteHideCommand(_anchorable); - } + /// + /// Provides derived classes an opportunity to handle changes to the AutoHideCommand property. + /// + protected virtual void OnAutoHideCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - #endregion - - #region AutoHideCommand - - /// - /// AutoHideCommand Dependency Property - /// - public static readonly DependencyProperty AutoHideCommandProperty = - DependencyProperty.Register("AutoHideCommand", typeof(ICommand), typeof(LayoutAnchorableItem), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnAutoHideCommandChanged), - new CoerceValueCallback(CoerceAutoHideCommandValue))); - - /// - /// Gets or sets the AutoHideCommand property. This dependency property - /// indicates the command to execute when user click the auto hide button. - /// - /// By default this command toggles auto hide state for an anchorable. - public ICommand AutoHideCommand - { - get { return (ICommand)GetValue(AutoHideCommandProperty); } - set { SetValue(AutoHideCommandProperty, value); } - } + /// + /// Coerces the AutoHideCommand value. + /// + private static object CoerceAutoHideCommandValue( DependencyObject d, object value ) + { + return value; + } - /// - /// Handles changes to the AutoHideCommand property. - /// - private static void OnAutoHideCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutAnchorableItem)d).OnAutoHideCommandChanged(e); - } + private bool CanExecuteAutoHideCommand( object parameter ) + { + if( LayoutElement == null ) + return false; - /// - /// Provides derived classes an opportunity to handle changes to the AutoHideCommand property. - /// - protected virtual void OnAutoHideCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + if( LayoutElement.FindParent() != null ) + return false;//is floating - /// - /// Coerces the AutoHideCommand value. - /// - private static object CoerceAutoHideCommandValue(DependencyObject d, object value) - { - return value; - } + return _anchorable.CanAutoHide; + } - private bool CanExecuteAutoHideCommand(object parameter) - { - if (LayoutElement == null) - return false; + private void ExecuteAutoHideCommand( object parameter ) + { + if( _anchorable != null && _anchorable.Root != null && _anchorable.Root.Manager != null ) + _anchorable.Root.Manager._ExecuteAutoHideCommand( _anchorable ); + } - if (LayoutElement.FindParent() != null) - return false;//is floating + #endregion - return _anchorable.CanAutoHide; - } + #region DockCommand - private void ExecuteAutoHideCommand(object parameter) - { - if (_anchorable != null && _anchorable.Root != null && _anchorable.Root.Manager != null) - _anchorable.Root.Manager._ExecuteAutoHideCommand(_anchorable); - } + /// + /// DockCommand Dependency Property + /// + public static readonly DependencyProperty DockCommandProperty = DependencyProperty.Register( "DockCommand", typeof( ICommand ), typeof( LayoutAnchorableItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnDockCommandChanged ), new CoerceValueCallback( CoerceDockCommandValue ) ) ); - #endregion - - #region DockCommand - - /// - /// DockCommand Dependency Property - /// - public static readonly DependencyProperty DockCommandProperty = - DependencyProperty.Register("DockCommand", typeof(ICommand), typeof(LayoutAnchorableItem), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnDockCommandChanged), - new CoerceValueCallback(CoerceDockCommandValue))); - - /// - /// Gets or sets the DockCommand property. This dependency property - /// indicates the command to execute when user click the Dock button. - /// - /// By default this command moves the anchorable inside the container pane which previously hosted the object. - public ICommand DockCommand - { - get { return (ICommand)GetValue(DockCommandProperty); } - set { SetValue(DockCommandProperty, value); } - } + /// + /// Gets or sets the DockCommand property. This dependency property + /// indicates the command to execute when user click the Dock button. + /// + /// By default this command moves the anchorable inside the container pane which previously hosted the object. + public ICommand DockCommand + { + get + { + return ( ICommand )GetValue( DockCommandProperty ); + } + set + { + SetValue( DockCommandProperty, value ); + } + } - /// - /// Handles changes to the DockCommand property. - /// - private static void OnDockCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutAnchorableItem)d).OnDockCommandChanged(e); - } + /// + /// Handles changes to the DockCommand property. + /// + private static void OnDockCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutAnchorableItem )d ).OnDockCommandChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the DockCommand property. - /// - protected virtual void OnDockCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + /// + /// Provides derived classes an opportunity to handle changes to the DockCommand property. + /// + protected virtual void OnDockCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - /// - /// Coerces the DockCommand value. - /// - private static object CoerceDockCommandValue(DependencyObject d, object value) - { - return value; - } + /// + /// Coerces the DockCommand value. + /// + private static object CoerceDockCommandValue( DependencyObject d, object value ) + { + return value; + } private bool CanExecuteDockCommand(object parameter) { @@ -271,94 +230,164 @@ namespace Xceed.Wpf.AvalonDock.Controls return LayoutElement.CanDock && LayoutElement.FindParent() != null; } - private void ExecuteDockCommand(object parameter) - { - LayoutElement.Root.Manager._ExecuteDockCommand(_anchorable); - } + private void ExecuteDockCommand( object parameter ) + { + LayoutElement.Root.Manager._ExecuteDockCommand( _anchorable ); + } - #endregion + #endregion - #region Visibility - ReentrantFlag _visibilityReentrantFlag = new ReentrantFlag(); + #region CanHide - protected override void OnVisibilityChanged() - { - if (_anchorable != null && _anchorable.Root != null) - { - if (_visibilityReentrantFlag.CanEnter) - { - using (_visibilityReentrantFlag.Enter()) - { - if (Visibility == System.Windows.Visibility.Hidden) - _anchorable.Hide(false); - else if (Visibility == System.Windows.Visibility.Visible) - _anchorable.Show(); - } - } - } - - base.OnVisibilityChanged(); - } + /// + /// CanHide Dependency Property + /// + public static readonly DependencyProperty CanHideProperty = DependencyProperty.Register( "CanHide", typeof( bool ), typeof( LayoutAnchorableItem ), new FrameworkPropertyMetadata( ( bool )true, + new PropertyChangedCallback( OnCanHideChanged ) ) ); + /// + /// Gets or sets the CanHide property. This dependency property + /// indicates if user can hide the anchorable item. + /// + public bool CanHide + { + get + { + return ( bool )GetValue( CanHideProperty ); + } + set + { + SetValue( CanHideProperty, value ); + } + } - void _anchorable_IsVisibleChanged(object sender, EventArgs e) - { - if (_anchorable != null && _anchorable.Root != null) - { - if (_visibilityReentrantFlag.CanEnter) - { - using (_visibilityReentrantFlag.Enter()) - { - if (_anchorable.IsVisible) - Visibility = Visibility.Visible; - else - Visibility = Visibility.Hidden; - } - } - } - } + /// + /// Handles changes to the CanHide property. + /// + private static void OnCanHideChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutAnchorableItem )d ).OnCanHideChanged( e ); + } - #endregion + /// + /// Provides derived classes an opportunity to handle changes to the CanHide property. + /// + protected virtual void OnCanHideChanged( DependencyPropertyChangedEventArgs e ) + { + if( _anchorable != null ) + _anchorable.CanHide = ( bool )e.NewValue; + } - #region CanHide + #endregion - /// - /// CanHide Dependency Property - /// - public static readonly DependencyProperty CanHideProperty = - DependencyProperty.Register("CanHide", typeof(bool), typeof(LayoutAnchorableItem), - new FrameworkPropertyMetadata((bool)true, - new PropertyChangedCallback(OnCanHideChanged))); + #endregion - /// - /// Gets or sets the CanHide property. This dependency property - /// indicates if user can hide the anchorable item. - /// - public bool CanHide - { - get { return (bool)GetValue(CanHideProperty); } - set { SetValue(CanHideProperty, value); } - } + #region Overrides + + internal override void Attach( LayoutContent model ) + { + _anchorable = model as LayoutAnchorable; + _anchorable.IsVisibleChanged += new EventHandler( _anchorable_IsVisibleChanged ); + + base.Attach( model ); + } - /// - /// Handles changes to the CanHide property. - /// - private static void OnCanHideChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + internal override void Detach() + { + _anchorable.IsVisibleChanged -= new EventHandler( _anchorable_IsVisibleChanged ); + _anchorable = null; + base.Detach(); + } + + protected override void Close() + { + if( ( _anchorable.Root != null ) && ( _anchorable.Root.Manager != null ) ) + { + var dockingManager = _anchorable.Root.Manager; + dockingManager._ExecuteCloseCommand( _anchorable ); + } + } + + protected override void InitDefaultCommands() + { + _defaultHideCommand = new RelayCommand( ( p ) => ExecuteHideCommand( p ), ( p ) => CanExecuteHideCommand( p ) ); + _defaultAutoHideCommand = new RelayCommand( ( p ) => ExecuteAutoHideCommand( p ), ( p ) => CanExecuteAutoHideCommand( p ) ); + _defaultDockCommand = new RelayCommand( ( p ) => ExecuteDockCommand( p ), ( p ) => CanExecuteDockCommand( p ) ); + + base.InitDefaultCommands(); + } + + protected override void ClearDefaultBindings() + { + if( HideCommand == _defaultHideCommand ) + BindingOperations.ClearBinding( this, HideCommandProperty ); + if( AutoHideCommand == _defaultAutoHideCommand ) + BindingOperations.ClearBinding( this, AutoHideCommandProperty ); + if( DockCommand == _defaultDockCommand ) + BindingOperations.ClearBinding( this, DockCommandProperty ); + + base.ClearDefaultBindings(); + } + + protected override void SetDefaultBindings() + { + if( HideCommand == null ) + HideCommand = _defaultHideCommand; + if( AutoHideCommand == null ) + AutoHideCommand = _defaultAutoHideCommand; + if( DockCommand == null ) + DockCommand = _defaultDockCommand; + + Visibility = _anchorable.IsVisible ? Visibility.Visible : System.Windows.Visibility.Hidden; + base.SetDefaultBindings(); + } + + protected override void OnVisibilityChanged() + { + if( _anchorable != null && _anchorable.Root != null ) + { + if( _visibilityReentrantFlag.CanEnter ) { - ((LayoutAnchorableItem)d).OnCanHideChanged(e); + using( _visibilityReentrantFlag.Enter() ) + { + if( Visibility == System.Windows.Visibility.Hidden ) + _anchorable.Hide( false ); + else if( Visibility == System.Windows.Visibility.Visible ) + _anchorable.Show(); + } } + } + + base.OnVisibilityChanged(); + } + + #endregion - /// - /// Provides derived classes an opportunity to handle changes to the CanHide property. - /// - protected virtual void OnCanHideChanged(DependencyPropertyChangedEventArgs e) + #region Private Methods + + private void _anchorable_IsVisibleChanged( object sender, EventArgs e ) + { + if( _anchorable != null && _anchorable.Root != null ) + { + if( _visibilityReentrantFlag.CanEnter ) { - if (_anchorable != null) - _anchorable.CanHide = (bool)e.NewValue; + using( _visibilityReentrantFlag.Enter() ) + { + if( _anchorable.IsVisible ) + Visibility = Visibility.Visible; + else + Visibility = Visibility.Hidden; + } } + } + } - #endregion - } + + + + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorablePaneControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorablePaneControl.cs index 62ae0ccf..3c725619 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorablePaneControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorablePaneControl.cs @@ -15,10 +15,6 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections.ObjectModel; using System.Windows.Controls; using System.Windows; using System.Windows.Data; @@ -26,63 +22,92 @@ using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorablePaneControl : TabControl, ILayoutControl//, ILogicalChildrenContainer + public class LayoutAnchorablePaneControl : TabControl, ILayoutControl//, ILogicalChildrenContainer + { + #region Members + + private LayoutAnchorablePane _model; + + #endregion + + #region Constructors + + static LayoutAnchorablePaneControl() { - static LayoutAnchorablePaneControl() - { - FocusableProperty.OverrideMetadata(typeof(LayoutAnchorablePaneControl), new FrameworkPropertyMetadata(false)); - } + FocusableProperty.OverrideMetadata( typeof( LayoutAnchorablePaneControl ), new FrameworkPropertyMetadata( false ) ); + } - public LayoutAnchorablePaneControl(LayoutAnchorablePane model) - { - if (model == null) - throw new ArgumentNullException("model"); + public LayoutAnchorablePaneControl( LayoutAnchorablePane model ) + { + if( model == null ) + throw new ArgumentNullException( "model" ); - _model = model; + _model = model; - SetBinding(ItemsSourceProperty, new Binding("Model.Children") { Source = this }); - SetBinding(FlowDirectionProperty, new Binding("Model.Root.Manager.FlowDirection") { Source = this }); + SetBinding( ItemsSourceProperty, new Binding( "Model.Children" ) { Source = this } ); + SetBinding( FlowDirectionProperty, new Binding( "Model.Root.Manager.FlowDirection" ) { Source = this } ); - this.LayoutUpdated += new EventHandler(OnLayoutUpdated); - } + this.LayoutUpdated += new EventHandler( OnLayoutUpdated ); + } - void OnLayoutUpdated(object sender, EventArgs e) - { - var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize; - modelWithAtcualSize.ActualWidth = ActualWidth; - modelWithAtcualSize.ActualHeight = ActualHeight; - } + #endregion - LayoutAnchorablePane _model; + #region Properties - public ILayoutElement Model - { - get { return _model; } - } + public ILayoutElement Model + { + get + { + return _model; + } + } - protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e) - { - _model.SelectedContent.IsActive = true; + #endregion - base.OnGotKeyboardFocus(e); - } + #region Overrides - protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) - { - base.OnMouseLeftButtonDown(e); + protected override void OnGotKeyboardFocus( System.Windows.Input.KeyboardFocusChangedEventArgs e ) + { + if( ( _model != null ) && ( _model.SelectedContent != null ) ) + { + _model.SelectedContent.IsActive = true; + } - if (!e.Handled && _model.SelectedContent != null) - _model.SelectedContent.IsActive = true; - } + base.OnGotKeyboardFocus( e ); + } - protected override void OnMouseRightButtonDown(System.Windows.Input.MouseButtonEventArgs e) - { - base.OnMouseRightButtonDown(e); + protected override void OnMouseLeftButtonDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseLeftButtonDown( e ); + + if( !e.Handled && ( _model != null ) && ( _model.SelectedContent != null ) ) + { + _model.SelectedContent.IsActive = true; + } + } + + protected override void OnMouseRightButtonDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseRightButtonDown( e ); - if (!e.Handled && _model.SelectedContent != null) - _model.SelectedContent.IsActive = true; + if( !e.Handled && ( _model != null ) && ( _model.SelectedContent != null ) ) + { + _model.SelectedContent.IsActive = true; + } + } + + + #endregion - } + #region Private Methods + private void OnLayoutUpdated( object sender, EventArgs e ) + { + var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize; + modelWithAtcualSize.ActualWidth = ActualWidth; + modelWithAtcualSize.ActualHeight = ActualHeight; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorablePaneGroupControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorablePaneGroupControl.cs index 0b7769bc..99269059 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorablePaneGroupControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorablePaneGroupControl.cs @@ -14,54 +14,60 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using Xceed.Wpf.AvalonDock.Layout; - namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorablePaneGroupControl : LayoutGridControl, ILayoutControl + public class LayoutAnchorablePaneGroupControl : LayoutGridControl, ILayoutControl + { + #region Members + + private LayoutAnchorablePaneGroup _model; + + #endregion + + #region Constructors + + internal LayoutAnchorablePaneGroupControl( LayoutAnchorablePaneGroup model ) + : base( model, model.Orientation ) { - internal LayoutAnchorablePaneGroupControl(LayoutAnchorablePaneGroup model) - : base(model, model.Orientation) - { - _model = model; - } + _model = model; + } + + #endregion - LayoutAnchorablePaneGroup _model; + #region Overrides - protected override void OnFixChildrenDockLengths() + protected override void OnFixChildrenDockLengths() + { + #region Setup DockWidth/Height for children + if( _model.Orientation == Orientation.Horizontal ) + { + for( int i = 0; i < _model.Children.Count; i++ ) { - #region Setup DockWidth/Height for children - if (_model.Orientation == Orientation.Horizontal) - { - for (int i = 0; i < _model.Children.Count; i++) - { - var childModel = _model.Children[i] as ILayoutPositionableElement; - if (!childModel.DockWidth.IsStar) - { - childModel.DockWidth = new GridLength(1.0, GridUnitType.Star); - } - } - } - else - { - for (int i = 0; i < _model.Children.Count; i++) - { - var childModel = _model.Children[i] as ILayoutPositionableElement; - if (!childModel.DockHeight.IsStar) - { - childModel.DockHeight = new GridLength(1.0, GridUnitType.Star); - } - } - } - #endregion + var childModel = _model.Children[ i ] as ILayoutPositionableElement; + if( !childModel.DockWidth.IsStar ) + { + childModel.DockWidth = new GridLength( 1.0, GridUnitType.Star ); + } } - + } + else + { + for( int i = 0; i < _model.Children.Count; i++ ) + { + var childModel = _model.Children[ i ] as ILayoutPositionableElement; + if( !childModel.DockHeight.IsStar ) + { + childModel.DockHeight = new GridLength( 1.0, GridUnitType.Star ); + } + } + } + #endregion } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableTabItem.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableTabItem.cs index 0e25dfd1..743e0265 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableTabItem.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAnchorableTabItem.cs @@ -14,187 +14,218 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; -using System.Collections.ObjectModel; using System.Windows.Controls; using System.Windows.Input; using Xceed.Wpf.AvalonDock.Layout; -using System.Reflection; -using System.Diagnostics; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAnchorableTabItem : Control - { - static LayoutAnchorableTabItem() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAnchorableTabItem), new FrameworkPropertyMetadata(typeof(LayoutAnchorableTabItem))); - } - - public LayoutAnchorableTabItem() - { - } - - - - #region Model - - /// - /// Model Dependency Property - /// - public static readonly DependencyProperty ModelProperty = - DependencyProperty.Register("Model", typeof(LayoutContent), typeof(LayoutAnchorableTabItem), - new FrameworkPropertyMetadata((LayoutContent)null, - new PropertyChangedCallback(OnModelChanged))); - - /// - /// Gets or sets the Model property. This dependency property - /// indicates model attached to the anchorable tab item. - /// - public LayoutContent Model - { - get { return (LayoutContent)GetValue(ModelProperty); } - set { SetValue(ModelProperty, value); } - } - - /// - /// Handles changes to the Model property. - /// - private static void OnModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutAnchorableTabItem)d).OnModelChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the Model property. - /// - protected virtual void OnModelChanged(DependencyPropertyChangedEventArgs e) - { - if (Model != null) - SetLayoutItem(Model.Root.Manager.GetLayoutItemFromModel(Model)); - else - SetLayoutItem(null); - //UpdateLogicalParent(); - } - - #endregion - - #region LayoutItem - - /// - /// LayoutItem Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey LayoutItemPropertyKey - = DependencyProperty.RegisterReadOnly("LayoutItem", typeof(LayoutItem), typeof(LayoutAnchorableTabItem), - new FrameworkPropertyMetadata((LayoutItem)null)); - - public static readonly DependencyProperty LayoutItemProperty - = LayoutItemPropertyKey.DependencyProperty; - - /// - /// Gets the LayoutItem property. This dependency property - /// indicates the LayoutItem attached to this tag item. - /// - public LayoutItem LayoutItem - { - get { return (LayoutItem)GetValue(LayoutItemProperty); } - } - - /// - /// Provides a secure method for setting the LayoutItem property. - /// This dependency property indicates the LayoutItem attached to this tag item. - /// - /// The new value for the property. - protected void SetLayoutItem(LayoutItem value) - { - SetValue(LayoutItemPropertyKey, value); - } - - #endregion - - bool _isMouseDown = false; - static LayoutAnchorableTabItem _draggingItem = null; - - internal static bool IsDraggingItem() - { - return _draggingItem != null; - } - - internal static LayoutAnchorableTabItem GetDraggingItem() - { - return _draggingItem; - } - internal static void ResetDraggingItem() - { - _draggingItem = null; - } - - protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) - { - base.OnMouseLeftButtonDown(e); - - _isMouseDown = true; - _draggingItem = this; - } - - protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e) - { - base.OnMouseMove(e); - - if (e.LeftButton != MouseButtonState.Pressed) - { - _isMouseDown = false; - _draggingItem = null; - } - } - - protected override void OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e) - { - _isMouseDown = false; - - base.OnMouseLeftButtonUp(e); - - Model.IsActive = true; - } - - protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e) - { - base.OnMouseLeave(e); - - if (_isMouseDown && e.LeftButton == MouseButtonState.Pressed) - { - _draggingItem = this; - } - - _isMouseDown = false; - } - - protected override void OnMouseEnter(MouseEventArgs e) - { - base.OnMouseEnter(e); - - if (_draggingItem != null && - _draggingItem != this && - e.LeftButton == MouseButtonState.Pressed) - { - //Trace.WriteLine("Dragging item from {0} to {1}", _draggingItem, this); - - var model = Model; - var container = model.Parent as ILayoutContainer; - var containerPane = model.Parent as ILayoutPane; - var childrenList = container.Children.ToList(); - containerPane.MoveChild(childrenList.IndexOf(_draggingItem.Model), childrenList.IndexOf(model)); - } - } - - protected override void OnPreviewGotKeyboardFocus(KeyboardFocusChangedEventArgs e) - { - base.OnPreviewGotKeyboardFocus(e); - - } + public class LayoutAnchorableTabItem : Control + { + #region Members + + private bool _isMouseDown = false; + private static LayoutAnchorableTabItem _draggingItem = null; + private static bool _cancelMouseLeave = false; + + #endregion + + #region Constructors + + static LayoutAnchorableTabItem() + { + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutAnchorableTabItem ), new FrameworkPropertyMetadata( typeof( LayoutAnchorableTabItem ) ) ); + } + + public LayoutAnchorableTabItem() + { + } + + #endregion + + #region Properties + + #region Model + + /// + /// Model Dependency Property + /// + public static readonly DependencyProperty ModelProperty = DependencyProperty.Register( "Model", typeof( LayoutContent ), typeof( LayoutAnchorableTabItem ), + new FrameworkPropertyMetadata( ( LayoutContent )null, new PropertyChangedCallback( OnModelChanged ) ) ); + + /// + /// Gets or sets the Model property. This dependency property + /// indicates model attached to the anchorable tab item. + /// + public LayoutContent Model + { + get + { + return ( LayoutContent )GetValue( ModelProperty ); + } + set + { + SetValue( ModelProperty, value ); + } + } + + /// + /// Handles changes to the Model property. + /// + private static void OnModelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutAnchorableTabItem )d ).OnModelChanged( e ); } + + /// + /// Provides derived classes an opportunity to handle changes to the Model property. + /// + protected virtual void OnModelChanged( DependencyPropertyChangedEventArgs e ) + { + if( Model != null ) + SetLayoutItem( Model.Root.Manager.GetLayoutItemFromModel( Model ) ); + else + SetLayoutItem( null ); + //UpdateLogicalParent(); + } + + #endregion + + #region LayoutItem + + /// + /// LayoutItem Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey LayoutItemPropertyKey = DependencyProperty.RegisterReadOnly( "LayoutItem", typeof( LayoutItem ), typeof( LayoutAnchorableTabItem ), + new FrameworkPropertyMetadata( ( LayoutItem )null ) ); + + public static readonly DependencyProperty LayoutItemProperty = LayoutItemPropertyKey.DependencyProperty; + + /// + /// Gets the LayoutItem property. This dependency property + /// indicates the LayoutItem attached to this tag item. + /// + public LayoutItem LayoutItem + { + get + { + return ( LayoutItem )GetValue( LayoutItemProperty ); + } + } + + /// + /// Provides a secure method for setting the LayoutItem property. + /// This dependency property indicates the LayoutItem attached to this tag item. + /// + /// The new value for the property. + protected void SetLayoutItem( LayoutItem value ) + { + SetValue( LayoutItemPropertyKey, value ); + } + + #endregion + + #endregion + + #region Overrides + protected override void OnMouseLeftButtonDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseLeftButtonDown( e ); + + _isMouseDown = true; + _draggingItem = this; + } + + protected override void OnMouseMove( System.Windows.Input.MouseEventArgs e ) + { + base.OnMouseMove( e ); + + if( e.LeftButton != MouseButtonState.Pressed ) + { + _isMouseDown = false; + _draggingItem = null; + } + else + { + _cancelMouseLeave = false; + } + } + + protected override void OnMouseLeftButtonUp( System.Windows.Input.MouseButtonEventArgs e ) + { + _isMouseDown = false; + + base.OnMouseLeftButtonUp( e ); + + Model.IsActive = true; + } + + protected override void OnMouseLeave( System.Windows.Input.MouseEventArgs e ) + { + base.OnMouseLeave( e ); + + if( _isMouseDown && e.LeftButton == MouseButtonState.Pressed ) + { + // drag the item if the mouse leave is not canceled. + // Mouse leave should be canceled when selecting a new tab to prevent automatic undock when Panel size is Auto. + _draggingItem = !_cancelMouseLeave ? this : null; + } + + _isMouseDown = false; + _cancelMouseLeave = false; + } + + protected override void OnMouseEnter( MouseEventArgs e ) + { + base.OnMouseEnter( e ); + + if( _draggingItem != this && + e.LeftButton == MouseButtonState.Pressed ) + { + var model = Model; + var container = model.Parent as ILayoutContainer; + var containerPane = model.Parent as ILayoutPane; + + if( ( containerPane is LayoutAnchorablePane ) && !( ( LayoutAnchorablePane )containerPane ).CanRepositionItems ) + return; + if( ( containerPane.Parent != null ) && ( containerPane.Parent is LayoutAnchorablePaneGroup ) && !( ( LayoutAnchorablePaneGroup )containerPane.Parent ).CanRepositionItems ) + return; + + var childrenList = container.Children.ToList(); + containerPane.MoveChild( childrenList.IndexOf( _draggingItem.Model ), childrenList.IndexOf( model ) ); + } + } + + protected override void OnPreviewGotKeyboardFocus( KeyboardFocusChangedEventArgs e ) + { + base.OnPreviewGotKeyboardFocus( e ); + + } + + #endregion + + #region Internal Methods + + internal static bool IsDraggingItem() + { + return _draggingItem != null; + } + + internal static LayoutAnchorableTabItem GetDraggingItem() + { + return _draggingItem; + } + internal static void ResetDraggingItem() + { + _draggingItem = null; + } + internal static void CancelMouseLeave() + { + _cancelMouseLeave = true; + } + + #endregion +} } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAutoHideWindowControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAutoHideWindowControl.cs index b5ab5f5c..f3004fb7 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAutoHideWindowControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutAutoHideWindowControl.cs @@ -15,9 +15,7 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Interop; using System.Windows.Controls; using System.Runtime.InteropServices; @@ -26,99 +24,147 @@ using System.Windows.Input; using System.Windows.Data; using System.Windows.Media; using Xceed.Wpf.AvalonDock.Layout; -using System.Diagnostics; -using System.Windows.Threading; -using System.ComponentModel; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutAutoHideWindowControl : HwndHost, ILayoutControl + public class LayoutAutoHideWindowControl : HwndHost, ILayoutControl + { + #region Members + + internal LayoutAnchorableControl _internalHost = null; + + private LayoutAnchorControl _anchor; + private LayoutAnchorable _model; + private HwndSource _internalHwndSource = null; + private IntPtr parentWindowHandle; + private bool _internalHost_ContentRendered = false; + private ContentPresenter _internalHostPresenter = new ContentPresenter(); + private Grid _internalGrid = null; + private AnchorSide _side; + private LayoutGridResizerControl _resizer = null; + private DockingManager _manager; + private Border _resizerGhost = null; + private Window _resizerWindowHost = null; + private Vector _initialStartPoint; + + #endregion + + #region Constructors + + static LayoutAutoHideWindowControl() { - static LayoutAutoHideWindowControl() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(typeof(LayoutAutoHideWindowControl))); - UIElement.FocusableProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(true)); - Control.IsTabStopProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(true)); - VisibilityProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(Visibility.Hidden)); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutAutoHideWindowControl ), new FrameworkPropertyMetadata( typeof( LayoutAutoHideWindowControl ) ) ); + UIElement.FocusableProperty.OverrideMetadata( typeof( LayoutAutoHideWindowControl ), new FrameworkPropertyMetadata( true ) ); + Control.IsTabStopProperty.OverrideMetadata( typeof( LayoutAutoHideWindowControl ), new FrameworkPropertyMetadata( true ) ); + VisibilityProperty.OverrideMetadata( typeof( LayoutAutoHideWindowControl ), new FrameworkPropertyMetadata( Visibility.Hidden ) ); + } - internal LayoutAutoHideWindowControl() - { - } + internal LayoutAutoHideWindowControl() + { + } - internal void Show(LayoutAnchorControl anchor) - { - if (_model != null) - throw new InvalidOperationException(); + #endregion - _anchor = anchor; - _model = anchor.Model as LayoutAnchorable; - _side = (anchor.Model.Parent.Parent as LayoutAnchorSide).Side; - _manager = _model.Root.Manager; - CreateInternalGrid(); + #region Properties - _model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged); + #region AnchorableStyle - Visibility = System.Windows.Visibility.Visible; - InvalidateMeasure(); - UpdateWindowPos(); - Trace.WriteLine("LayoutAutoHideWindowControl.Show()"); - } + /// + /// AnchorableStyle Dependency Property + /// + public static readonly DependencyProperty AnchorableStyleProperty = DependencyProperty.Register( "AnchorableStyle", typeof( Style ), typeof( LayoutAutoHideWindowControl ), + new FrameworkPropertyMetadata( ( Style )null ) ); - internal void Hide() - { - if (_model == null) - return; + /// + /// Gets or sets the AnchorableStyle property. This dependency property + /// indicates the style to apply to the LayoutAnchorableControl hosted in this auto hide window. + /// + public Style AnchorableStyle + { + get + { + return ( Style )GetValue( AnchorableStyleProperty ); + } + set + { + SetValue( AnchorableStyleProperty, value ); + } + } - _model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged); + #endregion - RemoveInternalGrid(); - _anchor = null; - _model = null; - _manager = null; - Visibility = System.Windows.Visibility.Hidden; + #region Background - Trace.WriteLine("LayoutAutoHideWindowControl.Hide()"); - } + /// + /// Background Dependency Property + /// + public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register( "Background", typeof( Brush ), typeof( LayoutAutoHideWindowControl ), + new FrameworkPropertyMetadata( ( Brush )null ) ); - LayoutAnchorControl _anchor; + /// + /// Gets or sets the Background property. This dependency property + /// indicates background of the autohide childwindow. + /// + public Brush Background + { + get + { + return ( Brush )GetValue( BackgroundProperty ); + } + set + { + SetValue( BackgroundProperty, value ); + } + } - LayoutAnchorable _model; + #endregion - public ILayoutElement Model - { - get { return _model; } - } + #region Model - HwndSource _internalHwndSource = null; - IntPtr parentWindowHandle; - protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent) - { - parentWindowHandle = hwndParent.Handle; - _internalHwndSource = new HwndSource(new HwndSourceParameters() - { - ParentWindow = hwndParent.Handle, - WindowStyle = Win32Helper.WS_CHILD | Win32Helper.WS_VISIBLE | Win32Helper.WS_CLIPSIBLINGS | Win32Helper.WS_CLIPCHILDREN, - Width = 0, - Height = 0, - }); - - _internalHost_ContentRendered = false; - _internalHwndSource.ContentRendered += _internalHwndSource_ContentRendered; - _internalHwndSource.RootVisual = _internalHostPresenter; - AddLogicalChild(_internalHostPresenter); - Win32Helper.BringWindowToTop(_internalHwndSource.Handle); - return new HandleRef(this, _internalHwndSource.Handle); - } + public ILayoutElement Model + { + get + { + return _model; + } + } - private bool _internalHost_ContentRendered = false; + #endregion - void _internalHwndSource_ContentRendered(object sender, EventArgs e) - { - _internalHost_ContentRendered = true; - } + #region Resizer + + internal bool IsResizing + { + get; + private set; + } + + #endregion + + #endregion + + #region Overrides + + protected override System.Runtime.InteropServices.HandleRef BuildWindowCore( System.Runtime.InteropServices.HandleRef hwndParent ) + { + parentWindowHandle = hwndParent.Handle; + _internalHwndSource = new HwndSource( new HwndSourceParameters() + { + ParentWindow = hwndParent.Handle, + WindowStyle = Win32Helper.WS_CHILD | Win32Helper.WS_VISIBLE | Win32Helper.WS_CLIPSIBLINGS | Win32Helper.WS_CLIPCHILDREN, + Width = 0, + Height = 0, + } ); + + _internalHost_ContentRendered = false; + _internalHwndSource.ContentRendered += _internalHwndSource_ContentRendered; + _internalHwndSource.RootVisual = _internalHostPresenter; + AddLogicalChild( _internalHostPresenter ); + Win32Helper.BringWindowToTop( _internalHwndSource.Handle ); + return new HandleRef( this, _internalHwndSource.Handle ); + } - protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { // Make sure that autohide windows always display on top of other Controls // (even Win32 control which WPF cannot normally overlay!) @@ -139,446 +185,410 @@ namespace Xceed.Wpf.AvalonDock.Controls return base.WndProc(hwnd, msg, wParam, lParam, ref handled); } - protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd) - { - if (_internalHwndSource != null) - { - _internalHwndSource.ContentRendered -= _internalHwndSource_ContentRendered; - _internalHwndSource.Dispose(); - _internalHwndSource = null; - } - } - - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - - - } - - ContentPresenter _internalHostPresenter = new ContentPresenter(); - Grid _internalGrid = null; - LayoutAnchorableControl _internalHost = null; - AnchorSide _side; - LayoutGridResizerControl _resizer = null; - DockingManager _manager; - - void _model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) - { - if (e.PropertyName == "IsAutoHidden") - { - if (!_model.IsAutoHidden) - { - _manager.HideAutoHideWindow(_anchor); - } - } - } - - void CreateInternalGrid() - { - _internalGrid = new Grid() { FlowDirection = System.Windows.FlowDirection.LeftToRight}; - _internalGrid.SetBinding(Grid.BackgroundProperty, new Binding("Background") { Source = this }); - - - _internalHost = new LayoutAnchorableControl() { Model = _model, Style = AnchorableStyle }; - _internalHost.SetBinding(FlowDirectionProperty, new Binding("Model.Root.Manager.FlowDirection") { Source = this }); - - KeyboardNavigation.SetTabNavigation(_internalGrid, KeyboardNavigationMode.Cycle); - - _resizer = new LayoutGridResizerControl(); - - _resizer.DragStarted += new System.Windows.Controls.Primitives.DragStartedEventHandler(OnResizerDragStarted); - _resizer.DragDelta += new System.Windows.Controls.Primitives.DragDeltaEventHandler(OnResizerDragDelta); - _resizer.DragCompleted += new System.Windows.Controls.Primitives.DragCompletedEventHandler(OnResizerDragCompleted); - - if (_side == AnchorSide.Right) - { - _internalGrid.ColumnDefinitions.Add(new ColumnDefinition(){ Width = new GridLength(_manager.GridSplitterWidth)}); - _internalGrid.ColumnDefinitions.Add(new ColumnDefinition(){ - Width = _model.AutoHideWidth == 0.0 ? new GridLength(_model.AutoHideMinWidth) : new GridLength(_model.AutoHideWidth, GridUnitType.Pixel)}); - - Grid.SetColumn(_resizer, 0); - Grid.SetColumn(_internalHost, 1); - - _resizer.Cursor = Cursors.SizeWE; - - HorizontalAlignment = System.Windows.HorizontalAlignment.Right; - VerticalAlignment = System.Windows.VerticalAlignment.Stretch; - } - else if (_side == AnchorSide.Left) - { - _internalGrid.ColumnDefinitions.Add(new ColumnDefinition() - { - Width = _model.AutoHideWidth == 0.0 ? new GridLength(_model.AutoHideMinWidth) : new GridLength(_model.AutoHideWidth, GridUnitType.Pixel), - }); - _internalGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(_manager.GridSplitterWidth) }); - - Grid.SetColumn(_internalHost, 0); - Grid.SetColumn(_resizer, 1); - - _resizer.Cursor = Cursors.SizeWE; - - HorizontalAlignment = System.Windows.HorizontalAlignment.Left; - VerticalAlignment = System.Windows.VerticalAlignment.Stretch; - } - else if (_side == AnchorSide.Top) - { - _internalGrid.RowDefinitions.Add(new RowDefinition() - { - Height = _model.AutoHideHeight == 0.0 ? new GridLength(_model.AutoHideMinHeight) : new GridLength(_model.AutoHideHeight, GridUnitType.Pixel), - }); - _internalGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(_manager.GridSplitterHeight) }); - - Grid.SetRow(_internalHost, 0); - Grid.SetRow(_resizer, 1); - - _resizer.Cursor = Cursors.SizeNS; - - VerticalAlignment = System.Windows.VerticalAlignment.Top; - HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch; + protected override void DestroyWindowCore( System.Runtime.InteropServices.HandleRef hwnd ) + { + if( _internalHwndSource != null ) + { + _internalHwndSource.ContentRendered -= _internalHwndSource_ContentRendered; + _internalHwndSource.Dispose(); + _internalHwndSource = null; + } + } - } - else if (_side == AnchorSide.Bottom) - { - _internalGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(_manager.GridSplitterHeight) }); - _internalGrid.RowDefinitions.Add(new RowDefinition() - { - Height = _model.AutoHideHeight == 0.0 ? new GridLength(_model.AutoHideMinHeight) : new GridLength(_model.AutoHideHeight, GridUnitType.Pixel), - }); + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + } - Grid.SetRow(_resizer, 0); - Grid.SetRow(_internalHost, 1); + protected override bool HasFocusWithinCore() + { + return false; + } - _resizer.Cursor = Cursors.SizeNS; + protected override System.Collections.IEnumerator LogicalChildren + { + get + { + if( _internalHostPresenter == null ) + return new UIElement[] { }.GetEnumerator(); + return new UIElement[] { _internalHostPresenter }.GetEnumerator(); + } + } - VerticalAlignment = System.Windows.VerticalAlignment.Bottom; - HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch; - } + protected override Size MeasureOverride( Size constraint ) + { + if( _internalHostPresenter == null ) + return base.MeasureOverride( constraint ); + _internalHostPresenter.Measure( constraint ); + //return base.MeasureOverride(constraint); + return _internalHostPresenter.DesiredSize; + } - _internalGrid.Children.Add(_resizer); - _internalGrid.Children.Add(_internalHost); - _internalHostPresenter.Content = _internalGrid; - } + protected override Size ArrangeOverride( Size finalSize ) + { + if( _internalHostPresenter == null ) + return base.ArrangeOverride( finalSize ); - void RemoveInternalGrid() - { - _resizer.DragStarted -= new System.Windows.Controls.Primitives.DragStartedEventHandler(OnResizerDragStarted); - _resizer.DragDelta -= new System.Windows.Controls.Primitives.DragDeltaEventHandler(OnResizerDragDelta); - _resizer.DragCompleted -= new System.Windows.Controls.Primitives.DragCompletedEventHandler(OnResizerDragCompleted); + _internalHostPresenter.Arrange( new Rect( finalSize ) ); + return base.ArrangeOverride( finalSize );// new Size(_internalHostPresenter.ActualWidth, _internalHostPresenter.ActualHeight); + } - _internalHostPresenter.Content = null; - } + #endregion + #region Internal Methods - protected override bool HasFocusWithinCore() - { - return false; - } + internal void Show( LayoutAnchorControl anchor ) + { + if( _model != null ) + throw new InvalidOperationException(); - #region Resizer + _anchor = anchor; + _model = anchor.Model as LayoutAnchorable; + _side = ( anchor.Model.Parent.Parent as LayoutAnchorSide ).Side; + _manager = _model.Root.Manager; + CreateInternalGrid(); - Border _resizerGhost = null; - Window _resizerWindowHost = null; - Vector _initialStartPoint; + _model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( _model_PropertyChanged ); - void ShowResizerOverlayWindow(LayoutGridResizerControl splitter) - { - _resizerGhost = new Border() - { - Background = splitter.BackgroundWhileDragging, - Opacity = splitter.OpacityWhileDragging - }; + Visibility = System.Windows.Visibility.Visible; + InvalidateMeasure(); + UpdateWindowPos(); + } - var areaElement = _manager.GetAutoHideAreaElement(); - var modelControlActualSize = this._internalHost.TransformActualSizeToAncestor(); + internal void Hide() + { + if( _model == null ) + return; - Point ptTopLeftScreen = areaElement.PointToScreenDPIWithoutFlowDirection(new Point()); + _model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler( _model_PropertyChanged ); - var managerSize = areaElement.TransformActualSizeToAncestor(); + RemoveInternalGrid(); + _anchor = null; + _model = null; + _manager = null; + Visibility = System.Windows.Visibility.Hidden; + } - Size windowSize; + internal bool IsWin32MouseOver + { + get + { + var ptMouse = new Win32Helper.Win32Point(); + if( !Win32Helper.GetCursorPos( ref ptMouse ) ) + return false; - if (_side == AnchorSide.Right || _side == AnchorSide.Left) - { - windowSize = new Size( - managerSize.Width - 25.0 + splitter.ActualWidth, - managerSize.Height); + Point location = this.PointToScreenDPI( new Point() ); - _resizerGhost.Width = splitter.ActualWidth; - _resizerGhost.Height = windowSize.Height; - ptTopLeftScreen.Offset(25, 0.0); - } - else - { - windowSize = new Size( - managerSize.Width, - managerSize.Height - _model.AutoHideMinHeight - 25.0 + splitter.ActualHeight); + Rect rectWindow = this.GetScreenArea(); + if( rectWindow.Contains( new Point( ptMouse.X, ptMouse.Y ) ) ) + return true; - _resizerGhost.Height = splitter.ActualHeight; - _resizerGhost.Width = windowSize.Width; - ptTopLeftScreen.Offset(0.0, 25.0); - } + var manager = Model.Root.Manager; + var anchor = manager.FindVisualChildren().Where( c => c.Model == Model ).FirstOrDefault(); - _initialStartPoint = splitter.PointToScreenDPIWithoutFlowDirection(new Point()) - ptTopLeftScreen; + if( anchor == null ) + return false; - if (_side == AnchorSide.Right || _side == AnchorSide.Left) - { - Canvas.SetLeft(_resizerGhost, _initialStartPoint.X); - } - else - { - Canvas.SetTop(_resizerGhost, _initialStartPoint.Y); - } + location = anchor.PointToScreenDPI( new Point() ); - Canvas panelHostResizer = new Canvas() - { - HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, - VerticalAlignment = System.Windows.VerticalAlignment.Stretch - }; + if( anchor.IsMouseOver ) + return true; - panelHostResizer.Children.Add(_resizerGhost); + return false; + } + } + #endregion - _resizerWindowHost = new Window() - { - ResizeMode = ResizeMode.NoResize, - WindowStyle = System.Windows.WindowStyle.None, - ShowInTaskbar = false, - AllowsTransparency = true, - Background = null, - Width = windowSize.Width, - Height = windowSize.Height, - Left = ptTopLeftScreen.X, - Top = ptTopLeftScreen.Y, - ShowActivated = false, - Owner = Window.GetWindow(this), - Content = panelHostResizer - }; - - _resizerWindowHost.Show(); - } + #region Private Methods - void HideResizerOverlayWindow() - { - if (_resizerWindowHost != null) - { - _resizerWindowHost.Close(); - _resizerWindowHost = null; - } - } + private void _internalHwndSource_ContentRendered( object sender, EventArgs e ) + { + _internalHost_ContentRendered = true; + } - internal bool IsResizing + private void _model_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e ) + { + if( e.PropertyName == "IsAutoHidden" ) + { + if( !_model.IsAutoHidden ) { - get; - private set; + _manager.HideAutoHideWindow( _anchor ); } + } + } - void OnResizerDragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) - { - LayoutGridResizerControl splitter = sender as LayoutGridResizerControl; - var rootVisual = this.FindVisualTreeRoot() as Visual; - - var trToWnd = TransformToAncestor(rootVisual); - Vector transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) - - trToWnd.Transform(new Point()); - - double delta; - if (_side == AnchorSide.Right || _side == AnchorSide.Left) - delta = Canvas.GetLeft(_resizerGhost) - _initialStartPoint.X; - else - delta = Canvas.GetTop(_resizerGhost) - _initialStartPoint.Y; - - if (_side == AnchorSide.Right) - { - if (_model.AutoHideWidth == 0.0) - _model.AutoHideWidth = _internalHost.ActualWidth - delta; - else - _model.AutoHideWidth -= delta; - - _internalGrid.ColumnDefinitions[1].Width = new GridLength(_model.AutoHideWidth, GridUnitType.Pixel); - } - else if (_side == AnchorSide.Left) - { - if (_model.AutoHideWidth == 0.0) - _model.AutoHideWidth = _internalHost.ActualWidth + delta; - else - _model.AutoHideWidth += delta; + private void CreateInternalGrid() + { + _internalGrid = new Grid() { FlowDirection = System.Windows.FlowDirection.LeftToRight }; + _internalGrid.SetBinding( Grid.BackgroundProperty, new Binding( "Background" ) { Source = this } ); - _internalGrid.ColumnDefinitions[0].Width = new GridLength(_model.AutoHideWidth, GridUnitType.Pixel); - } - else if (_side == AnchorSide.Top) - { - if (_model.AutoHideHeight == 0.0) - _model.AutoHideHeight = _internalHost.ActualHeight + delta; - else - _model.AutoHideHeight += delta; - _internalGrid.RowDefinitions[0].Height = new GridLength(_model.AutoHideHeight, GridUnitType.Pixel); - } - else if (_side == AnchorSide.Bottom) - { - if (_model.AutoHideHeight == 0.0) - _model.AutoHideHeight = _internalHost.ActualHeight - delta; - else - _model.AutoHideHeight -= delta; + _internalHost = new LayoutAnchorableControl() { Model = _model, Style = AnchorableStyle }; + _internalHost.SetBinding( FlowDirectionProperty, new Binding( "Model.Root.Manager.FlowDirection" ) { Source = this } ); - _internalGrid.RowDefinitions[1].Height = new GridLength(_model.AutoHideHeight, GridUnitType.Pixel); - } + KeyboardNavigation.SetTabNavigation( _internalGrid, KeyboardNavigationMode.Cycle ); - HideResizerOverlayWindow(); + _resizer = new LayoutGridResizerControl(); - IsResizing = false; - InvalidateMeasure(); - } + _resizer.DragStarted += new System.Windows.Controls.Primitives.DragStartedEventHandler( OnResizerDragStarted ); + _resizer.DragDelta += new System.Windows.Controls.Primitives.DragDeltaEventHandler( OnResizerDragDelta ); + _resizer.DragCompleted += new System.Windows.Controls.Primitives.DragCompletedEventHandler( OnResizerDragCompleted ); - void OnResizerDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) + if( _side == AnchorSide.Right ) + { + _internalGrid.ColumnDefinitions.Add( new ColumnDefinition() { Width = new GridLength( _manager.GridSplitterWidth ) } ); + _internalGrid.ColumnDefinitions.Add( new ColumnDefinition() { - LayoutGridResizerControl splitter = sender as LayoutGridResizerControl; - var rootVisual = this.FindVisualTreeRoot() as Visual; + Width = _model.AutoHideWidth == 0.0 ? new GridLength( _model.AutoHideMinWidth ) : new GridLength( _model.AutoHideWidth, GridUnitType.Pixel ) + } ); - var trToWnd = TransformToAncestor(rootVisual); - Vector transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) - - trToWnd.Transform(new Point()); + Grid.SetColumn( _resizer, 0 ); + Grid.SetColumn( _internalHost, 1 ); - if (_side == AnchorSide.Right || _side == AnchorSide.Left) - { - if (FrameworkElement.GetFlowDirection(_internalHost) == System.Windows.FlowDirection.RightToLeft) - transformedDelta.X = -transformedDelta.X; - Canvas.SetLeft(_resizerGhost, MathHelper.MinMax(_initialStartPoint.X + transformedDelta.X, 0.0, _resizerWindowHost.Width - _resizerGhost.Width)); - } - else - { - Canvas.SetTop(_resizerGhost, MathHelper.MinMax(_initialStartPoint.Y + transformedDelta.Y, 0.0, _resizerWindowHost.Height - _resizerGhost.Height)); - } - } + _resizer.Cursor = Cursors.SizeWE; - void OnResizerDragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) + HorizontalAlignment = System.Windows.HorizontalAlignment.Right; + VerticalAlignment = System.Windows.VerticalAlignment.Stretch; + } + else if( _side == AnchorSide.Left ) + { + _internalGrid.ColumnDefinitions.Add( new ColumnDefinition() { - var resizer = sender as LayoutGridResizerControl; - ShowResizerOverlayWindow(resizer); - IsResizing = true; - } - #endregion + Width = _model.AutoHideWidth == 0.0 ? new GridLength( _model.AutoHideMinWidth ) : new GridLength( _model.AutoHideWidth, GridUnitType.Pixel ), + } ); + _internalGrid.ColumnDefinitions.Add( new ColumnDefinition() { Width = new GridLength( _manager.GridSplitterWidth ) } ); - protected override System.Collections.IEnumerator LogicalChildren - { - get - { - if (_internalHostPresenter == null) - return new UIElement[] { }.GetEnumerator(); - return new UIElement[] { _internalHostPresenter }.GetEnumerator(); - } - } - - protected override Size MeasureOverride(Size constraint) - { - if (_internalHostPresenter == null) - return base.MeasureOverride(constraint); + Grid.SetColumn( _internalHost, 0 ); + Grid.SetColumn( _resizer, 1 ); - _internalHostPresenter.Measure(constraint); - //return base.MeasureOverride(constraint); - return _internalHostPresenter.DesiredSize; - } + _resizer.Cursor = Cursors.SizeWE; - protected override Size ArrangeOverride(Size finalSize) + HorizontalAlignment = System.Windows.HorizontalAlignment.Left; + VerticalAlignment = System.Windows.VerticalAlignment.Stretch; + } + else if( _side == AnchorSide.Top ) + { + _internalGrid.RowDefinitions.Add( new RowDefinition() { - if (_internalHostPresenter == null) - return base.ArrangeOverride(finalSize); + Height = _model.AutoHideHeight == 0.0 ? new GridLength( _model.AutoHideMinHeight ) : new GridLength( _model.AutoHideHeight, GridUnitType.Pixel ), + } ); + _internalGrid.RowDefinitions.Add( new RowDefinition() { Height = new GridLength( _manager.GridSplitterHeight ) } ); - _internalHostPresenter.Arrange(new Rect(finalSize)); - return base.ArrangeOverride(finalSize);// new Size(_internalHostPresenter.ActualWidth, _internalHostPresenter.ActualHeight); - } + Grid.SetRow( _internalHost, 0 ); + Grid.SetRow( _resizer, 1 ); - WeakReference _lastFocusedElement = null; - protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) - { - base.OnGotKeyboardFocus(e); - if (!e.Handled && _internalHostPresenter != null) - { - if (e.NewFocus == _internalHostPresenter) - { - var elementToFocus = _lastFocusedElement.GetValueOrDefault(); - if (elementToFocus != null) - Keyboard.Focus(elementToFocus); - e.Handled = true; - } - else - _lastFocusedElement = new WeakReference(e.NewFocus); - } - } - - #region Background - - /// - /// Background Dependency Property - /// - public static readonly DependencyProperty BackgroundProperty = - DependencyProperty.Register("Background", typeof(Brush), typeof(LayoutAutoHideWindowControl), - new FrameworkPropertyMetadata((Brush)null)); - - /// - /// Gets or sets the Background property. This dependency property - /// indicates background of the autohide childwindow. - /// - public Brush Background - { - get { return (Brush)GetValue(BackgroundProperty); } - set { SetValue(BackgroundProperty, value); } - } + _resizer.Cursor = Cursors.SizeNS; - #endregion + VerticalAlignment = System.Windows.VerticalAlignment.Top; + HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch; - internal bool IsWin32MouseOver + } + else if( _side == AnchorSide.Bottom ) + { + _internalGrid.RowDefinitions.Add( new RowDefinition() { Height = new GridLength( _manager.GridSplitterHeight ) } ); + _internalGrid.RowDefinitions.Add( new RowDefinition() { - get - { - var ptMouse = new Win32Helper.Win32Point(); - if (!Win32Helper.GetCursorPos(ref ptMouse)) - return false; + Height = _model.AutoHideHeight == 0.0 ? new GridLength( _model.AutoHideMinHeight ) : new GridLength( _model.AutoHideHeight, GridUnitType.Pixel ), + } ); - Point location = this.PointToScreenDPI(new Point()); + Grid.SetRow( _resizer, 0 ); + Grid.SetRow( _internalHost, 1 ); - Rect rectWindow = this.GetScreenArea(); - if (rectWindow.Contains(new Point(ptMouse.X, ptMouse.Y))) - return true; + _resizer.Cursor = Cursors.SizeNS; - var manager = Model.Root.Manager; - var anchor = manager.FindVisualChildren().Where(c => c.Model == Model).FirstOrDefault(); + VerticalAlignment = System.Windows.VerticalAlignment.Bottom; + HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch; + } - if (anchor == null) - return false; - location = anchor.PointToScreenDPI(new Point()); - - if (anchor.IsMouseOver) - return true; + _internalGrid.Children.Add( _resizer ); + _internalGrid.Children.Add( _internalHost ); + _internalHostPresenter.Content = _internalGrid; + } - return false; - } - } + private void RemoveInternalGrid() + { + _resizer.DragStarted -= new System.Windows.Controls.Primitives.DragStartedEventHandler( OnResizerDragStarted ); + _resizer.DragDelta -= new System.Windows.Controls.Primitives.DragDeltaEventHandler( OnResizerDragDelta ); + _resizer.DragCompleted -= new System.Windows.Controls.Primitives.DragCompletedEventHandler( OnResizerDragCompleted ); - #region AnchorableStyle + _internalHostPresenter.Content = null; + } - /// - /// AnchorableStyle Dependency Property - /// - public static readonly DependencyProperty AnchorableStyleProperty = - DependencyProperty.Register("AnchorableStyle", typeof(Style), typeof(LayoutAutoHideWindowControl), - new FrameworkPropertyMetadata((Style)null)); + private void ShowResizerOverlayWindow( LayoutGridResizerControl splitter ) + { + _resizerGhost = new Border() + { + Background = splitter.BackgroundWhileDragging, + Opacity = splitter.OpacityWhileDragging + }; + + var areaElement = _manager.GetAutoHideAreaElement(); + var modelControlActualSize = this._internalHost.TransformActualSizeToAncestor(); + + Point ptTopLeftScreen = areaElement.PointToScreenDPIWithoutFlowDirection( new Point() ); + + var managerSize = areaElement.TransformActualSizeToAncestor(); + + Size windowSize; + + if( _side == AnchorSide.Right || _side == AnchorSide.Left ) + { + windowSize = new Size( + managerSize.Width - 25.0 + splitter.ActualWidth, + managerSize.Height ); + + _resizerGhost.Width = splitter.ActualWidth; + _resizerGhost.Height = windowSize.Height; + ptTopLeftScreen.Offset( 25, 0.0 ); + } + else + { + windowSize = new Size( + managerSize.Width, + managerSize.Height - _model.AutoHideMinHeight - 25.0 + splitter.ActualHeight ); + + _resizerGhost.Height = splitter.ActualHeight; + _resizerGhost.Width = windowSize.Width; + ptTopLeftScreen.Offset( 0.0, 25.0 ); + } + + _initialStartPoint = splitter.PointToScreenDPIWithoutFlowDirection( new Point() ) - ptTopLeftScreen; + + if( _side == AnchorSide.Right || _side == AnchorSide.Left ) + { + Canvas.SetLeft( _resizerGhost, _initialStartPoint.X ); + } + else + { + Canvas.SetTop( _resizerGhost, _initialStartPoint.Y ); + } + + Canvas panelHostResizer = new Canvas() + { + HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, + VerticalAlignment = System.Windows.VerticalAlignment.Stretch + }; + + panelHostResizer.Children.Add( _resizerGhost ); + + + _resizerWindowHost = new Window() + { + ResizeMode = ResizeMode.NoResize, + WindowStyle = System.Windows.WindowStyle.None, + ShowInTaskbar = false, + AllowsTransparency = true, + Background = null, + Width = windowSize.Width, + Height = windowSize.Height, + Left = ptTopLeftScreen.X, + Top = ptTopLeftScreen.Y, + ShowActivated = false, + Owner = Window.GetWindow( this ), + Content = panelHostResizer + }; + + _resizerWindowHost.Show(); + } - /// - /// Gets or sets the AnchorableStyle property. This dependency property - /// indicates the style to apply to the LayoutAnchorableControl hosted in this auto hide window. - /// - public Style AnchorableStyle - { - get { return (Style)GetValue(AnchorableStyleProperty); } - set { SetValue(AnchorableStyleProperty, value); } - } + private void HideResizerOverlayWindow() + { + if( _resizerWindowHost != null ) + { + _resizerWindowHost.Close(); + _resizerWindowHost = null; + } + } - #endregion + private void OnResizerDragCompleted( object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e ) + { + LayoutGridResizerControl splitter = sender as LayoutGridResizerControl; + var rootVisual = this.FindVisualTreeRoot() as Visual; + + var trToWnd = TransformToAncestor( rootVisual ); + Vector transformedDelta = trToWnd.Transform( new Point( e.HorizontalChange, e.VerticalChange ) ) - + trToWnd.Transform( new Point() ); + + double delta; + if( _side == AnchorSide.Right || _side == AnchorSide.Left ) + delta = Canvas.GetLeft( _resizerGhost ) - _initialStartPoint.X; + else + delta = Canvas.GetTop( _resizerGhost ) - _initialStartPoint.Y; + + if( _side == AnchorSide.Right ) + { + if( _model.AutoHideWidth == 0.0 ) + _model.AutoHideWidth = _internalHost.ActualWidth - delta; + else + _model.AutoHideWidth -= delta; + + _internalGrid.ColumnDefinitions[ 1 ].Width = new GridLength( _model.AutoHideWidth, GridUnitType.Pixel ); + } + else if( _side == AnchorSide.Left ) + { + if( _model.AutoHideWidth == 0.0 ) + _model.AutoHideWidth = _internalHost.ActualWidth + delta; + else + _model.AutoHideWidth += delta; + + _internalGrid.ColumnDefinitions[ 0 ].Width = new GridLength( _model.AutoHideWidth, GridUnitType.Pixel ); + } + else if( _side == AnchorSide.Top ) + { + if( _model.AutoHideHeight == 0.0 ) + _model.AutoHideHeight = _internalHost.ActualHeight + delta; + else + _model.AutoHideHeight += delta; + + _internalGrid.RowDefinitions[ 0 ].Height = new GridLength( _model.AutoHideHeight, GridUnitType.Pixel ); + } + else if( _side == AnchorSide.Bottom ) + { + if( _model.AutoHideHeight == 0.0 ) + _model.AutoHideHeight = _internalHost.ActualHeight - delta; + else + _model.AutoHideHeight -= delta; + + _internalGrid.RowDefinitions[ 1 ].Height = new GridLength( _model.AutoHideHeight, GridUnitType.Pixel ); + } + + HideResizerOverlayWindow(); + + IsResizing = false; + InvalidateMeasure(); + } + private void OnResizerDragDelta( object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e ) + { + LayoutGridResizerControl splitter = sender as LayoutGridResizerControl; + var rootVisual = this.FindVisualTreeRoot() as Visual; + + var trToWnd = TransformToAncestor( rootVisual ); + Vector transformedDelta = trToWnd.Transform( new Point( e.HorizontalChange, e.VerticalChange ) ) - + trToWnd.Transform( new Point() ); + + if( _side == AnchorSide.Right || _side == AnchorSide.Left ) + { + if( FrameworkElement.GetFlowDirection( _internalHost ) == System.Windows.FlowDirection.RightToLeft ) + transformedDelta.X = -transformedDelta.X; + Canvas.SetLeft( _resizerGhost, MathHelper.MinMax( _initialStartPoint.X + transformedDelta.X, 0.0, _resizerWindowHost.Width - _resizerGhost.Width ) ); + } + else + { + Canvas.SetTop( _resizerGhost, MathHelper.MinMax( _initialStartPoint.Y + transformedDelta.Y, 0.0, _resizerWindowHost.Height - _resizerGhost.Height ) ); + } + } + private void OnResizerDragStarted( object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e ) + { + var resizer = sender as LayoutGridResizerControl; + ShowResizerOverlayWindow( resizer ); + IsResizing = true; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentControl.cs index e48d8ac1..b2e4a37f 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentControl.cs @@ -14,118 +14,170 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.ComponentModel; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutDocumentControl : Control + public class LayoutDocumentControl : Control + { + #region Constructors + + static LayoutDocumentControl() { - static LayoutDocumentControl() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutDocumentControl), new FrameworkPropertyMetadata(typeof(LayoutDocumentControl))); - FocusableProperty.OverrideMetadata(typeof(LayoutDocumentControl), new FrameworkPropertyMetadata(false)); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutDocumentControl ), new FrameworkPropertyMetadata( typeof( LayoutDocumentControl ) ) ); + FocusableProperty.OverrideMetadata( typeof( LayoutDocumentControl ), new FrameworkPropertyMetadata( true ) ); + } - public LayoutDocumentControl() - { - //SetBinding(FlowDirectionProperty, new Binding("Model.Root.Manager.FlowDirection") { Source = this }); + #endregion - } + #region Properties + #region Model - #region Model + /// + /// Model Dependency Property + /// + public static readonly DependencyProperty ModelProperty = DependencyProperty.Register( "Model", typeof( LayoutContent ), typeof( LayoutDocumentControl ), + new FrameworkPropertyMetadata( null, OnModelChanged ) ); - /// - /// Model Dependency Property - /// - public static readonly DependencyProperty ModelProperty = - DependencyProperty.Register("Model", typeof(LayoutContent), typeof(LayoutDocumentControl), - new FrameworkPropertyMetadata((LayoutContent)null, - new PropertyChangedCallback(OnModelChanged))); + /// + /// Gets or sets the Model property. This dependency property + /// indicates the model attached to this view. + /// + public LayoutContent Model + { + get + { + return ( LayoutContent )GetValue( ModelProperty ); + } + set + { + SetValue( ModelProperty, value ); + } + } - /// - /// Gets or sets the Model property. This dependency property - /// indicates the model attached to this view. - /// - public LayoutContent Model - { - get { return (LayoutContent)GetValue(ModelProperty); } - set { SetValue(ModelProperty, value); } - } + /// + /// Handles changes to the Model property. + /// + private static void OnModelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutDocumentControl )d ).OnModelChanged( e ); + } - /// - /// Handles changes to the Model property. - /// - private static void OnModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutDocumentControl)d).OnModelChanged(e); - } + /// + /// Provides derived classes an opportunity to handle changes to the Model property. + /// + protected virtual void OnModelChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.OldValue != null ) + { + ( ( LayoutContent )e.OldValue ).PropertyChanged -= Model_PropertyChanged; + } + + if( Model != null ) + { + Model.PropertyChanged += Model_PropertyChanged; + SetLayoutItem( Model.Root.Manager.GetLayoutItemFromModel( Model ) ); + } + else + { + SetLayoutItem( null ); + } + } - /// - /// Provides derived classes an opportunity to handle changes to the Model property. - /// - protected virtual void OnModelChanged(DependencyPropertyChangedEventArgs e) + private void Model_PropertyChanged( object sender, PropertyChangedEventArgs e ) + { + if( e.PropertyName == "IsEnabled" ) + { + if( Model != null ) { - if (Model != null) - SetLayoutItem(Model.Root.Manager.GetLayoutItemFromModel(Model)); - else - SetLayoutItem(null); + IsEnabled = Model.IsEnabled; + if( !IsEnabled && Model.IsActive ) + { + if( ( Model.Parent != null ) && ( Model.Parent is LayoutDocumentPane ) ) + { + ( ( LayoutDocumentPane )Model.Parent ).SetNextSelectedIndex(); + } + } } - #endregion + } + } - #region LayoutItem + #endregion - /// - /// LayoutItem Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey LayoutItemPropertyKey - = DependencyProperty.RegisterReadOnly("LayoutItem", typeof(LayoutItem), typeof(LayoutDocumentControl), - new FrameworkPropertyMetadata((LayoutItem)null)); + #region LayoutItem - public static readonly DependencyProperty LayoutItemProperty - = LayoutItemPropertyKey.DependencyProperty; + /// + /// LayoutItem Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey LayoutItemPropertyKey = DependencyProperty.RegisterReadOnly( "LayoutItem", typeof( LayoutItem ), typeof( LayoutDocumentControl ), + new FrameworkPropertyMetadata(( LayoutItem )null ) ); - /// - /// Gets the LayoutItem property. This dependency property - /// indicates the LayoutItem attached to this tag item. - /// - public LayoutItem LayoutItem - { - get { return (LayoutItem)GetValue(LayoutItemProperty); } - } + public static readonly DependencyProperty LayoutItemProperty = LayoutItemPropertyKey.DependencyProperty; - /// - /// Provides a secure method for setting the LayoutItem property. - /// This dependency property indicates the LayoutItem attached to this tag item. - /// - /// The new value for the property. - protected void SetLayoutItem(LayoutItem value) - { - SetValue(LayoutItemPropertyKey, value); - } + /// + /// Gets the LayoutItem property. This dependency property + /// indicates the LayoutItem attached to this tag item. + /// + public LayoutItem LayoutItem + { + get + { + return ( LayoutItem )GetValue( LayoutItemProperty ); + } + } - #endregion + /// + /// Provides a secure method for setting the LayoutItem property. + /// This dependency property indicates the LayoutItem attached to this tag item. + /// + /// The new value for the property. + protected void SetLayoutItem( LayoutItem value ) + { + SetValue( LayoutItemPropertyKey, value ); + } - protected override void OnPreviewGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e) - { - if (Model != null) - Model.IsActive = true; - base.OnPreviewGotKeyboardFocus(e); - } + #endregion + #endregion + #region Overrides + + protected override void OnPreviewGotKeyboardFocus( KeyboardFocusChangedEventArgs e ) + { + this.SetIsActive(); + base.OnPreviewGotKeyboardFocus( e ); + } + + protected override void OnMouseLeftButtonDown( MouseButtonEventArgs e ) + { + this.SetIsActive(); + base.OnMouseLeftButtonDown( e ); } + + protected override void OnMouseRightButtonDown( MouseButtonEventArgs e ) + { + this.SetIsActive(); + base.OnMouseLeftButtonDown( e ); + } + + + #endregion + + #region Private Methods + + private void SetIsActive() + { + if( this.Model != null ) + { + this.Model.IsActive = true; + } + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs index 3042d9a9..77a2f258 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs @@ -15,129 +15,148 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Data; using Xceed.Wpf.AvalonDock.Layout; using System.Windows; using System.Windows.Controls.Primitives; -using System.Windows.Media; using Microsoft.Windows.Shell; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutDocumentFloatingWindowControl : LayoutFloatingWindowControl + public class LayoutDocumentFloatingWindowControl : LayoutFloatingWindowControl + { + #region Members + + private LayoutDocumentFloatingWindow _model; + + #endregion + + #region Constructors + + static LayoutDocumentFloatingWindowControl() + { + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutDocumentFloatingWindowControl ), new FrameworkPropertyMetadata( typeof( LayoutDocumentFloatingWindowControl ) ) ); + } + + internal LayoutDocumentFloatingWindowControl( LayoutDocumentFloatingWindow model ) + : base( model ) + { + _model = model; + UpdateThemeResources(); + } + + #endregion + + #region Properties + + public LayoutItem RootDocumentLayoutItem + { + get + { + return _model.Root.Manager.GetLayoutItemFromModel( _model.RootDocument ); + } + } + + #endregion + + #region Overrides + + public override ILayoutElement Model + { + get + { + return _model; + } + } + + protected override void OnInitialized( EventArgs e ) + { + base.OnInitialized( e ); + + if( _model.RootDocument == null ) + { + InternalClose(); + } + else + { + var manager = _model.Root.Manager; + + Content = manager.CreateUIElementForModel( _model.RootDocument ); + + _model.RootDocumentChanged += new EventHandler( _model_RootDocumentChanged ); + } + } + + protected override IntPtr FilterMessage( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled ) { - static LayoutDocumentFloatingWindowControl() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutDocumentFloatingWindowControl), new FrameworkPropertyMetadata(typeof(LayoutDocumentFloatingWindowControl))); - } - - internal LayoutDocumentFloatingWindowControl(LayoutDocumentFloatingWindow model) - :base(model) - { - _model = model; - } - - - LayoutDocumentFloatingWindow _model; - - public override ILayoutElement Model - { - get { return _model; } - } - - public LayoutItem RootDocumentLayoutItem - { - get { return _model.Root.Manager.GetLayoutItemFromModel(_model.RootDocument); } - } - - protected override void OnInitialized(EventArgs e) - { - base.OnInitialized(e); - - if (_model.RootDocument == null) - { - InternalClose(); - } + switch( msg ) + { + case Win32Helper.WM_NCLBUTTONDOWN: //Left button down on title -> start dragging over docking manager + if( wParam.ToInt32() == Win32Helper.HT_CAPTION ) + { + if( _model.RootDocument != null ) + _model.RootDocument.IsActive = true; + } + break; + case Win32Helper.WM_NCRBUTTONUP: + if( wParam.ToInt32() == Win32Helper.HT_CAPTION ) + { + if( OpenContextMenu() ) + handled = true; + if( _model.Root.Manager.ShowSystemMenu ) + WindowChrome.GetWindowChrome( this ).ShowSystemMenu = !handled; else - { - var manager = _model.Root.Manager; - - Content = manager.CreateUIElementForModel(_model.RootDocument); - - _model.RootDocumentChanged += new EventHandler(_model_RootDocumentChanged); - } - } - - void _model_RootDocumentChanged(object sender, EventArgs e) - { - if (_model.RootDocument == null) - { - InternalClose(); - } - } - - protected override IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) - { - switch (msg) - { - case Win32Helper.WM_NCLBUTTONDOWN: //Left button down on title -> start dragging over docking manager - if (wParam.ToInt32() == Win32Helper.HT_CAPTION) - { - if (_model.RootDocument != null) - _model.RootDocument.IsActive = true; - } - break; - case Win32Helper.WM_NCRBUTTONUP: - if (wParam.ToInt32() == Win32Helper.HT_CAPTION) - { - if (OpenContextMenu()) - handled = true; - if (_model.Root.Manager.ShowSystemMenu) - WindowChrome.GetWindowChrome(this).ShowSystemMenu = !handled; - else - WindowChrome.GetWindowChrome(this).ShowSystemMenu = false; - } - break; - - } - - return base.FilterMessage(hwnd, msg, wParam, lParam, ref handled); - } - - bool OpenContextMenu() - { - var ctxMenu = _model.Root.Manager.DocumentContextMenu; - if (ctxMenu != null && RootDocumentLayoutItem != null) - { - ctxMenu.PlacementTarget = null; - ctxMenu.Placement = PlacementMode.MousePoint; - ctxMenu.DataContext = RootDocumentLayoutItem; - ctxMenu.IsOpen = true; - return true; - } - - return false; - } - - - protected override void OnClosed(EventArgs e) - { - var root = Model.Root; - root.Manager.RemoveFloatingWindow(this); - root.CollectGarbage(); - - base.OnClosed(e); - - if (!CloseInitiatedByUser) - { - root.FloatingWindows.Remove(_model); - } - - _model.RootDocumentChanged -= new EventHandler(_model_RootDocumentChanged); - } + WindowChrome.GetWindowChrome( this ).ShowSystemMenu = false; + } + break; + + } + return base.FilterMessage( hwnd, msg, wParam, lParam, ref handled ); } + + protected override void OnClosed( EventArgs e ) + { + var root = Model.Root; + root.Manager.RemoveFloatingWindow( this ); + root.CollectGarbage(); + + base.OnClosed( e ); + + if( !CloseInitiatedByUser ) + { + root.FloatingWindows.Remove( _model ); + } + + _model.RootDocumentChanged -= new EventHandler( _model_RootDocumentChanged ); + } + + #endregion + + #region Private Methods + + private void _model_RootDocumentChanged( object sender, EventArgs e ) + { + if( _model.RootDocument == null ) + { + InternalClose(); + } + } + + private bool OpenContextMenu() + { + var ctxMenu = _model.Root.Manager.DocumentContextMenu; + if( ctxMenu != null && RootDocumentLayoutItem != null ) + { + ctxMenu.PlacementTarget = null; + ctxMenu.Placement = PlacementMode.MousePoint; + ctxMenu.DataContext = RootDocumentLayoutItem; + ctxMenu.IsOpen = true; + return true; + } + + return false; + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentItem.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentItem.cs index 142426f0..7bcbba96 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentItem.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentItem.cs @@ -14,77 +14,130 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using Xceed.Wpf.AvalonDock.Layout; using System.Windows; +using Xceed.Wpf.AvalonDock.Commands; +using System.Windows.Input; +using System.Windows.Data; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutDocumentItem : LayoutItem + public class LayoutDocumentItem : LayoutItem + { + #region Members + + private LayoutDocument _document; + + #endregion + + #region Constructors + + internal LayoutDocumentItem() { - LayoutDocument _document; - internal LayoutDocumentItem() - { + } - } + #endregion - internal override void Attach(LayoutContent model) - { - _document = model as LayoutDocument; - base.Attach(model); - } + #region Properties - protected override void Close() - { - var dockingManager = _document.Root.Manager; - dockingManager._ExecuteCloseCommand(_document); - } + #region Description - #region Description - - /// - /// Description Dependency Property - /// - public static readonly DependencyProperty DescriptionProperty = - DependencyProperty.Register("Description", typeof(string), typeof(LayoutDocumentItem), - new FrameworkPropertyMetadata((string)null, - new PropertyChangedCallback(OnDescriptionChanged))); - - /// - /// Gets or sets the Description property. This dependency property - /// indicates the description to display for the document item. - /// - public string Description - { - get { return (string)GetValue(DescriptionProperty); } - set { SetValue(DescriptionProperty, value); } - } + /// + /// Description Dependency Property + /// + public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register( "Description", typeof( string ), typeof( LayoutDocumentItem ), + new FrameworkPropertyMetadata( ( string )null, new PropertyChangedCallback( OnDescriptionChanged ) ) ); - /// - /// Handles changes to the Description property. - /// - private static void OnDescriptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutDocumentItem)d).OnDescriptionChanged(e); - } + /// + /// Gets or sets the Description property. This dependency property + /// indicates the description to display for the document item. + /// + public string Description + { + get + { + return ( string )GetValue( DescriptionProperty ); + } + set + { + SetValue( DescriptionProperty, value ); + } + } - /// - /// Provides derived classes an opportunity to handle changes to the Description property. - /// - protected virtual void OnDescriptionChanged(DependencyPropertyChangedEventArgs e) - { - _document.Description = (string)e.NewValue; - } + /// + /// Handles changes to the Description property. + /// + private static void OnDescriptionChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutDocumentItem )d ).OnDescriptionChanged( e ); + } - #endregion + /// + /// Provides derived classes an opportunity to handle changes to the Description property. + /// + protected virtual void OnDescriptionChanged( DependencyPropertyChangedEventArgs e ) + { + _document.Description = ( string )e.NewValue; + } + + #endregion - internal override void Detach() + #endregion + + #region Overrides + + protected override void Close() + { + if( ( _document.Root != null ) && ( _document.Root.Manager != null ) ) + { + var dockingManager = _document.Root.Manager; + dockingManager._ExecuteCloseCommand( _document ); + } + } + + protected override void OnVisibilityChanged() + { + if( (_document != null) && (_document.Root != null) ) + { + _document.IsVisible = ( this.Visibility == Visibility.Visible ); + + if( _document.Parent is LayoutDocumentPane ) { - _document = null; - base.Detach(); + ( ( LayoutDocumentPane )_document.Parent ).ComputeVisibility(); } + } + + base.OnVisibilityChanged(); + } + + + + + + + + internal override void Attach( LayoutContent model ) + { + _document = model as LayoutDocument; + base.Attach( model ); + } + + internal override void Detach() + { + _document = null; + base.Detach(); } + + #endregion + + #region Private Methods + + + + + + + +#endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentPaneControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentPaneControl.cs index f6aebc4d..74827cbc 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentPaneControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentPaneControl.cs @@ -16,94 +16,102 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; -using System.Collections.ObjectModel; using System.Windows.Controls; using System.Windows.Data; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutDocumentPaneControl : TabControl, ILayoutControl//, ILogicalChildrenContainer + public class LayoutDocumentPaneControl : TabControl, ILayoutControl//, ILogicalChildrenContainer + { + #region Members + + private List _logicalChildren = new List(); + private LayoutDocumentPane _model; + + #endregion + + #region Constructors + + static LayoutDocumentPaneControl() { - static LayoutDocumentPaneControl() - { - FocusableProperty.OverrideMetadata(typeof(LayoutDocumentPaneControl), new FrameworkPropertyMetadata(false)); - } + FocusableProperty.OverrideMetadata( typeof( LayoutDocumentPaneControl ), new FrameworkPropertyMetadata( false ) ); + } + internal LayoutDocumentPaneControl( LayoutDocumentPane model ) + { + if( model == null ) + throw new ArgumentNullException( "model" ); - internal LayoutDocumentPaneControl(LayoutDocumentPane model) - { - if (model == null) - throw new ArgumentNullException("model"); + _model = model; + SetBinding( ItemsSourceProperty, new Binding( "Model.Children" ) { Source = this } ); + SetBinding( FlowDirectionProperty, new Binding( "Model.Root.Manager.FlowDirection" ) { Source = this } ); - _model = model; - SetBinding(ItemsSourceProperty, new Binding("Model.Children") { Source = this }); - SetBinding(FlowDirectionProperty, new Binding("Model.Root.Manager.FlowDirection") { Source = this }); + this.LayoutUpdated += new EventHandler( OnLayoutUpdated ); + } - this.LayoutUpdated += new EventHandler(OnLayoutUpdated); - } + #endregion - void OnLayoutUpdated(object sender, EventArgs e) - { - var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize; - modelWithAtcualSize.ActualWidth = ActualWidth; - modelWithAtcualSize.ActualHeight = ActualHeight; - } + #region Properties - protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e) - { - base.OnGotKeyboardFocus(e); - System.Diagnostics.Trace.WriteLine( string.Format( "OnGotKeyboardFocus({0}, {1})", e.Source, e.NewFocus ) ); + public ILayoutElement Model + { + get + { + return _model; + } + } + #endregion - //if (_model.SelectedContent != null) - // _model.SelectedContent.IsActive = true; + #region Overrides - } + protected override System.Collections.IEnumerator LogicalChildren + { + get + { + return _logicalChildren.GetEnumerator(); + } + } - protected override void OnSelectionChanged(SelectionChangedEventArgs e) - { - base.OnSelectionChanged(e); + protected override void OnSelectionChanged( SelectionChangedEventArgs e ) + { + base.OnSelectionChanged( e ); - if (_model.SelectedContent != null) - _model.SelectedContent.IsActive = true; - } + if( _model.SelectedContent != null ) + _model.SelectedContent.IsActive = true; + } - List _logicalChildren = new List(); + protected override void OnMouseLeftButtonDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseLeftButtonDown( e ); - protected override System.Collections.IEnumerator LogicalChildren - { - get - { - return _logicalChildren.GetEnumerator(); - } - } + if( !e.Handled && _model.SelectedContent != null ) + _model.SelectedContent.IsActive = true; + } - LayoutDocumentPane _model; + protected override void OnMouseRightButtonDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseRightButtonDown( e ); - public ILayoutElement Model - { - get { return _model; } - } + if( !e.Handled && _model.SelectedContent != null ) + _model.SelectedContent.IsActive = true; - protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) - { - base.OnMouseLeftButtonDown(e); + } - if (!e.Handled && _model.SelectedContent != null) - _model.SelectedContent.IsActive = true; - } - protected override void OnMouseRightButtonDown(System.Windows.Input.MouseButtonEventArgs e) - { - base.OnMouseRightButtonDown(e); + #endregion - if (!e.Handled && _model.SelectedContent != null) - _model.SelectedContent.IsActive = true; + #region Private Methods - } + private void OnLayoutUpdated( object sender, EventArgs e ) + { + var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize; + modelWithAtcualSize.ActualWidth = ActualWidth; + modelWithAtcualSize.ActualHeight = ActualHeight; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentPaneGroupControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentPaneGroupControl.cs index e9b368f5..17d577fb 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentPaneGroupControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentPaneGroupControl.cs @@ -14,53 +14,60 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutDocumentPaneGroupControl : LayoutGridControl, ILayoutControl + public class LayoutDocumentPaneGroupControl : LayoutGridControl, ILayoutControl + { + #region Members + + private LayoutDocumentPaneGroup _model; + + #endregion + + #region Constructors + + internal LayoutDocumentPaneGroupControl( LayoutDocumentPaneGroup model ) + : base( model, model.Orientation ) { - internal LayoutDocumentPaneGroupControl(LayoutDocumentPaneGroup model) - :base(model, model.Orientation) - { - _model = model; - } + _model = model; + } - LayoutDocumentPaneGroup _model; + #endregion - protected override void OnFixChildrenDockLengths() + #region Overrides + + protected override void OnFixChildrenDockLengths() + { + #region Setup DockWidth/Height for children + if( _model.Orientation == Orientation.Horizontal ) + { + for( int i = 0; i < _model.Children.Count; i++ ) { - #region Setup DockWidth/Height for children - if (_model.Orientation == Orientation.Horizontal) - { - for (int i = 0; i < _model.Children.Count; i++) - { - var childModel = _model.Children[i] as ILayoutPositionableElement; - if (!childModel.DockWidth.IsStar) - { - childModel.DockWidth = new GridLength(1.0, GridUnitType.Star); - } - } - } - else - { - for (int i = 0; i < _model.Children.Count; i++) - { - var childModel = _model.Children[i] as ILayoutPositionableElement; - if (!childModel.DockHeight.IsStar) - { - childModel.DockHeight = new GridLength(1.0, GridUnitType.Star); - } - } - } - #endregion + var childModel = _model.Children[ i ] as ILayoutPositionableElement; + if( !childModel.DockWidth.IsStar ) + { + childModel.DockWidth = new GridLength( 1.0, GridUnitType.Star ); + } } - + } + else + { + for( int i = 0; i < _model.Children.Count; i++ ) + { + var childModel = _model.Children[ i ] as ILayoutPositionableElement; + if( !childModel.DockHeight.IsStar ) + { + childModel.DockHeight = new GridLength( 1.0, GridUnitType.Star ); + } + } + } + #endregion } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentTabItem.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentTabItem.cs index e22098c7..951d2c1e 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentTabItem.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutDocumentTabItem.cs @@ -17,212 +17,249 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using Xceed.Wpf.AvalonDock.Layout; -using System.Diagnostics; -using System.Windows.Media; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutDocumentTabItem : Control + public class LayoutDocumentTabItem : Control + { + #region Members + + private List _otherTabsScreenArea = null; + private List _otherTabs = null; + private Rect _parentDocumentTabPanelScreenArea; + private DocumentPaneTabPanel _parentDocumentTabPanel; + private bool _isMouseDown = false; + private Point _mouseDownPoint; + + #endregion + + #region Contructors + + static LayoutDocumentTabItem() { - static LayoutDocumentTabItem() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutDocumentTabItem), new FrameworkPropertyMetadata(typeof(LayoutDocumentTabItem))); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutDocumentTabItem ), new FrameworkPropertyMetadata( typeof( LayoutDocumentTabItem ) ) ); + } - public LayoutDocumentTabItem() - { - } + public LayoutDocumentTabItem() + { + } - #region Model - - /// - /// Model Dependency Property - /// - public static readonly DependencyProperty ModelProperty = - DependencyProperty.Register("Model", typeof(LayoutContent), typeof(LayoutDocumentTabItem), - new FrameworkPropertyMetadata((LayoutContent)null, - new PropertyChangedCallback(OnModelChanged))); - - /// - /// Gets or sets the Model property. This dependency property - /// indicates the layout content model attached to the tab item. - /// - public LayoutContent Model - { - get { return (LayoutContent)GetValue(ModelProperty); } - set { SetValue(ModelProperty, value); } - } + #endregion - /// - /// Handles changes to the Model property. - /// - private static void OnModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutDocumentTabItem)d).OnModelChanged(e); - } + #region Properties + #region Model - /// - /// Provides derived classes an opportunity to handle changes to the Model property. - /// - protected virtual void OnModelChanged(DependencyPropertyChangedEventArgs e) - { - if (Model != null) - SetLayoutItem(Model.Root.Manager.GetLayoutItemFromModel(Model)); - else - SetLayoutItem(null); - //UpdateLogicalParent(); - } + /// + /// Model Dependency Property + /// + public static readonly DependencyProperty ModelProperty = DependencyProperty.Register( "Model", typeof( LayoutContent ), typeof( LayoutDocumentTabItem ), + new FrameworkPropertyMetadata( ( LayoutContent )null, new PropertyChangedCallback( OnModelChanged ) ) ); - #endregion + /// + /// Gets or sets the Model property. This dependency property + /// indicates the layout content model attached to the tab item. + /// + public LayoutContent Model + { + get + { + return ( LayoutContent )GetValue( ModelProperty ); + } + set + { + SetValue( ModelProperty, value ); + } + } - #region LayoutItem + /// + /// Handles changes to the Model property. + /// + private static void OnModelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutDocumentTabItem )d ).OnModelChanged( e ); + } - /// - /// LayoutItem Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey LayoutItemPropertyKey - = DependencyProperty.RegisterReadOnly("LayoutItem", typeof(LayoutItem), typeof(LayoutDocumentTabItem), - new FrameworkPropertyMetadata((LayoutItem)null)); - public static readonly DependencyProperty LayoutItemProperty - = LayoutItemPropertyKey.DependencyProperty; + /// + /// Provides derived classes an opportunity to handle changes to the Model property. + /// + protected virtual void OnModelChanged( DependencyPropertyChangedEventArgs e ) + { + if( Model != null ) + SetLayoutItem( Model.Root.Manager.GetLayoutItemFromModel( Model ) ); + else + SetLayoutItem( null ); + //UpdateLogicalParent(); + } - /// - /// Gets the LayoutItem property. This dependency property - /// indicates the LayoutItem attached to this tag item. - /// - public LayoutItem LayoutItem - { - get { return (LayoutItem)GetValue(LayoutItemProperty); } - } + #endregion - /// - /// Provides a secure method for setting the LayoutItem property. - /// This dependency property indicates the LayoutItem attached to this tag item. - /// - /// The new value for the property. - protected void SetLayoutItem(LayoutItem value) - { - SetValue(LayoutItemPropertyKey, value); - } + #region LayoutItem - #endregion + /// + /// LayoutItem Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey LayoutItemPropertyKey = DependencyProperty.RegisterReadOnly( "LayoutItem", typeof( LayoutItem ), typeof( LayoutDocumentTabItem ), + new FrameworkPropertyMetadata( ( LayoutItem )null ) ); - List _otherTabsScreenArea = null; - List _otherTabs = null; - Rect _parentDocumentTabPanelScreenArea; - DocumentPaneTabPanel _parentDocumentTabPanel; - bool _isMouseDown = false; - Point _mouseDownPoint; + public static readonly DependencyProperty LayoutItemProperty = LayoutItemPropertyKey.DependencyProperty; - void UpdateDragDetails() - { - _parentDocumentTabPanel = this.FindLogicalAncestor(); - _parentDocumentTabPanelScreenArea = _parentDocumentTabPanel.GetScreenArea(); - _otherTabs = _parentDocumentTabPanel.Children.Cast().Where(ch => - ch.Visibility != System.Windows.Visibility.Collapsed).ToList(); - Rect currentTabScreenArea = this.FindLogicalAncestor().GetScreenArea(); - _otherTabsScreenArea = _otherTabs.Select(ti => - { - var screenArea = ti.GetScreenArea(); - return new Rect(screenArea.Left, screenArea.Top, currentTabScreenArea.Width, screenArea.Height); - }).ToList(); - } + /// + /// Gets the LayoutItem property. This dependency property + /// indicates the LayoutItem attached to this tag item. + /// + public LayoutItem LayoutItem + { + get + { + return ( LayoutItem )GetValue( LayoutItemProperty ); + } + } - protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) - { - base.OnMouseLeftButtonDown(e); + /// + /// Provides a secure method for setting the LayoutItem property. + /// This dependency property indicates the LayoutItem attached to this tag item. + /// + /// The new value for the property. + protected void SetLayoutItem( LayoutItem value ) + { + SetValue( LayoutItemPropertyKey, value ); + } - Model.IsActive = true; + #endregion - if (e.ClickCount == 1) - { - _mouseDownPoint = e.GetPosition(this); - _isMouseDown = true; - } - } + #endregion - protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e) - { - base.OnMouseMove(e); - - if (_isMouseDown) - { - Point ptMouseMove = e.GetPosition(this); - - if (Math.Abs(ptMouseMove.X - _mouseDownPoint.X) > SystemParameters.MinimumHorizontalDragDistance || - Math.Abs(ptMouseMove.Y - _mouseDownPoint.Y) > SystemParameters.MinimumVerticalDragDistance) - { - UpdateDragDetails(); - CaptureMouse(); - _isMouseDown = false; - } - } - - if (IsMouseCaptured) - { - var mousePosInScreenCoord = this.PointToScreenDPI(e.GetPosition(this)); - if (!_parentDocumentTabPanelScreenArea.Contains(mousePosInScreenCoord)) - { - ReleaseMouseCapture(); - var manager = Model.Root.Manager; - manager.StartDraggingFloatingWindowForContent(Model); - } - else - { - int indexOfTabItemWithMouseOver = _otherTabsScreenArea.FindIndex(r => r.Contains(mousePosInScreenCoord)); - if (indexOfTabItemWithMouseOver >= 0) - { - var targetModel = _otherTabs[indexOfTabItemWithMouseOver].Content as LayoutContent; - var container = Model.Parent as ILayoutContainer; - var containerPane = Model.Parent as ILayoutPane; - var childrenList = container.Children.ToList(); - containerPane.MoveChild(childrenList.IndexOf(Model), childrenList.IndexOf(targetModel)); - Model.IsActive = true; - _parentDocumentTabPanel.UpdateLayout(); - UpdateDragDetails(); - } - } - } + #region Overrides - } + protected override void OnMouseLeftButtonDown( System.Windows.Input.MouseButtonEventArgs e ) + { + base.OnMouseLeftButtonDown( e ); - protected override void OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e) - { - if (IsMouseCaptured) - ReleaseMouseCapture(); - _isMouseDown = false; + Model.IsActive = true; - base.OnMouseLeftButtonUp(e); - } + if( e.ClickCount == 1 ) + { + _mouseDownPoint = e.GetPosition( this ); + _isMouseDown = true; + } + } + + protected override void OnMouseMove( System.Windows.Input.MouseEventArgs e ) + { + base.OnMouseMove( e ); + + if( _isMouseDown ) + { + Point ptMouseMove = e.GetPosition( this ); - protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e) + if( Math.Abs( ptMouseMove.X - _mouseDownPoint.X ) > SystemParameters.MinimumHorizontalDragDistance || + Math.Abs( ptMouseMove.Y - _mouseDownPoint.Y ) > SystemParameters.MinimumVerticalDragDistance ) { - base.OnMouseLeave(e); - _isMouseDown = false; + this.UpdateDragDetails(); + this.CaptureMouse(); + _isMouseDown = false; } + } - protected override void OnMouseEnter(MouseEventArgs e) + if( this.IsMouseCaptured ) + { + var mousePosInScreenCoord = this.PointToScreenDPI( e.GetPosition( this ) ); + if( !_parentDocumentTabPanelScreenArea.Contains( mousePosInScreenCoord ) ) { - base.OnMouseEnter(e); - _isMouseDown = false; + this.StartDraggingFloatingWindowForContent(); } - - protected override void OnMouseDown(MouseButtonEventArgs e) + else { - if (e.ChangedButton == MouseButton.Middle) - { - if (LayoutItem.CloseCommand.CanExecute(null)) - LayoutItem.CloseCommand.Execute(null); - } - - base.OnMouseDown(e); + int indexOfTabItemWithMouseOver = _otherTabsScreenArea.FindIndex( r => r.Contains( mousePosInScreenCoord ) ); + if( indexOfTabItemWithMouseOver >= 0 ) + { + var targetModel = _otherTabs[ indexOfTabItemWithMouseOver ].Content as LayoutContent; + var container = this.Model.Parent as ILayoutContainer; + var containerPane = this.Model.Parent as ILayoutPane; + + if( ( containerPane is LayoutDocumentPane ) && !( ( LayoutDocumentPane )containerPane ).CanRepositionItems ) + return; + if( ( containerPane.Parent != null ) && ( containerPane.Parent is LayoutDocumentPaneGroup ) && !( ( LayoutDocumentPaneGroup )containerPane.Parent ).CanRepositionItems ) + return; + + var childrenList = container.Children.ToList(); + containerPane.MoveChild( childrenList.IndexOf( Model ), childrenList.IndexOf( targetModel ) ); + this.Model.IsActive = true; + _parentDocumentTabPanel.UpdateLayout(); + this.UpdateDragDetails(); + } } + } + } + + protected override void OnMouseLeftButtonUp( System.Windows.Input.MouseButtonEventArgs e ) + { + if( IsMouseCaptured ) + ReleaseMouseCapture(); + _isMouseDown = false; + + base.OnMouseLeftButtonUp( e ); + } + + protected override void OnMouseLeave( System.Windows.Input.MouseEventArgs e ) + { + base.OnMouseLeave( e ); + _isMouseDown = false; } + + protected override void OnMouseEnter( MouseEventArgs e ) + { + base.OnMouseEnter( e ); + _isMouseDown = false; + } + + protected override void OnMouseDown( MouseButtonEventArgs e ) + { + if( e.ChangedButton == MouseButton.Middle ) + { + if( LayoutItem.CloseCommand.CanExecute( null ) ) + LayoutItem.CloseCommand.Execute( null ); + } + + base.OnMouseDown( e ); + } + + #endregion + + #region Private Methods + + private void UpdateDragDetails() + { + _parentDocumentTabPanel = this.FindLogicalAncestor(); + _parentDocumentTabPanelScreenArea = _parentDocumentTabPanel.GetScreenArea(); + _otherTabs = _parentDocumentTabPanel.Children.Cast().Where( ch => + ch.Visibility != System.Windows.Visibility.Collapsed ).ToList(); + Rect currentTabScreenArea = this.FindLogicalAncestor().GetScreenArea(); + _otherTabsScreenArea = _otherTabs.Select( ti => + { + var screenArea = ti.GetScreenArea(); + return new Rect( screenArea.Left, screenArea.Top, currentTabScreenArea.Width, screenArea.Height ); + } ).ToList(); + } + + private void StartDraggingFloatingWindowForContent() + { + this.ReleaseMouseCapture(); + + if( this.Model is LayoutAnchorable ) + { + ( ( LayoutAnchorable )this.Model ).ResetCanCloseInternal(); + } + var manager = this.Model.Root.Manager; + manager.StartDraggingFloatingWindowForContent( this.Model ); + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutFloatingWindowControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutFloatingWindowControl.cs index e1aca30d..f77c3590 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutFloatingWindowControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutFloatingWindowControl.cs @@ -15,9 +15,7 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Runtime.InteropServices; using System.Windows.Interop; @@ -26,493 +24,567 @@ using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; using Xceed.Wpf.AvalonDock.Layout; -using System.Diagnostics; using System.Windows.Documents; using Xceed.Wpf.AvalonDock.Themes; namespace Xceed.Wpf.AvalonDock.Controls { - public abstract class LayoutFloatingWindowControl : Window, ILayoutControl - { - static LayoutFloatingWindowControl() - { - LayoutFloatingWindowControl.ContentProperty.OverrideMetadata(typeof(LayoutFloatingWindowControl), new FrameworkPropertyMetadata(null, null, new CoerceValueCallback(CoerceContentValue))); - AllowsTransparencyProperty.OverrideMetadata(typeof(LayoutFloatingWindowControl), new FrameworkPropertyMetadata(false)); - ShowInTaskbarProperty.OverrideMetadata(typeof(LayoutFloatingWindowControl), new FrameworkPropertyMetadata(false)); - } - - static object CoerceContentValue(DependencyObject sender, object content) - { - return new FloatingWindowContentHost(sender as LayoutFloatingWindowControl) { Content = content as UIElement }; - } - - protected class FloatingWindowContentHost : HwndHost - { - LayoutFloatingWindowControl _owner; - public FloatingWindowContentHost(LayoutFloatingWindowControl owner) - { - _owner = owner; - var manager = _owner.Model.Root.Manager; - } - - - HwndSource _wpfContentHost = null; - Border _rootPresenter = null; - DockingManager _manager = null; - - protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent) - { - _wpfContentHost = new HwndSource(new HwndSourceParameters() - { - ParentWindow = hwndParent.Handle, - WindowStyle = Win32Helper.WS_CHILD | Win32Helper.WS_VISIBLE | Win32Helper.WS_CLIPSIBLINGS | Win32Helper.WS_CLIPCHILDREN, - Width = 1, - Height = 1 - }); - - _rootPresenter = new Border() { Child = new AdornerDecorator() { Child = Content }, Focusable = true }; - _rootPresenter.SetBinding(Border.BackgroundProperty, new Binding("Background") { Source = _owner }); - _wpfContentHost.RootVisual = _rootPresenter; - _wpfContentHost.SizeToContent = SizeToContent.Manual; - _manager = _owner.Model.Root.Manager; - _manager.InternalAddLogicalChild(_rootPresenter); - - return new HandleRef(this, _wpfContentHost.Handle); - } - - - protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) - { - Trace.WriteLine("FloatingWindowContentHost.GotKeyboardFocus"); - base.OnGotKeyboardFocus(e); - } - protected override void DestroyWindowCore(HandleRef hwnd) - { - _manager.InternalRemoveLogicalChild(_rootPresenter); - if (_wpfContentHost != null) - { - _wpfContentHost.Dispose(); - _wpfContentHost = null; - } - } - protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) - { - switch (msg) - { - case Win32Helper.WM_SETFOCUS: - Trace.WriteLine("FloatingWindowContentHost.WM_SETFOCUS"); - break; - case Win32Helper.WM_KILLFOCUS: - Trace.WriteLine("FloatingWindowContentHost.WM_KILLFOCUS"); - break; - } - return base.WndProc(hwnd, msg, wParam, lParam, ref handled); - } - - public Visual RootVisual - { - get { return _rootPresenter; } - } - - protected override Size MeasureOverride(Size constraint) - { - if (Content == null) - return base.MeasureOverride(constraint); - - Content.Measure(constraint); - return Content.DesiredSize; - } - - #region Content - - /// - /// Content Dependency Property - /// - public static readonly DependencyProperty ContentProperty = - DependencyProperty.Register("Content", typeof(UIElement), typeof(FloatingWindowContentHost), - new FrameworkPropertyMetadata((UIElement)null, - new PropertyChangedCallback(OnContentChanged))); - - /// - /// Gets or sets the Content property. This dependency property - /// indicates .... - /// - public UIElement Content - { - get { return (UIElement)GetValue(ContentProperty); } - set { SetValue(ContentProperty, value); } - } - - /// - /// Handles changes to the Content property. - /// - private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((FloatingWindowContentHost)d).OnContentChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the Content property. - /// - protected virtual void OnContentChanged(DependencyPropertyChangedEventArgs e) - { - if (_rootPresenter != null) - _rootPresenter.Child = Content; - } - - #endregion - } - - ILayoutElement _model; - - protected LayoutFloatingWindowControl(ILayoutElement model) - { - this.Loaded += new RoutedEventHandler(OnLoaded); - this.Unloaded += new RoutedEventHandler(OnUnloaded); - _model = model; - UpdateThemeResources(); - } - - internal virtual void UpdateThemeResources(Theme oldTheme = null) - { + public abstract class LayoutFloatingWindowControl : Window, ILayoutControl + { + #region Members + + private ResourceDictionary currentThemeResourceDictionary; // = null + private bool _isInternalChange; //false + private ILayoutElement _model; + private bool _attachDrag = false; + private HwndSource _hwndSrc; + private HwndSourceHook _hwndSrcHook; + private DragService _dragService = null; + private bool _internalCloseFlag = false; + + #endregion + + #region Constructors + + static LayoutFloatingWindowControl() + { + LayoutFloatingWindowControl.ContentProperty.OverrideMetadata( typeof( LayoutFloatingWindowControl ), new FrameworkPropertyMetadata( null, null, new CoerceValueCallback( CoerceContentValue ) ) ); + AllowsTransparencyProperty.OverrideMetadata( typeof( LayoutFloatingWindowControl ), new FrameworkPropertyMetadata( false ) ); + ShowInTaskbarProperty.OverrideMetadata( typeof( LayoutFloatingWindowControl ), new FrameworkPropertyMetadata( false ) ); + } + + protected LayoutFloatingWindowControl( ILayoutElement model ) + { + this.Loaded += new RoutedEventHandler( OnLoaded ); + this.Unloaded += new RoutedEventHandler( OnUnloaded ); + _model = model; + } + + #endregion + + #region Properties + + #region Model + + public abstract ILayoutElement Model + { + get; + } + + #endregion + + #region IsDragging + + /// + /// IsDragging Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey IsDraggingPropertyKey = DependencyProperty.RegisterReadOnly( "IsDragging", typeof( bool ), typeof( LayoutFloatingWindowControl ), + new FrameworkPropertyMetadata( ( bool )false, new PropertyChangedCallback( OnIsDraggingChanged ) ) ); + + public static readonly DependencyProperty IsDraggingProperty = IsDraggingPropertyKey.DependencyProperty; + + /// + /// Gets the IsDragging property. This dependency property + /// indicates that this floating window is being dragged. + /// + public bool IsDragging + { + get + { + return ( bool )GetValue( IsDraggingProperty ); + } + } + + /// + /// Provides a secure method for setting the IsDragging property. + /// This dependency property indicates that this floating window is being dragged. + /// + /// The new value for the property. + protected void SetIsDragging( bool value ) + { + SetValue( IsDraggingPropertyKey, value ); + } + + /// + /// Handles changes to the IsDragging property. + /// + private static void OnIsDraggingChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutFloatingWindowControl )d ).OnIsDraggingChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the IsDragging property. + /// + protected virtual void OnIsDraggingChanged( DependencyPropertyChangedEventArgs e ) + { + if( ( bool )e.NewValue ) + { + CaptureMouse(); + } + else + { + ReleaseMouseCapture(); + } + } + + #endregion + + #region CloseInitiatedByUser + + protected bool CloseInitiatedByUser + { + get + { + return !_internalCloseFlag; + } + } + + #endregion + + #region KeepContentVisibleOnClose + + internal bool KeepContentVisibleOnClose + { + get; + set; + } + + #endregion + + #region IsMaximized + + /// + /// IsMaximized Dependency Property + /// + public static readonly DependencyProperty IsMaximizedProperty = DependencyProperty.Register( "IsMaximized", typeof( bool ), typeof( LayoutFloatingWindowControl ), + new FrameworkPropertyMetadata( ( bool )false ) ); + + /// + /// Gets/sets the IsMaximized property. This dependency property + /// indicates if the window is maximized. + /// + public bool IsMaximized + { + get + { + return ( bool )GetValue( IsMaximizedProperty ); + } + private set + { + SetValue( IsMaximizedProperty, value ); + UpdatePositionAndSizeOfPanes(); + } + } + + /// + /// Provides a secure method for setting the IsMaximized property. + /// This dependency property indicates if the window is maximized. + /// + /// The new value for the property. + + protected override void OnStateChanged( EventArgs e ) + { + if( !_isInternalChange ) + { + if( WindowState == WindowState.Maximized ) + { + UpdateMaximizedState( true ); + } + else + { + WindowState = IsMaximized ? WindowState.Maximized : WindowState.Normal; + } + } + + base.OnStateChanged( e ); + } + + #endregion + + #endregion + + #region Overrides + + protected override void OnClosed( EventArgs e ) + { + if( Content != null ) + { + var host = Content as FloatingWindowContentHost; + host.Dispose(); + + if( _hwndSrc != null ) + { + _hwndSrc.RemoveHook( _hwndSrcHook ); + _hwndSrc.Dispose(); + _hwndSrc = null; + } + } + + base.OnClosed( e ); + } + + protected override void OnInitialized( EventArgs e ) + { + CommandBindings.Add( new CommandBinding( Microsoft.Windows.Shell.SystemCommands.CloseWindowCommand, + new ExecutedRoutedEventHandler( ( s, args ) => Microsoft.Windows.Shell.SystemCommands.CloseWindow( ( Window )args.Parameter ) ) ) ); + CommandBindings.Add( new CommandBinding( Microsoft.Windows.Shell.SystemCommands.MaximizeWindowCommand, + new ExecutedRoutedEventHandler( ( s, args ) => Microsoft.Windows.Shell.SystemCommands.MaximizeWindow( ( Window )args.Parameter ) ) ) ); + CommandBindings.Add( new CommandBinding( Microsoft.Windows.Shell.SystemCommands.MinimizeWindowCommand, + new ExecutedRoutedEventHandler( ( s, args ) => Microsoft.Windows.Shell.SystemCommands.MinimizeWindow( ( Window )args.Parameter ) ) ) ); + CommandBindings.Add( new CommandBinding( Microsoft.Windows.Shell.SystemCommands.RestoreWindowCommand, + new ExecutedRoutedEventHandler( ( s, args ) => Microsoft.Windows.Shell.SystemCommands.RestoreWindow( ( Window )args.Parameter ) ) ) ); + //Debug.Assert(this.Owner != null); + base.OnInitialized( e ); + } + + + #endregion + + #region Internal Methods + + internal virtual void UpdateThemeResources( Theme oldTheme = null ) + { if (Application.Current != null) return; - if (oldTheme != null) - { - var resourceDictionaryToRemove = - Resources.MergedDictionaries.FirstOrDefault(r => r.Source == oldTheme.GetResourceUri()); - if (resourceDictionaryToRemove != null) - Resources.MergedDictionaries.Remove( - resourceDictionaryToRemove); - } - - var manager = _model.Root.Manager; - if (manager.Theme != null) - { - Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = manager.Theme.GetResourceUri() }); - } - } - - protected override void OnClosed(EventArgs e) - { - if (Content != null) - { - var host = Content as FloatingWindowContentHost; - host.Dispose(); - - if (_hwndSrc != null) - { - _hwndSrc.RemoveHook(_hwndSrcHook); - _hwndSrc.Dispose(); - _hwndSrc = null; - } - } - - base.OnClosed(e); - } - - bool _attachDrag = false; - internal void AttachDrag(bool onActivated = true) - { - if (onActivated) - { - _attachDrag = true; - this.Activated += new EventHandler(OnActivated); - } - else - { - IntPtr windowHandle = new WindowInteropHelper(this).Handle; - IntPtr lParam = new IntPtr(((int)Left & (int)0xFFFF) | (((int)Top) << 16)); - Win32Helper.SendMessage(windowHandle, Win32Helper.WM_NCLBUTTONDOWN, new IntPtr(Win32Helper.HT_CAPTION), lParam); - } - } - - HwndSource _hwndSrc; - HwndSourceHook _hwndSrcHook; - - void OnLoaded(object sender, RoutedEventArgs e) - { - this.Loaded -= new RoutedEventHandler(OnLoaded); - - this.SetParentToMainWindowOf(Model.Root.Manager); - - - _hwndSrc = HwndSource.FromDependencyObject(this) as HwndSource; - _hwndSrcHook = new HwndSourceHook(FilterMessage); - _hwndSrc.AddHook(_hwndSrcHook); - } - - void OnUnloaded(object sender, RoutedEventArgs e) - { - this.Unloaded -= new RoutedEventHandler(OnUnloaded); - - if (_hwndSrc != null) - { - _hwndSrc.RemoveHook(_hwndSrcHook); - _hwndSrc.Dispose(); - _hwndSrc = null; - } - } - - void OnActivated(object sender, EventArgs e) - { - this.Activated -= new EventHandler(OnActivated); - - if (_attachDrag && Mouse.LeftButton == MouseButtonState.Pressed) - { - IntPtr windowHandle = new WindowInteropHelper(this).Handle; - var mousePosition = this.PointToScreenDPI(Mouse.GetPosition(this)); - var clientArea = Win32Helper.GetClientRect(windowHandle); - var windowArea = Win32Helper.GetWindowRect(windowHandle); - - Left = mousePosition.X - windowArea.Width / 2.0; - Top = mousePosition.Y - (windowArea.Height - clientArea.Height) / 2.0; - _attachDrag = false; - - IntPtr lParam = new IntPtr(((int)mousePosition.X & (int)0xFFFF) | (((int)mousePosition.Y) << 16)); - Win32Helper.SendMessage(windowHandle, Win32Helper.WM_NCLBUTTONDOWN, new IntPtr(Win32Helper.HT_CAPTION), lParam); - } - } - - - protected override void OnInitialized(EventArgs e) - { - CommandBindings.Add(new CommandBinding(Microsoft.Windows.Shell.SystemCommands.CloseWindowCommand, - new ExecutedRoutedEventHandler((s, args) => Microsoft.Windows.Shell.SystemCommands.CloseWindow((Window)args.Parameter)))); - CommandBindings.Add(new CommandBinding(Microsoft.Windows.Shell.SystemCommands.MaximizeWindowCommand, - new ExecutedRoutedEventHandler((s, args) => Microsoft.Windows.Shell.SystemCommands.MaximizeWindow((Window)args.Parameter)))); - CommandBindings.Add(new CommandBinding(Microsoft.Windows.Shell.SystemCommands.MinimizeWindowCommand, - new ExecutedRoutedEventHandler((s, args) => Microsoft.Windows.Shell.SystemCommands.MinimizeWindow((Window)args.Parameter)))); - CommandBindings.Add(new CommandBinding(Microsoft.Windows.Shell.SystemCommands.RestoreWindowCommand, - new ExecutedRoutedEventHandler((s, args) => Microsoft.Windows.Shell.SystemCommands.RestoreWindow((Window)args.Parameter)))); - //Debug.Assert(this.Owner != null); - base.OnInitialized(e); - } - - public abstract ILayoutElement Model { get; } - - - #region IsDragging - - /// - /// IsDragging Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey IsDraggingPropertyKey - = DependencyProperty.RegisterReadOnly("IsDragging", typeof(bool), typeof(LayoutFloatingWindowControl), - new FrameworkPropertyMetadata((bool)false, - new PropertyChangedCallback(OnIsDraggingChanged))); - - public static readonly DependencyProperty IsDraggingProperty - = IsDraggingPropertyKey.DependencyProperty; - - /// - /// Gets the IsDragging property. This dependency property - /// indicates that this floating window is being dragged. - /// - public bool IsDragging - { - get { return (bool)GetValue(IsDraggingProperty); } - } - - /// - /// Provides a secure method for setting the IsDragging property. - /// This dependency property indicates that this floating window is being dragged. - /// - /// The new value for the property. - protected void SetIsDragging(bool value) - { - SetValue(IsDraggingPropertyKey, value); - } - - /// - /// Handles changes to the IsDragging property. - /// - private static void OnIsDraggingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutFloatingWindowControl)d).OnIsDraggingChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the IsDragging property. - /// - protected virtual void OnIsDraggingChanged(DependencyPropertyChangedEventArgs e) - { - //Trace.WriteLine("IsDragging={0}", e.NewValue); - } - - #endregion - - - - DragService _dragService = null; - - void UpdatePositionAndSizeOfPanes() - { - foreach (var posElement in Model.Descendents().OfType()) - { - posElement.FloatingLeft = Left; - posElement.FloatingTop = Top; - posElement.FloatingWidth = Width; - posElement.FloatingHeight = Height; - } - } - - void UpdateMaximizedState(bool isMaximized) - { - foreach (var posElement in Model.Descendents().OfType()) - { - posElement.IsMaximized = isMaximized; - } - } - - protected virtual IntPtr FilterMessage( - IntPtr hwnd, - int msg, - IntPtr wParam, - IntPtr lParam, - ref bool handled - ) - { - handled = false; - - switch (msg) - { - case Win32Helper.WM_ACTIVATE: - if (((int)wParam & 0xFFFF) == Win32Helper.WA_INACTIVE) - { - if (lParam == this.GetParentWindowHandle()) - { - Win32Helper.SetActiveWindow(_hwndSrc.Handle); - handled = true; - } - } - break; - case Win32Helper.WM_EXITSIZEMOVE: - UpdatePositionAndSizeOfPanes(); - - if (_dragService != null) - { - bool dropFlag; - var mousePosition = this.TransformToDeviceDPI(Win32Helper.GetMousePosition()); - _dragService.Drop(mousePosition, out dropFlag); - _dragService = null; - SetIsDragging(false); - - if (dropFlag) - InternalClose(); - } - - break; - case Win32Helper.WM_MOVING: - { - UpdateDragPosition(); - } - break; - case Win32Helper.WM_LBUTTONUP: //set as handled right button click on title area (after showing context menu) - if (_dragService != null && Mouse.LeftButton == MouseButtonState.Released) - { - _dragService.Abort(); - _dragService = null; - SetIsDragging(false); - } - break; - case Win32Helper.WM_SYSCOMMAND: - IntPtr wMaximize = new IntPtr(Win32Helper.SC_MAXIMIZE); - IntPtr wRestore = new IntPtr(Win32Helper.SC_RESTORE); - if (wParam == wMaximize || wParam == wRestore) - { - UpdateMaximizedState(wParam == wMaximize); - } - break; - } - - - - return IntPtr.Zero; - } - - private void UpdateDragPosition() - { - if (_dragService == null) - { - _dragService = new DragService(this); - SetIsDragging(true); - } - - var mousePosition = this.TransformToDeviceDPI(Win32Helper.GetMousePosition()); - _dragService.UpdateMouseLocation(mousePosition); - } - - bool _internalCloseFlag = false; - - internal void InternalClose() - { - _internalCloseFlag = true; - Close(); - } - - - protected bool CloseInitiatedByUser - { - get { return !_internalCloseFlag; } - } - - internal bool KeepContentVisibleOnClose - { - get; - set; - } - - protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) - { - base.OnMouseLeftButtonUp(e); - } - - #region IsMaximized - - /// - /// IsMaximized Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey IsMaximizedPropertyKey - = DependencyProperty.RegisterReadOnly("IsMaximized", typeof(bool), typeof(LayoutFloatingWindowControl), - new FrameworkPropertyMetadata((bool)false)); - - public static readonly DependencyProperty IsMaximizedProperty - = IsMaximizedPropertyKey.DependencyProperty; - - /// - /// Gets the IsMaximized property. This dependency property - /// indicates if the window is maximized. - /// - public bool IsMaximized - { - get { return (bool)GetValue(IsMaximizedProperty); } - } - - /// - /// Provides a secure method for setting the IsMaximized property. - /// This dependency property indicates if the window is maximized. - /// - /// The new value for the property. - protected void SetIsMaximized(bool value) - { - SetValue(IsMaximizedPropertyKey, value); - } - - protected override void OnStateChanged(EventArgs e) - { - SetIsMaximized(WindowState == System.Windows.WindowState.Maximized); - base.OnStateChanged(e); - } - - #endregion - - - - - - - - } + if ( oldTheme != null ) + { + if( oldTheme is DictionaryTheme ) + { + if( currentThemeResourceDictionary != null ) + { + Resources.MergedDictionaries.Remove( currentThemeResourceDictionary ); + currentThemeResourceDictionary = null; + } + } + else + { + var resourceDictionaryToRemove = + Resources.MergedDictionaries.FirstOrDefault( r => r.Source == oldTheme.GetResourceUri() ); + if( resourceDictionaryToRemove != null ) + Resources.MergedDictionaries.Remove( + resourceDictionaryToRemove ); + } + } + + var manager = _model.Root.Manager; + if( manager.Theme != null ) + { + if( manager.Theme is DictionaryTheme ) + { + currentThemeResourceDictionary = ( ( DictionaryTheme )manager.Theme ).ThemeResourceDictionary; + Resources.MergedDictionaries.Add( currentThemeResourceDictionary ); + } + else + { + Resources.MergedDictionaries.Add( new ResourceDictionary() { Source = manager.Theme.GetResourceUri() } ); + } + } + } + + internal void AttachDrag( bool onActivated = true ) + { + if( onActivated ) + { + _attachDrag = true; + this.Activated += new EventHandler( OnActivated ); + } + else + { + IntPtr windowHandle = new WindowInteropHelper( this ).Handle; + IntPtr lParam = new IntPtr( ( ( int )Left & ( int )0xFFFF ) | ( ( ( int )Top ) << 16 ) ); + Win32Helper.SendMessage( windowHandle, Win32Helper.WM_NCLBUTTONDOWN, new IntPtr( Win32Helper.HT_CAPTION ), lParam ); + } + } + + protected virtual IntPtr FilterMessage( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled ) + { + handled = false; + + switch( msg ) + { + case Win32Helper.WM_ACTIVATE: + if( ( ( int )wParam & 0xFFFF ) == Win32Helper.WA_INACTIVE ) + { + if( lParam == this.GetParentWindowHandle() ) + { + Win32Helper.SetActiveWindow( _hwndSrc.Handle ); + handled = true; + } + } + break; + case Win32Helper.WM_EXITSIZEMOVE: + UpdatePositionAndSizeOfPanes(); + + if( _dragService != null ) + { + bool dropFlag; + var mousePosition = this.TransformToDeviceDPI( Win32Helper.GetMousePosition() ); + _dragService.Drop( mousePosition, out dropFlag ); + _dragService = null; + SetIsDragging( false ); + + if( dropFlag ) + InternalClose(); + } + + break; + case Win32Helper.WM_MOVING: + { + UpdateDragPosition(); + if( this.IsMaximized ) + { + this.UpdateMaximizedState( false ); + } + } + break; + case Win32Helper.WM_LBUTTONUP: //set as handled right button click on title area (after showing context menu) + if( _dragService != null && Mouse.LeftButton == MouseButtonState.Released ) + { + _dragService.Abort(); + _dragService = null; + SetIsDragging( false ); + } + break; + case Win32Helper.WM_SYSCOMMAND: + int command = ( int )wParam & 0xFFF0; + if( command == Win32Helper.SC_MAXIMIZE || command == Win32Helper.SC_RESTORE ) + { + UpdateMaximizedState( command == Win32Helper.SC_MAXIMIZE ); + } + break; + } + + + + return IntPtr.Zero; + } + + internal void InternalClose() + { + _internalCloseFlag = true; + Close(); + } + + #endregion + + #region Private Methods + + private static object CoerceContentValue( DependencyObject sender, object content ) + { + return new FloatingWindowContentHost( sender as LayoutFloatingWindowControl ) { Content = content as UIElement }; + } + + private void OnLoaded( object sender, RoutedEventArgs e ) + { + this.Loaded -= new RoutedEventHandler( OnLoaded ); + + this.SetParentToMainWindowOf( Model.Root.Manager ); + + _hwndSrc = HwndSource.FromDependencyObject( this ) as HwndSource; + _hwndSrcHook = new HwndSourceHook( FilterMessage ); + _hwndSrc.AddHook( _hwndSrcHook ); + + // Restore maximize state + var maximized = Model.Descendents().OfType().Any( l => l.IsMaximized ); + UpdateMaximizedState( maximized ); + } + + private void OnUnloaded( object sender, RoutedEventArgs e ) + { + this.Unloaded -= new RoutedEventHandler( OnUnloaded ); + + if( _hwndSrc != null ) + { + _hwndSrc.RemoveHook( _hwndSrcHook ); + InternalClose(); + } + } + + private void OnActivated( object sender, EventArgs e ) + { + this.Activated -= new EventHandler( OnActivated ); + + if( _attachDrag && Mouse.LeftButton == MouseButtonState.Pressed ) + { + IntPtr windowHandle = new WindowInteropHelper( this ).Handle; + var mousePosition = this.PointToScreenDPI( Mouse.GetPosition( this ) ); + var clientArea = Win32Helper.GetClientRect( windowHandle ); + var windowArea = Win32Helper.GetWindowRect( windowHandle ); + + Left = mousePosition.X - windowArea.Width / 2.0; + Top = mousePosition.Y - ( windowArea.Height - clientArea.Height ) / 2.0; + _attachDrag = false; + + IntPtr lParam = new IntPtr( ( ( int )mousePosition.X & ( int )0xFFFF ) | ( ( ( int )mousePosition.Y ) << 16 ) ); + Win32Helper.SendMessage( windowHandle, Win32Helper.WM_NCLBUTTONDOWN, new IntPtr( Win32Helper.HT_CAPTION ), lParam ); + } + } + + private void UpdatePositionAndSizeOfPanes() + { + foreach( var posElement in Model.Descendents().OfType() ) + { + posElement.FloatingLeft = Left; + posElement.FloatingTop = Top; + posElement.FloatingWidth = Width; + posElement.FloatingHeight = Height; + } + } + + private void UpdateMaximizedState( bool isMaximized ) + { + foreach( var posElement in Model.Descendents().OfType() ) + { + posElement.IsMaximized = isMaximized; + } + IsMaximized = isMaximized; + _isInternalChange = true; + WindowState = isMaximized ? WindowState.Maximized : WindowState.Normal; + _isInternalChange = false; + } + + private void UpdateDragPosition() + { + if( _dragService == null ) + { + _dragService = new DragService( this ); + SetIsDragging( true ); + } + + var mousePosition = this.TransformToDeviceDPI( Win32Helper.GetMousePosition() ); + _dragService.UpdateMouseLocation( mousePosition ); + } + + #endregion + + #region Internal Classes + + protected internal class FloatingWindowContentHost : HwndHost + { + #region Members + + private LayoutFloatingWindowControl _owner; + private HwndSource _wpfContentHost = null; + private Border _rootPresenter = null; + private DockingManager _manager = null; + + #endregion + + #region Constructors + + public FloatingWindowContentHost( LayoutFloatingWindowControl owner ) + { + _owner = owner; + var manager = _owner.Model.Root.Manager; + } + + #endregion + + #region Properties + + #region RootVisual + + public Visual RootVisual + { + get + { + return _rootPresenter; + } + } + + #endregion + + #region Content + + /// + /// Content Dependency Property + /// + public static readonly DependencyProperty ContentProperty = DependencyProperty.Register( "Content", typeof( UIElement ), typeof( FloatingWindowContentHost ), + new FrameworkPropertyMetadata( ( UIElement )null, new PropertyChangedCallback( OnContentChanged ) ) ); + + /// + /// Gets or sets the Content property. This dependency property + /// indicates .... + /// + public UIElement Content + { + get + { + return ( UIElement )GetValue( ContentProperty ); + } + set + { + SetValue( ContentProperty, value ); + } + } + + /// + /// Handles changes to the Content property. + /// + private static void OnContentChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( FloatingWindowContentHost )d ).OnContentChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the Content property. + /// + protected virtual void OnContentChanged( DependencyPropertyChangedEventArgs e ) + { + if( _rootPresenter != null ) + _rootPresenter.Child = Content; + } + + #endregion + + #endregion + + #region Overrides + + protected override System.Runtime.InteropServices.HandleRef BuildWindowCore( System.Runtime.InteropServices.HandleRef hwndParent ) + { + _wpfContentHost = new HwndSource( new HwndSourceParameters() + { + ParentWindow = hwndParent.Handle, + WindowStyle = Win32Helper.WS_CHILD | Win32Helper.WS_VISIBLE | Win32Helper.WS_CLIPSIBLINGS | Win32Helper.WS_CLIPCHILDREN, + Width = 1, + Height = 1 + } ); + + _rootPresenter = new Border() { Child = new AdornerDecorator() { Child = Content }, Focusable = true }; + _rootPresenter.SetBinding( Border.BackgroundProperty, new Binding( "Background" ) { Source = _owner } ); + _wpfContentHost.RootVisual = _rootPresenter; + _wpfContentHost.SizeToContent = SizeToContent.Manual; + _manager = _owner.Model.Root.Manager; + _manager.InternalAddLogicalChild( _rootPresenter ); + + return new HandleRef( this, _wpfContentHost.Handle ); + } + + protected override void DestroyWindowCore( HandleRef hwnd ) + { + _manager.InternalRemoveLogicalChild( _rootPresenter ); + if( _wpfContentHost != null ) + { + _wpfContentHost.Dispose(); + _wpfContentHost = null; + } + } + + protected override Size MeasureOverride( Size constraint ) + { + if( Content == null ) + return base.MeasureOverride( constraint ); + + Content.Measure( constraint ); + return Content.DesiredSize; + } + + #endregion + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutGridControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutGridControl.cs index 59cfa8b4..0f8960d6 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutGridControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutGridControl.cs @@ -15,550 +15,565 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using System.Windows.Input; using System.Windows.Media; using Xceed.Wpf.AvalonDock.Layout; -using System.Diagnostics; using System.Windows.Threading; namespace Xceed.Wpf.AvalonDock.Controls { - public abstract class LayoutGridControl : Grid, ILayoutControl where T : class, ILayoutPanelElement - { - static LayoutGridControl() - { - } + public abstract class LayoutGridControl : Grid, ILayoutControl where T : class, ILayoutPanelElement + { + #region Members - internal LayoutGridControl(LayoutPositionableGroup model, Orientation orientation) - { - if (model == null) - throw new ArgumentNullException("model"); + private LayoutPositionableGroup _model; + private Orientation _orientation; + private bool _initialized; + private ChildrenTreeChange? _asyncRefreshCalled; + private ReentrantFlag _fixingChildrenDockLengths = new ReentrantFlag(); + private Border _resizerGhost = null; + private Window _resizerWindowHost = null; + private Vector _initialStartPoint; - _model = model; - _orientation = orientation; + #endregion - FlowDirection = System.Windows.FlowDirection.LeftToRight; - } + #region Constructors - LayoutPositionableGroup _model; - public ILayoutElement Model - { - get { return _model; } - } + static LayoutGridControl() + { + } - Orientation _orientation; + internal LayoutGridControl( LayoutPositionableGroup model, Orientation orientation ) + { + if( model == null ) + throw new ArgumentNullException( "model" ); - public Orientation Orientation - { - get { return (_model as ILayoutOrientableGroup).Orientation; } - } + _model = model; + _orientation = orientation; - bool _initialized; - ChildrenTreeChange? _asyncRefreshCalled; + FlowDirection = System.Windows.FlowDirection.LeftToRight; + } - bool AsyncRefreshCalled - { - get { return _asyncRefreshCalled != null; } - } + #endregion - protected override void OnInitialized(EventArgs e) - { - base.OnInitialized(e); - - _model.ChildrenTreeChanged += (s, args) => - { - if (_asyncRefreshCalled.HasValue && - _asyncRefreshCalled.Value == args.Change) - return; - _asyncRefreshCalled = args.Change; - Dispatcher.BeginInvoke(new Action(() => - { - _asyncRefreshCalled = null; - UpdateChildren(); - }), DispatcherPriority.Normal, null); - }; - - this.LayoutUpdated += new EventHandler(OnLayoutUpdated); - } + #region Properties - void OnLayoutUpdated(object sender, EventArgs e) - { - var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize; - modelWithAtcualSize.ActualWidth = ActualWidth; - modelWithAtcualSize.ActualHeight = ActualHeight; + public ILayoutElement Model + { + get + { + return _model; + } + } - if (!_initialized) - { - _initialized = true; - UpdateChildren(); - } - } + public Orientation Orientation + { + get + { + return ( _model as ILayoutOrientableGroup ).Orientation; + } + } - void UpdateChildren() - { - var alreadyContainedChildren = Children.OfType().ToArray(); + private bool AsyncRefreshCalled + { + get + { + return _asyncRefreshCalled != null; + } + } - DetachOldSplitters(); - DetachPropertChangeHandler(); + #endregion - Children.Clear(); - ColumnDefinitions.Clear(); - RowDefinitions.Clear(); + #region Overrides - if (_model == null || - _model.Root == null) - return; + protected override void OnInitialized( EventArgs e ) + { + base.OnInitialized( e ); + + _model.ChildrenTreeChanged += ( s, args ) => + { + if( _asyncRefreshCalled.HasValue && + _asyncRefreshCalled.Value == args.Change ) + return; + _asyncRefreshCalled = args.Change; + Dispatcher.BeginInvoke( new Action( () => + { + _asyncRefreshCalled = null; + UpdateChildren(); + } ), DispatcherPriority.Normal, null ); + }; + + this.LayoutUpdated += new EventHandler( OnLayoutUpdated ); + } - var manager = _model.Root.Manager; - if (manager == null) - return; + #endregion + #region Internal Methods - foreach (ILayoutElement child in _model.Children) - { - var foundContainedChild = alreadyContainedChildren.FirstOrDefault(chVM => chVM.Model == child); - if (foundContainedChild != null) - Children.Add(foundContainedChild as UIElement); - else - Children.Add(manager.CreateUIElementForModel(child)); - } + protected void FixChildrenDockLengths() + { + using( _fixingChildrenDockLengths.Enter() ) + OnFixChildrenDockLengths(); + } - CreateSplitters(); + protected abstract void OnFixChildrenDockLengths(); - UpdateRowColDefinitions(); + #endregion - AttachNewSplitters(); - AttachPropertyChangeHandler(); - } + #region Private Methods - private void AttachPropertyChangeHandler() - { - foreach (var child in InternalChildren.OfType()) - { - child.Model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(this.OnChildModelPropertyChanged); - } - } + private void OnLayoutUpdated( object sender, EventArgs e ) + { + var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize; + modelWithAtcualSize.ActualWidth = ActualWidth; + modelWithAtcualSize.ActualHeight = ActualHeight; + + if( !_initialized ) + { + _initialized = true; + UpdateChildren(); + } + } - private void DetachPropertChangeHandler() - { - foreach (var child in InternalChildren.OfType()) - { - child.Model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(this.OnChildModelPropertyChanged); - } - } + private void UpdateChildren() + { + var alreadyContainedChildren = Children.OfType().ToArray(); - void OnChildModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) - { - if (AsyncRefreshCalled) - return; + DetachOldSplitters(); + DetachPropertChangeHandler(); - if (_fixingChildrenDockLengths.CanEnter && e.PropertyName == "DockWidth" && Orientation == System.Windows.Controls.Orientation.Horizontal) - { - if (ColumnDefinitions.Count == InternalChildren.Count) - { - var changedElement = sender as ILayoutPositionableElement; - var childFromModel = InternalChildren.OfType().First(ch => ch.Model == changedElement) as UIElement; - int indexOfChild = InternalChildren.IndexOf(childFromModel); - ColumnDefinitions[indexOfChild].Width = changedElement.DockWidth; - } - } - else if (_fixingChildrenDockLengths.CanEnter && e.PropertyName == "DockHeight" && Orientation == System.Windows.Controls.Orientation.Vertical) - { - if (RowDefinitions.Count == InternalChildren.Count) - { - var changedElement = sender as ILayoutPositionableElement; - var childFromModel = InternalChildren.OfType().First(ch => ch.Model == changedElement) as UIElement; - int indexOfChild = InternalChildren.IndexOf(childFromModel); - RowDefinitions[indexOfChild].Height = changedElement.DockHeight; - } - } - else if (e.PropertyName == "IsVisible") - { - UpdateRowColDefinitions(); - } - } + Children.Clear(); + ColumnDefinitions.Clear(); + RowDefinitions.Clear(); + if( _model == null || + _model.Root == null ) + return; - void UpdateRowColDefinitions() - { - var root = _model.Root; - if (root == null) - return; - var manager = root.Manager; - if (manager == null) - return; + var manager = _model.Root.Manager; + if( manager == null ) + return; - FixChildrenDockLengths(); - //Debug.Assert(InternalChildren.Count == _model.ChildrenCount + (_model.ChildrenCount - 1)); + foreach( ILayoutElement child in _model.Children ) + { + var foundContainedChild = alreadyContainedChildren.FirstOrDefault( chVM => chVM.Model == child ); + if( foundContainedChild != null ) + Children.Add( foundContainedChild as UIElement ); + else + Children.Add( manager.CreateUIElementForModel( child ) ); + } - #region Setup GridRows/Cols - RowDefinitions.Clear(); - ColumnDefinitions.Clear(); - if (Orientation == Orientation.Horizontal) - { - int iColumn = 0; - int iChild = 0; - for (int iChildModel = 0; iChildModel < _model.Children.Count; iChildModel++, iColumn++, iChild++) - { - var childModel = _model.Children[iChildModel] as ILayoutPositionableElement; - ColumnDefinitions.Add(new ColumnDefinition() - { - Width = childModel.IsVisible ? childModel.DockWidth : new GridLength(0.0, GridUnitType.Pixel), - MinWidth = childModel.IsVisible ? childModel.DockMinWidth : 0.0 - }); - Grid.SetColumn(InternalChildren[iChild], iColumn); - - //append column for splitter - if (iChild < InternalChildren.Count - 1) - { - iChild++; - iColumn++; - - bool nextChildModelVisibleExist = false; - for (int i = iChildModel + 1; i < _model.Children.Count; i++) - { - var nextChildModel = _model.Children[i] as ILayoutPositionableElement; - if (nextChildModel.IsVisible) - { - nextChildModelVisibleExist = true; - break; - } - } - - ColumnDefinitions.Add(new ColumnDefinition() - { - Width = childModel.IsVisible && nextChildModelVisibleExist ? new GridLength(manager.GridSplitterWidth) : new GridLength(0.0, GridUnitType.Pixel) - }); - Grid.SetColumn(InternalChildren[iChild], iColumn); - } - } - } - else //if (_model.Orientation == Orientation.Vertical) - { - int iRow = 0; - int iChild = 0; - for (int iChildModel = 0; iChildModel < _model.Children.Count; iChildModel++, iRow++, iChild++) - { - var childModel = _model.Children[iChildModel] as ILayoutPositionableElement; - RowDefinitions.Add(new RowDefinition() - { - Height = childModel.IsVisible ? childModel.DockHeight : new GridLength(0.0, GridUnitType.Pixel), - MinHeight = childModel.IsVisible ? childModel.DockMinHeight : 0.0 - }); - Grid.SetRow(InternalChildren[iChild], iRow); - - //if (RowDefinitions.Last().Height.Value == 0.0) - // System.Diagnostics.Debugger.Break(); - - //append row for splitter (if necessary) - if (iChild < InternalChildren.Count - 1) - { - iChild++; - iRow++; - - bool nextChildModelVisibleExist = false; - for (int i = iChildModel + 1; i < _model.Children.Count; i++) - { - var nextChildModel = _model.Children[i] as ILayoutPositionableElement; - if (nextChildModel.IsVisible) - { - nextChildModelVisibleExist = true; - break; - } - } - - RowDefinitions.Add(new RowDefinition() - { - Height = childModel.IsVisible && nextChildModelVisibleExist ? new GridLength(manager.GridSplitterHeight) : new GridLength(0.0, GridUnitType.Pixel) - }); - //if (RowDefinitions.Last().Height.Value == 0.0) - // System.Diagnostics.Debugger.Break(); - Grid.SetRow(InternalChildren[iChild], iRow); - } - } - } + CreateSplitters(); - #endregion - } + UpdateRowColDefinitions(); - ReentrantFlag _fixingChildrenDockLengths = new ReentrantFlag(); - protected void FixChildrenDockLengths() - { - using (_fixingChildrenDockLengths.Enter()) - OnFixChildrenDockLengths(); - } + AttachNewSplitters(); + AttachPropertyChangeHandler(); + } - protected abstract void OnFixChildrenDockLengths(); + private void AttachPropertyChangeHandler() + { + foreach( var child in InternalChildren.OfType() ) + { + child.Model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler( this.OnChildModelPropertyChanged ); + } + } - #region Splitters + private void DetachPropertChangeHandler() + { + foreach( var child in InternalChildren.OfType() ) + { + child.Model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler( this.OnChildModelPropertyChanged ); + } + } - void CreateSplitters() - { - for (int iChild = 1; iChild < Children.Count; iChild++) - { - var splitter = new LayoutGridResizerControl(); - splitter.Cursor = this.Orientation == Orientation.Horizontal ? Cursors.SizeWE : Cursors.SizeNS; - Children.Insert(iChild, splitter); - iChild++; - } - } + private void OnChildModelPropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e ) + { + if( AsyncRefreshCalled ) + return; - void DetachOldSplitters() + if( _fixingChildrenDockLengths.CanEnter && e.PropertyName == "DockWidth" && Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + if( ColumnDefinitions.Count == InternalChildren.Count ) { - foreach (var splitter in Children.OfType()) - { - splitter.DragStarted -= new System.Windows.Controls.Primitives.DragStartedEventHandler(OnSplitterDragStarted); - splitter.DragDelta -= new System.Windows.Controls.Primitives.DragDeltaEventHandler(OnSplitterDragDelta); - splitter.DragCompleted -= new System.Windows.Controls.Primitives.DragCompletedEventHandler(OnSplitterDragCompleted); - } + var changedElement = sender as ILayoutPositionableElement; + var childFromModel = InternalChildren.OfType().First( ch => ch.Model == changedElement ) as UIElement; + int indexOfChild = InternalChildren.IndexOf( childFromModel ); + ColumnDefinitions[ indexOfChild ].Width = changedElement.DockWidth; } - - void AttachNewSplitters() + } + else if( _fixingChildrenDockLengths.CanEnter && e.PropertyName == "DockHeight" && Orientation == System.Windows.Controls.Orientation.Vertical ) + { + if( RowDefinitions.Count == InternalChildren.Count ) { - foreach (var splitter in Children.OfType()) - { - splitter.DragStarted += new System.Windows.Controls.Primitives.DragStartedEventHandler(OnSplitterDragStarted); - splitter.DragDelta += new System.Windows.Controls.Primitives.DragDeltaEventHandler(OnSplitterDragDelta); - splitter.DragCompleted += new System.Windows.Controls.Primitives.DragCompletedEventHandler(OnSplitterDragCompleted); - } - } - - void OnSplitterDragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) - { - var resizer = sender as LayoutGridResizerControl; - ShowResizerOverlayWindow(resizer); + var changedElement = sender as ILayoutPositionableElement; + var childFromModel = InternalChildren.OfType().First( ch => ch.Model == changedElement ) as UIElement; + int indexOfChild = InternalChildren.IndexOf( childFromModel ); + RowDefinitions[ indexOfChild ].Height = changedElement.DockHeight; } + } + else if( e.PropertyName == "IsVisible" ) + { + UpdateRowColDefinitions(); + } + } - void OnSplitterDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) + private void UpdateRowColDefinitions() + { + var root = _model.Root; + if( root == null ) + return; + var manager = root.Manager; + if( manager == null ) + return; + + FixChildrenDockLengths(); + + //Debug.Assert(InternalChildren.Count == _model.ChildrenCount + (_model.ChildrenCount - 1)); + + #region Setup GridRows/Cols + RowDefinitions.Clear(); + ColumnDefinitions.Clear(); + if( Orientation == Orientation.Horizontal ) + { + int iColumn = 0; + int iChild = 0; + for( int iChildModel = 0; iChildModel < _model.Children.Count; iChildModel++, iColumn++, iChild++ ) { - LayoutGridResizerControl splitter = sender as LayoutGridResizerControl; - var rootVisual = this.FindVisualTreeRoot() as Visual; - - var trToWnd = TransformToAncestor(rootVisual); - Vector transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) - - trToWnd.Transform(new Point()); - - if (Orientation == System.Windows.Controls.Orientation.Horizontal) + var childModel = _model.Children[ iChildModel ] as ILayoutPositionableElement; + ColumnDefinitions.Add( new ColumnDefinition() + { + Width = childModel.IsVisible ? childModel.DockWidth : new GridLength( 0.0, GridUnitType.Pixel ), + MinWidth = childModel.IsVisible ? childModel.DockMinWidth : 0.0 + } ); + Grid.SetColumn( InternalChildren[ iChild ], iColumn ); + + //append column for splitter + if( iChild < InternalChildren.Count - 1 ) + { + iChild++; + iColumn++; + + bool nextChildModelVisibleExist = false; + for( int i = iChildModel + 1; i < _model.Children.Count; i++ ) { - Canvas.SetLeft(_resizerGhost, MathHelper.MinMax(_initialStartPoint.X + transformedDelta.X, 0.0, _resizerWindowHost.Width - _resizerGhost.Width)); + var nextChildModel = _model.Children[ i ] as ILayoutPositionableElement; + if( nextChildModel.IsVisible ) + { + nextChildModelVisibleExist = true; + break; + } } - else - { - Canvas.SetTop(_resizerGhost, MathHelper.MinMax(_initialStartPoint.Y + transformedDelta.Y, 0.0, _resizerWindowHost.Height - _resizerGhost.Height)); - } - } - - void OnSplitterDragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) - { - LayoutGridResizerControl splitter = sender as LayoutGridResizerControl; - var rootVisual = this.FindVisualTreeRoot() as Visual; - var trToWnd = TransformToAncestor(rootVisual); - Vector transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) - - trToWnd.Transform(new Point()); - - double delta; - if (Orientation == System.Windows.Controls.Orientation.Horizontal) - delta = Canvas.GetLeft(_resizerGhost) - _initialStartPoint.X; - else - delta = Canvas.GetTop(_resizerGhost) - _initialStartPoint.Y; - - int indexOfResizer = InternalChildren.IndexOf(splitter); - - var prevChild = InternalChildren[indexOfResizer - 1] as FrameworkElement; - var nextChild = GetNextVisibleChild(indexOfResizer); - - var prevChildActualSize = prevChild.TransformActualSizeToAncestor(); - var nextChildActualSize = nextChild.TransformActualSizeToAncestor(); - - var prevChildModel = (ILayoutPositionableElement)(prevChild as ILayoutControl).Model; - var nextChildModel = (ILayoutPositionableElement)(nextChild as ILayoutControl).Model; - - if (Orientation == System.Windows.Controls.Orientation.Horizontal) - { - //Trace.WriteLine(string.Format("PrevChild From {0}", prevChildModel.DockWidth)); - if (prevChildModel.DockWidth.IsStar) - { - prevChildModel.DockWidth = new GridLength(prevChildModel.DockWidth.Value * (prevChildActualSize.Width + delta) / prevChildActualSize.Width, GridUnitType.Star); - } - else - { - prevChildModel.DockWidth = new GridLength(prevChildModel.DockWidth.Value + delta, GridUnitType.Pixel); - } - //Trace.WriteLine(string.Format("PrevChild To {0}", prevChildModel.DockWidth)); - - //Trace.WriteLine(string.Format("NextChild From {0}", nextChildModel.DockWidth)); - if (nextChildModel.DockWidth.IsStar) - { - nextChildModel.DockWidth = new GridLength(nextChildModel.DockWidth.Value * (nextChildActualSize.Width - delta) / nextChildActualSize.Width, GridUnitType.Star); - } - else - { - nextChildModel.DockWidth = new GridLength(nextChildModel.DockWidth.Value - delta, GridUnitType.Pixel); - } - //Trace.WriteLine(string.Format("NextChild To {0}", nextChildModel.DockWidth)); - } - else + ColumnDefinitions.Add( new ColumnDefinition() { - //Trace.WriteLine(string.Format("PrevChild From {0}", prevChildModel.DockHeight)); - if (prevChildModel.DockHeight.IsStar) - { - prevChildModel.DockHeight = new GridLength(prevChildModel.DockHeight.Value * (prevChildActualSize.Height + delta) / prevChildActualSize.Height, GridUnitType.Star); - } - else - { - prevChildModel.DockHeight = new GridLength(prevChildModel.DockHeight.Value + delta, GridUnitType.Pixel); - } - //Trace.WriteLine(string.Format("PrevChild To {0}", prevChildModel.DockHeight)); - - //Trace.WriteLine(string.Format("NextChild From {0}", nextChildModel.DockHeight)); - if (nextChildModel.DockHeight.IsStar) - { - nextChildModel.DockHeight = new GridLength(nextChildModel.DockHeight.Value * (nextChildActualSize.Height - delta) / nextChildActualSize.Height, GridUnitType.Star); - } - else - { - nextChildModel.DockHeight = new GridLength(nextChildModel.DockHeight.Value - delta, GridUnitType.Pixel); - } - //Trace.WriteLine(string.Format("NextChild To {0}", nextChildModel.DockHeight)); - } - - HideResizerOverlayWindow(); + Width = childModel.IsVisible && nextChildModelVisibleExist ? new GridLength( manager.GridSplitterWidth ) : new GridLength( 0.0, GridUnitType.Pixel ) + } ); + Grid.SetColumn( InternalChildren[ iChild ], iColumn ); + } } - - Border _resizerGhost = null; - Window _resizerWindowHost = null; - Vector _initialStartPoint; - - FrameworkElement GetNextVisibleChild(int index) + } + else //if (_model.Orientation == Orientation.Vertical) + { + int iRow = 0; + int iChild = 0; + for( int iChildModel = 0; iChildModel < _model.Children.Count; iChildModel++, iRow++, iChild++ ) { - for (int i = index + 1; i < InternalChildren.Count; i++) + var childModel = _model.Children[ iChildModel ] as ILayoutPositionableElement; + RowDefinitions.Add( new RowDefinition() + { + Height = childModel.IsVisible ? childModel.DockHeight : new GridLength( 0.0, GridUnitType.Pixel ), + MinHeight = childModel.IsVisible ? childModel.DockMinHeight : 0.0 + } ); + Grid.SetRow( InternalChildren[ iChild ], iRow ); + + //if (RowDefinitions.Last().Height.Value == 0.0) + // System.Diagnostics.Debugger.Break(); + + //append row for splitter (if necessary) + if( iChild < InternalChildren.Count - 1 ) + { + iChild++; + iRow++; + + bool nextChildModelVisibleExist = false; + for( int i = iChildModel + 1; i < _model.Children.Count; i++ ) { - if (InternalChildren[i] is LayoutGridResizerControl) - continue; - - if (Orientation == System.Windows.Controls.Orientation.Horizontal) - { - if (ColumnDefinitions[i].Width.IsStar || ColumnDefinitions[i].Width.Value > 0) - return InternalChildren[i] as FrameworkElement; - } - else - { - if (RowDefinitions[i].Height.IsStar || RowDefinitions[i].Height.Value > 0) - return InternalChildren[i] as FrameworkElement; - } + var nextChildModel = _model.Children[ i ] as ILayoutPositionableElement; + if( nextChildModel.IsVisible ) + { + nextChildModelVisibleExist = true; + break; + } } - return null; - } - - void ShowResizerOverlayWindow(LayoutGridResizerControl splitter) - { - _resizerGhost = new Border() + RowDefinitions.Add( new RowDefinition() { - Background = splitter.BackgroundWhileDragging, - Opacity = splitter.OpacityWhileDragging - }; - - int indexOfResizer = InternalChildren.IndexOf(splitter); + Height = childModel.IsVisible && nextChildModelVisibleExist ? new GridLength( manager.GridSplitterHeight ) : new GridLength( 0.0, GridUnitType.Pixel ) + } ); + //if (RowDefinitions.Last().Height.Value == 0.0) + // System.Diagnostics.Debugger.Break(); + Grid.SetRow( InternalChildren[ iChild ], iRow ); + } + } + } - var prevChild = InternalChildren[indexOfResizer - 1] as FrameworkElement; - var nextChild = GetNextVisibleChild(indexOfResizer); + #endregion + } - var prevChildActualSize = prevChild.TransformActualSizeToAncestor(); - var nextChildActualSize = nextChild.TransformActualSizeToAncestor(); + private void CreateSplitters() + { + for( int iChild = 1; iChild < Children.Count; iChild++ ) + { + var splitter = new LayoutGridResizerControl(); + splitter.Cursor = this.Orientation == Orientation.Horizontal ? Cursors.SizeWE : Cursors.SizeNS; + Children.Insert( iChild, splitter ); + iChild++; + } + } - var prevChildModel = (ILayoutPositionableElement)(prevChild as ILayoutControl).Model; - var nextChildModel = (ILayoutPositionableElement)(nextChild as ILayoutControl).Model; + private void DetachOldSplitters() + { + foreach( var splitter in Children.OfType() ) + { + splitter.DragStarted -= new System.Windows.Controls.Primitives.DragStartedEventHandler( OnSplitterDragStarted ); + splitter.DragDelta -= new System.Windows.Controls.Primitives.DragDeltaEventHandler( OnSplitterDragDelta ); + splitter.DragCompleted -= new System.Windows.Controls.Primitives.DragCompletedEventHandler( OnSplitterDragCompleted ); + } + } - Point ptTopLeftScreen = prevChild.PointToScreenDPIWithoutFlowDirection(new Point()); + private void AttachNewSplitters() + { + foreach( var splitter in Children.OfType() ) + { + splitter.DragStarted += new System.Windows.Controls.Primitives.DragStartedEventHandler( OnSplitterDragStarted ); + splitter.DragDelta += new System.Windows.Controls.Primitives.DragDeltaEventHandler( OnSplitterDragDelta ); + splitter.DragCompleted += new System.Windows.Controls.Primitives.DragCompletedEventHandler( OnSplitterDragCompleted ); + } + } - Size actualSize; + private void OnSplitterDragStarted( object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e ) + { + var resizer = sender as LayoutGridResizerControl; + ShowResizerOverlayWindow( resizer ); + } - if (Orientation == System.Windows.Controls.Orientation.Horizontal) - { - actualSize = new Size( - prevChildActualSize.Width - prevChildModel.DockMinWidth + splitter.ActualWidth + nextChildActualSize.Width - nextChildModel.DockMinWidth, - nextChildActualSize.Height); + private void OnSplitterDragDelta( object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e ) + { + LayoutGridResizerControl splitter = sender as LayoutGridResizerControl; + var rootVisual = this.FindVisualTreeRoot() as Visual; + + var trToWnd = TransformToAncestor( rootVisual ); + Vector transformedDelta = trToWnd.Transform( new Point( e.HorizontalChange, e.VerticalChange ) ) - + trToWnd.Transform( new Point() ); + + if( Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + Canvas.SetLeft( _resizerGhost, MathHelper.MinMax( _initialStartPoint.X + transformedDelta.X, 0.0, _resizerWindowHost.Width - _resizerGhost.Width ) ); + } + else + { + Canvas.SetTop( _resizerGhost, MathHelper.MinMax( _initialStartPoint.Y + transformedDelta.Y, 0.0, _resizerWindowHost.Height - _resizerGhost.Height ) ); + } + } - _resizerGhost.Width = splitter.ActualWidth; - _resizerGhost.Height = actualSize.Height; - ptTopLeftScreen.Offset(prevChildModel.DockMinWidth, 0.0); - } - else - { - actualSize = new Size( - prevChildActualSize.Width, - prevChildActualSize.Height - prevChildModel.DockMinHeight + splitter.ActualHeight + nextChildActualSize.Height - nextChildModel.DockMinHeight); + private void OnSplitterDragCompleted( object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e ) + { + LayoutGridResizerControl splitter = sender as LayoutGridResizerControl; + var rootVisual = this.FindVisualTreeRoot() as Visual; - _resizerGhost.Height = splitter.ActualHeight; - _resizerGhost.Width = actualSize.Width; + var trToWnd = TransformToAncestor( rootVisual ); + Vector transformedDelta = trToWnd.Transform( new Point( e.HorizontalChange, e.VerticalChange ) ) - + trToWnd.Transform( new Point() ); - ptTopLeftScreen.Offset(0.0, prevChildModel.DockMinHeight); - } + double delta; + if( Orientation == System.Windows.Controls.Orientation.Horizontal ) + delta = Canvas.GetLeft( _resizerGhost ) - _initialStartPoint.X; + else + delta = Canvas.GetTop( _resizerGhost ) - _initialStartPoint.Y; - _initialStartPoint = splitter.PointToScreenDPIWithoutFlowDirection(new Point()) - ptTopLeftScreen; + int indexOfResizer = InternalChildren.IndexOf( splitter ); - if (Orientation == System.Windows.Controls.Orientation.Horizontal) - { - Canvas.SetLeft(_resizerGhost, _initialStartPoint.X); - } - else - { - Canvas.SetTop(_resizerGhost, _initialStartPoint.Y); - } + var prevChild = InternalChildren[ indexOfResizer - 1 ] as FrameworkElement; + var nextChild = GetNextVisibleChild( indexOfResizer ); - Canvas panelHostResizer = new Canvas() - { - HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, - VerticalAlignment = System.Windows.VerticalAlignment.Stretch - }; + var prevChildActualSize = prevChild.TransformActualSizeToAncestor(); + var nextChildActualSize = nextChild.TransformActualSizeToAncestor(); - panelHostResizer.Children.Add(_resizerGhost); + var prevChildModel = ( ILayoutPositionableElement )( prevChild as ILayoutControl ).Model; + var nextChildModel = ( ILayoutPositionableElement )( nextChild as ILayoutControl ).Model; + if( Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + if( prevChildModel.DockWidth.IsStar ) + { + prevChildModel.DockWidth = new GridLength( prevChildModel.DockWidth.Value * ( prevChildActualSize.Width + delta ) / prevChildActualSize.Width, GridUnitType.Star ); + } + else + { + var width = ( prevChildModel.DockWidth.IsAuto ) ? prevChildActualSize.Width : prevChildModel.DockWidth.Value; + prevChildModel.DockWidth = new GridLength( width + delta, GridUnitType.Pixel ); + } - _resizerWindowHost = new Window() - { - SizeToContent = System.Windows.SizeToContent.Manual, - ResizeMode = ResizeMode.NoResize, - WindowStyle = System.Windows.WindowStyle.None, - ShowInTaskbar = false, - AllowsTransparency = true, - Background = null, - Width = actualSize.Width, - Height = actualSize.Height, - Left = ptTopLeftScreen.X, - Top = ptTopLeftScreen.Y, - ShowActivated = false, - //Owner = Window.GetWindow(this), - Content = panelHostResizer - }; - _resizerWindowHost.Loaded += (s, e) => - { - _resizerWindowHost.SetParentToMainWindowOf(this); - }; - _resizerWindowHost.Show(); + if( nextChildModel.DockWidth.IsStar ) + { + nextChildModel.DockWidth = new GridLength( nextChildModel.DockWidth.Value * ( nextChildActualSize.Width - delta ) / nextChildActualSize.Width, GridUnitType.Star ); + } + else + { + var width = ( nextChildModel.DockWidth.IsAuto ) ? nextChildActualSize.Width : nextChildModel.DockWidth.Value; + nextChildModel.DockWidth = new GridLength( width - delta, GridUnitType.Pixel ); + } + } + else + { + if( prevChildModel.DockHeight.IsStar ) + { + prevChildModel.DockHeight = new GridLength( prevChildModel.DockHeight.Value * ( prevChildActualSize.Height + delta ) / prevChildActualSize.Height, GridUnitType.Star ); + } + else + { + var height = ( prevChildModel.DockHeight.IsAuto ) ? prevChildActualSize.Height : prevChildModel.DockHeight.Value; + prevChildModel.DockHeight = new GridLength( height + delta, GridUnitType.Pixel ); } - void HideResizerOverlayWindow() + if( nextChildModel.DockHeight.IsStar ) { - if (_resizerWindowHost != null) - { - _resizerWindowHost.Close(); - _resizerWindowHost = null; - } + nextChildModel.DockHeight = new GridLength( nextChildModel.DockHeight.Value * ( nextChildActualSize.Height - delta ) / nextChildActualSize.Height, GridUnitType.Star ); } + else + { + var height = ( nextChildModel.DockHeight.IsAuto ) ? nextChildActualSize.Height : nextChildModel.DockHeight.Value; + nextChildModel.DockHeight = new GridLength( height - delta, GridUnitType.Pixel ); + } + } - #endregion + HideResizerOverlayWindow(); + } + private FrameworkElement GetNextVisibleChild( int index ) + { + for( int i = index + 1; i < InternalChildren.Count; i++ ) + { + if( InternalChildren[ i ] is LayoutGridResizerControl ) + continue; + if( Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + if( ColumnDefinitions[ i ].Width.IsStar || ColumnDefinitions[ i ].Width.Value > 0 ) + return InternalChildren[ i ] as FrameworkElement; + } + else + { + if( RowDefinitions[ i ].Height.IsStar || RowDefinitions[ i ].Height.Value > 0 ) + return InternalChildren[ i ] as FrameworkElement; + } + } + return null; + } + private void ShowResizerOverlayWindow( LayoutGridResizerControl splitter ) + { + _resizerGhost = new Border() + { + Background = splitter.BackgroundWhileDragging, + Opacity = splitter.OpacityWhileDragging + }; + + int indexOfResizer = InternalChildren.IndexOf( splitter ); + + var prevChild = InternalChildren[ indexOfResizer - 1 ] as FrameworkElement; + var nextChild = GetNextVisibleChild( indexOfResizer ); + + var prevChildActualSize = prevChild.TransformActualSizeToAncestor(); + var nextChildActualSize = nextChild.TransformActualSizeToAncestor(); + + var prevChildModel = ( ILayoutPositionableElement )( prevChild as ILayoutControl ).Model; + var nextChildModel = ( ILayoutPositionableElement )( nextChild as ILayoutControl ).Model; + + Point ptTopLeftScreen = prevChild.PointToScreenDPIWithoutFlowDirection( new Point() ); + + Size actualSize; + + if( Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + actualSize = new Size( + prevChildActualSize.Width - prevChildModel.DockMinWidth + splitter.ActualWidth + nextChildActualSize.Width - nextChildModel.DockMinWidth, + nextChildActualSize.Height ); + + _resizerGhost.Width = splitter.ActualWidth; + _resizerGhost.Height = actualSize.Height; + ptTopLeftScreen.Offset( prevChildModel.DockMinWidth, 0.0 ); + } + else + { + actualSize = new Size( + prevChildActualSize.Width, + prevChildActualSize.Height - prevChildModel.DockMinHeight + splitter.ActualHeight + nextChildActualSize.Height - nextChildModel.DockMinHeight ); + + _resizerGhost.Height = splitter.ActualHeight; + _resizerGhost.Width = actualSize.Width; + + ptTopLeftScreen.Offset( 0.0, prevChildModel.DockMinHeight ); + } + + _initialStartPoint = splitter.PointToScreenDPIWithoutFlowDirection( new Point() ) - ptTopLeftScreen; + + if( Orientation == System.Windows.Controls.Orientation.Horizontal ) + { + Canvas.SetLeft( _resizerGhost, _initialStartPoint.X ); + } + else + { + Canvas.SetTop( _resizerGhost, _initialStartPoint.Y ); + } + + Canvas panelHostResizer = new Canvas() + { + HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, + VerticalAlignment = System.Windows.VerticalAlignment.Stretch + }; + + panelHostResizer.Children.Add( _resizerGhost ); + + + _resizerWindowHost = new Window() + { + SizeToContent = System.Windows.SizeToContent.Manual, + ResizeMode = ResizeMode.NoResize, + WindowStyle = System.Windows.WindowStyle.None, + ShowInTaskbar = false, + AllowsTransparency = true, + Background = null, + Width = actualSize.Width, + Height = actualSize.Height, + Left = ptTopLeftScreen.X, + Top = ptTopLeftScreen.Y, + ShowActivated = false, + //Owner = Window.GetWindow(this), + Content = panelHostResizer + }; + _resizerWindowHost.Loaded += ( s, e ) => + { + _resizerWindowHost.SetParentToMainWindowOf( this ); + }; + _resizerWindowHost.Show(); } + + private void HideResizerOverlayWindow() + { + if( _resizerWindowHost != null ) + { + _resizerWindowHost.Close(); + _resizerWindowHost = null; + } + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutGridResizerControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutGridResizerControl.cs index 709f6c47..6347f96b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutGridResizerControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutGridResizerControl.cs @@ -14,70 +14,83 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Controls.Primitives; using System.Windows; using System.Windows.Media; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutGridResizerControl : Thumb + public class LayoutGridResizerControl : Thumb + { + #region Constructors + + static LayoutGridResizerControl() + { + //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. + //This style is defined in themes\generic.xaml + DefaultStyleKeyProperty.OverrideMetadata( typeof( LayoutGridResizerControl ), new FrameworkPropertyMetadata( typeof( LayoutGridResizerControl ) ) ); + HorizontalAlignmentProperty.OverrideMetadata( typeof( LayoutGridResizerControl ), new FrameworkPropertyMetadata( HorizontalAlignment.Stretch, FrameworkPropertyMetadataOptions.AffectsParentMeasure ) ); + VerticalAlignmentProperty.OverrideMetadata( typeof( LayoutGridResizerControl ), new FrameworkPropertyMetadata( VerticalAlignment.Stretch, FrameworkPropertyMetadataOptions.AffectsParentMeasure ) ); + BackgroundProperty.OverrideMetadata( typeof( LayoutGridResizerControl ), new FrameworkPropertyMetadata( Brushes.Transparent ) ); + IsHitTestVisibleProperty.OverrideMetadata( typeof( LayoutGridResizerControl ), new FrameworkPropertyMetadata( true, null ) ); + } + + #endregion + + #region Properties + + #region BackgroundWhileDragging + + /// + /// BackgroundWhileDragging Dependency Property + /// + public static readonly DependencyProperty BackgroundWhileDraggingProperty = DependencyProperty.Register( "BackgroundWhileDragging", typeof( Brush ), typeof( LayoutGridResizerControl ), + new FrameworkPropertyMetadata( ( Brush )Brushes.Black ) ); + + /// + /// Gets or sets the BackgroundWhileDragging property. This dependency property + /// indicates .... + /// + public Brush BackgroundWhileDragging { - static LayoutGridResizerControl() - { - //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. - //This style is defined in themes\generic.xaml - DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutGridResizerControl), new FrameworkPropertyMetadata(typeof(LayoutGridResizerControl))); - HorizontalAlignmentProperty.OverrideMetadata(typeof(LayoutGridResizerControl), new FrameworkPropertyMetadata(HorizontalAlignment.Stretch, FrameworkPropertyMetadataOptions.AffectsParentMeasure)); - VerticalAlignmentProperty.OverrideMetadata(typeof(LayoutGridResizerControl), new FrameworkPropertyMetadata(VerticalAlignment.Stretch, FrameworkPropertyMetadataOptions.AffectsParentMeasure)); - BackgroundProperty.OverrideMetadata(typeof(LayoutGridResizerControl), new FrameworkPropertyMetadata(Brushes.Transparent)); - IsHitTestVisibleProperty.OverrideMetadata(typeof(LayoutGridResizerControl), new FrameworkPropertyMetadata(true, null)); - } - - - #region BackgroundWhileDragging - - /// - /// BackgroundWhileDragging Dependency Property - /// - public static readonly DependencyProperty BackgroundWhileDraggingProperty = - DependencyProperty.Register("BackgroundWhileDragging", typeof(Brush), typeof(LayoutGridResizerControl), - new FrameworkPropertyMetadata((Brush)Brushes.Black)); - - /// - /// Gets or sets the BackgroundWhileDragging property. This dependency property - /// indicates .... - /// - public Brush BackgroundWhileDragging - { - get { return (Brush)GetValue(BackgroundWhileDraggingProperty); } - set { SetValue(BackgroundWhileDraggingProperty, value); } - } - - #endregion - - #region OpacityWhileDragging - - /// - /// OpacityWhileDragging Dependency Property - /// - public static readonly DependencyProperty OpacityWhileDraggingProperty = - DependencyProperty.Register("OpacityWhileDragging", typeof(double), typeof(LayoutGridResizerControl), - new FrameworkPropertyMetadata((double)0.5)); - - /// - /// Gets or sets the OpacityWhileDragging property. This dependency property - /// indicates .... - /// - public double OpacityWhileDragging - { - get { return (double)GetValue(OpacityWhileDraggingProperty); } - set { SetValue(OpacityWhileDraggingProperty, value); } - } - - #endregion + get + { + return ( Brush )GetValue( BackgroundWhileDraggingProperty ); + } + set + { + SetValue( BackgroundWhileDraggingProperty, value ); + } } + + #endregion + + #region OpacityWhileDragging + + /// + /// OpacityWhileDragging Dependency Property + /// + public static readonly DependencyProperty OpacityWhileDraggingProperty = DependencyProperty.Register( "OpacityWhileDragging", typeof( double ), typeof( LayoutGridResizerControl ), + new FrameworkPropertyMetadata( ( double )0.5 ) ); + + /// + /// Gets or sets the OpacityWhileDragging property. This dependency property + /// indicates .... + /// + public double OpacityWhileDragging + { + get + { + return ( double )GetValue( OpacityWhileDraggingProperty ); + } + set + { + SetValue( OpacityWhileDraggingProperty, value ); + } + } + + #endregion + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutItem.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutItem.cs index b1cd8e7d..236d9e90 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutItem.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutItem.cs @@ -15,513 +15,414 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using Xceed.Wpf.AvalonDock.Layout; using System.Windows.Input; using Xceed.Wpf.AvalonDock.Commands; -using System.ComponentModel; using System.Windows.Data; using System.Windows.Media; using System.Windows.Controls; namespace Xceed.Wpf.AvalonDock.Controls { - public abstract class LayoutItem : FrameworkElement + public abstract class LayoutItem : FrameworkElement + { + #region Members + + private ICommand _defaultCloseCommand; + private ICommand _defaultFloatCommand; + private ICommand _defaultDockAsDocumentCommand; + private ICommand _defaultCloseAllButThisCommand; + private ICommand _defaultCloseAllCommand; + private ICommand _defaultActivateCommand; + private ICommand _defaultNewVerticalTabGroupCommand; + private ICommand _defaultNewHorizontalTabGroupCommand; + private ICommand _defaultMoveToNextTabGroupCommand; + private ICommand _defaultMoveToPreviousTabGroupCommand; + private ContentPresenter _view = null; + private ReentrantFlag _isSelectedReentrantFlag = new ReentrantFlag(); + private ReentrantFlag _isActiveReentrantFlag = new ReentrantFlag(); + + #endregion + + #region Constructors + + static LayoutItem() { - static LayoutItem() - { - ToolTipProperty.OverrideMetadata(typeof(LayoutItem), new FrameworkPropertyMetadata(null, (s, e) => OnToolTipChanged(s,e))); - VisibilityProperty.OverrideMetadata(typeof(LayoutItem), new FrameworkPropertyMetadata(Visibility.Visible, (s,e) => OnVisibilityChanged(s, e))); - } - - - internal LayoutItem() - { - - } - - internal virtual void Attach(LayoutContent model) - { - LayoutElement = model; - Model = model.Content; - - InitDefaultCommands(); - - LayoutElement.IsSelectedChanged+=new EventHandler(LayoutElement_IsSelectedChanged); - LayoutElement.IsActiveChanged+=new EventHandler(LayoutElement_IsActiveChanged); - - DataContext = this; - System.Diagnostics.Trace.WriteLine( string.Format( "Attach({0})", LayoutElement.Title ) ); - } - - + ToolTipProperty.OverrideMetadata( typeof( LayoutItem ), new FrameworkPropertyMetadata( null, ( s, e ) => OnToolTipChanged( s, e ) ) ); + VisibilityProperty.OverrideMetadata( typeof( LayoutItem ), new FrameworkPropertyMetadata( Visibility.Visible, ( s, e ) => OnVisibilityChanged( s, e ) ) ); + } - void LayoutElement_IsActiveChanged(object sender, EventArgs e) - { - if (_isActiveReentrantFlag.CanEnter) - { - using (_isActiveReentrantFlag.Enter()) - { - var bnd = BindingOperations.GetBinding(this, IsActiveProperty); - IsActive = LayoutElement.IsActive; - var bnd2 = BindingOperations.GetBinding(this, IsActiveProperty); - } - } - } - void LayoutElement_IsSelectedChanged(object sender, EventArgs e) - { - if (_isSelectedReentrantFlag.CanEnter) - { - using (_isSelectedReentrantFlag.Enter()) - { - IsSelected = LayoutElement.IsSelected; - } - } - } + internal LayoutItem() + { + } - internal virtual void Detach() - { - System.Diagnostics.Trace.WriteLine( string.Format( "Detach({0})", LayoutElement.Title ) ); - LayoutElement.IsSelectedChanged -= new EventHandler(LayoutElement_IsSelectedChanged); - LayoutElement.IsActiveChanged -= new EventHandler(LayoutElement_IsActiveChanged); - LayoutElement = null; - Model = null; - } + #endregion - public LayoutContent LayoutElement - { - get; - private set; - } + #region Properties - public object Model - { - get; - private set; - } + #region LayoutElement - ICommand _defaultCloseCommand; - ICommand _defaultFloatCommand; - ICommand _defaultDockAsDocumentCommand; - ICommand _defaultCloseAllButThisCommand; - ICommand _defaultActivateCommand; - ICommand _defaultNewVerticalTabGroupCommand; - ICommand _defaultNewHorizontalTabGroupCommand; - ICommand _defaultMoveToNextTabGroupCommand; - ICommand _defaultMoveToPreviousTabGroupCommand; + public LayoutContent LayoutElement + { + get; + private set; + } - protected virtual void InitDefaultCommands() - { - _defaultCloseCommand = new RelayCommand((p) => ExecuteCloseCommand(p), (p) => CanExecuteCloseCommand(p)); - _defaultFloatCommand = new RelayCommand((p) => ExecuteFloatCommand(p), (p) => CanExecuteFloatCommand(p)); - _defaultDockAsDocumentCommand = new RelayCommand((p) => ExecuteDockAsDocumentCommand(p), (p) => CanExecuteDockAsDocumentCommand(p)); - _defaultCloseAllButThisCommand = new RelayCommand((p) => ExecuteCloseAllButThisCommand(p), (p) => CanExecuteCloseAllButThisCommand(p)); - _defaultActivateCommand = new RelayCommand((p) => ExecuteActivateCommand(p), (p) => CanExecuteActivateCommand(p)); - _defaultNewVerticalTabGroupCommand = new RelayCommand((p) => ExecuteNewVerticalTabGroupCommand(p), (p) => CanExecuteNewVerticalTabGroupCommand(p)); - _defaultNewHorizontalTabGroupCommand = new RelayCommand((p) => ExecuteNewHorizontalTabGroupCommand(p), (p) => CanExecuteNewHorizontalTabGroupCommand(p)); - _defaultMoveToNextTabGroupCommand = new RelayCommand((p) => ExecuteMoveToNextTabGroupCommand(p), (p) => CanExecuteMoveToNextTabGroupCommand(p)); - _defaultMoveToPreviousTabGroupCommand = new RelayCommand((p) => ExecuteMoveToPreviousTabGroupCommand(p), (p) => CanExecuteMoveToPreviousTabGroupCommand(p)); - } + #endregion - protected virtual void ClearDefaultBindings() - { - if (CloseCommand == _defaultCloseCommand) - BindingOperations.ClearBinding(this, CloseCommandProperty); - if (FloatCommand == _defaultFloatCommand) - BindingOperations.ClearBinding(this, FloatCommandProperty); - if (DockAsDocumentCommand == _defaultDockAsDocumentCommand) - BindingOperations.ClearBinding(this, DockAsDocumentCommandProperty); - if (CloseAllButThisCommand == _defaultCloseAllButThisCommand) - BindingOperations.ClearBinding(this, CloseAllButThisCommandProperty); - if (ActivateCommand == _defaultActivateCommand) - BindingOperations.ClearBinding(this, ActivateCommandProperty); - if (NewVerticalTabGroupCommand == _defaultNewVerticalTabGroupCommand) - BindingOperations.ClearBinding(this, NewVerticalTabGroupCommandProperty); - if (NewHorizontalTabGroupCommand == _defaultNewHorizontalTabGroupCommand) - BindingOperations.ClearBinding(this, NewHorizontalTabGroupCommandProperty); - if (MoveToNextTabGroupCommand == _defaultMoveToNextTabGroupCommand) - BindingOperations.ClearBinding(this, MoveToNextTabGroupCommandProperty); - if (MoveToPreviousTabGroupCommand == _defaultMoveToPreviousTabGroupCommand) - BindingOperations.ClearBinding(this, MoveToPreviousTabGroupCommandProperty); - } + #region Model - protected virtual void SetDefaultBindings() - { - if (CloseCommand == null) - CloseCommand = _defaultCloseCommand; - if (FloatCommand == null) - FloatCommand = _defaultFloatCommand; - if (DockAsDocumentCommand == null) - DockAsDocumentCommand = _defaultDockAsDocumentCommand; - if (CloseAllButThisCommand == null) - CloseAllButThisCommand = _defaultCloseAllButThisCommand; - if (ActivateCommand == null) - ActivateCommand = _defaultActivateCommand; - if (NewVerticalTabGroupCommand == null) - NewVerticalTabGroupCommand = _defaultNewVerticalTabGroupCommand; - if (NewHorizontalTabGroupCommand == null) - NewHorizontalTabGroupCommand = _defaultNewHorizontalTabGroupCommand; - if (MoveToNextTabGroupCommand == null) - MoveToNextTabGroupCommand = _defaultMoveToNextTabGroupCommand; - if (MoveToPreviousTabGroupCommand == null) - MoveToPreviousTabGroupCommand = _defaultMoveToPreviousTabGroupCommand; - - - IsSelected = LayoutElement.IsSelected; - IsActive = LayoutElement.IsActive; - } + public object Model + { + get; + private set; + } - internal void _ClearDefaultBindings() - { - ClearDefaultBindings(); - } + #endregion - internal void _SetDefaultBindings() - { - SetDefaultBindings(); - } + #region View - ContentPresenter _view = null; - public ContentPresenter View - { - get + public ContentPresenter View + { + get + { + if( _view == null ) + { + _view = new ContentPresenter(); + + _view.SetBinding( ContentPresenter.ContentProperty, new Binding( "Content" ) { Source = LayoutElement } ); + if( ( LayoutElement != null ) && ( LayoutElement.Root != null ) ) + { + _view.SetBinding( ContentPresenter.ContentTemplateProperty, new Binding( "LayoutItemTemplate" ) { Source = LayoutElement.Root.Manager } ); + _view.SetBinding( ContentPresenter.ContentTemplateSelectorProperty, new Binding( "LayoutItemTemplateSelector" ) { Source = LayoutElement.Root.Manager } ); + if( LayoutElement.Root.Manager != null ) { - if (_view == null) - { - _view = new ContentPresenter(); - - _view.SetBinding(ContentPresenter.ContentProperty, new Binding("Content") { Source = LayoutElement }); - _view.SetBinding(ContentPresenter.ContentTemplateProperty, new Binding("LayoutItemTemplate") { Source = LayoutElement.Root.Manager}); - _view.SetBinding(ContentPresenter.ContentTemplateSelectorProperty, new Binding("LayoutItemTemplateSelector") { Source = LayoutElement.Root.Manager }); - LayoutElement.Root.Manager.InternalAddLogicalChild(_view); - } - - return _view; + LayoutElement.Root.Manager.InternalAddLogicalChild( _view ); } + } } + return _view; + } + } - #region Title - - /// - /// Title Dependency Property - /// - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register("Title", typeof(string), typeof(LayoutItem), - new FrameworkPropertyMetadata((string)null, - new PropertyChangedCallback(OnTitleChanged))); - - /// - /// Gets or sets the Title property. This dependency property - /// indicates the title of the element. - /// - public string Title - { - get { return (string)GetValue(TitleProperty); } - set { SetValue(TitleProperty, value); } - } - - /// - /// Handles changes to the Title property. - /// - private static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnTitleChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the Title property. - /// - protected virtual void OnTitleChanged(DependencyPropertyChangedEventArgs e) - { - if (LayoutElement != null) - LayoutElement.Title = (string)e.NewValue; - } - - #endregion - - #region ToolTip - private static void OnToolTipChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)s).OnToolTipChanged(); - } + #endregion - private void OnToolTipChanged() - { - if (LayoutElement != null) - LayoutElement.ToolTip = ToolTip; - } - #endregion + #region Title - #region IconSource + /// + /// Title Dependency Property + /// + public static readonly DependencyProperty TitleProperty = DependencyProperty.Register( "Title", typeof( string ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( string )null, new PropertyChangedCallback( OnTitleChanged ) ) ); - /// - /// IconSource Dependency Property - /// - public static readonly DependencyProperty IconSourceProperty = - DependencyProperty.Register("IconSource", typeof(ImageSource), typeof(LayoutItem), - new FrameworkPropertyMetadata((ImageSource)null, - new PropertyChangedCallback(OnIconSourceChanged))); + /// + /// Gets or sets the Title property. This dependency property + /// indicates the title of the element. + /// + public string Title + { + get + { + return ( string )GetValue( TitleProperty ); + } + set + { + SetValue( TitleProperty, value ); + } + } - /// - /// Gets or sets the IconSource property. This dependency property - /// indicates icon associated with the item. - /// - public ImageSource IconSource - { - get { return (ImageSource)GetValue(IconSourceProperty); } - set { SetValue(IconSourceProperty, value); } - } + /// + /// Handles changes to the Title property. + /// + private static void OnTitleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnTitleChanged( e ); + } - /// - /// Handles changes to the IconSource property. - /// - private static void OnIconSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnIconSourceChanged(e); - } + /// + /// Provides derived classes an opportunity to handle changes to the Title property. + /// + protected virtual void OnTitleChanged( DependencyPropertyChangedEventArgs e ) + { + if( LayoutElement != null ) + LayoutElement.Title = ( string )e.NewValue; + } - /// - /// Provides derived classes an opportunity to handle changes to the IconSource property. - /// - protected virtual void OnIconSourceChanged(DependencyPropertyChangedEventArgs e) - { - if (LayoutElement != null) - LayoutElement.IconSource = IconSource; - } + #endregion - #endregion + #region IconSource - #region Visibility + /// + /// IconSource Dependency Property + /// + public static readonly DependencyProperty IconSourceProperty = DependencyProperty.Register( "IconSource", typeof( ImageSource ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( ImageSource )null, new PropertyChangedCallback( OnIconSourceChanged ) ) ); - private static void OnVisibilityChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)s).OnVisibilityChanged(); - } + /// + /// Gets or sets the IconSource property. This dependency property + /// indicates icon associated with the item. + /// + public ImageSource IconSource + { + get + { + return ( ImageSource )GetValue( IconSourceProperty ); + } + set + { + SetValue( IconSourceProperty, value ); + } + } - protected virtual void OnVisibilityChanged() - { - if (LayoutElement != null && - Visibility == System.Windows.Visibility.Collapsed) - LayoutElement.Close(); - } + /// + /// Handles changes to the IconSource property. + /// + private static void OnIconSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnIconSourceChanged( e ); + } - #endregion + /// + /// Provides derived classes an opportunity to handle changes to the IconSource property. + /// + protected virtual void OnIconSourceChanged( DependencyPropertyChangedEventArgs e ) + { + if( LayoutElement != null ) + LayoutElement.IconSource = IconSource; + } - #region ContentId + #endregion - /// - /// ContentId Dependency Property - /// - public static readonly DependencyProperty ContentIdProperty = - DependencyProperty.Register("ContentId", typeof(string), typeof(LayoutItem), - new FrameworkPropertyMetadata((string)null, - new PropertyChangedCallback(OnContentIdChanged))); + #region ContentId - /// - /// Gets or sets the ContentId property. This dependency property - /// indicates the content id used to retrive content when deserializing layouts. - /// - public string ContentId - { - get { return (string)GetValue(ContentIdProperty); } - set { SetValue(ContentIdProperty, value); } - } + /// + /// ContentId Dependency Property + /// + public static readonly DependencyProperty ContentIdProperty = DependencyProperty.Register( "ContentId", typeof( string ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( string )null, new PropertyChangedCallback( OnContentIdChanged ) ) ); - /// - /// Handles changes to the ContentId property. - /// - private static void OnContentIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnContentIdChanged(e); - } + /// + /// Gets or sets the ContentId property. This dependency property + /// indicates the content id used to retrive content when deserializing layouts. + /// + public string ContentId + { + get + { + return ( string )GetValue( ContentIdProperty ); + } + set + { + SetValue( ContentIdProperty, value ); + } + } - /// - /// Provides derived classes an opportunity to handle changes to the ContentId property. - /// - protected virtual void OnContentIdChanged(DependencyPropertyChangedEventArgs e) - { - if (LayoutElement != null) - LayoutElement.ContentId = (string)e.NewValue; - } + /// + /// Handles changes to the ContentId property. + /// + private static void OnContentIdChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnContentIdChanged( e ); + } - #endregion + /// + /// Provides derived classes an opportunity to handle changes to the ContentId property. + /// + protected virtual void OnContentIdChanged( DependencyPropertyChangedEventArgs e ) + { + if( LayoutElement != null ) + LayoutElement.ContentId = ( string )e.NewValue; + } - #region IsSelected + #endregion - ReentrantFlag _isSelectedReentrantFlag = new ReentrantFlag(); + #region IsSelected - /// - /// IsSelected Dependency Property - /// - public static readonly DependencyProperty IsSelectedProperty = - DependencyProperty.Register("IsSelected", typeof(bool), typeof(LayoutItem), - new FrameworkPropertyMetadata((bool)false, - new PropertyChangedCallback(OnIsSelectedChanged))); + /// + /// IsSelected Dependency Property + /// + public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( "IsSelected", typeof( bool ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( bool )false, new PropertyChangedCallback( OnIsSelectedChanged ) ) ); - /// - /// Gets or sets the IsSelected property. This dependency property - /// indicates if the item is selected inside its container. - /// - public bool IsSelected - { - get { return (bool)GetValue(IsSelectedProperty); } - set { SetValue(IsSelectedProperty, value); } - } + /// + /// Gets or sets the IsSelected property. This dependency property + /// indicates if the item is selected inside its container. + /// + public bool IsSelected + { + get + { + return ( bool )GetValue( IsSelectedProperty ); + } + set + { + SetValue( IsSelectedProperty, value ); + } + } - /// - /// Handles changes to the IsSelected property. - /// - private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnIsSelectedChanged(e); - } + /// + /// Handles changes to the IsSelected property. + /// + private static void OnIsSelectedChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnIsSelectedChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the IsSelected property. - /// - protected virtual void OnIsSelectedChanged(DependencyPropertyChangedEventArgs e) + /// + /// Provides derived classes an opportunity to handle changes to the IsSelected property. + /// + protected virtual void OnIsSelectedChanged( DependencyPropertyChangedEventArgs e ) + { + if( _isSelectedReentrantFlag.CanEnter ) + { + using( _isSelectedReentrantFlag.Enter() ) { - if (_isSelectedReentrantFlag.CanEnter) - { - using (_isSelectedReentrantFlag.Enter()) - { - if (LayoutElement != null) - LayoutElement.IsSelected = (bool)e.NewValue; - } - } + if( LayoutElement != null ) + LayoutElement.IsSelected = ( bool )e.NewValue; } + } + } - #endregion - - #region IsActive + #endregion - ReentrantFlag _isActiveReentrantFlag = new ReentrantFlag(); + #region IsActive - /// - /// IsActive Dependency Property - /// - public static readonly DependencyProperty IsActiveProperty = - DependencyProperty.Register("IsActive", typeof(bool), typeof(LayoutItem), - new FrameworkPropertyMetadata((bool)false, - new PropertyChangedCallback(OnIsActiveChanged))); + /// + /// IsActive Dependency Property + /// + public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register( "IsActive", typeof( bool ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( bool )false, new PropertyChangedCallback( OnIsActiveChanged ) ) ); - /// - /// Gets or sets the IsActive property. This dependency property - /// indicates if the item is active in the UI. - /// - public bool IsActive - { - get { return (bool)GetValue(IsActiveProperty); } - set { SetValue(IsActiveProperty, value); } - } + /// + /// Gets or sets the IsActive property. This dependency property + /// indicates if the item is active in the UI. + /// + public bool IsActive + { + get + { + return ( bool )GetValue( IsActiveProperty ); + } + set + { + SetValue( IsActiveProperty, value ); + } + } - /// - /// Handles changes to the IsActive property. - /// - private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnIsActiveChanged(e); - } + /// + /// Handles changes to the IsActive property. + /// + private static void OnIsActiveChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnIsActiveChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the IsActive property. - /// - protected virtual void OnIsActiveChanged(DependencyPropertyChangedEventArgs e) + /// + /// Provides derived classes an opportunity to handle changes to the IsActive property. + /// + protected virtual void OnIsActiveChanged( DependencyPropertyChangedEventArgs e ) + { + if( _isActiveReentrantFlag.CanEnter ) + { + using( _isActiveReentrantFlag.Enter() ) { - if (_isActiveReentrantFlag.CanEnter) - { - using (_isActiveReentrantFlag.Enter()) - { - if (LayoutElement != null) - LayoutElement.IsActive = (bool)e.NewValue; - } - } + if( LayoutElement != null ) + LayoutElement.IsActive = ( bool )e.NewValue; } + } + } - #endregion + #endregion - #region CanClose + #region CanClose - /// - /// CanClose Dependency Property - /// - public static readonly DependencyProperty CanCloseProperty = - DependencyProperty.Register("CanClose", typeof(bool), typeof(LayoutItem), - new FrameworkPropertyMetadata((bool)true, - new PropertyChangedCallback(OnCanCloseChanged))); + /// + /// CanClose Dependency Property + /// + public static readonly DependencyProperty CanCloseProperty = DependencyProperty.Register( "CanClose", typeof( bool ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( bool )true, new PropertyChangedCallback( OnCanCloseChanged ) ) ); - /// - /// Gets or sets the CanClose property. This dependency property - /// indicates if the item can be closed. - /// - public bool CanClose - { - get { return (bool)GetValue(CanCloseProperty); } - set { SetValue(CanCloseProperty, value); } - } + /// + /// Gets or sets the CanClose property. This dependency property + /// indicates if the item can be closed. + /// + public bool CanClose + { + get + { + return ( bool )GetValue( CanCloseProperty ); + } + set + { + SetValue( CanCloseProperty, value ); + } + } - /// - /// Handles changes to the CanClose property. - /// - private static void OnCanCloseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnCanCloseChanged(e); - } + /// + /// Handles changes to the CanClose property. + /// + private static void OnCanCloseChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnCanCloseChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the CanClose property. - /// - protected virtual void OnCanCloseChanged(DependencyPropertyChangedEventArgs e) - { - if (LayoutElement != null) - LayoutElement.CanClose = (bool)e.NewValue; - } + /// + /// Provides derived classes an opportunity to handle changes to the CanClose property. + /// + protected virtual void OnCanCloseChanged( DependencyPropertyChangedEventArgs e ) + { + if( LayoutElement != null ) + LayoutElement.CanClose = ( bool )e.NewValue; + } - #endregion + #endregion - #region CanFloat + #region CanFloat - /// - /// CanFloat Dependency Property - /// - public static readonly DependencyProperty CanFloatProperty = - DependencyProperty.Register("CanFloat", typeof(bool), typeof(LayoutItem), - new FrameworkPropertyMetadata((bool)true, - new PropertyChangedCallback(OnCanFloatChanged))); + /// + /// CanFloat Dependency Property + /// + public static readonly DependencyProperty CanFloatProperty = DependencyProperty.Register( "CanFloat", typeof( bool ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( bool )true, new PropertyChangedCallback( OnCanFloatChanged ) ) ); - /// - /// Gets or sets the CanFloat property. This dependency property - /// indicates if user can move the layout element dragging it to another position. - /// - public bool CanFloat - { - get { return (bool)GetValue(CanFloatProperty); } - set { SetValue(CanFloatProperty, value); } - } + /// + /// Gets or sets the CanFloat property. This dependency property + /// indicates if user can move the layout element dragging it to another position. + /// + public bool CanFloat + { + get + { + return ( bool )GetValue( CanFloatProperty ); + } + set + { + SetValue( CanFloatProperty, value ); + } + } - /// - /// Handles changes to the CanFloat property. - /// - private static void OnCanFloatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnCanFloatChanged(e); - } + /// + /// Handles changes to the CanFloat property. + /// + private static void OnCanFloatChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnCanFloatChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the CanFloat property. - /// - protected virtual void OnCanFloatChanged(DependencyPropertyChangedEventArgs e) - { - if (LayoutElement != null) - LayoutElement.CanFloat = (bool)e.NewValue; - } + /// + /// Provides derived classes an opportunity to handle changes to the CanFloat property. + /// + protected virtual void OnCanFloatChanged( DependencyPropertyChangedEventArgs e ) + { + if( LayoutElement != null ) + LayoutElement.CanFloat = ( bool )e.NewValue; + } - #endregion + #endregion #region CanDock @@ -548,572 +449,826 @@ namespace Xceed.Wpf.AvalonDock.Controls #endregion + #endregion + + #region Commands + #region CloseCommand /// /// CloseCommand Dependency Property /// - public static readonly DependencyProperty CloseCommandProperty = - DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnCloseCommandChanged), - new CoerceValueCallback(CoerceCloseCommandValue))); + public static readonly DependencyProperty CloseCommandProperty = DependencyProperty.Register( "CloseCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnCloseCommandChanged ), new CoerceValueCallback( CoerceCloseCommandValue ) ) ); - /// - /// Gets or sets the CloseCommand property. This dependency property - /// indicates the command to execute when user click the document close button. - /// - public ICommand CloseCommand - { - get { return (ICommand)GetValue(CloseCommandProperty); } - set { SetValue(CloseCommandProperty, value); } - } + /// + /// Gets or sets the CloseCommand property. This dependency property + /// indicates the command to execute when user click the document close button. + /// + public ICommand CloseCommand + { + get + { + return ( ICommand )GetValue( CloseCommandProperty ); + } + set + { + SetValue( CloseCommandProperty, value ); + } + } - /// - /// Handles changes to the CloseCommand property. - /// - private static void OnCloseCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnCloseCommandChanged(e); - } + /// + /// Handles changes to the CloseCommand property. + /// + private static void OnCloseCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnCloseCommandChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the CloseCommand property. - /// - protected virtual void OnCloseCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + /// + /// Provides derived classes an opportunity to handle changes to the CloseCommand property. + /// + protected virtual void OnCloseCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - /// - /// Coerces the CloseCommand value. - /// - private static object CoerceCloseCommandValue(DependencyObject d, object value) - { - return value; - } + /// + /// Coerces the CloseCommand value. + /// + private static object CoerceCloseCommandValue( DependencyObject d, object value ) + { + return value; + } - private bool CanExecuteCloseCommand(object parameter) - { -#if DEBUG - if( LayoutElement != null ) - System.Diagnostics.Trace.WriteLine( string.Format( "CanExecuteCloseCommand({0}) = {1}", LayoutElement.Title, LayoutElement.CanClose ) ); -#endif - return LayoutElement != null && LayoutElement.CanClose; - } + private bool CanExecuteCloseCommand( object parameter ) + { + return LayoutElement != null && LayoutElement.CanClose; + } - private void ExecuteCloseCommand(object parameter) - { - Close(); - } + private void ExecuteCloseCommand( object parameter ) + { + Close(); + } - protected abstract void Close(); + protected abstract void Close(); - #endregion + #endregion - #region FloatCommand - /// - /// FloatCommand Dependency Property - /// - public static readonly DependencyProperty FloatCommandProperty = - DependencyProperty.Register("FloatCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnFloatCommandChanged), - new CoerceValueCallback(CoerceFloatCommandValue))); + #region FloatCommand + /// + /// FloatCommand Dependency Property + /// + public static readonly DependencyProperty FloatCommandProperty = DependencyProperty.Register( "FloatCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnFloatCommandChanged ), new CoerceValueCallback( CoerceFloatCommandValue ) ) ); - /// - /// Gets or sets the FloatCommand property. This dependency property - /// indicates the command to execute when user click the float button. - /// - /// By default this command move the anchorable inside new floating window. - public ICommand FloatCommand - { - get { return (ICommand)GetValue(FloatCommandProperty); } - set { SetValue(FloatCommandProperty, value); } - } + /// + /// Gets or sets the FloatCommand property. This dependency property + /// indicates the command to execute when user click the float button. + /// + /// By default this command move the anchorable inside new floating window. + public ICommand FloatCommand + { + get + { + return ( ICommand )GetValue( FloatCommandProperty ); + } + set + { + SetValue( FloatCommandProperty, value ); + } + } - /// - /// Handles changes to the FloatCommand property. - /// - private static void OnFloatCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnFloatCommandChanged(e); - } + /// + /// Handles changes to the FloatCommand property. + /// + private static void OnFloatCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnFloatCommandChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the FloatCommand property. - /// - protected virtual void OnFloatCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + /// + /// Provides derived classes an opportunity to handle changes to the FloatCommand property. + /// + protected virtual void OnFloatCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - /// - /// Coerces the FloatCommand value. - /// - private static object CoerceFloatCommandValue(DependencyObject d, object value) - { - return value; - } + /// + /// Coerces the FloatCommand value. + /// + private static object CoerceFloatCommandValue( DependencyObject d, object value ) + { + return value; + } - private bool CanExecuteFloatCommand(object anchorable) - { - return LayoutElement != null && LayoutElement.CanFloat && LayoutElement.FindParent() == null; - } + private bool CanExecuteFloatCommand( object anchorable ) + { + return LayoutElement != null && LayoutElement.CanFloat && LayoutElement.FindParent() == null; + } - private void ExecuteFloatCommand(object parameter) - { - LayoutElement.Root.Manager._ExecuteFloatCommand(LayoutElement); - } + private void ExecuteFloatCommand( object parameter ) + { + LayoutElement.Root.Manager._ExecuteFloatCommand( LayoutElement ); + } - protected virtual void Float() - { + protected virtual void Float() + { - } + } - #endregion + #endregion - #region DockAsDocumentCommand + #region DockAsDocumentCommand - /// - /// DockAsDocumentCommand Dependency Property - /// - public static readonly DependencyProperty DockAsDocumentCommandProperty = - DependencyProperty.Register("DockAsDocumentCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnDockAsDocumentCommandChanged), - new CoerceValueCallback(CoerceDockAsDocumentCommandValue))); + /// + /// DockAsDocumentCommand Dependency Property + /// + public static readonly DependencyProperty DockAsDocumentCommandProperty = DependencyProperty.Register( "DockAsDocumentCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnDockAsDocumentCommandChanged ), new CoerceValueCallback( CoerceDockAsDocumentCommandValue ) ) ); - /// - /// Gets or sets the DockAsDocumentCommand property. This dependency property - /// indicates the command to execute when user click the DockAsDocument button. - /// - /// By default this command move the anchorable inside the last focused document pane. - public ICommand DockAsDocumentCommand - { - get { return (ICommand)GetValue(DockAsDocumentCommandProperty); } - set { SetValue(DockAsDocumentCommandProperty, value); } - } + /// + /// Gets or sets the DockAsDocumentCommand property. This dependency property + /// indicates the command to execute when user click the DockAsDocument button. + /// + /// By default this command move the anchorable inside the last focused document pane. + public ICommand DockAsDocumentCommand + { + get + { + return ( ICommand )GetValue( DockAsDocumentCommandProperty ); + } + set + { + SetValue( DockAsDocumentCommandProperty, value ); + } + } - /// - /// Handles changes to the DockAsDocumentCommand property. - /// - private static void OnDockAsDocumentCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnDockAsDocumentCommandChanged(e); - } + /// + /// Handles changes to the DockAsDocumentCommand property. + /// + private static void OnDockAsDocumentCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnDockAsDocumentCommandChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the DockAsDocumentCommand property. - /// - protected virtual void OnDockAsDocumentCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + /// + /// Provides derived classes an opportunity to handle changes to the DockAsDocumentCommand property. + /// + protected virtual void OnDockAsDocumentCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - /// - /// Coerces the DockAsDocumentCommand value. - /// - private static object CoerceDockAsDocumentCommandValue(DependencyObject d, object value) - { - return value; - } + /// + /// Coerces the DockAsDocumentCommand value. + /// + private static object CoerceDockAsDocumentCommandValue( DependencyObject d, object value ) + { + return value; + } private bool CanExecuteDockAsDocumentCommand(object parameter) { return LayoutElement != null && LayoutElement.CanDock && LayoutElement.FindParent() == null; } - private void ExecuteDockAsDocumentCommand(object parameter) - { - LayoutElement.Root.Manager._ExecuteDockAsDocumentCommand(LayoutElement); - } + private void ExecuteDockAsDocumentCommand( object parameter ) + { + LayoutElement.Root.Manager._ExecuteDockAsDocumentCommand( LayoutElement ); + } - #endregion + #endregion - #region CloseAllButThisCommand + #region CloseAllButThisCommand - /// - /// CloseAllButThisCommand Dependency Property - /// - public static readonly DependencyProperty CloseAllButThisCommandProperty = - DependencyProperty.Register("CloseAllButThisCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnCloseAllButThisCommandChanged), - new CoerceValueCallback(CoerceCloseAllButThisCommandValue))); + /// + /// CloseAllButThisCommand Dependency Property + /// + public static readonly DependencyProperty CloseAllButThisCommandProperty = DependencyProperty.Register( "CloseAllButThisCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnCloseAllButThisCommandChanged ), new CoerceValueCallback( CoerceCloseAllButThisCommandValue ) ) ); - /// - /// Gets or sets the CloseAllButThisCommand property. This dependency property - /// indicates the 'Close All But This' command. - /// - public ICommand CloseAllButThisCommand - { - get { return (ICommand)GetValue(CloseAllButThisCommandProperty); } - set { SetValue(CloseAllButThisCommandProperty, value); } - } + /// + /// Gets or sets the CloseAllButThisCommand property. This dependency property + /// indicates the 'Close All But This' command. + /// + public ICommand CloseAllButThisCommand + { + get + { + return ( ICommand )GetValue( CloseAllButThisCommandProperty ); + } + set + { + SetValue( CloseAllButThisCommandProperty, value ); + } + } - /// - /// Handles changes to the CloseAllButThisCommand property. - /// - private static void OnCloseAllButThisCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnCloseAllButThisCommandChanged(e); - } + /// + /// Handles changes to the CloseAllButThisCommand property. + /// + private static void OnCloseAllButThisCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnCloseAllButThisCommandChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the CloseAllButThisCommand property. - /// - protected virtual void OnCloseAllButThisCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + /// + /// Provides derived classes an opportunity to handle changes to the CloseAllButThisCommand property. + /// + protected virtual void OnCloseAllButThisCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - /// - /// Coerces the CloseAllButThisCommand value. - /// - private static object CoerceCloseAllButThisCommandValue(DependencyObject d, object value) - { - return value; - } + /// + /// Coerces the CloseAllButThisCommand value. + /// + private static object CoerceCloseAllButThisCommandValue( DependencyObject d, object value ) + { + return value; + } - private bool CanExecuteCloseAllButThisCommand(object parameter) - { - if (LayoutElement == null) - return false; - var root = LayoutElement.Root; - if (root == null) - return false; - - return LayoutElement.Root.Manager.Layout. - Descendents().OfType().Where(d => d != LayoutElement && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).Any(); - } + private bool CanExecuteCloseAllButThisCommand( object parameter ) + { + if( LayoutElement == null ) + return false; + var root = LayoutElement.Root; + if( root == null ) + return false; + + return LayoutElement.Root.Manager.Layout. + Descendents().OfType().Where( d => d != LayoutElement && ( d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow ) ).Any(); + } - private void ExecuteCloseAllButThisCommand(object parameter) - { - LayoutElement.Root.Manager._ExecuteCloseAllButThisCommand(LayoutElement); - } + private void ExecuteCloseAllButThisCommand( object parameter ) + { + LayoutElement.Root.Manager._ExecuteCloseAllButThisCommand( LayoutElement ); + } - #endregion + #endregion - #region ActivateCommand + #region CloseAllCommand - /// - /// ActivateCommand Dependency Property - /// - public static readonly DependencyProperty ActivateCommandProperty = - DependencyProperty.Register("ActivateCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnActivateCommandChanged), - new CoerceValueCallback(CoerceActivateCommandValue))); + /// + /// CloseAllCommand Dependency Property + /// + public static readonly DependencyProperty CloseAllCommandProperty = DependencyProperty.Register( "CloseAllCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnCloseAllCommandChanged ), new CoerceValueCallback( CoerceCloseAllCommandValue ) ) ); - /// - /// Gets or sets the ActivateCommand property. This dependency property - /// indicates the command to execute when user wants to activate a content (either a Document or an Anchorable). - /// - public ICommand ActivateCommand - { - get { return (ICommand)GetValue(ActivateCommandProperty); } - set { SetValue(ActivateCommandProperty, value); } - } + /// + /// Gets or sets the CloseAllCommand property. This dependency property + /// indicates the 'Close All' command. + /// + public ICommand CloseAllCommand + { + get + { + return ( ICommand )GetValue( CloseAllCommandProperty ); + } + set + { + SetValue( CloseAllCommandProperty, value ); + } + } - /// - /// Handles changes to the ActivateCommand property. - /// - private static void OnActivateCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnActivateCommandChanged(e); - } + /// + /// Handles changes to the CloseAllCommand property. + /// + private static void OnCloseAllCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnCloseAllCommandChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the ActivateCommand property. - /// - protected virtual void OnActivateCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + /// + /// Provides derived classes an opportunity to handle changes to the CloseAllCommand property. + /// + protected virtual void OnCloseAllCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - /// - /// Coerces the ActivateCommand value. - /// - private static object CoerceActivateCommandValue(DependencyObject d, object value) - { - return value; - } + /// + /// Coerces the CloseAllCommand value. + /// + private static object CoerceCloseAllCommandValue( DependencyObject d, object value ) + { + return value; + } - private bool CanExecuteActivateCommand(object parameter) - { - return LayoutElement != null; - } + private bool CanExecuteCloseAllCommand( object parameter ) + { + if( LayoutElement == null ) + return false; + var root = LayoutElement.Root; + if( root == null ) + return false; + + return LayoutElement.Root.Manager.Layout. + Descendents().OfType().Where( d => ( d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow ) ).Any(); + } - private void ExecuteActivateCommand(object parameter) - { - LayoutElement.Root.Manager._ExecuteContentActivateCommand(LayoutElement); - } + private void ExecuteCloseAllCommand( object parameter ) + { + LayoutElement.Root.Manager._ExecuteCloseAllCommand( LayoutElement ); + } - #endregion + #endregion - #region NewVerticalTabGroupCommand + #region ActivateCommand - /// - /// NewVerticalTabGroupCommand Dependency Property - /// - public static readonly DependencyProperty NewVerticalTabGroupCommandProperty = - DependencyProperty.Register("NewVerticalTabGroupCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata((ICommand)null, - new PropertyChangedCallback(OnNewVerticalTabGroupCommandChanged))); + /// + /// ActivateCommand Dependency Property + /// + public static readonly DependencyProperty ActivateCommandProperty = DependencyProperty.Register( "ActivateCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnActivateCommandChanged ), new CoerceValueCallback( CoerceActivateCommandValue ) ) ); - /// - /// Gets or sets the NewVerticalTabGroupCommand property. This dependency property - /// indicates the new vertical tab group command. - /// - public ICommand NewVerticalTabGroupCommand - { - get { return (ICommand)GetValue(NewVerticalTabGroupCommandProperty); } - set { SetValue(NewVerticalTabGroupCommandProperty, value); } - } + /// + /// Gets or sets the ActivateCommand property. This dependency property + /// indicates the command to execute when user wants to activate a content (either a Document or an Anchorable). + /// + public ICommand ActivateCommand + { + get + { + return ( ICommand )GetValue( ActivateCommandProperty ); + } + set + { + SetValue( ActivateCommandProperty, value ); + } + } - /// - /// Handles changes to the NewVerticalTabGroupCommand property. - /// - private static void OnNewVerticalTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnNewVerticalTabGroupCommandChanged(e); - } + /// + /// Handles changes to the ActivateCommand property. + /// + private static void OnActivateCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnActivateCommandChanged( e ); + } - /// - /// Provides derived classes an opportunity to handle changes to the NewVerticalTabGroupCommand property. - /// - protected virtual void OnNewVerticalTabGroupCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + /// + /// Provides derived classes an opportunity to handle changes to the ActivateCommand property. + /// + protected virtual void OnActivateCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - private bool CanExecuteNewVerticalTabGroupCommand(object parameter) - { - if (LayoutElement == null) - return false; - var parentDocumentGroup = LayoutElement.FindParent(); - var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; - return ((parentDocumentGroup == null || - parentDocumentGroup.ChildrenCount == 1 || - parentDocumentGroup.Root.Manager.AllowMixedOrientation || - parentDocumentGroup.Orientation == System.Windows.Controls.Orientation.Horizontal) && - parentDocumentPane != null && - parentDocumentPane.ChildrenCount > 1); - } + /// + /// Coerces the ActivateCommand value. + /// + private static object CoerceActivateCommandValue( DependencyObject d, object value ) + { + return value; + } - private void ExecuteNewVerticalTabGroupCommand(object parameter) - { - var layoutElement = LayoutElement; - var parentDocumentGroup = layoutElement.FindParent(); - var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; + private bool CanExecuteActivateCommand( object parameter ) + { + return LayoutElement != null; + } - if (parentDocumentGroup == null) - { - var grandParent = parentDocumentPane.Parent as ILayoutContainer; - parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; - grandParent.ReplaceChild(parentDocumentPane, parentDocumentGroup); - parentDocumentGroup.Children.Add(parentDocumentPane); - } - parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; - int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); - parentDocumentGroup.InsertChildAt(indexOfParentPane + 1, new LayoutDocumentPane(layoutElement)); - layoutElement.IsActive = true; - layoutElement.Root.CollectGarbage(); - } - #endregion + private void ExecuteActivateCommand( object parameter ) + { + LayoutElement.Root.Manager._ExecuteContentActivateCommand( LayoutElement ); + } - #region NewHorizontalTabGroupCommand + #endregion - /// - /// NewHorizontalTabGroupCommand Dependency Property - /// - public static readonly DependencyProperty NewHorizontalTabGroupCommandProperty = - DependencyProperty.Register("NewHorizontalTabGroupCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata((ICommand)null, - new PropertyChangedCallback(OnNewHorizontalTabGroupCommandChanged))); + #region NewVerticalTabGroupCommand - /// - /// Gets or sets the NewHorizontalTabGroupCommand property. This dependency property - /// indicates the new horizontal tab group command. - /// - public ICommand NewHorizontalTabGroupCommand - { - get { return (ICommand)GetValue(NewHorizontalTabGroupCommandProperty); } - set { SetValue(NewHorizontalTabGroupCommandProperty, value); } - } + /// + /// NewVerticalTabGroupCommand Dependency Property + /// + public static readonly DependencyProperty NewVerticalTabGroupCommandProperty = DependencyProperty.Register( "NewVerticalTabGroupCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( ICommand )null, new PropertyChangedCallback( OnNewVerticalTabGroupCommandChanged ) ) ); - /// - /// Handles changes to the NewHorizontalTabGroupCommand property. - /// - private static void OnNewHorizontalTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnNewHorizontalTabGroupCommandChanged(e); - } + /// + /// Gets or sets the NewVerticalTabGroupCommand property. This dependency property + /// indicates the new vertical tab group command. + /// + public ICommand NewVerticalTabGroupCommand + { + get + { + return ( ICommand )GetValue( NewVerticalTabGroupCommandProperty ); + } + set + { + SetValue( NewVerticalTabGroupCommandProperty, value ); + } + } - /// - /// Provides derived classes an opportunity to handle changes to the NewHorizontalTabGroupCommand property. - /// - protected virtual void OnNewHorizontalTabGroupCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + /// + /// Handles changes to the NewVerticalTabGroupCommand property. + /// + private static void OnNewVerticalTabGroupCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnNewVerticalTabGroupCommandChanged( e ); + } + /// + /// Provides derived classes an opportunity to handle changes to the NewVerticalTabGroupCommand property. + /// + protected virtual void OnNewVerticalTabGroupCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - private bool CanExecuteNewHorizontalTabGroupCommand(object parameter) - { - if (LayoutElement == null) - return false; - var parentDocumentGroup = LayoutElement.FindParent(); - var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; - return ((parentDocumentGroup == null || - parentDocumentGroup.ChildrenCount == 1 || - parentDocumentGroup.Root.Manager.AllowMixedOrientation || - parentDocumentGroup.Orientation == System.Windows.Controls.Orientation.Vertical) && - parentDocumentPane != null && - parentDocumentPane.ChildrenCount > 1); - } + private bool CanExecuteNewVerticalTabGroupCommand( object parameter ) + { + if( LayoutElement == null ) + return false; + var parentDocumentGroup = LayoutElement.FindParent(); + var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; + return ( ( parentDocumentGroup == null || + parentDocumentGroup.ChildrenCount == 1 || + parentDocumentGroup.Root.Manager.AllowMixedOrientation || + parentDocumentGroup.Orientation == System.Windows.Controls.Orientation.Horizontal ) && + parentDocumentPane != null && + parentDocumentPane.ChildrenCount > 1 ); + } - private void ExecuteNewHorizontalTabGroupCommand(object parameter) - { - var layoutElement = LayoutElement; - var parentDocumentGroup = layoutElement.FindParent(); - var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; + private void ExecuteNewVerticalTabGroupCommand( object parameter ) + { + var layoutElement = LayoutElement; + var parentDocumentGroup = layoutElement.FindParent(); + var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; + + if( parentDocumentGroup == null ) + { + var grandParent = parentDocumentPane.Parent as ILayoutContainer; + parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; + grandParent.ReplaceChild( parentDocumentPane, parentDocumentGroup ); + parentDocumentGroup.Children.Add( parentDocumentPane ); + } + parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; + int indexOfParentPane = parentDocumentGroup.IndexOfChild( parentDocumentPane ); + parentDocumentGroup.InsertChildAt( indexOfParentPane + 1, new LayoutDocumentPane( layoutElement ) ); + layoutElement.IsActive = true; + layoutElement.Root.CollectGarbage(); + } + #endregion - if (parentDocumentGroup == null) - { - var grandParent = parentDocumentPane.Parent as ILayoutContainer; - parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; - grandParent.ReplaceChild(parentDocumentPane, parentDocumentGroup); - parentDocumentGroup.Children.Add(parentDocumentPane); - } - parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Vertical; - int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); - parentDocumentGroup.InsertChildAt(indexOfParentPane + 1, new LayoutDocumentPane(layoutElement)); - layoutElement.IsActive = true; - layoutElement.Root.CollectGarbage(); - } - #endregion + #region NewHorizontalTabGroupCommand - #region MoveToNextTabGroupCommand + /// + /// NewHorizontalTabGroupCommand Dependency Property + /// + public static readonly DependencyProperty NewHorizontalTabGroupCommandProperty = DependencyProperty.Register( "NewHorizontalTabGroupCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( ICommand )null, new PropertyChangedCallback( OnNewHorizontalTabGroupCommandChanged ) ) ); - /// - /// MoveToNextTabGroupCommand Dependency Property - /// - public static readonly DependencyProperty MoveToNextTabGroupCommandProperty = - DependencyProperty.Register("MoveToNextTabGroupCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata((ICommand)null, - new PropertyChangedCallback(OnMoveToNextTabGroupCommandChanged))); + /// + /// Gets or sets the NewHorizontalTabGroupCommand property. This dependency property + /// indicates the new horizontal tab group command. + /// + public ICommand NewHorizontalTabGroupCommand + { + get + { + return ( ICommand )GetValue( NewHorizontalTabGroupCommandProperty ); + } + set + { + SetValue( NewHorizontalTabGroupCommandProperty, value ); + } + } - /// - /// Gets or sets the MoveToNextTabGroupCommand property. This dependency property - /// indicates move to next tab group command. - /// - public ICommand MoveToNextTabGroupCommand - { - get { return (ICommand)GetValue(MoveToNextTabGroupCommandProperty); } - set { SetValue(MoveToNextTabGroupCommandProperty, value); } - } + /// + /// Handles changes to the NewHorizontalTabGroupCommand property. + /// + private static void OnNewHorizontalTabGroupCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnNewHorizontalTabGroupCommandChanged( e ); + } - /// - /// Handles changes to the MoveToNextTabGroupCommand property. - /// - private static void OnMoveToNextTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnMoveToNextTabGroupCommandChanged(e); - } + /// + /// Provides derived classes an opportunity to handle changes to the NewHorizontalTabGroupCommand property. + /// + protected virtual void OnNewHorizontalTabGroupCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } - /// - /// Provides derived classes an opportunity to handle changes to the MoveToNextTabGroupCommand property. - /// - protected virtual void OnMoveToNextTabGroupCommandChanged(DependencyPropertyChangedEventArgs e) - { - } - private bool CanExecuteMoveToNextTabGroupCommand(object parameter) - { - if (LayoutElement == null) - return false; - - var parentDocumentGroup = LayoutElement.FindParent(); - var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; - return (parentDocumentGroup != null && - parentDocumentPane != null && - parentDocumentGroup.ChildrenCount > 1 && - parentDocumentGroup.IndexOfChild(parentDocumentPane) < parentDocumentGroup.ChildrenCount - 1 && - parentDocumentGroup.Children[parentDocumentGroup.IndexOfChild(parentDocumentPane) + 1] is LayoutDocumentPane); - } + private bool CanExecuteNewHorizontalTabGroupCommand( object parameter ) + { + if( LayoutElement == null ) + return false; + var parentDocumentGroup = LayoutElement.FindParent(); + var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; + return ( ( parentDocumentGroup == null || + parentDocumentGroup.ChildrenCount == 1 || + parentDocumentGroup.Root.Manager.AllowMixedOrientation || + parentDocumentGroup.Orientation == System.Windows.Controls.Orientation.Vertical ) && + parentDocumentPane != null && + parentDocumentPane.ChildrenCount > 1 ); + } - private void ExecuteMoveToNextTabGroupCommand(object parameter) - { - var layoutElement = LayoutElement; - var parentDocumentGroup = layoutElement.FindParent(); - var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; - int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); - var nextDocumentPane = parentDocumentGroup.Children[indexOfParentPane + 1] as LayoutDocumentPane; - nextDocumentPane.InsertChildAt(0, layoutElement); - layoutElement.IsActive = true; - layoutElement.Root.CollectGarbage(); - } + private void ExecuteNewHorizontalTabGroupCommand( object parameter ) + { + var layoutElement = LayoutElement; + var parentDocumentGroup = layoutElement.FindParent(); + var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; + + if( parentDocumentGroup == null ) + { + var grandParent = parentDocumentPane.Parent as ILayoutContainer; + parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; + grandParent.ReplaceChild( parentDocumentPane, parentDocumentGroup ); + parentDocumentGroup.Children.Add( parentDocumentPane ); + } + parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Vertical; + int indexOfParentPane = parentDocumentGroup.IndexOfChild( parentDocumentPane ); + parentDocumentGroup.InsertChildAt( indexOfParentPane + 1, new LayoutDocumentPane( layoutElement ) ); + layoutElement.IsActive = true; + layoutElement.Root.CollectGarbage(); + } + #endregion + + #region MoveToNextTabGroupCommand + /// + /// MoveToNextTabGroupCommand Dependency Property + /// + public static readonly DependencyProperty MoveToNextTabGroupCommandProperty = DependencyProperty.Register( "MoveToNextTabGroupCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( ICommand )null, new PropertyChangedCallback( OnMoveToNextTabGroupCommandChanged ) ) ); + + /// + /// Gets or sets the MoveToNextTabGroupCommand property. This dependency property + /// indicates move to next tab group command. + /// + public ICommand MoveToNextTabGroupCommand + { + get + { + return ( ICommand )GetValue( MoveToNextTabGroupCommandProperty ); + } + set + { + SetValue( MoveToNextTabGroupCommandProperty, value ); + } + } + + /// + /// Handles changes to the MoveToNextTabGroupCommand property. + /// + private static void OnMoveToNextTabGroupCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnMoveToNextTabGroupCommandChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the MoveToNextTabGroupCommand property. + /// + protected virtual void OnMoveToNextTabGroupCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } + + private bool CanExecuteMoveToNextTabGroupCommand( object parameter ) + { + if( LayoutElement == null ) + return false; + + var parentDocumentGroup = LayoutElement.FindParent(); + var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; + return ( parentDocumentGroup != null && + parentDocumentPane != null && + parentDocumentGroup.ChildrenCount > 1 && + parentDocumentGroup.IndexOfChild( parentDocumentPane ) < parentDocumentGroup.ChildrenCount - 1 && + parentDocumentGroup.Children[ parentDocumentGroup.IndexOfChild( parentDocumentPane ) + 1 ] is LayoutDocumentPane ); + } + + private void ExecuteMoveToNextTabGroupCommand( object parameter ) + { + var layoutElement = LayoutElement; + var parentDocumentGroup = layoutElement.FindParent(); + var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; + int indexOfParentPane = parentDocumentGroup.IndexOfChild( parentDocumentPane ); + var nextDocumentPane = parentDocumentGroup.Children[ indexOfParentPane + 1 ] as LayoutDocumentPane; + nextDocumentPane.InsertChildAt( 0, layoutElement ); + layoutElement.IsActive = true; + layoutElement.Root.CollectGarbage(); + } + + #endregion + + #region MoveToPreviousTabGroupCommand + + /// + /// MoveToPreviousTabGroupCommand Dependency Property + /// + public static readonly DependencyProperty MoveToPreviousTabGroupCommandProperty = DependencyProperty.Register( "MoveToPreviousTabGroupCommand", typeof( ICommand ), typeof( LayoutItem ), + new FrameworkPropertyMetadata( ( ICommand )null, new PropertyChangedCallback( OnMoveToPreviousTabGroupCommandChanged ) ) ); + + /// + /// Gets or sets the MoveToPreviousTabGroupCommand property. This dependency property + /// indicates move to rpevious tab group command. + /// + public ICommand MoveToPreviousTabGroupCommand + { + get + { + return ( ICommand )GetValue( MoveToPreviousTabGroupCommandProperty ); + } + set + { + SetValue( MoveToPreviousTabGroupCommandProperty, value ); + } + } + + /// + /// Handles changes to the MoveToPreviousTabGroupCommand property. + /// + private static void OnMoveToPreviousTabGroupCommandChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )d ).OnMoveToPreviousTabGroupCommandChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the MoveToPreviousTabGroupCommand property. + /// + protected virtual void OnMoveToPreviousTabGroupCommandChanged( DependencyPropertyChangedEventArgs e ) + { + } + + private bool CanExecuteMoveToPreviousTabGroupCommand( object parameter ) + { + if( LayoutElement == null ) + return false; + var parentDocumentGroup = LayoutElement.FindParent(); + var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; + return ( parentDocumentGroup != null && + parentDocumentPane != null && + parentDocumentGroup.ChildrenCount > 1 && + parentDocumentGroup.IndexOfChild( parentDocumentPane ) > 0 && + parentDocumentGroup.Children[ parentDocumentGroup.IndexOfChild( parentDocumentPane ) - 1 ] is LayoutDocumentPane ); + } + + private void ExecuteMoveToPreviousTabGroupCommand( object parameter ) + { + var layoutElement = LayoutElement; + var parentDocumentGroup = layoutElement.FindParent(); + var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; + int indexOfParentPane = parentDocumentGroup.IndexOfChild( parentDocumentPane ); + var nextDocumentPane = parentDocumentGroup.Children[ indexOfParentPane - 1 ] as LayoutDocumentPane; + nextDocumentPane.InsertChildAt( 0, layoutElement ); + layoutElement.IsActive = true; + layoutElement.Root.CollectGarbage(); + } #endregion - #region MoveToPreviousTabGroupCommand + #endregion - /// - /// MoveToPreviousTabGroupCommand Dependency Property - /// - public static readonly DependencyProperty MoveToPreviousTabGroupCommandProperty = - DependencyProperty.Register("MoveToPreviousTabGroupCommand", typeof(ICommand), typeof(LayoutItem), - new FrameworkPropertyMetadata((ICommand)null, - new PropertyChangedCallback(OnMoveToPreviousTabGroupCommandChanged))); + #region Internal Methods - /// - /// Gets or sets the MoveToPreviousTabGroupCommand property. This dependency property - /// indicates move to rpevious tab group command. - /// - public ICommand MoveToPreviousTabGroupCommand - { - get { return (ICommand)GetValue(MoveToPreviousTabGroupCommandProperty); } - set { SetValue(MoveToPreviousTabGroupCommandProperty, value); } - } + protected virtual void InitDefaultCommands() + { + _defaultCloseCommand = new RelayCommand( ( p ) => ExecuteCloseCommand( p ), ( p ) => CanExecuteCloseCommand( p ) ); + _defaultFloatCommand = new RelayCommand( ( p ) => ExecuteFloatCommand( p ), ( p ) => CanExecuteFloatCommand( p ) ); + _defaultDockAsDocumentCommand = new RelayCommand( ( p ) => ExecuteDockAsDocumentCommand( p ), ( p ) => CanExecuteDockAsDocumentCommand( p ) ); + _defaultCloseAllButThisCommand = new RelayCommand( ( p ) => ExecuteCloseAllButThisCommand( p ), ( p ) => CanExecuteCloseAllButThisCommand( p ) ); + _defaultCloseAllCommand = new RelayCommand( ( p ) => ExecuteCloseAllCommand( p ), ( p ) => CanExecuteCloseAllCommand( p ) ); + _defaultActivateCommand = new RelayCommand( ( p ) => ExecuteActivateCommand( p ), ( p ) => CanExecuteActivateCommand( p ) ); + _defaultNewVerticalTabGroupCommand = new RelayCommand( ( p ) => ExecuteNewVerticalTabGroupCommand( p ), ( p ) => CanExecuteNewVerticalTabGroupCommand( p ) ); + _defaultNewHorizontalTabGroupCommand = new RelayCommand( ( p ) => ExecuteNewHorizontalTabGroupCommand( p ), ( p ) => CanExecuteNewHorizontalTabGroupCommand( p ) ); + _defaultMoveToNextTabGroupCommand = new RelayCommand( ( p ) => ExecuteMoveToNextTabGroupCommand( p ), ( p ) => CanExecuteMoveToNextTabGroupCommand( p ) ); + _defaultMoveToPreviousTabGroupCommand = new RelayCommand( ( p ) => ExecuteMoveToPreviousTabGroupCommand( p ), ( p ) => CanExecuteMoveToPreviousTabGroupCommand( p ) ); + } - /// - /// Handles changes to the MoveToPreviousTabGroupCommand property. - /// - private static void OnMoveToPreviousTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((LayoutItem)d).OnMoveToPreviousTabGroupCommandChanged(e); - } + protected virtual void ClearDefaultBindings() + { + if( CloseCommand == _defaultCloseCommand ) + BindingOperations.ClearBinding( this, CloseCommandProperty ); + if( FloatCommand == _defaultFloatCommand ) + BindingOperations.ClearBinding( this, FloatCommandProperty ); + if( DockAsDocumentCommand == _defaultDockAsDocumentCommand ) + BindingOperations.ClearBinding( this, DockAsDocumentCommandProperty ); + if( CloseAllButThisCommand == _defaultCloseAllButThisCommand ) + BindingOperations.ClearBinding( this, CloseAllButThisCommandProperty ); + if( CloseAllCommand == _defaultCloseAllCommand ) + BindingOperations.ClearBinding( this, CloseAllCommandProperty ); + if( ActivateCommand == _defaultActivateCommand ) + BindingOperations.ClearBinding( this, ActivateCommandProperty ); + if( NewVerticalTabGroupCommand == _defaultNewVerticalTabGroupCommand ) + BindingOperations.ClearBinding( this, NewVerticalTabGroupCommandProperty ); + if( NewHorizontalTabGroupCommand == _defaultNewHorizontalTabGroupCommand ) + BindingOperations.ClearBinding( this, NewHorizontalTabGroupCommandProperty ); + if( MoveToNextTabGroupCommand == _defaultMoveToNextTabGroupCommand ) + BindingOperations.ClearBinding( this, MoveToNextTabGroupCommandProperty ); + if( MoveToPreviousTabGroupCommand == _defaultMoveToPreviousTabGroupCommand ) + BindingOperations.ClearBinding( this, MoveToPreviousTabGroupCommandProperty ); + } - /// - /// Provides derived classes an opportunity to handle changes to the MoveToPreviousTabGroupCommand property. - /// - protected virtual void OnMoveToPreviousTabGroupCommandChanged(DependencyPropertyChangedEventArgs e) - { - } + protected virtual void SetDefaultBindings() + { + if( CloseCommand == null ) + CloseCommand = _defaultCloseCommand; + if( FloatCommand == null ) + FloatCommand = _defaultFloatCommand; + if( DockAsDocumentCommand == null ) + DockAsDocumentCommand = _defaultDockAsDocumentCommand; + if( CloseAllButThisCommand == null ) + CloseAllButThisCommand = _defaultCloseAllButThisCommand; + if( CloseAllCommand == null ) + CloseAllCommand = _defaultCloseAllCommand; + if( ActivateCommand == null ) + ActivateCommand = _defaultActivateCommand; + if( NewVerticalTabGroupCommand == null ) + NewVerticalTabGroupCommand = _defaultNewVerticalTabGroupCommand; + if( NewHorizontalTabGroupCommand == null ) + NewHorizontalTabGroupCommand = _defaultNewHorizontalTabGroupCommand; + if( MoveToNextTabGroupCommand == null ) + MoveToNextTabGroupCommand = _defaultMoveToNextTabGroupCommand; + if( MoveToPreviousTabGroupCommand == null ) + MoveToPreviousTabGroupCommand = _defaultMoveToPreviousTabGroupCommand; + + + IsSelected = LayoutElement.IsSelected; + IsActive = LayoutElement.IsActive; + CanClose = LayoutElement.CanClose; + } + + protected virtual void OnVisibilityChanged() + { + if( LayoutElement != null && + Visibility == System.Windows.Visibility.Collapsed ) + LayoutElement.Close(); + } + + internal virtual void Attach( LayoutContent model ) + { + LayoutElement = model; + Model = model.Content; + + InitDefaultCommands(); + + LayoutElement.IsSelectedChanged += new EventHandler( LayoutElement_IsSelectedChanged ); + LayoutElement.IsActiveChanged += new EventHandler( LayoutElement_IsActiveChanged ); + + DataContext = this; + } + + internal virtual void Detach() + { + LayoutElement.IsSelectedChanged -= new EventHandler( LayoutElement_IsSelectedChanged ); + LayoutElement.IsActiveChanged -= new EventHandler( LayoutElement_IsActiveChanged ); + LayoutElement = null; + Model = null; + } + + internal void _ClearDefaultBindings() + { + ClearDefaultBindings(); + } - private bool CanExecuteMoveToPreviousTabGroupCommand(object parameter) + internal void _SetDefaultBindings() + { + SetDefaultBindings(); + } + + internal bool IsViewExists() + { + return ( _view != null ); + } + + #endregion + + #region Private Methods + + private void LayoutElement_IsActiveChanged( object sender, EventArgs e ) + { + if( _isActiveReentrantFlag.CanEnter ) + { + using( _isActiveReentrantFlag.Enter() ) { - if (LayoutElement == null) - return false; - var parentDocumentGroup = LayoutElement.FindParent(); - var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; - return (parentDocumentGroup != null && - parentDocumentPane != null && - parentDocumentGroup.ChildrenCount > 1 && - parentDocumentGroup.IndexOfChild(parentDocumentPane) > 0 && - parentDocumentGroup.Children[parentDocumentGroup.IndexOfChild(parentDocumentPane) - 1] is LayoutDocumentPane); + var bnd = BindingOperations.GetBinding( this, IsActiveProperty ); + IsActive = LayoutElement.IsActive; + var bnd2 = BindingOperations.GetBinding( this, IsActiveProperty ); } + } + } - private void ExecuteMoveToPreviousTabGroupCommand(object parameter) + private void LayoutElement_IsSelectedChanged( object sender, EventArgs e ) + { + if( _isSelectedReentrantFlag.CanEnter ) + { + using( _isSelectedReentrantFlag.Enter() ) { - var layoutElement = LayoutElement; - var parentDocumentGroup = layoutElement.FindParent(); - var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; - int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); - var nextDocumentPane = parentDocumentGroup.Children[indexOfParentPane - 1] as LayoutDocumentPane; - nextDocumentPane.InsertChildAt(0, layoutElement); - layoutElement.IsActive = true; - layoutElement.Root.CollectGarbage(); + IsSelected = LayoutElement.IsSelected; } - #endregion + } + } + private static void OnToolTipChanged( DependencyObject s, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )s ).OnToolTipChanged(); + } + private void OnToolTipChanged() + { + if( LayoutElement != null ) + LayoutElement.ToolTip = ToolTip; + } + private static void OnVisibilityChanged( DependencyObject s, DependencyPropertyChangedEventArgs e ) + { + ( ( LayoutItem )s ).OnVisibilityChanged(); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutPanelControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutPanelControl.cs index d71bc3ee..3fe90c42 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutPanelControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutPanelControl.cs @@ -15,117 +15,125 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public class LayoutPanelControl : LayoutGridControl, ILayoutControl + public class LayoutPanelControl : LayoutGridControl, ILayoutControl + { + #region Members + + private LayoutPanel _model; + + #endregion + + #region Constructors + + internal LayoutPanelControl( LayoutPanel model ) + : base( model, model.Orientation ) { - internal LayoutPanelControl(LayoutPanel model) - :base(model, model.Orientation) - { - _model = model; + _model = model; - } + } - LayoutPanel _model; + #endregion - protected override void OnFixChildrenDockLengths() - { - if (ActualWidth == 0.0 || - ActualHeight == 0.0) - return; + #region Overrides - var modelAsPositionableElement = _model as ILayoutPositionableElementWithActualSize; - #region Setup DockWidth/Height for children - if (_model.Orientation == Orientation.Horizontal) + protected override void OnFixChildrenDockLengths() + { + if( ActualWidth == 0.0 || + ActualHeight == 0.0 ) + return; + + var modelAsPositionableElement = _model as ILayoutPositionableElementWithActualSize; + #region Setup DockWidth/Height for children + if( _model.Orientation == Orientation.Horizontal ) + { + if( _model.ContainsChildOfType() ) + { + for( int i = 0; i < _model.Children.Count; i++ ) + { + var childContainerModel = _model.Children[ i ] as ILayoutContainer; + var childPositionableModel = _model.Children[ i ] as ILayoutPositionableElement; + + if( childContainerModel != null && + ( childContainerModel.IsOfType() || + childContainerModel.ContainsChildOfType() ) ) { - if (_model.ContainsChildOfType()) - { - for (int i = 0; i < _model.Children.Count; i++) - { - var childContainerModel = _model.Children[i] as ILayoutContainer; - var childPositionableModel = _model.Children[i] as ILayoutPositionableElement; - - if (childContainerModel != null && - (childContainerModel.IsOfType() || - childContainerModel.ContainsChildOfType())) - { - childPositionableModel.DockWidth = new GridLength(1.0, GridUnitType.Star); - } - else if (childPositionableModel != null && childPositionableModel.DockWidth.IsStar) - { - var childPositionableModelWidthActualSize = childPositionableModel as ILayoutPositionableElementWithActualSize; - - var widthToSet = Math.Max(childPositionableModelWidthActualSize.ActualWidth, childPositionableModel.DockMinWidth); - - widthToSet = Math.Min(widthToSet, ActualWidth / 2.0); - widthToSet = Math.Max(widthToSet, childPositionableModel.DockMinWidth); - - childPositionableModel.DockWidth = new GridLength( - widthToSet, - GridUnitType.Pixel); - } - } - } - else - { - for (int i = 0; i < _model.Children.Count; i++) - { - var childPositionableModel = _model.Children[i] as ILayoutPositionableElement; - if (!childPositionableModel.DockWidth.IsStar) - { - childPositionableModel.DockWidth = new GridLength(1.0, GridUnitType.Star); - } - } - } + childPositionableModel.DockWidth = new GridLength( 1.0, GridUnitType.Star ); } - else + else if( childPositionableModel != null && childPositionableModel.DockWidth.IsStar ) { - if (_model.ContainsChildOfType()) - { - for (int i = 0; i < _model.Children.Count; i++) - { - var childContainerModel = _model.Children[i] as ILayoutContainer; - var childPositionableModel = _model.Children[i] as ILayoutPositionableElement; - - if (childContainerModel != null && - (childContainerModel.IsOfType() || - childContainerModel.ContainsChildOfType())) - { - childPositionableModel.DockHeight = new GridLength(1.0, GridUnitType.Star); - } - else if (childPositionableModel != null && childPositionableModel.DockHeight.IsStar) - { - var childPositionableModelWidthActualSize = childPositionableModel as ILayoutPositionableElementWithActualSize; - - var heightToSet = Math.Max(childPositionableModelWidthActualSize.ActualHeight, childPositionableModel.DockMinHeight); - heightToSet = Math.Min(heightToSet, ActualHeight / 2.0); - heightToSet = Math.Max(heightToSet, childPositionableModel.DockMinHeight); - - childPositionableModel.DockHeight = new GridLength(heightToSet, GridUnitType.Pixel); - } - } - } - else - { - for (int i = 0; i < _model.Children.Count; i++) - { - var childPositionableModel = _model.Children[i] as ILayoutPositionableElement; - if (!childPositionableModel.DockHeight.IsStar) - { - childPositionableModel.DockHeight = new GridLength(1.0, GridUnitType.Star); - } - } - } + var childPositionableModelWidthActualSize = childPositionableModel as ILayoutPositionableElementWithActualSize; + + var widthToSet = Math.Max( childPositionableModelWidthActualSize.ActualWidth, childPositionableModel.DockMinWidth ); + + widthToSet = Math.Min( widthToSet, ActualWidth / 2.0 ); + widthToSet = Math.Max( widthToSet, childPositionableModel.DockMinWidth ); + + childPositionableModel.DockWidth = new GridLength( + widthToSet, + GridUnitType.Pixel ); } - #endregion + } } + else + { + for( int i = 0; i < _model.Children.Count; i++ ) + { + var childPositionableModel = _model.Children[ i ] as ILayoutPositionableElement; + if( !childPositionableModel.DockWidth.IsStar ) + { + childPositionableModel.DockWidth = new GridLength( 1.0, GridUnitType.Star ); + } + } + } + } + else + { + if( _model.ContainsChildOfType() ) + { + for( int i = 0; i < _model.Children.Count; i++ ) + { + var childContainerModel = _model.Children[ i ] as ILayoutContainer; + var childPositionableModel = _model.Children[ i ] as ILayoutPositionableElement; + + if( childContainerModel != null && + ( childContainerModel.IsOfType() || + childContainerModel.ContainsChildOfType() ) ) + { + childPositionableModel.DockHeight = new GridLength( 1.0, GridUnitType.Star ); + } + else if( childPositionableModel != null && childPositionableModel.DockHeight.IsStar ) + { + var childPositionableModelWidthActualSize = childPositionableModel as ILayoutPositionableElementWithActualSize; + + var heightToSet = Math.Max( childPositionableModelWidthActualSize.ActualHeight, childPositionableModel.DockMinHeight ); + heightToSet = Math.Min( heightToSet, ActualHeight / 2.0 ); + heightToSet = Math.Max( heightToSet, childPositionableModel.DockMinHeight ); + childPositionableModel.DockHeight = new GridLength( heightToSet, GridUnitType.Pixel ); + } + } + } + else + { + for( int i = 0; i < _model.Children.Count; i++ ) + { + var childPositionableModel = _model.Children[ i ] as ILayoutPositionableElement; + if( !childPositionableModel.DockHeight.IsStar ) + { + childPositionableModel.DockHeight = new GridLength( 1.0, GridUnitType.Star ); + } + } + } + } + #endregion } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/MenuItemEx.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/MenuItemEx.cs index 811efb11..55803e0b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/MenuItemEx.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/MenuItemEx.cs @@ -14,126 +14,146 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - public class MenuItemEx : MenuItem + public class MenuItemEx : MenuItem + { + #region Members + + private bool _reentrantFlag = false; + + #endregion + + #region Constructors + + static MenuItemEx() + { + IconProperty.OverrideMetadata( typeof( MenuItemEx ), new FrameworkPropertyMetadata( new PropertyChangedCallback( OnIconPropertyChanged ) ) ); + } + + public MenuItemEx() + { + } + + #endregion + + #region Properties + + #region IconTemplate + + /// + /// IconTemplate Dependency Property + /// + public static readonly DependencyProperty IconTemplateProperty = DependencyProperty.Register( "IconTemplate", typeof( DataTemplate ), typeof( MenuItemEx ), + new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnIconTemplateChanged ) ) ); + + /// + /// Gets or sets the IconTemplate property. This dependency property + /// indicates the data template for the icon. + /// + public DataTemplate IconTemplate + { + get + { + return ( DataTemplate )GetValue( IconTemplateProperty ); + } + set + { + SetValue( IconTemplateProperty, value ); + } + } + + /// + /// Handles changes to the IconTemplate property. + /// + private static void OnIconTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( MenuItemEx )d ).OnIconTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the IconTemplate property. + /// + protected virtual void OnIconTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + UpdateIcon(); + } + + #endregion + + #region IconTemplateSelector + + /// + /// IconTemplateSelector Dependency Property + /// + public static readonly DependencyProperty IconTemplateSelectorProperty = DependencyProperty.Register( "IconTemplateSelector", typeof( DataTemplateSelector ), typeof( MenuItemEx ), + new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnIconTemplateSelectorChanged ) ) ); + + /// + /// Gets or sets the IconTemplateSelector property. This dependency property + /// indicates the DataTemplateSelector for the Icon. + /// + public DataTemplateSelector IconTemplateSelector + { + get + { + return ( DataTemplateSelector )GetValue( IconTemplateSelectorProperty ); + } + set + { + SetValue( IconTemplateSelectorProperty, value ); + } + } + + /// + /// Handles changes to the IconTemplateSelector property. + /// + private static void OnIconTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( MenuItemEx )d ).OnIconTemplateSelectorChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the IconTemplateSelector property. + /// + protected virtual void OnIconTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) { - static MenuItemEx() - { - IconProperty.OverrideMetadata(typeof(MenuItemEx), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIconPropertyChanged))); - } - - - public MenuItemEx() - { - } - - #region IconTemplate - - /// - /// IconTemplate Dependency Property - /// - public static readonly DependencyProperty IconTemplateProperty = - DependencyProperty.Register("IconTemplate", typeof(DataTemplate), typeof(MenuItemEx), - new FrameworkPropertyMetadata((DataTemplate)null, - new PropertyChangedCallback(OnIconTemplateChanged))); - - /// - /// Gets or sets the IconTemplate property. This dependency property - /// indicates the data template for the icon. - /// - public DataTemplate IconTemplate - { - get { return (DataTemplate)GetValue(IconTemplateProperty); } - set { SetValue(IconTemplateProperty, value); } - } - - /// - /// Handles changes to the IconTemplate property. - /// - private static void OnIconTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((MenuItemEx)d).OnIconTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the IconTemplate property. - /// - protected virtual void OnIconTemplateChanged(DependencyPropertyChangedEventArgs e) - { - UpdateIcon(); - } - - #endregion - - #region IconTemplateSelector - - /// - /// IconTemplateSelector Dependency Property - /// - public static readonly DependencyProperty IconTemplateSelectorProperty = - DependencyProperty.Register("IconTemplateSelector", typeof(DataTemplateSelector), typeof(MenuItemEx), - new FrameworkPropertyMetadata((DataTemplateSelector)null, - new PropertyChangedCallback(OnIconTemplateSelectorChanged))); - - /// - /// Gets or sets the IconTemplateSelector property. This dependency property - /// indicates the DataTemplateSelector for the Icon. - /// - public DataTemplateSelector IconTemplateSelector - { - get { return (DataTemplateSelector)GetValue(IconTemplateSelectorProperty); } - set { SetValue(IconTemplateSelectorProperty, value); } - } - - /// - /// Handles changes to the IconTemplateSelector property. - /// - private static void OnIconTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((MenuItemEx)d).OnIconTemplateSelectorChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the IconTemplateSelector property. - /// - protected virtual void OnIconTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - UpdateIcon(); - } - - #endregion - - static void OnIconPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null) - { - ((MenuItemEx)sender).UpdateIcon(); - } - } - - bool _reentrantFlag = false; - void UpdateIcon() - { - if (_reentrantFlag) - return; - _reentrantFlag = true; - if (IconTemplateSelector != null) - { - var dataTemplateToUse = IconTemplateSelector.SelectTemplate(Icon, this); - if (dataTemplateToUse != null) - Icon = dataTemplateToUse.LoadContent(); - } - else if (IconTemplate != null) - Icon = IconTemplate.LoadContent(); - _reentrantFlag = false; - } + UpdateIcon(); } + + #endregion + + #endregion + + #region Private Mehods + + private static void OnIconPropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e ) + { + if( e.NewValue != null ) + { + ( ( MenuItemEx )sender ).UpdateIcon(); + } + } + + private void UpdateIcon() + { + if( _reentrantFlag ) + return; + _reentrantFlag = true; + if( IconTemplateSelector != null ) + { + var dataTemplateToUse = IconTemplateSelector.SelectTemplate( Icon, this ); + if( dataTemplateToUse != null ) + Icon = dataTemplateToUse.LoadContent(); + } + else if( IconTemplate != null ) + Icon = IconTemplate.LoadContent(); + _reentrantFlag = false; + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/NavigatorWindow.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/NavigatorWindow.cs index fd5f5a8c..a0a7f461 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/NavigatorWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/NavigatorWindow.cs @@ -14,334 +14,481 @@ ***********************************************************************************/ -using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using Xceed.Wpf.AvalonDock.Layout; -using System.Windows.Interop; -using System.Windows.Threading; using Xceed.Wpf.AvalonDock.Themes; +using System.Windows.Controls; namespace Xceed.Wpf.AvalonDock.Controls { - public class NavigatorWindow : Window + [TemplatePart( Name = PART_AnchorableListBox, Type = typeof( ListBox ) )] + [TemplatePart( Name = PART_DocumentListBox, Type = typeof( ListBox ) )] + public class NavigatorWindow : Window + { + #region Members + + private const string PART_AnchorableListBox = "PART_AnchorableListBox"; + private const string PART_DocumentListBox = "PART_DocumentListBox"; + + private ResourceDictionary currentThemeResourceDictionary; // = null + private DockingManager _manager; + private bool _isSelectingDocument; + private ListBox _anchorableListBox; + private ListBox _documentListBox; + private bool _internalSetSelectedDocument = false; + private bool _internalSetSelectedAnchorable = false; + + #endregion + + #region Constructors + + static NavigatorWindow() { - static NavigatorWindow() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(NavigatorWindow), new FrameworkPropertyMetadata(typeof(NavigatorWindow))); - ShowActivatedProperty.OverrideMetadata(typeof(NavigatorWindow), new FrameworkPropertyMetadata(false)); - ShowInTaskbarProperty.OverrideMetadata(typeof(NavigatorWindow), new FrameworkPropertyMetadata(false)); - } + DefaultStyleKeyProperty.OverrideMetadata( typeof( NavigatorWindow ), new FrameworkPropertyMetadata( typeof( NavigatorWindow ) ) ); + ShowActivatedProperty.OverrideMetadata( typeof( NavigatorWindow ), new FrameworkPropertyMetadata( false ) ); + ShowInTaskbarProperty.OverrideMetadata( typeof( NavigatorWindow ), new FrameworkPropertyMetadata( false ) ); + } - DockingManager _manager; - internal NavigatorWindow(DockingManager manager) - { - _manager = manager; + internal NavigatorWindow( DockingManager manager ) + { + _manager = manager; + + _internalSetSelectedDocument = true; + this.SetAnchorables( _manager.Layout.Descendents().OfType().Where( a => a.IsVisible ).Select( d => ( LayoutAnchorableItem )_manager.GetLayoutItemFromModel( d ) ).ToArray() ); + this.SetDocuments( _manager.Layout.Descendents().OfType().OrderByDescending( d => d.LastActivationTimeStamp.GetValueOrDefault() ).Select( d => ( LayoutDocumentItem )_manager.GetLayoutItemFromModel( d ) ).ToArray() ); + _internalSetSelectedDocument = false; + + if( this.Documents.Length > 1 ) + { + this.InternalSetSelectedDocument( this.Documents[ 1 ] ); + _isSelectingDocument = true; + } + else if( this.Anchorables.Count() > 1 ) + { + this.InternalSetSelectedAnchorable( this.Anchorables.ToArray()[ 1 ] ); + _isSelectingDocument = false; + } + + this.DataContext = this; + + this.Loaded += new RoutedEventHandler( OnLoaded ); + this.Unloaded += new RoutedEventHandler( OnUnloaded ); + + this.UpdateThemeResources(); + } - _internalSetSelectedDocument = true; - SetAnchorables(_manager.Layout.Descendents().OfType().Where(a => a.IsVisible).Select(d => (LayoutAnchorableItem)_manager.GetLayoutItemFromModel(d)).ToArray()); - SetDocuments(_manager.Layout.Descendents().OfType().OrderByDescending(d => d.LastActivationTimeStamp.GetValueOrDefault()).Select(d => (LayoutDocumentItem)_manager.GetLayoutItemFromModel(d)).ToArray()); - _internalSetSelectedDocument = false; + #endregion - if (Documents.Length > 1) - InternalSetSelectedDocument(Documents[1]); + #region Properties - this.DataContext = this; + #region Documents - this.Loaded += new RoutedEventHandler(OnLoaded); - this.Unloaded += new RoutedEventHandler(OnUnloaded); + /// + /// Documents Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey DocumentsPropertyKey = DependencyProperty.RegisterReadOnly( "Documents", typeof( IEnumerable ), typeof( NavigatorWindow ), + new FrameworkPropertyMetadata( null ) ); - UpdateThemeResources(); - } + public static readonly DependencyProperty DocumentsProperty = DocumentsPropertyKey.DependencyProperty; + /// + /// Gets the Documents property. This dependency property + /// indicates the list of documents. + /// + public LayoutDocumentItem[] Documents + { + get + { + return ( LayoutDocumentItem[] )GetValue( DocumentsProperty ); + } + } - internal void UpdateThemeResources(Theme oldTheme = null) - { - if (Application.Current != null) - return; + #endregion - if (oldTheme != null) - { - var resourceDictionaryToRemove = - Resources.MergedDictionaries.FirstOrDefault(r => r.Source == oldTheme.GetResourceUri()); - if (resourceDictionaryToRemove != null) - Resources.MergedDictionaries.Remove( - resourceDictionaryToRemove); - } + #region Anchorables - if (_manager.Theme != null) - { - Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = _manager.Theme.GetResourceUri() }); - } - } + /// + /// Anchorables Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey AnchorablesPropertyKey = DependencyProperty.RegisterReadOnly( "Anchorables", typeof( IEnumerable ), typeof( NavigatorWindow ), + new FrameworkPropertyMetadata( ( IEnumerable )null ) ); + public static readonly DependencyProperty AnchorablesProperty = AnchorablesPropertyKey.DependencyProperty; - void OnLoaded(object sender, RoutedEventArgs e) - { - this.Loaded -= new RoutedEventHandler(OnLoaded); + /// + /// Gets the Anchorables property. This dependency property + /// indicates the list of anchorables. + /// + public IEnumerable Anchorables + { + get + { + return ( IEnumerable )GetValue( AnchorablesProperty ); + } + } - this.Focus(); + #endregion - //this.SetParentToMainWindowOf(_manager); - WindowStartupLocation = WindowStartupLocation.CenterOwner; - } + #region SelectedDocument - void OnUnloaded(object sender, RoutedEventArgs e) - { - this.Unloaded -= new RoutedEventHandler(OnUnloaded); + /// + /// SelectedDocument Dependency Property + /// + public static readonly DependencyProperty SelectedDocumentProperty = DependencyProperty.Register( "SelectedDocument", typeof( LayoutDocumentItem ), typeof( NavigatorWindow ), + new FrameworkPropertyMetadata( ( LayoutDocumentItem )null, new PropertyChangedCallback( OnSelectedDocumentChanged ) ) ); - //_hwndSrc.RemoveHook(_hwndSrcHook); - //_hwndSrc.Dispose(); - //_hwndSrc = null; - } + /// + /// Gets or sets the SelectedDocument property. This dependency property + /// indicates the selected document. + /// + public LayoutDocumentItem SelectedDocument + { + get + { + return ( LayoutDocumentItem )GetValue( SelectedDocumentProperty ); + } + set + { + SetValue( SelectedDocumentProperty, value ); + } + } - //protected virtual IntPtr FilterMessage( - // IntPtr hwnd, - // int msg, - // IntPtr wParam, - // IntPtr lParam, - // ref bool handled - // ) - //{ - // handled = false; - - // switch (msg) - // { - // case Win32Helper.WM_ACTIVATE: - // if (((int)wParam & 0xFFFF) == Win32Helper.WA_INACTIVE) - // { - // if (lParam == new WindowInteropHelper(this.Owner).Handle) - // { - // Win32Helper.SetActiveWindow(_hwndSrc.Handle); - // handled = true; - // } - - // } - // break; - // } - - // return IntPtr.Zero; - //} - - - #region Documents - - /// - /// Documents Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey DocumentsPropertyKey - = DependencyProperty.RegisterReadOnly("Documents", typeof(IEnumerable), typeof(NavigatorWindow), - new FrameworkPropertyMetadata(null)); - - public static readonly DependencyProperty DocumentsProperty - = DocumentsPropertyKey.DependencyProperty; - - /// - /// Gets the Documents property. This dependency property - /// indicates the list of documents. - /// - public LayoutDocumentItem[] Documents - { - get { return (LayoutDocumentItem[])GetValue(DocumentsProperty); } - } + /// + /// Handles changes to the SelectedDocument property. + /// + private static void OnSelectedDocumentChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( NavigatorWindow )d ).OnSelectedDocumentChanged( e ); + } - /// - /// Provides a secure method for setting the Documents property. - /// This dependency property indicates the list of documents. - /// - /// The new value for the property. - protected void SetDocuments(LayoutDocumentItem[] value) - { - SetValue(DocumentsPropertyKey, value); - } + /// + /// Provides derived classes an opportunity to handle changes to the SelectedDocument property. + /// + protected virtual void OnSelectedDocumentChanged( DependencyPropertyChangedEventArgs e ) + { + if( _internalSetSelectedDocument ) + return; + + if( this.SelectedDocument != null && + this.SelectedDocument.ActivateCommand.CanExecute( null ) ) + { + this.Hide(); + this.SelectedDocument.ActivateCommand.Execute( null ); + } + } - #endregion + #endregion - #region Anchorables + #region SelectedAnchorable - /// - /// Anchorables Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey AnchorablesPropertyKey - = DependencyProperty.RegisterReadOnly("Anchorables", typeof(IEnumerable), typeof(NavigatorWindow), - new FrameworkPropertyMetadata((IEnumerable)null)); + /// + /// SelectedAnchorable Dependency Property + /// + public static readonly DependencyProperty SelectedAnchorableProperty = DependencyProperty.Register( "SelectedAnchorable", typeof( LayoutAnchorableItem ), typeof( NavigatorWindow ), + new FrameworkPropertyMetadata( ( LayoutAnchorableItem )null, new PropertyChangedCallback( OnSelectedAnchorableChanged ) ) ); - public static readonly DependencyProperty AnchorablesProperty - = AnchorablesPropertyKey.DependencyProperty; + /// + /// Gets or sets the SelectedAnchorable property. This dependency property + /// indicates the selected anchorable. + /// + public LayoutAnchorableItem SelectedAnchorable + { + get + { + return ( LayoutAnchorableItem )GetValue( SelectedAnchorableProperty ); + } + set + { + SetValue( SelectedAnchorableProperty, value ); + } + } - /// - /// Gets the Anchorables property. This dependency property - /// indicates the list of anchorables. - /// - public IEnumerable Anchorables - { - get { return (IEnumerable)GetValue(AnchorablesProperty); } - } + /// + /// Handles changes to the SelectedAnchorable property. + /// + private static void OnSelectedAnchorableChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( NavigatorWindow )d ).OnSelectedAnchorableChanged( e ); + } - /// - /// Provides a secure method for setting the Anchorables property. - /// This dependency property indicates the list of anchorables. - /// - /// The new value for the property. - protected void SetAnchorables(IEnumerable value) - { - SetValue(AnchorablesPropertyKey, value); - } + /// + /// Provides derived classes an opportunity to handle changes to the SelectedAnchorable property. + /// + protected virtual void OnSelectedAnchorableChanged( DependencyPropertyChangedEventArgs e ) + { + if( _internalSetSelectedAnchorable ) + return; + + var selectedAnchorable = e.NewValue as LayoutAnchorableItem; + if( this.SelectedAnchorable != null && + this.SelectedAnchorable.ActivateCommand.CanExecute( null ) ) + { + this.Close(); + this.SelectedAnchorable.ActivateCommand.Execute( null ); + } + } - #endregion + #endregion - #region SelectedDocument + #endregion - /// - /// SelectedDocument Dependency Property - /// - public static readonly DependencyProperty SelectedDocumentProperty = - DependencyProperty.Register("SelectedDocument", typeof(LayoutDocumentItem), typeof(NavigatorWindow), - new FrameworkPropertyMetadata((LayoutDocumentItem)null, - new PropertyChangedCallback(OnSelectedDocumentChanged))); + #region Overrides - /// - /// Gets or sets the SelectedDocument property. This dependency property - /// indicates the selected document. - /// - public LayoutDocumentItem SelectedDocument - { - get { return (LayoutDocumentItem)GetValue(SelectedDocumentProperty); } - set { SetValue(SelectedDocumentProperty, value); } - } + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _anchorableListBox = this.GetTemplateChild( PART_AnchorableListBox ) as ListBox; + _documentListBox = this.GetTemplateChild( PART_DocumentListBox ) as ListBox; + } + + protected override void OnPreviewKeyDown( System.Windows.Input.KeyEventArgs e ) + { + bool shouldHandle = false; - /// - /// Handles changes to the SelectedDocument property. - /// - private static void OnSelectedDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + // Press Tab to switch Selected LayoutContent. + if( e.Key == System.Windows.Input.Key.Tab) + { + // Selecting LayoutDocuments + if( _isSelectingDocument ) { - ((NavigatorWindow)d).OnSelectedDocumentChanged(e); + if( this.SelectedDocument != null ) + { + // Jump to next LayoutDocument + var docIndex = this.Documents.IndexOf( this.SelectedDocument ); + if( docIndex < (this.Documents.Length - 1) ) + { + this.SelectNextDocument(); + shouldHandle = true; + } + // Jump to first LayoutAnchorable + else if( this.Anchorables.Count() > 0 ) + { + _isSelectingDocument = false; + this.InternalSetSelectedDocument( null ); + this.InternalSetSelectedAnchorable( this.Anchorables.First() ); + shouldHandle = true; + } + } + // There is no SelectedDocument, select the first one. + else + { + if( this.Documents.Length > 0 ) + { + this.InternalSetSelectedDocument( this.Documents[ 0 ] ); + shouldHandle = true; + } + } } - - /// - /// Provides derived classes an opportunity to handle changes to the SelectedDocument property. - /// - protected virtual void OnSelectedDocumentChanged(DependencyPropertyChangedEventArgs e) + // Selecting LayoutAnchorables + else { - if (_internalSetSelectedDocument) - return; - - if (SelectedDocument != null && - SelectedDocument.ActivateCommand.CanExecute(null)) + if( this.SelectedAnchorable != null ) + { + // Jump to next LayoutAnchorable + var anchorableIndex = this.Anchorables.ToArray().IndexOf( this.SelectedAnchorable ); + if( anchorableIndex < (this.Anchorables.Count() - 1) ) + { + this.SelectNextAnchorable(); + shouldHandle = true; + } + // Jump to first LayoutDocument + else if( this.Documents.Length > 0 ) { - System.Diagnostics.Trace.WriteLine( "OnSelectedDocumentChanged()" ); - SelectedDocument.ActivateCommand.Execute(null); - Hide(); + _isSelectingDocument = true; + this.InternalSetSelectedAnchorable( null ); + this.InternalSetSelectedDocument( this.Documents[ 0 ] ); + shouldHandle = true; } + } + // There is no SelectedAnchorable, select the first one. + else + { + if( this.Anchorables.Count() > 0 ) + { + this.InternalSetSelectedAnchorable( this.Anchorables.ToArray()[ 0 ] ); + shouldHandle = true; + } + } + } + } + + if( shouldHandle ) + { + e.Handled = true; + } + base.OnPreviewKeyDown( e ); + } + protected override void OnPreviewKeyUp( System.Windows.Input.KeyEventArgs e ) + { + if( e.Key != System.Windows.Input.Key.Tab ) + { + this.Close(); + + if( this.SelectedDocument != null && + this.SelectedDocument.ActivateCommand.CanExecute( null ) ) + { + this.SelectedDocument.ActivateCommand.Execute( null ); } - bool _internalSetSelectedDocument = false; - void InternalSetSelectedDocument(LayoutDocumentItem documentToSelect) + if( this.SelectedDocument == null && + this.SelectedAnchorable != null && + this.SelectedAnchorable.ActivateCommand.CanExecute( null ) ) { - _internalSetSelectedDocument = true; - SelectedDocument = documentToSelect; - _internalSetSelectedDocument = false; + this.SelectedAnchorable.ActivateCommand.Execute( null ); } - #endregion + e.Handled = true; + } - #region SelectedAnchorable + base.OnPreviewKeyUp( e ); + } + + + #endregion + + #region Internal Methods + + /// + /// Provides a secure method for setting the Anchorables property. + /// This dependency property indicates the list of anchorables. + /// + /// The new value for the property. + protected void SetAnchorables( IEnumerable value ) + { + this.SetValue( AnchorablesPropertyKey, value ); + } - /// - /// SelectedAnchorable Dependency Property - /// - public static readonly DependencyProperty SelectedAnchorableProperty = - DependencyProperty.Register("SelectedAnchorable", typeof(LayoutAnchorableItem), typeof(NavigatorWindow), - new FrameworkPropertyMetadata((LayoutAnchorableItem)null, - new PropertyChangedCallback(OnSelectedAnchorableChanged))); + /// + /// Provides a secure method for setting the Documents property. + /// This dependency property indicates the list of documents. + /// + /// The new value for the property. + protected void SetDocuments( LayoutDocumentItem[] value ) + { + this.SetValue( DocumentsPropertyKey, value ); + } - /// - /// Gets or sets the SelectedAnchorable property. This dependency property - /// indicates the selected anchorable. - /// - public LayoutAnchorableItem SelectedAnchorable + internal void UpdateThemeResources( Theme oldTheme = null ) + { + if (Application.Current != null) + return; + + if ( oldTheme != null ) + { + if( oldTheme is DictionaryTheme ) { - get { return (LayoutAnchorableItem)GetValue(SelectedAnchorableProperty); } - set { SetValue(SelectedAnchorableProperty, value); } + if( currentThemeResourceDictionary != null ) + { + this.Resources.MergedDictionaries.Remove( currentThemeResourceDictionary ); + currentThemeResourceDictionary = null; + } } - - /// - /// Handles changes to the SelectedAnchorable property. - /// - private static void OnSelectedAnchorableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + else { - ((NavigatorWindow)d).OnSelectedAnchorableChanged(e); + var resourceDictionaryToRemove = this.Resources.MergedDictionaries.FirstOrDefault( r => r.Source == oldTheme.GetResourceUri() ); + if( resourceDictionaryToRemove != null ) + { + this.Resources.MergedDictionaries.Remove( resourceDictionaryToRemove ); + } } + } - /// - /// Provides derived classes an opportunity to handle changes to the SelectedAnchorable property. - /// - protected virtual void OnSelectedAnchorableChanged(DependencyPropertyChangedEventArgs e) + if( _manager.Theme != null ) + { + if( _manager.Theme is DictionaryTheme ) { - var selectedAnchorable = e.NewValue as LayoutAnchorableItem; - if (SelectedAnchorable != null && - SelectedAnchorable.ActivateCommand.CanExecute(null)) - { - SelectedAnchorable.ActivateCommand.Execute(null); - Close(); - } + currentThemeResourceDictionary = ( ( DictionaryTheme )_manager.Theme ).ThemeResourceDictionary; + this.Resources.MergedDictionaries.Add( currentThemeResourceDictionary ); } - - #endregion - - - internal void SelectNextDocument() + else { - if (SelectedDocument != null) - { - int docIndex = Documents.IndexOf(SelectedDocument); - docIndex++; - if (docIndex == Documents.Length) - docIndex = 0; - InternalSetSelectedDocument(Documents[docIndex]); - } - + this.Resources.MergedDictionaries.Add( new ResourceDictionary() { Source = _manager.Theme.GetResourceUri() } ); } + } + } - protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e) + internal void SelectNextDocument() + { + if( this.SelectedDocument != null ) + { + int docIndex = this.Documents.IndexOf( this.SelectedDocument ); + docIndex++; + if( docIndex == this.Documents.Length ) { - base.OnKeyDown(e); + docIndex = 0; } + this.InternalSetSelectedDocument( this.Documents[ docIndex ] ); + } + } - protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e) + internal void SelectNextAnchorable() + { + if( this.SelectedAnchorable != null ) + { + var anchorablesArray = this.Anchorables.ToArray(); + int anchorableIndex = anchorablesArray.IndexOf( this.SelectedAnchorable ); + anchorableIndex++; + if( anchorableIndex == this.Anchorables.Count() ) { - if (e.Key == System.Windows.Input.Key.Tab) - { - SelectNextDocument(); - e.Handled = true; - } - - - base.OnPreviewKeyDown(e); + anchorableIndex = 0; } + this.InternalSetSelectedAnchorable( anchorablesArray[ anchorableIndex ] ); + } + } - protected override void OnPreviewKeyUp(System.Windows.Input.KeyEventArgs e) - { - if (e.Key != System.Windows.Input.Key.Tab) - { - if (SelectedAnchorable != null && - SelectedAnchorable.ActivateCommand.CanExecute(null)) - SelectedAnchorable.ActivateCommand.Execute(null); + #endregion - if (SelectedAnchorable == null && - SelectedDocument != null && - SelectedDocument.ActivateCommand.CanExecute(null)) - SelectedDocument.ActivateCommand.Execute(null); - Close(); - e.Handled = true; - } + #region Private Methods + private void InternalSetSelectedAnchorable( LayoutAnchorableItem anchorableToSelect ) + { + _internalSetSelectedAnchorable = true; + this.SelectedAnchorable = anchorableToSelect; + _internalSetSelectedAnchorable = false; + + if( _anchorableListBox != null ) + { + _anchorableListBox.Focus(); + } + } - base.OnPreviewKeyUp(e); - } + private void InternalSetSelectedDocument( LayoutDocumentItem documentToSelect ) + { + _internalSetSelectedDocument = true; + this.SelectedDocument = documentToSelect; + _internalSetSelectedDocument = false; + + if( ( _documentListBox != null ) && ( documentToSelect != null ) ) + { + _documentListBox.Focus(); + } + } + private void OnLoaded( object sender, RoutedEventArgs e ) + { + this.Loaded -= new RoutedEventHandler( OnLoaded ); + + if( ( _documentListBox != null ) && (this.SelectedDocument != null) ) + { + _documentListBox.Focus(); + } + else if( ( _anchorableListBox != null ) && (this.SelectedAnchorable != null) ) + { + _anchorableListBox.Focus(); + } + + WindowStartupLocation = WindowStartupLocation.CenterOwner; } + + private void OnUnloaded( object sender, RoutedEventArgs e ) + { + this.Unloaded -= new RoutedEventHandler( OnUnloaded ); + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayArea.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayArea.cs index c402c97f..d6fa1f76 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayArea.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayArea.cs @@ -14,41 +14,47 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Controls; using System.Windows; -using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Controls { - public abstract class OverlayArea : IOverlayWindowArea - { - internal OverlayArea(IOverlayWindow overlayWindow) - { - _overlayWindow = overlayWindow; - } + public abstract class OverlayArea : IOverlayWindowArea + { + #region Members + + private IOverlayWindow _overlayWindow; + private Rect? _screenDetectionArea; + + #endregion - IOverlayWindow _overlayWindow; + #region Constructors + + internal OverlayArea( IOverlayWindow overlayWindow ) + { + _overlayWindow = overlayWindow; + } - Rect? _screenDetectionArea; - Rect IOverlayWindowArea.ScreenDetectionArea - { - get - { - return _screenDetectionArea.Value; - } - } + #endregion - protected void SetScreenDetectionArea(Rect rect) - { - _screenDetectionArea = rect; - } + #region Internal Methods + protected void SetScreenDetectionArea( Rect rect ) + { + _screenDetectionArea = rect; + } + #endregion + #region IOverlayWindowArea + Rect IOverlayWindowArea.ScreenDetectionArea + { + get + { + return _screenDetectionArea.Value; + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindow.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindow.cs index c6d81798..edf631f5 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindow.cs @@ -14,344 +14,509 @@ ***********************************************************************************/ -using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Windows.Controls; -using System.Windows.Media; using System.Windows.Shapes; using Xceed.Wpf.AvalonDock.Layout; -using System.Diagnostics; using Xceed.Wpf.AvalonDock.Themes; namespace Xceed.Wpf.AvalonDock.Controls { - public class OverlayWindow : Window, IOverlayWindow - { - static OverlayWindow() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(typeof(OverlayWindow))); - - OverlayWindow.AllowsTransparencyProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(true)); - OverlayWindow.WindowStyleProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(WindowStyle.None)); - OverlayWindow.ShowInTaskbarProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(false)); - OverlayWindow.ShowActivatedProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(false)); - OverlayWindow.VisibilityProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(Visibility.Hidden)); - } - - - internal OverlayWindow(IOverlayWindowHost host) - { - _host = host; - UpdateThemeResources(); - } - - - internal void UpdateThemeResources(Theme oldTheme = null) - { - if (Application.Current != null) - return; - - if (oldTheme != null) - { - var resourceDictionaryToRemove = - Resources.MergedDictionaries.FirstOrDefault(r => r.Source == oldTheme.GetResourceUri()); - if (resourceDictionaryToRemove != null) - Resources.MergedDictionaries.Remove( - resourceDictionaryToRemove); - } - - if (_host.Manager.Theme != null) - { - Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = _host.Manager.Theme.GetResourceUri() }); - } - } - - - Canvas _mainCanvasPanel; - Grid _gridDockingManagerDropTargets; - Grid _gridAnchorablePaneDropTargets; - Grid _gridDocumentPaneDropTargets; - Grid _gridDocumentPaneFullDropTargets; - - FrameworkElement _dockingManagerDropTargetBottom; - FrameworkElement _dockingManagerDropTargetTop; - FrameworkElement _dockingManagerDropTargetLeft; - FrameworkElement _dockingManagerDropTargetRight; - - FrameworkElement _anchorablePaneDropTargetBottom; - FrameworkElement _anchorablePaneDropTargetTop; - FrameworkElement _anchorablePaneDropTargetLeft; - FrameworkElement _anchorablePaneDropTargetRight; - FrameworkElement _anchorablePaneDropTargetInto; - - FrameworkElement _documentPaneDropTargetBottom; - FrameworkElement _documentPaneDropTargetTop; - FrameworkElement _documentPaneDropTargetLeft; - FrameworkElement _documentPaneDropTargetRight; - FrameworkElement _documentPaneDropTargetInto; - - FrameworkElement _documentPaneDropTargetBottomAsAnchorablePane; - FrameworkElement _documentPaneDropTargetTopAsAnchorablePane; - FrameworkElement _documentPaneDropTargetLeftAsAnchorablePane; - FrameworkElement _documentPaneDropTargetRightAsAnchorablePane; - - FrameworkElement _documentPaneFullDropTargetBottom; - FrameworkElement _documentPaneFullDropTargetTop; - FrameworkElement _documentPaneFullDropTargetLeft; - FrameworkElement _documentPaneFullDropTargetRight; - FrameworkElement _documentPaneFullDropTargetInto; - - Path _previewBox; - - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - - _mainCanvasPanel = GetTemplateChild("PART_DropTargetsContainer") as Canvas; - _gridDockingManagerDropTargets = GetTemplateChild("PART_DockingManagerDropTargets") as Grid; - _gridAnchorablePaneDropTargets = GetTemplateChild("PART_AnchorablePaneDropTargets") as Grid; - _gridDocumentPaneDropTargets = GetTemplateChild("PART_DocumentPaneDropTargets") as Grid; - _gridDocumentPaneFullDropTargets = GetTemplateChild("PART_DocumentPaneFullDropTargets") as Grid; - - _gridDockingManagerDropTargets.Visibility = System.Windows.Visibility.Hidden; - _gridAnchorablePaneDropTargets.Visibility = System.Windows.Visibility.Hidden; - _gridDocumentPaneDropTargets.Visibility = System.Windows.Visibility.Hidden; - if (_gridDocumentPaneFullDropTargets != null) - _gridDocumentPaneFullDropTargets.Visibility = System.Windows.Visibility.Hidden; - - _dockingManagerDropTargetBottom = GetTemplateChild("PART_DockingManagerDropTargetBottom") as FrameworkElement; - _dockingManagerDropTargetTop = GetTemplateChild("PART_DockingManagerDropTargetTop") as FrameworkElement; - _dockingManagerDropTargetLeft = GetTemplateChild("PART_DockingManagerDropTargetLeft") as FrameworkElement; - _dockingManagerDropTargetRight = GetTemplateChild("PART_DockingManagerDropTargetRight") as FrameworkElement; - - _anchorablePaneDropTargetBottom = GetTemplateChild("PART_AnchorablePaneDropTargetBottom") as FrameworkElement; - _anchorablePaneDropTargetTop = GetTemplateChild("PART_AnchorablePaneDropTargetTop") as FrameworkElement; - _anchorablePaneDropTargetLeft = GetTemplateChild("PART_AnchorablePaneDropTargetLeft") as FrameworkElement; - _anchorablePaneDropTargetRight = GetTemplateChild("PART_AnchorablePaneDropTargetRight") as FrameworkElement; - _anchorablePaneDropTargetInto = GetTemplateChild("PART_AnchorablePaneDropTargetInto") as FrameworkElement; - - _documentPaneDropTargetBottom = GetTemplateChild("PART_DocumentPaneDropTargetBottom") as FrameworkElement; - _documentPaneDropTargetTop = GetTemplateChild("PART_DocumentPaneDropTargetTop") as FrameworkElement; - _documentPaneDropTargetLeft = GetTemplateChild("PART_DocumentPaneDropTargetLeft") as FrameworkElement; - _documentPaneDropTargetRight = GetTemplateChild("PART_DocumentPaneDropTargetRight") as FrameworkElement; - _documentPaneDropTargetInto = GetTemplateChild("PART_DocumentPaneDropTargetInto") as FrameworkElement; - - _documentPaneDropTargetBottomAsAnchorablePane = GetTemplateChild("PART_DocumentPaneDropTargetBottomAsAnchorablePane") as FrameworkElement; - _documentPaneDropTargetTopAsAnchorablePane = GetTemplateChild("PART_DocumentPaneDropTargetTopAsAnchorablePane") as FrameworkElement; - _documentPaneDropTargetLeftAsAnchorablePane = GetTemplateChild("PART_DocumentPaneDropTargetLeftAsAnchorablePane") as FrameworkElement; - _documentPaneDropTargetRightAsAnchorablePane = GetTemplateChild("PART_DocumentPaneDropTargetRightAsAnchorablePane") as FrameworkElement; - - _documentPaneFullDropTargetBottom = GetTemplateChild("PART_DocumentPaneFullDropTargetBottom") as FrameworkElement; - _documentPaneFullDropTargetTop = GetTemplateChild("PART_DocumentPaneFullDropTargetTop") as FrameworkElement; - _documentPaneFullDropTargetLeft = GetTemplateChild("PART_DocumentPaneFullDropTargetLeft") as FrameworkElement; - _documentPaneFullDropTargetRight = GetTemplateChild("PART_DocumentPaneFullDropTargetRight") as FrameworkElement; - _documentPaneFullDropTargetInto = GetTemplateChild("PART_DocumentPaneFullDropTargetInto") as FrameworkElement; - - _previewBox = GetTemplateChild("PART_PreviewBox") as Path; - } - - - internal void EnableDropTargets() - { - //Trace.WriteLine("EnableDropTargets()"); - if (_mainCanvasPanel != null) - _mainCanvasPanel.Visibility = System.Windows.Visibility.Visible; - } - - internal void HideDropTargets() - { - //Trace.WriteLine("HideDropTargets()"); - if (_mainCanvasPanel != null) - _mainCanvasPanel.Visibility = System.Windows.Visibility.Hidden; - - } - - IOverlayWindowHost _host; - - IEnumerable IOverlayWindow.GetTargets() - { - foreach (var visibleArea in _visibleAreas) - { - switch (visibleArea.Type) - { - case DropAreaType.DockingManager: - { - var dropAreaDockingManager = visibleArea as DropArea; - yield return new DockingManagerDropTarget(dropAreaDockingManager.AreaElement, _dockingManagerDropTargetLeft.GetScreenArea(), DropTargetType.DockingManagerDockLeft); - yield return new DockingManagerDropTarget(dropAreaDockingManager.AreaElement, _dockingManagerDropTargetTop.GetScreenArea(), DropTargetType.DockingManagerDockTop); - yield return new DockingManagerDropTarget(dropAreaDockingManager.AreaElement, _dockingManagerDropTargetBottom.GetScreenArea(), DropTargetType.DockingManagerDockBottom); - yield return new DockingManagerDropTarget(dropAreaDockingManager.AreaElement, _dockingManagerDropTargetRight.GetScreenArea(), DropTargetType.DockingManagerDockRight); - } - break; - case DropAreaType.AnchorablePane: - { - var dropAreaAnchorablePane = visibleArea as DropArea; - yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetLeft.GetScreenArea(), DropTargetType.AnchorablePaneDockLeft); - yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetTop.GetScreenArea(), DropTargetType.AnchorablePaneDockTop); - yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetRight.GetScreenArea(), DropTargetType.AnchorablePaneDockRight); - yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetBottom.GetScreenArea(), DropTargetType.AnchorablePaneDockBottom); - yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetInto.GetScreenArea(), DropTargetType.AnchorablePaneDockInside); - - var parentPaneModel = dropAreaAnchorablePane.AreaElement.Model as LayoutAnchorablePane; - LayoutAnchorableTabItem lastAreaTabItem = null; - foreach (var dropAreaTabItem in dropAreaAnchorablePane.AreaElement.FindVisualChildren()) - { - var tabItemModel = dropAreaTabItem.Model as LayoutAnchorable; - lastAreaTabItem = lastAreaTabItem == null || lastAreaTabItem.GetScreenArea().Right < dropAreaTabItem.GetScreenArea().Right ? - dropAreaTabItem : lastAreaTabItem; - int tabIndex = parentPaneModel.Children.IndexOf(tabItemModel); - yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, dropAreaTabItem.GetScreenArea(), DropTargetType.AnchorablePaneDockInside, tabIndex); - } - - if (lastAreaTabItem != null) - { - var lastAreaTabItemScreenArea = lastAreaTabItem.GetScreenArea(); - var newAreaTabItemScreenArea = new Rect(lastAreaTabItemScreenArea.TopRight, new Point(lastAreaTabItemScreenArea.Right + lastAreaTabItemScreenArea.Width, lastAreaTabItemScreenArea.Bottom)); - if (newAreaTabItemScreenArea.Right < dropAreaAnchorablePane.AreaElement.GetScreenArea().Right) - yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, newAreaTabItemScreenArea, DropTargetType.AnchorablePaneDockInside, parentPaneModel.Children.Count); - } - - var dropAreaTitle = dropAreaAnchorablePane.AreaElement.FindVisualChildren().FirstOrDefault(); - if (dropAreaTitle != null) - yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, dropAreaTitle.GetScreenArea(), DropTargetType.AnchorablePaneDockInside); - } - break; - case DropAreaType.DocumentPane: - { - bool isDraggingAnchorables = _floatingWindow.Model is LayoutAnchorableFloatingWindow; - if (isDraggingAnchorables && _gridDocumentPaneFullDropTargets != null) - { - var dropAreaDocumentPane = visibleArea as DropArea; - if (_documentPaneFullDropTargetLeft.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetLeft.GetScreenArea(), DropTargetType.DocumentPaneDockLeft); - if (_documentPaneFullDropTargetTop.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetTop.GetScreenArea(), DropTargetType.DocumentPaneDockTop); - if (_documentPaneFullDropTargetRight.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetRight.GetScreenArea(), DropTargetType.DocumentPaneDockRight); - if (_documentPaneFullDropTargetBottom.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetBottom.GetScreenArea(), DropTargetType.DocumentPaneDockBottom); - if (_documentPaneFullDropTargetInto.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetInto.GetScreenArea(), DropTargetType.DocumentPaneDockInside); - - var parentPaneModel = dropAreaDocumentPane.AreaElement.Model as LayoutDocumentPane; - LayoutDocumentTabItem lastAreaTabItem = null; - foreach (var dropAreaTabItem in dropAreaDocumentPane.AreaElement.FindVisualChildren()) - { - var tabItemModel = dropAreaTabItem.Model; - lastAreaTabItem = lastAreaTabItem == null || lastAreaTabItem.GetScreenArea().Right < dropAreaTabItem.GetScreenArea().Right ? - dropAreaTabItem : lastAreaTabItem; - int tabIndex = parentPaneModel.Children.IndexOf(tabItemModel); - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, dropAreaTabItem.GetScreenArea(), DropTargetType.DocumentPaneDockInside, tabIndex); - } - - if (lastAreaTabItem != null) - { - var lastAreaTabItemScreenArea = lastAreaTabItem.GetScreenArea(); - var newAreaTabItemScreenArea = new Rect(lastAreaTabItemScreenArea.TopRight, new Point(lastAreaTabItemScreenArea.Right + lastAreaTabItemScreenArea.Width, lastAreaTabItemScreenArea.Bottom)); - if (newAreaTabItemScreenArea.Right < dropAreaDocumentPane.AreaElement.GetScreenArea().Right) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, newAreaTabItemScreenArea, DropTargetType.DocumentPaneDockInside, parentPaneModel.Children.Count); - } - - if (_documentPaneDropTargetLeftAsAnchorablePane.IsVisible) - yield return new DocumentPaneDropAsAnchorableTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetLeftAsAnchorablePane.GetScreenArea(), DropTargetType.DocumentPaneDockAsAnchorableLeft); - if (_documentPaneDropTargetTopAsAnchorablePane.IsVisible) - yield return new DocumentPaneDropAsAnchorableTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetTopAsAnchorablePane.GetScreenArea(), DropTargetType.DocumentPaneDockAsAnchorableTop); - if (_documentPaneDropTargetRightAsAnchorablePane.IsVisible) - yield return new DocumentPaneDropAsAnchorableTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetRightAsAnchorablePane.GetScreenArea(), DropTargetType.DocumentPaneDockAsAnchorableRight); - if (_documentPaneDropTargetBottomAsAnchorablePane.IsVisible) - yield return new DocumentPaneDropAsAnchorableTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetBottomAsAnchorablePane.GetScreenArea(), DropTargetType.DocumentPaneDockAsAnchorableBottom); - } - else - { - - var dropAreaDocumentPane = visibleArea as DropArea; - if (_documentPaneDropTargetLeft.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetLeft.GetScreenArea(), DropTargetType.DocumentPaneDockLeft); - if (_documentPaneDropTargetTop.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetTop.GetScreenArea(), DropTargetType.DocumentPaneDockTop); - if (_documentPaneDropTargetRight.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetRight.GetScreenArea(), DropTargetType.DocumentPaneDockRight); - if (_documentPaneDropTargetBottom.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetBottom.GetScreenArea(), DropTargetType.DocumentPaneDockBottom); - if (_documentPaneDropTargetInto.IsVisible) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetInto.GetScreenArea(), DropTargetType.DocumentPaneDockInside); - - var parentPaneModel = dropAreaDocumentPane.AreaElement.Model as LayoutDocumentPane; - LayoutDocumentTabItem lastAreaTabItem = null; - foreach (var dropAreaTabItem in dropAreaDocumentPane.AreaElement.FindVisualChildren()) - { - var tabItemModel = dropAreaTabItem.Model; - lastAreaTabItem = lastAreaTabItem == null || lastAreaTabItem.GetScreenArea().Right < dropAreaTabItem.GetScreenArea().Right ? - dropAreaTabItem : lastAreaTabItem; - int tabIndex = parentPaneModel.Children.IndexOf(tabItemModel); - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, dropAreaTabItem.GetScreenArea(), DropTargetType.DocumentPaneDockInside, tabIndex); - } - - if (lastAreaTabItem != null) - { - var lastAreaTabItemScreenArea = lastAreaTabItem.GetScreenArea(); - var newAreaTabItemScreenArea = new Rect(lastAreaTabItemScreenArea.TopRight, new Point(lastAreaTabItemScreenArea.Right + lastAreaTabItemScreenArea.Width, lastAreaTabItemScreenArea.Bottom)); - if (newAreaTabItemScreenArea.Right < dropAreaDocumentPane.AreaElement.GetScreenArea().Right) - yield return new DocumentPaneDropTarget(dropAreaDocumentPane.AreaElement, newAreaTabItemScreenArea, DropTargetType.DocumentPaneDockInside, parentPaneModel.Children.Count); - } - } - } - break; - case DropAreaType.DocumentPaneGroup: - { - var dropAreaDocumentPane = visibleArea as DropArea; - if (_documentPaneDropTargetInto.IsVisible) - yield return new DocumentPaneGroupDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetInto.GetScreenArea(), DropTargetType.DocumentPaneGroupDockInside); - } - break; - } - - } - yield break; - } - - LayoutFloatingWindowControl _floatingWindow = null; - void IOverlayWindow.DragEnter(LayoutFloatingWindowControl floatingWindow) - { - _floatingWindow = floatingWindow; - EnableDropTargets(); - } - - void IOverlayWindow.DragLeave(LayoutFloatingWindowControl floatingWindow) - { - Visibility = System.Windows.Visibility.Hidden; - _floatingWindow = null; - } - - protected override void OnClosing(System.ComponentModel.CancelEventArgs e) - { - base.OnClosing(e); - } - - - List _visibleAreas = new List(); - void IOverlayWindow.DragEnter(IDropArea area) - { - _visibleAreas.Add(area); - - FrameworkElement areaElement; - switch (area.Type) - { - case DropAreaType.DockingManager: - areaElement = _gridDockingManagerDropTargets; - break; - case DropAreaType.AnchorablePane: - areaElement = _gridAnchorablePaneDropTargets; - break; - case DropAreaType.DocumentPaneGroup: - { - areaElement = _gridDocumentPaneDropTargets; - var dropAreaDocumentPaneGroup = area as DropArea; - var layoutDocumentPane = (dropAreaDocumentPaneGroup.AreaElement.Model as LayoutDocumentPaneGroup).Children.First() as LayoutDocumentPane; - var parentDocumentPaneGroup = layoutDocumentPane.Parent as LayoutDocumentPaneGroup; + public class OverlayWindow : Window, IOverlayWindow + { + #region Members + + private ResourceDictionary currentThemeResourceDictionary; // = null + private Canvas _mainCanvasPanel; + private Grid _gridDockingManagerDropTargets; + private Grid _gridAnchorablePaneDropTargets; + private Grid _gridDocumentPaneDropTargets; + private Grid _gridDocumentPaneFullDropTargets; + + private FrameworkElement _dockingManagerDropTargetBottom; + private FrameworkElement _dockingManagerDropTargetTop; + private FrameworkElement _dockingManagerDropTargetLeft; + private FrameworkElement _dockingManagerDropTargetRight; + + private FrameworkElement _anchorablePaneDropTargetBottom; + private FrameworkElement _anchorablePaneDropTargetTop; + private FrameworkElement _anchorablePaneDropTargetLeft; + private FrameworkElement _anchorablePaneDropTargetRight; + private FrameworkElement _anchorablePaneDropTargetInto; + + private FrameworkElement _documentPaneDropTargetBottom; + private FrameworkElement _documentPaneDropTargetTop; + private FrameworkElement _documentPaneDropTargetLeft; + private FrameworkElement _documentPaneDropTargetRight; + private FrameworkElement _documentPaneDropTargetInto; + + private FrameworkElement _documentPaneDropTargetBottomAsAnchorablePane; + private FrameworkElement _documentPaneDropTargetTopAsAnchorablePane; + private FrameworkElement _documentPaneDropTargetLeftAsAnchorablePane; + private FrameworkElement _documentPaneDropTargetRightAsAnchorablePane; + + private FrameworkElement _documentPaneFullDropTargetBottom; + private FrameworkElement _documentPaneFullDropTargetTop; + private FrameworkElement _documentPaneFullDropTargetLeft; + private FrameworkElement _documentPaneFullDropTargetRight; + private FrameworkElement _documentPaneFullDropTargetInto; + + private Path _previewBox; + private IOverlayWindowHost _host; + private LayoutFloatingWindowControl _floatingWindow = null; + private List _visibleAreas = new List(); + + #endregion + + #region Constructors + + static OverlayWindow() + { + DefaultStyleKeyProperty.OverrideMetadata( typeof( OverlayWindow ), new FrameworkPropertyMetadata( typeof( OverlayWindow ) ) ); + + OverlayWindow.AllowsTransparencyProperty.OverrideMetadata( typeof( OverlayWindow ), new FrameworkPropertyMetadata( true ) ); + OverlayWindow.WindowStyleProperty.OverrideMetadata( typeof( OverlayWindow ), new FrameworkPropertyMetadata( WindowStyle.None ) ); + OverlayWindow.ShowInTaskbarProperty.OverrideMetadata( typeof( OverlayWindow ), new FrameworkPropertyMetadata( false ) ); + OverlayWindow.ShowActivatedProperty.OverrideMetadata( typeof( OverlayWindow ), new FrameworkPropertyMetadata( false ) ); + OverlayWindow.VisibilityProperty.OverrideMetadata( typeof( OverlayWindow ), new FrameworkPropertyMetadata( Visibility.Hidden ) ); + } + + internal OverlayWindow( IOverlayWindowHost host ) + { + _host = host; + UpdateThemeResources(); + } + + #endregion + + #region Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _mainCanvasPanel = GetTemplateChild( "PART_DropTargetsContainer" ) as Canvas; + _gridDockingManagerDropTargets = GetTemplateChild( "PART_DockingManagerDropTargets" ) as Grid; + _gridAnchorablePaneDropTargets = GetTemplateChild( "PART_AnchorablePaneDropTargets" ) as Grid; + _gridDocumentPaneDropTargets = GetTemplateChild( "PART_DocumentPaneDropTargets" ) as Grid; + _gridDocumentPaneFullDropTargets = GetTemplateChild( "PART_DocumentPaneFullDropTargets" ) as Grid; + + _gridDockingManagerDropTargets.Visibility = System.Windows.Visibility.Hidden; + _gridAnchorablePaneDropTargets.Visibility = System.Windows.Visibility.Hidden; + _gridDocumentPaneDropTargets.Visibility = System.Windows.Visibility.Hidden; + if( _gridDocumentPaneFullDropTargets != null ) + _gridDocumentPaneFullDropTargets.Visibility = System.Windows.Visibility.Hidden; + + _dockingManagerDropTargetBottom = GetTemplateChild( "PART_DockingManagerDropTargetBottom" ) as FrameworkElement; + _dockingManagerDropTargetTop = GetTemplateChild( "PART_DockingManagerDropTargetTop" ) as FrameworkElement; + _dockingManagerDropTargetLeft = GetTemplateChild( "PART_DockingManagerDropTargetLeft" ) as FrameworkElement; + _dockingManagerDropTargetRight = GetTemplateChild( "PART_DockingManagerDropTargetRight" ) as FrameworkElement; + + _anchorablePaneDropTargetBottom = GetTemplateChild( "PART_AnchorablePaneDropTargetBottom" ) as FrameworkElement; + _anchorablePaneDropTargetTop = GetTemplateChild( "PART_AnchorablePaneDropTargetTop" ) as FrameworkElement; + _anchorablePaneDropTargetLeft = GetTemplateChild( "PART_AnchorablePaneDropTargetLeft" ) as FrameworkElement; + _anchorablePaneDropTargetRight = GetTemplateChild( "PART_AnchorablePaneDropTargetRight" ) as FrameworkElement; + _anchorablePaneDropTargetInto = GetTemplateChild( "PART_AnchorablePaneDropTargetInto" ) as FrameworkElement; + + _documentPaneDropTargetBottom = GetTemplateChild( "PART_DocumentPaneDropTargetBottom" ) as FrameworkElement; + _documentPaneDropTargetTop = GetTemplateChild( "PART_DocumentPaneDropTargetTop" ) as FrameworkElement; + _documentPaneDropTargetLeft = GetTemplateChild( "PART_DocumentPaneDropTargetLeft" ) as FrameworkElement; + _documentPaneDropTargetRight = GetTemplateChild( "PART_DocumentPaneDropTargetRight" ) as FrameworkElement; + _documentPaneDropTargetInto = GetTemplateChild( "PART_DocumentPaneDropTargetInto" ) as FrameworkElement; + + _documentPaneDropTargetBottomAsAnchorablePane = GetTemplateChild( "PART_DocumentPaneDropTargetBottomAsAnchorablePane" ) as FrameworkElement; + _documentPaneDropTargetTopAsAnchorablePane = GetTemplateChild( "PART_DocumentPaneDropTargetTopAsAnchorablePane" ) as FrameworkElement; + _documentPaneDropTargetLeftAsAnchorablePane = GetTemplateChild( "PART_DocumentPaneDropTargetLeftAsAnchorablePane" ) as FrameworkElement; + _documentPaneDropTargetRightAsAnchorablePane = GetTemplateChild( "PART_DocumentPaneDropTargetRightAsAnchorablePane" ) as FrameworkElement; + + _documentPaneFullDropTargetBottom = GetTemplateChild( "PART_DocumentPaneFullDropTargetBottom" ) as FrameworkElement; + _documentPaneFullDropTargetTop = GetTemplateChild( "PART_DocumentPaneFullDropTargetTop" ) as FrameworkElement; + _documentPaneFullDropTargetLeft = GetTemplateChild( "PART_DocumentPaneFullDropTargetLeft" ) as FrameworkElement; + _documentPaneFullDropTargetRight = GetTemplateChild( "PART_DocumentPaneFullDropTargetRight" ) as FrameworkElement; + _documentPaneFullDropTargetInto = GetTemplateChild( "PART_DocumentPaneFullDropTargetInto" ) as FrameworkElement; + + _previewBox = GetTemplateChild( "PART_PreviewBox" ) as Path; + } + + protected override void OnClosing( System.ComponentModel.CancelEventArgs e ) + { + base.OnClosing( e ); + } + + #endregion + + #region Internal Methods + + internal void UpdateThemeResources( Theme oldTheme = null ) + { + if (Application.Current != null) + return; + + if ( oldTheme != null ) + { + if( oldTheme is DictionaryTheme ) + { + if( currentThemeResourceDictionary != null ) + { + Resources.MergedDictionaries.Remove( currentThemeResourceDictionary ); + currentThemeResourceDictionary = null; + } + } + else + { + var resourceDictionaryToRemove = + Resources.MergedDictionaries.FirstOrDefault( r => r.Source == oldTheme.GetResourceUri() ); + if( resourceDictionaryToRemove != null ) + Resources.MergedDictionaries.Remove( + resourceDictionaryToRemove ); + } + } + + if( _host.Manager.Theme != null ) + { + if( _host.Manager.Theme is DictionaryTheme ) + { + currentThemeResourceDictionary = ( ( DictionaryTheme )_host.Manager.Theme ).ThemeResourceDictionary; + Resources.MergedDictionaries.Add( currentThemeResourceDictionary ); + } + else + { + Resources.MergedDictionaries.Add( new ResourceDictionary() { Source = _host.Manager.Theme.GetResourceUri() } ); + } + } + } + + internal void EnableDropTargets() + { + if( _mainCanvasPanel != null ) + _mainCanvasPanel.Visibility = System.Windows.Visibility.Visible; + } + + internal void HideDropTargets() + { + if( _mainCanvasPanel != null ) + _mainCanvasPanel.Visibility = System.Windows.Visibility.Hidden; + + } + + #endregion + + #region Private Methods + + /// + /// This method controls the DropTargetInto button of the overlay window. + /// It checks that only 1 of the defined ContentLayouts can be present on the LayoutDocumentPane or LayoutAnchorablePane. + /// The combination between the ContentLayout Title and the ContentId is the search key, and has to be unique. + /// If a floating window is dropped on a LayoutDocumentPane or LayoutAnchorablePane, it checks if one of the containing LayoutContents + /// is already present on the LayoutDocumentPane or LayoutAnchorablePane. If so, then it will disable the DropTargetInto button. + /// + /// The given LayoutDocumentPane or LayoutAnchorablePane + private void SetDropTargetIntoVisibility( ILayoutPositionableElement positionableElement ) + { + if( positionableElement is LayoutAnchorablePane ) + { + _anchorablePaneDropTargetInto.Visibility = Visibility.Visible; + } + else if( positionableElement is LayoutDocumentPane ) + { + _documentPaneDropTargetInto.Visibility = Visibility.Visible; + } + + if( positionableElement == null || _floatingWindow.Model == null || positionableElement.AllowDuplicateContent ) + { + return; + } + + // Find all content layouts in the anchorable pane (object to drop on) + var contentLayoutsOnPositionableElementPane = GetAllLayoutContents( positionableElement ); + + // Find all content layouts in the floating window (object to drop) + var contentLayoutsOnFloatingWindow = GetAllLayoutContents( _floatingWindow.Model ); + + // If any of the content layouts is present in the drop area, then disable the DropTargetInto button. + foreach( var content in contentLayoutsOnFloatingWindow ) + { + if( !contentLayoutsOnPositionableElementPane.Any( item => + item.Title == content.Title && + item.ContentId == content.ContentId ) ) + { + continue; + } + + if( positionableElement is LayoutAnchorablePane ) + { + _anchorablePaneDropTargetInto.Visibility = Visibility.Hidden; + } + else if( positionableElement is LayoutDocumentPane ) + { + _documentPaneDropTargetInto.Visibility = Visibility.Hidden; + } + break; + } + } + + /// + /// Find any LayoutDocument or LayoutAnchorable from a given source (e.g. LayoutDocumentPane, LayoutAnchorableFloatingWindow, etc.) + /// + /// The given source to search in + /// A list of all LayoutContent's + private List GetAllLayoutContents( object source ) + { + var result = new List(); + + var documentFloatingWindow = source as LayoutDocumentFloatingWindow; + if( documentFloatingWindow != null ) + { + foreach( var layoutElement in documentFloatingWindow.Children ) + { + result.AddRange( GetAllLayoutContents( layoutElement ) ); + } + } + + var anchorableFloatingWindow = source as LayoutAnchorableFloatingWindow; + if( anchorableFloatingWindow != null ) + { + foreach( var layoutElement in anchorableFloatingWindow.Children ) + { + result.AddRange( GetAllLayoutContents( layoutElement ) ); + } + } + + var documentPaneGroup = source as LayoutDocumentPaneGroup; + if( documentPaneGroup != null ) + { + foreach( var layoutDocumentPane in documentPaneGroup.Children ) + { + result.AddRange( GetAllLayoutContents( layoutDocumentPane ) ); + } + } + + var anchorablePaneGroup = source as LayoutAnchorablePaneGroup; + if( anchorablePaneGroup != null ) + { + foreach( var layoutDocumentPane in anchorablePaneGroup.Children ) + { + result.AddRange( GetAllLayoutContents( layoutDocumentPane ) ); + } + } + + var documentPane = source as LayoutDocumentPane; + if( documentPane != null ) + { + foreach( var layoutContent in documentPane.Children ) + { + result.Add( layoutContent ); + } + } + + var anchorablePane = source as LayoutAnchorablePane; + if( anchorablePane != null ) + { + foreach( var layoutContent in anchorablePane.Children ) + { + result.Add( layoutContent ); + } + } + + var document = source as LayoutDocument; + if( document != null ) + { + result.Add( document ); + } + + var anchorable = source as LayoutAnchorable; + if( anchorable != null ) + { + result.Add( anchorable ); + } + + return result; + } + + #endregion + + #region IOverlayWindow + + IEnumerable IOverlayWindow.GetTargets() + { + foreach( var visibleArea in _visibleAreas ) + { + switch( visibleArea.Type ) + { + case DropAreaType.DockingManager: + { + var dropAreaDockingManager = visibleArea as DropArea; + yield return new DockingManagerDropTarget( dropAreaDockingManager.AreaElement, _dockingManagerDropTargetLeft.GetScreenArea(), DropTargetType.DockingManagerDockLeft ); + yield return new DockingManagerDropTarget( dropAreaDockingManager.AreaElement, _dockingManagerDropTargetTop.GetScreenArea(), DropTargetType.DockingManagerDockTop ); + yield return new DockingManagerDropTarget( dropAreaDockingManager.AreaElement, _dockingManagerDropTargetBottom.GetScreenArea(), DropTargetType.DockingManagerDockBottom ); + yield return new DockingManagerDropTarget( dropAreaDockingManager.AreaElement, _dockingManagerDropTargetRight.GetScreenArea(), DropTargetType.DockingManagerDockRight ); + } + break; + case DropAreaType.AnchorablePane: + { + var dropAreaAnchorablePane = visibleArea as DropArea; + yield return new AnchorablePaneDropTarget( dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetLeft.GetScreenArea(), DropTargetType.AnchorablePaneDockLeft ); + yield return new AnchorablePaneDropTarget( dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetTop.GetScreenArea(), DropTargetType.AnchorablePaneDockTop ); + yield return new AnchorablePaneDropTarget( dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetRight.GetScreenArea(), DropTargetType.AnchorablePaneDockRight ); + yield return new AnchorablePaneDropTarget( dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetBottom.GetScreenArea(), DropTargetType.AnchorablePaneDockBottom ); + if( _anchorablePaneDropTargetInto.IsVisible ) + yield return new AnchorablePaneDropTarget( dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetInto.GetScreenArea(), DropTargetType.AnchorablePaneDockInside ); + + var parentPaneModel = dropAreaAnchorablePane.AreaElement.Model as LayoutAnchorablePane; + LayoutAnchorableTabItem lastAreaTabItem = null; + foreach( var dropAreaTabItem in dropAreaAnchorablePane.AreaElement.FindVisualChildren() ) + { + var tabItemModel = dropAreaTabItem.Model as LayoutAnchorable; + lastAreaTabItem = lastAreaTabItem == null || lastAreaTabItem.GetScreenArea().Right < dropAreaTabItem.GetScreenArea().Right ? + dropAreaTabItem : lastAreaTabItem; + int tabIndex = parentPaneModel.Children.IndexOf( tabItemModel ); + yield return new AnchorablePaneDropTarget( dropAreaAnchorablePane.AreaElement, dropAreaTabItem.GetScreenArea(), DropTargetType.AnchorablePaneDockInside, tabIndex ); + } + + if( lastAreaTabItem != null ) + { + var lastAreaTabItemScreenArea = lastAreaTabItem.GetScreenArea(); + var newAreaTabItemScreenArea = new Rect( lastAreaTabItemScreenArea.TopRight, new Point( lastAreaTabItemScreenArea.Right + lastAreaTabItemScreenArea.Width, lastAreaTabItemScreenArea.Bottom ) ); + if( newAreaTabItemScreenArea.Right < dropAreaAnchorablePane.AreaElement.GetScreenArea().Right ) + yield return new AnchorablePaneDropTarget( dropAreaAnchorablePane.AreaElement, newAreaTabItemScreenArea, DropTargetType.AnchorablePaneDockInside, parentPaneModel.Children.Count ); + } + + var dropAreaTitle = dropAreaAnchorablePane.AreaElement.FindVisualChildren().FirstOrDefault(); + if( dropAreaTitle != null ) + yield return new AnchorablePaneDropTarget( dropAreaAnchorablePane.AreaElement, dropAreaTitle.GetScreenArea(), DropTargetType.AnchorablePaneDockInside ); + } + break; + case DropAreaType.DocumentPane: + { + bool isDraggingAnchorables = _floatingWindow.Model is LayoutAnchorableFloatingWindow; + if( isDraggingAnchorables && _gridDocumentPaneFullDropTargets != null ) + { + var dropAreaDocumentPane = visibleArea as DropArea; + if( _documentPaneFullDropTargetLeft.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetLeft.GetScreenArea(), DropTargetType.DocumentPaneDockLeft ); + if( _documentPaneFullDropTargetTop.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetTop.GetScreenArea(), DropTargetType.DocumentPaneDockTop ); + if( _documentPaneFullDropTargetRight.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetRight.GetScreenArea(), DropTargetType.DocumentPaneDockRight ); + if( _documentPaneFullDropTargetBottom.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetBottom.GetScreenArea(), DropTargetType.DocumentPaneDockBottom ); + if( _documentPaneFullDropTargetInto.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneFullDropTargetInto.GetScreenArea(), DropTargetType.DocumentPaneDockInside ); + + var parentPaneModel = dropAreaDocumentPane.AreaElement.Model as LayoutDocumentPane; + LayoutDocumentTabItem lastAreaTabItem = null; + foreach( var dropAreaTabItem in dropAreaDocumentPane.AreaElement.FindVisualChildren() ) + { + var tabItemModel = dropAreaTabItem.Model; + lastAreaTabItem = lastAreaTabItem == null || lastAreaTabItem.GetScreenArea().Right < dropAreaTabItem.GetScreenArea().Right ? + dropAreaTabItem : lastAreaTabItem; + int tabIndex = parentPaneModel.Children.IndexOf( tabItemModel ); + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, dropAreaTabItem.GetScreenArea(), DropTargetType.DocumentPaneDockInside, tabIndex ); + } + + if( lastAreaTabItem != null ) + { + var lastAreaTabItemScreenArea = lastAreaTabItem.GetScreenArea(); + var newAreaTabItemScreenArea = new Rect( lastAreaTabItemScreenArea.TopRight, new Point( lastAreaTabItemScreenArea.Right + lastAreaTabItemScreenArea.Width, lastAreaTabItemScreenArea.Bottom ) ); + if( newAreaTabItemScreenArea.Right < dropAreaDocumentPane.AreaElement.GetScreenArea().Right ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, newAreaTabItemScreenArea, DropTargetType.DocumentPaneDockInside, parentPaneModel.Children.Count ); + } + + if( _documentPaneDropTargetLeftAsAnchorablePane.IsVisible ) + yield return new DocumentPaneDropAsAnchorableTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetLeftAsAnchorablePane.GetScreenArea(), DropTargetType.DocumentPaneDockAsAnchorableLeft ); + if( _documentPaneDropTargetTopAsAnchorablePane.IsVisible ) + yield return new DocumentPaneDropAsAnchorableTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetTopAsAnchorablePane.GetScreenArea(), DropTargetType.DocumentPaneDockAsAnchorableTop ); + if( _documentPaneDropTargetRightAsAnchorablePane.IsVisible ) + yield return new DocumentPaneDropAsAnchorableTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetRightAsAnchorablePane.GetScreenArea(), DropTargetType.DocumentPaneDockAsAnchorableRight ); + if( _documentPaneDropTargetBottomAsAnchorablePane.IsVisible ) + yield return new DocumentPaneDropAsAnchorableTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetBottomAsAnchorablePane.GetScreenArea(), DropTargetType.DocumentPaneDockAsAnchorableBottom ); + } + else + { + + var dropAreaDocumentPane = visibleArea as DropArea; + if( _documentPaneDropTargetLeft.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetLeft.GetScreenArea(), DropTargetType.DocumentPaneDockLeft ); + if( _documentPaneDropTargetTop.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetTop.GetScreenArea(), DropTargetType.DocumentPaneDockTop ); + if( _documentPaneDropTargetRight.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetRight.GetScreenArea(), DropTargetType.DocumentPaneDockRight ); + if( _documentPaneDropTargetBottom.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetBottom.GetScreenArea(), DropTargetType.DocumentPaneDockBottom ); + if( _documentPaneDropTargetInto.IsVisible ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetInto.GetScreenArea(), DropTargetType.DocumentPaneDockInside ); + + var parentPaneModel = dropAreaDocumentPane.AreaElement.Model as LayoutDocumentPane; + LayoutDocumentTabItem lastAreaTabItem = null; + foreach( var dropAreaTabItem in dropAreaDocumentPane.AreaElement.FindVisualChildren() ) + { + var tabItemModel = dropAreaTabItem.Model; + lastAreaTabItem = lastAreaTabItem == null || lastAreaTabItem.GetScreenArea().Right < dropAreaTabItem.GetScreenArea().Right ? + dropAreaTabItem : lastAreaTabItem; + int tabIndex = parentPaneModel.Children.IndexOf( tabItemModel ); + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, dropAreaTabItem.GetScreenArea(), DropTargetType.DocumentPaneDockInside, tabIndex ); + } + + if( lastAreaTabItem != null ) + { + var lastAreaTabItemScreenArea = lastAreaTabItem.GetScreenArea(); + var newAreaTabItemScreenArea = new Rect( lastAreaTabItemScreenArea.TopRight, new Point( lastAreaTabItemScreenArea.Right + lastAreaTabItemScreenArea.Width, lastAreaTabItemScreenArea.Bottom ) ); + if( newAreaTabItemScreenArea.Right < dropAreaDocumentPane.AreaElement.GetScreenArea().Right ) + yield return new DocumentPaneDropTarget( dropAreaDocumentPane.AreaElement, newAreaTabItemScreenArea, DropTargetType.DocumentPaneDockInside, parentPaneModel.Children.Count ); + } + } + } + break; + case DropAreaType.DocumentPaneGroup: + { + var dropAreaDocumentPane = visibleArea as DropArea; + if( _documentPaneDropTargetInto.IsVisible ) + yield return new DocumentPaneGroupDropTarget( dropAreaDocumentPane.AreaElement, _documentPaneDropTargetInto.GetScreenArea(), DropTargetType.DocumentPaneGroupDockInside ); + } + break; + } + + } + yield break; + } + + void IOverlayWindow.DragEnter( LayoutFloatingWindowControl floatingWindow ) + { + _floatingWindow = floatingWindow; + EnableDropTargets(); + } + + void IOverlayWindow.DragLeave( LayoutFloatingWindowControl floatingWindow ) + { + Visibility = System.Windows.Visibility.Hidden; + _floatingWindow = null; + } + + void IOverlayWindow.DragEnter( IDropArea area ) + { + _visibleAreas.Add( area ); + + FrameworkElement areaElement; + switch( area.Type ) + { + case DropAreaType.DockingManager: + areaElement = _gridDockingManagerDropTargets; + break; + case DropAreaType.AnchorablePane: + areaElement = _gridAnchorablePaneDropTargets; + + var dropAreaAnchorablePaneGroup = area as DropArea; + var layoutAnchorablePane = dropAreaAnchorablePaneGroup.AreaElement.Model as LayoutAnchorablePane; + SetDropTargetIntoVisibility( layoutAnchorablePane ); + break; + case DropAreaType.DocumentPaneGroup: + { + areaElement = _gridDocumentPaneDropTargets; + var dropAreaDocumentPaneGroup = area as DropArea; + var layoutDocumentPane = ( dropAreaDocumentPaneGroup.AreaElement.Model as LayoutDocumentPaneGroup ).Children.First() as LayoutDocumentPane; + var parentDocumentPaneGroup = layoutDocumentPane.Parent as LayoutDocumentPaneGroup; _documentPaneDropTargetLeft.Visibility = Visibility.Hidden; _documentPaneDropTargetRight.Visibility = Visibility.Hidden; @@ -373,135 +538,139 @@ namespace Xceed.Wpf.AvalonDock.Controls var layoutDocumentPane = dropAreaDocumentPaneGroup.AreaElement.Model as LayoutDocumentPane; var parentDocumentPaneGroup = layoutDocumentPane.Parent as LayoutDocumentPaneGroup; - if (parentDocumentPaneGroup != null && - parentDocumentPaneGroup.Children.Where(c => c.IsVisible).Count() > 1) - { - var manager = parentDocumentPaneGroup.Root.Manager; - if (!manager.AllowMixedOrientation) - { - _documentPaneFullDropTargetLeft.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Hidden; - _documentPaneFullDropTargetRight.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Hidden; - _documentPaneFullDropTargetTop.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Vertical ? Visibility.Visible : Visibility.Hidden; - _documentPaneFullDropTargetBottom.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Vertical ? Visibility.Visible : Visibility.Hidden; - } - else - { - _documentPaneFullDropTargetLeft.Visibility = Visibility.Visible; - _documentPaneFullDropTargetRight.Visibility = Visibility.Visible; - _documentPaneFullDropTargetTop.Visibility = Visibility.Visible; - _documentPaneFullDropTargetBottom.Visibility = Visibility.Visible; - } - } - else if (parentDocumentPaneGroup == null && - layoutDocumentPane != null && - layoutDocumentPane.ChildrenCount == 0) - { - _documentPaneFullDropTargetLeft.Visibility = Visibility.Hidden; - _documentPaneFullDropTargetRight.Visibility = Visibility.Hidden; - _documentPaneFullDropTargetTop.Visibility = Visibility.Hidden; - _documentPaneFullDropTargetBottom.Visibility = Visibility.Hidden; - } - else - { - _documentPaneFullDropTargetLeft.Visibility = Visibility.Visible; - _documentPaneFullDropTargetRight.Visibility = Visibility.Visible; - _documentPaneFullDropTargetTop.Visibility = Visibility.Visible; - _documentPaneFullDropTargetBottom.Visibility = Visibility.Visible; - } - - if (parentDocumentPaneGroup != null && - parentDocumentPaneGroup.Children.Where(c => c.IsVisible).Count() > 1) - { - int indexOfDocumentPane = parentDocumentPaneGroup.Children.Where(ch => ch.IsVisible).ToList().IndexOf(layoutDocumentPane); - bool isFirstChild = indexOfDocumentPane == 0; - bool isLastChild = indexOfDocumentPane == parentDocumentPaneGroup.ChildrenCount - 1; - - var manager = parentDocumentPaneGroup.Root.Manager; - if (!manager.AllowMixedOrientation) - { - _documentPaneDropTargetBottomAsAnchorablePane.Visibility = - parentDocumentPaneGroup.Orientation == Orientation.Vertical ? - (isLastChild ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden) : - System.Windows.Visibility.Hidden; - _documentPaneDropTargetTopAsAnchorablePane.Visibility = - parentDocumentPaneGroup.Orientation == Orientation.Vertical ? - (isFirstChild ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden) : - System.Windows.Visibility.Hidden; - - _documentPaneDropTargetLeftAsAnchorablePane.Visibility = - parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? - (isFirstChild ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden) : - System.Windows.Visibility.Hidden; - - - _documentPaneDropTargetRightAsAnchorablePane.Visibility = - parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? - (isLastChild ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden) : - System.Windows.Visibility.Hidden; - } - else - { - _documentPaneDropTargetBottomAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; - _documentPaneDropTargetLeftAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; - _documentPaneDropTargetRightAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; - _documentPaneDropTargetTopAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; - } - } - else - { - _documentPaneDropTargetBottomAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; - _documentPaneDropTargetLeftAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; - _documentPaneDropTargetRightAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; - _documentPaneDropTargetTopAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; - } - } - else - { - areaElement = _gridDocumentPaneDropTargets; - var dropAreaDocumentPaneGroup = area as DropArea; - var layoutDocumentPane = dropAreaDocumentPaneGroup.AreaElement.Model as LayoutDocumentPane; - var parentDocumentPaneGroup = layoutDocumentPane.Parent as LayoutDocumentPaneGroup; - - if (parentDocumentPaneGroup != null && - parentDocumentPaneGroup.Children.Where(c => c.IsVisible).Count() > 1) - { - var manager = parentDocumentPaneGroup.Root.Manager; - if (!manager.AllowMixedOrientation) - { - _documentPaneDropTargetLeft.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Hidden; - _documentPaneDropTargetRight.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Hidden; - _documentPaneDropTargetTop.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Vertical ? Visibility.Visible : Visibility.Hidden; - _documentPaneDropTargetBottom.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Vertical ? Visibility.Visible : Visibility.Hidden; - } - else - { - _documentPaneDropTargetLeft.Visibility = Visibility.Visible; - _documentPaneDropTargetRight.Visibility = Visibility.Visible; - _documentPaneDropTargetTop.Visibility = Visibility.Visible; - _documentPaneDropTargetBottom.Visibility = Visibility.Visible; - } - - } - else if (parentDocumentPaneGroup == null && - layoutDocumentPane != null && - layoutDocumentPane.ChildrenCount == 0) - { - _documentPaneDropTargetLeft.Visibility = Visibility.Hidden; - _documentPaneDropTargetRight.Visibility = Visibility.Hidden; - _documentPaneDropTargetTop.Visibility = Visibility.Hidden; - _documentPaneDropTargetBottom.Visibility = Visibility.Hidden; - } - else - { - _documentPaneDropTargetLeft.Visibility = Visibility.Visible; - _documentPaneDropTargetRight.Visibility = Visibility.Visible; - _documentPaneDropTargetTop.Visibility = Visibility.Visible; - _documentPaneDropTargetBottom.Visibility = Visibility.Visible; - } - } - } - break; - } + SetDropTargetIntoVisibility( layoutDocumentPane ); + + if( parentDocumentPaneGroup != null && + parentDocumentPaneGroup.Children.Where( c => c.IsVisible ).Count() > 1 ) + { + var manager = parentDocumentPaneGroup.Root.Manager; + if( !manager.AllowMixedOrientation ) + { + _documentPaneFullDropTargetLeft.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Hidden; + _documentPaneFullDropTargetRight.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Hidden; + _documentPaneFullDropTargetTop.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Vertical ? Visibility.Visible : Visibility.Hidden; + _documentPaneFullDropTargetBottom.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Vertical ? Visibility.Visible : Visibility.Hidden; + } + else + { + _documentPaneFullDropTargetLeft.Visibility = Visibility.Visible; + _documentPaneFullDropTargetRight.Visibility = Visibility.Visible; + _documentPaneFullDropTargetTop.Visibility = Visibility.Visible; + _documentPaneFullDropTargetBottom.Visibility = Visibility.Visible; + } + } + else if( parentDocumentPaneGroup == null && + layoutDocumentPane != null && + layoutDocumentPane.ChildrenCount == 0 ) + { + _documentPaneFullDropTargetLeft.Visibility = Visibility.Hidden; + _documentPaneFullDropTargetRight.Visibility = Visibility.Hidden; + _documentPaneFullDropTargetTop.Visibility = Visibility.Hidden; + _documentPaneFullDropTargetBottom.Visibility = Visibility.Hidden; + } + else + { + _documentPaneFullDropTargetLeft.Visibility = Visibility.Visible; + _documentPaneFullDropTargetRight.Visibility = Visibility.Visible; + _documentPaneFullDropTargetTop.Visibility = Visibility.Visible; + _documentPaneFullDropTargetBottom.Visibility = Visibility.Visible; + } + + if( parentDocumentPaneGroup != null && + parentDocumentPaneGroup.Children.Where( c => c.IsVisible ).Count() > 1 ) + { + int indexOfDocumentPane = parentDocumentPaneGroup.Children.Where( ch => ch.IsVisible ).ToList().IndexOf( layoutDocumentPane ); + bool isFirstChild = indexOfDocumentPane == 0; + bool isLastChild = indexOfDocumentPane == parentDocumentPaneGroup.ChildrenCount - 1; + + var manager = parentDocumentPaneGroup.Root.Manager; + if( !manager.AllowMixedOrientation ) + { + _documentPaneDropTargetBottomAsAnchorablePane.Visibility = + parentDocumentPaneGroup.Orientation == Orientation.Vertical ? + ( isLastChild ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden ) : + System.Windows.Visibility.Hidden; + _documentPaneDropTargetTopAsAnchorablePane.Visibility = + parentDocumentPaneGroup.Orientation == Orientation.Vertical ? + ( isFirstChild ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden ) : + System.Windows.Visibility.Hidden; + + _documentPaneDropTargetLeftAsAnchorablePane.Visibility = + parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? + ( isFirstChild ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden ) : + System.Windows.Visibility.Hidden; + + + _documentPaneDropTargetRightAsAnchorablePane.Visibility = + parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? + ( isLastChild ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden ) : + System.Windows.Visibility.Hidden; + } + else + { + _documentPaneDropTargetBottomAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; + _documentPaneDropTargetLeftAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; + _documentPaneDropTargetRightAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; + _documentPaneDropTargetTopAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; + } + } + else + { + _documentPaneDropTargetBottomAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; + _documentPaneDropTargetLeftAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; + _documentPaneDropTargetRightAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; + _documentPaneDropTargetTopAsAnchorablePane.Visibility = System.Windows.Visibility.Visible; + } + } + else + { + areaElement = _gridDocumentPaneDropTargets; + var dropAreaDocumentPaneGroup = area as DropArea; + var layoutDocumentPane = dropAreaDocumentPaneGroup.AreaElement.Model as LayoutDocumentPane; + var parentDocumentPaneGroup = layoutDocumentPane.Parent as LayoutDocumentPaneGroup; + + SetDropTargetIntoVisibility( layoutDocumentPane ); + + if( parentDocumentPaneGroup != null && + parentDocumentPaneGroup.Children.Where( c => c.IsVisible ).Count() > 1 ) + { + var manager = parentDocumentPaneGroup.Root.Manager; + if( !manager.AllowMixedOrientation ) + { + _documentPaneDropTargetLeft.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Hidden; + _documentPaneDropTargetRight.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Hidden; + _documentPaneDropTargetTop.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Vertical ? Visibility.Visible : Visibility.Hidden; + _documentPaneDropTargetBottom.Visibility = parentDocumentPaneGroup.Orientation == Orientation.Vertical ? Visibility.Visible : Visibility.Hidden; + } + else + { + _documentPaneDropTargetLeft.Visibility = Visibility.Visible; + _documentPaneDropTargetRight.Visibility = Visibility.Visible; + _documentPaneDropTargetTop.Visibility = Visibility.Visible; + _documentPaneDropTargetBottom.Visibility = Visibility.Visible; + } + + } + else if( parentDocumentPaneGroup == null && + layoutDocumentPane != null && + layoutDocumentPane.ChildrenCount == 0 ) + { + _documentPaneDropTargetLeft.Visibility = Visibility.Hidden; + _documentPaneDropTargetRight.Visibility = Visibility.Hidden; + _documentPaneDropTargetTop.Visibility = Visibility.Hidden; + _documentPaneDropTargetBottom.Visibility = Visibility.Hidden; + } + else + { + _documentPaneDropTargetLeft.Visibility = Visibility.Visible; + _documentPaneDropTargetRight.Visibility = Visibility.Visible; + _documentPaneDropTargetTop.Visibility = Visibility.Visible; + _documentPaneDropTargetBottom.Visibility = Visibility.Visible; + } + } + } + break; + } if (areaElement != null) { @@ -513,9 +682,9 @@ namespace Xceed.Wpf.AvalonDock.Controls } } - void IOverlayWindow.DragLeave(IDropArea area) - { - _visibleAreas.Remove(area); + void IOverlayWindow.DragLeave( IDropArea area ) + { + _visibleAreas.Remove( area ); FrameworkElement areaElement; switch (area.Type) @@ -544,30 +713,29 @@ namespace Xceed.Wpf.AvalonDock.Controls break; } - if (areaElement != null) - areaElement.Visibility = System.Windows.Visibility.Hidden; - } - - void IOverlayWindow.DragEnter(IDropTarget target) - { - var previewBoxPath = target.GetPreviewPath(this, _floatingWindow.Model as LayoutFloatingWindow); - if (previewBoxPath != null) - { - _previewBox.Data = previewBoxPath; - _previewBox.Visibility = System.Windows.Visibility.Visible; - } - } - - void IOverlayWindow.DragLeave(IDropTarget target) - { - _previewBox.Visibility = System.Windows.Visibility.Hidden; - } - - void IOverlayWindow.DragDrop(IDropTarget target) - { - target.Drop(_floatingWindow.Model as LayoutFloatingWindow); - } - - - } + areaElement.Visibility = System.Windows.Visibility.Hidden; + } + + void IOverlayWindow.DragEnter( IDropTarget target ) + { + var previewBoxPath = target.GetPreviewPath( this, _floatingWindow.Model as LayoutFloatingWindow ); + if( previewBoxPath != null ) + { + _previewBox.Data = previewBoxPath; + _previewBox.Visibility = System.Windows.Visibility.Visible; + } + } + + void IOverlayWindow.DragLeave( IDropTarget target ) + { + _previewBox.Visibility = System.Windows.Visibility.Hidden; + } + + void IOverlayWindow.DragDrop( IDropTarget target ) + { + target.Drop( _floatingWindow.Model as LayoutFloatingWindow ); + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindowDropTarget.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindowDropTarget.cs index 50b0468d..f84f87af 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindowDropTarget.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindowDropTarget.cs @@ -14,42 +14,51 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Controls; using System.Windows; namespace Xceed.Wpf.AvalonDock.Controls { - public class OverlayWindowDropTarget : IOverlayWindowDropTarget + public class OverlayWindowDropTarget : IOverlayWindowDropTarget + { + #region Members + + private IOverlayWindowArea _overlayArea; + private Rect _screenDetectionArea; + private OverlayWindowDropTargetType _type; + + #endregion + + #region Constructors + + internal OverlayWindowDropTarget( IOverlayWindowArea overlayArea, OverlayWindowDropTargetType targetType, FrameworkElement element ) { - internal OverlayWindowDropTarget(IOverlayWindowArea overlayArea, OverlayWindowDropTargetType targetType, FrameworkElement element) - { - _overlayArea = overlayArea; - _type = targetType; - _screenDetectionArea = new Rect(element.TransformToDeviceDPI(new Point()), element.TransformActualSizeToAncestor()); - } + _overlayArea = overlayArea; + _type = targetType; + _screenDetectionArea = new Rect( element.TransformToDeviceDPI( new Point() ), element.TransformActualSizeToAncestor() ); + } - IOverlayWindowArea _overlayArea; + #endregion - Rect _screenDetectionArea; - Rect IOverlayWindowDropTarget.ScreenDetectionArea - { - get - { - return _screenDetectionArea; - } - } + #region IOverlayWindowDropTarget - OverlayWindowDropTargetType _type; - OverlayWindowDropTargetType IOverlayWindowDropTarget.Type - { - get { return _type; } - } + Rect IOverlayWindowDropTarget.ScreenDetectionArea + { + get + { + return _screenDetectionArea; + } + } + OverlayWindowDropTargetType IOverlayWindowDropTarget.Type + { + get + { + return _type; + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindowDropTargetType.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindowDropTargetType.cs index 72e7a8c6..38019274 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindowDropTargetType.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/OverlayWindowDropTargetType.cs @@ -14,31 +14,26 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Controls { - public enum OverlayWindowDropTargetType - { - DockingManagerDockLeft, - DockingManagerDockTop, - DockingManagerDockRight, - DockingManagerDockBottom, - - DocumentPaneDockLeft, - DocumentPaneDockTop, - DocumentPaneDockRight, - DocumentPaneDockBottom, - DocumentPaneDockInside, - - AnchorablePaneDockLeft, - AnchorablePaneDockTop, - AnchorablePaneDockRight, - AnchorablePaneDockBottom, - AnchorablePaneDockInside, - - } + public enum OverlayWindowDropTargetType + { + DockingManagerDockLeft, + DockingManagerDockTop, + DockingManagerDockRight, + DockingManagerDockBottom, + + DocumentPaneDockLeft, + DocumentPaneDockTop, + DocumentPaneDockRight, + DocumentPaneDockBottom, + DocumentPaneDockInside, + + AnchorablePaneDockLeft, + AnchorablePaneDockTop, + AnchorablePaneDockRight, + AnchorablePaneDockBottom, + AnchorablePaneDockInside, + + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/ReentrantFlag.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/ReentrantFlag.cs index d37b569d..9da6440d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/ReentrantFlag.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/ReentrantFlag.cs @@ -15,42 +15,57 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Controls { - class ReentrantFlag + internal class ReentrantFlag + { + #region Members + + private bool _flag = false; + + #endregion + + #region Properties + + public bool CanEnter { - public class _ReentrantFlagHandler : IDisposable - { - ReentrantFlag _owner; - public _ReentrantFlagHandler(ReentrantFlag owner) - { - _owner = owner; - _owner._flag = true; - } - - public void Dispose() - { - _owner._flag = false; - } - } - - bool _flag = false; - - public _ReentrantFlagHandler Enter() - { - if (_flag) - throw new InvalidOperationException(); - return new _ReentrantFlagHandler(this); - } - - public bool CanEnter - { - get { return !_flag; } - } + get + { + return !_flag; + } + } + + #endregion + #region Public Methods + + public _ReentrantFlagHandler Enter() + { + if( _flag ) + throw new InvalidOperationException(); + return new _ReentrantFlagHandler( this ); } + + #endregion + + #region Internal Classes + + public class _ReentrantFlagHandler : IDisposable + { + private ReentrantFlag _owner; + public _ReentrantFlagHandler( ReentrantFlag owner ) + { + _owner = owner; + _owner._flag = true; + } + + public void Dispose() + { + _owner._flag = false; + } + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ComGuids.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ComGuids.cs index c84fbb18..b2890ef8 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ComGuids.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ComGuids.cs @@ -20,92 +20,92 @@ namespace Standard { - internal static partial class IID + internal static partial class IID + { + /// IID_IEnumIDList + public const string EnumIdList = "000214F2-0000-0000-C000-000000000046"; + /// IID_IEnumObjects + public const string EnumObjects = "2c1c7e2e-2d0e-4059-831e-1e6f82335c2e"; + /// IID_IHTMLDocument2 + public const string HtmlDocument2 = "332C4425-26CB-11D0-B483-00C04FD90119"; + /// IID_IModalWindow + public const string ModalWindow = "b4db1657-70d7-485e-8e3e-6fcb5a5c1802"; + /// IID_IObjectArray + public const string ObjectArray = "92CA9DCD-5622-4bba-A805-5E9F541BD8C9"; + /// IID_IObjectCollection + public const string ObjectCollection = "5632b1a4-e38a-400a-928a-d4cd63230295"; + /// IID_IPropertyNotifySink + public const string PropertyNotifySink = "9BFBBC02-EFF1-101A-84ED-00AA00341D07"; + /// IID_IPropertyStore + public const string PropertyStore = "886d8eeb-8cf2-4446-8d02-cdba1dbdcf99"; + /// IID_IServiceProvider + public const string ServiceProvider = "6d5140c1-7436-11ce-8034-00aa006009fa"; + /// IID_IShellFolder + public const string ShellFolder = "000214E6-0000-0000-C000-000000000046"; + /// IID_IShellLink + public const string ShellLink = "000214F9-0000-0000-C000-000000000046"; + /// IID_IShellItem + public const string ShellItem = "43826d1e-e718-42ee-bc55-a1e261c37bfe"; + /// IID_IShellItem2 + public const string ShellItem2 = "7e9fb0d3-919f-4307-ab2e-9b1860310c93"; + /// IID_IShellItemArray + public const string ShellItemArray = "B63EA76D-1F85-456F-A19C-48159EFA858B"; + /// IID_ITaskbarList + public const string TaskbarList = "56FDF342-FD6D-11d0-958A-006097C9A090"; + /// IID_ITaskbarList2 + public const string TaskbarList2 = "602D4995-B13A-429b-A66E-1935E44F4317"; + /// IID_IUnknown + public const string Unknown = "00000000-0000-0000-C000-000000000046"; + + #region Win7 IIDs + + /// IID_IApplicationDestinations + public const string ApplicationDestinations = "12337d35-94c6-48a0-bce7-6a9c69d4d600"; + /// IID_IApplicationDocumentLists + public const string ApplicationDocumentLists = "3c594f9f-9f30-47a1-979a-c9e83d3d0a06"; + /// IID_ICustomDestinationList + public const string CustomDestinationList = "6332debf-87b5-4670-90c0-5e57b408a49e"; + /// IID_IObjectWithAppUserModelID + public const string ObjectWithAppUserModelId = "36db0196-9665-46d1-9ba7-d3709eecf9ed"; + /// IID_IObjectWithProgID + public const string ObjectWithProgId = "71e806fb-8dee-46fc-bf8c-7748a8a1ae13"; + /// IID_ITaskbarList3 + public const string TaskbarList3 = "ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf"; + /// IID_ITaskbarList4 + public const string TaskbarList4 = "c43dc798-95d1-4bea-9030-bb99e2983a1a"; + + #endregion + } + + internal static partial class CLSID + { + public static T CoCreateInstance( string clsid ) { - /// IID_IEnumIDList - public const string EnumIdList = "000214F2-0000-0000-C000-000000000046"; - /// IID_IEnumObjects - public const string EnumObjects = "2c1c7e2e-2d0e-4059-831e-1e6f82335c2e"; - /// IID_IHTMLDocument2 - public const string HtmlDocument2 = "332C4425-26CB-11D0-B483-00C04FD90119"; - /// IID_IModalWindow - public const string ModalWindow = "b4db1657-70d7-485e-8e3e-6fcb5a5c1802"; - /// IID_IObjectArray - public const string ObjectArray = "92CA9DCD-5622-4bba-A805-5E9F541BD8C9"; - /// IID_IObjectCollection - public const string ObjectCollection = "5632b1a4-e38a-400a-928a-d4cd63230295"; - /// IID_IPropertyNotifySink - public const string PropertyNotifySink = "9BFBBC02-EFF1-101A-84ED-00AA00341D07"; - /// IID_IPropertyStore - public const string PropertyStore = "886d8eeb-8cf2-4446-8d02-cdba1dbdcf99"; - /// IID_IServiceProvider - public const string ServiceProvider = "6d5140c1-7436-11ce-8034-00aa006009fa"; - /// IID_IShellFolder - public const string ShellFolder = "000214E6-0000-0000-C000-000000000046"; - /// IID_IShellLink - public const string ShellLink = "000214F9-0000-0000-C000-000000000046"; - /// IID_IShellItem - public const string ShellItem = "43826d1e-e718-42ee-bc55-a1e261c37bfe"; - /// IID_IShellItem2 - public const string ShellItem2 = "7e9fb0d3-919f-4307-ab2e-9b1860310c93"; - /// IID_IShellItemArray - public const string ShellItemArray = "B63EA76D-1F85-456F-A19C-48159EFA858B"; - /// IID_ITaskbarList - public const string TaskbarList = "56FDF342-FD6D-11d0-958A-006097C9A090"; - /// IID_ITaskbarList2 - public const string TaskbarList2 = "602D4995-B13A-429b-A66E-1935E44F4317"; - /// IID_IUnknown - public const string Unknown = "00000000-0000-0000-C000-000000000046"; - - #region Win7 IIDs - - /// IID_IApplicationDestinations - public const string ApplicationDestinations = "12337d35-94c6-48a0-bce7-6a9c69d4d600"; - /// IID_IApplicationDocumentLists - public const string ApplicationDocumentLists = "3c594f9f-9f30-47a1-979a-c9e83d3d0a06"; - /// IID_ICustomDestinationList - public const string CustomDestinationList = "6332debf-87b5-4670-90c0-5e57b408a49e"; - /// IID_IObjectWithAppUserModelID - public const string ObjectWithAppUserModelId = "36db0196-9665-46d1-9ba7-d3709eecf9ed"; - /// IID_IObjectWithProgID - public const string ObjectWithProgId = "71e806fb-8dee-46fc-bf8c-7748a8a1ae13"; - /// IID_ITaskbarList3 - public const string TaskbarList3 = "ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf"; - /// IID_ITaskbarList4 - public const string TaskbarList4 = "c43dc798-95d1-4bea-9030-bb99e2983a1a"; - - #endregion + return ( T )System.Activator.CreateInstance( System.Type.GetTypeFromCLSID( new System.Guid( clsid ) ) ); } - internal static partial class CLSID - { - public static T CoCreateInstance(string clsid) - { - return (T)System.Activator.CreateInstance(System.Type.GetTypeFromCLSID(new System.Guid(clsid))); - } - - /// CLSID_TaskbarList - /// IID_ITaskbarList - public const string TaskbarList = "56FDF344-FD6D-11d0-958A-006097C9A090"; - /// CLSID_EnumerableObjectCollection - /// IID_IEnumObjects. - public const string EnumerableObjectCollection = "2d3468c1-36a7-43b6-ac24-d3f02fd9607a"; - /// CLSID_ShellLink - /// IID_IShellLink - public const string ShellLink = "00021401-0000-0000-C000-000000000046"; - - #region Win7 CLSIDs - - /// CLSID_DestinationList - /// IID_ICustomDestinationList - public const string DestinationList = "77f10cf0-3db5-4966-b520-b7c54fd35ed6"; - /// CLSID_ApplicationDestinations - /// IID_IApplicationDestinations - public const string ApplicationDestinations = "86c14003-4d6b-4ef3-a7b4-0506663b2e68"; - /// CLSID_ApplicationDocumentLists - /// IID_IApplicationDocumentLists - public const string ApplicationDocumentLists = "86bec222-30f2-47e0-9f25-60d11cd75c28"; - - #endregion - } + /// CLSID_TaskbarList + /// IID_ITaskbarList + public const string TaskbarList = "56FDF344-FD6D-11d0-958A-006097C9A090"; + /// CLSID_EnumerableObjectCollection + /// IID_IEnumObjects. + public const string EnumerableObjectCollection = "2d3468c1-36a7-43b6-ac24-d3f02fd9607a"; + /// CLSID_ShellLink + /// IID_IShellLink + public const string ShellLink = "00021401-0000-0000-C000-000000000046"; + + #region Win7 CLSIDs + + /// CLSID_DestinationList + /// IID_ICustomDestinationList + public const string DestinationList = "77f10cf0-3db5-4966-b520-b7c54fd35ed6"; + /// CLSID_ApplicationDestinations + /// IID_IApplicationDestinations + public const string ApplicationDestinations = "86c14003-4d6b-4ef3-a7b4-0506663b2e68"; + /// CLSID_ApplicationDocumentLists + /// IID_IApplicationDocumentLists + public const string ApplicationDocumentLists = "86bec222-30f2-47e0-9f25-60d11cd75c28"; + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Debug.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Debug.cs index fb4dd759..29f1dd8b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Debug.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Debug.cs @@ -29,361 +29,361 @@ // might be included in multiple assemblies. namespace Standard { - using System; - using System.Diagnostics; - using System.Threading; - - /// A static class for verifying assumptions. - internal static class Assert + using System; + using System.Diagnostics; + using System.Threading; + + /// A static class for verifying assumptions. + internal static class Assert + { + private static void _Break() { - private static void _Break() - { #if DEV_DEBUG - Debugger.Break(); + Debugger.Break(); #else Debug.Assert(false); #endif - } + } - /// A function signature for Assert.Evaluate. - public delegate void EvaluateFunction(); + /// A function signature for Assert.Evaluate. + public delegate void EvaluateFunction(); - /// A function signature for Assert.Implies. - /// Returns the truth of a predicate. - public delegate bool ImplicationFunction(); + /// A function signature for Assert.Implies. + /// Returns the truth of a predicate. + public delegate bool ImplicationFunction(); - /// - /// Executes the specified argument. - /// - /// The function to execute. - [Conditional("DEBUG")] - public static void Evaluate(EvaluateFunction argument) - { - IsNotNull(argument); - argument(); - } + /// + /// Executes the specified argument. + /// + /// The function to execute. + [Conditional( "DEBUG" )] + public static void Evaluate( EvaluateFunction argument ) + { + IsNotNull( argument ); + argument(); + } - /// Obsolete: Use Standard.Assert.AreEqual instead of Assert.Equals - /// The generic type to compare for equality. - /// The first generic type data to compare. This is is the expected value. - /// The second generic type data to compare. This is the actual value. - [ - Obsolete("Use Assert.AreEqual instead of Assert.Equals", false), - Conditional("DEBUG") - ] - public static void Equals(T expected, T actual) - { - AreEqual(expected, actual); - } + /// Obsolete: Use Standard.Assert.AreEqual instead of Assert.Equals + /// The generic type to compare for equality. + /// The first generic type data to compare. This is is the expected value. + /// The second generic type data to compare. This is the actual value. + [ + Obsolete( "Use Assert.AreEqual instead of Assert.Equals", false ), + Conditional( "DEBUG" ) + ] + public static void Equals( T expected, T actual ) + { + AreEqual( expected, actual ); + } - /// - /// Verifies that two generic type data are equal. The assertion fails if they are not. - /// - /// The generic type to compare for equality. - /// The first generic type data to compare. This is is the expected value. - /// The second generic type data to compare. This is the actual value. - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void AreEqual(T expected, T actual) + /// + /// Verifies that two generic type data are equal. The assertion fails if they are not. + /// + /// The generic type to compare for equality. + /// The first generic type data to compare. This is is the expected value. + /// The second generic type data to compare. This is the actual value. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void AreEqual( T expected, T actual ) + { + if( null == expected ) + { + // Two nulls are considered equal, regardless of type semantics. + if( null != actual && !actual.Equals( expected ) ) { - if (null == expected) - { - // Two nulls are considered equal, regardless of type semantics. - if (null != actual && !actual.Equals(expected)) - { - _Break(); - } - } - else if (!expected.Equals(actual)) - { - _Break(); - } + _Break(); } + } + else if( !expected.Equals( actual ) ) + { + _Break(); + } + } - /// - /// Verifies that two generic type data are not equal. The assertion fails if they are. - /// - /// The generic type to compare for inequality. - /// The first generic type data to compare. This is is the value that's not expected. - /// The second generic type data to compare. This is the actual value. - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void AreNotEqual(T notExpected, T actual) + /// + /// Verifies that two generic type data are not equal. The assertion fails if they are. + /// + /// The generic type to compare for inequality. + /// The first generic type data to compare. This is is the value that's not expected. + /// The second generic type data to compare. This is the actual value. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void AreNotEqual( T notExpected, T actual ) + { + if( null == notExpected ) + { + // Two nulls are considered equal, regardless of type semantics. + if( null == actual || actual.Equals( notExpected ) ) { - if (null == notExpected) - { - // Two nulls are considered equal, regardless of type semantics. - if (null == actual || actual.Equals(notExpected)) - { - _Break(); - } - } - else if (notExpected.Equals(actual)) - { - _Break(); - } + _Break(); } + } + else if( notExpected.Equals( actual ) ) + { + _Break(); + } + } - /// - /// Verifies that if the specified condition is true, then so is the result. - /// The assertion fails if the condition is true but the result is false. - /// - /// if set to true [condition]. - /// - /// A second Boolean statement. If the first was true then so must this be. - /// If the first statement was false then the value of this is ignored. - /// - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void Implies(bool condition, bool result) - { - if (condition && !result) - { - _Break(); - } - } + /// + /// Verifies that if the specified condition is true, then so is the result. + /// The assertion fails if the condition is true but the result is false. + /// + /// if set to true [condition]. + /// + /// A second Boolean statement. If the first was true then so must this be. + /// If the first statement was false then the value of this is ignored. + /// + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void Implies( bool condition, bool result ) + { + if( condition && !result ) + { + _Break(); + } + } - /// - /// Lazy evaluation overload. Verifies that if a condition is true, then so is a secondary value. - /// - /// The conditional value. - /// A function to be evaluated for truth if the condition argument is true. - /// - /// This overload only evaluates the result if the first condition is true. - /// - [Conditional("DEBUG")] - public static void Implies(bool condition, ImplicationFunction result) - { - if (condition && !result()) - { - _Break(); - } - } + /// + /// Lazy evaluation overload. Verifies that if a condition is true, then so is a secondary value. + /// + /// The conditional value. + /// A function to be evaluated for truth if the condition argument is true. + /// + /// This overload only evaluates the result if the first condition is true. + /// + [Conditional( "DEBUG" )] + public static void Implies( bool condition, ImplicationFunction result ) + { + if( condition && !result() ) + { + _Break(); + } + } - /// - /// Verifies that a string has content. I.e. it is not null and it is not empty. - /// - /// The string to verify. - [Conditional("DEBUG")] - public static void IsNeitherNullNorEmpty(string value) - { - IsFalse(string.IsNullOrEmpty(value)); - } + /// + /// Verifies that a string has content. I.e. it is not null and it is not empty. + /// + /// The string to verify. + [Conditional( "DEBUG" )] + public static void IsNeitherNullNorEmpty( string value ) + { + IsFalse( string.IsNullOrEmpty( value ) ); + } - /// - /// Verifies that a string has content. I.e. it is not null and it is not purely whitespace. - /// - /// The string to verify. - [Conditional("DEBUG")] - public static void IsNeitherNullNorWhitespace(string value) - { - if (string.IsNullOrEmpty(value)) - { - _Break(); - } - - if (value.Trim().Length == 0) - { - _Break(); - } - } + /// + /// Verifies that a string has content. I.e. it is not null and it is not purely whitespace. + /// + /// The string to verify. + [Conditional( "DEBUG" )] + public static void IsNeitherNullNorWhitespace( string value ) + { + if( string.IsNullOrEmpty( value ) ) + { + _Break(); + } + + if( value.Trim().Length == 0 ) + { + _Break(); + } + } - /// - /// Verifies the specified value is not null. The assertion fails if it is. - /// - /// The generic reference type. - /// The value to check for nullness. - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void IsNotNull(T value) where T : class - { - if (null == value) - { - _Break(); - } - } + /// + /// Verifies the specified value is not null. The assertion fails if it is. + /// + /// The generic reference type. + /// The value to check for nullness. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void IsNotNull( T value ) where T : class + { + if( null == value ) + { + _Break(); + } + } - [Conditional("DEBUG")] - public static void IsDefault(T value) where T : struct - { - if (!value.Equals(default(T))) - { - Assert.Fail(); - } - } + [Conditional( "DEBUG" )] + public static void IsDefault( T value ) where T : struct + { + if( !value.Equals( default( T ) ) ) + { + Assert.Fail(); + } + } - [Conditional("DEBUG")] - public static void IsNotDefault(T value) where T : struct - { - if (value.Equals(default(T))) - { - Assert.Fail(); - } - } + [Conditional( "DEBUG" )] + public static void IsNotDefault( T value ) where T : struct + { + if( value.Equals( default( T ) ) ) + { + Assert.Fail(); + } + } - /// - /// Verifies that the specified condition is false. The assertion fails if it is true. - /// - /// The expression that should be false. - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void IsFalse(bool condition) - { - if (condition) - { - _Break(); - } - } + /// + /// Verifies that the specified condition is false. The assertion fails if it is true. + /// + /// The expression that should be false. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void IsFalse( bool condition ) + { + if( condition ) + { + _Break(); + } + } - /// - /// Verifies that the specified condition is false. The assertion fails if it is true. - /// - /// The expression that should be false. - /// The message to display if the condition is true. - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void IsFalse(bool condition, string message) - { - if (condition) - { - _Break(); - } - } + /// + /// Verifies that the specified condition is false. The assertion fails if it is true. + /// + /// The expression that should be false. + /// The message to display if the condition is true. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void IsFalse( bool condition, string message ) + { + if( condition ) + { + _Break(); + } + } - /// - /// Verifies that the specified condition is true. The assertion fails if it is not. - /// - /// A condition that is expected to be true. - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void IsTrue(bool condition) - { - if (!condition) - { - _Break(); - } - } + /// + /// Verifies that the specified condition is true. The assertion fails if it is not. + /// + /// A condition that is expected to be true. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void IsTrue( bool condition ) + { + if( !condition ) + { + _Break(); + } + } - /// - /// Verifies that the specified condition is true. The assertion fails if it is not. - /// - /// A condition that is expected to be true. - /// The message to write in case the condition is false. - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void IsTrue(bool condition, string message) - { - if (!condition) - { - _Break(); - } - } + /// + /// Verifies that the specified condition is true. The assertion fails if it is not. + /// + /// A condition that is expected to be true. + /// The message to write in case the condition is false. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void IsTrue( bool condition, string message ) + { + if( !condition ) + { + _Break(); + } + } - /// - /// This line should never be executed. The assertion always fails. - /// - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void Fail() - { - _Break(); - } + /// + /// This line should never be executed. The assertion always fails. + /// + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void Fail() + { + _Break(); + } - /// - /// This line should never be executed. The assertion always fails. - /// - /// The message to display if this function is executed. - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void Fail(string message) - { - _Break(); - } + /// + /// This line should never be executed. The assertion always fails. + /// + /// The message to display if this function is executed. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void Fail( string message ) + { + _Break(); + } - /// - /// Verifies that the specified object is null. The assertion fails if it is not. - /// - /// The item to verify is null. - [Conditional("DEBUG")] - public static void IsNull(T item) where T : class - { - if (null != item) - { - _Break(); - } - } + /// + /// Verifies that the specified object is null. The assertion fails if it is not. + /// + /// The item to verify is null. + [Conditional( "DEBUG" )] + public static void IsNull( T item ) where T : class + { + if( null != item ) + { + _Break(); + } + } - /// - /// Verifies that the specified value is within the expected range. The assertion fails if it isn't. - /// - /// The lower bound inclusive value. - /// The value to verify. - /// The upper bound inclusive value. - [Conditional("DEBUG")] - public static void BoundedDoubleInc(double lowerBoundInclusive, double value, double upperBoundInclusive) - { - if (value < lowerBoundInclusive || value > upperBoundInclusive) - { - _Break(); - } - } + /// + /// Verifies that the specified value is within the expected range. The assertion fails if it isn't. + /// + /// The lower bound inclusive value. + /// The value to verify. + /// The upper bound inclusive value. + [Conditional( "DEBUG" )] + public static void BoundedDoubleInc( double lowerBoundInclusive, double value, double upperBoundInclusive ) + { + if( value < lowerBoundInclusive || value > upperBoundInclusive ) + { + _Break(); + } + } - /// - /// Verifies that the specified value is within the expected range. The assertion fails if it isn't. - /// - /// The lower bound inclusive value. - /// The value to verify. - /// The upper bound exclusive value. - [Conditional("DEBUG")] - public static void BoundedInteger(int lowerBoundInclusive, int value, int upperBoundExclusive) - { - if (value < lowerBoundInclusive || value >= upperBoundExclusive) - { - _Break(); - } - } + /// + /// Verifies that the specified value is within the expected range. The assertion fails if it isn't. + /// + /// The lower bound inclusive value. + /// The value to verify. + /// The upper bound exclusive value. + [Conditional( "DEBUG" )] + public static void BoundedInteger( int lowerBoundInclusive, int value, int upperBoundExclusive ) + { + if( value < lowerBoundInclusive || value >= upperBoundExclusive ) + { + _Break(); + } + } - /// - /// Verify the current thread's apartment state is what's expected. The assertion fails if it isn't - /// - /// - /// The expected apartment state for the current thread. - /// - /// This breaks into the debugger in the case of a failed assertion. - [Conditional("DEBUG")] - public static void IsApartmentState(ApartmentState expectedState) - { - if (Thread.CurrentThread.GetApartmentState() != expectedState) - { - _Break(); - } - } + /// + /// Verify the current thread's apartment state is what's expected. The assertion fails if it isn't + /// + /// + /// The expected apartment state for the current thread. + /// + /// This breaks into the debugger in the case of a failed assertion. + [Conditional( "DEBUG" )] + public static void IsApartmentState( ApartmentState expectedState ) + { + if( Thread.CurrentThread.GetApartmentState() != expectedState ) + { + _Break(); + } + } - [Conditional("DEBUG")] - public static void NullableIsNotNull(T? value) where T : struct - { - if (null == value) - { - _Break(); - } - } + [Conditional( "DEBUG" )] + public static void NullableIsNotNull( T? value ) where T : struct + { + if( null == value ) + { + _Break(); + } + } - [Conditional("DEBUG")] - public static void NullableIsNull(T? value) where T : struct - { - if (null != value) - { - _Break(); - } - } + [Conditional( "DEBUG" )] + public static void NullableIsNull( T? value ) where T : struct + { + if( null != value ) + { + _Break(); + } + } - [Conditional("DEBUG")] - public static void IsNotOnMainThread() - { - if (System.Windows.Application.Current.Dispatcher.CheckAccess()) - { - _Break(); - } - } + [Conditional( "DEBUG" )] + public static void IsNotOnMainThread() + { + if( System.Windows.Application.Current.Dispatcher.CheckAccess() ) + { + _Break(); + } } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DoubleUtil.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DoubleUtil.cs index 29e25ee5..d4a955bc 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DoubleUtil.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DoubleUtil.cs @@ -17,132 +17,132 @@ namespace Standard { - using System; - using System.Diagnostics.CodeAnalysis; + using System; + using System.Diagnostics.CodeAnalysis; + + /// + /// DoubleUtil uses fixed eps to provide fuzzy comparison functionality for doubles. + /// Note that FP noise is a big problem and using any of these compare + /// methods is not a complete solution, but rather the way to reduce + /// the probability of repeating unnecessary work. + /// + internal static class DoubleUtilities + { + /// + /// Epsilon - more or less random, more or less small number. + /// + private const double Epsilon = 0.00000153; + + /// + /// AreClose returns whether or not two doubles are "close". That is, whether or + /// not they are within epsilon of each other. + /// There are plenty of ways for this to return false even for numbers which + /// are theoretically identical, so no code calling this should fail to work if this + /// returns false. + /// + /// The first double to compare. + /// The second double to compare. + /// The result of the AreClose comparision. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool AreClose( double value1, double value2 ) + { + if( value1 == value2 ) + { + return true; + } + + double delta = value1 - value2; + return ( delta < Epsilon ) && ( delta > -Epsilon ); + } + + /// + /// LessThan returns whether or not the first double is less than the second double. + /// That is, whether or not the first is strictly less than *and* not within epsilon of + /// the other number. + /// There are plenty of ways for this to return false even for numbers which + /// are theoretically identical, so no code calling this should fail to work if this + /// returns false. + /// + /// The first double to compare. + /// The second double to compare. + /// The result of the LessThan comparision. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool LessThan( double value1, double value2 ) + { + return ( value1 < value2 ) && !AreClose( value1, value2 ); + } + + /// + /// GreaterThan returns whether or not the first double is greater than the second double. + /// That is, whether or not the first is strictly greater than *and* not within epsilon of + /// the other number. + /// There are plenty of ways for this to return false even for numbers which + /// are theoretically identical, so no code calling this should fail to work if this + /// returns false. + /// + /// The first double to compare. + /// The second double to compare. + /// The result of the GreaterThan comparision. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool GreaterThan( double value1, double value2 ) + { + return ( value1 > value2 ) && !AreClose( value1, value2 ); + } + + /// + /// LessThanOrClose returns whether or not the first double is less than or close to + /// the second double. That is, whether or not the first is strictly less than or within + /// epsilon of the other number. + /// There are plenty of ways for this to return false even for numbers which + /// are theoretically identical, so no code calling this should fail to work if this + /// returns false. + /// + /// The first double to compare. + /// The second double to compare. + /// The result of the LessThanOrClose comparision. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool LessThanOrClose( double value1, double value2 ) + { + return ( value1 < value2 ) || AreClose( value1, value2 ); + } + + /// + /// GreaterThanOrClose returns whether or not the first double is greater than or close to + /// the second double. That is, whether or not the first is strictly greater than or within + /// epsilon of the other number. + /// There are plenty of ways for this to return false even for numbers which + /// are theoretically identical, so no code calling this should fail to work if this + /// returns false. + /// + /// The first double to compare. + /// The second double to compare. + /// The result of the GreaterThanOrClose comparision. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool GreaterThanOrClose( double value1, double value2 ) + { + return ( value1 > value2 ) || AreClose( value1, value2 ); + } + + /// + /// Test to see if a double is a finite number (is not NaN or Infinity). + /// + /// The value to test. + /// Whether or not the value is a finite number. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsFinite( double value ) + { + return !double.IsNaN( value ) && !double.IsInfinity( value ); + } /// - /// DoubleUtil uses fixed eps to provide fuzzy comparison functionality for doubles. - /// Note that FP noise is a big problem and using any of these compare - /// methods is not a complete solution, but rather the way to reduce - /// the probability of repeating unnecessary work. + /// Test to see if a double a valid size value (is finite and > 0). /// - internal static class DoubleUtilities + /// The value to test. + /// Whether or not the value is a valid size value. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsValidSize( double value ) { - /// - /// Epsilon - more or less random, more or less small number. - /// - private const double Epsilon = 0.00000153; - - /// - /// AreClose returns whether or not two doubles are "close". That is, whether or - /// not they are within epsilon of each other. - /// There are plenty of ways for this to return false even for numbers which - /// are theoretically identical, so no code calling this should fail to work if this - /// returns false. - /// - /// The first double to compare. - /// The second double to compare. - /// The result of the AreClose comparision. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool AreClose(double value1, double value2) - { - if (value1 == value2) - { - return true; - } - - double delta = value1 - value2; - return (delta < Epsilon) && (delta > -Epsilon); - } - - /// - /// LessThan returns whether or not the first double is less than the second double. - /// That is, whether or not the first is strictly less than *and* not within epsilon of - /// the other number. - /// There are plenty of ways for this to return false even for numbers which - /// are theoretically identical, so no code calling this should fail to work if this - /// returns false. - /// - /// The first double to compare. - /// The second double to compare. - /// The result of the LessThan comparision. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool LessThan(double value1, double value2) - { - return (value1 < value2) && !AreClose(value1, value2); - } - - /// - /// GreaterThan returns whether or not the first double is greater than the second double. - /// That is, whether or not the first is strictly greater than *and* not within epsilon of - /// the other number. - /// There are plenty of ways for this to return false even for numbers which - /// are theoretically identical, so no code calling this should fail to work if this - /// returns false. - /// - /// The first double to compare. - /// The second double to compare. - /// The result of the GreaterThan comparision. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool GreaterThan(double value1, double value2) - { - return (value1 > value2) && !AreClose(value1, value2); - } - - /// - /// LessThanOrClose returns whether or not the first double is less than or close to - /// the second double. That is, whether or not the first is strictly less than or within - /// epsilon of the other number. - /// There are plenty of ways for this to return false even for numbers which - /// are theoretically identical, so no code calling this should fail to work if this - /// returns false. - /// - /// The first double to compare. - /// The second double to compare. - /// The result of the LessThanOrClose comparision. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool LessThanOrClose(double value1, double value2) - { - return (value1 < value2) || AreClose(value1, value2); - } - - /// - /// GreaterThanOrClose returns whether or not the first double is greater than or close to - /// the second double. That is, whether or not the first is strictly greater than or within - /// epsilon of the other number. - /// There are plenty of ways for this to return false even for numbers which - /// are theoretically identical, so no code calling this should fail to work if this - /// returns false. - /// - /// The first double to compare. - /// The second double to compare. - /// The result of the GreaterThanOrClose comparision. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool GreaterThanOrClose(double value1, double value2) - { - return (value1 > value2) || AreClose(value1, value2); - } - - /// - /// Test to see if a double is a finite number (is not NaN or Infinity). - /// - /// The value to test. - /// Whether or not the value is a finite number. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool IsFinite(double value) - { - return !double.IsNaN(value) && !double.IsInfinity(value); - } - - /// - /// Test to see if a double a valid size value (is finite and > 0). - /// - /// The value to test. - /// Whether or not the value is a valid size value. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool IsValidSize(double value) - { - return IsFinite(value) && GreaterThanOrClose(value, 0); - } + return IsFinite( value ) && GreaterThanOrClose( value, 0 ); } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DpiHelper.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DpiHelper.cs index 98398098..3f056311 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DpiHelper.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DpiHelper.cs @@ -20,83 +20,82 @@ namespace Standard { - using System; - using System.Diagnostics.CodeAnalysis; - using System.Windows; - using System.Windows.Media; + using System.Diagnostics.CodeAnalysis; + using System.Windows; + using System.Windows.Media; - internal static class DpiHelper + internal static class DpiHelper + { + private static Matrix _transformToDevice; + private static Matrix _transformToDip; + + [SuppressMessage( "Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline" )] + static DpiHelper() + { + using( SafeDC desktop = SafeDC.GetDesktop() ) + { + // Can get these in the static constructor. They shouldn't vary window to window, + // and changing the system DPI requires a restart. + int pixelsPerInchX = NativeMethods.GetDeviceCaps( desktop, DeviceCap.LOGPIXELSX ); + int pixelsPerInchY = NativeMethods.GetDeviceCaps( desktop, DeviceCap.LOGPIXELSY ); + + _transformToDip = Matrix.Identity; + _transformToDip.Scale( 96d / ( double )pixelsPerInchX, 96d / ( double )pixelsPerInchY ); + _transformToDevice = Matrix.Identity; + _transformToDevice.Scale( ( double )pixelsPerInchX / 96d, ( double )pixelsPerInchY / 96d ); + } + } + + /// + /// Convert a point in device independent pixels (1/96") to a point in the system coordinates. + /// + /// A point in the logical coordinate system. + /// Returns the parameter converted to the system's coordinates. + public static Point LogicalPixelsToDevice( Point logicalPoint ) + { + return _transformToDevice.Transform( logicalPoint ); + } + + /// + /// Convert a point in system coordinates to a point in device independent pixels (1/96"). + /// + /// A point in the physical coordinate system. + /// Returns the parameter converted to the device independent coordinate system. + public static Point DevicePixelsToLogical( Point devicePoint ) + { + return _transformToDip.Transform( devicePoint ); + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static Rect LogicalRectToDevice( Rect logicalRectangle ) { - private static Matrix _transformToDevice; - private static Matrix _transformToDip; - - [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")] - static DpiHelper() - { - using (SafeDC desktop = SafeDC.GetDesktop()) - { - // Can get these in the static constructor. They shouldn't vary window to window, - // and changing the system DPI requires a restart. - int pixelsPerInchX = NativeMethods.GetDeviceCaps(desktop, DeviceCap.LOGPIXELSX); - int pixelsPerInchY = NativeMethods.GetDeviceCaps(desktop, DeviceCap.LOGPIXELSY); - - _transformToDip = Matrix.Identity; - _transformToDip.Scale(96d / (double)pixelsPerInchX, 96d / (double)pixelsPerInchY); - _transformToDevice = Matrix.Identity; - _transformToDevice.Scale((double)pixelsPerInchX / 96d, (double)pixelsPerInchY / 96d); - } - } - - /// - /// Convert a point in device independent pixels (1/96") to a point in the system coordinates. - /// - /// A point in the logical coordinate system. - /// Returns the parameter converted to the system's coordinates. - public static Point LogicalPixelsToDevice(Point logicalPoint) - { - return _transformToDevice.Transform(logicalPoint); - } - - /// - /// Convert a point in system coordinates to a point in device independent pixels (1/96"). - /// - /// A point in the physical coordinate system. - /// Returns the parameter converted to the device independent coordinate system. - public static Point DevicePixelsToLogical(Point devicePoint) - { - return _transformToDip.Transform(devicePoint); - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static Rect LogicalRectToDevice(Rect logicalRectangle) - { - Point topLeft = LogicalPixelsToDevice(new Point(logicalRectangle.Left, logicalRectangle.Top)); - Point bottomRight = LogicalPixelsToDevice(new Point(logicalRectangle.Right, logicalRectangle.Bottom)); - - return new Rect(topLeft, bottomRight); - } - - public static Rect DeviceRectToLogical(Rect deviceRectangle) - { - Point topLeft = DevicePixelsToLogical(new Point(deviceRectangle.Left, deviceRectangle.Top)); - Point bottomRight = DevicePixelsToLogical(new Point(deviceRectangle.Right, deviceRectangle.Bottom)); - - return new Rect(topLeft, bottomRight); - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static Size LogicalSizeToDevice(Size logicalSize) - { - Point pt = LogicalPixelsToDevice(new Point(logicalSize.Width, logicalSize.Height)); - - return new Size { Width = pt.X, Height = pt.Y }; - } - - public static Size DeviceSizeToLogical(Size deviceSize) - { - Point pt = DevicePixelsToLogical(new Point(deviceSize.Width, deviceSize.Height)); - - return new Size(pt.X, pt.Y); - } + Point topLeft = LogicalPixelsToDevice( new Point( logicalRectangle.Left, logicalRectangle.Top ) ); + Point bottomRight = LogicalPixelsToDevice( new Point( logicalRectangle.Right, logicalRectangle.Bottom ) ); + + return new Rect( topLeft, bottomRight ); + } + + public static Rect DeviceRectToLogical( Rect deviceRectangle ) + { + Point topLeft = DevicePixelsToLogical( new Point( deviceRectangle.Left, deviceRectangle.Top ) ); + Point bottomRight = DevicePixelsToLogical( new Point( deviceRectangle.Right, deviceRectangle.Bottom ) ); + + return new Rect( topLeft, bottomRight ); + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static Size LogicalSizeToDevice( Size logicalSize ) + { + Point pt = LogicalPixelsToDevice( new Point( logicalSize.Width, logicalSize.Height ) ); + + return new Size { Width = pt.X, Height = pt.Y }; + } + + public static Size DeviceSizeToLogical( Size deviceSize ) + { + Point pt = DevicePixelsToLogical( new Point( deviceSize.Width, deviceSize.Height ) ); + + return new Size( pt.X, pt.Y ); } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ErrorCodes.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ErrorCodes.cs index 24e9fb5a..c58f5321 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ErrorCodes.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ErrorCodes.cs @@ -20,505 +20,511 @@ namespace Standard { - using System; - using System.ComponentModel; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.Reflection; - using System.Runtime.InteropServices; + using System; + using System.ComponentModel; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.Reflection; + using System.Runtime.InteropServices; + + /// + /// Wrapper for common Win32 status codes. + /// + [StructLayout( LayoutKind.Explicit )] + internal struct Win32Error + { + [FieldOffset( 0 )] + private readonly int _value; + + // NOTE: These public static field declarations are automatically + // picked up by (HRESULT's) ToString through reflection. + + /// The operation completed successfully. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_SUCCESS = new Win32Error( 0 ); + /// Incorrect function. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_INVALID_FUNCTION = new Win32Error( 1 ); + /// The system cannot find the file specified. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_FILE_NOT_FOUND = new Win32Error( 2 ); + /// The system cannot find the path specified. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_PATH_NOT_FOUND = new Win32Error( 3 ); + /// The system cannot open the file. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_TOO_MANY_OPEN_FILES = new Win32Error( 4 ); + /// Access is denied. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_ACCESS_DENIED = new Win32Error( 5 ); + /// The handle is invalid. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_INVALID_HANDLE = new Win32Error( 6 ); + /// Not enough storage is available to complete this operation. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_OUTOFMEMORY = new Win32Error( 14 ); + /// There are no more files. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_NO_MORE_FILES = new Win32Error( 18 ); + /// The process cannot access the file because it is being used by another process. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_SHARING_VIOLATION = new Win32Error( 32 ); + /// The parameter is incorrect. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_INVALID_PARAMETER = new Win32Error( 87 ); + /// The data area passed to a system call is too small. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_INSUFFICIENT_BUFFER = new Win32Error( 122 ); + /// Cannot nest calls to LoadModule. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_NESTING_NOT_ALLOWED = new Win32Error( 215 ); + /// Illegal operation attempted on a registry key that has been marked for deletion. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_KEY_DELETED = new Win32Error( 1018 ); + /// Element not found. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_NOT_FOUND = new Win32Error( 1168 ); + /// There was no match for the specified key in the index. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_NO_MATCH = new Win32Error( 1169 ); + /// An invalid device was specified. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_BAD_DEVICE = new Win32Error( 1200 ); + /// The operation was canceled by the user. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_CANCELLED = new Win32Error( 1223 ); + /// The window class was already registered. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_CLASS_ALREADY_EXISTS = new Win32Error( 1410 ); + /// The specified datatype is invalid. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly Win32Error ERROR_INVALID_DATATYPE = new Win32Error( 1804 ); /// - /// Wrapper for common Win32 status codes. + /// Create a new Win32 error. /// - [StructLayout(LayoutKind.Explicit)] - internal struct Win32Error + /// The integer value of the error. + public Win32Error( int i ) { - [FieldOffset(0)] - private readonly int _value; - - // NOTE: These public static field declarations are automatically - // picked up by (HRESULT's) ToString through reflection. - - /// The operation completed successfully. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_SUCCESS = new Win32Error(0); - /// Incorrect function. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_INVALID_FUNCTION = new Win32Error(1); - /// The system cannot find the file specified. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_FILE_NOT_FOUND = new Win32Error(2); - /// The system cannot find the path specified. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_PATH_NOT_FOUND = new Win32Error(3); - /// The system cannot open the file. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_TOO_MANY_OPEN_FILES = new Win32Error(4); - /// Access is denied. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_ACCESS_DENIED = new Win32Error(5); - /// The handle is invalid. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_INVALID_HANDLE = new Win32Error(6); - /// Not enough storage is available to complete this operation. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_OUTOFMEMORY = new Win32Error(14); - /// There are no more files. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_NO_MORE_FILES = new Win32Error(18); - /// The process cannot access the file because it is being used by another process. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_SHARING_VIOLATION = new Win32Error(32); - /// The parameter is incorrect. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_INVALID_PARAMETER = new Win32Error(87); - /// The data area passed to a system call is too small. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_INSUFFICIENT_BUFFER = new Win32Error(122); - /// Cannot nest calls to LoadModule. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_NESTING_NOT_ALLOWED = new Win32Error(215); - /// Illegal operation attempted on a registry key that has been marked for deletion. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_KEY_DELETED = new Win32Error(1018); - /// Element not found. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_NOT_FOUND = new Win32Error(1168); - /// There was no match for the specified key in the index. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_NO_MATCH = new Win32Error(1169); - /// An invalid device was specified. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_BAD_DEVICE = new Win32Error(1200); - /// The operation was canceled by the user. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_CANCELLED = new Win32Error(1223); - /// The window class was already registered. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_CLASS_ALREADY_EXISTS = new Win32Error(1410); - /// The specified datatype is invalid. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly Win32Error ERROR_INVALID_DATATYPE = new Win32Error(1804); - - /// - /// Create a new Win32 error. - /// - /// The integer value of the error. - public Win32Error(int i) - { - _value = i; - } + _value = i; + } - /// Performs HRESULT_FROM_WIN32 conversion. - /// The Win32 error being converted to an HRESULT. - /// The equivilent HRESULT value. - public static explicit operator HRESULT(Win32Error error) - { - // #define __HRESULT_FROM_WIN32(x) - // ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) - if (error._value <= 0) - { - return new HRESULT((uint)error._value); - } - return HRESULT.Make(true, Facility.Win32, error._value & 0x0000FFFF); - } + /// Performs HRESULT_FROM_WIN32 conversion. + /// The Win32 error being converted to an HRESULT. + /// The equivilent HRESULT value. + public static explicit operator HRESULT( Win32Error error ) + { + // #define __HRESULT_FROM_WIN32(x) + // ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) + if( error._value <= 0 ) + { + return new HRESULT( ( uint )error._value ); + } + return HRESULT.Make( true, Facility.Win32, error._value & 0x0000FFFF ); + } - // Method version of the cast operation - /// Performs HRESULT_FROM_WIN32 conversion. - /// The Win32 error being converted to an HRESULT. - /// The equivilent HRESULT value. - public HRESULT ToHRESULT() - { - return (HRESULT)this; - } + // Method version of the cast operation + /// Performs HRESULT_FROM_WIN32 conversion. + /// The Win32 error being converted to an HRESULT. + /// The equivilent HRESULT value. + public HRESULT ToHRESULT() + { + return ( HRESULT )this; + } - /// Performs the equivalent of Win32's GetLastError() - /// A Win32Error instance with the result of the native GetLastError - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public static Win32Error GetLastError() - { - return new Win32Error(Marshal.GetLastWin32Error()); - } + /// Performs the equivalent of Win32's GetLastError() + /// A Win32Error instance with the result of the native GetLastError + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public static Win32Error GetLastError() + { + return new Win32Error( Marshal.GetLastWin32Error() ); + } - public override bool Equals(object obj) - { - try - { - return ((Win32Error)obj)._value == _value; - } - catch (InvalidCastException) - { - return false; - } - } + public override bool Equals( object obj ) + { + try + { + return ( ( Win32Error )obj )._value == _value; + } + catch( InvalidCastException ) + { + return false; + } + } - public override int GetHashCode() - { - return _value.GetHashCode(); - } + public override int GetHashCode() + { + return _value.GetHashCode(); + } - /// - /// Compare two Win32 error codes for equality. - /// - /// The first error code to compare. - /// The second error code to compare. - /// Whether the two error codes are the same. - public static bool operator ==(Win32Error errLeft, Win32Error errRight) - { - return errLeft._value == errRight._value; - } + /// + /// Compare two Win32 error codes for equality. + /// + /// The first error code to compare. + /// The second error code to compare. + /// Whether the two error codes are the same. + public static bool operator ==( Win32Error errLeft, Win32Error errRight ) + { + return errLeft._value == errRight._value; + } - /// - /// Compare two Win32 error codes for inequality. - /// - /// The first error code to compare. - /// The second error code to compare. - /// Whether the two error codes are not the same. - public static bool operator !=(Win32Error errLeft, Win32Error errRight) - { - return !(errLeft == errRight); - } + /// + /// Compare two Win32 error codes for inequality. + /// + /// The first error code to compare. + /// The second error code to compare. + /// Whether the two error codes are not the same. + public static bool operator !=( Win32Error errLeft, Win32Error errRight ) + { + return !( errLeft == errRight ); } + } + + internal enum Facility + { + /// FACILITY_NULL + Null = 0, + /// FACILITY_RPC + Rpc = 1, + /// FACILITY_DISPATCH + Dispatch = 2, + /// FACILITY_STORAGE + Storage = 3, + /// FACILITY_ITF + Itf = 4, + /// FACILITY_WIN32 + Win32 = 7, + /// FACILITY_WINDOWS + Windows = 8, + /// FACILITY_CONTROL + Control = 10, + /// MSDN doced facility code for ESE errors. + Ese = 0xE5E, + /// FACILITY_WINCODEC (WIC) + WinCodec = 0x898, + } + + /// Wrapper for HRESULT status codes. + [StructLayout( LayoutKind.Explicit )] + internal struct HRESULT + { + [FieldOffset( 0 )] + private readonly uint _value; + + // NOTE: These public static field declarations are automatically + // picked up by ToString through reflection. + /// S_OK + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT S_OK = new HRESULT( 0x00000000 ); + /// S_FALSE + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT S_FALSE = new HRESULT( 0x00000001 ); + /// E_PENDING + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_PENDING = new HRESULT( 0x8000000A ); + /// E_NOTIMPL + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_NOTIMPL = new HRESULT( 0x80004001 ); + /// E_NOINTERFACE + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_NOINTERFACE = new HRESULT( 0x80004002 ); + /// E_POINTER + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_POINTER = new HRESULT( 0x80004003 ); + /// E_ABORT + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_ABORT = new HRESULT( 0x80004004 ); + /// E_FAIL + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_FAIL = new HRESULT( 0x80004005 ); + /// E_UNEXPECTED + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_UNEXPECTED = new HRESULT( 0x8000FFFF ); + /// STG_E_INVALIDFUNCTION + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT STG_E_INVALIDFUNCTION = new HRESULT( 0x80030001 ); + /// REGDB_E_CLASSNOTREG + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT REGDB_E_CLASSNOTREG = new HRESULT( 0x80040154 ); + + /// DESTS_E_NO_MATCHING_ASSOC_HANDLER. Win7 internal error code for Jump Lists. + /// There is no Assoc Handler for the given item registered by the specified application. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT DESTS_E_NO_MATCHING_ASSOC_HANDLER = new HRESULT( 0x80040F03 ); + /// DESTS_E_NORECDOCS. Win7 internal error code for Jump Lists. + /// The given item is excluded from the recent docs folder by the NoRecDocs bit on its registration. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT DESTS_E_NORECDOCS = new HRESULT( 0x80040F04 ); + /// DESTS_E_NOTALLCLEARED. Win7 internal error code for Jump Lists. + /// Not all of the items were successfully cleared + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT DESTS_E_NOTALLCLEARED = new HRESULT( 0x80040F05 ); + + /// E_ACCESSDENIED + /// Win32Error ERROR_ACCESS_DENIED. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_ACCESSDENIED = new HRESULT( 0x80070005 ); + /// E_OUTOFMEMORY + /// Win32Error ERROR_OUTOFMEMORY. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_OUTOFMEMORY = new HRESULT( 0x8007000E ); + /// E_INVALIDARG + /// Win32Error ERROR_INVALID_PARAMETER. + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT E_INVALIDARG = new HRESULT( 0x80070057 ); + /// INTSAFE_E_ARITHMETIC_OVERFLOW + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT INTSAFE_E_ARITHMETIC_OVERFLOW = new HRESULT( 0x80070216 ); + /// COR_E_OBJECTDISPOSED + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT COR_E_OBJECTDISPOSED = new HRESULT( 0x80131622 ); + /// WC_E_GREATERTHAN + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT WC_E_GREATERTHAN = new HRESULT( 0xC00CEE23 ); + /// WC_E_SYNTAX + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + public static readonly HRESULT WC_E_SYNTAX = new HRESULT( 0xC00CEE2D ); - internal enum Facility + /// + /// Create an HRESULT from an integer value. + /// + /// + public HRESULT( uint i ) { - /// FACILITY_NULL - Null = 0, - /// FACILITY_RPC - Rpc = 1, - /// FACILITY_DISPATCH - Dispatch = 2, - /// FACILITY_STORAGE - Storage = 3, - /// FACILITY_ITF - Itf = 4, - /// FACILITY_WIN32 - Win32 = 7, - /// FACILITY_WINDOWS - Windows = 8, - /// FACILITY_CONTROL - Control = 10, - /// MSDN doced facility code for ESE errors. - Ese = 0xE5E, - /// FACILITY_WINCODEC (WIC) - WinCodec = 0x898, + _value = i; } - /// Wrapper for HRESULT status codes. - [StructLayout(LayoutKind.Explicit)] - internal struct HRESULT + public static HRESULT Make( bool severe, Facility facility, int code ) { - [FieldOffset(0)] - private readonly uint _value; - - // NOTE: These public static field declarations are automatically - // picked up by ToString through reflection. - /// S_OK - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT S_OK = new HRESULT(0x00000000); - /// S_FALSE - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT S_FALSE = new HRESULT(0x00000001); - /// E_PENDING - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_PENDING = new HRESULT(0x8000000A); - /// E_NOTIMPL - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_NOTIMPL = new HRESULT(0x80004001); - /// E_NOINTERFACE - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_NOINTERFACE = new HRESULT(0x80004002); - /// E_POINTER - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_POINTER = new HRESULT(0x80004003); - /// E_ABORT - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_ABORT = new HRESULT(0x80004004); - /// E_FAIL - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_FAIL = new HRESULT(0x80004005); - /// E_UNEXPECTED - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_UNEXPECTED = new HRESULT(0x8000FFFF); - /// STG_E_INVALIDFUNCTION - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT STG_E_INVALIDFUNCTION = new HRESULT(0x80030001); - /// REGDB_E_CLASSNOTREG - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT REGDB_E_CLASSNOTREG = new HRESULT(0x80040154); - - /// DESTS_E_NO_MATCHING_ASSOC_HANDLER. Win7 internal error code for Jump Lists. - /// There is no Assoc Handler for the given item registered by the specified application. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT DESTS_E_NO_MATCHING_ASSOC_HANDLER = new HRESULT(0x80040F03); - /// DESTS_E_NORECDOCS. Win7 internal error code for Jump Lists. - /// The given item is excluded from the recent docs folder by the NoRecDocs bit on its registration. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT DESTS_E_NORECDOCS = new HRESULT(0x80040F04); - /// DESTS_E_NOTALLCLEARED. Win7 internal error code for Jump Lists. - /// Not all of the items were successfully cleared - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT DESTS_E_NOTALLCLEARED = new HRESULT(0x80040F05); - - /// E_ACCESSDENIED - /// Win32Error ERROR_ACCESS_DENIED. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_ACCESSDENIED = new HRESULT(0x80070005); - /// E_OUTOFMEMORY - /// Win32Error ERROR_OUTOFMEMORY. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_OUTOFMEMORY = new HRESULT(0x8007000E); - /// E_INVALIDARG - /// Win32Error ERROR_INVALID_PARAMETER. - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT E_INVALIDARG = new HRESULT(0x80070057); - /// INTSAFE_E_ARITHMETIC_OVERFLOW - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT INTSAFE_E_ARITHMETIC_OVERFLOW = new HRESULT(0x80070216); - /// COR_E_OBJECTDISPOSED - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT COR_E_OBJECTDISPOSED = new HRESULT(0x80131622); - /// WC_E_GREATERTHAN - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT WC_E_GREATERTHAN = new HRESULT(0xC00CEE23); - /// WC_E_SYNTAX - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - public static readonly HRESULT WC_E_SYNTAX = new HRESULT(0xC00CEE2D); - - /// - /// Create an HRESULT from an integer value. - /// - /// - public HRESULT(uint i) - { - _value = i; - } + // #define MAKE_HRESULT(sev,fac,code) \ + // ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) - public static HRESULT Make(bool severe, Facility facility, int code) - { - // #define MAKE_HRESULT(sev,fac,code) \ - // ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + // Severity has 1 bit reserved. + // bitness is enforced by the boolean parameter. - // Severity has 1 bit reserved. - // bitness is enforced by the boolean parameter. + // Facility has 11 bits reserved (different than SCODES, which have 4 bits reserved) + // MSDN documentation incorrectly uses 12 bits for the ESE facility (e5e), so go ahead and let that one slide. + // And WIC also ignores it the documented size... + Assert.Implies( ( int )facility != ( int )( ( int )facility & 0x1FF ), facility == Facility.Ese || facility == Facility.WinCodec ); + // Code has 4 bits reserved. + Assert.AreEqual( code, code & 0xFFFF ); - // Facility has 11 bits reserved (different than SCODES, which have 4 bits reserved) - // MSDN documentation incorrectly uses 12 bits for the ESE facility (e5e), so go ahead and let that one slide. - // And WIC also ignores it the documented size... - Assert.Implies((int)facility != (int)((int)facility & 0x1FF), facility == Facility.Ese || facility == Facility.WinCodec); - // Code has 4 bits reserved. - Assert.AreEqual(code, code & 0xFFFF); + return new HRESULT( ( uint )( ( severe ? ( 1 << 31 ) : 0 ) | ( ( int )facility << 16 ) | code ) ); + } - return new HRESULT((uint)((severe ? (1 << 31) : 0) | ((int)facility << 16) | code)); - } + /// + /// retrieve HRESULT_FACILITY + /// + public Facility Facility + { + get + { + return GetFacility( ( int )_value ); + } + } - /// - /// retrieve HRESULT_FACILITY - /// - public Facility Facility - { - get - { - return GetFacility((int)_value); - } - } + public static Facility GetFacility( int errorCode ) + { + // #define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) + return ( Facility )( ( errorCode >> 16 ) & 0x1fff ); + } - public static Facility GetFacility(int errorCode) + /// + /// retrieve HRESULT_CODE + /// + public int Code + { + get + { + return GetCode( ( int )_value ); + } + } + + public static int GetCode( int error ) + { + // #define HRESULT_CODE(hr) ((hr) & 0xFFFF) + return ( int )( error & 0xFFFF ); + } + + #region Object class override members + + /// + /// Get a string representation of this HRESULT. + /// + /// + public override string ToString() + { + // Use reflection to try to name this HRESULT. + // This is expensive, but if someone's ever printing HRESULT strings then + // I think it's a fair guess that they're not in a performance critical area + // (e.g. printing exception strings). + // This is less error prone than trying to keep the list in the function. + // To properly add an HRESULT's name to the ToString table, just add the HRESULT + // like all the others above. + // + // CONSIDER: This data is static. It could be cached + // after first usage for fast lookup since the keys are unique. + // + foreach( FieldInfo publicStaticField in typeof( HRESULT ).GetFields( BindingFlags.Static | BindingFlags.Public ) ) + { + if( publicStaticField.FieldType == typeof( HRESULT ) ) { - // #define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) - return (Facility)((errorCode >> 16) & 0x1fff); + var hr = ( HRESULT )publicStaticField.GetValue( null ); + if( hr == this ) + { + return publicStaticField.Name; + } } + } - /// - /// retrieve HRESULT_CODE - /// - public int Code + // Try Win32 error codes also + if( Facility == Facility.Win32 ) + { + foreach( FieldInfo publicStaticField in typeof( Win32Error ).GetFields( BindingFlags.Static | BindingFlags.Public ) ) { - get + if( publicStaticField.FieldType == typeof( Win32Error ) ) + { + var error = ( Win32Error )publicStaticField.GetValue( null ); + if( ( HRESULT )error == this ) { - return GetCode((int)_value); + return "HRESULT_FROM_WIN32(" + publicStaticField.Name + ")"; } + } } + } - public static int GetCode(int error) - { - // #define HRESULT_CODE(hr) ((hr) & 0xFFFF) - return (int)(error & 0xFFFF); - } - - #region Object class override members + // If there's no good name for this HRESULT, + // return the string as readable hex (0x########) format. + return string.Format( CultureInfo.InvariantCulture, "0x{0:X8}", _value ); + } - /// - /// Get a string representation of this HRESULT. - /// - /// - public override string ToString() - { - // Use reflection to try to name this HRESULT. - // This is expensive, but if someone's ever printing HRESULT strings then - // I think it's a fair guess that they're not in a performance critical area - // (e.g. printing exception strings). - // This is less error prone than trying to keep the list in the function. - // To properly add an HRESULT's name to the ToString table, just add the HRESULT - // like all the others above. - // - // CONSIDER: This data is static. It could be cached - // after first usage for fast lookup since the keys are unique. - // - foreach (FieldInfo publicStaticField in typeof(HRESULT).GetFields(BindingFlags.Static | BindingFlags.Public)) - { - if (publicStaticField.FieldType == typeof(HRESULT)) - { - var hr = (HRESULT)publicStaticField.GetValue(null); - if (hr == this) - { - return publicStaticField.Name; - } - } - } + public override bool Equals( object obj ) + { + try + { + return ( ( HRESULT )obj )._value == _value; + } + catch( InvalidCastException ) + { + return false; + } + } - // Try Win32 error codes also - if (Facility == Facility.Win32) - { - foreach (FieldInfo publicStaticField in typeof(Win32Error).GetFields(BindingFlags.Static | BindingFlags.Public)) - { - if (publicStaticField.FieldType == typeof(Win32Error)) - { - var error = (Win32Error)publicStaticField.GetValue(null); - if ((HRESULT)error == this) - { - return "HRESULT_FROM_WIN32(" + publicStaticField.Name + ")"; - } - } - } - } + public override int GetHashCode() + { + return _value.GetHashCode(); + } - // If there's no good name for this HRESULT, - // return the string as readable hex (0x########) format. - return string.Format(CultureInfo.InvariantCulture, "0x{0:X8}", _value); - } + #endregion - public override bool Equals(object obj) - { - try - { - return ((HRESULT)obj)._value == _value; - } - catch (InvalidCastException) - { - return false; - } - } + public static bool operator ==( HRESULT hrLeft, HRESULT hrRight ) + { + return hrLeft._value == hrRight._value; + } - public override int GetHashCode() - { - return _value.GetHashCode(); - } + public static bool operator !=( HRESULT hrLeft, HRESULT hrRight ) + { + return !( hrLeft == hrRight ); + } - #endregion + public bool Succeeded + { + get + { + return ( int )_value >= 0; + } + } - public static bool operator ==(HRESULT hrLeft, HRESULT hrRight) - { - return hrLeft._value == hrRight._value; - } + public bool Failed + { + get + { + return ( int )_value < 0; + } + } - public static bool operator !=(HRESULT hrLeft, HRESULT hrRight) - { - return !(hrLeft == hrRight); - } + public void ThrowIfFailed() + { + ThrowIfFailed( null ); + } - public bool Succeeded + [ + SuppressMessage( + "Microsoft.Usage", + "CA2201:DoNotRaiseReservedExceptionTypes", + Justification = "Only recreating Exceptions that were already raised." ), + SuppressMessage( + "Microsoft.Security", + "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" ) + ] + public void ThrowIfFailed( string message ) + { + if( Failed ) + { + if( string.IsNullOrEmpty( message ) ) { - get { return (int)_value >= 0; } + message = ToString(); } - - public bool Failed +#if DEBUG + else { - get { return (int)_value < 0; } + message += " (" + ToString() + ")"; } - - public void ThrowIfFailed() +#endif + // Wow. Reflection in a throw call. Later on this may turn out to have been a bad idea. + // If you're throwing an exception I assume it's OK for me to take some time to give it back. + // I want to convert the HRESULT to a more appropriate exception type than COMException. + // Marshal.ThrowExceptionForHR does this for me, but the general call uses GetErrorInfo + // if it's set, and then ignores the HRESULT that I've provided. This makes it so this + // call works the first time but you get burned on the second. To avoid this, I use + // the overload that explicitly ignores the IErrorInfo. + // In addition, the function doesn't allow me to set the Message unless I go through + // the process of implementing an IErrorInfo and then use that. There's no stock + // implementations of IErrorInfo available and I don't think it's worth the maintenance + // overhead of doing it, nor would it have significant value over this approach. + Exception e = Marshal.GetExceptionForHR( ( int )_value, new IntPtr( -1 ) ); + Assert.IsNotNull( e ); + // ArgumentNullException doesn't have the right constructor parameters, + // (nor does Win32Exception...) + // but E_POINTER gets mapped to NullReferenceException, + // so I don't think it will ever matter. + Assert.IsFalse( e is ArgumentNullException ); + + // If we're not getting anything better than a COMException from Marshal, + // then at least check the facility and attempt to do better ourselves. + if( e.GetType() == typeof( COMException ) ) { - ThrowIfFailed(null); + switch( Facility ) + { + case Facility.Win32: + e = new Win32Exception( Code, message ); + break; + default: + e = new COMException( message, ( int )_value ); + break; + } } - - [ - SuppressMessage( - "Microsoft.Usage", - "CA2201:DoNotRaiseReservedExceptionTypes", - Justification="Only recreating Exceptions that were already raised."), - SuppressMessage( - "Microsoft.Security", - "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands") - ] - public void ThrowIfFailed(string message) + else { - if (Failed) - { - if (string.IsNullOrEmpty(message)) - { - message = ToString(); - } -#if DEBUG - else - { - message += " (" + ToString() + ")"; - } -#endif - // Wow. Reflection in a throw call. Later on this may turn out to have been a bad idea. - // If you're throwing an exception I assume it's OK for me to take some time to give it back. - // I want to convert the HRESULT to a more appropriate exception type than COMException. - // Marshal.ThrowExceptionForHR does this for me, but the general call uses GetErrorInfo - // if it's set, and then ignores the HRESULT that I've provided. This makes it so this - // call works the first time but you get burned on the second. To avoid this, I use - // the overload that explicitly ignores the IErrorInfo. - // In addition, the function doesn't allow me to set the Message unless I go through - // the process of implementing an IErrorInfo and then use that. There's no stock - // implementations of IErrorInfo available and I don't think it's worth the maintenance - // overhead of doing it, nor would it have significant value over this approach. - Exception e = Marshal.GetExceptionForHR((int)_value, new IntPtr(-1)); - Assert.IsNotNull(e); - // ArgumentNullException doesn't have the right constructor parameters, - // (nor does Win32Exception...) - // but E_POINTER gets mapped to NullReferenceException, - // so I don't think it will ever matter. - Assert.IsFalse(e is ArgumentNullException); - - // If we're not getting anything better than a COMException from Marshal, - // then at least check the facility and attempt to do better ourselves. - if (e.GetType() == typeof(COMException)) - { - switch (Facility) - { - case Facility.Win32: - e = new Win32Exception(Code, message); - break; - default: - e = new COMException(message, (int)_value); - break; - } - } - else - { - ConstructorInfo cons = e.GetType().GetConstructor(new[] { typeof(string) }); - if (null != cons) - { - e = cons.Invoke(new object[] { message }) as Exception; - Assert.IsNotNull(e); - } - } - throw e; - } + ConstructorInfo cons = e.GetType().GetConstructor( new[] { typeof( string ) } ); + if( null != cons ) + { + e = cons.Invoke( new object[] { message } ) as Exception; + Assert.IsNotNull( e ); + } } + throw e; + } + } - /// - /// Convert the result of Win32 GetLastError() into a raised exception. - /// - public static void ThrowLastError() - { - ((HRESULT)Win32Error.GetLastError()).ThrowIfFailed(); - // Only expecting to call this when we're expecting a failed GetLastError() - Assert.Fail(); - } + /// + /// Convert the result of Win32 GetLastError() into a raised exception. + /// + public static void ThrowLastError() + { + ( ( HRESULT )Win32Error.GetLastError() ).ThrowIfFailed(); + // Only expecting to call this when we're expecting a failed GetLastError() + Assert.Fail(); } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/MessageWindow.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/MessageWindow.cs index a4128748..f15b715a 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/MessageWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/MessageWindow.cs @@ -20,166 +20,169 @@ namespace Standard { - using System; - using System.Runtime.InteropServices; - using System.Windows; - using System.Windows.Threading; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - - internal sealed class MessageWindow : DispatcherObject, IDisposable + using System; + using System.Runtime.InteropServices; + using System.Windows; + using System.Windows.Threading; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + + internal sealed class MessageWindow : DispatcherObject, IDisposable + { + // Alias this to a static so the wrapper doesn't get GC'd + private static readonly WndProc s_WndProc = new WndProc( _WndProc ); + private static readonly Dictionary s_windowLookup = new Dictionary(); + + private WndProc _wndProcCallback; + private string _className; + private bool _isDisposed; + + public IntPtr Handle { - // Alias this to a static so the wrapper doesn't get GC'd - private static readonly WndProc s_WndProc = new WndProc(_WndProc); - private static readonly Dictionary s_windowLookup = new Dictionary(); + get; private set; + } - private WndProc _wndProcCallback; - private string _className; - private bool _isDisposed; + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public MessageWindow( CS classStyle, WS style, WS_EX exStyle, Rect location, string name, WndProc callback ) + { + // A null callback means just use DefWindowProc. + _wndProcCallback = callback; + _className = "MessageWindowClass+" + Guid.NewGuid().ToString(); + + var wc = new WNDCLASSEX + { + cbSize = Marshal.SizeOf( typeof( WNDCLASSEX ) ), + style = classStyle, + lpfnWndProc = s_WndProc, + hInstance = NativeMethods.GetModuleHandle( null ), + hbrBackground = NativeMethods.GetStockObject( StockObject.NULL_BRUSH ), + lpszMenuName = "", + lpszClassName = _className, + }; + + NativeMethods.RegisterClassEx( ref wc ); + + GCHandle gcHandle = default( GCHandle ); + try + { + gcHandle = GCHandle.Alloc( this ); + IntPtr pinnedThisPtr = ( IntPtr )gcHandle; + + Handle = NativeMethods.CreateWindowEx( + exStyle, + _className, + name, + style, + ( int )location.X, + ( int )location.Y, + ( int )location.Width, + ( int )location.Height, + IntPtr.Zero, + IntPtr.Zero, + IntPtr.Zero, + pinnedThisPtr ); + } + finally + { + gcHandle.Free(); + } + } - public IntPtr Handle { get; private set; } + ~MessageWindow() + { + _Dispose( false, false ); + } - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public MessageWindow(CS classStyle, WS style, WS_EX exStyle, Rect location, string name, WndProc callback) - { - // A null callback means just use DefWindowProc. - _wndProcCallback = callback; - _className = "MessageWindowClass+" + Guid.NewGuid().ToString(); - - var wc = new WNDCLASSEX - { - cbSize = Marshal.SizeOf(typeof(WNDCLASSEX)), - style = classStyle, - lpfnWndProc = s_WndProc, - hInstance = NativeMethods.GetModuleHandle(null), - hbrBackground = NativeMethods.GetStockObject(StockObject.NULL_BRUSH), - lpszMenuName = "", - lpszClassName = _className, - }; - - NativeMethods.RegisterClassEx(ref wc); - - GCHandle gcHandle = default(GCHandle); - try - { - gcHandle = GCHandle.Alloc(this); - IntPtr pinnedThisPtr = (IntPtr)gcHandle; - - Handle = NativeMethods.CreateWindowEx( - exStyle, - _className, - name, - style, - (int)location.X, - (int)location.Y, - (int)location.Width, - (int)location.Height, - IntPtr.Zero, - IntPtr.Zero, - IntPtr.Zero, - pinnedThisPtr); - } - finally - { - gcHandle.Free(); - } - } + public void Dispose() + { + _Dispose( true, false ); + GC.SuppressFinalize( this ); + } - ~MessageWindow() + // This isn't right if the Dispatcher has already started shutting down. + // It will wind up leaking the class ATOM... + [SuppressMessage( "Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing" )] + private void _Dispose( bool disposing, bool isHwndBeingDestroyed ) + { + if( _isDisposed ) + { + // Block against reentrancy. + return; + } + + _isDisposed = true; + + IntPtr hwnd = Handle; + string className = _className; + + if( isHwndBeingDestroyed ) + { + Dispatcher.BeginInvoke( DispatcherPriority.Normal, ( DispatcherOperationCallback )( arg => _DestroyWindow( IntPtr.Zero, className ) ) ); + } + else if( Handle != IntPtr.Zero ) + { + if( CheckAccess() ) { - _Dispose(false, false); + _DestroyWindow( hwnd, className ); } - - public void Dispose() + else { - _Dispose(true, false); - GC.SuppressFinalize(this); + Dispatcher.BeginInvoke( DispatcherPriority.Normal, ( DispatcherOperationCallback )( arg => _DestroyWindow( hwnd, className ) ) ); } + } - // This isn't right if the Dispatcher has already started shutting down. - // It will wind up leaking the class ATOM... - [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing")] - private void _Dispose(bool disposing, bool isHwndBeingDestroyed) - { - if (_isDisposed) - { - // Block against reentrancy. - return; - } - - _isDisposed = true; - - IntPtr hwnd = Handle; - string className = _className; - - if (isHwndBeingDestroyed) - { - Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)(arg => _DestroyWindow(IntPtr.Zero, className))); - } - else if (Handle != IntPtr.Zero) - { - if (CheckAccess()) - { - _DestroyWindow(hwnd, className); - } - else - { - Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)(arg => _DestroyWindow(hwnd, className))); - } - } - - s_windowLookup.Remove(hwnd); - - _className = null; - Handle = IntPtr.Zero; - } + s_windowLookup.Remove( hwnd ); - [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly")] - private static IntPtr _WndProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam) - { - IntPtr ret = IntPtr.Zero; - MessageWindow hwndWrapper = null; - - if (msg == WM.CREATE) - { - var createStruct = (CREATESTRUCT)Marshal.PtrToStructure(lParam, typeof(CREATESTRUCT)); - GCHandle gcHandle = GCHandle.FromIntPtr(createStruct.lpCreateParams); - hwndWrapper = (MessageWindow)gcHandle.Target; - s_windowLookup.Add(hwnd, hwndWrapper); - } - else - { - if (!s_windowLookup.TryGetValue(hwnd, out hwndWrapper)) - { - return NativeMethods.DefWindowProc(hwnd, msg, wParam, lParam); - } - } - Assert.IsNotNull(hwndWrapper); - - WndProc callback = hwndWrapper._wndProcCallback; - if (callback != null) - { - ret = callback(hwnd, msg, wParam, lParam); - } - else - { - ret = NativeMethods.DefWindowProc(hwnd, msg, wParam, lParam); - } - - if (msg == WM.NCDESTROY) - { - hwndWrapper._Dispose(true, true); - GC.SuppressFinalize(hwndWrapper); - } - - return ret; - } + _className = null; + Handle = IntPtr.Zero; + } - private static object _DestroyWindow(IntPtr hwnd, string className) + [SuppressMessage( "Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly" )] + private static IntPtr _WndProc( IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam ) + { + IntPtr ret = IntPtr.Zero; + MessageWindow hwndWrapper = null; + + if( msg == WM.CREATE ) + { + var createStruct = ( CREATESTRUCT )Marshal.PtrToStructure( lParam, typeof( CREATESTRUCT ) ); + GCHandle gcHandle = GCHandle.FromIntPtr( createStruct.lpCreateParams ); + hwndWrapper = ( MessageWindow )gcHandle.Target; + s_windowLookup.Add( hwnd, hwndWrapper ); + } + else + { + if( !s_windowLookup.TryGetValue( hwnd, out hwndWrapper ) ) { - Utility.SafeDestroyWindow(ref hwnd); - NativeMethods.UnregisterClass(className, NativeMethods.GetModuleHandle(null)); - return null; + return NativeMethods.DefWindowProc( hwnd, msg, wParam, lParam ); } + } + Assert.IsNotNull( hwndWrapper ); + + WndProc callback = hwndWrapper._wndProcCallback; + if( callback != null ) + { + ret = callback( hwnd, msg, wParam, lParam ); + } + else + { + ret = NativeMethods.DefWindowProc( hwnd, msg, wParam, lParam ); + } + + if( msg == WM.NCDESTROY ) + { + hwndWrapper._Dispose( true, true ); + GC.SuppressFinalize( hwndWrapper ); + } + + return ret; + } + + private static object _DestroyWindow( IntPtr hwnd, string className ) + { + Utility.SafeDestroyWindow( ref hwnd ); + NativeMethods.UnregisterClass( className, NativeMethods.GetModuleHandle( null ) ); + return null; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/NativeMethods.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/NativeMethods.cs index c4452ba1..ab3ca01f 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/NativeMethods.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/NativeMethods.cs @@ -20,3455 +20,3526 @@ namespace Standard { - using System; - using System.ComponentModel; - using System.Diagnostics.CodeAnalysis; - using System.IO; - using System.Runtime.ConstrainedExecution; - using System.Runtime.InteropServices; - using System.Runtime.InteropServices.ComTypes; - using System.Security.Permissions; - using System.Text; - using Microsoft.Win32.SafeHandles; - - // Some COM interfaces and Win32 structures are already declared in the framework. - // Interesting ones to remember in System.Runtime.InteropServices.ComTypes are: - using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; - using IPersistFile = System.Runtime.InteropServices.ComTypes.IPersistFile; - using IStream = System.Runtime.InteropServices.ComTypes.IStream; - - #region Native Values - - internal static class Win32Value - { - public const uint MAX_PATH = 260; - public const uint INFOTIPSIZE = 1024; - public const uint TRUE = 1; - public const uint FALSE = 0; - public const uint sizeof_WCHAR = 2; - public const uint sizeof_CHAR = 1; - public const uint sizeof_BOOL = 4; - } - + using System; + using System.ComponentModel; + using System.Diagnostics.CodeAnalysis; + using System.IO; + using System.Runtime.ConstrainedExecution; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + using System.Security.Permissions; + using System.Text; + using Microsoft.Win32.SafeHandles; + + // Some COM interfaces and Win32 structures are already declared in the framework. + // Interesting ones to remember in System.Runtime.InteropServices.ComTypes are: + using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; + using IPersistFile = System.Runtime.InteropServices.ComTypes.IPersistFile; + using IStream = System.Runtime.InteropServices.ComTypes.IStream; + + #region Native Values + + internal static class Win32Value + { + public const uint MAX_PATH = 260; + public const uint INFOTIPSIZE = 1024; + public const uint TRUE = 1; + public const uint FALSE = 0; + public const uint sizeof_WCHAR = 2; + public const uint sizeof_CHAR = 1; + public const uint sizeof_BOOL = 4; + } + + /// + /// HIGHCONTRAST flags + /// + [Flags] + internal enum HCF + { + HIGHCONTRASTON = 0x00000001, + AVAILABLE = 0x00000002, + HOTKEYACTIVE = 0x00000004, + CONFIRMHOTKEY = 0x00000008, + HOTKEYSOUND = 0x00000010, + INDICATOR = 0x00000020, + HOTKEYAVAILABLE = 0x00000040, + } + + /// + /// BITMAPINFOHEADER Compression type. BI_*. + /// + internal enum BI + { + RGB = 0, + } + + /// + /// CombingRgn flags. RGN_* + /// + internal enum RGN + { /// - /// HIGHCONTRAST flags + /// Creates the intersection of the two combined regions. /// - [Flags] - internal enum HCF - { - HIGHCONTRASTON = 0x00000001, - AVAILABLE = 0x00000002, - HOTKEYACTIVE = 0x00000004, - CONFIRMHOTKEY = 0x00000008, - HOTKEYSOUND = 0x00000010, - INDICATOR = 0x00000020, - HOTKEYAVAILABLE = 0x00000040, - } - - /// - /// BITMAPINFOHEADER Compression type. BI_*. - /// - internal enum BI - { - RGB = 0, - } - + AND = 1, /// - /// CombingRgn flags. RGN_* + /// Creates the union of two combined regions. /// - internal enum RGN - { - /// - /// Creates the intersection of the two combined regions. - /// - AND = 1, - /// - /// Creates the union of two combined regions. - /// - OR = 2, - /// - /// Creates the union of two combined regions except for any overlapping areas. - /// - XOR = 3, - /// - /// Combines the parts of hrgnSrc1 that are not part of hrgnSrc2. - /// - DIFF = 4, - /// - /// Creates a copy of the region identified by hrgnSrc1. - /// - COPY = 5, - } - - internal enum CombineRgnResult - { - ERROR = 0, - NULLREGION = 1, - SIMPLEREGION = 2, - COMPLEXREGION = 3, - } - + OR = 2, /// - /// For IWebBrowser2. OLECMDEXECOPT_* + /// Creates the union of two combined regions except for any overlapping areas. /// - internal enum OLECMDEXECOPT - { - DODEFAULT = 0, - PROMPTUSER = 1, - DONTPROMPTUSER = 2, - SHOWHELP = 3 - } - + XOR = 3, /// - /// For IWebBrowser2. OLECMDF_* + /// Combines the parts of hrgnSrc1 that are not part of hrgnSrc2. /// - internal enum OLECMDF - { - SUPPORTED = 1, - ENABLED = 2, - LATCHED = 4, - NINCHED = 8, - INVISIBLE = 16, - DEFHIDEONCTXTMENU = 32 - } - + DIFF = 4, /// - /// For IWebBrowser2. OLECMDID_* + /// Creates a copy of the region identified by hrgnSrc1. /// - internal enum OLECMDID - { - OPEN = 1, - NEW = 2, - SAVE = 3, - SAVEAS = 4, - SAVECOPYAS = 5, - PRINT = 6, - PRINTPREVIEW = 7, - PAGESETUP = 8, - SPELL = 9, - PROPERTIES = 10, - CUT = 11, - COPY = 12, - PASTE = 13, - PASTESPECIAL = 14, - UNDO = 15, - REDO = 16, - SELECTALL = 17, - CLEARSELECTION = 18, - ZOOM = 19, - GETZOOMRANGE = 20, - UPDATECOMMANDS = 21, - REFRESH = 22, - STOP = 23, - HIDETOOLBARS = 24, - SETPROGRESSMAX = 25, - SETPROGRESSPOS = 26, - SETPROGRESSTEXT = 27, - SETTITLE = 28, - SETDOWNLOADSTATE = 29, - STOPDOWNLOAD = 30, - ONTOOLBARACTIVATED = 31, - FIND = 32, - DELETE = 33, - HTTPEQUIV = 34, - HTTPEQUIV_DONE = 35, - ENABLE_INTERACTION = 36, - ONUNLOAD = 37, - PROPERTYBAG2 = 38, - PREREFRESH = 39, - SHOWSCRIPTERROR = 40, - SHOWMESSAGE = 41, - SHOWFIND = 42, - SHOWPAGESETUP = 43, - SHOWPRINT = 44, - CLOSE = 45, - ALLOWUILESSSAVEAS = 46, - DONTDOWNLOADCSS = 47, - UPDATEPAGESTATUS = 48, - PRINT2 = 49, - PRINTPREVIEW2 = 50, - SETPRINTTEMPLATE = 51, - GETPRINTTEMPLATE = 52, - PAGEACTIONBLOCKED = 55, - PAGEACTIONUIQUERY = 56, - FOCUSVIEWCONTROLS = 57, - FOCUSVIEWCONTROLSQUERY = 58, - SHOWPAGEACTIONMENU = 59 - } - + COPY = 5, + } + + internal enum CombineRgnResult + { + ERROR = 0, + NULLREGION = 1, + SIMPLEREGION = 2, + COMPLEXREGION = 3, + } + + /// + /// For IWebBrowser2. OLECMDEXECOPT_* + /// + internal enum OLECMDEXECOPT + { + DODEFAULT = 0, + PROMPTUSER = 1, + DONTPROMPTUSER = 2, + SHOWHELP = 3 + } + + /// + /// For IWebBrowser2. OLECMDF_* + /// + internal enum OLECMDF + { + SUPPORTED = 1, + ENABLED = 2, + LATCHED = 4, + NINCHED = 8, + INVISIBLE = 16, + DEFHIDEONCTXTMENU = 32 + } + + /// + /// For IWebBrowser2. OLECMDID_* + /// + internal enum OLECMDID + { + OPEN = 1, + NEW = 2, + SAVE = 3, + SAVEAS = 4, + SAVECOPYAS = 5, + PRINT = 6, + PRINTPREVIEW = 7, + PAGESETUP = 8, + SPELL = 9, + PROPERTIES = 10, + CUT = 11, + COPY = 12, + PASTE = 13, + PASTESPECIAL = 14, + UNDO = 15, + REDO = 16, + SELECTALL = 17, + CLEARSELECTION = 18, + ZOOM = 19, + GETZOOMRANGE = 20, + UPDATECOMMANDS = 21, + REFRESH = 22, + STOP = 23, + HIDETOOLBARS = 24, + SETPROGRESSMAX = 25, + SETPROGRESSPOS = 26, + SETPROGRESSTEXT = 27, + SETTITLE = 28, + SETDOWNLOADSTATE = 29, + STOPDOWNLOAD = 30, + ONTOOLBARACTIVATED = 31, + FIND = 32, + DELETE = 33, + HTTPEQUIV = 34, + HTTPEQUIV_DONE = 35, + ENABLE_INTERACTION = 36, + ONUNLOAD = 37, + PROPERTYBAG2 = 38, + PREREFRESH = 39, + SHOWSCRIPTERROR = 40, + SHOWMESSAGE = 41, + SHOWFIND = 42, + SHOWPAGESETUP = 43, + SHOWPRINT = 44, + CLOSE = 45, + ALLOWUILESSSAVEAS = 46, + DONTDOWNLOADCSS = 47, + UPDATEPAGESTATUS = 48, + PRINT2 = 49, + PRINTPREVIEW2 = 50, + SETPRINTTEMPLATE = 51, + GETPRINTTEMPLATE = 52, + PAGEACTIONBLOCKED = 55, + PAGEACTIONUIQUERY = 56, + FOCUSVIEWCONTROLS = 57, + FOCUSVIEWCONTROLSQUERY = 58, + SHOWPAGEACTIONMENU = 59 + } + + /// + /// For IWebBrowser2. READYSTATE_* + /// + enum READYSTATE + { + UNINITIALIZED = 0, + LOADING = 1, + LOADED = 2, + INTERACTIVE = 3, + COMPLETE = 4 + } + + /// + /// DATAOBJ_GET_ITEM_FLAGS. DOGIF_*. + /// + internal enum DOGIF + { + DEFAULT = 0x0000, + TRAVERSE_LINK = 0x0001, // if the item is a link get the target + NO_HDROP = 0x0002, // don't fallback and use CF_HDROP clipboard format + NO_URL = 0x0004, // don't fallback and use URL clipboard format + ONLY_IF_ONE = 0x0008, // only return the item if there is one item in the array + } + + internal enum DWM_SIT + { + None, + DISPLAYFRAME = 1, + } + + [Flags] + internal enum ErrorModes + { + /// Use the system default, which is to display all error dialog boxes. + Default = 0x0, /// - /// For IWebBrowser2. READYSTATE_* + /// The system does not display the critical-error-handler message box. + /// Instead, the system sends the error to the calling process. /// - enum READYSTATE - { - UNINITIALIZED = 0, - LOADING = 1, - LOADED = 2, - INTERACTIVE = 3, - COMPLETE = 4 - } - + FailCriticalErrors = 0x1, /// - /// DATAOBJ_GET_ITEM_FLAGS. DOGIF_*. + /// 64-bit Windows: The system automatically fixes memory alignment faults and makes them + /// invisible to the application. It does this for the calling process and any descendant processes. + /// After this value is set for a process, subsequent attempts to clear the value are ignored. /// - internal enum DOGIF - { - DEFAULT = 0x0000, - TRAVERSE_LINK = 0x0001, // if the item is a link get the target - NO_HDROP = 0x0002, // don't fallback and use CF_HDROP clipboard format - NO_URL = 0x0004, // don't fallback and use URL clipboard format - ONLY_IF_ONE = 0x0008, // only return the item if there is one item in the array - } - - internal enum DWM_SIT - { - None, - DISPLAYFRAME = 1, - } - - [Flags] - internal enum ErrorModes - { - /// Use the system default, which is to display all error dialog boxes. - Default = 0x0, - /// - /// The system does not display the critical-error-handler message box. - /// Instead, the system sends the error to the calling process. - /// - FailCriticalErrors = 0x1, - /// - /// 64-bit Windows: The system automatically fixes memory alignment faults and makes them - /// invisible to the application. It does this for the calling process and any descendant processes. - /// After this value is set for a process, subsequent attempts to clear the value are ignored. - /// - NoGpFaultErrorBox = 0x2, - /// - /// The system does not display the general-protection-fault message box. - /// This flag should only be set by debugging applications that handle general - /// protection (GP) faults themselves with an exception handler. - /// - NoAlignmentFaultExcept = 0x4, - /// - /// The system does not display a message box when it fails to find a file. - /// Instead, the error is returned to the calling process. - /// - NoOpenFileErrorBox = 0x8000 - } - + NoGpFaultErrorBox = 0x2, /// - /// Non-client hit test values, HT* + /// The system does not display the general-protection-fault message box. + /// This flag should only be set by debugging applications that handle general + /// protection (GP) faults themselves with an exception handler. /// - internal enum HT - { - ERROR = -2, - TRANSPARENT = -1, - NOWHERE = 0, - CLIENT = 1, - CAPTION = 2, - SYSMENU = 3, - GROWBOX = 4, - SIZE = GROWBOX, - MENU = 5, - HSCROLL = 6, - VSCROLL = 7, - MINBUTTON = 8, - MAXBUTTON = 9, - LEFT = 10, - RIGHT = 11, - TOP = 12, - TOPLEFT = 13, - TOPRIGHT = 14, - BOTTOM = 15, - BOTTOMLEFT = 16, - BOTTOMRIGHT = 17, - BORDER = 18, - REDUCE = MINBUTTON, - ZOOM = MAXBUTTON, - SIZEFIRST = LEFT, - SIZELAST = BOTTOMRIGHT, - OBJECT = 19, - CLOSE = 20, - HELP = 21 - } - + NoAlignmentFaultExcept = 0x4, /// - /// GetClassLongPtr values, GCLP_* + /// The system does not display a message box when it fails to find a file. + /// Instead, the error is returned to the calling process. /// - internal enum GCLP - { - HBRBACKGROUND = -10, - } + NoOpenFileErrorBox = 0x8000 + } + + /// + /// Non-client hit test values, HT* + /// + internal enum HT + { + ERROR = -2, + TRANSPARENT = -1, + NOWHERE = 0, + CLIENT = 1, + CAPTION = 2, + SYSMENU = 3, + GROWBOX = 4, + SIZE = GROWBOX, + MENU = 5, + HSCROLL = 6, + VSCROLL = 7, + MINBUTTON = 8, + MAXBUTTON = 9, + LEFT = 10, + RIGHT = 11, + TOP = 12, + TOPLEFT = 13, + TOPRIGHT = 14, + BOTTOM = 15, + BOTTOMLEFT = 16, + BOTTOMRIGHT = 17, + BORDER = 18, + REDUCE = MINBUTTON, + ZOOM = MAXBUTTON, + SIZEFIRST = LEFT, + SIZELAST = BOTTOMRIGHT, + OBJECT = 19, + CLOSE = 20, + HELP = 21 + } + + /// + /// GetClassLongPtr values, GCLP_* + /// + internal enum GCLP + { + HBRBACKGROUND = -10, + } + + /// + /// GetWindowLongPtr values, GWL_* + /// + internal enum GWL + { + WNDPROC = ( -4 ), + HINSTANCE = ( -6 ), + HWNDPARENT = ( -8 ), + STYLE = ( -16 ), + EXSTYLE = ( -20 ), + USERDATA = ( -21 ), + ID = ( -12 ) + } + + /// + /// SystemMetrics. SM_* + /// + internal enum SM + { + CXSCREEN = 0, + CYSCREEN = 1, + CXVSCROLL = 2, + CYHSCROLL = 3, + CYCAPTION = 4, + CXBORDER = 5, + CYBORDER = 6, + CXFIXEDFRAME = 7, + CYFIXEDFRAME = 8, + CYVTHUMB = 9, + CXHTHUMB = 10, + CXICON = 11, + CYICON = 12, + CXCURSOR = 13, + CYCURSOR = 14, + CYMENU = 15, + CXFULLSCREEN = 16, + CYFULLSCREEN = 17, + CYKANJIWINDOW = 18, + MOUSEPRESENT = 19, + CYVSCROLL = 20, + CXHSCROLL = 21, + DEBUG = 22, + SWAPBUTTON = 23, + CXMIN = 28, + CYMIN = 29, + CXSIZE = 30, + CYSIZE = 31, + CXFRAME = 32, + CXSIZEFRAME = CXFRAME, + CYFRAME = 33, + CYSIZEFRAME = CYFRAME, + CXMINTRACK = 34, + CYMINTRACK = 35, + CXDOUBLECLK = 36, + CYDOUBLECLK = 37, + CXICONSPACING = 38, + CYICONSPACING = 39, + MENUDROPALIGNMENT = 40, + PENWINDOWS = 41, + DBCSENABLED = 42, + CMOUSEBUTTONS = 43, + SECURE = 44, + CXEDGE = 45, + CYEDGE = 46, + CXMINSPACING = 47, + CYMINSPACING = 48, + CXSMICON = 49, + CYSMICON = 50, + CYSMCAPTION = 51, + CXSMSIZE = 52, + CYSMSIZE = 53, + CXMENUSIZE = 54, + CYMENUSIZE = 55, + ARRANGE = 56, + CXMINIMIZED = 57, + CYMINIMIZED = 58, + CXMAXTRACK = 59, + CYMAXTRACK = 60, + CXMAXIMIZED = 61, + CYMAXIMIZED = 62, + NETWORK = 63, + CLEANBOOT = 67, + CXDRAG = 68, + CYDRAG = 69, + SHOWSOUNDS = 70, + CXMENUCHECK = 71, + CYMENUCHECK = 72, + SLOWMACHINE = 73, + MIDEASTENABLED = 74, + MOUSEWHEELPRESENT = 75, + XVIRTUALSCREEN = 76, + YVIRTUALSCREEN = 77, + CXVIRTUALSCREEN = 78, + CYVIRTUALSCREEN = 79, + CMONITORS = 80, + SAMEDISPLAYFORMAT = 81, + IMMENABLED = 82, + CXFOCUSBORDER = 83, + CYFOCUSBORDER = 84, + TABLETPC = 86, + MEDIACENTER = 87, + REMOTESESSION = 0x1000, + REMOTECONTROL = 0x2001, + } + + /// + /// SystemParameterInfo values, SPI_* + /// + internal enum SPI + { + GETBEEP = 0x0001, + SETBEEP = 0x0002, + GETMOUSE = 0x0003, + SETMOUSE = 0x0004, + GETBORDER = 0x0005, + SETBORDER = 0x0006, + GETKEYBOARDSPEED = 0x000A, + SETKEYBOARDSPEED = 0x000B, + LANGDRIVER = 0x000C, + ICONHORIZONTALSPACING = 0x000D, + GETSCREENSAVETIMEOUT = 0x000E, + SETSCREENSAVETIMEOUT = 0x000F, + GETSCREENSAVEACTIVE = 0x0010, + SETSCREENSAVEACTIVE = 0x0011, + GETGRIDGRANULARITY = 0x0012, + SETGRIDGRANULARITY = 0x0013, + SETDESKWALLPAPER = 0x0014, + SETDESKPATTERN = 0x0015, + GETKEYBOARDDELAY = 0x0016, + SETKEYBOARDDELAY = 0x0017, + ICONVERTICALSPACING = 0x0018, + GETICONTITLEWRAP = 0x0019, + SETICONTITLEWRAP = 0x001A, + GETMENUDROPALIGNMENT = 0x001B, + SETMENUDROPALIGNMENT = 0x001C, + SETDOUBLECLKWIDTH = 0x001D, + SETDOUBLECLKHEIGHT = 0x001E, + GETICONTITLELOGFONT = 0x001F, + SETDOUBLECLICKTIME = 0x0020, + SETMOUSEBUTTONSWAP = 0x0021, + SETICONTITLELOGFONT = 0x0022, + GETFASTTASKSWITCH = 0x0023, + SETFASTTASKSWITCH = 0x0024, + + SETDRAGFULLWINDOWS = 0x0025, + GETDRAGFULLWINDOWS = 0x0026, + GETNONCLIENTMETRICS = 0x0029, + SETNONCLIENTMETRICS = 0x002A, + GETMINIMIZEDMETRICS = 0x002B, + SETMINIMIZEDMETRICS = 0x002C, + GETICONMETRICS = 0x002D, + SETICONMETRICS = 0x002E, + SETWORKAREA = 0x002F, + GETWORKAREA = 0x0030, + SETPENWINDOWS = 0x0031, + GETHIGHCONTRAST = 0x0042, + SETHIGHCONTRAST = 0x0043, + GETKEYBOARDPREF = 0x0044, + SETKEYBOARDPREF = 0x0045, + GETSCREENREADER = 0x0046, + SETSCREENREADER = 0x0047, + GETANIMATION = 0x0048, + SETANIMATION = 0x0049, + GETFONTSMOOTHING = 0x004A, + SETFONTSMOOTHING = 0x004B, + SETDRAGWIDTH = 0x004C, + SETDRAGHEIGHT = 0x004D, + SETHANDHELD = 0x004E, + GETLOWPOWERTIMEOUT = 0x004F, + GETPOWEROFFTIMEOUT = 0x0050, + SETLOWPOWERTIMEOUT = 0x0051, + SETPOWEROFFTIMEOUT = 0x0052, + GETLOWPOWERACTIVE = 0x0053, + GETPOWEROFFACTIVE = 0x0054, + SETLOWPOWERACTIVE = 0x0055, + SETPOWEROFFACTIVE = 0x0056, + SETCURSORS = 0x0057, + SETICONS = 0x0058, + GETDEFAULTINPUTLANG = 0x0059, + SETDEFAULTINPUTLANG = 0x005A, + SETLANGTOGGLE = 0x005B, + GETWINDOWSEXTENSION = 0x005C, + SETMOUSETRAILS = 0x005D, + GETMOUSETRAILS = 0x005E, + SETSCREENSAVERRUNNING = 0x0061, + SCREENSAVERRUNNING = SETSCREENSAVERRUNNING, + GETFILTERKEYS = 0x0032, + SETFILTERKEYS = 0x0033, + GETTOGGLEKEYS = 0x0034, + SETTOGGLEKEYS = 0x0035, + GETMOUSEKEYS = 0x0036, + SETMOUSEKEYS = 0x0037, + GETSHOWSOUNDS = 0x0038, + SETSHOWSOUNDS = 0x0039, + GETSTICKYKEYS = 0x003A, + SETSTICKYKEYS = 0x003B, + GETACCESSTIMEOUT = 0x003C, + SETACCESSTIMEOUT = 0x003D, + + GETSERIALKEYS = 0x003E, + SETSERIALKEYS = 0x003F, + GETSOUNDSENTRY = 0x0040, + SETSOUNDSENTRY = 0x0041, + GETSNAPTODEFBUTTON = 0x005F, + SETSNAPTODEFBUTTON = 0x0060, + GETMOUSEHOVERWIDTH = 0x0062, + SETMOUSEHOVERWIDTH = 0x0063, + GETMOUSEHOVERHEIGHT = 0x0064, + SETMOUSEHOVERHEIGHT = 0x0065, + GETMOUSEHOVERTIME = 0x0066, + SETMOUSEHOVERTIME = 0x0067, + GETWHEELSCROLLLINES = 0x0068, + SETWHEELSCROLLLINES = 0x0069, + GETMENUSHOWDELAY = 0x006A, + SETMENUSHOWDELAY = 0x006B, + + GETWHEELSCROLLCHARS = 0x006C, + SETWHEELSCROLLCHARS = 0x006D, + + GETSHOWIMEUI = 0x006E, + SETSHOWIMEUI = 0x006F, + + GETMOUSESPEED = 0x0070, + SETMOUSESPEED = 0x0071, + GETSCREENSAVERRUNNING = 0x0072, + GETDESKWALLPAPER = 0x0073, + + GETAUDIODESCRIPTION = 0x0074, + SETAUDIODESCRIPTION = 0x0075, + + GETSCREENSAVESECURE = 0x0076, + SETSCREENSAVESECURE = 0x0077, + + GETHUNGAPPTIMEOUT = 0x0078, + SETHUNGAPPTIMEOUT = 0x0079, + GETWAITTOKILLTIMEOUT = 0x007A, + SETWAITTOKILLTIMEOUT = 0x007B, + GETWAITTOKILLSERVICETIMEOUT = 0x007C, + SETWAITTOKILLSERVICETIMEOUT = 0x007D, + GETMOUSEDOCKTHRESHOLD = 0x007E, + SETMOUSEDOCKTHRESHOLD = 0x007F, + GETPENDOCKTHRESHOLD = 0x0080, + SETPENDOCKTHRESHOLD = 0x0081, + GETWINARRANGING = 0x0082, + SETWINARRANGING = 0x0083, + GETMOUSEDRAGOUTTHRESHOLD = 0x0084, + SETMOUSEDRAGOUTTHRESHOLD = 0x0085, + GETPENDRAGOUTTHRESHOLD = 0x0086, + SETPENDRAGOUTTHRESHOLD = 0x0087, + GETMOUSESIDEMOVETHRESHOLD = 0x0088, + SETMOUSESIDEMOVETHRESHOLD = 0x0089, + GETPENSIDEMOVETHRESHOLD = 0x008A, + SETPENSIDEMOVETHRESHOLD = 0x008B, + GETDRAGFROMMAXIMIZE = 0x008C, + SETDRAGFROMMAXIMIZE = 0x008D, + GETSNAPSIZING = 0x008E, + SETSNAPSIZING = 0x008F, + GETDOCKMOVING = 0x0090, + SETDOCKMOVING = 0x0091, + + GETACTIVEWINDOWTRACKING = 0x1000, + SETACTIVEWINDOWTRACKING = 0x1001, + GETMENUANIMATION = 0x1002, + SETMENUANIMATION = 0x1003, + GETCOMBOBOXANIMATION = 0x1004, + SETCOMBOBOXANIMATION = 0x1005, + GETLISTBOXSMOOTHSCROLLING = 0x1006, + SETLISTBOXSMOOTHSCROLLING = 0x1007, + GETGRADIENTCAPTIONS = 0x1008, + SETGRADIENTCAPTIONS = 0x1009, + GETKEYBOARDCUES = 0x100A, + SETKEYBOARDCUES = 0x100B, + GETMENUUNDERLINES = GETKEYBOARDCUES, + SETMENUUNDERLINES = SETKEYBOARDCUES, + GETACTIVEWNDTRKZORDER = 0x100C, + SETACTIVEWNDTRKZORDER = 0x100D, + GETHOTTRACKING = 0x100E, + SETHOTTRACKING = 0x100F, + GETMENUFADE = 0x1012, + SETMENUFADE = 0x1013, + GETSELECTIONFADE = 0x1014, + SETSELECTIONFADE = 0x1015, + GETTOOLTIPANIMATION = 0x1016, + SETTOOLTIPANIMATION = 0x1017, + GETTOOLTIPFADE = 0x1018, + SETTOOLTIPFADE = 0x1019, + GETCURSORSHADOW = 0x101A, + SETCURSORSHADOW = 0x101B, + GETMOUSESONAR = 0x101C, + SETMOUSESONAR = 0x101D, + GETMOUSECLICKLOCK = 0x101E, + SETMOUSECLICKLOCK = 0x101F, + GETMOUSEVANISH = 0x1020, + SETMOUSEVANISH = 0x1021, + GETFLATMENU = 0x1022, + SETFLATMENU = 0x1023, + GETDROPSHADOW = 0x1024, + SETDROPSHADOW = 0x1025, + GETBLOCKSENDINPUTRESETS = 0x1026, + SETBLOCKSENDINPUTRESETS = 0x1027, + + GETUIEFFECTS = 0x103E, + SETUIEFFECTS = 0x103F, + + GETDISABLEOVERLAPPEDCONTENT = 0x1040, + SETDISABLEOVERLAPPEDCONTENT = 0x1041, + GETCLIENTAREAANIMATION = 0x1042, + SETCLIENTAREAANIMATION = 0x1043, + GETCLEARTYPE = 0x1048, + SETCLEARTYPE = 0x1049, + GETSPEECHRECOGNITION = 0x104A, + SETSPEECHRECOGNITION = 0x104B, + + GETFOREGROUNDLOCKTIMEOUT = 0x2000, + SETFOREGROUNDLOCKTIMEOUT = 0x2001, + GETACTIVEWNDTRKTIMEOUT = 0x2002, + SETACTIVEWNDTRKTIMEOUT = 0x2003, + GETFOREGROUNDFLASHCOUNT = 0x2004, + SETFOREGROUNDFLASHCOUNT = 0x2005, + GETCARETWIDTH = 0x2006, + SETCARETWIDTH = 0x2007, + + GETMOUSECLICKLOCKTIME = 0x2008, + SETMOUSECLICKLOCKTIME = 0x2009, + GETFONTSMOOTHINGTYPE = 0x200A, + SETFONTSMOOTHINGTYPE = 0x200B, + + GETFONTSMOOTHINGCONTRAST = 0x200C, + SETFONTSMOOTHINGCONTRAST = 0x200D, + + GETFOCUSBORDERWIDTH = 0x200E, + SETFOCUSBORDERWIDTH = 0x200F, + GETFOCUSBORDERHEIGHT = 0x2010, + SETFOCUSBORDERHEIGHT = 0x2011, + + GETFONTSMOOTHINGORIENTATION = 0x2012, + SETFONTSMOOTHINGORIENTATION = 0x2013, + + GETMINIMUMHITRADIUS = 0x2014, + SETMINIMUMHITRADIUS = 0x2015, + GETMESSAGEDURATION = 0x2016, + SETMESSAGEDURATION = 0x2017, + } + + /// + /// SystemParameterInfo flag values, SPIF_* + /// + [Flags] + internal enum SPIF + { + None = 0, + UPDATEINIFILE = 0x01, + SENDCHANGE = 0x02, + SENDWININICHANGE = SENDCHANGE, + } + + [Flags] + internal enum STATE_SYSTEM + { + UNAVAILABLE = 0x00000001, // Disabled + SELECTED = 0x00000002, + FOCUSED = 0x00000004, + PRESSED = 0x00000008, + CHECKED = 0x00000010, + MIXED = 0x00000020, // 3-state checkbox or toolbar button + INDETERMINATE = MIXED, + READONLY = 0x00000040, + HOTTRACKED = 0x00000080, + DEFAULT = 0x00000100, + EXPANDED = 0x00000200, + COLLAPSED = 0x00000400, + BUSY = 0x00000800, + FLOATING = 0x00001000, // Children "owned" not "contained" by parent + MARQUEED = 0x00002000, + ANIMATED = 0x00004000, + INVISIBLE = 0x00008000, + OFFSCREEN = 0x00010000, + SIZEABLE = 0x00020000, + MOVEABLE = 0x00040000, + SELFVOICING = 0x00080000, + FOCUSABLE = 0x00100000, + SELECTABLE = 0x00200000, + LINKED = 0x00400000, + TRAVERSED = 0x00800000, + MULTISELECTABLE = 0x01000000, // Supports multiple selection + EXTSELECTABLE = 0x02000000, // Supports extended selection + ALERT_LOW = 0x04000000, // This information is of low priority + ALERT_MEDIUM = 0x08000000, // This information is of medium priority + ALERT_HIGH = 0x10000000, // This information is of high priority + PROTECTED = 0x20000000, // access to this is restricted + VALID = 0x3FFFFFFF, + } + + internal enum StockObject : int + { + WHITE_BRUSH = 0, + LTGRAY_BRUSH = 1, + GRAY_BRUSH = 2, + DKGRAY_BRUSH = 3, + BLACK_BRUSH = 4, + NULL_BRUSH = 5, + HOLLOW_BRUSH = NULL_BRUSH, + WHITE_PEN = 6, + BLACK_PEN = 7, + NULL_PEN = 8, + SYSTEM_FONT = 13, + DEFAULT_PALETTE = 15, + } + + /// + /// CS_* + /// + [Flags] + internal enum CS : uint + { + VREDRAW = 0x0001, + HREDRAW = 0x0002, + DBLCLKS = 0x0008, + OWNDC = 0x0020, + CLASSDC = 0x0040, + PARENTDC = 0x0080, + NOCLOSE = 0x0200, + SAVEBITS = 0x0800, + BYTEALIGNCLIENT = 0x1000, + BYTEALIGNWINDOW = 0x2000, + GLOBALCLASS = 0x4000, + IME = 0x00010000, + DROPSHADOW = 0x00020000 + } + + /// + /// WindowStyle values, WS_* + /// + [Flags] + internal enum WS : uint + { + OVERLAPPED = 0x00000000, + POPUP = 0x80000000, + CHILD = 0x40000000, + MINIMIZE = 0x20000000, + VISIBLE = 0x10000000, + DISABLED = 0x08000000, + CLIPSIBLINGS = 0x04000000, + CLIPCHILDREN = 0x02000000, + MAXIMIZE = 0x01000000, + BORDER = 0x00800000, + DLGFRAME = 0x00400000, + VSCROLL = 0x00200000, + HSCROLL = 0x00100000, + SYSMENU = 0x00080000, + THICKFRAME = 0x00040000, + GROUP = 0x00020000, + TABSTOP = 0x00010000, + + MINIMIZEBOX = 0x00020000, + MAXIMIZEBOX = 0x00010000, + + CAPTION = BORDER | DLGFRAME, + TILED = OVERLAPPED, + ICONIC = MINIMIZE, + SIZEBOX = THICKFRAME, + TILEDWINDOW = OVERLAPPEDWINDOW, + + OVERLAPPEDWINDOW = OVERLAPPED | CAPTION | SYSMENU | THICKFRAME | MINIMIZEBOX | MAXIMIZEBOX, + POPUPWINDOW = POPUP | BORDER | SYSMENU, + CHILDWINDOW = CHILD, + } + + /// + /// Window message values, WM_* + /// + internal enum WM + { + NULL = 0x0000, + CREATE = 0x0001, + DESTROY = 0x0002, + MOVE = 0x0003, + SIZE = 0x0005, + ACTIVATE = 0x0006, + SETFOCUS = 0x0007, + KILLFOCUS = 0x0008, + ENABLE = 0x000A, + SETREDRAW = 0x000B, + SETTEXT = 0x000C, + GETTEXT = 0x000D, + GETTEXTLENGTH = 0x000E, + PAINT = 0x000F, + CLOSE = 0x0010, + QUERYENDSESSION = 0x0011, + QUIT = 0x0012, + QUERYOPEN = 0x0013, + ERASEBKGND = 0x0014, + SYSCOLORCHANGE = 0x0015, + SHOWWINDOW = 0x0018, + CTLCOLOR = 0x0019, + WININICHANGE = 0x001A, + SETTINGCHANGE = 0x001A, + ACTIVATEAPP = 0x001C, + SETCURSOR = 0x0020, + MOUSEACTIVATE = 0x0021, + CHILDACTIVATE = 0x0022, + QUEUESYNC = 0x0023, + GETMINMAXINFO = 0x0024, + + WINDOWPOSCHANGING = 0x0046, + WINDOWPOSCHANGED = 0x0047, + + CONTEXTMENU = 0x007B, + STYLECHANGING = 0x007C, + STYLECHANGED = 0x007D, + DISPLAYCHANGE = 0x007E, + GETICON = 0x007F, + SETICON = 0x0080, + NCCREATE = 0x0081, + NCDESTROY = 0x0082, + NCCALCSIZE = 0x0083, + NCHITTEST = 0x0084, + NCPAINT = 0x0085, + NCACTIVATE = 0x0086, + GETDLGCODE = 0x0087, + SYNCPAINT = 0x0088, + NCMOUSEMOVE = 0x00A0, + NCLBUTTONDOWN = 0x00A1, + NCLBUTTONUP = 0x00A2, + NCLBUTTONDBLCLK = 0x00A3, + NCRBUTTONDOWN = 0x00A4, + NCRBUTTONUP = 0x00A5, + NCRBUTTONDBLCLK = 0x00A6, + NCMBUTTONDOWN = 0x00A7, + NCMBUTTONUP = 0x00A8, + NCMBUTTONDBLCLK = 0x00A9, + + SYSKEYDOWN = 0x0104, + SYSKEYUP = 0x0105, + SYSCHAR = 0x0106, + SYSDEADCHAR = 0x0107, + COMMAND = 0x0111, + SYSCOMMAND = 0x0112, + + MOUSEMOVE = 0x0200, + LBUTTONDOWN = 0x0201, + LBUTTONUP = 0x0202, + LBUTTONDBLCLK = 0x0203, + RBUTTONDOWN = 0x0204, + RBUTTONUP = 0x0205, + RBUTTONDBLCLK = 0x0206, + MBUTTONDOWN = 0x0207, + MBUTTONUP = 0x0208, + MBUTTONDBLCLK = 0x0209, + MOUSEWHEEL = 0x020A, + XBUTTONDOWN = 0x020B, + XBUTTONUP = 0x020C, + XBUTTONDBLCLK = 0x020D, + MOUSEHWHEEL = 0x020E, + PARENTNOTIFY = 0x0210, + + CAPTURECHANGED = 0x0215, + POWERBROADCAST = 0x0218, + DEVICECHANGE = 0x0219, + + ENTERSIZEMOVE = 0x0231, + EXITSIZEMOVE = 0x0232, + + IME_SETCONTEXT = 0x0281, + IME_NOTIFY = 0x0282, + IME_CONTROL = 0x0283, + IME_COMPOSITIONFULL = 0x0284, + IME_SELECT = 0x0285, + IME_CHAR = 0x0286, + IME_REQUEST = 0x0288, + IME_KEYDOWN = 0x0290, + IME_KEYUP = 0x0291, + + NCMOUSELEAVE = 0x02A2, + + TABLET_DEFBASE = 0x02C0, + //WM_TABLET_MAXOFFSET = 0x20, + + TABLET_ADDED = TABLET_DEFBASE + 8, + TABLET_DELETED = TABLET_DEFBASE + 9, + TABLET_FLICK = TABLET_DEFBASE + 11, + TABLET_QUERYSYSTEMGESTURESTATUS = TABLET_DEFBASE + 12, + + CUT = 0x0300, + COPY = 0x0301, + PASTE = 0x0302, + CLEAR = 0x0303, + UNDO = 0x0304, + RENDERFORMAT = 0x0305, + RENDERALLFORMATS = 0x0306, + DESTROYCLIPBOARD = 0x0307, + DRAWCLIPBOARD = 0x0308, + PAINTCLIPBOARD = 0x0309, + VSCROLLCLIPBOARD = 0x030A, + SIZECLIPBOARD = 0x030B, + ASKCBFORMATNAME = 0x030C, + CHANGECBCHAIN = 0x030D, + HSCROLLCLIPBOARD = 0x030E, + QUERYNEWPALETTE = 0x030F, + PALETTEISCHANGING = 0x0310, + PALETTECHANGED = 0x0311, + HOTKEY = 0x0312, + PRINT = 0x0317, + PRINTCLIENT = 0x0318, + APPCOMMAND = 0x0319, + THEMECHANGED = 0x031A, + + DWMCOMPOSITIONCHANGED = 0x031E, + DWMNCRENDERINGCHANGED = 0x031F, + DWMCOLORIZATIONCOLORCHANGED = 0x0320, + DWMWINDOWMAXIMIZEDCHANGE = 0x0321, + + GETTITLEBARINFOEX = 0x033F, + #region Windows 7 + DWMSENDICONICTHUMBNAIL = 0x0323, + DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326, + #endregion - /// - /// GetWindowLongPtr values, GWL_* + USER = 0x0400, + + // This is the hard-coded message value used by WinForms for Shell_NotifyIcon. + // It's relatively safe to reuse. + TRAYMOUSEMESSAGE = 0x800, //WM_USER + 1024 + APP = 0x8000, + } + + /// + /// Window style extended values, WS_EX_* + /// + [Flags] + internal enum WS_EX : uint + { + None = 0, + DLGMODALFRAME = 0x00000001, + NOPARENTNOTIFY = 0x00000004, + TOPMOST = 0x00000008, + ACCEPTFILES = 0x00000010, + TRANSPARENT = 0x00000020, + MDICHILD = 0x00000040, + TOOLWINDOW = 0x00000080, + WINDOWEDGE = 0x00000100, + CLIENTEDGE = 0x00000200, + CONTEXTHELP = 0x00000400, + RIGHT = 0x00001000, + LEFT = 0x00000000, + RTLREADING = 0x00002000, + LTRREADING = 0x00000000, + LEFTSCROLLBAR = 0x00004000, + RIGHTSCROLLBAR = 0x00000000, + CONTROLPARENT = 0x00010000, + STATICEDGE = 0x00020000, + APPWINDOW = 0x00040000, + LAYERED = 0x00080000, + NOINHERITLAYOUT = 0x00100000, // Disable inheritence of mirroring by children + LAYOUTRTL = 0x00400000, // Right to left mirroring + COMPOSITED = 0x02000000, + NOACTIVATE = 0x08000000, + OVERLAPPEDWINDOW = ( WINDOWEDGE | CLIENTEDGE ), + PALETTEWINDOW = ( WINDOWEDGE | TOOLWINDOW | TOPMOST ), + } + + /// + /// GetDeviceCaps nIndex values. + /// + internal enum DeviceCap + { + /// Number of bits per pixel /// - internal enum GWL - { - WNDPROC = (-4), - HINSTANCE = (-6), - HWNDPARENT = (-8), - STYLE = (-16), - EXSTYLE = (-20), - USERDATA = (-21), - ID = (-12) - } - + BITSPIXEL = 12, /// - /// SystemMetrics. SM_* + /// Number of planes /// - internal enum SM - { - CXSCREEN = 0, - CYSCREEN = 1, - CXVSCROLL = 2, - CYHSCROLL = 3, - CYCAPTION = 4, - CXBORDER = 5, - CYBORDER = 6, - CXFIXEDFRAME = 7, - CYFIXEDFRAME = 8, - CYVTHUMB = 9, - CXHTHUMB = 10, - CXICON = 11, - CYICON = 12, - CXCURSOR = 13, - CYCURSOR = 14, - CYMENU = 15, - CXFULLSCREEN = 16, - CYFULLSCREEN = 17, - CYKANJIWINDOW = 18, - MOUSEPRESENT = 19, - CYVSCROLL = 20, - CXHSCROLL = 21, - DEBUG = 22, - SWAPBUTTON = 23, - CXMIN = 28, - CYMIN = 29, - CXSIZE = 30, - CYSIZE = 31, - CXFRAME = 32, - CXSIZEFRAME = CXFRAME, - CYFRAME = 33, - CYSIZEFRAME = CYFRAME, - CXMINTRACK = 34, - CYMINTRACK = 35, - CXDOUBLECLK = 36, - CYDOUBLECLK = 37, - CXICONSPACING = 38, - CYICONSPACING = 39, - MENUDROPALIGNMENT = 40, - PENWINDOWS = 41, - DBCSENABLED = 42, - CMOUSEBUTTONS = 43, - SECURE = 44, - CXEDGE = 45, - CYEDGE = 46, - CXMINSPACING = 47, - CYMINSPACING = 48, - CXSMICON = 49, - CYSMICON = 50, - CYSMCAPTION = 51, - CXSMSIZE = 52, - CYSMSIZE = 53, - CXMENUSIZE = 54, - CYMENUSIZE = 55, - ARRANGE = 56, - CXMINIMIZED = 57, - CYMINIMIZED = 58, - CXMAXTRACK = 59, - CYMAXTRACK = 60, - CXMAXIMIZED = 61, - CYMAXIMIZED = 62, - NETWORK = 63, - CLEANBOOT = 67, - CXDRAG = 68, - CYDRAG = 69, - SHOWSOUNDS = 70, - CXMENUCHECK = 71, - CYMENUCHECK = 72, - SLOWMACHINE = 73, - MIDEASTENABLED = 74, - MOUSEWHEELPRESENT = 75, - XVIRTUALSCREEN = 76, - YVIRTUALSCREEN = 77, - CXVIRTUALSCREEN = 78, - CYVIRTUALSCREEN = 79, - CMONITORS = 80, - SAMEDISPLAYFORMAT = 81, - IMMENABLED = 82, - CXFOCUSBORDER = 83, - CYFOCUSBORDER = 84, - TABLETPC = 86, - MEDIACENTER = 87, - REMOTESESSION = 0x1000, - REMOTECONTROL = 0x2001, - } - + PLANES = 14, /// - /// SystemParameterInfo values, SPI_* + /// Logical pixels inch in X /// - internal enum SPI - { - GETBEEP = 0x0001, - SETBEEP = 0x0002, - GETMOUSE = 0x0003, - SETMOUSE = 0x0004, - GETBORDER = 0x0005, - SETBORDER = 0x0006, - GETKEYBOARDSPEED = 0x000A, - SETKEYBOARDSPEED = 0x000B, - LANGDRIVER = 0x000C, - ICONHORIZONTALSPACING = 0x000D, - GETSCREENSAVETIMEOUT = 0x000E, - SETSCREENSAVETIMEOUT = 0x000F, - GETSCREENSAVEACTIVE = 0x0010, - SETSCREENSAVEACTIVE = 0x0011, - GETGRIDGRANULARITY = 0x0012, - SETGRIDGRANULARITY = 0x0013, - SETDESKWALLPAPER = 0x0014, - SETDESKPATTERN = 0x0015, - GETKEYBOARDDELAY = 0x0016, - SETKEYBOARDDELAY = 0x0017, - ICONVERTICALSPACING = 0x0018, - GETICONTITLEWRAP = 0x0019, - SETICONTITLEWRAP = 0x001A, - GETMENUDROPALIGNMENT = 0x001B, - SETMENUDROPALIGNMENT = 0x001C, - SETDOUBLECLKWIDTH = 0x001D, - SETDOUBLECLKHEIGHT = 0x001E, - GETICONTITLELOGFONT = 0x001F, - SETDOUBLECLICKTIME = 0x0020, - SETMOUSEBUTTONSWAP = 0x0021, - SETICONTITLELOGFONT = 0x0022, - GETFASTTASKSWITCH = 0x0023, - SETFASTTASKSWITCH = 0x0024, - - SETDRAGFULLWINDOWS = 0x0025, - GETDRAGFULLWINDOWS = 0x0026, - GETNONCLIENTMETRICS = 0x0029, - SETNONCLIENTMETRICS = 0x002A, - GETMINIMIZEDMETRICS = 0x002B, - SETMINIMIZEDMETRICS = 0x002C, - GETICONMETRICS = 0x002D, - SETICONMETRICS = 0x002E, - SETWORKAREA = 0x002F, - GETWORKAREA = 0x0030, - SETPENWINDOWS = 0x0031, - GETHIGHCONTRAST = 0x0042, - SETHIGHCONTRAST = 0x0043, - GETKEYBOARDPREF = 0x0044, - SETKEYBOARDPREF = 0x0045, - GETSCREENREADER = 0x0046, - SETSCREENREADER = 0x0047, - GETANIMATION = 0x0048, - SETANIMATION = 0x0049, - GETFONTSMOOTHING = 0x004A, - SETFONTSMOOTHING = 0x004B, - SETDRAGWIDTH = 0x004C, - SETDRAGHEIGHT = 0x004D, - SETHANDHELD = 0x004E, - GETLOWPOWERTIMEOUT = 0x004F, - GETPOWEROFFTIMEOUT = 0x0050, - SETLOWPOWERTIMEOUT = 0x0051, - SETPOWEROFFTIMEOUT = 0x0052, - GETLOWPOWERACTIVE = 0x0053, - GETPOWEROFFACTIVE = 0x0054, - SETLOWPOWERACTIVE = 0x0055, - SETPOWEROFFACTIVE = 0x0056, - SETCURSORS = 0x0057, - SETICONS = 0x0058, - GETDEFAULTINPUTLANG = 0x0059, - SETDEFAULTINPUTLANG = 0x005A, - SETLANGTOGGLE = 0x005B, - GETWINDOWSEXTENSION = 0x005C, - SETMOUSETRAILS = 0x005D, - GETMOUSETRAILS = 0x005E, - SETSCREENSAVERRUNNING = 0x0061, - SCREENSAVERRUNNING = SETSCREENSAVERRUNNING, - GETFILTERKEYS = 0x0032, - SETFILTERKEYS = 0x0033, - GETTOGGLEKEYS = 0x0034, - SETTOGGLEKEYS = 0x0035, - GETMOUSEKEYS = 0x0036, - SETMOUSEKEYS = 0x0037, - GETSHOWSOUNDS = 0x0038, - SETSHOWSOUNDS = 0x0039, - GETSTICKYKEYS = 0x003A, - SETSTICKYKEYS = 0x003B, - GETACCESSTIMEOUT = 0x003C, - SETACCESSTIMEOUT = 0x003D, - - GETSERIALKEYS = 0x003E, - SETSERIALKEYS = 0x003F, - GETSOUNDSENTRY = 0x0040, - SETSOUNDSENTRY = 0x0041, - GETSNAPTODEFBUTTON = 0x005F, - SETSNAPTODEFBUTTON = 0x0060, - GETMOUSEHOVERWIDTH = 0x0062, - SETMOUSEHOVERWIDTH = 0x0063, - GETMOUSEHOVERHEIGHT = 0x0064, - SETMOUSEHOVERHEIGHT = 0x0065, - GETMOUSEHOVERTIME = 0x0066, - SETMOUSEHOVERTIME = 0x0067, - GETWHEELSCROLLLINES = 0x0068, - SETWHEELSCROLLLINES = 0x0069, - GETMENUSHOWDELAY = 0x006A, - SETMENUSHOWDELAY = 0x006B, - - GETWHEELSCROLLCHARS = 0x006C, - SETWHEELSCROLLCHARS = 0x006D, - - GETSHOWIMEUI = 0x006E, - SETSHOWIMEUI = 0x006F, - - GETMOUSESPEED = 0x0070, - SETMOUSESPEED = 0x0071, - GETSCREENSAVERRUNNING = 0x0072, - GETDESKWALLPAPER = 0x0073, - - GETAUDIODESCRIPTION = 0x0074, - SETAUDIODESCRIPTION = 0x0075, - - GETSCREENSAVESECURE = 0x0076, - SETSCREENSAVESECURE = 0x0077, - - GETHUNGAPPTIMEOUT = 0x0078, - SETHUNGAPPTIMEOUT = 0x0079, - GETWAITTOKILLTIMEOUT = 0x007A, - SETWAITTOKILLTIMEOUT = 0x007B, - GETWAITTOKILLSERVICETIMEOUT = 0x007C, - SETWAITTOKILLSERVICETIMEOUT = 0x007D, - GETMOUSEDOCKTHRESHOLD = 0x007E, - SETMOUSEDOCKTHRESHOLD = 0x007F, - GETPENDOCKTHRESHOLD = 0x0080, - SETPENDOCKTHRESHOLD = 0x0081, - GETWINARRANGING = 0x0082, - SETWINARRANGING = 0x0083, - GETMOUSEDRAGOUTTHRESHOLD = 0x0084, - SETMOUSEDRAGOUTTHRESHOLD = 0x0085, - GETPENDRAGOUTTHRESHOLD = 0x0086, - SETPENDRAGOUTTHRESHOLD = 0x0087, - GETMOUSESIDEMOVETHRESHOLD = 0x0088, - SETMOUSESIDEMOVETHRESHOLD = 0x0089, - GETPENSIDEMOVETHRESHOLD = 0x008A, - SETPENSIDEMOVETHRESHOLD = 0x008B, - GETDRAGFROMMAXIMIZE = 0x008C, - SETDRAGFROMMAXIMIZE = 0x008D, - GETSNAPSIZING = 0x008E, - SETSNAPSIZING = 0x008F, - GETDOCKMOVING = 0x0090, - SETDOCKMOVING = 0x0091, - - GETACTIVEWINDOWTRACKING = 0x1000, - SETACTIVEWINDOWTRACKING = 0x1001, - GETMENUANIMATION = 0x1002, - SETMENUANIMATION = 0x1003, - GETCOMBOBOXANIMATION = 0x1004, - SETCOMBOBOXANIMATION = 0x1005, - GETLISTBOXSMOOTHSCROLLING = 0x1006, - SETLISTBOXSMOOTHSCROLLING = 0x1007, - GETGRADIENTCAPTIONS = 0x1008, - SETGRADIENTCAPTIONS = 0x1009, - GETKEYBOARDCUES = 0x100A, - SETKEYBOARDCUES = 0x100B, - GETMENUUNDERLINES = GETKEYBOARDCUES, - SETMENUUNDERLINES = SETKEYBOARDCUES, - GETACTIVEWNDTRKZORDER = 0x100C, - SETACTIVEWNDTRKZORDER = 0x100D, - GETHOTTRACKING = 0x100E, - SETHOTTRACKING = 0x100F, - GETMENUFADE = 0x1012, - SETMENUFADE = 0x1013, - GETSELECTIONFADE = 0x1014, - SETSELECTIONFADE = 0x1015, - GETTOOLTIPANIMATION = 0x1016, - SETTOOLTIPANIMATION = 0x1017, - GETTOOLTIPFADE = 0x1018, - SETTOOLTIPFADE = 0x1019, - GETCURSORSHADOW = 0x101A, - SETCURSORSHADOW = 0x101B, - GETMOUSESONAR = 0x101C, - SETMOUSESONAR = 0x101D, - GETMOUSECLICKLOCK = 0x101E, - SETMOUSECLICKLOCK = 0x101F, - GETMOUSEVANISH = 0x1020, - SETMOUSEVANISH = 0x1021, - GETFLATMENU = 0x1022, - SETFLATMENU = 0x1023, - GETDROPSHADOW = 0x1024, - SETDROPSHADOW = 0x1025, - GETBLOCKSENDINPUTRESETS = 0x1026, - SETBLOCKSENDINPUTRESETS = 0x1027, - - GETUIEFFECTS = 0x103E, - SETUIEFFECTS = 0x103F, - - GETDISABLEOVERLAPPEDCONTENT = 0x1040, - SETDISABLEOVERLAPPEDCONTENT = 0x1041, - GETCLIENTAREAANIMATION = 0x1042, - SETCLIENTAREAANIMATION = 0x1043, - GETCLEARTYPE = 0x1048, - SETCLEARTYPE = 0x1049, - GETSPEECHRECOGNITION = 0x104A, - SETSPEECHRECOGNITION = 0x104B, - - GETFOREGROUNDLOCKTIMEOUT = 0x2000, - SETFOREGROUNDLOCKTIMEOUT = 0x2001, - GETACTIVEWNDTRKTIMEOUT = 0x2002, - SETACTIVEWNDTRKTIMEOUT = 0x2003, - GETFOREGROUNDFLASHCOUNT = 0x2004, - SETFOREGROUNDFLASHCOUNT = 0x2005, - GETCARETWIDTH = 0x2006, - SETCARETWIDTH = 0x2007, - - GETMOUSECLICKLOCKTIME = 0x2008, - SETMOUSECLICKLOCKTIME = 0x2009, - GETFONTSMOOTHINGTYPE = 0x200A, - SETFONTSMOOTHINGTYPE = 0x200B, - - GETFONTSMOOTHINGCONTRAST = 0x200C, - SETFONTSMOOTHINGCONTRAST = 0x200D, - - GETFOCUSBORDERWIDTH = 0x200E, - SETFOCUSBORDERWIDTH = 0x200F, - GETFOCUSBORDERHEIGHT = 0x2010, - SETFOCUSBORDERHEIGHT = 0x2011, - - GETFONTSMOOTHINGORIENTATION = 0x2012, - SETFONTSMOOTHINGORIENTATION = 0x2013, - - GETMINIMUMHITRADIUS = 0x2014, - SETMINIMUMHITRADIUS = 0x2015, - GETMESSAGEDURATION = 0x2016, - SETMESSAGEDURATION = 0x2017, - } - + LOGPIXELSX = 88, /// - /// SystemParameterInfo flag values, SPIF_* + /// Logical pixels inch in Y /// - [Flags] - internal enum SPIF - { - None = 0, - UPDATEINIFILE = 0x01, - SENDCHANGE = 0x02, - SENDWININICHANGE = SENDCHANGE, - } - - [Flags] - internal enum STATE_SYSTEM - { - UNAVAILABLE = 0x00000001, // Disabled - SELECTED = 0x00000002, - FOCUSED = 0x00000004, - PRESSED = 0x00000008, - CHECKED = 0x00000010, - MIXED = 0x00000020, // 3-state checkbox or toolbar button - INDETERMINATE = MIXED, - READONLY = 0x00000040, - HOTTRACKED = 0x00000080, - DEFAULT = 0x00000100, - EXPANDED = 0x00000200, - COLLAPSED = 0x00000400, - BUSY = 0x00000800, - FLOATING = 0x00001000, // Children "owned" not "contained" by parent - MARQUEED = 0x00002000, - ANIMATED = 0x00004000, - INVISIBLE = 0x00008000, - OFFSCREEN = 0x00010000, - SIZEABLE = 0x00020000, - MOVEABLE = 0x00040000, - SELFVOICING = 0x00080000, - FOCUSABLE = 0x00100000, - SELECTABLE = 0x00200000, - LINKED = 0x00400000, - TRAVERSED = 0x00800000, - MULTISELECTABLE = 0x01000000, // Supports multiple selection - EXTSELECTABLE = 0x02000000, // Supports extended selection - ALERT_LOW = 0x04000000, // This information is of low priority - ALERT_MEDIUM = 0x08000000, // This information is of medium priority - ALERT_HIGH = 0x10000000, // This information is of high priority - PROTECTED = 0x20000000, // access to this is restricted - VALID = 0x3FFFFFFF, - } - - internal enum StockObject : int - { - WHITE_BRUSH = 0, - LTGRAY_BRUSH = 1, - GRAY_BRUSH = 2, - DKGRAY_BRUSH = 3, - BLACK_BRUSH = 4, - NULL_BRUSH = 5, - HOLLOW_BRUSH = NULL_BRUSH, - WHITE_PEN = 6, - BLACK_PEN = 7, - NULL_PEN = 8, - SYSTEM_FONT = 13, - DEFAULT_PALETTE = 15, - } - + LOGPIXELSY = 90, + } + + internal enum FO : int + { + MOVE = 0x0001, + COPY = 0x0002, + DELETE = 0x0003, + RENAME = 0x0004, + } + + /// + /// "FILEOP_FLAGS", FOF_*. + /// + internal enum FOF : ushort + { + MULTIDESTFILES = 0x0001, + CONFIRMMOUSE = 0x0002, + SILENT = 0x0004, + RENAMEONCOLLISION = 0x0008, + NOCONFIRMATION = 0x0010, + WANTMAPPINGHANDLE = 0x0020, + ALLOWUNDO = 0x0040, + FILESONLY = 0x0080, + SIMPLEPROGRESS = 0x0100, + NOCONFIRMMKDIR = 0x0200, + NOERRORUI = 0x0400, + NOCOPYSECURITYATTRIBS = 0x0800, + NORECURSION = 0x1000, + NO_CONNECTED_ELEMENTS = 0x2000, + WANTNUKEWARNING = 0x4000, + NORECURSEREPARSE = 0x8000, + } + + /// + /// EnableMenuItem uEnable values, MF_* + /// + [Flags] + internal enum MF : uint + { /// - /// CS_* + /// Possible return value for EnableMenuItem /// - [Flags] - internal enum CS : uint - { - VREDRAW = 0x0001, - HREDRAW = 0x0002, - DBLCLKS = 0x0008, - OWNDC = 0x0020, - CLASSDC = 0x0040, - PARENTDC = 0x0080, - NOCLOSE = 0x0200, - SAVEBITS = 0x0800, - BYTEALIGNCLIENT = 0x1000, - BYTEALIGNWINDOW = 0x2000, - GLOBALCLASS = 0x4000, - IME = 0x00010000, - DROPSHADOW = 0x00020000 - } - + DOES_NOT_EXIST = unchecked(( uint )-1), + ENABLED = 0, + BYCOMMAND = 0, + GRAYED = 1, + DISABLED = 2, + } + + /// Specifies the type of visual style attribute to set on a window. + internal enum WINDOWTHEMEATTRIBUTETYPE : uint + { + /// Non-client area window attributes will be set. + WTA_NONCLIENT = 1, + } + + /// + /// DWMFLIP3DWINDOWPOLICY. DWMFLIP3D_* + /// + internal enum DWMFLIP3D + { + DEFAULT, + EXCLUDEBELOW, + EXCLUDEABOVE, + //LAST + } + + /// + /// DWMNCRENDERINGPOLICY. DWMNCRP_* + /// + internal enum DWMNCRP + { + USEWINDOWSTYLE, + DISABLED, + ENABLED, + //LAST + } + + /// + /// DWMWINDOWATTRIBUTE. DWMWA_* + /// + internal enum DWMWA + { + NCRENDERING_ENABLED = 1, + NCRENDERING_POLICY, + TRANSITIONS_FORCEDISABLED, + ALLOW_NCPAINT, + CAPTION_BUTTON_BOUNDS, + NONCLIENT_RTL_LAYOUT, + FORCE_ICONIC_REPRESENTATION, + FLIP3D_POLICY, + EXTENDED_FRAME_BOUNDS, + + // New to Windows 7: + + HAS_ICONIC_BITMAP, + DISALLOW_PEEK, + EXCLUDED_FROM_PEEK, + + // LAST + } + + /// + /// WindowThemeNonClientAttributes + /// + [Flags] + internal enum WTNCA : uint + { + /// Prevents the window caption from being drawn. + NODRAWCAPTION = 0x00000001, + /// Prevents the system icon from being drawn. + NODRAWICON = 0x00000002, + /// Prevents the system icon menu from appearing. + NOSYSMENU = 0x00000004, + /// Prevents mirroring of the question mark, even in right-to-left (RTL) layout. + NOMIRRORHELP = 0x00000008, + /// A mask that contains all the valid bits. + VALIDBITS = NODRAWCAPTION | NODRAWICON | NOMIRRORHELP | NOSYSMENU, + } + + /// + /// SetWindowPos options + /// + [Flags] + internal enum SWP + { + ASYNCWINDOWPOS = 0x4000, + DEFERERASE = 0x2000, + DRAWFRAME = 0x0020, + FRAMECHANGED = 0x0020, + HIDEWINDOW = 0x0080, + NOACTIVATE = 0x0010, + NOCOPYBITS = 0x0100, + NOMOVE = 0x0002, + NOOWNERZORDER = 0x0200, + NOREDRAW = 0x0008, + NOREPOSITION = 0x0200, + NOSENDCHANGING = 0x0400, + NOSIZE = 0x0001, + NOZORDER = 0x0004, + SHOWWINDOW = 0x0040, + } + + /// + /// ShowWindow options + /// + internal enum SW + { + HIDE = 0, + SHOWNORMAL = 1, + NORMAL = 1, + SHOWMINIMIZED = 2, + SHOWMAXIMIZED = 3, + MAXIMIZE = 3, + SHOWNOACTIVATE = 4, + SHOW = 5, + MINIMIZE = 6, + SHOWMINNOACTIVE = 7, + SHOWNA = 8, + RESTORE = 9, + SHOWDEFAULT = 10, + FORCEMINIMIZE = 11, + } + + internal enum SC + { + SIZE = 0xF000, + MOVE = 0xF010, + MINIMIZE = 0xF020, + MAXIMIZE = 0xF030, + NEXTWINDOW = 0xF040, + PREVWINDOW = 0xF050, + CLOSE = 0xF060, + VSCROLL = 0xF070, + HSCROLL = 0xF080, + MOUSEMENU = 0xF090, + KEYMENU = 0xF100, + ARRANGE = 0xF110, + RESTORE = 0xF120, + TASKLIST = 0xF130, + SCREENSAVE = 0xF140, + HOTKEY = 0xF150, + DEFAULT = 0xF160, + MONITORPOWER = 0xF170, + CONTEXTHELP = 0xF180, + SEPARATOR = 0xF00F, /// - /// WindowStyle values, WS_* + /// SCF_ISSECURE /// - [Flags] - internal enum WS : uint - { - OVERLAPPED = 0x00000000, - POPUP = 0x80000000, - CHILD = 0x40000000, - MINIMIZE = 0x20000000, - VISIBLE = 0x10000000, - DISABLED = 0x08000000, - CLIPSIBLINGS = 0x04000000, - CLIPCHILDREN = 0x02000000, - MAXIMIZE = 0x01000000, - BORDER = 0x00800000, - DLGFRAME = 0x00400000, - VSCROLL = 0x00200000, - HSCROLL = 0x00100000, - SYSMENU = 0x00080000, - THICKFRAME = 0x00040000, - GROUP = 0x00020000, - TABSTOP = 0x00010000, - - MINIMIZEBOX = 0x00020000, - MAXIMIZEBOX = 0x00010000, - - CAPTION = BORDER | DLGFRAME, - TILED = OVERLAPPED, - ICONIC = MINIMIZE, - SIZEBOX = THICKFRAME, - TILEDWINDOW = OVERLAPPEDWINDOW, - - OVERLAPPEDWINDOW = OVERLAPPED | CAPTION | SYSMENU | THICKFRAME | MINIMIZEBOX | MAXIMIZEBOX, - POPUPWINDOW = POPUP | BORDER | SYSMENU, - CHILDWINDOW = CHILD, - } + F_ISSECURE = 0x00000001, + ICON = MINIMIZE, + ZOOM = MAXIMIZE, + } + + /// + /// GDI+ Status codes + /// + internal enum Status + { + Ok = 0, + GenericError = 1, + InvalidParameter = 2, + OutOfMemory = 3, + ObjectBusy = 4, + InsufficientBuffer = 5, + NotImplemented = 6, + Win32Error = 7, + WrongState = 8, + Aborted = 9, + FileNotFound = 10, + ValueOverflow = 11, + AccessDenied = 12, + UnknownImageFormat = 13, + FontFamilyNotFound = 14, + FontStyleNotFound = 15, + NotTrueTypeFont = 16, + UnsupportedGdiplusVersion = 17, + GdiplusNotInitialized = 18, + PropertyNotFound = 19, + PropertyNotSupported = 20, + ProfileNotFound = 21, + } + + internal enum MOUSEEVENTF : int + { + //mouse event constants + LEFTDOWN = 2, + LEFTUP = 4 + } + + /// + /// MSGFLT_*. New in Vista. Realiased in Windows 7. + /// + internal enum MSGFLT + { + // Win7 versions of this enum: + RESET = 0, + ALLOW = 1, + DISALLOW = 2, + + // Vista versions of this enum: + // ADD = 1, + // REMOVE = 2, + } + + internal enum MSGFLTINFO + { + NONE = 0, + ALREADYALLOWED_FORWND = 1, + ALREADYDISALLOWED_FORWND = 2, + ALLOWED_HIGHER = 3, + } + + internal enum INPUT_TYPE : uint + { + MOUSE = 0, + } + + /// + /// Shell_NotifyIcon messages. NIM_* + /// + internal enum NIM : uint + { + ADD = 0, + MODIFY = 1, + DELETE = 2, + SETFOCUS = 3, + SETVERSION = 4, + } + + /// + /// SHAddToRecentDocuments flags. SHARD_* + /// + internal enum SHARD + { + PIDL = 0x00000001, + PATHA = 0x00000002, + PATHW = 0x00000003, + APPIDINFO = 0x00000004, // indicates the data type is a pointer to a SHARDAPPIDINFO structure + APPIDINFOIDLIST = 0x00000005, // indicates the data type is a pointer to a SHARDAPPIDINFOIDLIST structure + LINK = 0x00000006, // indicates the data type is a pointer to an IShellLink instance + APPIDINFOLINK = 0x00000007, // indicates the data type is a pointer to a SHARDAPPIDINFOLINK structure + } + + [Flags] + enum SLGP + { + SHORTPATH = 0x1, + UNCPRIORITY = 0x2, + RAWPATH = 0x4 + } + + /// + /// Shell_NotifyIcon flags. NIF_* + /// + [Flags] + internal enum NIF : uint + { + MESSAGE = 0x0001, + ICON = 0x0002, + TIP = 0x0004, + STATE = 0x0008, + INFO = 0x0010, + GUID = 0x0020, /// - /// Window message values, WM_* + /// Vista only. /// - internal enum WM - { - NULL = 0x0000, - CREATE = 0x0001, - DESTROY = 0x0002, - MOVE = 0x0003, - SIZE = 0x0005, - ACTIVATE = 0x0006, - SETFOCUS = 0x0007, - KILLFOCUS = 0x0008, - ENABLE = 0x000A, - SETREDRAW = 0x000B, - SETTEXT = 0x000C, - GETTEXT = 0x000D, - GETTEXTLENGTH = 0x000E, - PAINT = 0x000F, - CLOSE = 0x0010, - QUERYENDSESSION = 0x0011, - QUIT = 0x0012, - QUERYOPEN = 0x0013, - ERASEBKGND = 0x0014, - SYSCOLORCHANGE = 0x0015, - SHOWWINDOW = 0x0018, - CTLCOLOR = 0x0019, - WININICHANGE = 0x001A, - SETTINGCHANGE = 0x001A, - ACTIVATEAPP = 0x001C, - SETCURSOR = 0x0020, - MOUSEACTIVATE = 0x0021, - CHILDACTIVATE = 0x0022, - QUEUESYNC = 0x0023, - GETMINMAXINFO = 0x0024, - - WINDOWPOSCHANGING = 0x0046, - WINDOWPOSCHANGED = 0x0047, - - CONTEXTMENU = 0x007B, - STYLECHANGING = 0x007C, - STYLECHANGED = 0x007D, - DISPLAYCHANGE = 0x007E, - GETICON = 0x007F, - SETICON = 0x0080, - NCCREATE = 0x0081, - NCDESTROY = 0x0082, - NCCALCSIZE = 0x0083, - NCHITTEST = 0x0084, - NCPAINT = 0x0085, - NCACTIVATE = 0x0086, - GETDLGCODE = 0x0087, - SYNCPAINT = 0x0088, - NCMOUSEMOVE = 0x00A0, - NCLBUTTONDOWN = 0x00A1, - NCLBUTTONUP = 0x00A2, - NCLBUTTONDBLCLK = 0x00A3, - NCRBUTTONDOWN = 0x00A4, - NCRBUTTONUP = 0x00A5, - NCRBUTTONDBLCLK = 0x00A6, - NCMBUTTONDOWN = 0x00A7, - NCMBUTTONUP = 0x00A8, - NCMBUTTONDBLCLK = 0x00A9, - - SYSKEYDOWN = 0x0104, - SYSKEYUP = 0x0105, - SYSCHAR = 0x0106, - SYSDEADCHAR = 0x0107, - COMMAND = 0x0111, - SYSCOMMAND = 0x0112, - - MOUSEMOVE = 0x0200, - LBUTTONDOWN = 0x0201, - LBUTTONUP = 0x0202, - LBUTTONDBLCLK = 0x0203, - RBUTTONDOWN = 0x0204, - RBUTTONUP = 0x0205, - RBUTTONDBLCLK = 0x0206, - MBUTTONDOWN = 0x0207, - MBUTTONUP = 0x0208, - MBUTTONDBLCLK = 0x0209, - MOUSEWHEEL = 0x020A, - XBUTTONDOWN = 0x020B, - XBUTTONUP = 0x020C, - XBUTTONDBLCLK = 0x020D, - MOUSEHWHEEL = 0x020E, - PARENTNOTIFY = 0x0210, - - CAPTURECHANGED = 0x0215, - POWERBROADCAST = 0x0218, - DEVICECHANGE = 0x0219, - - ENTERSIZEMOVE = 0x0231, - EXITSIZEMOVE = 0x0232, - - IME_SETCONTEXT = 0x0281, - IME_NOTIFY = 0x0282, - IME_CONTROL = 0x0283, - IME_COMPOSITIONFULL = 0x0284, - IME_SELECT = 0x0285, - IME_CHAR = 0x0286, - IME_REQUEST = 0x0288, - IME_KEYDOWN = 0x0290, - IME_KEYUP = 0x0291, - - NCMOUSELEAVE = 0x02A2, - - TABLET_DEFBASE = 0x02C0, - //WM_TABLET_MAXOFFSET = 0x20, - - TABLET_ADDED = TABLET_DEFBASE + 8, - TABLET_DELETED = TABLET_DEFBASE + 9, - TABLET_FLICK = TABLET_DEFBASE + 11, - TABLET_QUERYSYSTEMGESTURESTATUS = TABLET_DEFBASE + 12, - - CUT = 0x0300, - COPY = 0x0301, - PASTE = 0x0302, - CLEAR = 0x0303, - UNDO = 0x0304, - RENDERFORMAT = 0x0305, - RENDERALLFORMATS = 0x0306, - DESTROYCLIPBOARD = 0x0307, - DRAWCLIPBOARD = 0x0308, - PAINTCLIPBOARD = 0x0309, - VSCROLLCLIPBOARD = 0x030A, - SIZECLIPBOARD = 0x030B, - ASKCBFORMATNAME = 0x030C, - CHANGECBCHAIN = 0x030D, - HSCROLLCLIPBOARD = 0x030E, - QUERYNEWPALETTE = 0x030F, - PALETTEISCHANGING = 0x0310, - PALETTECHANGED = 0x0311, - HOTKEY = 0x0312, - PRINT = 0x0317, - PRINTCLIENT = 0x0318, - APPCOMMAND = 0x0319, - THEMECHANGED = 0x031A, - - DWMCOMPOSITIONCHANGED = 0x031E, - DWMNCRENDERINGCHANGED = 0x031F, - DWMCOLORIZATIONCOLORCHANGED = 0x0320, - DWMWINDOWMAXIMIZEDCHANGE = 0x0321, - - GETTITLEBARINFOEX = 0x033F, - #region Windows 7 - DWMSENDICONICTHUMBNAIL = 0x0323, - DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326, - #endregion - - USER = 0x0400, - - // This is the hard-coded message value used by WinForms for Shell_NotifyIcon. - // It's relatively safe to reuse. - TRAYMOUSEMESSAGE = 0x800, //WM_USER + 1024 - APP = 0x8000, - } - + REALTIME = 0x0040, /// - /// Window style extended values, WS_EX_* + /// Vista only. /// - [Flags] - internal enum WS_EX : uint - { - None = 0, - DLGMODALFRAME = 0x00000001, - NOPARENTNOTIFY = 0x00000004, - TOPMOST = 0x00000008, - ACCEPTFILES = 0x00000010, - TRANSPARENT = 0x00000020, - MDICHILD = 0x00000040, - TOOLWINDOW = 0x00000080, - WINDOWEDGE = 0x00000100, - CLIENTEDGE = 0x00000200, - CONTEXTHELP = 0x00000400, - RIGHT = 0x00001000, - LEFT = 0x00000000, - RTLREADING = 0x00002000, - LTRREADING = 0x00000000, - LEFTSCROLLBAR = 0x00004000, - RIGHTSCROLLBAR = 0x00000000, - CONTROLPARENT = 0x00010000, - STATICEDGE = 0x00020000, - APPWINDOW = 0x00040000, - LAYERED = 0x00080000, - NOINHERITLAYOUT = 0x00100000, // Disable inheritence of mirroring by children - LAYOUTRTL = 0x00400000, // Right to left mirroring - COMPOSITED = 0x02000000, - NOACTIVATE = 0x08000000, - OVERLAPPEDWINDOW = (WINDOWEDGE | CLIENTEDGE), - PALETTEWINDOW = (WINDOWEDGE | TOOLWINDOW | TOPMOST), - } + SHOWTIP = 0x0080, + + XP_MASK = MESSAGE | ICON | STATE | INFO | GUID, + VISTA_MASK = XP_MASK | REALTIME | SHOWTIP, + } + + /// + /// Shell_NotifyIcon info flags. NIIF_* + /// + internal enum NIIF + { + NONE = 0x00000000, + INFO = 0x00000001, + WARNING = 0x00000002, + ERROR = 0x00000003, + /// XP SP2 and later. + USER = 0x00000004, + /// XP and later. + NOSOUND = 0x00000010, + /// Vista and later. + LARGE_ICON = 0x00000020, + /// Windows 7 and later + NIIF_RESPECT_QUIET_TIME = 0x00000080, + /// XP and later. Native version called NIIF_ICON_MASK. + XP_ICON_MASK = 0x0000000F, + } + + /// + /// AC_* + /// + internal enum AC : byte + { + SRC_OVER = 0, + SRC_ALPHA = 1, + } + + internal enum ULW + { + ALPHA = 2, + COLORKEY = 1, + OPAQUE = 4, + } + + internal enum WVR + { + ALIGNTOP = 0x0010, + ALIGNLEFT = 0x0020, + ALIGNBOTTOM = 0x0040, + ALIGNRIGHT = 0x0080, + HREDRAW = 0x0100, + VREDRAW = 0x0200, + VALIDRECTS = 0x0400, + REDRAW = HREDRAW | VREDRAW, + } + + #endregion + + #region SafeHandles + + internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid + { + [SecurityPermission( SecurityAction.LinkDemand, UnmanagedCode = true )] + private SafeFindHandle() : base( true ) { } + + protected override bool ReleaseHandle() + { + return NativeMethods.FindClose( handle ); + } + } + + internal sealed class SafeDC : SafeHandleZeroOrMinusOneIsInvalid + { + private static class NativeMethods + { + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll" )] + public static extern int ReleaseDC( IntPtr hWnd, IntPtr hDC ); - /// - /// GetDeviceCaps nIndex values. - /// - internal enum DeviceCap - { - /// Number of bits per pixel - /// - BITSPIXEL = 12, - /// - /// Number of planes - /// - PLANES = 14, - /// - /// Logical pixels inch in X - /// - LOGPIXELSX = 88, - /// - /// Logical pixels inch in Y - /// - LOGPIXELSY = 90, - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll" )] + public static extern SafeDC GetDC( IntPtr hwnd ); + + // Weird legacy function, documentation is unclear about how to use it... + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", CharSet = CharSet.Unicode )] + public static extern SafeDC CreateDC( [MarshalAs( UnmanagedType.LPWStr )] string lpszDriver, [MarshalAs( UnmanagedType.LPWStr )] string lpszDevice, IntPtr lpszOutput, IntPtr lpInitData ); - internal enum FO : int - { - MOVE = 0x0001, - COPY = 0x0002, - DELETE = 0x0003, - RENAME = 0x0004, - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", CharSet = CharSet.Unicode, SetLastError = true )] + public static extern SafeDC CreateCompatibleDC( IntPtr hdc ); - /// - /// "FILEOP_FLAGS", FOF_*. - /// - internal enum FOF : ushort - { - MULTIDESTFILES = 0x0001, - CONFIRMMOUSE = 0x0002, - SILENT = 0x0004, - RENAMEONCOLLISION = 0x0008, - NOCONFIRMATION = 0x0010, - WANTMAPPINGHANDLE = 0x0020, - ALLOWUNDO = 0x0040, - FILESONLY = 0x0080, - SIMPLEPROGRESS = 0x0100, - NOCONFIRMMKDIR = 0x0200, - NOERRORUI = 0x0400, - NOCOPYSECURITYATTRIBS = 0x0800, - NORECURSION = 0x1000, - NO_CONNECTED_ELEMENTS = 0x2000, - WANTNUKEWARNING = 0x4000, - NORECURSEREPARSE = 0x8000, - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool DeleteDC( IntPtr hdc ); + } + + private IntPtr? _hwnd; + private bool _created; - /// - /// EnableMenuItem uEnable values, MF_* - /// - [Flags] - internal enum MF : uint + public IntPtr Hwnd { - /// - /// Possible return value for EnableMenuItem - /// - DOES_NOT_EXIST = unchecked((uint)-1), - ENABLED = 0, - BYCOMMAND = 0, - GRAYED = 1, - DISABLED = 2, + set + { + Assert.NullableIsNull( _hwnd ); + _hwnd = value; + } } - /// Specifies the type of visual style attribute to set on a window. - internal enum WINDOWTHEMEATTRIBUTETYPE : uint - { - /// Non-client area window attributes will be set. - WTA_NONCLIENT = 1, - } + private SafeDC() : base( true ) { } - /// - /// DWMFLIP3DWINDOWPOLICY. DWMFLIP3D_* - /// - internal enum DWMFLIP3D + [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] + protected override bool ReleaseHandle() { - DEFAULT, - EXCLUDEBELOW, - EXCLUDEABOVE, - //LAST - } + if( _created ) + { + return NativeMethods.DeleteDC( handle ); + } - /// - /// DWMNCRENDERINGPOLICY. DWMNCRP_* - /// - internal enum DWMNCRP - { - USEWINDOWSTYLE, - DISABLED, - ENABLED, - //LAST + if( !_hwnd.HasValue || _hwnd.Value == IntPtr.Zero ) + { + return true; + } + + return NativeMethods.ReleaseDC( _hwnd.Value, handle ) == 1; } - /// - /// DWMWINDOWATTRIBUTE. DWMWA_* - /// - internal enum DWMWA + [SuppressMessage( "Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes" ), SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static SafeDC CreateDC( string deviceName ) { - NCRENDERING_ENABLED = 1, - NCRENDERING_POLICY, - TRANSITIONS_FORCEDISABLED, - ALLOW_NCPAINT, - CAPTION_BUTTON_BOUNDS, - NONCLIENT_RTL_LAYOUT, - FORCE_ICONIC_REPRESENTATION, - FLIP3D_POLICY, - EXTENDED_FRAME_BOUNDS, - - // New to Windows 7: + SafeDC dc = null; + try + { + // Should this really be on the driver parameter? + dc = NativeMethods.CreateDC( deviceName, null, IntPtr.Zero, IntPtr.Zero ); + } + finally + { + if( dc != null ) + { + dc._created = true; + } + } - HAS_ICONIC_BITMAP, - DISALLOW_PEEK, - EXCLUDED_FROM_PEEK, + if( dc.IsInvalid ) + { + dc.Dispose(); + throw new SystemException( "Unable to create a device context from the specified device information." ); + } - // LAST + return dc; } - /// - /// WindowThemeNonClientAttributes - /// - [Flags] - internal enum WTNCA : uint + [SuppressMessage( "Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes" ), SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static SafeDC CreateCompatibleDC( SafeDC hdc ) { - /// Prevents the window caption from being drawn. - NODRAWCAPTION = 0x00000001, - /// Prevents the system icon from being drawn. - NODRAWICON = 0x00000002, - /// Prevents the system icon menu from appearing. - NOSYSMENU = 0x00000004, - /// Prevents mirroring of the question mark, even in right-to-left (RTL) layout. - NOMIRRORHELP = 0x00000008, - /// A mask that contains all the valid bits. - VALIDBITS = NODRAWCAPTION | NODRAWICON | NOMIRRORHELP | NOSYSMENU, - } + SafeDC dc = null; + try + { + IntPtr hPtr = IntPtr.Zero; + if( hdc != null ) + { + hPtr = hdc.handle; + } + dc = NativeMethods.CreateCompatibleDC( hPtr ); + if( dc == null ) + { + HRESULT.ThrowLastError(); + } + } + finally + { + if( dc != null ) + { + dc._created = true; + } + } - /// - /// SetWindowPos options - /// - [Flags] - internal enum SWP - { - ASYNCWINDOWPOS = 0x4000, - DEFERERASE = 0x2000, - DRAWFRAME = 0x0020, - FRAMECHANGED = 0x0020, - HIDEWINDOW = 0x0080, - NOACTIVATE = 0x0010, - NOCOPYBITS = 0x0100, - NOMOVE = 0x0002, - NOOWNERZORDER = 0x0200, - NOREDRAW = 0x0008, - NOREPOSITION = 0x0200, - NOSENDCHANGING = 0x0400, - NOSIZE = 0x0001, - NOZORDER = 0x0004, - SHOWWINDOW = 0x0040, - } + if( dc.IsInvalid ) + { + dc.Dispose(); + throw new SystemException( "Unable to create a device context from the specified device information." ); + } - /// - /// ShowWindow options - /// - internal enum SW - { - HIDE = 0, - SHOWNORMAL = 1, - NORMAL = 1, - SHOWMINIMIZED = 2, - SHOWMAXIMIZED = 3, - MAXIMIZE = 3, - SHOWNOACTIVATE = 4, - SHOW = 5, - MINIMIZE = 6, - SHOWMINNOACTIVE = 7, - SHOWNA = 8, - RESTORE = 9, - SHOWDEFAULT = 10, - FORCEMINIMIZE = 11, - } - - internal enum SC - { - SIZE = 0xF000, - MOVE = 0xF010, - MINIMIZE = 0xF020, - MAXIMIZE = 0xF030, - NEXTWINDOW = 0xF040, - PREVWINDOW = 0xF050, - CLOSE = 0xF060, - VSCROLL = 0xF070, - HSCROLL = 0xF080, - MOUSEMENU = 0xF090, - KEYMENU = 0xF100, - ARRANGE = 0xF110, - RESTORE = 0xF120, - TASKLIST = 0xF130, - SCREENSAVE = 0xF140, - HOTKEY = 0xF150, - DEFAULT = 0xF160, - MONITORPOWER = 0xF170, - CONTEXTHELP = 0xF180, - SEPARATOR = 0xF00F, - /// - /// SCF_ISSECURE - /// - F_ISSECURE = 0x00000001, - ICON = MINIMIZE, - ZOOM = MAXIMIZE, + return dc; } - /// - /// GDI+ Status codes - /// - internal enum Status - { - Ok = 0, - GenericError = 1, - InvalidParameter = 2, - OutOfMemory = 3, - ObjectBusy = 4, - InsufficientBuffer = 5, - NotImplemented = 6, - Win32Error = 7, - WrongState = 8, - Aborted = 9, - FileNotFound = 10, - ValueOverflow = 11, - AccessDenied = 12, - UnknownImageFormat = 13, - FontFamilyNotFound = 14, - FontStyleNotFound = 15, - NotTrueTypeFont = 16, - UnsupportedGdiplusVersion = 17, - GdiplusNotInitialized = 18, - PropertyNotFound = 19, - PropertyNotSupported = 20, - ProfileNotFound = 21, - } - - internal enum MOUSEEVENTF : int - { - //mouse event constants - LEFTDOWN = 2, - LEFTUP = 4 - } - - /// - /// MSGFLT_*. New in Vista. Realiased in Windows 7. - /// - internal enum MSGFLT + public static SafeDC GetDC( IntPtr hwnd ) { - // Win7 versions of this enum: - RESET = 0, - ALLOW = 1, - DISALLOW = 2, + SafeDC dc = null; + try + { + dc = NativeMethods.GetDC( hwnd ); + } + finally + { + if( dc != null ) + { + dc.Hwnd = hwnd; + } + } - // Vista versions of this enum: - // ADD = 1, - // REMOVE = 2, - } + if( dc.IsInvalid ) + { + // GetDC does not set the last error... + HRESULT.E_FAIL.ThrowIfFailed(); + } - internal enum MSGFLTINFO - { - NONE = 0, - ALREADYALLOWED_FORWND = 1, - ALREADYDISALLOWED_FORWND = 2, - ALLOWED_HIGHER = 3, + return dc; } - internal enum INPUT_TYPE : uint + public static SafeDC GetDesktop() { - MOUSE = 0, + return GetDC( IntPtr.Zero ); } - /// - /// Shell_NotifyIcon messages. NIM_* - /// - internal enum NIM : uint + [SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static SafeDC WrapDC( IntPtr hdc ) { - ADD = 0, - MODIFY = 1, - DELETE = 2, - SETFOCUS = 3, - SETVERSION = 4, + // This won't actually get released by the class, but it allows an IntPtr to be converted for signatures. + return new SafeDC + { + handle = hdc, + _created = false, + _hwnd = IntPtr.Zero, + }; } + } - /// - /// SHAddToRecentDocuments flags. SHARD_* - /// - internal enum SHARD + internal sealed class SafeHBITMAP : SafeHandleZeroOrMinusOneIsInvalid + { + private SafeHBITMAP() : base( true ) { } + + [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] + protected override bool ReleaseHandle() { - PIDL = 0x00000001, - PATHA = 0x00000002, - PATHW = 0x00000003, - APPIDINFO = 0x00000004, // indicates the data type is a pointer to a SHARDAPPIDINFO structure - APPIDINFOIDLIST = 0x00000005, // indicates the data type is a pointer to a SHARDAPPIDINFOIDLIST structure - LINK = 0x00000006, // indicates the data type is a pointer to an IShellLink instance - APPIDINFOLINK = 0x00000007, // indicates the data type is a pointer to a SHARDAPPIDINFOLINK structure + return NativeMethods.DeleteObject( handle ); } + } + + internal sealed class SafeGdiplusStartupToken : SafeHandleZeroOrMinusOneIsInvalid + { + private SafeGdiplusStartupToken() : base( true ) { } - [Flags] - enum SLGP + [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] + protected override bool ReleaseHandle() { - SHORTPATH = 0x1, - UNCPRIORITY = 0x2, - RAWPATH = 0x4 + Status s = NativeMethods.GdiplusShutdown( this.handle ); + return s == Status.Ok; } - /// - /// Shell_NotifyIcon flags. NIF_* - /// - [Flags] - internal enum NIF : uint + [SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [SuppressMessage( "Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes" )] + public static SafeGdiplusStartupToken Startup() { - MESSAGE = 0x0001, - ICON = 0x0002, - TIP = 0x0004, - STATE = 0x0008, - INFO = 0x0010, - GUID = 0x0020, - - /// - /// Vista only. - /// - REALTIME = 0x0040, - /// - /// Vista only. - /// - SHOWTIP = 0x0080, - - XP_MASK = MESSAGE | ICON | STATE | INFO | GUID, - VISTA_MASK = XP_MASK | REALTIME | SHOWTIP, + SafeGdiplusStartupToken safeHandle = new SafeGdiplusStartupToken(); + IntPtr unsafeHandle; + StartupOutput output; + Status s = NativeMethods.GdiplusStartup( out unsafeHandle, new StartupInput(), out output ); + if( s == Status.Ok ) + { + safeHandle.handle = unsafeHandle; + return safeHandle; + } + safeHandle.Dispose(); + throw new Exception( "Unable to initialize GDI+" ); } + } - /// - /// Shell_NotifyIcon info flags. NIIF_* - /// - internal enum NIIF - { - NONE = 0x00000000, - INFO = 0x00000001, - WARNING = 0x00000002, - ERROR = 0x00000003, - /// XP SP2 and later. - USER = 0x00000004, - /// XP and later. - NOSOUND = 0x00000010, - /// Vista and later. - LARGE_ICON = 0x00000020, - /// Windows 7 and later - NIIF_RESPECT_QUIET_TIME = 0x00000080, - /// XP and later. Native version called NIIF_ICON_MASK. - XP_ICON_MASK = 0x0000000F, - } + internal sealed class SafeConnectionPointCookie : SafeHandleZeroOrMinusOneIsInvalid + { + private IConnectionPoint _cp; + // handle holds the cookie value. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [SuppressMessage( "Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IConnectionPoint" )] + public SafeConnectionPointCookie( IConnectionPointContainer target, object sink, Guid eventId ) + : base( true ) + { + Verify.IsNotNull( target, "target" ); + Verify.IsNotNull( sink, "sink" ); + Verify.IsNotDefault( eventId, "eventId" ); + + handle = IntPtr.Zero; + + IConnectionPoint cp = null; + try + { + int dwCookie; + target.FindConnectionPoint( ref eventId, out cp ); + cp.Advise( sink, out dwCookie ); + if( dwCookie == 0 ) + { + throw new InvalidOperationException( "IConnectionPoint::Advise returned an invalid cookie." ); + } + handle = new IntPtr( dwCookie ); + _cp = cp; + cp = null; + } + finally + { + Utility.SafeRelease( ref cp ); + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public void Disconnect() + { + ReleaseHandle(); + } + + [SuppressMessage( "Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes" )] + [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] + protected override bool ReleaseHandle() + { + try + { + if( !this.IsInvalid ) + { + int dwCookie = handle.ToInt32(); + handle = IntPtr.Zero; + + Assert.IsNotNull( _cp ); + try + { + _cp.Unadvise( dwCookie ); + } + finally + { + Utility.SafeRelease( ref _cp ); + } + } + return true; + } + catch + { + return false; + } + } + } + + #endregion + + #region Native Types + + [StructLayout( LayoutKind.Sequential )] + internal struct BLENDFUNCTION + { + // Must be AC_SRC_OVER + public AC BlendOp; + // Must be 0. + public byte BlendFlags; + // Alpha transparency between 0 (transparent) - 255 (opaque) + public byte SourceConstantAlpha; + // Must be AC_SRC_ALPHA + public AC AlphaFormat; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct HIGHCONTRAST + { + public int cbSize; + public HCF dwFlags; + //[MarshalAs(UnmanagedType.LPWStr, SizeConst=80)] + //public String lpszDefaultScheme; + public IntPtr lpszDefaultScheme; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct RGBQUAD + { + public byte rgbBlue; + public byte rgbGreen; + public byte rgbRed; + public byte rgbReserved; + } + + [StructLayout( LayoutKind.Sequential, Pack = 2 )] + internal struct BITMAPINFOHEADER + { + public int biSize; + public int biWidth; + public int biHeight; + public short biPlanes; + public short biBitCount; + public BI biCompression; + public int biSizeImage; + public int biXPelsPerMeter; + public int biYPelsPerMeter; + public int biClrUsed; + public int biClrImportant; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct BITMAPINFO + { + public BITMAPINFOHEADER bmiHeader; + public RGBQUAD bmiColors; + } + + // Win7 only. + [StructLayout( LayoutKind.Sequential )] + internal struct CHANGEFILTERSTRUCT + { + public uint cbSize; + public MSGFLTINFO ExtStatus; + } + + [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )] + internal struct CREATESTRUCT + { + public IntPtr lpCreateParams; + public IntPtr hInstance; + public IntPtr hMenu; + public IntPtr hwndParent; + public int cy; + public int cx; + public int y; + public int x; + public WS style; + [MarshalAs( UnmanagedType.LPWStr )] + public string lpszName; + [MarshalAs( UnmanagedType.LPWStr )] + public string lpszClass; + public WS_EX dwExStyle; + } + + [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1 )] + internal struct SHFILEOPSTRUCT + { + public IntPtr hwnd; + [MarshalAs( UnmanagedType.U4 )] + public FO wFunc; + // double-null terminated arrays of LPWSTRS + public string pFrom; + public string pTo; + [MarshalAs( UnmanagedType.U2 )] + public FOF fFlags; + [MarshalAs( UnmanagedType.Bool )] + public int fAnyOperationsAborted; + public IntPtr hNameMappings; + public string lpszProgressTitle; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct TITLEBARINFO + { + public int cbSize; + public RECT rcTitleBar; + public STATE_SYSTEM rgstate_TitleBar; + public STATE_SYSTEM rgstate_Reserved; + public STATE_SYSTEM rgstate_MinimizeButton; + public STATE_SYSTEM rgstate_MaximizeButton; + public STATE_SYSTEM rgstate_HelpButton; + public STATE_SYSTEM rgstate_CloseButton; + } + + // New to Vista. + [StructLayout( LayoutKind.Sequential )] + internal struct TITLEBARINFOEX + { + public int cbSize; + public RECT rcTitleBar; + public STATE_SYSTEM rgstate_TitleBar; + public STATE_SYSTEM rgstate_Reserved; + public STATE_SYSTEM rgstate_MinimizeButton; + public STATE_SYSTEM rgstate_MaximizeButton; + public STATE_SYSTEM rgstate_HelpButton; + public STATE_SYSTEM rgstate_CloseButton; + public RECT rgrect_TitleBar; + public RECT rgrect_Reserved; + public RECT rgrect_MinimizeButton; + public RECT rgrect_MaximizeButton; + public RECT rgrect_HelpButton; + public RECT rgrect_CloseButton; + } + + [SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )] + [StructLayout( LayoutKind.Sequential )] + internal class NOTIFYICONDATA + { + public int cbSize; + public IntPtr hWnd; + public int uID; + public NIF uFlags; + public int uCallbackMessage; + public IntPtr hIcon; + [MarshalAs( UnmanagedType.ByValArray, SizeConst = 128 )] + public char[] szTip = new char[ 128 ]; /// - /// AC_* + /// The state of the icon. There are two flags that can be set independently. + /// NIS_HIDDEN = 1. The icon is hidden. + /// NIS_SHAREDICON = 2. The icon is shared. /// - internal enum AC : byte - { - SRC_OVER = 0, - SRC_ALPHA = 1, - } + public uint dwState; + public uint dwStateMask; + [MarshalAs( UnmanagedType.ByValArray, SizeConst = 256 )] + public char[] szInfo = new char[ 256 ]; + // Prior to Vista this was a union of uTimeout and uVersion. As of Vista, uTimeout has been deprecated. + public uint uVersion; // Used with Shell_NotifyIcon flag NIM_SETVERSION. + [MarshalAs( UnmanagedType.ByValArray, SizeConst = 64 )] + public char[] szInfoTitle = new char[ 64 ]; + public uint dwInfoFlags; + public Guid guidItem; + // Vista only + IntPtr hBalloonIcon; + } - internal enum ULW + [SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )] + [StructLayout( LayoutKind.Explicit )] + internal class PROPVARIANT : IDisposable + { + private static class NativeMethods { - ALPHA = 2, - COLORKEY = 1, - OPAQUE = 4, + [DllImport( "ole32.dll" )] + internal static extern HRESULT PropVariantClear( PROPVARIANT pvar ); } - internal enum WVR + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + [FieldOffset( 0 )] + private ushort vt; + [SuppressMessage( "Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources" )] + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + [FieldOffset( 8 )] + private IntPtr pointerVal; + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + [FieldOffset( 8 )] + private byte byteVal; + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + [FieldOffset( 8 )] + private long longVal; + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] + [FieldOffset( 8 )] + private short boolVal; + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public VarEnum VarType { - ALIGNTOP = 0x0010, - ALIGNLEFT = 0x0020, - ALIGNBOTTOM = 0x0040, - ALIGNRIGHT = 0x0080, - HREDRAW = 0x0100, - VREDRAW = 0x0200, - VALIDRECTS = 0x0400, - REDRAW = HREDRAW | VREDRAW, + get + { + return ( VarEnum )vt; + } } - #endregion - - #region SafeHandles - - internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid + // Right now only using this for strings. + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public string GetValue() { - [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] - private SafeFindHandle() : base(true) { } + if( vt == ( ushort )VarEnum.VT_LPWSTR ) + { + return Marshal.PtrToStringUni( pointerVal ); + } - protected override bool ReleaseHandle() - { - return NativeMethods.FindClose(handle); - } + return null; } - internal sealed class SafeDC : SafeHandleZeroOrMinusOneIsInvalid + public void SetValue( bool f ) { - private static class NativeMethods - { - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll")] - public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll")] - public static extern SafeDC GetDC(IntPtr hwnd); - - // Weird legacy function, documentation is unclear about how to use it... - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", CharSet = CharSet.Unicode)] - public static extern SafeDC CreateDC([MarshalAs(UnmanagedType.LPWStr)] string lpszDriver, [MarshalAs(UnmanagedType.LPWStr)] string lpszDevice, IntPtr lpszOutput, IntPtr lpInitData); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern SafeDC CreateCompatibleDC(IntPtr hdc); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DeleteDC(IntPtr hdc); - } - - private IntPtr? _hwnd; - private bool _created; - - public IntPtr Hwnd - { - set - { - Assert.NullableIsNull(_hwnd); - _hwnd = value; - } - } - - private SafeDC() : base(true) { } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected override bool ReleaseHandle() - { - if (_created) - { - return NativeMethods.DeleteDC(handle); - } - - if (!_hwnd.HasValue || _hwnd.Value == IntPtr.Zero) - { - return true; - } - - return NativeMethods.ReleaseDC(_hwnd.Value, handle) == 1; - } - - [SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static SafeDC CreateDC(string deviceName) - { - SafeDC dc = null; - try - { - // Should this really be on the driver parameter? - dc = NativeMethods.CreateDC(deviceName, null, IntPtr.Zero, IntPtr.Zero); - } - finally - { - if (dc != null) - { - dc._created = true; - } - } - - if (dc.IsInvalid) - { - dc.Dispose(); - throw new SystemException("Unable to create a device context from the specified device information."); - } - - return dc; - } - - [SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static SafeDC CreateCompatibleDC(SafeDC hdc) - { - SafeDC dc = null; - try - { - IntPtr hPtr = IntPtr.Zero; - if (hdc != null) - { - hPtr = hdc.handle; - } - dc = NativeMethods.CreateCompatibleDC(hPtr); - if (dc == null) - { - HRESULT.ThrowLastError(); - } - } - finally - { - if (dc != null) - { - dc._created = true; - } - } - - if (dc.IsInvalid) - { - dc.Dispose(); - throw new SystemException("Unable to create a device context from the specified device information."); - } - - return dc; - } - - public static SafeDC GetDC(IntPtr hwnd) - { - SafeDC dc = null; - try - { - dc = NativeMethods.GetDC(hwnd); - } - finally - { - if (dc != null) - { - dc.Hwnd = hwnd; - } - } - - if (dc.IsInvalid) - { - // GetDC does not set the last error... - HRESULT.E_FAIL.ThrowIfFailed(); - } - - return dc; - } - - public static SafeDC GetDesktop() - { - return GetDC(IntPtr.Zero); - } - - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static SafeDC WrapDC(IntPtr hdc) - { - // This won't actually get released by the class, but it allows an IntPtr to be converted for signatures. - return new SafeDC - { - handle = hdc, - _created = false, - _hwnd = IntPtr.Zero, - }; - } + Clear(); + vt = ( ushort )VarEnum.VT_BOOL; + boolVal = ( short )( f ? -1 : 0 ); } - internal sealed class SafeHBITMAP : SafeHandleZeroOrMinusOneIsInvalid + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public void SetValue( string val ) { - private SafeHBITMAP() : base(true) { } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected override bool ReleaseHandle() - { - return NativeMethods.DeleteObject(handle); - } + Clear(); + vt = ( ushort )VarEnum.VT_LPWSTR; + pointerVal = Marshal.StringToCoTaskMemUni( val ); } - internal sealed class SafeGdiplusStartupToken : SafeHandleZeroOrMinusOneIsInvalid + public void Clear() { - private SafeGdiplusStartupToken() : base(true) { } + HRESULT hr = NativeMethods.PropVariantClear( this ); + Assert.IsTrue( hr.Succeeded ); + } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected override bool ReleaseHandle() - { - Status s = NativeMethods.GdiplusShutdown(this.handle); - return s == Status.Ok; - } + #region IDisposable Pattern - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")] - public static SafeGdiplusStartupToken Startup() - { - SafeGdiplusStartupToken safeHandle = new SafeGdiplusStartupToken(); - IntPtr unsafeHandle; - StartupOutput output; - Status s = NativeMethods.GdiplusStartup(out unsafeHandle, new StartupInput(), out output); - if (s == Status.Ok) - { - safeHandle.handle = unsafeHandle; - return safeHandle; - } - safeHandle.Dispose(); - throw new Exception("Unable to initialize GDI+"); - } + public void Dispose() + { + Dispose( true ); + GC.SuppressFinalize( this ); } - internal sealed class SafeConnectionPointCookie : SafeHandleZeroOrMinusOneIsInvalid + ~PROPVARIANT() { - private IConnectionPoint _cp; - // handle holds the cookie value. - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IConnectionPoint")] - public SafeConnectionPointCookie(IConnectionPointContainer target, object sink, Guid eventId) - : base(true) - { - Verify.IsNotNull(target, "target"); - Verify.IsNotNull(sink, "sink"); - Verify.IsNotDefault(eventId, "eventId"); - - handle = IntPtr.Zero; - - IConnectionPoint cp = null; - try - { - int dwCookie; - target.FindConnectionPoint(ref eventId, out cp); - cp.Advise(sink, out dwCookie); - if (dwCookie == 0) - { - throw new InvalidOperationException("IConnectionPoint::Advise returned an invalid cookie."); - } - handle = new IntPtr(dwCookie); - _cp = cp; - cp = null; - } - finally - { - Utility.SafeRelease(ref cp); - } - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public void Disconnect() - { - ReleaseHandle(); - } + Dispose( false ); + } - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected override bool ReleaseHandle() - { - try - { - if (!this.IsInvalid) - { - int dwCookie = handle.ToInt32(); - handle = IntPtr.Zero; - - Assert.IsNotNull(_cp); - try - { - _cp.Unadvise(dwCookie); - } - finally - { - Utility.SafeRelease(ref _cp); - } - } - return true; - } - catch - { - return false; - } - } + [SuppressMessage( "Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing" )] + private void Dispose( bool disposing ) + { + Clear(); } #endregion + } + + [SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )] + [StructLayout( LayoutKind.Sequential, Pack = 4 )] + internal class SHARDAPPIDINFO + { + [MarshalAs( UnmanagedType.Interface )] + object psi; // The namespace location of the the item that should be added to the recent docs folder. + [MarshalAs( UnmanagedType.LPWStr )] + string pszAppID; // The id of the application that should be associated with this recent doc. + } + + [SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )] + [StructLayout( LayoutKind.Sequential, Pack = 4 )] + internal class SHARDAPPIDINFOIDLIST + { + /// The idlist for the shell item that should be added to the recent docs folder. + IntPtr pidl; + /// The id of the application that should be associated with this recent doc. + [MarshalAs( UnmanagedType.LPWStr )] + string pszAppID; + } + + [SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )] + [StructLayout( LayoutKind.Sequential, Pack = 4 )] + internal class SHARDAPPIDINFOLINK + { + IntPtr psl; // An IShellLink instance that when launched opens a recently used item in the specified + // application. This link is not added to the recent docs folder, but will be added to the + // specified application's destination list. + [MarshalAs( UnmanagedType.LPWStr )] + string pszAppID; // The id of the application that should be associated with this recent doc. + } + + + [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )] + internal struct LOGFONT + { + public int lfHeight; + public int lfWidth; + public int lfEscapement; + public int lfOrientation; + public int lfWeight; + public byte lfItalic; + public byte lfUnderline; + public byte lfStrikeOut; + public byte lfCharSet; + public byte lfOutPrecision; + public byte lfClipPrecision; + public byte lfQuality; + public byte lfPitchAndFamily; + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 32 )] + public string lfFaceName; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct MINMAXINFO + { + public POINT ptReserved; + public POINT ptMaxSize; + public POINT ptMaxPosition; + public POINT ptMinTrackSize; + public POINT ptMaxTrackSize; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct NONCLIENTMETRICS + { + public int cbSize; + public int iBorderWidth; + public int iScrollWidth; + public int iScrollHeight; + public int iCaptionWidth; + public int iCaptionHeight; + public LOGFONT lfCaptionFont; + public int iSmCaptionWidth; + public int iSmCaptionHeight; + public LOGFONT lfSmCaptionFont; + public int iMenuWidth; + public int iMenuHeight; + public LOGFONT lfMenuFont; + public LOGFONT lfStatusFont; + public LOGFONT lfMessageFont; + // Vista only + public int iPaddedBorderWidth; + + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public static NONCLIENTMETRICS VistaMetricsStruct + { + get + { + var ncm = new NONCLIENTMETRICS(); + ncm.cbSize = Marshal.SizeOf( typeof( NONCLIENTMETRICS ) ); + return ncm; + } + } + + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public static NONCLIENTMETRICS XPMetricsStruct + { + get + { + var ncm = new NONCLIENTMETRICS(); + // Account for the missing iPaddedBorderWidth + ncm.cbSize = Marshal.SizeOf( typeof( NONCLIENTMETRICS ) ) - sizeof( int ); + return ncm; + } + } + } + + /// Defines options that are used to set window visual style attributes. + [StructLayout( LayoutKind.Explicit )] + internal struct WTA_OPTIONS + { + // public static readonly uint Size = (uint)Marshal.SizeOf(typeof(WTA_OPTIONS)); + public const uint Size = 8; - #region Native Types + /// + /// A combination of flags that modify window visual style attributes. + /// Can be a combination of the WTNCA constants. + /// + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Used by native code." )] + [FieldOffset( 0 )] + public WTNCA dwFlags; - [StructLayout(LayoutKind.Sequential)] - internal struct BLENDFUNCTION - { - // Must be AC_SRC_OVER - public AC BlendOp; - // Must be 0. - public byte BlendFlags; - // Alpha transparency between 0 (transparent) - 255 (opaque) - public byte SourceConstantAlpha; - // Must be AC_SRC_ALPHA - public AC AlphaFormat; + /// + /// A bitmask that describes how the values specified in dwFlags should be applied. + /// If the bit corresponding to a value in dwFlags is 0, that flag will be removed. + /// If the bit is 1, the flag will be added. + /// + [SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Used by native code." )] + [FieldOffset( 4 )] + public WTNCA dwMask; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct MARGINS + { + /// Width of left border that retains its size. + public int cxLeftWidth; + /// Width of right border that retains its size. + public int cxRightWidth; + /// Height of top border that retains its size. + public int cyTopHeight; + /// Height of bottom border that retains its size. + public int cyBottomHeight; + }; + + [StructLayout( LayoutKind.Sequential )] + internal class MONITORINFO + { + public int cbSize = Marshal.SizeOf( typeof( MONITORINFO ) ); + public RECT rcMonitor; + public RECT rcWork; + public int dwFlags; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct POINT + { + public int x; + public int y; + } + + [SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )] + [StructLayout( LayoutKind.Sequential )] + internal class RefPOINT + { + public int x; + public int y; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct RECT + { + private int _left; + private int _top; + private int _right; + private int _bottom; + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public void Offset( int dx, int dy ) + { + _left += dx; + _top += dy; + _right += dx; + _bottom += dy; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Left + { + get + { + return _left; + } + set + { + _left = value; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Right + { + get + { + return _right; + } + set + { + _right = value; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Top + { + get + { + return _top; + } + set + { + _top = value; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Bottom + { + get + { + return _bottom; + } + set + { + _bottom = value; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Width + { + get + { + return _right - _left; + } } - [StructLayout(LayoutKind.Sequential)] - internal struct HIGHCONTRAST + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Height { - public int cbSize; - public HCF dwFlags; - //[MarshalAs(UnmanagedType.LPWStr, SizeConst=80)] - //public String lpszDefaultScheme; - public IntPtr lpszDefaultScheme; + get + { + return _bottom - _top; + } } - [StructLayout(LayoutKind.Sequential)] - internal struct RGBQUAD + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public POINT Position { - public byte rgbBlue; - public byte rgbGreen; - public byte rgbRed; - public byte rgbReserved; + get + { + return new POINT { x = _left, y = _top }; + } } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - internal struct BITMAPINFOHEADER + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public SIZE Size { - public int biSize; - public int biWidth; - public int biHeight; - public short biPlanes; - public short biBitCount; - public BI biCompression; - public int biSizeImage; - public int biXPelsPerMeter; - public int biYPelsPerMeter; - public int biClrUsed; - public int biClrImportant; + get + { + return new SIZE { cx = Width, cy = Height }; + } } - [StructLayout(LayoutKind.Sequential)] - internal struct BITMAPINFO + public static RECT Union( RECT rect1, RECT rect2 ) { - public BITMAPINFOHEADER bmiHeader; - public RGBQUAD bmiColors; + return new RECT + { + Left = Math.Min( rect1.Left, rect2.Left ), + Top = Math.Min( rect1.Top, rect2.Top ), + Right = Math.Max( rect1.Right, rect2.Right ), + Bottom = Math.Max( rect1.Bottom, rect2.Bottom ), + }; } - // Win7 only. - [StructLayout(LayoutKind.Sequential)] - internal struct CHANGEFILTERSTRUCT - { - public uint cbSize; - public MSGFLTINFO ExtStatus; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct CREATESTRUCT - { - public IntPtr lpCreateParams; - public IntPtr hInstance; - public IntPtr hMenu; - public IntPtr hwndParent; - public int cy; - public int cx; - public int y; - public int x; - public WS style; - [MarshalAs(UnmanagedType.LPWStr)] - public string lpszName; - [MarshalAs(UnmanagedType.LPWStr)] - public string lpszClass; - public WS_EX dwExStyle; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)] - internal struct SHFILEOPSTRUCT - { - public IntPtr hwnd; - [MarshalAs(UnmanagedType.U4)] - public FO wFunc; - // double-null terminated arrays of LPWSTRS - public string pFrom; - public string pTo; - [MarshalAs(UnmanagedType.U2)] - public FOF fFlags; - [MarshalAs(UnmanagedType.Bool)] - public int fAnyOperationsAborted; - public IntPtr hNameMappings; - public string lpszProgressTitle; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct TITLEBARINFO - { - public int cbSize; - public RECT rcTitleBar; - public STATE_SYSTEM rgstate_TitleBar; - public STATE_SYSTEM rgstate_Reserved; - public STATE_SYSTEM rgstate_MinimizeButton; - public STATE_SYSTEM rgstate_MaximizeButton; - public STATE_SYSTEM rgstate_HelpButton; - public STATE_SYSTEM rgstate_CloseButton; - } - - // New to Vista. - [StructLayout(LayoutKind.Sequential)] - internal struct TITLEBARINFOEX - { - public int cbSize; - public RECT rcTitleBar; - public STATE_SYSTEM rgstate_TitleBar; - public STATE_SYSTEM rgstate_Reserved; - public STATE_SYSTEM rgstate_MinimizeButton; - public STATE_SYSTEM rgstate_MaximizeButton; - public STATE_SYSTEM rgstate_HelpButton; - public STATE_SYSTEM rgstate_CloseButton; - public RECT rgrect_TitleBar; - public RECT rgrect_Reserved; - public RECT rgrect_MinimizeButton; - public RECT rgrect_MaximizeButton; - public RECT rgrect_HelpButton; - public RECT rgrect_CloseButton; - } - - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - [StructLayout(LayoutKind.Sequential)] - internal class NOTIFYICONDATA - { - public int cbSize; - public IntPtr hWnd; - public int uID; - public NIF uFlags; - public int uCallbackMessage; - public IntPtr hIcon; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] - public char[] szTip = new char[128]; - /// - /// The state of the icon. There are two flags that can be set independently. - /// NIS_HIDDEN = 1. The icon is hidden. - /// NIS_SHAREDICON = 2. The icon is shared. - /// - public uint dwState; - public uint dwStateMask; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] - public char[] szInfo = new char[256]; - // Prior to Vista this was a union of uTimeout and uVersion. As of Vista, uTimeout has been deprecated. - public uint uVersion; // Used with Shell_NotifyIcon flag NIM_SETVERSION. - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] - public char[] szInfoTitle = new char[64]; - public uint dwInfoFlags; - public Guid guidItem; - // Vista only - IntPtr hBalloonIcon; - } - - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - [StructLayout(LayoutKind.Explicit)] - internal class PROPVARIANT : IDisposable - { - private static class NativeMethods - { - [DllImport("ole32.dll")] - internal static extern HRESULT PropVariantClear(PROPVARIANT pvar); - } - - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - [FieldOffset(0)] - private ushort vt; - [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - [FieldOffset(8)] - private IntPtr pointerVal; - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - [FieldOffset(8)] - private byte byteVal; - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - [FieldOffset(8)] - private long longVal; - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - [FieldOffset(8)] - private short boolVal; - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public VarEnum VarType - { - get { return (VarEnum)vt; } - } - - // Right now only using this for strings. - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public string GetValue() - { - if (vt == (ushort)VarEnum.VT_LPWSTR) - { - return Marshal.PtrToStringUni(pointerVal); - } - - return null; - } - - public void SetValue(bool f) - { - Clear(); - vt = (ushort)VarEnum.VT_BOOL; - boolVal = (short)(f ? -1 : 0); - } - - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public void SetValue(string val) - { - Clear(); - vt = (ushort)VarEnum.VT_LPWSTR; - pointerVal = Marshal.StringToCoTaskMemUni(val); - } - - public void Clear() - { - HRESULT hr = NativeMethods.PropVariantClear(this); - Assert.IsTrue(hr.Succeeded); - } - - #region IDisposable Pattern - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~PROPVARIANT() - { - Dispose(false); - } - - [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing")] - private void Dispose(bool disposing) - { - Clear(); - } - - #endregion - } - - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - [StructLayout(LayoutKind.Sequential, Pack = 4)] - internal class SHARDAPPIDINFO - { - [MarshalAs(UnmanagedType.Interface)] - object psi; // The namespace location of the the item that should be added to the recent docs folder. - [MarshalAs(UnmanagedType.LPWStr)] - string pszAppID; // The id of the application that should be associated with this recent doc. - } - - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - [StructLayout(LayoutKind.Sequential, Pack = 4)] - internal class SHARDAPPIDINFOIDLIST - { - /// The idlist for the shell item that should be added to the recent docs folder. - IntPtr pidl; - /// The id of the application that should be associated with this recent doc. - [MarshalAs(UnmanagedType.LPWStr)] - string pszAppID; - } - - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - [StructLayout(LayoutKind.Sequential, Pack = 4)] - internal class SHARDAPPIDINFOLINK - { - IntPtr psl; // An IShellLink instance that when launched opens a recently used item in the specified - // application. This link is not added to the recent docs folder, but will be added to the - // specified application's destination list. - [MarshalAs(UnmanagedType.LPWStr)] - string pszAppID; // The id of the application that should be associated with this recent doc. - } - - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct LOGFONT - { - public int lfHeight; - public int lfWidth; - public int lfEscapement; - public int lfOrientation; - public int lfWeight; - public byte lfItalic; - public byte lfUnderline; - public byte lfStrikeOut; - public byte lfCharSet; - public byte lfOutPrecision; - public byte lfClipPrecision; - public byte lfQuality; - public byte lfPitchAndFamily; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] - public string lfFaceName; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct MINMAXINFO - { - public POINT ptReserved; - public POINT ptMaxSize; - public POINT ptMaxPosition; - public POINT ptMinTrackSize; - public POINT ptMaxTrackSize; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct NONCLIENTMETRICS - { - public int cbSize; - public int iBorderWidth; - public int iScrollWidth; - public int iScrollHeight; - public int iCaptionWidth; - public int iCaptionHeight; - public LOGFONT lfCaptionFont; - public int iSmCaptionWidth; - public int iSmCaptionHeight; - public LOGFONT lfSmCaptionFont; - public int iMenuWidth; - public int iMenuHeight; - public LOGFONT lfMenuFont; - public LOGFONT lfStatusFont; - public LOGFONT lfMessageFont; - // Vista only - public int iPaddedBorderWidth; - - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public static NONCLIENTMETRICS VistaMetricsStruct - { - get - { - var ncm = new NONCLIENTMETRICS(); - ncm.cbSize = Marshal.SizeOf(typeof(NONCLIENTMETRICS)); - return ncm; - } - } - - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public static NONCLIENTMETRICS XPMetricsStruct - { - get - { - var ncm = new NONCLIENTMETRICS(); - // Account for the missing iPaddedBorderWidth - ncm.cbSize = Marshal.SizeOf(typeof(NONCLIENTMETRICS)) - sizeof(int); - return ncm; - } - } - } - - /// Defines options that are used to set window visual style attributes. - [StructLayout(LayoutKind.Explicit)] - internal struct WTA_OPTIONS + public override bool Equals( object obj ) { - // public static readonly uint Size = (uint)Marshal.SizeOf(typeof(WTA_OPTIONS)); - public const uint Size = 8; - - /// - /// A combination of flags that modify window visual style attributes. - /// Can be a combination of the WTNCA constants. - /// - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Used by native code.")] - [FieldOffset(0)] - public WTNCA dwFlags; - - /// - /// A bitmask that describes how the values specified in dwFlags should be applied. - /// If the bit corresponding to a value in dwFlags is 0, that flag will be removed. - /// If the bit is 1, the flag will be added. - /// - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Used by native code.")] - [FieldOffset(4)] - public WTNCA dwMask; + try + { + var rc = ( RECT )obj; + return rc._bottom == _bottom + && rc._left == _left + && rc._right == _right + && rc._top == _top; + } + catch( InvalidCastException ) + { + return false; + } } - [StructLayout(LayoutKind.Sequential)] - internal struct MARGINS + public override int GetHashCode() { - /// Width of left border that retains its size. - public int cxLeftWidth; - /// Width of right border that retains its size. - public int cxRightWidth; - /// Height of top border that retains its size. - public int cyTopHeight; - /// Height of bottom border that retains its size. - public int cyBottomHeight; - }; - - [StructLayout(LayoutKind.Sequential)] - internal class MONITORINFO - { - public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); - public RECT rcMonitor; - public RECT rcWork; - public int dwFlags; + return ( _left << 16 | Utility.LOWORD( _right ) ) ^ ( _top << 16 | Utility.LOWORD( _bottom ) ); } + } + + [SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )] + [StructLayout( LayoutKind.Sequential )] + internal class RefRECT + { + private int _left; + private int _top; + private int _right; + private int _bottom; - [StructLayout(LayoutKind.Sequential)] - internal struct POINT + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public RefRECT( int left, int top, int right, int bottom ) { - public int x; - public int y; + _left = left; + _top = top; + _right = right; + _bottom = bottom; } - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - [StructLayout(LayoutKind.Sequential)] - internal class RefPOINT + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Width { - public int x; - public int y; + get + { + return _right - _left; + } } - [StructLayout(LayoutKind.Sequential)] - internal struct RECT + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Height { - private int _left; - private int _top; - private int _right; - private int _bottom; - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public void Offset(int dx, int dy) - { - _left += dx; - _top += dy; - _right += dx; - _bottom += dy; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Left - { - get { return _left; } - set { _left = value; } - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Right - { - get { return _right; } - set { _right = value; } - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Top - { - get { return _top; } - set { _top = value; } - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Bottom - { - get { return _bottom; } - set { _bottom = value; } - } + get + { + return _bottom - _top; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Left + { + get + { + return _left; + } + set + { + _left = value; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Right + { + get + { + return _right; + } + set + { + _right = value; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Top + { + get + { + return _top; + } + set + { + _top = value; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public int Bottom + { + get + { + return _bottom; + } + set + { + _bottom = value; + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public void Offset( int dx, int dy ) + { + _left += dx; + _top += dy; + _right += dx; + _bottom += dy; + } + } + + [StructLayout( LayoutKind.Sequential )] + internal struct SIZE + { + public int cx; + public int cy; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct StartupOutput + { + public IntPtr hook; + public IntPtr unhook; + } + + [StructLayout( LayoutKind.Sequential )] + internal class StartupInput + { + public int GdiplusVersion = 1; + public IntPtr DebugEventCallback; + public bool SuppressBackgroundThread; + public bool SuppressExternalCodecs; + } + + [SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )] + [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )] + [BestFitMapping( false )] + internal class WIN32_FIND_DATAW + { + public FileAttributes dwFileAttributes; + public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime; + public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime; + public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime; + public int nFileSizeHigh; + public int nFileSizeLow; + public int dwReserved0; + public int dwReserved1; + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 260 )] + public string cFileName; + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 14 )] + public string cAlternateFileName; + } + + [StructLayout( LayoutKind.Sequential )] + internal class WINDOWPLACEMENT + { + public int length = Marshal.SizeOf( typeof( WINDOWPLACEMENT ) ); + public int flags; + public SW showCmd; + public POINT ptMinPosition; + public POINT ptMaxPosition; + public RECT rcNormalPosition; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct WINDOWPOS + { + public IntPtr hwnd; + public IntPtr hwndInsertAfter; + public int x; + public int y; + public int cx; + public int cy; + public int flags; + } + + [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )] + internal struct WNDCLASSEX + { + public int cbSize; + public CS style; + public WndProc lpfnWndProc; + public int cbClsExtra; + public int cbWndExtra; + public IntPtr hInstance; + public IntPtr hIcon; + public IntPtr hCursor; + public IntPtr hbrBackground; + [MarshalAs( UnmanagedType.LPWStr )] + public string lpszMenuName; + [MarshalAs( UnmanagedType.LPWStr )] + public string lpszClassName; + public IntPtr hIconSm; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct MOUSEINPUT + { + public int dx; + public int dy; + public int mouseData; + public int dwFlags; + public int time; + public IntPtr dwExtraInfo; + } + + [StructLayout( LayoutKind.Sequential )] + internal struct INPUT + { + public uint type; + public MOUSEINPUT mi; + }; + + [StructLayout( LayoutKind.Sequential )] + internal struct UNSIGNED_RATIO + { + public uint uiNumerator; + public uint uiDenominator; + } + + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + internal struct DWM_TIMING_INFO + { + public int cbSize; + public UNSIGNED_RATIO rateRefresh; + public ulong qpcRefreshPeriod; + public UNSIGNED_RATIO rateCompose; + public ulong qpcVBlank; + public ulong cRefresh; + public uint cDXRefresh; + public ulong qpcCompose; + public ulong cFrame; + public uint cDXPresent; + public ulong cRefreshFrame; + public ulong cFrameSubmitted; + public uint cDXPresentSubmitted; + public ulong cFrameConfirmed; + public uint cDXPresentConfirmed; + public ulong cRefreshConfirmed; + public uint cDXRefreshConfirmed; + public ulong cFramesLate; + public uint cFramesOutstanding; + public ulong cFrameDisplayed; + public ulong qpcFrameDisplayed; + public ulong cRefreshFrameDisplayed; + public ulong cFrameComplete; + public ulong qpcFrameComplete; + public ulong cFramePending; + public ulong qpcFramePending; + public ulong cFramesDisplayed; + public ulong cFramesComplete; + public ulong cFramesPending; + public ulong cFramesAvailable; + public ulong cFramesDropped; + public ulong cFramesMissed; + public ulong cRefreshNextDisplayed; + public ulong cRefreshNextPresented; + public ulong cRefreshesDisplayed; + public ulong cRefreshesPresented; + public ulong cRefreshStarted; + public ulong cPixelsReceived; + public ulong cPixelsDrawn; + public ulong cBuffersEmpty; + } + + #endregion + + /// Delegate declaration that matches native WndProc signatures. + internal delegate IntPtr WndProc( IntPtr hwnd, WM uMsg, IntPtr wParam, IntPtr lParam ); + + /// Delegate declaration that matches native WndProc signatures. + internal delegate IntPtr WndProcHook( IntPtr hwnd, WM uMsg, IntPtr wParam, IntPtr lParam, ref bool handled ); + + /// Delegate declaration that matches managed WndProc signatures. + internal delegate IntPtr MessageHandler( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ); + + // Some native methods are shimmed through public versions that handle converting failures into thrown exceptions. + internal static class NativeMethods + { + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "AdjustWindowRectEx", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _AdjustWindowRectEx( ref RECT lpRect, WS dwStyle, [MarshalAs( UnmanagedType.Bool )] bool bMenu, WS_EX dwExStyle ); + + public static RECT AdjustWindowRectEx( RECT lpRect, WS dwStyle, bool bMenu, WS_EX dwExStyle ) + { + // Native version modifies the parameter in place. + if( !_AdjustWindowRectEx( ref lpRect, dwStyle, bMenu, dwExStyle ) ) + { + HRESULT.ThrowLastError(); + } + + return lpRect; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "ChangeWindowMessageFilter", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _ChangeWindowMessageFilter( WM message, MSGFLT dwFlag ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "ChangeWindowMessageFilterEx", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _ChangeWindowMessageFilterEx( IntPtr hwnd, WM message, MSGFLT action, [In, Out, Optional] ref CHANGEFILTERSTRUCT pChangeFilterStruct ); + + // Note that processes at or below SECURITY_MANDATORY_LOW_RID are not allowed to change the message filter. + // If those processes call this function, it will fail and generate the extended error code, ERROR_ACCESS_DENIED. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static HRESULT ChangeWindowMessageFilterEx( IntPtr hwnd, WM message, MSGFLT action, out MSGFLTINFO filterInfo ) + { + filterInfo = MSGFLTINFO.NONE; + + bool ret; + + // This origins of this API were added for Vista. The Ex version was added for Windows 7. + // If we're not on either, then this message filter isolation doesn't exist. + if( !Utility.IsOSVistaOrNewer ) + { + return HRESULT.S_FALSE; + } + + // If we're on Vista rather than Win7 then we can't use the Ex version of this function. + // The Ex version is preferred if possible because this results in process-wide modifications of the filter + // and is deprecated as of Win7. + if( !Utility.IsOSWindows7OrNewer ) + { + // Note that the Win7 MSGFLT_ALLOW/DISALLOW enum values map to the Vista MSGFLT_ADD/REMOVE + ret = _ChangeWindowMessageFilter( message, action ); + if( !ret ) + { + return ( HRESULT )Win32Error.GetLastError(); + } + return HRESULT.S_OK; + } + + var filterstruct = new CHANGEFILTERSTRUCT { cbSize = ( uint )Marshal.SizeOf( typeof( CHANGEFILTERSTRUCT ) ) }; + ret = _ChangeWindowMessageFilterEx( hwnd, message, action, ref filterstruct ); + if( !ret ) + { + return ( HRESULT )Win32Error.GetLastError(); + } + + filterInfo = filterstruct.ExtStatus; + return HRESULT.S_OK; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Width - { - get { return _right - _left; } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll" )] + public static extern CombineRgnResult CombineRgn( IntPtr hrgnDest, IntPtr hrgnSrc1, IntPtr hrgnSrc2, RGN fnCombineMode ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Height - { - get { return _bottom - _top; } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "shell32.dll", EntryPoint = "CommandLineToArgvW", CharSet = CharSet.Unicode )] + private static extern IntPtr _CommandLineToArgvW( [MarshalAs( UnmanagedType.LPWStr )] string cmdLine, out int numArgs ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public POINT Position - { - get { return new POINT { x = _left, y = _top }; } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static string[] CommandLineToArgvW( string cmdLine ) + { + IntPtr argv = IntPtr.Zero; + try + { + int numArgs = 0; - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public SIZE Size + argv = _CommandLineToArgvW( cmdLine, out numArgs ); + if( argv == IntPtr.Zero ) { - get { return new SIZE { cx = Width, cy = Height }; } + throw new Win32Exception(); } + var result = new string[ numArgs ]; - public static RECT Union(RECT rect1, RECT rect2) + for( int i = 0; i < numArgs; i++ ) { - return new RECT - { - Left = Math.Min(rect1.Left, rect2.Left), - Top = Math.Min(rect1.Top, rect2.Top), - Right = Math.Max(rect1.Right, rect2.Right), - Bottom = Math.Max(rect1.Bottom, rect2.Bottom), - }; + IntPtr currArg = Marshal.ReadIntPtr( argv, i * Marshal.SizeOf( typeof( IntPtr ) ) ); + result[ i ] = Marshal.PtrToStringUni( currArg ); } - public override bool Equals(object obj) - { - try - { - var rc = (RECT)obj; - return rc._bottom == _bottom - && rc._left == _left - && rc._right == _right - && rc._top == _top; - } - catch (InvalidCastException) - { - return false; - } - } + return result; + } + finally + { - public override int GetHashCode() - { - return (_left << 16 | Utility.LOWORD(_right)) ^ (_top << 16 | Utility.LOWORD(_bottom)); - } + IntPtr p = _LocalFree( argv ); + // Otherwise LocalFree failed. + Assert.AreEqual( IntPtr.Zero, p ); + } } - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - [StructLayout(LayoutKind.Sequential)] - internal class RefRECT - { - private int _left; - private int _top; - private int _right; - private int _bottom; + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", EntryPoint = "CreateDIBSection", SetLastError = true )] + private static extern SafeHBITMAP _CreateDIBSection( SafeDC hdc, [In] ref BITMAPINFO bitmapInfo, int iUsage, [Out] out IntPtr ppvBits, IntPtr hSection, int dwOffset ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", EntryPoint = "CreateDIBSection", SetLastError = true )] + private static extern SafeHBITMAP _CreateDIBSectionIntPtr( IntPtr hdc, [In] ref BITMAPINFO bitmapInfo, int iUsage, [Out] out IntPtr ppvBits, IntPtr hSection, int dwOffset ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static SafeHBITMAP CreateDIBSection( SafeDC hdc, ref BITMAPINFO bitmapInfo, out IntPtr ppvBits, IntPtr hSection, int dwOffset ) + { + const int DIB_RGB_COLORS = 0; + SafeHBITMAP hBitmap = null; + if( hdc == null ) + { + hBitmap = _CreateDIBSectionIntPtr( IntPtr.Zero, ref bitmapInfo, DIB_RGB_COLORS, out ppvBits, hSection, dwOffset ); + } + else + { + hBitmap = _CreateDIBSection( hdc, ref bitmapInfo, DIB_RGB_COLORS, out ppvBits, hSection, dwOffset ); + } + + if( hBitmap.IsInvalid ) + { + HRESULT.ThrowLastError(); + } + + return hBitmap; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", EntryPoint = "CreateRoundRectRgn", SetLastError = true )] + private static extern IntPtr _CreateRoundRectRgn( int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr CreateRoundRectRgn( int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse ) + { + IntPtr ret = _CreateRoundRectRgn( nLeftRect, nTopRect, nRightRect, nBottomRect, nWidthEllipse, nHeightEllipse ); + if( IntPtr.Zero == ret ) + { + throw new Win32Exception(); + } + return ret; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", EntryPoint = "CreateRectRgn", SetLastError = true )] + private static extern IntPtr _CreateRectRgn( int nLeftRect, int nTopRect, int nRightRect, int nBottomRect ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr CreateRectRgn( int nLeftRect, int nTopRect, int nRightRect, int nBottomRect ) + { + IntPtr ret = _CreateRectRgn( nLeftRect, nTopRect, nRightRect, nBottomRect ); + if( IntPtr.Zero == ret ) + { + throw new Win32Exception(); + } + return ret; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", EntryPoint = "CreateRectRgnIndirect", SetLastError = true )] + private static extern IntPtr _CreateRectRgnIndirect( [In] ref RECT lprc ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr CreateRectRgnIndirect( RECT lprc ) + { + IntPtr ret = _CreateRectRgnIndirect( ref lprc ); + if( IntPtr.Zero == ret ) + { + throw new Win32Exception(); + } + return ret; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll" )] + public static extern IntPtr CreateSolidBrush( int crColor ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateWindowExW" )] + private static extern IntPtr _CreateWindowEx( + WS_EX dwExStyle, + [MarshalAs( UnmanagedType.LPWStr )] string lpClassName, + [MarshalAs( UnmanagedType.LPWStr )] string lpWindowName, + WS dwStyle, + int x, + int y, + int nWidth, + int nHeight, + IntPtr hWndParent, + IntPtr hMenu, + IntPtr hInstance, + IntPtr lpParam ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr CreateWindowEx( + WS_EX dwExStyle, + string lpClassName, + string lpWindowName, + WS dwStyle, + int x, + int y, + int nWidth, + int nHeight, + IntPtr hWndParent, + IntPtr hMenu, + IntPtr hInstance, + IntPtr lpParam ) + { + IntPtr ret = _CreateWindowEx( dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam ); + if( IntPtr.Zero == ret ) + { + HRESULT.ThrowLastError(); + } + + return ret; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", CharSet = CharSet.Unicode, EntryPoint = "DefWindowProcW" )] + public static extern IntPtr DefWindowProc( IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool DeleteObject( IntPtr hObject ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public RefRECT(int left, int top, int right, int bottom) - { - _left = left; - _top = top; - _right = right; - _bottom = bottom; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool DestroyIcon( IntPtr handle ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Width - { - get { return _right - _left; } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool DestroyWindow( IntPtr hwnd ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool IsWindow( IntPtr hwnd ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Height - { - get { return _bottom - _top; } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "dwmapi.dll", PreserveSig = false )] + public static extern void DwmExtendFrameIntoClientArea( IntPtr hwnd, ref MARGINS pMarInset ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Left - { - get { return _left; } - set { _left = value; } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "dwmapi.dll", EntryPoint = "DwmIsCompositionEnabled", PreserveSig = false )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _DwmIsCompositionEnabled(); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Right - { - get { return _right; } - set { _right = value; } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "dwmapi.dll", EntryPoint = "DwmGetColorizationColor", PreserveSig = true )] + private static extern HRESULT _DwmGetColorizationColor( out uint pcrColorization, [Out, MarshalAs( UnmanagedType.Bool )] out bool pfOpaqueBlend ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Top + public static bool DwmGetColorizationColor( out uint pcrColorization, out bool pfOpaqueBlend ) + { + // Make this call safe to make on downlevel OSes... + if( Utility.IsOSVistaOrNewer && IsThemeActive() ) + { + HRESULT hr = _DwmGetColorizationColor( out pcrColorization, out pfOpaqueBlend ); + if( hr.Succeeded ) { - get { return _top; } - set { _top = value; } - } + return true; + } + } + + // Default values. If for some reason the native DWM API fails it's never enough of a reason + // to bring down the app. Empirically it still sometimes returns errors even when the theme service is on. + // We'll still use the boolean return value to allow the caller to respond if they care. + pcrColorization = 0xFF000000; + pfOpaqueBlend = true; + + return false; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool DwmIsCompositionEnabled() + { + // Make this call safe to make on downlevel OSes... + if( !Utility.IsOSVistaOrNewer ) + { + return false; + } + return _DwmIsCompositionEnabled(); + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public int Bottom - { - get { return _bottom; } - set { _bottom = value; } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "dwmapi.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool DwmDefWindowProc( IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam, out IntPtr plResult ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public void Offset(int dx, int dy) - { - _left += dx; - _top += dy; - _right += dx; - _bottom += dy; - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "dwmapi.dll", EntryPoint = "DwmSetWindowAttribute" )] + private static extern void _DwmSetWindowAttribute( IntPtr hwnd, DWMWA dwAttribute, ref int pvAttribute, int cbAttribute ); - [StructLayout(LayoutKind.Sequential)] - internal struct SIZE + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void DwmSetWindowAttributeFlip3DPolicy( IntPtr hwnd, DWMFLIP3D flip3dPolicy ) { - public int cx; - public int cy; + Assert.IsTrue( Utility.IsOSVistaOrNewer ); + var dwPolicy = ( int )flip3dPolicy; + _DwmSetWindowAttribute( hwnd, DWMWA.FLIP3D_POLICY, ref dwPolicy, sizeof( int ) ); } - [StructLayout(LayoutKind.Sequential)] - internal struct StartupOutput + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void DwmSetWindowAttributeDisallowPeek( IntPtr hwnd, bool disallowPeek ) { - public IntPtr hook; - public IntPtr unhook; + Assert.IsTrue( Utility.IsOSWindows7OrNewer ); + int dwDisallow = ( int )( disallowPeek ? Win32Value.TRUE : Win32Value.FALSE ); + _DwmSetWindowAttribute( hwnd, DWMWA.DISALLOW_PEEK, ref dwDisallow, sizeof( int ) ); } - [StructLayout(LayoutKind.Sequential)] - internal class StartupInput - { - public int GdiplusVersion = 1; - public IntPtr DebugEventCallback; - public bool SuppressBackgroundThread; - public bool SuppressExternalCodecs; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "EnableMenuItem" )] + private static extern int _EnableMenuItem( IntPtr hMenu, SC uIDEnableItem, MF uEnable ); - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - [BestFitMapping(false)] - internal class WIN32_FIND_DATAW + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static MF EnableMenuItem( IntPtr hMenu, SC uIDEnableItem, MF uEnable ) { - public FileAttributes dwFileAttributes; - public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime; - public int nFileSizeHigh; - public int nFileSizeLow; - public int dwReserved0; - public int dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - [StructLayout(LayoutKind.Sequential)] - internal class WINDOWPLACEMENT - { - public int length = Marshal.SizeOf(typeof(WINDOWPLACEMENT)); - public int flags; - public SW showCmd; - public POINT ptMinPosition; - public POINT ptMaxPosition; - public RECT rcNormalPosition; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct WINDOWPOS - { - public IntPtr hwnd; - public IntPtr hwndInsertAfter; - public int x; - public int y; - public int cx; - public int cy; - public int flags; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct WNDCLASSEX - { - public int cbSize; - public CS style; - public WndProc lpfnWndProc; - public int cbClsExtra; - public int cbWndExtra; - public IntPtr hInstance; - public IntPtr hIcon; - public IntPtr hCursor; - public IntPtr hbrBackground; - [MarshalAs(UnmanagedType.LPWStr)] - public string lpszMenuName; - [MarshalAs(UnmanagedType.LPWStr)] - public string lpszClassName; - public IntPtr hIconSm; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct MOUSEINPUT - { - public int dx; - public int dy; - public int mouseData; - public int dwFlags; - public int time; - public IntPtr dwExtraInfo; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct INPUT - { - public uint type; - public MOUSEINPUT mi; - }; - - [StructLayout(LayoutKind.Sequential)] - internal struct UNSIGNED_RATIO - { - public uint uiNumerator; - public uint uiDenominator; - } - - [StructLayout(LayoutKind.Sequential, Pack=1)] - internal struct DWM_TIMING_INFO - { - public int cbSize; - public UNSIGNED_RATIO rateRefresh; - public ulong qpcRefreshPeriod; - public UNSIGNED_RATIO rateCompose; - public ulong qpcVBlank; - public ulong cRefresh; - public uint cDXRefresh; - public ulong qpcCompose; - public ulong cFrame; - public uint cDXPresent; - public ulong cRefreshFrame; - public ulong cFrameSubmitted; - public uint cDXPresentSubmitted; - public ulong cFrameConfirmed; - public uint cDXPresentConfirmed; - public ulong cRefreshConfirmed; - public uint cDXRefreshConfirmed; - public ulong cFramesLate; - public uint cFramesOutstanding; - public ulong cFrameDisplayed; - public ulong qpcFrameDisplayed; - public ulong cRefreshFrameDisplayed; - public ulong cFrameComplete; - public ulong qpcFrameComplete; - public ulong cFramePending; - public ulong qpcFramePending; - public ulong cFramesDisplayed; - public ulong cFramesComplete; - public ulong cFramesPending; - public ulong cFramesAvailable; - public ulong cFramesDropped; - public ulong cFramesMissed; - public ulong cRefreshNextDisplayed; - public ulong cRefreshNextPresented; - public ulong cRefreshesDisplayed; - public ulong cRefreshesPresented; - public ulong cRefreshStarted; - public ulong cPixelsReceived; - public ulong cPixelsDrawn; - public ulong cBuffersEmpty; + // Returns the previous state of the menu item, or -1 if the menu item does not exist. + int iRet = _EnableMenuItem( hMenu, uIDEnableItem, uEnable ); + return ( MF )iRet; } - #endregion - - /// Delegate declaration that matches native WndProc signatures. - internal delegate IntPtr WndProc(IntPtr hwnd, WM uMsg, IntPtr wParam, IntPtr lParam); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "RemoveMenu", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _RemoveMenu( IntPtr hMenu, uint uPosition, uint uFlags ); - /// Delegate declaration that matches native WndProc signatures. - internal delegate IntPtr WndProcHook(IntPtr hwnd, WM uMsg, IntPtr wParam, IntPtr lParam, ref bool handled); - - /// Delegate declaration that matches managed WndProc signatures. - internal delegate IntPtr MessageHandler(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled); - - // Some native methods are shimmed through public versions that handle converting failures into thrown exceptions. - internal static class NativeMethods + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void RemoveMenu( IntPtr hMenu, SC uPosition, MF uFlags ) { - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "AdjustWindowRectEx", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _AdjustWindowRectEx(ref RECT lpRect, WS dwStyle, [MarshalAs(UnmanagedType.Bool)] bool bMenu, WS_EX dwExStyle); - - public static RECT AdjustWindowRectEx(RECT lpRect, WS dwStyle, bool bMenu, WS_EX dwExStyle) - { - // Native version modifies the parameter in place. - if (!_AdjustWindowRectEx(ref lpRect, dwStyle, bMenu, dwExStyle)) - { - HRESULT.ThrowLastError(); - } - - return lpRect; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "ChangeWindowMessageFilter", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _ChangeWindowMessageFilter(WM message, MSGFLT dwFlag); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "ChangeWindowMessageFilterEx", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _ChangeWindowMessageFilterEx(IntPtr hwnd, WM message, MSGFLT action, [In, Out, Optional] ref CHANGEFILTERSTRUCT pChangeFilterStruct); - - // Note that processes at or below SECURITY_MANDATORY_LOW_RID are not allowed to change the message filter. - // If those processes call this function, it will fail and generate the extended error code, ERROR_ACCESS_DENIED. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static HRESULT ChangeWindowMessageFilterEx(IntPtr hwnd, WM message, MSGFLT action, out MSGFLTINFO filterInfo) - { - filterInfo = MSGFLTINFO.NONE; - - bool ret; - - // This origins of this API were added for Vista. The Ex version was added for Windows 7. - // If we're not on either, then this message filter isolation doesn't exist. - if (!Utility.IsOSVistaOrNewer) - { - return HRESULT.S_FALSE; - } - - // If we're on Vista rather than Win7 then we can't use the Ex version of this function. - // The Ex version is preferred if possible because this results in process-wide modifications of the filter - // and is deprecated as of Win7. - if (!Utility.IsOSWindows7OrNewer) - { - // Note that the Win7 MSGFLT_ALLOW/DISALLOW enum values map to the Vista MSGFLT_ADD/REMOVE - ret = _ChangeWindowMessageFilter(message, action); - if (!ret) - { - return (HRESULT)Win32Error.GetLastError(); - } - return HRESULT.S_OK; - } - - var filterstruct = new CHANGEFILTERSTRUCT { cbSize = (uint)Marshal.SizeOf(typeof(CHANGEFILTERSTRUCT)) }; - ret = _ChangeWindowMessageFilterEx(hwnd, message, action, ref filterstruct); - if (!ret) - { - return (HRESULT)Win32Error.GetLastError(); - } - - filterInfo = filterstruct.ExtStatus; - return HRESULT.S_OK; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll")] - public static extern CombineRgnResult CombineRgn(IntPtr hrgnDest, IntPtr hrgnSrc1, IntPtr hrgnSrc2, RGN fnCombineMode); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("shell32.dll", EntryPoint = "CommandLineToArgvW", CharSet = CharSet.Unicode)] - private static extern IntPtr _CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string cmdLine, out int numArgs); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static string[] CommandLineToArgvW(string cmdLine) - { - IntPtr argv = IntPtr.Zero; - try - { - int numArgs = 0; - - argv = _CommandLineToArgvW(cmdLine, out numArgs); - if (argv == IntPtr.Zero) - { - throw new Win32Exception(); - } - var result = new string[numArgs]; - - for (int i = 0; i < numArgs; i++) - { - IntPtr currArg = Marshal.ReadIntPtr(argv, i * Marshal.SizeOf(typeof(IntPtr))); - result[i] = Marshal.PtrToStringUni(currArg); - } - - return result; - } - finally - { - - IntPtr p = _LocalFree(argv); - // Otherwise LocalFree failed. - Assert.AreEqual(IntPtr.Zero, p); - } - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", EntryPoint = "CreateDIBSection", SetLastError = true)] - private static extern SafeHBITMAP _CreateDIBSection(SafeDC hdc, [In] ref BITMAPINFO bitmapInfo, int iUsage, [Out] out IntPtr ppvBits, IntPtr hSection, int dwOffset); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", EntryPoint = "CreateDIBSection", SetLastError = true)] - private static extern SafeHBITMAP _CreateDIBSectionIntPtr(IntPtr hdc, [In] ref BITMAPINFO bitmapInfo, int iUsage, [Out] out IntPtr ppvBits, IntPtr hSection, int dwOffset); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static SafeHBITMAP CreateDIBSection(SafeDC hdc, ref BITMAPINFO bitmapInfo, out IntPtr ppvBits, IntPtr hSection, int dwOffset) - { - const int DIB_RGB_COLORS = 0; - SafeHBITMAP hBitmap = null; - if (hdc == null) - { - hBitmap = _CreateDIBSectionIntPtr(IntPtr.Zero, ref bitmapInfo, DIB_RGB_COLORS, out ppvBits, hSection, dwOffset); - } - else - { - hBitmap = _CreateDIBSection(hdc, ref bitmapInfo, DIB_RGB_COLORS, out ppvBits, hSection, dwOffset); - } - - if (hBitmap.IsInvalid) - { - HRESULT.ThrowLastError(); - } - - return hBitmap; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", EntryPoint = "CreateRoundRectRgn", SetLastError = true)] - private static extern IntPtr _CreateRoundRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr CreateRoundRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse) - { - IntPtr ret = _CreateRoundRectRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, nWidthEllipse, nHeightEllipse); - if (IntPtr.Zero == ret) - { - throw new Win32Exception(); - } - return ret; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", EntryPoint = "CreateRectRgn", SetLastError = true)] - private static extern IntPtr _CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) - { - IntPtr ret = _CreateRectRgn(nLeftRect, nTopRect, nRightRect, nBottomRect); - if (IntPtr.Zero == ret) - { - throw new Win32Exception(); - } - return ret; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", EntryPoint = "CreateRectRgnIndirect", SetLastError = true)] - private static extern IntPtr _CreateRectRgnIndirect([In] ref RECT lprc); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr CreateRectRgnIndirect(RECT lprc) - { - IntPtr ret = _CreateRectRgnIndirect(ref lprc); - if (IntPtr.Zero == ret) - { - throw new Win32Exception(); - } - return ret; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll")] - public static extern IntPtr CreateSolidBrush(int crColor); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateWindowExW")] - private static extern IntPtr _CreateWindowEx( - WS_EX dwExStyle, - [MarshalAs(UnmanagedType.LPWStr)] string lpClassName, - [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, - WS dwStyle, - int x, - int y, - int nWidth, - int nHeight, - IntPtr hWndParent, - IntPtr hMenu, - IntPtr hInstance, - IntPtr lpParam); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr CreateWindowEx( - WS_EX dwExStyle, - string lpClassName, - string lpWindowName, - WS dwStyle, - int x, - int y, - int nWidth, - int nHeight, - IntPtr hWndParent, - IntPtr hMenu, - IntPtr hInstance, - IntPtr lpParam) - { - IntPtr ret = _CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); - if (IntPtr.Zero == ret) - { - HRESULT.ThrowLastError(); - } - - return ret; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "DefWindowProcW")] - public static extern IntPtr DefWindowProc(IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DeleteObject(IntPtr hObject); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DestroyIcon(IntPtr handle); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DestroyWindow(IntPtr hwnd); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsWindow(IntPtr hwnd); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS pMarInset); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("dwmapi.dll", EntryPoint = "DwmIsCompositionEnabled", PreserveSig = false)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _DwmIsCompositionEnabled(); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("dwmapi.dll", EntryPoint = "DwmGetColorizationColor", PreserveSig = true)] - private static extern HRESULT _DwmGetColorizationColor(out uint pcrColorization, [Out, MarshalAs(UnmanagedType.Bool)] out bool pfOpaqueBlend); - - public static bool DwmGetColorizationColor(out uint pcrColorization, out bool pfOpaqueBlend) - { - // Make this call safe to make on downlevel OSes... - if (Utility.IsOSVistaOrNewer && IsThemeActive()) - { - HRESULT hr = _DwmGetColorizationColor(out pcrColorization, out pfOpaqueBlend); - if (hr.Succeeded) - { - return true; - } - } - - // Default values. If for some reason the native DWM API fails it's never enough of a reason - // to bring down the app. Empirically it still sometimes returns errors even when the theme service is on. - // We'll still use the boolean return value to allow the caller to respond if they care. - pcrColorization = 0xFF000000; - pfOpaqueBlend = true; - - return false; - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool DwmIsCompositionEnabled() - { - // Make this call safe to make on downlevel OSes... - if (!Utility.IsOSVistaOrNewer) - { - return false; - } - return _DwmIsCompositionEnabled(); - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("dwmapi.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DwmDefWindowProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam, out IntPtr plResult); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("dwmapi.dll", EntryPoint = "DwmSetWindowAttribute")] - private static extern void _DwmSetWindowAttribute(IntPtr hwnd, DWMWA dwAttribute, ref int pvAttribute, int cbAttribute); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void DwmSetWindowAttributeFlip3DPolicy(IntPtr hwnd, DWMFLIP3D flip3dPolicy) - { - Assert.IsTrue(Utility.IsOSVistaOrNewer); - var dwPolicy = (int)flip3dPolicy; - _DwmSetWindowAttribute(hwnd, DWMWA.FLIP3D_POLICY, ref dwPolicy, sizeof(int)); - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void DwmSetWindowAttributeDisallowPeek(IntPtr hwnd, bool disallowPeek) - { - Assert.IsTrue(Utility.IsOSWindows7OrNewer); - int dwDisallow = (int)(disallowPeek ? Win32Value.TRUE : Win32Value.FALSE); - _DwmSetWindowAttribute(hwnd, DWMWA.DISALLOW_PEEK, ref dwDisallow, sizeof(int)); - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "EnableMenuItem")] - private static extern int _EnableMenuItem(IntPtr hMenu, SC uIDEnableItem, MF uEnable); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static MF EnableMenuItem(IntPtr hMenu, SC uIDEnableItem, MF uEnable) - { - // Returns the previous state of the menu item, or -1 if the menu item does not exist. - int iRet = _EnableMenuItem(hMenu, uIDEnableItem, uEnable); - return (MF)iRet; - } + if( !_RemoveMenu( hMenu, ( uint )uPosition, ( uint )uFlags ) ) + { + throw new Win32Exception(); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "RemoveMenu", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "DrawMenuBar", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _DrawMenuBar( IntPtr hWnd ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void RemoveMenu(IntPtr hMenu, SC uPosition, MF uFlags) - { - if (!_RemoveMenu(hMenu, (uint)uPosition, (uint)uFlags)) - { - throw new Win32Exception(); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void DrawMenuBar( IntPtr hWnd ) + { + if( !_DrawMenuBar( hWnd ) ) + { + throw new Win32Exception(); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "DrawMenuBar", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _DrawMenuBar(IntPtr hWnd); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "kernel32.dll" )] + [ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool FindClose( IntPtr handle ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void DrawMenuBar(IntPtr hWnd) - { - if (!_DrawMenuBar(hWnd)) - { - throw new Win32Exception(); - } - } + // Not shimming this SetLastError=true function because callers want to evaluate the reason for failure. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true )] + public static extern SafeFindHandle FindFirstFileW( string lpFileName, [In, Out, MarshalAs( UnmanagedType.LPStruct )] WIN32_FIND_DATAW lpFindFileData ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("kernel32.dll")] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool FindClose(IntPtr handle); - - // Not shimming this SetLastError=true function because callers want to evaluate the reason for failure. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern SafeFindHandle FindFirstFileW(string lpFileName, [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_DATAW lpFindFileData); - - // Not shimming this SetLastError=true function because callers want to evaluate the reason for failure. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool FindNextFileW(SafeFindHandle hndFindFile, [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_DATAW lpFindFileData); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "GetClientRect", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _GetClientRect(IntPtr hwnd, [Out] out RECT lpRect); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static RECT GetClientRect(IntPtr hwnd) - { - RECT rc; - if (!_GetClientRect(hwnd, out rc)) - { - HRESULT.ThrowLastError(); - } - return rc; - } + // Not shimming this SetLastError=true function because callers want to evaluate the reason for failure. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "kernel32.dll", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool FindNextFileW( SafeFindHandle hndFindFile, [In, Out, MarshalAs( UnmanagedType.LPStruct )] WIN32_FIND_DATAW lpFindFileData ); - [DllImport("uxtheme.dll", EntryPoint="GetCurrentThemeName", CharSet = CharSet.Unicode)] - private static extern HRESULT _GetCurrentThemeName( - StringBuilder pszThemeFileName, - int dwMaxNameChars, - StringBuilder pszColorBuff, - int cchMaxColorChars, - StringBuilder pszSizeBuff, - int cchMaxSizeChars); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "GetClientRect", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _GetClientRect( IntPtr hwnd, [Out] out RECT lpRect ); - public static void GetCurrentThemeName(out string themeFileName, out string color, out string size) - { - // Not expecting strings longer than MAX_PATH. We will return the error - var fileNameBuilder = new StringBuilder((int)Win32Value.MAX_PATH); - var colorBuilder = new StringBuilder((int)Win32Value.MAX_PATH); - var sizeBuilder = new StringBuilder((int)Win32Value.MAX_PATH); - - // This will throw if the theme service is not active (e.g. not UxTheme!IsThemeActive). - _GetCurrentThemeName(fileNameBuilder, fileNameBuilder.Capacity, - colorBuilder, colorBuilder.Capacity, - sizeBuilder, sizeBuilder.Capacity) - .ThrowIfFailed(); - - themeFileName = fileNameBuilder.ToString(); - color = colorBuilder.ToString(); - size = sizeBuilder.ToString(); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static RECT GetClientRect( IntPtr hwnd ) + { + RECT rc; + if( !_GetClientRect( hwnd, out rc ) ) + { + HRESULT.ThrowLastError(); + } + return rc; + } - [DllImport("uxtheme.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsThemeActive(); + [DllImport( "uxtheme.dll", EntryPoint = "GetCurrentThemeName", CharSet = CharSet.Unicode )] + private static extern HRESULT _GetCurrentThemeName( + StringBuilder pszThemeFileName, + int dwMaxNameChars, + StringBuilder pszColorBuff, + int cchMaxColorChars, + StringBuilder pszSizeBuff, + int cchMaxSizeChars ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [Obsolete("Use SafeDC.GetDC instead.", true)] - public static void GetDC() { } + public static void GetCurrentThemeName( out string themeFileName, out string color, out string size ) + { + // Not expecting strings longer than MAX_PATH. We will return the error + var fileNameBuilder = new StringBuilder( ( int )Win32Value.MAX_PATH ); + var colorBuilder = new StringBuilder( ( int )Win32Value.MAX_PATH ); + var sizeBuilder = new StringBuilder( ( int )Win32Value.MAX_PATH ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll")] - public static extern int GetDeviceCaps(SafeDC hdc, DeviceCap nIndex); + // This will throw if the theme service is not active (e.g. not UxTheme!IsThemeActive). + _GetCurrentThemeName( fileNameBuilder, fileNameBuilder.Capacity, + colorBuilder, colorBuilder.Capacity, + sizeBuilder, sizeBuilder.Capacity ) + .ThrowIfFailed(); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("kernel32.dll", EntryPoint = "GetModuleFileName", CharSet = CharSet.Unicode, SetLastError = true)] - private static extern int _GetModuleFileName(IntPtr hModule, StringBuilder lpFilename, int nSize); + themeFileName = fileNameBuilder.ToString(); + color = colorBuilder.ToString(); + size = sizeBuilder.ToString(); + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static string GetModuleFileName(IntPtr hModule) - { - var buffer = new StringBuilder((int)Win32Value.MAX_PATH); - while (true) - { - int size = _GetModuleFileName(hModule, buffer, buffer.Capacity); - if (size == 0) - { - HRESULT.ThrowLastError(); - } - - // GetModuleFileName returns nSize when it's truncated but does NOT set the last error. - // MSDN documentation says this has changed in Windows 2000+. - if (size == buffer.Capacity) - { - // Enlarge the buffer and try again. - buffer.EnsureCapacity(buffer.Capacity * 2); - continue; - } - - return buffer.ToString(); - } - } + [DllImport( "uxtheme.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool IsThemeActive(); - [DllImport("kernel32.dll", EntryPoint = "GetModuleHandleW", CharSet = CharSet.Unicode, SetLastError = true)] - private static extern IntPtr _GetModuleHandle([MarshalAs(UnmanagedType.LPWStr)] string lpModuleName); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [Obsolete( "Use SafeDC.GetDC instead.", true )] + public static void GetDC() + { + } - public static IntPtr GetModuleHandle(string lpModuleName) - { - IntPtr retPtr = _GetModuleHandle(lpModuleName); - if (retPtr == IntPtr.Zero) - { - HRESULT.ThrowLastError(); - } - return retPtr; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll" )] + public static extern int GetDeviceCaps( SafeDC hdc, DeviceCap nIndex ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "GetMonitorInfo", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _GetMonitorInfo(IntPtr hMonitor, [In, Out] MONITORINFO lpmi); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "kernel32.dll", EntryPoint = "GetModuleFileName", CharSet = CharSet.Unicode, SetLastError = true )] + private static extern int _GetModuleFileName( IntPtr hModule, StringBuilder lpFilename, int nSize ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static MONITORINFO GetMonitorInfo(IntPtr hMonitor) + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static string GetModuleFileName( IntPtr hModule ) + { + var buffer = new StringBuilder( ( int )Win32Value.MAX_PATH ); + while( true ) + { + int size = _GetModuleFileName( hModule, buffer, buffer.Capacity ); + if( size == 0 ) { - var mi = new MONITORINFO(); - if (!_GetMonitorInfo(hMonitor, mi)) - { - throw new Win32Exception(); - } - return mi; + HRESULT.ThrowLastError(); } - [DllImport("gdi32.dll", EntryPoint = "GetStockObject", SetLastError = true)] - private static extern IntPtr _GetStockObject(StockObject fnObject); - - public static IntPtr GetStockObject(StockObject fnObject) + // GetModuleFileName returns nSize when it's truncated but does NOT set the last error. + // MSDN documentation says this has changed in Windows 2000+. + if( size == buffer.Capacity ) { - IntPtr retPtr = _GetStockObject(fnObject); - if (retPtr == null) - { - HRESULT.ThrowLastError(); - } - return retPtr; + // Enlarge the buffer and try again. + buffer.EnsureCapacity( buffer.Capacity * 2 ); + continue; } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll")] - public static extern IntPtr GetSystemMenu(IntPtr hWnd, [MarshalAs(UnmanagedType.Bool)] bool bRevert); + return buffer.ToString(); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll")] - public static extern int GetSystemMetrics(SM nIndex); + [DllImport( "kernel32.dll", EntryPoint = "GetModuleHandleW", CharSet = CharSet.Unicode, SetLastError = true )] + private static extern IntPtr _GetModuleHandle( [MarshalAs( UnmanagedType.LPWStr )] string lpModuleName ); - // This is aliased as a macro in 32bit Windows. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr GetWindowLongPtr(IntPtr hwnd, GWL nIndex) - { - IntPtr ret = IntPtr.Zero; - if (8 == IntPtr.Size) - { - ret = GetWindowLongPtr64(hwnd, nIndex); - } - else - { - ret = new IntPtr(GetWindowLongPtr32(hwnd, nIndex)); - } - if (IntPtr.Zero == ret) - { - throw new Win32Exception(); - } - return ret; - } + public static IntPtr GetModuleHandle( string lpModuleName ) + { + IntPtr retPtr = _GetModuleHandle( lpModuleName ); + if( retPtr == IntPtr.Zero ) + { + HRESULT.ThrowLastError(); + } + return retPtr; + } - /// - /// Sets attributes to control how visual styles are applied to a specified window. - /// - /// - /// Handle to a window to apply changes to. - /// - /// - /// Value of type WINDOWTHEMEATTRIBUTETYPE that specifies the type of attribute to set. - /// The value of this parameter determines the type of data that should be passed in the pvAttribute parameter. - /// Can be the following value: - /// WTA_NONCLIENT (Specifies non-client related attributes). - /// pvAttribute must be a pointer of type WTA_OPTIONS. - /// - /// - /// A pointer that specifies attributes to set. Type is determined by the value of the eAttribute value. - /// - /// - /// Specifies the size, in bytes, of the data pointed to by pvAttribute. - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("uxtheme.dll", PreserveSig = false)] - public static extern void SetWindowThemeAttribute([In] IntPtr hwnd, [In] WINDOWTHEMEATTRIBUTETYPE eAttribute, [In] ref WTA_OPTIONS pvAttribute, [In] uint cbAttribute); - - [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "GetWindowLong", SetLastError = true)] - private static extern int GetWindowLongPtr32(IntPtr hWnd, GWL nIndex); - - [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", SetLastError = true)] - private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, GWL nIndex); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetWindowPlacement(IntPtr hwnd, WINDOWPLACEMENT lpwndpl); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static WINDOWPLACEMENT GetWindowPlacement(IntPtr hwnd) - { - WINDOWPLACEMENT wndpl = new WINDOWPLACEMENT(); - if (GetWindowPlacement(hwnd, wndpl)) - { - return wndpl; - } - throw new Win32Exception(); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "GetMonitorInfo", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _GetMonitorInfo( IntPtr hMonitor, [In, Out] MONITORINFO lpmi ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "GetWindowRect", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _GetWindowRect(IntPtr hWnd, out RECT lpRect); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static MONITORINFO GetMonitorInfo( IntPtr hMonitor ) + { + var mi = new MONITORINFO(); + if( !_GetMonitorInfo( hMonitor, mi ) ) + { + throw new Win32Exception(); + } + return mi; + } - public static RECT GetWindowRect(IntPtr hwnd) - { - RECT rc; - if (!_GetWindowRect(hwnd, out rc)) - { - HRESULT.ThrowLastError(); - } - return rc; - } + [DllImport( "gdi32.dll", EntryPoint = "GetStockObject", SetLastError = true )] + private static extern IntPtr _GetStockObject( StockObject fnObject ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdiplus.dll")] - public static extern Status GdipCreateBitmapFromStream(IStream stream, out IntPtr bitmap); + public static IntPtr GetStockObject( StockObject fnObject ) + { + IntPtr retPtr = _GetStockObject( fnObject ); + if( retPtr == null ) + { + HRESULT.ThrowLastError(); + } + return retPtr; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdiplus.dll")] - public static extern Status GdipCreateHBITMAPFromBitmap(IntPtr bitmap, out IntPtr hbmReturn, Int32 background); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll" )] + public static extern IntPtr GetSystemMenu( IntPtr hWnd, [MarshalAs( UnmanagedType.Bool )] bool bRevert ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdiplus.dll")] - public static extern Status GdipCreateHICONFromBitmap(IntPtr bitmap, out IntPtr hbmReturn); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll" )] + public static extern int GetSystemMetrics( SM nIndex ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdiplus.dll")] - public static extern Status GdipDisposeImage(IntPtr image); + // This is aliased as a macro in 32bit Windows. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr GetWindowLongPtr( IntPtr hwnd, GWL nIndex ) + { + IntPtr ret = IntPtr.Zero; + if( 8 == IntPtr.Size ) + { + ret = GetWindowLongPtr64( hwnd, nIndex ); + } + else + { + ret = new IntPtr( GetWindowLongPtr32( hwnd, nIndex ) ); + } + if( IntPtr.Zero == ret ) + { + throw new Win32Exception(); + } + return ret; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdiplus.dll")] - public static extern Status GdipImageForceValidation(IntPtr image); + /// + /// Sets attributes to control how visual styles are applied to a specified window. + /// + /// + /// Handle to a window to apply changes to. + /// + /// + /// Value of type WINDOWTHEMEATTRIBUTETYPE that specifies the type of attribute to set. + /// The value of this parameter determines the type of data that should be passed in the pvAttribute parameter. + /// Can be the following value: + /// WTA_NONCLIENT (Specifies non-client related attributes). + /// pvAttribute must be a pointer of type WTA_OPTIONS. + /// + /// + /// A pointer that specifies attributes to set. Type is determined by the value of the eAttribute value. + /// + /// + /// Specifies the size, in bytes, of the data pointed to by pvAttribute. + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "uxtheme.dll", PreserveSig = false )] + public static extern void SetWindowThemeAttribute( [In] IntPtr hwnd, [In] WINDOWTHEMEATTRIBUTETYPE eAttribute, [In] ref WTA_OPTIONS pvAttribute, [In] uint cbAttribute ); + + [SuppressMessage( "Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "GetWindowLong", SetLastError = true )] + private static extern int GetWindowLongPtr32( IntPtr hWnd, GWL nIndex ); + + [SuppressMessage( "Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "GetWindowLongPtr", SetLastError = true )] + private static extern IntPtr GetWindowLongPtr64( IntPtr hWnd, GWL nIndex ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool GetWindowPlacement( IntPtr hwnd, WINDOWPLACEMENT lpwndpl ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static WINDOWPLACEMENT GetWindowPlacement( IntPtr hwnd ) + { + WINDOWPLACEMENT wndpl = new WINDOWPLACEMENT(); + if( GetWindowPlacement( hwnd, wndpl ) ) + { + return wndpl; + } + throw new Win32Exception(); + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "GetWindowRect", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _GetWindowRect( IntPtr hWnd, out RECT lpRect ); + + public static RECT GetWindowRect( IntPtr hwnd ) + { + RECT rc; + if( !_GetWindowRect( hwnd, out rc ) ) + { + HRESULT.ThrowLastError(); + } + return rc; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdiplus.dll" )] + public static extern Status GdipCreateBitmapFromStream( IStream stream, out IntPtr bitmap ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdiplus.dll" )] + public static extern Status GdipCreateHBITMAPFromBitmap( IntPtr bitmap, out IntPtr hbmReturn, Int32 background ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdiplus.dll" )] + public static extern Status GdipCreateHICONFromBitmap( IntPtr bitmap, out IntPtr hbmReturn ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdiplus.dll" )] + public static extern Status GdipDisposeImage( IntPtr image ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdiplus.dll" )] + public static extern Status GdipImageForceValidation( IntPtr image ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdiplus.dll" )] + public static extern Status GdiplusStartup( out IntPtr token, StartupInput input, out StartupOutput output ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdiplus.dll" )] + public static extern Status GdiplusShutdown( IntPtr token ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool IsWindowVisible( IntPtr hwnd ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "kernel32.dll", EntryPoint = "LocalFree", SetLastError = true )] + private static extern IntPtr _LocalFree( IntPtr hMem ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll" )] + public static extern IntPtr MonitorFromWindow( IntPtr hwnd, uint dwFlags ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "PostMessage", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _PostMessage( IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void PostMessage( IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam ) + { + if( !_PostMessage( hWnd, Msg, wParam, lParam ) ) + { + throw new Win32Exception(); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdiplus.dll")] - public static extern Status GdiplusStartup(out IntPtr token, StartupInput input, out StartupOutput output); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", SetLastError = true, EntryPoint = "RegisterClassExW" )] + private static extern short _RegisterClassEx( [In] ref WNDCLASSEX lpwcx ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdiplus.dll")] - public static extern Status GdiplusShutdown(IntPtr token); + // Note that this will throw HRESULT_FROM_WIN32(ERROR_CLASS_ALREADY_EXISTS) on duplicate registration. + // If needed, consider adding a Try* version of this function that returns the error code since that + // may be ignorable. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static short RegisterClassEx( ref WNDCLASSEX lpwcx ) + { + short ret = _RegisterClassEx( ref lpwcx ); + if( ret == 0 ) + { + HRESULT.ThrowLastError(); + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsWindowVisible(IntPtr hwnd); + return ret; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("kernel32.dll", EntryPoint = "LocalFree", SetLastError = true)] - private static extern IntPtr _LocalFree(IntPtr hMem); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "RegisterWindowMessage", SetLastError = true, CharSet = CharSet.Unicode )] + private static extern uint _RegisterWindowMessage( [MarshalAs( UnmanagedType.LPWStr )] string lpString ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll")] - public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static WM RegisterWindowMessage( string lpString ) + { + uint iRet = _RegisterWindowMessage( lpString ); + if( iRet == 0 ) + { + HRESULT.ThrowLastError(); + } + return ( WM )iRet; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "PostMessage", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _PostMessage(IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SetActiveWindow", SetLastError = true )] + private static extern IntPtr _SetActiveWindow( IntPtr hWnd ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void PostMessage(IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam) - { - if (!_PostMessage(hWnd, Msg, wParam, lParam)) - { - throw new Win32Exception(); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr SetActiveWindow( IntPtr hwnd ) + { + Verify.IsNotDefault( hwnd, "hwnd" ); + IntPtr ret = _SetActiveWindow( hwnd ); + if( ret == IntPtr.Zero ) + { + HRESULT.ThrowLastError(); + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassExW")] - private static extern short _RegisterClassEx([In] ref WNDCLASSEX lpwcx); + return ret; + } - // Note that this will throw HRESULT_FROM_WIN32(ERROR_CLASS_ALREADY_EXISTS) on duplicate registration. - // If needed, consider adding a Try* version of this function that returns the error code since that - // may be ignorable. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static short RegisterClassEx(ref WNDCLASSEX lpwcx) - { - short ret = _RegisterClassEx(ref lpwcx); - if (ret == 0) - { - HRESULT.ThrowLastError(); - } + // This is aliased as a macro in 32bit Windows. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr SetClassLongPtr( IntPtr hwnd, GCLP nIndex, IntPtr dwNewLong ) + { + if( 8 == IntPtr.Size ) + { + return SetClassLongPtr64( hwnd, nIndex, dwNewLong ); + } + return new IntPtr( SetClassLongPtr32( hwnd, nIndex, dwNewLong.ToInt32() ) ); + } - return ret; - } + [SuppressMessage( "Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SetClassLong", SetLastError = true )] + private static extern int SetClassLongPtr32( IntPtr hWnd, GCLP nIndex, int dwNewLong ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "RegisterWindowMessage", SetLastError = true, CharSet = CharSet.Unicode)] - private static extern uint _RegisterWindowMessage([MarshalAs(UnmanagedType.LPWStr)] string lpString); + [SuppressMessage( "Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SetClassLongPtr", SetLastError = true )] + private static extern IntPtr SetClassLongPtr64( IntPtr hWnd, GCLP nIndex, IntPtr dwNewLong ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static WM RegisterWindowMessage(string lpString) - { - uint iRet = _RegisterWindowMessage(lpString); - if (iRet == 0) - { - HRESULT.ThrowLastError(); - } - return (WM)iRet; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "kernel32.dll", SetLastError = true )] + public static extern ErrorModes SetErrorMode( ErrorModes newMode ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SetActiveWindow", SetLastError = true)] - private static extern IntPtr _SetActiveWindow(IntPtr hWnd); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "kernel32.dll", SetLastError = true, EntryPoint = "SetProcessWorkingSetSize" )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _SetProcessWorkingSetSize( IntPtr hProcess, IntPtr dwMinimiumWorkingSetSize, IntPtr dwMaximumWorkingSetSize ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr SetActiveWindow(IntPtr hwnd) - { - Verify.IsNotDefault(hwnd, "hwnd"); - IntPtr ret = _SetActiveWindow(hwnd); - if (ret == IntPtr.Zero) - { - HRESULT.ThrowLastError(); - } - - return ret; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SetProcessWorkingSetSize( IntPtr hProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize ) + { + if( !_SetProcessWorkingSetSize( hProcess, new IntPtr( dwMinimumWorkingSetSize ), new IntPtr( dwMaximumWorkingSetSize ) ) ) + { + throw new Win32Exception(); + } + } - // This is aliased as a macro in 32bit Windows. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr SetClassLongPtr(IntPtr hwnd, GCLP nIndex, IntPtr dwNewLong) - { - if (8 == IntPtr.Size) - { - return SetClassLongPtr64(hwnd, nIndex, dwNewLong); - } - return new IntPtr(SetClassLongPtr32(hwnd, nIndex, dwNewLong.ToInt32())); - } + // This is aliased as a macro in 32bit Windows. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr SetWindowLongPtr( IntPtr hwnd, GWL nIndex, IntPtr dwNewLong ) + { + if( 8 == IntPtr.Size ) + { + return SetWindowLongPtr64( hwnd, nIndex, dwNewLong ); + } + return new IntPtr( SetWindowLongPtr32( hwnd, nIndex, dwNewLong.ToInt32() ) ); + } - [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SetClassLong", SetLastError = true)] - private static extern int SetClassLongPtr32(IntPtr hWnd, GCLP nIndex, int dwNewLong); + [SuppressMessage( "Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SetWindowLong", SetLastError = true )] + private static extern int SetWindowLongPtr32( IntPtr hWnd, GWL nIndex, int dwNewLong ); - [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SetClassLongPtr", SetLastError = true)] - private static extern IntPtr SetClassLongPtr64(IntPtr hWnd, GCLP nIndex, IntPtr dwNewLong); + [SuppressMessage( "Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true )] + private static extern IntPtr SetWindowLongPtr64( IntPtr hWnd, GWL nIndex, IntPtr dwNewLong ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("kernel32.dll", SetLastError = true)] - public static extern ErrorModes SetErrorMode(ErrorModes newMode); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SetWindowRgn", SetLastError = true )] + private static extern int _SetWindowRgn( IntPtr hWnd, IntPtr hRgn, [MarshalAs( UnmanagedType.Bool )] bool bRedraw ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "SetProcessWorkingSetSize")] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _SetProcessWorkingSetSize(IntPtr hProcess, IntPtr dwMinimiumWorkingSetSize, IntPtr dwMaximumWorkingSetSize); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SetWindowRgn( IntPtr hWnd, IntPtr hRgn, bool bRedraw ) + { + int err = _SetWindowRgn( hWnd, hRgn, bRedraw ); + if( 0 == err ) + { + throw new Win32Exception(); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SetProcessWorkingSetSize(IntPtr hProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize) - { - if (!_SetProcessWorkingSetSize(hProcess, new IntPtr(dwMinimumWorkingSetSize), new IntPtr(dwMaximumWorkingSetSize))) - { - throw new Win32Exception(); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SetWindowPos", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _SetWindowPos( IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SWP uFlags ); - // This is aliased as a macro in 32bit Windows. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr SetWindowLongPtr(IntPtr hwnd, GWL nIndex, IntPtr dwNewLong) - { - if (8 == IntPtr.Size) - { - return SetWindowLongPtr64(hwnd, nIndex, dwNewLong); - } - return new IntPtr(SetWindowLongPtr32(hwnd, nIndex, dwNewLong.ToInt32())); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool SetWindowPos( IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SWP uFlags ) + { + if( !_SetWindowPos( hWnd, hWndInsertAfter, x, y, cx, cy, uFlags ) ) + { + // If this fails it's never worth taking down the process. Let the caller deal with the error if they want. + return false; + } - [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)] - private static extern int SetWindowLongPtr32(IntPtr hWnd, GWL nIndex, int dwNewLong); + return true; + } - [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)] - private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, GWL nIndex, IntPtr dwNewLong); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "shell32.dll", SetLastError = false )] + public static extern Win32Error SHFileOperation( ref SHFILEOPSTRUCT lpFileOp ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SetWindowRgn", SetLastError = true)] - private static extern int _SetWindowRgn(IntPtr hWnd, IntPtr hRgn, [MarshalAs(UnmanagedType.Bool)] bool bRedraw); + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool ShowWindow( IntPtr hwnd, SW nCmdShow ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool bRedraw) - { - int err = _SetWindowRgn(hWnd, hRgn, bRedraw); - if (0 == err) - { - throw new Win32Exception(); - } - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SetWindowPos", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SWP uFlags); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SystemParametersInfoW", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _SystemParametersInfo_String( SPI uiAction, int uiParam, [MarshalAs( UnmanagedType.LPWStr )] string pvParam, SPIF fWinIni ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SWP uFlags) - { - if (!_SetWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags)) - { - // If this fails it's never worth taking down the process. Let the caller deal with the error if they want. - return false; - } + /// Overload of SystemParametersInfo for getting and setting NONCLIENTMETRICS. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SystemParametersInfoW", SetLastError = true, CharSet = CharSet.Unicode )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _SystemParametersInfo_NONCLIENTMETRICS( SPI uiAction, int uiParam, [In, Out] ref NONCLIENTMETRICS pvParam, SPIF fWinIni ); - return true; - } + /// Overload of SystemParametersInfo for getting and setting HIGHCONTRAST. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "SystemParametersInfoW", SetLastError = true, CharSet = CharSet.Unicode )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _SystemParametersInfo_HIGHCONTRAST( SPI uiAction, int uiParam, [In, Out] ref HIGHCONTRAST pvParam, SPIF fWinIni ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("shell32.dll", SetLastError = false)] - public static extern Win32Error SHFileOperation(ref SHFILEOPSTRUCT lpFileOp); - - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool ShowWindow(IntPtr hwnd, SW nCmdShow); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SystemParametersInfoW", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _SystemParametersInfo_String(SPI uiAction, int uiParam, [MarshalAs(UnmanagedType.LPWStr)] string pvParam, SPIF fWinIni); - - /// Overload of SystemParametersInfo for getting and setting NONCLIENTMETRICS. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SystemParametersInfoW", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _SystemParametersInfo_NONCLIENTMETRICS(SPI uiAction, int uiParam, [In, Out] ref NONCLIENTMETRICS pvParam, SPIF fWinIni); - - /// Overload of SystemParametersInfo for getting and setting HIGHCONTRAST. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "SystemParametersInfoW", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _SystemParametersInfo_HIGHCONTRAST(SPI uiAction, int uiParam, [In, Out] ref HIGHCONTRAST pvParam, SPIF fWinIni); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SystemParametersInfo(SPI uiAction, int uiParam, string pvParam, SPIF fWinIni) - { - if (!_SystemParametersInfo_String(uiAction, uiParam, pvParam, fWinIni)) - { - HRESULT.ThrowLastError(); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SystemParametersInfo( SPI uiAction, int uiParam, string pvParam, SPIF fWinIni ) + { + if( !_SystemParametersInfo_String( uiAction, uiParam, pvParam, fWinIni ) ) + { + HRESULT.ThrowLastError(); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static NONCLIENTMETRICS SystemParameterInfo_GetNONCLIENTMETRICS() - { - var metrics = Utility.IsOSVistaOrNewer - ? NONCLIENTMETRICS.VistaMetricsStruct - : NONCLIENTMETRICS.XPMetricsStruct; + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static NONCLIENTMETRICS SystemParameterInfo_GetNONCLIENTMETRICS() + { + var metrics = Utility.IsOSVistaOrNewer + ? NONCLIENTMETRICS.VistaMetricsStruct + : NONCLIENTMETRICS.XPMetricsStruct; - if (!_SystemParametersInfo_NONCLIENTMETRICS(SPI.GETNONCLIENTMETRICS, metrics.cbSize, ref metrics, SPIF.None)) - { - HRESULT.ThrowLastError(); - } + if( !_SystemParametersInfo_NONCLIENTMETRICS( SPI.GETNONCLIENTMETRICS, metrics.cbSize, ref metrics, SPIF.None ) ) + { + HRESULT.ThrowLastError(); + } - return metrics; - } + return metrics; + } - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public static HIGHCONTRAST SystemParameterInfo_GetHIGHCONTRAST() - { - var hc = new HIGHCONTRAST { cbSize = Marshal.SizeOf(typeof(HIGHCONTRAST)) }; + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public static HIGHCONTRAST SystemParameterInfo_GetHIGHCONTRAST() + { + var hc = new HIGHCONTRAST { cbSize = Marshal.SizeOf( typeof( HIGHCONTRAST ) ) }; - if (!_SystemParametersInfo_HIGHCONTRAST(SPI.GETHIGHCONTRAST, hc.cbSize, ref hc, SPIF.None)) - { - HRESULT.ThrowLastError(); - } + if( !_SystemParametersInfo_HIGHCONTRAST( SPI.GETHIGHCONTRAST, hc.cbSize, ref hc, SPIF.None ) ) + { + HRESULT.ThrowLastError(); + } - return hc; - } + return hc; + } - // This function is strange in that it returns a BOOL if TPM_RETURNCMD isn't specified, but otherwise the command Id. - // Currently it's only used with TPM_RETURNCMD, so making the signature match that. - [DllImport("user32.dll")] - public static extern uint TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm); + // This function is strange in that it returns a BOOL if TPM_RETURNCMD isn't specified, but otherwise the command Id. + // Currently it's only used with TPM_RETURNCMD, so making the signature match that. + [DllImport( "user32.dll" )] + public static extern uint TrackPopupMenuEx( IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", EntryPoint = "SelectObject", SetLastError = true )] + private static extern IntPtr _SelectObject( SafeDC hdc, IntPtr hgdiobj ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr SelectObject( SafeDC hdc, IntPtr hgdiobj ) + { + IntPtr ret = _SelectObject( hdc, hgdiobj ); + if( ret == IntPtr.Zero ) + { + HRESULT.ThrowLastError(); + } + return ret; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "gdi32.dll", EntryPoint = "SelectObject", SetLastError = true )] + private static extern IntPtr _SelectObjectSafeHBITMAP( SafeDC hdc, SafeHBITMAP hgdiobj ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr SelectObject( SafeDC hdc, SafeHBITMAP hgdiobj ) + { + IntPtr ret = _SelectObjectSafeHBITMAP( hdc, hgdiobj ); + if( ret == IntPtr.Zero ) + { + HRESULT.ThrowLastError(); + } + return ret; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", EntryPoint = "SelectObject", SetLastError = true)] - private static extern IntPtr _SelectObject(SafeDC hdc, IntPtr hgdiobj); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", SetLastError = true )] + public static extern int SendInput( int nInputs, ref INPUT pInputs, int cbSize ); + + // Depending on the message, callers may want to call GetLastError based on the return value. + [DllImport( "user32.dll", SetLastError = true )] + public static extern IntPtr SendMessage( IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "UnregisterClass", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _UnregisterClassAtom( IntPtr lpClassName, IntPtr hInstance ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr SelectObject(SafeDC hdc, IntPtr hgdiobj) - { - IntPtr ret = _SelectObject(hdc, hgdiobj); - if (ret == IntPtr.Zero) - { - HRESULT.ThrowLastError(); - } - return ret; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", EntryPoint = "UnregisterClass", CharSet = CharSet.Unicode, SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _UnregisterClassName( string lpClassName, IntPtr hInstance ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("gdi32.dll", EntryPoint = "SelectObject", SetLastError = true)] - private static extern IntPtr _SelectObjectSafeHBITMAP(SafeDC hdc, SafeHBITMAP hgdiobj); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void UnregisterClass( short atom, IntPtr hinstance ) + { + if( !_UnregisterClassAtom( new IntPtr( atom ), hinstance ) ) + { + HRESULT.ThrowLastError(); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr SelectObject(SafeDC hdc, SafeHBITMAP hgdiobj) - { - IntPtr ret = _SelectObjectSafeHBITMAP(hdc, hgdiobj); - if (ret == IntPtr.Zero) - { - HRESULT.ThrowLastError(); - } - return ret; - } + public static void UnregisterClass( string lpClassName, IntPtr hInstance ) + { + if( !_UnregisterClassName( lpClassName, hInstance ) ) + { + HRESULT.ThrowLastError(); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", SetLastError = true)] - public static extern int SendInput(int nInputs, ref INPUT pInputs, int cbSize); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", SetLastError = true, EntryPoint = "UpdateLayeredWindow" )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _UpdateLayeredWindow( + IntPtr hwnd, + SafeDC hdcDst, + [In] ref POINT pptDst, + [In] ref SIZE psize, + SafeDC hdcSrc, + [In] ref POINT pptSrc, + int crKey, + ref BLENDFUNCTION pblend, + ULW dwFlags ); - // Depending on the message, callers may want to call GetLastError based on the return value. - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr SendMessage(IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "user32.dll", SetLastError = true, EntryPoint = "UpdateLayeredWindow" )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool _UpdateLayeredWindowIntPtr( + IntPtr hwnd, + IntPtr hdcDst, + IntPtr pptDst, + IntPtr psize, + IntPtr hdcSrc, + IntPtr pptSrc, + int crKey, + ref BLENDFUNCTION pblend, + ULW dwFlags ); + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void UpdateLayeredWindow( + IntPtr hwnd, + SafeDC hdcDst, + ref POINT pptDst, + ref SIZE psize, + SafeDC hdcSrc, + ref POINT pptSrc, + int crKey, + ref BLENDFUNCTION pblend, + ULW dwFlags ) + { + if( !_UpdateLayeredWindow( hwnd, hdcDst, ref pptDst, ref psize, hdcSrc, ref pptSrc, crKey, ref pblend, dwFlags ) ) + { + HRESULT.ThrowLastError(); + } + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void UpdateLayeredWindow( + IntPtr hwnd, + int crKey, + ref BLENDFUNCTION pblend, + ULW dwFlags ) + { + if( !_UpdateLayeredWindowIntPtr( hwnd, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, crKey, ref pblend, dwFlags ) ) + { + HRESULT.ThrowLastError(); + } + } + + #region Win7 declarations + + [DllImport( "shell32.dll", EntryPoint = "SHAddToRecentDocs" )] + private static extern void _SHAddToRecentDocs_String( SHARD uFlags, [MarshalAs( UnmanagedType.LPWStr )] string pv ); + + // This overload is required. There's a cast in the Shell code that causes the wrong vtbl to be used + // if we let the marshaller convert the parameter to an IUnknown. + [DllImport( "shell32.dll", EntryPoint = "SHAddToRecentDocs" )] + private static extern void _SHAddToRecentDocs_ShellLink( SHARD uFlags, IShellLinkW pv ); + + public static void SHAddToRecentDocs( string path ) + { + _SHAddToRecentDocs_String( SHARD.PATHW, path ); + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "UnregisterClass", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _UnregisterClassAtom(IntPtr lpClassName, IntPtr hInstance); + // Win7 only. + public static void SHAddToRecentDocs( IShellLinkW shellLink ) + { + _SHAddToRecentDocs_ShellLink( SHARD.LINK, shellLink ); + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", EntryPoint = "UnregisterClass", CharSet = CharSet.Unicode, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _UnregisterClassName(string lpClassName, IntPtr hInstance); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void UnregisterClass(short atom, IntPtr hinstance) - { - if (!_UnregisterClassAtom(new IntPtr(atom), hinstance)) - { - HRESULT.ThrowLastError(); - } - } + // #define DWM_SIT_DISPLAYFRAME 0x00000001 // Display a window frame around the provided bitmap - public static void UnregisterClass(string lpClassName, IntPtr hInstance) - { - if (!_UnregisterClassName(lpClassName, hInstance)) - { - HRESULT.ThrowLastError(); - } - } + [DllImport( "dwmapi.dll", EntryPoint = "DwmGetCompositionTimingInfo" )] + private static extern HRESULT _DwmGetCompositionTimingInfo( IntPtr hwnd, ref DWM_TIMING_INFO pTimingInfo ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", SetLastError = true, EntryPoint = "UpdateLayeredWindow")] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _UpdateLayeredWindow( - IntPtr hwnd, - SafeDC hdcDst, - [In] ref POINT pptDst, - [In] ref SIZE psize, - SafeDC hdcSrc, - [In] ref POINT pptSrc, - int crKey, - ref BLENDFUNCTION pblend, - ULW dwFlags); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("user32.dll", SetLastError = true, EntryPoint = "UpdateLayeredWindow")] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _UpdateLayeredWindowIntPtr( - IntPtr hwnd, - IntPtr hdcDst, - IntPtr pptDst, - IntPtr psize, - IntPtr hdcSrc, - IntPtr pptSrc, - int crKey, - ref BLENDFUNCTION pblend, - ULW dwFlags); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void UpdateLayeredWindow( - IntPtr hwnd, - SafeDC hdcDst, - ref POINT pptDst, - ref SIZE psize, - SafeDC hdcSrc, - ref POINT pptSrc, - int crKey, - ref BLENDFUNCTION pblend, - ULW dwFlags) - { - if (!_UpdateLayeredWindow(hwnd, hdcDst, ref pptDst, ref psize, hdcSrc, ref pptSrc, crKey, ref pblend, dwFlags)) - { - HRESULT.ThrowLastError(); - } - } + public static DWM_TIMING_INFO? DwmGetCompositionTimingInfo( IntPtr hwnd ) + { + if( !Utility.IsOSVistaOrNewer ) + { + // API was new to Vista. + return null; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void UpdateLayeredWindow( - IntPtr hwnd, - int crKey, - ref BLENDFUNCTION pblend, - ULW dwFlags) - { - if (!_UpdateLayeredWindowIntPtr(hwnd, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, crKey, ref pblend, dwFlags)) - { - HRESULT.ThrowLastError(); - } - } + var dti = new DWM_TIMING_INFO { cbSize = Marshal.SizeOf( typeof( DWM_TIMING_INFO ) ) }; + HRESULT hr = _DwmGetCompositionTimingInfo( Utility.IsOSWindows8OrNewer ? IntPtr.Zero : hwnd, ref dti ); + if( hr == HRESULT.E_PENDING ) + { + // The system isn't yet ready to respond. Return null rather than throw. + return null; + } + hr.ThrowIfFailed(); - #region Win7 declarations + return dti; + } - [DllImport("shell32.dll", EntryPoint = "SHAddToRecentDocs")] - private static extern void _SHAddToRecentDocs_String(SHARD uFlags, [MarshalAs(UnmanagedType.LPWStr)] string pv); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "dwmapi.dll", PreserveSig = false )] + public static extern void DwmInvalidateIconicBitmaps( IntPtr hwnd ); - // This overload is required. There's a cast in the Shell code that causes the wrong vtbl to be used - // if we let the marshaller convert the parameter to an IUnknown. - [DllImport("shell32.dll", EntryPoint = "SHAddToRecentDocs")] - private static extern void _SHAddToRecentDocs_ShellLink(SHARD uFlags, IShellLinkW pv); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "dwmapi.dll", PreserveSig = false )] + public static extern void DwmSetIconicThumbnail( IntPtr hwnd, IntPtr hbmp, DWM_SIT dwSITFlags ); - public static void SHAddToRecentDocs(string path) - { - _SHAddToRecentDocs_String(SHARD.PATHW, path); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "dwmapi.dll", PreserveSig = false )] + public static extern void DwmSetIconicLivePreviewBitmap( IntPtr hwnd, IntPtr hbmp, RefPOINT pptClient, DWM_SIT dwSITFlags ); - // Win7 only. - public static void SHAddToRecentDocs(IShellLinkW shellLink) - { - _SHAddToRecentDocs_ShellLink(SHARD.LINK, shellLink); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "shell32.dll", PreserveSig = false )] + public static extern void SHGetItemFromDataObject( IDataObject pdtobj, DOGIF dwFlags, [In] ref Guid riid, [Out, MarshalAs( UnmanagedType.Interface )] out object ppv ); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "shell32.dll", PreserveSig = false )] + public static extern HRESULT SHCreateItemFromParsingName( [MarshalAs( UnmanagedType.LPWStr )] string pszPath, IBindCtx pbc, [In] ref Guid riid, [Out, MarshalAs( UnmanagedType.Interface )] out object ppv ); - // #define DWM_SIT_DISPLAYFRAME 0x00000001 // Display a window frame around the provided bitmap + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "shell32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool Shell_NotifyIcon( NIM dwMessage, [In] NOTIFYICONDATA lpdata ); - [DllImport("dwmapi.dll", EntryPoint="DwmGetCompositionTimingInfo")] - private static extern HRESULT _DwmGetCompositionTimingInfo(IntPtr hwnd, ref DWM_TIMING_INFO pTimingInfo); + /// + /// Sets the User Model AppID for the current process, enabling Windows to retrieve this ID + /// + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "shell32.dll", PreserveSig = false )] + public static extern void SetCurrentProcessExplicitAppUserModelID( [MarshalAs( UnmanagedType.LPWStr )] string AppID ); - public static DWM_TIMING_INFO? DwmGetCompositionTimingInfo(IntPtr hwnd) - { - if (!Utility.IsOSVistaOrNewer) - { - // API was new to Vista. - return null; - } - - var dti = new DWM_TIMING_INFO { cbSize = Marshal.SizeOf(typeof(DWM_TIMING_INFO)) }; - HRESULT hr = _DwmGetCompositionTimingInfo(hwnd, ref dti); - if (hr == HRESULT.E_PENDING) - { - // The system isn't yet ready to respond. Return null rather than throw. - return null; - } - hr.ThrowIfFailed(); - - return dti; - } + /// + /// Retrieves the User Model AppID that has been explicitly set for the current process via SetCurrentProcessExplicitAppUserModelID + /// + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DllImport( "shell32.dll" )] + public static extern HRESULT GetCurrentProcessExplicitAppUserModelID( [Out, MarshalAs( UnmanagedType.LPWStr )] out string AppID ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmInvalidateIconicBitmaps(IntPtr hwnd); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmSetIconicThumbnail(IntPtr hwnd, IntPtr hbmp, DWM_SIT dwSITFlags); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmSetIconicLivePreviewBitmap(IntPtr hwnd, IntPtr hbmp, RefPOINT pptClient, DWM_SIT dwSITFlags); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("shell32.dll", PreserveSig = false)] - public static extern void SHGetItemFromDataObject(IDataObject pdtobj, DOGIF dwFlags, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("shell32.dll", PreserveSig = false)] - public static extern HRESULT SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv); - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("shell32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool Shell_NotifyIcon(NIM dwMessage, [In] NOTIFYICONDATA lpdata); - - /// - /// Sets the User Model AppID for the current process, enabling Windows to retrieve this ID - /// - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("shell32.dll", PreserveSig = false)] - public static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID); - - /// - /// Retrieves the User Model AppID that has been explicitly set for the current process via SetCurrentProcessExplicitAppUserModelID - /// - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport("shell32.dll")] - public static extern HRESULT GetCurrentProcessExplicitAppUserModelID([Out, MarshalAs(UnmanagedType.LPWStr)] out string AppID); - - #endregion - } + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ShellProvider.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ShellProvider.cs index 8a1de317..2f926d80 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ShellProvider.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ShellProvider.cs @@ -20,964 +20,976 @@ namespace Standard { - using System; - using System.Runtime.InteropServices; - using System.Runtime.InteropServices.ComTypes; - using System.Text; - - using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; - - #region Enums and Static Property Classes - - /// ShellItem attribute flags. SIATTRIBFLAGS_* - internal enum SIATTRIBFLAGS - { - AND = 0x00000001, - OR = 0x00000002, - APPCOMPAT = 0x00000003, - } - - internal enum APPDOCLISTTYPE - { - ADLT_RECENT = 0, // The recently used documents list - ADLT_FREQUENT, // The frequently used documents list - } - - /// - /// Flags for SetTabProperties. STPF_* - /// - /// The native enum was called STPFLAG. - [Flags] - internal enum STPF - { - NONE = 0x00000000, - USEAPPTHUMBNAILALWAYS = 0x00000001, - USEAPPTHUMBNAILWHENACTIVE = 0x00000002, - USEAPPPEEKALWAYS = 0x00000004, - USEAPPPEEKWHENACTIVE = 0x00000008, - } - - /// - /// Flags for Setting Taskbar Progress state. TBPF_* - /// + using System; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + using System.Text; + + using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; + + #region Enums and Static Property Classes + + /// ShellItem attribute flags. SIATTRIBFLAGS_* + internal enum SIATTRIBFLAGS + { + AND = 0x00000001, + OR = 0x00000002, + APPCOMPAT = 0x00000003, + } + + internal enum APPDOCLISTTYPE + { + ADLT_RECENT = 0, // The recently used documents list + ADLT_FREQUENT, // The frequently used documents list + } + + /// + /// Flags for SetTabProperties. STPF_* + /// + /// The native enum was called STPFLAG. + [Flags] + internal enum STPF + { + NONE = 0x00000000, + USEAPPTHUMBNAILALWAYS = 0x00000001, + USEAPPTHUMBNAILWHENACTIVE = 0x00000002, + USEAPPPEEKALWAYS = 0x00000004, + USEAPPPEEKWHENACTIVE = 0x00000008, + } + + /// + /// Flags for Setting Taskbar Progress state. TBPF_* + /// + /// + /// The native enum was called TBPFLAG. + /// + internal enum TBPF + { + NOPROGRESS = 0x00000000, + INDETERMINATE = 0x00000001, + NORMAL = 0x00000002, + ERROR = 0x00000004, + PAUSED = 0x00000008, + } + + /// + /// THUMBBUTTON mask. THB_* + /// + [Flags] + internal enum THB : uint + { + BITMAP = 0x0001, + ICON = 0x0002, + TOOLTIP = 0x0004, + FLAGS = 0x0008, + } + + /// + /// THUMBBUTTON flags. THBF_* + /// + [Flags] + internal enum THBF : uint + { + ENABLED = 0x0000, + DISABLED = 0x0001, + DISMISSONCLICK = 0x0002, + NOBACKGROUND = 0x0004, + HIDDEN = 0x0008, + // Added post-beta + NONINTERACTIVE = 0x0010, + } + + /// + /// GetPropertyStoreFlags. GPS_*. + /// + /// + /// These are new for Vista, but are used in downlevel components + /// + internal enum GPS + { + // If no flags are specified (GPS_DEFAULT), a read-only property store is returned that includes properties for the file or item. + // In the case that the shell item is a file, the property store contains: + // 1. properties about the file from the file system + // 2. properties from the file itself provided by the file's property handler, unless that file is offline, + // see GPS_OPENSLOWITEM + // 3. if requested by the file's property handler and supported by the file system, properties stored in the + // alternate property store. + // + // Non-file shell items should return a similar read-only store + // + // Specifying other GPS_ flags modifies the store that is returned + DEFAULT = 0x00000000, + HANDLERPROPERTIESONLY = 0x00000001, // only include properties directly from the file's property handler + READWRITE = 0x00000002, // Writable stores will only include handler properties + TEMPORARY = 0x00000004, // A read/write store that only holds properties for the lifetime of the IShellItem object + FASTPROPERTIESONLY = 0x00000008, // do not include any properties from the file's property handler (because the file's property handler will hit the disk) + OPENSLOWITEM = 0x00000010, // include properties from a file's property handler, even if it means retrieving the file from offline storage. + DELAYCREATION = 0x00000020, // delay the creation of the file's property handler until those properties are read, written, or enumerated + BESTEFFORT = 0x00000040, // For readonly stores, succeed and return all available properties, even if one or more sources of properties fails. Not valid with GPS_READWRITE. + NO_OPLOCK = 0x00000080, // some data sources protect the read property store with an oplock, this disables that + MASK_VALID = 0x000000FF, + } + + /// + /// KNOWNDESTCATEGORY. KDC_* + /// + internal enum KDC + { + FREQUENT = 1, + RECENT, + } + + // IShellFolder::GetAttributesOf flags + [Flags] + internal enum SFGAO : uint + { + /// Objects can be copied + /// DROPEFFECT_COPY + CANCOPY = 0x1, + /// Objects can be moved + /// DROPEFFECT_MOVE + CANMOVE = 0x2, + /// Objects can be linked /// - /// The native enum was called TBPFLAG. + /// DROPEFFECT_LINK. + /// + /// If this bit is set on an item in the shell folder, a + /// 'Create Shortcut' menu item will be added to the File + /// menu and context menus for the item. If the user selects + /// that command, your IContextMenu::InvokeCommand() will be called + /// with 'link'. + /// That flag will also be used to determine if 'Create Shortcut' + /// should be added when the item in your folder is dragged to another + /// folder. /// - internal enum TBPF - { - NOPROGRESS = 0x00000000, - INDETERMINATE = 0x00000001, - NORMAL = 0x00000002, - ERROR = 0x00000004, - PAUSED = 0x00000008, - } - + CANLINK = 0x4, + /// supports BindToObject(IID_IStorage) + STORAGE = 0x00000008, + /// Objects can be renamed + CANRENAME = 0x00000010, + /// Objects can be deleted + CANDELETE = 0x00000020, + /// Objects have property sheets + HASPROPSHEET = 0x00000040, + + // unused = 0x00000080, + + /// Objects are drop target + DROPTARGET = 0x00000100, + CAPABILITYMASK = 0x00000177, + // unused = 0x00000200, + // unused = 0x00000400, + // unused = 0x00000800, + // unused = 0x00001000, + /// Object is encrypted (use alt color) + ENCRYPTED = 0x00002000, + /// 'Slow' object + ISSLOW = 0x00004000, + /// Ghosted icon + GHOSTED = 0x00008000, + /// Shortcut (link) + LINK = 0x00010000, + /// Shared + SHARE = 0x00020000, + /// Read-only + READONLY = 0x00040000, + /// Hidden object + HIDDEN = 0x00080000, + DISPLAYATTRMASK = 0x000FC000, + /// May contain children with SFGAO_FILESYSTEM + FILESYSANCESTOR = 0x10000000, + /// Support BindToObject(IID_IShellFolder) + FOLDER = 0x20000000, + /// Is a win32 file system object (file/folder/root) + FILESYSTEM = 0x40000000, + /// May contain children with SFGAO_FOLDER (may be slow) + HASSUBFOLDER = 0x80000000, + CONTENTSMASK = 0x80000000, + /// Invalidate cached information (may be slow) + VALIDATE = 0x01000000, + /// Is this removeable media? + REMOVABLE = 0x02000000, + /// Object is compressed (use alt color) + COMPRESSED = 0x04000000, + /// Supports IShellFolder, but only implements CreateViewObject() (non-folder view) + BROWSABLE = 0x08000000, + /// Is a non-enumerated object (should be hidden) + NONENUMERATED = 0x00100000, + /// Should show bold in explorer tree + NEWCONTENT = 0x00200000, + /// Obsolete + CANMONIKER = 0x00400000, + /// Obsolete + HASSTORAGE = 0x00400000, + /// Supports BindToObject(IID_IStream) + STREAM = 0x00400000, + /// May contain children with SFGAO_STORAGE or SFGAO_STREAM + STORAGEANCESTOR = 0x00800000, + /// For determining storage capabilities, ie for open/save semantics + STORAGECAPMASK = 0x70C50008, /// - /// THUMBBUTTON mask. THB_* + /// Attributes that are masked out for PKEY_SFGAOFlags because they are considered + /// to cause slow calculations or lack context + /// (SFGAO_VALIDATE | SFGAO_ISSLOW | SFGAO_HASSUBFOLDER and others) /// - [Flags] - internal enum THB : uint - { - BITMAP = 0x0001, - ICON = 0x0002, - TOOLTIP = 0x0004, - FLAGS = 0x0008, - } - + PKEYSFGAOMASK = 0x81044000, + } + + /// + /// IShellFolder::EnumObjects grfFlags bits. Also called SHCONT + /// + internal enum SHCONTF + { + CHECKING_FOR_CHILDREN = 0x0010, // hint that client is checking if (what) child items the folder contains - not all details (e.g. short file name) are needed + FOLDERS = 0x0020, // only want folders enumerated (SFGAO_FOLDER) + NONFOLDERS = 0x0040, // include non folders (items without SFGAO_FOLDER) + INCLUDEHIDDEN = 0x0080, // show items normally hidden (items with SFGAO_HIDDEN) + INIT_ON_FIRST_NEXT = 0x0100, // DEFUNCT - this is always assumed + NETPRINTERSRCH = 0x0200, // hint that client is looking for printers + SHAREABLE = 0x0400, // hint that client is looking sharable resources (local drives or hidden root shares) + STORAGE = 0x0800, // include all items with accessible storage and their ancestors + NAVIGATION_ENUM = 0x1000, // mark child folders to indicate that they should provide a "navigation" enumeration by default + FASTITEMS = 0x2000, // hint that client is only interested in items that can be enumerated quickly + FLATLIST = 0x4000, // enumerate items as flat list even if folder is stacked + ENABLE_ASYNC = 0x8000, // inform enumerator that client is listening for change notifications so enumerator does not need to be complete, items can be reported via change notifications + } + + /// + /// IShellFolder::GetDisplayNameOf/SetNameOf uFlags. Also called SHGDNF. + /// + /// + /// For compatibility with SIGDN, these bits must all sit in the LOW word. + /// + [Flags] + internal enum SHGDN + { + SHGDN_NORMAL = 0x0000, // default (display purpose) + SHGDN_INFOLDER = 0x0001, // displayed under a folder (relative) + SHGDN_FOREDITING = 0x1000, // for in-place editing + SHGDN_FORADDRESSBAR = 0x4000, // UI friendly parsing name (remove ugly stuff) + SHGDN_FORPARSING = 0x8000, // parsing name for ParseDisplayName() + } + + /// + /// SHELLITEMCOMPAREHINTF. SICHINT_*. + /// + internal enum SICHINT : uint + { + /// iOrder based on display in a folder view + DISPLAY = 0x00000000, + /// exact instance compare + ALLFIELDS = 0x80000000, + /// iOrder based on canonical name (better performance) + CANONICAL = 0x10000000, + TEST_FILESYSPATH_IF_NOT_EQUAL = 0x20000000, + }; + + /// + /// ShellItem enum. SIGDN_*. + /// + internal enum SIGDN : uint + { // lower word (& with 0xFFFF) + NORMALDISPLAY = 0x00000000, // SHGDN_NORMAL + PARENTRELATIVEPARSING = 0x80018001, // SHGDN_INFOLDER | SHGDN_FORPARSING + DESKTOPABSOLUTEPARSING = 0x80028000, // SHGDN_FORPARSING + PARENTRELATIVEEDITING = 0x80031001, // SHGDN_INFOLDER | SHGDN_FOREDITING + DESKTOPABSOLUTEEDITING = 0x8004c000, // SHGDN_FORPARSING | SHGDN_FORADDRESSBAR + FILESYSPATH = 0x80058000, // SHGDN_FORPARSING + URL = 0x80068000, // SHGDN_FORPARSING + PARENTRELATIVEFORADDRESSBAR = 0x8007c001, // SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR + PARENTRELATIVE = 0x80080001, // SHGDN_INFOLDER + } + + /// + /// STR_GPS_* + /// + /// + /// When requesting a property store through IShellFolder, you can specify the equivalent of + /// GPS_DEFAULT by passing in a null IBindCtx parameter. + /// + /// You can specify the equivalent of GPS_READWRITE by passing a mode of STGM_READWRITE | STGM_EXCLUSIVE + /// in the bind context + /// + /// Here are the string versions of GPS_ flags, passed to IShellFolder::BindToObject() via IBindCtx::RegisterObjectParam() + /// These flags are valid when requesting an IPropertySetStorage or IPropertyStore handler + /// + /// The meaning of these flags are described above. + /// + /// There is no STR_ equivalent for GPS_TEMPORARY because temporary property stores + /// are provided by IShellItem2 only -- not by the underlying IShellFolder. + /// + internal static class STR_GPS + { + public const string HANDLERPROPERTIESONLY = "GPS_HANDLERPROPERTIESONLY"; + public const string FASTPROPERTIESONLY = "GPS_FASTPROPERTIESONLY"; + public const string OPENSLOWITEM = "GPS_OPENSLOWITEM"; + public const string DELAYCREATION = "GPS_DELAYCREATION"; + public const string BESTEFFORT = "GPS_BESTEFFORT"; + public const string NO_OPLOCK = "GPS_NO_OPLOCK"; + } + + #endregion + + #region Structs + + [StructLayout( LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode )] + internal struct THUMBBUTTON + { /// - /// THUMBBUTTON flags. THBF_* + /// WPARAM value for a THUMBBUTTON being clicked. /// - [Flags] - internal enum THBF : uint - { - ENABLED = 0x0000, - DISABLED = 0x0001, - DISMISSONCLICK = 0x0002, - NOBACKGROUND = 0x0004, - HIDDEN = 0x0008, - // Added post-beta - NONINTERACTIVE = 0x0010, - } + public const int THBN_CLICKED = 0x1800; + + public THB dwMask; + public uint iId; + public uint iBitmap; + public IntPtr hIcon; + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 260 )] + public string szTip; + public THBF dwFlags; + } + + + [StructLayout( LayoutKind.Sequential, Pack = 4 )] + internal struct PKEY + { + /// fmtid + private readonly Guid _fmtid; + /// pid + private readonly uint _pid; + + public PKEY( Guid fmtid, uint pid ) + { + _fmtid = fmtid; + _pid = pid; + } + + /// PKEY_Title + public static readonly PKEY Title = new PKEY( new Guid( "F29F85E0-4FF9-1068-AB91-08002B27B3D9" ), 2 ); + /// PKEY_AppUserModel_ID + public static readonly PKEY AppUserModel_ID = new PKEY( new Guid( "9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3" ), 5 ); + /// PKEY_AppUserModel_IsDestListSeparator + public static readonly PKEY AppUserModel_IsDestListSeparator = new PKEY( new Guid( "9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3" ), 6 ); + /// PKEY_AppUserModel_RelaunchCommand + public static readonly PKEY AppUserModel_RelaunchCommand = new PKEY( new Guid( "9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3" ), 2 ); + /// PKEY_AppUserModel_RelaunchDisplayNameResource + public static readonly PKEY AppUserModel_RelaunchDisplayNameResource = new PKEY( new Guid( "9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3" ), 4 ); + /// PKEY_AppUserModel_RelaunchIconResource + public static readonly PKEY AppUserModel_RelaunchIconResource = new PKEY( new Guid( "9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3" ), 3 ); + } + + #endregion + + #region Interfaces + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.EnumIdList ), + ] + internal interface IEnumIDList + { + [PreserveSig()] + HRESULT Next( uint celt, out IntPtr rgelt, out int pceltFetched ); + [PreserveSig()] + HRESULT Skip( uint celt ); + void Reset(); + void Clone( [Out, MarshalAs( UnmanagedType.Interface )] out IEnumIDList ppenum ); + } + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.EnumObjects ), + ] + internal interface IEnumObjects + { + //[local] + // This signature might not work... Hopefully don't need this interface though. + void Next( uint celt, [In] ref Guid riid, [Out, MarshalAs( UnmanagedType.LPArray, ArraySubType = UnmanagedType.IUnknown, IidParameterIndex = 1, SizeParamIndex = 0 )] object[] rgelt, [Out] out uint pceltFetched ); + + /* + [call_as(Next)] HRESULT RemoteNext( + [in] ULONG celt, + [in] REFIID riid, + [out, size_is(celt), length_is(*pceltFetched), iid_is(riid)] void **rgelt, + [out] ULONG *pceltFetched); + */ + + void Skip( uint celt ); + + void Reset(); + + IEnumObjects Clone(); + } + + /// Unknown Object Array + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ObjectArray ), + ] + internal interface IObjectArray + { + uint GetCount(); + [return: MarshalAs( UnmanagedType.IUnknown )] + object GetAt( [In] uint uiIndex, [In] ref Guid riid ); + } + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ObjectArray ), + ] + interface IObjectCollection : IObjectArray + { + #region IObjectArray redeclarations + new uint GetCount(); + [return: MarshalAs( UnmanagedType.IUnknown )] + new object GetAt( [In] uint uiIndex, [In] ref Guid riid ); + #endregion - /// - /// GetPropertyStoreFlags. GPS_*. - /// - /// - /// These are new for Vista, but are used in downlevel components - /// - internal enum GPS - { - // If no flags are specified (GPS_DEFAULT), a read-only property store is returned that includes properties for the file or item. - // In the case that the shell item is a file, the property store contains: - // 1. properties about the file from the file system - // 2. properties from the file itself provided by the file's property handler, unless that file is offline, - // see GPS_OPENSLOWITEM - // 3. if requested by the file's property handler and supported by the file system, properties stored in the - // alternate property store. - // - // Non-file shell items should return a similar read-only store - // - // Specifying other GPS_ flags modifies the store that is returned - DEFAULT = 0x00000000, - HANDLERPROPERTIESONLY = 0x00000001, // only include properties directly from the file's property handler - READWRITE = 0x00000002, // Writable stores will only include handler properties - TEMPORARY = 0x00000004, // A read/write store that only holds properties for the lifetime of the IShellItem object - FASTPROPERTIESONLY = 0x00000008, // do not include any properties from the file's property handler (because the file's property handler will hit the disk) - OPENSLOWITEM = 0x00000010, // include properties from a file's property handler, even if it means retrieving the file from offline storage. - DELAYCREATION = 0x00000020, // delay the creation of the file's property handler until those properties are read, written, or enumerated - BESTEFFORT = 0x00000040, // For readonly stores, succeed and return all available properties, even if one or more sources of properties fails. Not valid with GPS_READWRITE. - NO_OPLOCK = 0x00000080, // some data sources protect the read property store with an oplock, this disables that - MASK_VALID = 0x000000FF, - } + void AddObject( [MarshalAs( UnmanagedType.IUnknown )] object punk ); + void AddFromArray( IObjectArray poaSource ); + void RemoveObjectAt( uint uiIndex ); + void Clear(); + } + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.PropertyStore ) + ] + internal interface IPropertyStore + { + uint GetCount(); + PKEY GetAt( uint iProp ); + void GetValue( [In] ref PKEY pkey, [In, Out] PROPVARIANT pv ); + void SetValue( [In] ref PKEY pkey, PROPVARIANT pv ); + void Commit(); + } + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ShellFolder ), + ] + internal interface IShellFolder + { + void ParseDisplayName( + [In] IntPtr hwnd, + [In] IBindCtx pbc, + [In, MarshalAs( UnmanagedType.LPWStr )] string pszDisplayName, + [In, Out] ref int pchEaten, + [Out] out IntPtr ppidl, + [In, Out] ref uint pdwAttributes ); + + IEnumIDList EnumObjects( + [In] IntPtr hwnd, + [In] SHCONTF grfFlags ); + + // returns an instance of a sub-folder which is specified by the IDList (pidl). + // IShellFolder or derived interfaces + [return: MarshalAs( UnmanagedType.Interface )] + object BindToObject( + [In] IntPtr pidl, + [In] IBindCtx pbc, + [In] ref Guid riid ); + + // produces the same result as BindToObject() + [return: MarshalAs( UnmanagedType.Interface )] + object BindToStorage( [In] IntPtr pidl, [In] IBindCtx pbc, [In] ref Guid riid ); + + // compares two IDLists and returns the result. The shell + // explorer always passes 0 as lParam, which indicates 'sort by name'. + // It should return 0 (as CODE of the scode), if two id indicates the + // same object; negative value if pidl1 should be placed before pidl2; + // positive value if pidl2 should be placed before pidl1. + // use the macro ResultFromShort() to extract the result comparison + // it deals with the casting and type conversion issues for you + [PreserveSig] + HRESULT CompareIDs( [In] IntPtr lParam, [In] IntPtr pidl1, [In] IntPtr pidl2 ); + + // creates a view object of the folder itself. The view + // object is a difference instance from the shell folder object. + // 'hwndOwner' can be used as the owner window of its dialog box or + // menu during the lifetime of the view object. + // This member function should always create a new + // instance which has only one reference count. The explorer may create + // more than one instances of view object from one shell folder object + // and treat them as separate instances. + // returns IShellView derived interface + [return: MarshalAs( UnmanagedType.Interface )] + object CreateViewObject( [In] IntPtr hwndOwner, [In] ref Guid riid ); + + // returns the attributes of specified objects in that + // folder. 'cidl' and 'apidl' specifies objects. 'apidl' contains only + // simple IDLists. The explorer initializes *prgfInOut with a set of + // flags to be evaluated. The shell folder may optimize the operation + // by not returning unspecified flags. + void GetAttributesOf( + [In] uint cidl, + [In] IntPtr apidl, + [In, Out] ref SFGAO rgfInOut ); + + // creates a UI object to be used for specified objects. + // The shell explorer passes either IID_IDataObject (for transfer operation) + // or IID_IContextMenu (for context menu operation) as riid + // and many other interfaces + [return: MarshalAs( UnmanagedType.Interface )] + object GetUIObjectOf( + [In] IntPtr hwndOwner, + [In] uint cidl, + [In, MarshalAs( UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 2 )] IntPtr apidl, + [In] ref Guid riid, + [In, Out] ref uint rgfReserved ); + + // returns the display name of the specified object. + // If the ID contains the display name (in the locale character set), + // it returns the offset to the name. Otherwise, it returns a pointer + // to the display name string (UNICODE), which is allocated by the + // task allocator, or fills in a buffer. + // use the helper APIS StrRetToStr() or StrRetToBuf() to deal with the different + // forms of the STRRET structure + void GetDisplayNameOf( [In] IntPtr pidl, [In] SHGDN uFlags, [Out] out IntPtr pName ); + + // sets the display name of the specified object. + // If it changes the ID as well, it returns the new ID which is + // alocated by the task allocator. + void SetNameOf( [In] IntPtr hwnd, + [In] IntPtr pidl, + [In, MarshalAs( UnmanagedType.LPWStr )] string pszName, + [In] SHGDN uFlags, + [Out] out IntPtr ppidlOut ); + } + + /// + /// Shell Namespace helper + /// + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ShellItem ), + ] + internal interface IShellItem + { + [return: MarshalAs( UnmanagedType.Interface )] + object BindToHandler( IBindCtx pbc, [In] ref Guid bhid, [In] ref Guid riid ); + + IShellItem GetParent(); + + [return: MarshalAs( UnmanagedType.LPWStr )] + string GetDisplayName( SIGDN sigdnName ); + + SFGAO GetAttributes( SFGAO sfgaoMask ); + + int Compare( IShellItem psi, SICHINT hint ); + } + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ShellItemArray ), + ] + internal interface IShellItemArray + { + [return: MarshalAs( UnmanagedType.Interface )] + object BindToHandler( IBindCtx pbc, [In] ref Guid rbhid, [In] ref Guid riid ); + + [return: MarshalAs( UnmanagedType.Interface )] + object GetPropertyStore( int flags, [In] ref Guid riid ); + + [return: MarshalAs( UnmanagedType.Interface )] + object GetPropertyDescriptionList( [In] ref PKEY keyType, [In] ref Guid riid ); + + uint GetAttributes( SIATTRIBFLAGS dwAttribFlags, uint sfgaoMask ); + + uint GetCount(); + + IShellItem GetItemAt( uint dwIndex ); + + [return: MarshalAs( UnmanagedType.Interface )] + object EnumItems(); + } + + /// + /// Shell Namespace helper 2 + /// + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ShellItem2 ), + ] + interface IShellItem2 : IShellItem + { + #region IShellItem redeclarations + [return: MarshalAs( UnmanagedType.Interface )] + new object BindToHandler( [In] IBindCtx pbc, [In] ref Guid bhid, [In] ref Guid riid ); + new IShellItem GetParent(); + [return: MarshalAs( UnmanagedType.LPWStr )] + new string GetDisplayName( SIGDN sigdnName ); + new SFGAO GetAttributes( SFGAO sfgaoMask ); + new int Compare( IShellItem psi, SICHINT hint ); + #endregion + [return: MarshalAs( UnmanagedType.Interface )] + object GetPropertyStore( + GPS flags, + [In] ref Guid riid ); + + [return: MarshalAs( UnmanagedType.Interface )] + object GetPropertyStoreWithCreateObject( + GPS flags, + [MarshalAs( UnmanagedType.IUnknown )] object punkCreateObject, // factory for low-rights creation of type ICreateObject + [In] ref Guid riid ); + + [return: MarshalAs( UnmanagedType.Interface )] + object GetPropertyStoreForKeys( + IntPtr rgKeys, + uint cKeys, + GPS flags, + [In] ref Guid riid ); + + [return: MarshalAs( UnmanagedType.Interface )] + object GetPropertyDescriptionList( + IntPtr keyType, + [In] ref Guid riid ); + + // Ensures any cached information in this item is up to date, or returns __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) if the item does not exist. + void Update( IBindCtx pbc ); + + PROPVARIANT GetProperty( IntPtr key ); + + Guid GetCLSID( IntPtr key ); + + FILETIME GetFileTime( IntPtr key ); + + int GetInt32( IntPtr key ); + + [return: MarshalAs( UnmanagedType.LPWStr )] + string GetString( IntPtr key ); + + uint GetUInt32( IntPtr key ); + + ulong GetUInt64( IntPtr key ); + + [return: MarshalAs( UnmanagedType.Bool )] + void GetBool( IntPtr key ); + } + + [ + ComImport, + InterfaceTypeAttribute( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ShellLink ), + ] + internal interface IShellLinkW + { + void GetPath( [Out, MarshalAs( UnmanagedType.LPWStr )] StringBuilder pszFile, int cchMaxPath, [In, Out] WIN32_FIND_DATAW pfd, SLGP fFlags ); + void GetIDList( out IntPtr ppidl ); + void SetIDList( IntPtr pidl ); + void GetDescription( [Out, MarshalAs( UnmanagedType.LPWStr )] StringBuilder pszFile, int cchMaxName ); + void SetDescription( [MarshalAs( UnmanagedType.LPWStr )] string pszName ); + void GetWorkingDirectory( [Out, MarshalAs( UnmanagedType.LPWStr )] StringBuilder pszDir, int cchMaxPath ); + void SetWorkingDirectory( [MarshalAs( UnmanagedType.LPWStr )] string pszDir ); + void GetArguments( [Out, MarshalAs( UnmanagedType.LPWStr )] StringBuilder pszArgs, int cchMaxPath ); + void SetArguments( [MarshalAs( UnmanagedType.LPWStr )] string pszArgs ); + short GetHotKey(); + void SetHotKey( short wHotKey ); + uint GetShowCmd(); + void SetShowCmd( uint iShowCmd ); + void GetIconLocation( [Out, MarshalAs( UnmanagedType.LPWStr )] StringBuilder pszIconPath, int cchIconPath, out int piIcon ); + void SetIconLocation( [MarshalAs( UnmanagedType.LPWStr )] string pszIconPath, int iIcon ); + void SetRelativePath( [MarshalAs( UnmanagedType.LPWStr )] string pszPathRel, uint dwReserved ); + void Resolve( IntPtr hwnd, uint fFlags ); + void SetPath( [MarshalAs( UnmanagedType.LPWStr )] string pszFile ); + } + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.TaskbarList ), + ] + internal interface ITaskbarList + { /// - /// KNOWNDESTCATEGORY. KDC_* + /// This function must be called first to validate use of other members. /// - internal enum KDC - { - FREQUENT = 1, - RECENT, - } - - // IShellFolder::GetAttributesOf flags - [Flags] - internal enum SFGAO : uint - { - /// Objects can be copied - /// DROPEFFECT_COPY - CANCOPY = 0x1, - /// Objects can be moved - /// DROPEFFECT_MOVE - CANMOVE = 0x2, - /// Objects can be linked - /// - /// DROPEFFECT_LINK. - /// - /// If this bit is set on an item in the shell folder, a - /// 'Create Shortcut' menu item will be added to the File - /// menu and context menus for the item. If the user selects - /// that command, your IContextMenu::InvokeCommand() will be called - /// with 'link'. - /// That flag will also be used to determine if 'Create Shortcut' - /// should be added when the item in your folder is dragged to another - /// folder. - /// - CANLINK = 0x4, - /// supports BindToObject(IID_IStorage) - STORAGE = 0x00000008, - /// Objects can be renamed - CANRENAME = 0x00000010, - /// Objects can be deleted - CANDELETE = 0x00000020, - /// Objects have property sheets - HASPROPSHEET = 0x00000040, - - // unused = 0x00000080, - - /// Objects are drop target - DROPTARGET = 0x00000100, - CAPABILITYMASK = 0x00000177, - // unused = 0x00000200, - // unused = 0x00000400, - // unused = 0x00000800, - // unused = 0x00001000, - /// Object is encrypted (use alt color) - ENCRYPTED = 0x00002000, - /// 'Slow' object - ISSLOW = 0x00004000, - /// Ghosted icon - GHOSTED = 0x00008000, - /// Shortcut (link) - LINK = 0x00010000, - /// Shared - SHARE = 0x00020000, - /// Read-only - READONLY = 0x00040000, - /// Hidden object - HIDDEN = 0x00080000, - DISPLAYATTRMASK = 0x000FC000, - /// May contain children with SFGAO_FILESYSTEM - FILESYSANCESTOR = 0x10000000, - /// Support BindToObject(IID_IShellFolder) - FOLDER = 0x20000000, - /// Is a win32 file system object (file/folder/root) - FILESYSTEM = 0x40000000, - /// May contain children with SFGAO_FOLDER (may be slow) - HASSUBFOLDER = 0x80000000, - CONTENTSMASK = 0x80000000, - /// Invalidate cached information (may be slow) - VALIDATE = 0x01000000, - /// Is this removeable media? - REMOVABLE = 0x02000000, - /// Object is compressed (use alt color) - COMPRESSED = 0x04000000, - /// Supports IShellFolder, but only implements CreateViewObject() (non-folder view) - BROWSABLE = 0x08000000, - /// Is a non-enumerated object (should be hidden) - NONENUMERATED = 0x00100000, - /// Should show bold in explorer tree - NEWCONTENT = 0x00200000, - /// Obsolete - CANMONIKER = 0x00400000, - /// Obsolete - HASSTORAGE = 0x00400000, - /// Supports BindToObject(IID_IStream) - STREAM = 0x00400000, - /// May contain children with SFGAO_STORAGE or SFGAO_STREAM - STORAGEANCESTOR = 0x00800000, - /// For determining storage capabilities, ie for open/save semantics - STORAGECAPMASK = 0x70C50008, - /// - /// Attributes that are masked out for PKEY_SFGAOFlags because they are considered - /// to cause slow calculations or lack context - /// (SFGAO_VALIDATE | SFGAO_ISSLOW | SFGAO_HASSUBFOLDER and others) - /// - PKEYSFGAOMASK = 0x81044000, - } + void HrInit(); /// - /// IShellFolder::EnumObjects grfFlags bits. Also called SHCONT + /// This function adds a tab for hwnd to the taskbar. /// - internal enum SHCONTF - { - CHECKING_FOR_CHILDREN = 0x0010, // hint that client is checking if (what) child items the folder contains - not all details (e.g. short file name) are needed - FOLDERS = 0x0020, // only want folders enumerated (SFGAO_FOLDER) - NONFOLDERS = 0x0040, // include non folders (items without SFGAO_FOLDER) - INCLUDEHIDDEN = 0x0080, // show items normally hidden (items with SFGAO_HIDDEN) - INIT_ON_FIRST_NEXT = 0x0100, // DEFUNCT - this is always assumed - NETPRINTERSRCH = 0x0200, // hint that client is looking for printers - SHAREABLE = 0x0400, // hint that client is looking sharable resources (local drives or hidden root shares) - STORAGE = 0x0800, // include all items with accessible storage and their ancestors - NAVIGATION_ENUM = 0x1000, // mark child folders to indicate that they should provide a "navigation" enumeration by default - FASTITEMS = 0x2000, // hint that client is only interested in items that can be enumerated quickly - FLATLIST = 0x4000, // enumerate items as flat list even if folder is stacked - ENABLE_ASYNC = 0x8000, // inform enumerator that client is listening for change notifications so enumerator does not need to be complete, items can be reported via change notifications - } + /// The HWND for which to add the tab. + void AddTab( IntPtr hwnd ); /// - /// IShellFolder::GetDisplayNameOf/SetNameOf uFlags. Also called SHGDNF. + /// This function deletes a tab for hwnd from the taskbar. /// - /// - /// For compatibility with SIGDN, these bits must all sit in the LOW word. - /// - [Flags] - internal enum SHGDN - { - SHGDN_NORMAL = 0x0000, // default (display purpose) - SHGDN_INFOLDER = 0x0001, // displayed under a folder (relative) - SHGDN_FOREDITING = 0x1000, // for in-place editing - SHGDN_FORADDRESSBAR = 0x4000, // UI friendly parsing name (remove ugly stuff) - SHGDN_FORPARSING = 0x8000, // parsing name for ParseDisplayName() - } + /// The HWND for which the tab is to be deleted. + void DeleteTab( IntPtr hwnd ); /// - /// SHELLITEMCOMPAREHINTF. SICHINT_*. + /// This function activates the tab associated with hwnd on the taskbar. /// - internal enum SICHINT : uint - { - /// iOrder based on display in a folder view - DISPLAY = 0x00000000, - /// exact instance compare - ALLFIELDS = 0x80000000, - /// iOrder based on canonical name (better performance) - CANONICAL = 0x10000000, - TEST_FILESYSPATH_IF_NOT_EQUAL = 0x20000000, - }; + /// The HWND for which the tab is to be actuvated. + void ActivateTab( IntPtr hwnd ); /// - /// ShellItem enum. SIGDN_*. + /// This function marks hwnd in the taskbar as the active tab. /// - internal enum SIGDN : uint - { // lower word (& with 0xFFFF) - NORMALDISPLAY = 0x00000000, // SHGDN_NORMAL - PARENTRELATIVEPARSING = 0x80018001, // SHGDN_INFOLDER | SHGDN_FORPARSING - DESKTOPABSOLUTEPARSING = 0x80028000, // SHGDN_FORPARSING - PARENTRELATIVEEDITING = 0x80031001, // SHGDN_INFOLDER | SHGDN_FOREDITING - DESKTOPABSOLUTEEDITING = 0x8004c000, // SHGDN_FORPARSING | SHGDN_FORADDRESSBAR - FILESYSPATH = 0x80058000, // SHGDN_FORPARSING - URL = 0x80068000, // SHGDN_FORPARSING - PARENTRELATIVEFORADDRESSBAR = 0x8007c001, // SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR - PARENTRELATIVE = 0x80080001, // SHGDN_INFOLDER - } + /// The HWND to activate. + void SetActiveAlt( IntPtr hwnd ); + } + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.TaskbarList2 ), + ] + internal interface ITaskbarList2 : ITaskbarList + { + #region ITaskbarList redeclaration + new void HrInit(); + new void AddTab( IntPtr hwnd ); + new void DeleteTab( IntPtr hwnd ); + new void ActivateTab( IntPtr hwnd ); + new void SetActiveAlt( IntPtr hwnd ); + #endregion /// - /// STR_GPS_* + /// Marks a window as full-screen. /// + /// The handle of the window to be marked. + /// A Boolean value marking the desired full-screen status of the window. /// - /// When requesting a property store through IShellFolder, you can specify the equivalent of - /// GPS_DEFAULT by passing in a null IBindCtx parameter. - /// - /// You can specify the equivalent of GPS_READWRITE by passing a mode of STGM_READWRITE | STGM_EXCLUSIVE - /// in the bind context - /// - /// Here are the string versions of GPS_ flags, passed to IShellFolder::BindToObject() via IBindCtx::RegisterObjectParam() - /// These flags are valid when requesting an IPropertySetStorage or IPropertyStore handler - /// - /// The meaning of these flags are described above. - /// - /// There is no STR_ equivalent for GPS_TEMPORARY because temporary property stores - /// are provided by IShellItem2 only -- not by the underlying IShellFolder. + /// Setting the value of fFullscreen to true, the Shell treats this window as a full-screen window, and the taskbar + /// is moved to the bottom of the z-order when this window is active. Setting the value of fFullscreen to false + /// removes the full-screen marking, but does not cause the Shell to treat the window as though it were + /// definitely not full-screen. With a false fFullscreen value, the Shell depends on its automatic detection facility + /// to specify how the window should be treated, possibly still flagging the window as full-screen. /// - internal static class STR_GPS - { - public const string HANDLERPROPERTIESONLY = "GPS_HANDLERPROPERTIESONLY"; - public const string FASTPROPERTIESONLY = "GPS_FASTPROPERTIESONLY"; - public const string OPENSLOWITEM = "GPS_OPENSLOWITEM"; - public const string DELAYCREATION = "GPS_DELAYCREATION"; - public const string BESTEFFORT = "GPS_BESTEFFORT"; - public const string NO_OPLOCK = "GPS_NO_OPLOCK"; - } - - #endregion - - #region Structs - - [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)] - internal struct THUMBBUTTON - { - /// - /// WPARAM value for a THUMBBUTTON being clicked. - /// - public const int THBN_CLICKED = 0x1800; - - public THB dwMask; - public uint iId; - public uint iBitmap; - public IntPtr hIcon; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string szTip; - public THBF dwFlags; - } - - - [StructLayout(LayoutKind.Sequential, Pack = 4)] - internal struct PKEY - { - /// fmtid - private readonly Guid _fmtid; - /// pid - private readonly uint _pid; - - public PKEY(Guid fmtid, uint pid) - { - _fmtid = fmtid; - _pid = pid; - } - - /// PKEY_Title - public static readonly PKEY Title = new PKEY(new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), 2); - /// PKEY_AppUserModel_ID - public static readonly PKEY AppUserModel_ID = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5); - /// PKEY_AppUserModel_IsDestListSeparator - public static readonly PKEY AppUserModel_IsDestListSeparator = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 6); - /// PKEY_AppUserModel_RelaunchCommand - public static readonly PKEY AppUserModel_RelaunchCommand = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 2); - /// PKEY_AppUserModel_RelaunchDisplayNameResource - public static readonly PKEY AppUserModel_RelaunchDisplayNameResource = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 4); - /// PKEY_AppUserModel_RelaunchIconResource - public static readonly PKEY AppUserModel_RelaunchIconResource = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 3); - } - - #endregion - - #region Interfaces - - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.EnumIdList), - ] - internal interface IEnumIDList - { - [PreserveSig()] - HRESULT Next(uint celt, out IntPtr rgelt, out int pceltFetched); - [PreserveSig()] - HRESULT Skip(uint celt); - void Reset(); - void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumIDList ppenum); - } - - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.EnumObjects), - ] - internal interface IEnumObjects - { - //[local] - // This signature might not work... Hopefully don't need this interface though. - void Next(uint celt, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.IUnknown, IidParameterIndex = 1, SizeParamIndex = 0)] object[] rgelt, [Out] out uint pceltFetched); - - /* - [call_as(Next)] HRESULT RemoteNext( - [in] ULONG celt, - [in] REFIID riid, - [out, size_is(celt), length_is(*pceltFetched), iid_is(riid)] void **rgelt, - [out] ULONG *pceltFetched); - */ - - void Skip(uint celt); - - void Reset(); - - IEnumObjects Clone(); - } - - /// Unknown Object Array - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ObjectArray), - ] - internal interface IObjectArray - { - uint GetCount(); - [return: MarshalAs(UnmanagedType.IUnknown)] - object GetAt([In] uint uiIndex, [In] ref Guid riid); - } - - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ObjectArray), - ] - interface IObjectCollection : IObjectArray - { - #region IObjectArray redeclarations - new uint GetCount(); - [return: MarshalAs(UnmanagedType.IUnknown)] - new object GetAt([In] uint uiIndex, [In] ref Guid riid); - #endregion - - void AddObject([MarshalAs(UnmanagedType.IUnknown)] object punk); - void AddFromArray(IObjectArray poaSource); - void RemoveObjectAt(uint uiIndex); - void Clear(); - } - - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.PropertyStore) - ] - internal interface IPropertyStore - { - uint GetCount(); - PKEY GetAt(uint iProp); - void GetValue([In] ref PKEY pkey, [In, Out] PROPVARIANT pv); - void SetValue([In] ref PKEY pkey, PROPVARIANT pv); - void Commit(); - } - - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ShellFolder), - ] - internal interface IShellFolder - { - void ParseDisplayName( - [In] IntPtr hwnd, - [In] IBindCtx pbc, - [In, MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, - [In, Out] ref int pchEaten, - [Out] out IntPtr ppidl, - [In, Out] ref uint pdwAttributes); - - IEnumIDList EnumObjects( - [In] IntPtr hwnd, - [In] SHCONTF grfFlags); - - // returns an instance of a sub-folder which is specified by the IDList (pidl). - // IShellFolder or derived interfaces - [return: MarshalAs(UnmanagedType.Interface)] - object BindToObject( - [In] IntPtr pidl, - [In] IBindCtx pbc, - [In] ref Guid riid); - - // produces the same result as BindToObject() - [return: MarshalAs(UnmanagedType.Interface)] - object BindToStorage([In] IntPtr pidl, [In] IBindCtx pbc, [In] ref Guid riid); - - // compares two IDLists and returns the result. The shell - // explorer always passes 0 as lParam, which indicates 'sort by name'. - // It should return 0 (as CODE of the scode), if two id indicates the - // same object; negative value if pidl1 should be placed before pidl2; - // positive value if pidl2 should be placed before pidl1. - // use the macro ResultFromShort() to extract the result comparison - // it deals with the casting and type conversion issues for you - [PreserveSig] - HRESULT CompareIDs([In] IntPtr lParam, [In] IntPtr pidl1, [In] IntPtr pidl2); - - // creates a view object of the folder itself. The view - // object is a difference instance from the shell folder object. - // 'hwndOwner' can be used as the owner window of its dialog box or - // menu during the lifetime of the view object. - // This member function should always create a new - // instance which has only one reference count. The explorer may create - // more than one instances of view object from one shell folder object - // and treat them as separate instances. - // returns IShellView derived interface - [return: MarshalAs(UnmanagedType.Interface)] - object CreateViewObject([In] IntPtr hwndOwner, [In] ref Guid riid); - - // returns the attributes of specified objects in that - // folder. 'cidl' and 'apidl' specifies objects. 'apidl' contains only - // simple IDLists. The explorer initializes *prgfInOut with a set of - // flags to be evaluated. The shell folder may optimize the operation - // by not returning unspecified flags. - void GetAttributesOf( - [In] uint cidl, - [In] IntPtr apidl, - [In, Out] ref SFGAO rgfInOut); - - // creates a UI object to be used for specified objects. - // The shell explorer passes either IID_IDataObject (for transfer operation) - // or IID_IContextMenu (for context menu operation) as riid - // and many other interfaces - [return: MarshalAs(UnmanagedType.Interface)] - object GetUIObjectOf( - [In] IntPtr hwndOwner, - [In] uint cidl, - [In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 2)] IntPtr apidl, - [In] ref Guid riid, - [In, Out] ref uint rgfReserved); - - // returns the display name of the specified object. - // If the ID contains the display name (in the locale character set), - // it returns the offset to the name. Otherwise, it returns a pointer - // to the display name string (UNICODE), which is allocated by the - // task allocator, or fills in a buffer. - // use the helper APIS StrRetToStr() or StrRetToBuf() to deal with the different - // forms of the STRRET structure - void GetDisplayNameOf([In] IntPtr pidl, [In] SHGDN uFlags, [Out] out IntPtr pName); - - // sets the display name of the specified object. - // If it changes the ID as well, it returns the new ID which is - // alocated by the task allocator. - void SetNameOf([In] IntPtr hwnd, - [In] IntPtr pidl, - [In, MarshalAs(UnmanagedType.LPWStr)] string pszName, - [In] SHGDN uFlags, - [Out] out IntPtr ppidlOut); - } - + void MarkFullscreenWindow( IntPtr hwnd, [MarshalAs( UnmanagedType.Bool )] bool fFullscreen ); + } + + // Used to remove items from the automatic destination lists created when apps or the system call SHAddToRecentDocs to report usage of a document. + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ApplicationDestinations ) + ] + internal interface IApplicationDestinations + { + // Set the App User Model ID for the application removing destinations from its list. If an AppID is not provided + // via this method, the system will use a heuristically determined ID. This method must be called before + // RemoveDestination or RemoveAllDestinations. + void SetAppID( [In, MarshalAs( UnmanagedType.LPWStr )] string pszAppID ); + + // Remove an IShellItem or an IShellLink from the automatic destination list + void RemoveDestination( [MarshalAs( UnmanagedType.IUnknown )] object punk ); + + // Clear the frequent and recent destination lists for this application. + void RemoveAllDestinations(); + } + + /// + /// Allows an application to retrieve the most recent and frequent documents opened in that app, as reported via SHAddToRecentDocs + /// + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ApplicationDocumentLists ) + ] + internal interface IApplicationDocumentLists + { /// - /// Shell Namespace helper + /// Set the App User Model ID for the application retrieving this list. If an AppID is not provided via this method, + /// the system will use a heuristically determined ID. This method must be called before GetList. /// - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ShellItem), - ] - internal interface IShellItem - { - [return: MarshalAs(UnmanagedType.Interface)] - object BindToHandler(IBindCtx pbc, [In] ref Guid bhid, [In] ref Guid riid); - - IShellItem GetParent(); - - [return: MarshalAs(UnmanagedType.LPWStr)] - string GetDisplayName(SIGDN sigdnName); - - SFGAO GetAttributes(SFGAO sfgaoMask); - - int Compare(IShellItem psi, SICHINT hint); - } - - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ShellItemArray), - ] - internal interface IShellItemArray - { - [return: MarshalAs(UnmanagedType.Interface)] - object BindToHandler(IBindCtx pbc, [In] ref Guid rbhid, [In] ref Guid riid); - - [return: MarshalAs(UnmanagedType.Interface)] - object GetPropertyStore(int flags, [In] ref Guid riid); - - [return: MarshalAs(UnmanagedType.Interface)] - object GetPropertyDescriptionList([In] ref PKEY keyType, [In] ref Guid riid); - - uint GetAttributes(SIATTRIBFLAGS dwAttribFlags, uint sfgaoMask); - - uint GetCount(); - - IShellItem GetItemAt(uint dwIndex); - - [return: MarshalAs(UnmanagedType.Interface)] - object EnumItems(); - } + /// App Id. + void SetAppID( [MarshalAs( UnmanagedType.LPWStr )] string pszAppID ); /// - /// Shell Namespace helper 2 + /// Retrieve an IEnumObjects or IObjectArray for IShellItems and/or IShellLinks. + /// Items may appear in both the frequent and recent lists. /// - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ShellItem2), - ] - interface IShellItem2 : IShellItem - { - #region IShellItem redeclarations - [return: MarshalAs(UnmanagedType.Interface)] - new object BindToHandler([In] IBindCtx pbc, [In] ref Guid bhid, [In] ref Guid riid); - new IShellItem GetParent(); - [return: MarshalAs(UnmanagedType.LPWStr)] - new string GetDisplayName(SIGDN sigdnName); - new SFGAO GetAttributes(SFGAO sfgaoMask); - new int Compare(IShellItem psi, SICHINT hint); - #endregion - - [return: MarshalAs(UnmanagedType.Interface)] - object GetPropertyStore( - GPS flags, - [In] ref Guid riid); - - [return: MarshalAs(UnmanagedType.Interface)] - object GetPropertyStoreWithCreateObject( - GPS flags, - [MarshalAs(UnmanagedType.IUnknown)] object punkCreateObject, // factory for low-rights creation of type ICreateObject - [In] ref Guid riid); - - [return: MarshalAs(UnmanagedType.Interface)] - object GetPropertyStoreForKeys( - IntPtr rgKeys, - uint cKeys, - GPS flags, - [In] ref Guid riid); - - [return: MarshalAs(UnmanagedType.Interface)] - object GetPropertyDescriptionList( - IntPtr keyType, - [In] ref Guid riid); - - // Ensures any cached information in this item is up to date, or returns __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) if the item does not exist. - void Update(IBindCtx pbc); - - PROPVARIANT GetProperty(IntPtr key); - - Guid GetCLSID(IntPtr key); - - FILETIME GetFileTime(IntPtr key); - - int GetInt32(IntPtr key); - - [return: MarshalAs(UnmanagedType.LPWStr)] - string GetString(IntPtr key); - - uint GetUInt32(IntPtr key); + /// + /// + [return: MarshalAs( UnmanagedType.IUnknown )] + object GetList( [In] APPDOCLISTTYPE listtype, [In] uint cItemsDesired, [In] ref Guid riid ); + } + + // Custom Destination List + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.CustomDestinationList ) + ] + internal interface ICustomDestinationList + { + void SetAppID( [In, MarshalAs( UnmanagedType.LPWStr )] string pszAppID ); + + // Retrieve IObjectArray of IShellItems or IShellLinks that represent removed destinations + [return: MarshalAs( UnmanagedType.Interface )] + object BeginList( out uint pcMaxSlots, [In] ref Guid riid ); + + // PreserveSig because this will return custom errors when attempting to add unregistered ShellItems. + // Can't readily detect that case without just trying to append it. + [PreserveSig] + HRESULT AppendCategory( [MarshalAs( UnmanagedType.LPWStr )] string pszCategory, IObjectArray poa ); + void AppendKnownCategory( KDC category ); + [PreserveSig] + HRESULT AddUserTasks( IObjectArray poa ); + void CommitList(); + + // Retrieve IObjectCollection of IShellItems + [return: MarshalAs( UnmanagedType.Interface )] + object GetRemovedDestinations( [In] ref Guid riid ); + void DeleteList( [MarshalAs( UnmanagedType.LPWStr )] string pszAppID ); + void AbortList(); + } + + /// + /// Provides access to the App User Model ID on objects supporting this value. + /// + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ObjectWithAppUserModelId ) + ] + internal interface IObjectWithAppUserModelId + { + void SetAppID( [MarshalAs( UnmanagedType.LPWStr )] string pszAppID ); + [return: MarshalAs( UnmanagedType.LPWStr )] + string GetAppID(); + }; + + /// + /// Provides access to the ProgID associated with an object + /// + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.ObjectWithProgId ) + ] + internal interface IObjectWithProgId + { + void SetProgID( [MarshalAs( UnmanagedType.LPWStr )] string pszProgID ); + [return: MarshalAs( UnmanagedType.LPWStr )] + string GetProgID(); + }; + + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.TaskbarList3 ), + ] + internal interface ITaskbarList3 : ITaskbarList2 + { + #region ITaskbarList2 redeclaration + + #region ITaskbarList redeclaration + new void HrInit(); + new void AddTab( IntPtr hwnd ); + new void DeleteTab( IntPtr hwnd ); + new void ActivateTab( IntPtr hwnd ); + new void SetActiveAlt( IntPtr hwnd ); + #endregion - ulong GetUInt64(IntPtr key); + new void MarkFullscreenWindow( IntPtr hwnd, [MarshalAs( UnmanagedType.Bool )] bool fFullscreen ); - [return: MarshalAs(UnmanagedType.Bool)] - void GetBool(IntPtr key); - } + #endregion - [ - ComImport, - InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ShellLink), - ] - internal interface IShellLinkW - { - void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, [In, Out] WIN32_FIND_DATAW pfd, SLGP fFlags); - void GetIDList(out IntPtr ppidl); - void SetIDList(IntPtr pidl); - void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName); - void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); - void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); - void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - short GetHotKey(); - void SetHotKey(short wHotKey); - uint GetShowCmd(); - void SetShowCmd(uint iShowCmd); - void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon); - void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved); - void Resolve(IntPtr hwnd, uint fFlags); - void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } + [PreserveSig] + HRESULT SetProgressValue( IntPtr hwnd, ulong ullCompleted, ulong ullTotal ); - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.TaskbarList), - ] - internal interface ITaskbarList - { - /// - /// This function must be called first to validate use of other members. - /// - void HrInit(); - - /// - /// This function adds a tab for hwnd to the taskbar. - /// - /// The HWND for which to add the tab. - void AddTab(IntPtr hwnd); - - /// - /// This function deletes a tab for hwnd from the taskbar. - /// - /// The HWND for which the tab is to be deleted. - void DeleteTab(IntPtr hwnd); - - /// - /// This function activates the tab associated with hwnd on the taskbar. - /// - /// The HWND for which the tab is to be actuvated. - void ActivateTab(IntPtr hwnd); - - /// - /// This function marks hwnd in the taskbar as the active tab. - /// - /// The HWND to activate. - void SetActiveAlt(IntPtr hwnd); - } + [PreserveSig] + HRESULT SetProgressState( IntPtr hwnd, TBPF tbpFlags ); - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.TaskbarList2), - ] - internal interface ITaskbarList2 : ITaskbarList - { - #region ITaskbarList redeclaration - new void HrInit(); - new void AddTab(IntPtr hwnd); - new void DeleteTab(IntPtr hwnd); - new void ActivateTab(IntPtr hwnd); - new void SetActiveAlt(IntPtr hwnd); - #endregion - - /// - /// Marks a window as full-screen. - /// - /// The handle of the window to be marked. - /// A Boolean value marking the desired full-screen status of the window. - /// - /// Setting the value of fFullscreen to true, the Shell treats this window as a full-screen window, and the taskbar - /// is moved to the bottom of the z-order when this window is active. Setting the value of fFullscreen to false - /// removes the full-screen marking, but does not cause the Shell to treat the window as though it were - /// definitely not full-screen. With a false fFullscreen value, the Shell depends on its automatic detection facility - /// to specify how the window should be treated, possibly still flagging the window as full-screen. - /// - void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen); - } + [PreserveSig] + HRESULT RegisterTab( IntPtr hwndTab, IntPtr hwndMDI ); - // Used to remove items from the automatic destination lists created when apps or the system call SHAddToRecentDocs to report usage of a document. - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ApplicationDestinations) - ] - internal interface IApplicationDestinations - { - // Set the App User Model ID for the application removing destinations from its list. If an AppID is not provided - // via this method, the system will use a heuristically determined ID. This method must be called before - // RemoveDestination or RemoveAllDestinations. - void SetAppID([In, MarshalAs(UnmanagedType.LPWStr)] string pszAppID); + [PreserveSig] + HRESULT UnregisterTab( IntPtr hwndTab ); - // Remove an IShellItem or an IShellLink from the automatic destination list - void RemoveDestination([MarshalAs(UnmanagedType.IUnknown)] object punk); + [PreserveSig] + HRESULT SetTabOrder( IntPtr hwndTab, IntPtr hwndInsertBefore ); - // Clear the frequent and recent destination lists for this application. - void RemoveAllDestinations(); - } + [PreserveSig] + HRESULT SetTabActive( IntPtr hwndTab, IntPtr hwndMDI, uint dwReserved ); - /// - /// Allows an application to retrieve the most recent and frequent documents opened in that app, as reported via SHAddToRecentDocs - /// - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ApplicationDocumentLists) - ] - internal interface IApplicationDocumentLists - { - /// - /// Set the App User Model ID for the application retrieving this list. If an AppID is not provided via this method, - /// the system will use a heuristically determined ID. This method must be called before GetList. - /// - /// App Id. - void SetAppID([MarshalAs(UnmanagedType.LPWStr)] string pszAppID); - - /// - /// Retrieve an IEnumObjects or IObjectArray for IShellItems and/or IShellLinks. - /// Items may appear in both the frequent and recent lists. - /// - /// - /// - [return: MarshalAs(UnmanagedType.IUnknown)] - object GetList([In] APPDOCLISTTYPE listtype, [In] uint cItemsDesired, [In] ref Guid riid); - } + [PreserveSig] + HRESULT ThumbBarAddButtons( IntPtr hwnd, uint cButtons, [MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 1 )] THUMBBUTTON[] pButtons ); - // Custom Destination List - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.CustomDestinationList) - ] - internal interface ICustomDestinationList - { - void SetAppID([In, MarshalAs(UnmanagedType.LPWStr)] string pszAppID); - - // Retrieve IObjectArray of IShellItems or IShellLinks that represent removed destinations - [return: MarshalAs(UnmanagedType.Interface)] - object BeginList(out uint pcMaxSlots, [In] ref Guid riid); - - // PreserveSig because this will return custom errors when attempting to add unregistered ShellItems. - // Can't readily detect that case without just trying to append it. - [PreserveSig] - HRESULT AppendCategory([MarshalAs(UnmanagedType.LPWStr)] string pszCategory, IObjectArray poa); - void AppendKnownCategory(KDC category); - [PreserveSig] - HRESULT AddUserTasks(IObjectArray poa); - void CommitList(); - - // Retrieve IObjectCollection of IShellItems - [return: MarshalAs(UnmanagedType.Interface)] - object GetRemovedDestinations([In] ref Guid riid); - void DeleteList([MarshalAs(UnmanagedType.LPWStr)] string pszAppID); - void AbortList(); - } + [PreserveSig] + HRESULT ThumbBarUpdateButtons( IntPtr hwnd, uint cButtons, [MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 1 )] THUMBBUTTON[] pButtons ); - /// - /// Provides access to the App User Model ID on objects supporting this value. - /// - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ObjectWithAppUserModelId) - ] - internal interface IObjectWithAppUserModelId - { - void SetAppID([MarshalAs(UnmanagedType.LPWStr)] string pszAppID); - [return: MarshalAs(UnmanagedType.LPWStr)] - string GetAppID(); - }; - - /// - /// Provides access to the ProgID associated with an object - /// - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.ObjectWithProgId) - ] - internal interface IObjectWithProgId - { - void SetProgID([MarshalAs(UnmanagedType.LPWStr)] string pszProgID); - [return: MarshalAs(UnmanagedType.LPWStr)] - string GetProgID(); - }; - - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.TaskbarList3), - ] - internal interface ITaskbarList3 : ITaskbarList2 - { - #region ITaskbarList2 redeclaration - - #region ITaskbarList redeclaration - new void HrInit(); - new void AddTab(IntPtr hwnd); - new void DeleteTab(IntPtr hwnd); - new void ActivateTab(IntPtr hwnd); - new void SetActiveAlt(IntPtr hwnd); - #endregion - - new void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen); - - #endregion + [PreserveSig] + HRESULT ThumbBarSetImageList( IntPtr hwnd, [MarshalAs( UnmanagedType.IUnknown )] object himl ); - [PreserveSig] - HRESULT SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal); + [PreserveSig] + HRESULT SetOverlayIcon( IntPtr hwnd, IntPtr hIcon, [MarshalAs( UnmanagedType.LPWStr )] string pszDescription ); - [PreserveSig] - HRESULT SetProgressState(IntPtr hwnd, TBPF tbpFlags); + [PreserveSig] + HRESULT SetThumbnailTooltip( IntPtr hwnd, [MarshalAs( UnmanagedType.LPWStr )] string pszTip ); - [PreserveSig] - HRESULT RegisterTab(IntPtr hwndTab, IntPtr hwndMDI); + // Using RefRECT to making passing NULL possible. Removes clipping from the HWND. + [PreserveSig] + HRESULT SetThumbnailClip( IntPtr hwnd, RefRECT prcClip ); + } - [PreserveSig] - HRESULT UnregisterTab(IntPtr hwndTab); + [ + ComImport, + InterfaceType( ComInterfaceType.InterfaceIsIUnknown ), + Guid( IID.TaskbarList3 ), + ] + internal interface ITaskbarList4 : ITaskbarList3 + { + #region ITaskbarList3 redeclaration - [PreserveSig] - HRESULT SetTabOrder(IntPtr hwndTab, IntPtr hwndInsertBefore); + #region ITaskbarList2 redeclaration - [PreserveSig] - HRESULT SetTabActive(IntPtr hwndTab, IntPtr hwndMDI, uint dwReserved); - - [PreserveSig] - HRESULT ThumbBarAddButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] THUMBBUTTON[] pButtons); - - [PreserveSig] - HRESULT ThumbBarUpdateButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] THUMBBUTTON[] pButtons); + #region ITaskbarList redeclaration + new void HrInit(); + new void AddTab( IntPtr hwnd ); + new void DeleteTab( IntPtr hwnd ); + new void ActivateTab( IntPtr hwnd ); + new void SetActiveAlt( IntPtr hwnd ); + #endregion - [PreserveSig] - HRESULT ThumbBarSetImageList(IntPtr hwnd, [MarshalAs(UnmanagedType.IUnknown)] object himl); + new void MarkFullscreenWindow( IntPtr hwnd, [MarshalAs( UnmanagedType.Bool )] bool fFullscreen ); - [PreserveSig] - HRESULT SetOverlayIcon(IntPtr hwnd, IntPtr hIcon, [MarshalAs(UnmanagedType.LPWStr)] string pszDescription); + #endregion - [PreserveSig] - HRESULT SetThumbnailTooltip(IntPtr hwnd, [MarshalAs(UnmanagedType.LPWStr)] string pszTip); + [PreserveSig] + new HRESULT SetProgressValue( IntPtr hwnd, ulong ullCompleted, ulong ullTotal ); + [PreserveSig] + new HRESULT SetProgressState( IntPtr hwnd, TBPF tbpFlags ); + [PreserveSig] + new HRESULT RegisterTab( IntPtr hwndTab, IntPtr hwndMDI ); + [PreserveSig] + new HRESULT UnregisterTab( IntPtr hwndTab ); + [PreserveSig] + new HRESULT SetTabOrder( IntPtr hwndTab, IntPtr hwndInsertBefore ); + [PreserveSig] + new HRESULT SetTabActive( IntPtr hwndTab, IntPtr hwndMDI, uint dwReserved ); + [PreserveSig] + new HRESULT ThumbBarAddButtons( IntPtr hwnd, uint cButtons, [MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 1 )] THUMBBUTTON[] pButtons ); + [PreserveSig] + new HRESULT ThumbBarUpdateButtons( IntPtr hwnd, uint cButtons, [MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 1 )] THUMBBUTTON[] pButtons ); + [PreserveSig] + new HRESULT ThumbBarSetImageList( IntPtr hwnd, [MarshalAs( UnmanagedType.IUnknown )] object himl ); + [PreserveSig] + new HRESULT SetOverlayIcon( IntPtr hwnd, IntPtr hIcon, [MarshalAs( UnmanagedType.LPWStr )] string pszDescription ); + [PreserveSig] + new HRESULT SetThumbnailTooltip( IntPtr hwnd, [MarshalAs( UnmanagedType.LPWStr )] string pszTip ); + // Using RefRECT to making passing NULL possible. Removes clipping from the HWND. + [PreserveSig] + new HRESULT SetThumbnailClip( IntPtr hwnd, RefRECT prcClip ); - // Using RefRECT to making passing NULL possible. Removes clipping from the HWND. - [PreserveSig] - HRESULT SetThumbnailClip(IntPtr hwnd, RefRECT prcClip); - } + #endregion - [ - ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid(IID.TaskbarList3), - ] - internal interface ITaskbarList4 : ITaskbarList3 - { - #region ITaskbarList3 redeclaration - - #region ITaskbarList2 redeclaration - - #region ITaskbarList redeclaration - new void HrInit(); - new void AddTab(IntPtr hwnd); - new void DeleteTab(IntPtr hwnd); - new void ActivateTab(IntPtr hwnd); - new void SetActiveAlt(IntPtr hwnd); - #endregion - - new void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen); - - #endregion - - [PreserveSig] new HRESULT SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal); - [PreserveSig] new HRESULT SetProgressState(IntPtr hwnd, TBPF tbpFlags); - [PreserveSig] new HRESULT RegisterTab(IntPtr hwndTab, IntPtr hwndMDI); - [PreserveSig] new HRESULT UnregisterTab(IntPtr hwndTab); - [PreserveSig] new HRESULT SetTabOrder(IntPtr hwndTab, IntPtr hwndInsertBefore); - [PreserveSig] new HRESULT SetTabActive(IntPtr hwndTab, IntPtr hwndMDI, uint dwReserved); - [PreserveSig] new HRESULT ThumbBarAddButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] THUMBBUTTON[] pButtons); - [PreserveSig] new HRESULT ThumbBarUpdateButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] THUMBBUTTON[] pButtons); - [PreserveSig] new HRESULT ThumbBarSetImageList(IntPtr hwnd, [MarshalAs(UnmanagedType.IUnknown)] object himl); - [PreserveSig] new HRESULT SetOverlayIcon(IntPtr hwnd, IntPtr hIcon, [MarshalAs(UnmanagedType.LPWStr)] string pszDescription); - [PreserveSig] new HRESULT SetThumbnailTooltip(IntPtr hwnd, [MarshalAs(UnmanagedType.LPWStr)] string pszTip); - // Using RefRECT to making passing NULL possible. Removes clipping from the HWND. - [PreserveSig] new HRESULT SetThumbnailClip(IntPtr hwnd, RefRECT prcClip); - - #endregion - - void SetTabProperties(IntPtr hwndTab, STPF stpFlags); - } + void SetTabProperties( IntPtr hwndTab, STPF stpFlags ); + } - #endregion + #endregion } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/StreamHelper.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/StreamHelper.cs index 189647df..72c3f39a 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/StreamHelper.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/StreamHelper.cs @@ -20,338 +20,338 @@ namespace Standard { - using System; - using System.Diagnostics.CodeAnalysis; - using System.IO; - using System.Runtime.InteropServices; - using System.Runtime.InteropServices.ComTypes; + using System; + using System.Diagnostics.CodeAnalysis; + using System.IO; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + + // disambiguate with System.Runtime.InteropServices.STATSTG + using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG; + + // All these methods return void. Does the standard marshaller convert them to HRESULTs? + /// + /// Wraps a managed stream instance into an interface pointer consumable by COM. + /// + internal sealed class ManagedIStream : IStream, IDisposable + { + private const int STGTY_STREAM = 2; + private const int STGM_READWRITE = 2; + private const int LOCK_EXCLUSIVE = 2; + + private Stream _source; - // disambiguate with System.Runtime.InteropServices.STATSTG - using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG; + /// + /// Initializes a new instance of the ManagedIStream class with the specified managed Stream object. + /// + /// + /// The stream that this IStream reference is wrapping. + /// + public ManagedIStream( Stream source ) + { + Verify.IsNotNull( source, "source" ); + _source = source; + } + + private void _Validate() + { + if( null == _source ) + { + throw new ObjectDisposedException( "this" ); + } + } + + // Comments are taken from MSDN IStream documentation. + #region IStream Members - // All these methods return void. Does the standard marshaller convert them to HRESULTs? /// - /// Wraps a managed stream instance into an interface pointer consumable by COM. + /// Creates a new stream object with its own seek pointer that + /// references the same bytes as the original stream. /// - internal sealed class ManagedIStream : IStream, IDisposable + /// + /// When this method returns, contains the new stream object. This parameter is passed uninitialized. + /// + /// + /// For more information, see the existing documentation for IStream::Clone in the MSDN library. + /// This class doesn't implement Clone. A COMException is thrown if it is used. + /// + [SuppressMessage( "Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)" )] + [Obsolete( "The method is not implemented", true )] + public void Clone( out IStream ppstm ) { - private const int STGTY_STREAM = 2; - private const int STGM_READWRITE = 2; - private const int LOCK_EXCLUSIVE = 2; - - private Stream _source; - - /// - /// Initializes a new instance of the ManagedIStream class with the specified managed Stream object. - /// - /// - /// The stream that this IStream reference is wrapping. - /// - public ManagedIStream(Stream source) - { - Verify.IsNotNull(source, "source"); - _source = source; - } + ppstm = null; + HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed( "The method is not implemented." ); + } - private void _Validate() - { - if (null == _source) - { - throw new ObjectDisposedException("this"); - } - } + /// + /// Ensures that any changes made to a stream object that is open in transacted + /// mode are reflected in the parent storage. + /// + /// + /// A value that controls how the changes for the stream object are committed. + /// + /// + /// For more information, see the existing documentation for IStream::Commit in the MSDN library. + /// + public void Commit( int grfCommitFlags ) + { + _Validate(); + _source.Flush(); + } - // Comments are taken from MSDN IStream documentation. - #region IStream Members - - /// - /// Creates a new stream object with its own seek pointer that - /// references the same bytes as the original stream. - /// - /// - /// When this method returns, contains the new stream object. This parameter is passed uninitialized. - /// - /// - /// For more information, see the existing documentation for IStream::Clone in the MSDN library. - /// This class doesn't implement Clone. A COMException is thrown if it is used. - /// - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)")] - [Obsolete("The method is not implemented", true)] - public void Clone(out IStream ppstm) - { - ppstm = null; - HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed("The method is not implemented."); - } + /// + /// Copies a specified number of bytes from the current seek pointer in the + /// stream to the current seek pointer in another stream. + /// + /// + /// A reference to the destination stream. + /// + /// + /// The number of bytes to copy from the source stream. + /// + /// + /// On successful return, contains the actual number of bytes read from the source. + /// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written + /// to this parameter on success.) + /// + /// + /// On successful return, contains the actual number of bytes written to the destination. + /// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written + /// to this parameter on success.) + /// + [SuppressMessage( "Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0" )] + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public void CopyTo( IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten ) + { + Verify.IsNotNull( pstm, "pstm" ); - /// - /// Ensures that any changes made to a stream object that is open in transacted - /// mode are reflected in the parent storage. - /// - /// - /// A value that controls how the changes for the stream object are committed. - /// - /// - /// For more information, see the existing documentation for IStream::Commit in the MSDN library. - /// - public void Commit(int grfCommitFlags) - { - _Validate(); - _source.Flush(); - } + _Validate(); - /// - /// Copies a specified number of bytes from the current seek pointer in the - /// stream to the current seek pointer in another stream. - /// - /// - /// A reference to the destination stream. - /// - /// - /// The number of bytes to copy from the source stream. - /// - /// - /// On successful return, contains the actual number of bytes read from the source. - /// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written - /// to this parameter on success.) - /// - /// - /// On successful return, contains the actual number of bytes written to the destination. - /// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written - /// to this parameter on success.) - /// - [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) - { - Verify.IsNotNull(pstm, "pstm"); - - _Validate(); - - // Reasonbly sized buffer, don't try to copy large streams in bulk. - var buffer = new byte[4096]; - long cbWritten = 0; - - while (cbWritten < cb) - { - int cbRead = _source.Read(buffer, 0, buffer.Length); - if (0 == cbRead) - { - break; - } - - // COM documentation is a bit vague here whether NULL is valid for the third parameter. - // Going to assume it is, as most implementations I've seen treat it as optional. - // It's possible this will break on some IStream implementations. - pstm.Write(buffer, cbRead, IntPtr.Zero); - cbWritten += cbRead; - } - - if (IntPtr.Zero != pcbRead) - { - Marshal.WriteInt64(pcbRead, cbWritten); - } - - if (IntPtr.Zero != pcbWritten) - { - Marshal.WriteInt64(pcbWritten, cbWritten); - } - } + // Reasonbly sized buffer, don't try to copy large streams in bulk. + var buffer = new byte[ 4096 ]; + long cbWritten = 0; - /// - /// Restricts access to a specified range of bytes in the stream. - /// - /// - /// The byte offset for the beginning of the range. - /// - /// - /// The length of the range, in bytes, to restrict. - /// - /// - /// The requested restrictions on accessing the range. - /// - /// - /// For more information, see the existing documentation for IStream::LockRegion in the MSDN library. - /// This class doesn't implement LockRegion. A COMException is thrown if it is used. - /// - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)"), Obsolete("The method is not implemented", true)] - public void LockRegion(long libOffset, long cb, int dwLockType) + while( cbWritten < cb ) + { + int cbRead = _source.Read( buffer, 0, buffer.Length ); + if( 0 == cbRead ) { - HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed("The method is not implemented."); + break; } - /// - /// Reads a specified number of bytes from the stream object into memory starting at the current seek pointer. - /// - /// - /// When this method returns, contains the data read from the stream. This parameter is passed uninitialized. - /// - /// - /// The number of bytes to read from the stream object. - /// - /// - /// A pointer to a ULONG variable that receives the actual number of bytes read from the stream object. - /// - /// - /// For more information, see the existing documentation for ISequentialStream::Read in the MSDN library. - /// - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public void Read(byte[] pv, int cb, IntPtr pcbRead) - { - _Validate(); + // COM documentation is a bit vague here whether NULL is valid for the third parameter. + // Going to assume it is, as most implementations I've seen treat it as optional. + // It's possible this will break on some IStream implementations. + pstm.Write( buffer, cbRead, IntPtr.Zero ); + cbWritten += cbRead; + } + + if( IntPtr.Zero != pcbRead ) + { + Marshal.WriteInt64( pcbRead, cbWritten ); + } + + if( IntPtr.Zero != pcbWritten ) + { + Marshal.WriteInt64( pcbWritten, cbWritten ); + } + } - int cbRead = _source.Read(pv, 0, cb); + /// + /// Restricts access to a specified range of bytes in the stream. + /// + /// + /// The byte offset for the beginning of the range. + /// + /// + /// The length of the range, in bytes, to restrict. + /// + /// + /// The requested restrictions on accessing the range. + /// + /// + /// For more information, see the existing documentation for IStream::LockRegion in the MSDN library. + /// This class doesn't implement LockRegion. A COMException is thrown if it is used. + /// + [SuppressMessage( "Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)" ), Obsolete( "The method is not implemented", true )] + public void LockRegion( long libOffset, long cb, int dwLockType ) + { + HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed( "The method is not implemented." ); + } - if (IntPtr.Zero != pcbRead) - { - Marshal.WriteInt32(pcbRead, cbRead); - } - } + /// + /// Reads a specified number of bytes from the stream object into memory starting at the current seek pointer. + /// + /// + /// When this method returns, contains the data read from the stream. This parameter is passed uninitialized. + /// + /// + /// The number of bytes to read from the stream object. + /// + /// + /// A pointer to a ULONG variable that receives the actual number of bytes read from the stream object. + /// + /// + /// For more information, see the existing documentation for ISequentialStream::Read in the MSDN library. + /// + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public void Read( byte[] pv, int cb, IntPtr pcbRead ) + { + _Validate(); + int cbRead = _source.Read( pv, 0, cb ); - /// - /// Discards all changes that have been made to a transacted stream since the last Commit call. - /// - /// - /// This class doesn't implement Revert. A COMException is thrown if it is used. - /// - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)"), Obsolete("The method is not implemented", true)] - public void Revert() - { - HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed("The method is not implemented."); - } + if( IntPtr.Zero != pcbRead ) + { + Marshal.WriteInt32( pcbRead, cbRead ); + } + } - /// - /// Changes the seek pointer to a new location relative to the beginning of the - /// stream, to the end of the stream, or to the current seek pointer. - /// - /// - /// The displacement to add to dwOrigin. - /// - /// - /// The origin of the seek. The origin can be the beginning of the file, the current seek pointer, or the end of the file. - /// - /// - /// On successful return, contains the offset of the seek pointer from the beginning of the stream. - /// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written - /// to this parameter on success.) - /// - /// - /// For more information, see the existing documentation for IStream::Seek in the MSDN library. - /// - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) - { - _Validate(); - long position = _source.Seek(dlibMove, (SeekOrigin)dwOrigin); + /// + /// Discards all changes that have been made to a transacted stream since the last Commit call. + /// + /// + /// This class doesn't implement Revert. A COMException is thrown if it is used. + /// + [SuppressMessage( "Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)" ), Obsolete( "The method is not implemented", true )] + public void Revert() + { + HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed( "The method is not implemented." ); + } - if (IntPtr.Zero != plibNewPosition) - { - Marshal.WriteInt64(plibNewPosition, position); - } - } + /// + /// Changes the seek pointer to a new location relative to the beginning of the + /// stream, to the end of the stream, or to the current seek pointer. + /// + /// + /// The displacement to add to dwOrigin. + /// + /// + /// The origin of the seek. The origin can be the beginning of the file, the current seek pointer, or the end of the file. + /// + /// + /// On successful return, contains the offset of the seek pointer from the beginning of the stream. + /// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written + /// to this parameter on success.) + /// + /// + /// For more information, see the existing documentation for IStream::Seek in the MSDN library. + /// + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public void Seek( long dlibMove, int dwOrigin, IntPtr plibNewPosition ) + { + _Validate(); - /// - /// Changes the size of the stream object. - /// - /// - /// The new size of the stream as a number of bytes. - /// - /// - /// For more information, see the existing documentation for IStream::SetSize in the MSDN library. - /// - public void SetSize(long libNewSize) - { - _Validate(); - _source.SetLength(libNewSize); - } + long position = _source.Seek( dlibMove, ( SeekOrigin )dwOrigin ); - /// - /// Retrieves the STATSTG structure for this stream. - /// - /// - /// When this method returns, contains a STATSTG structure that describes this stream object. - /// This parameter is passed uninitialized. - /// - /// - /// Members in the STATSTG structure that this method does not return, thus saving some memory allocation operations. - /// - public void Stat(out STATSTG pstatstg, int grfStatFlag) - { - pstatstg = default(STATSTG); - _Validate(); + if( IntPtr.Zero != plibNewPosition ) + { + Marshal.WriteInt64( plibNewPosition, position ); + } + } - pstatstg.type = STGTY_STREAM; - pstatstg.cbSize = _source.Length; - pstatstg.grfMode = STGM_READWRITE; - pstatstg.grfLocksSupported = LOCK_EXCLUSIVE; - } + /// + /// Changes the size of the stream object. + /// + /// + /// The new size of the stream as a number of bytes. + /// + /// + /// For more information, see the existing documentation for IStream::SetSize in the MSDN library. + /// + public void SetSize( long libNewSize ) + { + _Validate(); + _source.SetLength( libNewSize ); + } - /// - /// Removes the access restriction on a range of bytes previously restricted with the LockRegion method. - /// - /// The byte offset for the beginning of the range. - /// - /// - /// The length, in bytes, of the range to restrict. - /// - /// - /// The access restrictions previously placed on the range. - /// - /// - /// For more information, see the existing documentation for IStream::UnlockRegion in the MSDN library. - /// This class doesn't implement UnlockRegion. A COMException is thrown if it is used. - /// - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)")] - [Obsolete("The method is not implemented", true)] - public void UnlockRegion(long libOffset, long cb, int dwLockType) - { - HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed("The method is not implemented."); - } + /// + /// Retrieves the STATSTG structure for this stream. + /// + /// + /// When this method returns, contains a STATSTG structure that describes this stream object. + /// This parameter is passed uninitialized. + /// + /// + /// Members in the STATSTG structure that this method does not return, thus saving some memory allocation operations. + /// + public void Stat( out STATSTG pstatstg, int grfStatFlag ) + { + pstatstg = default( STATSTG ); + _Validate(); - /// - /// Writes a specified number of bytes into the stream object starting at the current seek pointer. - /// - /// - /// The buffer to write this stream to. - /// - /// - /// The number of bytes to write to the stream. - /// - /// - /// On successful return, contains the actual number of bytes written to the stream object. - /// If the caller sets this pointer to null, this method does not provide the actual number - /// of bytes written. - /// - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public void Write(byte[] pv, int cb, IntPtr pcbWritten) - { - _Validate(); + pstatstg.type = STGTY_STREAM; + pstatstg.cbSize = _source.Length; + pstatstg.grfMode = STGM_READWRITE; + pstatstg.grfLocksSupported = LOCK_EXCLUSIVE; + } - _source.Write(pv, 0, cb); + /// + /// Removes the access restriction on a range of bytes previously restricted with the LockRegion method. + /// + /// The byte offset for the beginning of the range. + /// + /// + /// The length, in bytes, of the range to restrict. + /// + /// + /// The access restrictions previously placed on the range. + /// + /// + /// For more information, see the existing documentation for IStream::UnlockRegion in the MSDN library. + /// This class doesn't implement UnlockRegion. A COMException is thrown if it is used. + /// + [SuppressMessage( "Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)" )] + [Obsolete( "The method is not implemented", true )] + public void UnlockRegion( long libOffset, long cb, int dwLockType ) + { + HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed( "The method is not implemented." ); + } - if (IntPtr.Zero != pcbWritten) - { - Marshal.WriteInt32(pcbWritten, cb); - } - } + /// + /// Writes a specified number of bytes into the stream object starting at the current seek pointer. + /// + /// + /// The buffer to write this stream to. + /// + /// + /// The number of bytes to write to the stream. + /// + /// + /// On successful return, contains the actual number of bytes written to the stream object. + /// If the caller sets this pointer to null, this method does not provide the actual number + /// of bytes written. + /// + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public void Write( byte[] pv, int cb, IntPtr pcbWritten ) + { + _Validate(); - #endregion + _source.Write( pv, 0, cb ); - #region IDisposable Members + if( IntPtr.Zero != pcbWritten ) + { + Marshal.WriteInt32( pcbWritten, cb ); + } + } - /// - /// Releases resources controlled by this object. - /// - /// - /// Dispose can be called multiple times, but trying to use the object - /// after it has been disposed will generally throw ObjectDisposedExceptions. - /// - public void Dispose() - { - _source = null; - } + #endregion - #endregion + #region IDisposable Members + + /// + /// Releases resources controlled by this object. + /// + /// + /// Dispose can be called multiple times, but trying to use the object + /// after it has been disposed will generally throw ObjectDisposedExceptions. + /// + public void Dispose() + { + _source = null; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Utilities.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Utilities.cs index 0460fa8a..9157d939 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Utilities.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Utilities.cs @@ -25,1029 +25,1047 @@ // might be included in multiple assemblies. namespace Standard { - using System; - using System.Collections.Generic; - using System.ComponentModel; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.IO; - using System.Reflection; - using System.Runtime.InteropServices; - using System.Security.Cryptography; - using System.Text; - using System.Windows; - using System.Windows.Media; - using System.Windows.Media.Imaging; - - internal static partial class Utility + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.IO; + using System.Reflection; + using System.Runtime.InteropServices; + using System.Security.Cryptography; + using System.Text; + using System.Windows; + using System.Windows.Media; + using System.Windows.Media.Imaging; + + internal static partial class Utility + { + private static readonly Version _osVersion = Environment.OSVersion.Version; + private static readonly Version _presentationFrameworkVersion = Assembly.GetAssembly( typeof( Window ) ).GetName().Version; + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + private static bool _MemCmp( IntPtr left, IntPtr right, long cb ) { - private static readonly Version _osVersion = Environment.OSVersion.Version; - private static readonly Version _presentationFrameworkVersion = Assembly.GetAssembly(typeof(Window)).GetName().Version; + int offset = 0; - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private static bool _MemCmp(IntPtr left, IntPtr right, long cb) - { - int offset = 0; - - for (; offset < (cb - sizeof(Int64)); offset += sizeof(Int64)) - { - Int64 left64 = Marshal.ReadInt64(left, offset); - Int64 right64 = Marshal.ReadInt64(right, offset); - - if (left64 != right64) - { - return false; - } - } - - for (; offset < cb; offset += sizeof(byte)) - { - byte left8 = Marshal.ReadByte(left, offset); - byte right8 = Marshal.ReadByte(right, offset); - - if (left8 != right8) - { - return false; - } - } - - return true; - } - - /// The native RGB macro. - /// - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static int RGB(Color c) - { - return c.R | (c.G << 8) | (c.B << 16); - } - - /// Convert a native integer that represent a color with an alpha channel into a Color struct. - /// The integer that represents the color. Its bits are of the format 0xAARRGGBB. - /// A Color representation of the parameter. - public static Color ColorFromArgbDword(uint color) - { - return Color.FromArgb( - (byte)((color & 0xFF000000) >> 24), - (byte)((color & 0x00FF0000) >> 16), - (byte)((color & 0x0000FF00) >> 8), - (byte)((color & 0x000000FF) >> 0)); - } - - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static int GET_X_LPARAM(IntPtr lParam) - { - return LOWORD(lParam.ToInt32()); - } + for( ; offset < ( cb - sizeof( Int64 ) ); offset += sizeof( Int64 ) ) + { + Int64 left64 = Marshal.ReadInt64( left, offset ); + Int64 right64 = Marshal.ReadInt64( right, offset ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static int GET_Y_LPARAM(IntPtr lParam) + if( left64 != right64 ) { - return HIWORD(lParam.ToInt32()); + return false; } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static int HIWORD(int i) - { - return (short)(i >> 16); - } + for( ; offset < cb; offset += sizeof( byte ) ) + { + byte left8 = Marshal.ReadByte( left, offset ); + byte right8 = Marshal.ReadByte( right, offset ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static int LOWORD(int i) + if( left8 != right8 ) { - return (short)(i & 0xFFFF); + return false; } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public static bool AreStreamsEqual(Stream left, Stream right) - { - if (null == left) - { - return right == null; - } - if (null == right) - { - return false; - } + return true; + } - if (!left.CanRead || !right.CanRead) - { - throw new NotSupportedException("The streams can't be read for comparison"); - } + /// The native RGB macro. + /// + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static int RGB( Color c ) + { + return c.R | ( c.G << 8 ) | ( c.B << 16 ); + } - if (left.Length != right.Length) - { - return false; - } + /// Convert a native integer that represent a color with an alpha channel into a Color struct. + /// The integer that represents the color. Its bits are of the format 0xAARRGGBB. + /// A Color representation of the parameter. + public static Color ColorFromArgbDword( uint color ) + { + return Color.FromArgb( + ( byte )( ( color & 0xFF000000 ) >> 24 ), + ( byte )( ( color & 0x00FF0000 ) >> 16 ), + ( byte )( ( color & 0x0000FF00 ) >> 8 ), + ( byte )( ( color & 0x000000FF ) >> 0 ) ); + } - var length = (int)left.Length; - // seek to beginning - left.Position = 0; - right.Position = 0; + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static int GET_X_LPARAM( IntPtr lParam ) + { + return LOWORD( lParam.ToInt32() ); + } - // total bytes read - int totalReadLeft = 0; - int totalReadRight = 0; + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static int GET_Y_LPARAM( IntPtr lParam ) + { + return HIWORD( lParam.ToInt32() ); + } - // bytes read on this iteration - int cbReadLeft = 0; - int cbReadRight = 0; + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static int HIWORD( int i ) + { + return ( short )( i >> 16 ); + } - // where to store the read data - var leftBuffer = new byte[512]; - var rightBuffer = new byte[512]; + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static int LOWORD( int i ) + { + return ( short )( i & 0xFFFF ); + } - // pin the left buffer - GCHandle handleLeft = GCHandle.Alloc(leftBuffer, GCHandleType.Pinned); - IntPtr ptrLeft = handleLeft.AddrOfPinnedObject(); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public static bool AreStreamsEqual( Stream left, Stream right ) + { + if( null == left ) + { + return right == null; + } + if( null == right ) + { + return false; + } + + if( !left.CanRead || !right.CanRead ) + { + throw new NotSupportedException( "The streams can't be read for comparison" ); + } + + if( left.Length != right.Length ) + { + return false; + } + + var length = ( int )left.Length; + + // seek to beginning + left.Position = 0; + right.Position = 0; + + // total bytes read + int totalReadLeft = 0; + int totalReadRight = 0; + + // bytes read on this iteration + int cbReadLeft = 0; + int cbReadRight = 0; + + // where to store the read data + var leftBuffer = new byte[ 512 ]; + var rightBuffer = new byte[ 512 ]; + + // pin the left buffer + GCHandle handleLeft = GCHandle.Alloc( leftBuffer, GCHandleType.Pinned ); + IntPtr ptrLeft = handleLeft.AddrOfPinnedObject(); + + // pin the right buffer + GCHandle handleRight = GCHandle.Alloc( rightBuffer, GCHandleType.Pinned ); + IntPtr ptrRight = handleRight.AddrOfPinnedObject(); + + try + { + while( totalReadLeft < length ) + { + Assert.AreEqual( totalReadLeft, totalReadRight ); - // pin the right buffer - GCHandle handleRight = GCHandle.Alloc(rightBuffer, GCHandleType.Pinned); - IntPtr ptrRight = handleRight.AddrOfPinnedObject(); + cbReadLeft = left.Read( leftBuffer, 0, leftBuffer.Length ); + cbReadRight = right.Read( rightBuffer, 0, rightBuffer.Length ); - try - { - while (totalReadLeft < length) - { - Assert.AreEqual(totalReadLeft, totalReadRight); + // verify the contents are an exact match + if( cbReadLeft != cbReadRight ) + { + return false; + } - cbReadLeft = left.Read(leftBuffer, 0, leftBuffer.Length); - cbReadRight = right.Read(rightBuffer, 0, rightBuffer.Length); + if( !_MemCmp( ptrLeft, ptrRight, cbReadLeft ) ) + { + return false; + } - // verify the contents are an exact match - if (cbReadLeft != cbReadRight) - { - return false; - } + totalReadLeft += cbReadLeft; + totalReadRight += cbReadRight; + } - if (!_MemCmp(ptrLeft, ptrRight, cbReadLeft)) - { - return false; - } + Assert.AreEqual( cbReadLeft, cbReadRight ); + Assert.AreEqual( totalReadLeft, totalReadRight ); + Assert.AreEqual( length, totalReadLeft ); + + return true; + } + finally + { + handleLeft.Free(); + handleRight.Free(); + } + } - totalReadLeft += cbReadLeft; - totalReadRight += cbReadRight; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool GuidTryParse( string guidString, out Guid guid ) + { + Verify.IsNeitherNullNorEmpty( guidString, "guidString" ); + + try + { + guid = new Guid( guidString ); + return true; + } + catch( FormatException ) + { + } + catch( OverflowException ) + { + } + // Doesn't seem to be a valid guid. + guid = default( Guid ); + return false; + } - Assert.AreEqual(cbReadLeft, cbReadRight); - Assert.AreEqual(totalReadLeft, totalReadRight); - Assert.AreEqual(length, totalReadLeft); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsFlagSet( int value, int mask ) + { + return 0 != ( value & mask ); + } - return true; - } - finally - { - handleLeft.Free(); - handleRight.Free(); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsFlagSet( uint value, uint mask ) + { + return 0 != ( value & mask ); + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool GuidTryParse(string guidString, out Guid guid) - { - Verify.IsNeitherNullNorEmpty(guidString, "guidString"); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsFlagSet( long value, long mask ) + { + return 0 != ( value & mask ); + } - try - { - guid = new Guid(guidString); - return true; - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - // Doesn't seem to be a valid guid. - guid = default(Guid); - return false; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsFlagSet( ulong value, ulong mask ) + { + return 0 != ( value & mask ); + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool IsFlagSet(int value, int mask) - { - return 0 != (value & mask); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsOSVistaOrNewer + { + get + { + return _osVersion >= new Version( 6, 0 ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool IsFlagSet(uint value, uint mask) - { - return 0 != (value & mask); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsOSWindows7OrNewer + { + get + { + return _osVersion >= new Version( 6, 1 ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool IsFlagSet(long value, long mask) - { - return 0 != (value & mask); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool IsOSWindows8OrNewer + { + get + { + return _osVersion >= new Version( 6, 2 ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool IsFlagSet(ulong value, ulong mask) - { - return 0 != (value & mask); - } + /// + /// Is this using WPF4? + /// + /// + /// There are a few specific bugs in Window in 3.5SP1 and below that require workarounds + /// when handling WM_NCCALCSIZE on the HWND. + /// + public static bool IsPresentationFrameworkVersionLessThan4 + { + get + { + return _presentationFrameworkVersion < new Version( 4, 0 ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool IsOSVistaOrNewer + // Caller is responsible for destroying the HICON + // Caller is responsible to ensure that GDI+ has been initialized. + [SuppressMessage( "Microsoft.Usage", "CA2202:Do not dispose objects multiple times" )] + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static IntPtr GenerateHICON( ImageSource image, Size dimensions ) + { + if( image == null ) + { + return IntPtr.Zero; + } + + // If we're getting this from a ".ico" resource, then it comes through as a BitmapFrame. + // We can use leverage this as a shortcut to get the right 16x16 representation + // because DrawImage doesn't do that for us. + var bf = image as BitmapFrame; + if( bf != null ) + { + bf = GetBestMatch( bf.Decoder.Frames, ( int )dimensions.Width, ( int )dimensions.Height ); + } + else + { + // Constrain the dimensions based on the aspect ratio. + var drawingDimensions = new Rect( 0, 0, dimensions.Width, dimensions.Height ); + + // There's no reason to assume that the requested image dimensions are square. + double renderRatio = dimensions.Width / dimensions.Height; + double aspectRatio = image.Width / image.Height; + + // If it's smaller than the requested size, then place it in the middle and pad the image. + if( image.Width <= dimensions.Width && image.Height <= dimensions.Height ) { - get { return _osVersion >= new Version(6, 0); } + drawingDimensions = new Rect( ( dimensions.Width - image.Width ) / 2, ( dimensions.Height - image.Height ) / 2, image.Width, image.Height ); } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool IsOSWindows7OrNewer + else if( renderRatio > aspectRatio ) { - get { return _osVersion >= new Version(6, 1); } + double scaledRenderWidth = ( image.Width / image.Height ) * dimensions.Width; + drawingDimensions = new Rect( ( dimensions.Width - scaledRenderWidth ) / 2, 0, scaledRenderWidth, dimensions.Height ); } - - /// - /// Is this using WPF4? - /// - /// - /// There are a few specific bugs in Window in 3.5SP1 and below that require workarounds - /// when handling WM_NCCALCSIZE on the HWND. - /// - public static bool IsPresentationFrameworkVersionLessThan4 + else if( renderRatio < aspectRatio ) { - get { return _presentationFrameworkVersion < new Version(4, 0); } + double scaledRenderHeight = ( image.Height / image.Width ) * dimensions.Height; + drawingDimensions = new Rect( 0, ( dimensions.Height - scaledRenderHeight ) / 2, dimensions.Width, scaledRenderHeight ); } - // Caller is responsible for destroying the HICON - // Caller is responsible to ensure that GDI+ has been initialized. - [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static IntPtr GenerateHICON(ImageSource image, Size dimensions) + var dv = new DrawingVisual(); + DrawingContext dc = dv.RenderOpen(); + dc.DrawImage( image, drawingDimensions ); + dc.Close(); + + var bmp = new RenderTargetBitmap( ( int )dimensions.Width, ( int )dimensions.Height, 96, 96, PixelFormats.Pbgra32 ); + bmp.Render( dv ); + bf = BitmapFrame.Create( bmp ); + } + + // Using GDI+ to convert to an HICON. + // I'd rather not duplicate their code. + using( MemoryStream memstm = new MemoryStream() ) + { + BitmapEncoder enc = new PngBitmapEncoder(); + enc.Frames.Add( bf ); + enc.Save( memstm ); + + using( var istm = new ManagedIStream( memstm ) ) { - if (image == null) - { - return IntPtr.Zero; - } - - // If we're getting this from a ".ico" resource, then it comes through as a BitmapFrame. - // We can use leverage this as a shortcut to get the right 16x16 representation - // because DrawImage doesn't do that for us. - var bf = image as BitmapFrame; - if (bf != null) + // We are not bubbling out GDI+ errors when creating the native image fails. + IntPtr bitmap = IntPtr.Zero; + try + { + Status gpStatus = NativeMethods.GdipCreateBitmapFromStream( istm, out bitmap ); + if( Status.Ok != gpStatus ) { - bf = GetBestMatch(bf.Decoder.Frames, (int)dimensions.Width, (int)dimensions.Height); - } - else - { - // Constrain the dimensions based on the aspect ratio. - var drawingDimensions = new Rect(0, 0, dimensions.Width, dimensions.Height); - - // There's no reason to assume that the requested image dimensions are square. - double renderRatio = dimensions.Width / dimensions.Height; - double aspectRatio = image.Width / image.Height; - - // If it's smaller than the requested size, then place it in the middle and pad the image. - if (image.Width <= dimensions.Width && image.Height <= dimensions.Height) - { - drawingDimensions = new Rect((dimensions.Width - image.Width) / 2, (dimensions.Height - image.Height) / 2, image.Width, image.Height); - } - else if (renderRatio > aspectRatio) - { - double scaledRenderWidth = (image.Width / image.Height) * dimensions.Width; - drawingDimensions = new Rect((dimensions.Width - scaledRenderWidth) / 2, 0, scaledRenderWidth, dimensions.Height); - } - else if (renderRatio < aspectRatio) - { - double scaledRenderHeight = (image.Height / image.Width) * dimensions.Height; - drawingDimensions = new Rect(0, (dimensions.Height - scaledRenderHeight) / 2, dimensions.Width, scaledRenderHeight); - } - - var dv = new DrawingVisual(); - DrawingContext dc = dv.RenderOpen(); - dc.DrawImage(image, drawingDimensions); - dc.Close(); - - var bmp = new RenderTargetBitmap((int)dimensions.Width, (int)dimensions.Height, 96, 96, PixelFormats.Pbgra32); - bmp.Render(dv); - bf = BitmapFrame.Create(bmp); + return IntPtr.Zero; } - // Using GDI+ to convert to an HICON. - // I'd rather not duplicate their code. - using (MemoryStream memstm = new MemoryStream()) + IntPtr hicon; + gpStatus = NativeMethods.GdipCreateHICONFromBitmap( bitmap, out hicon ); + if( Status.Ok != gpStatus ) { - BitmapEncoder enc = new PngBitmapEncoder(); - enc.Frames.Add(bf); - enc.Save(memstm); - - using (var istm = new ManagedIStream(memstm)) - { - // We are not bubbling out GDI+ errors when creating the native image fails. - IntPtr bitmap = IntPtr.Zero; - try - { - Status gpStatus = NativeMethods.GdipCreateBitmapFromStream(istm, out bitmap); - if (Status.Ok != gpStatus) - { - return IntPtr.Zero; - } - - IntPtr hicon; - gpStatus = NativeMethods.GdipCreateHICONFromBitmap(bitmap, out hicon); - if (Status.Ok != gpStatus) - { - return IntPtr.Zero; - } - - // Caller is responsible for freeing this. - return hicon; - } - finally - { - Utility.SafeDisposeImage(ref bitmap); - } - } + return IntPtr.Zero; } - } - public static BitmapFrame GetBestMatch(IList frames, int width, int height) - { - return _GetBestMatch(frames, _GetBitDepth(), width, height); + // Caller is responsible for freeing this. + return hicon; + } + finally + { + Utility.SafeDisposeImage( ref bitmap ); + } } + } + } - private static int _MatchImage(BitmapFrame frame, int bitDepth, int width, int height, int bpp) - { - int score = 2 * _WeightedAbs(bpp, bitDepth, false) + - _WeightedAbs(frame.PixelWidth, width, true) + - _WeightedAbs(frame.PixelHeight, height, true); + public static BitmapFrame GetBestMatch( IList frames, int width, int height ) + { + return _GetBestMatch( frames, _GetBitDepth(), width, height ); + } - return score; - } + private static int _MatchImage( BitmapFrame frame, int bitDepth, int width, int height, int bpp ) + { + int score = 2 * _WeightedAbs( bpp, bitDepth, false ) + + _WeightedAbs( frame.PixelWidth, width, true ) + + _WeightedAbs( frame.PixelHeight, height, true ); - private static int _WeightedAbs(int valueHave, int valueWant, bool fPunish) - { - int diff = (valueHave - valueWant); + return score; + } - if (diff < 0) - { - diff = (fPunish ? -2 : -1) * diff; - } + private static int _WeightedAbs( int valueHave, int valueWant, bool fPunish ) + { + int diff = ( valueHave - valueWant ); - return diff; - } + if( diff < 0 ) + { + diff = ( fPunish ? -2 : -1 ) * diff; + } - /// From a list of BitmapFrames find the one that best matches the requested dimensions. - /// The methods used here are copied from Win32 sources. We want to be consistent with - /// system behaviors. - private static BitmapFrame _GetBestMatch(IList frames, int bitDepth, int width, int height) - { - int bestScore = int.MaxValue; - int bestBpp = 0; - int bestIndex = 0; + return diff; + } - bool isBitmapIconDecoder = frames[0].Decoder is IconBitmapDecoder; + /// From a list of BitmapFrames find the one that best matches the requested dimensions. + /// The methods used here are copied from Win32 sources. We want to be consistent with + /// system behaviors. + private static BitmapFrame _GetBestMatch( IList frames, int bitDepth, int width, int height ) + { + int bestScore = int.MaxValue; + int bestBpp = 0; + int bestIndex = 0; - for (int i = 0; i < frames.Count && bestScore != 0; ++i) - { - int currentIconBitDepth = isBitmapIconDecoder ? frames[i].Thumbnail.Format.BitsPerPixel : frames[i].Format.BitsPerPixel; - - if (currentIconBitDepth == 0) - { - currentIconBitDepth = 8; - } - - int score = _MatchImage(frames[i], bitDepth, width, height, currentIconBitDepth); - if (score < bestScore) - { - bestIndex = i; - bestBpp = currentIconBitDepth; - bestScore = score; - } - else if (score == bestScore) - { - // Tie breaker: choose the higher color depth. If that fails, choose first one. - if (bestBpp < currentIconBitDepth) - { - bestIndex = i; - bestBpp = currentIconBitDepth; - } - } - } + bool isBitmapIconDecoder = frames[ 0 ].Decoder is IconBitmapDecoder; - return frames[bestIndex]; - } + for( int i = 0; i < frames.Count && bestScore != 0; ++i ) + { + int currentIconBitDepth = isBitmapIconDecoder ? frames[ i ].Thumbnail.Format.BitsPerPixel : frames[ i ].Format.BitsPerPixel; - // This can be cached. It's not going to change under reasonable circumstances. - private static int s_bitDepth; // = 0; - private static int _GetBitDepth() + if( currentIconBitDepth == 0 ) { - if (s_bitDepth == 0) - { - using (SafeDC dc = SafeDC.GetDesktop()) - { - s_bitDepth = NativeMethods.GetDeviceCaps(dc, DeviceCap.BITSPIXEL) * NativeMethods.GetDeviceCaps(dc, DeviceCap.PLANES); - } - } - return s_bitDepth; + currentIconBitDepth = 8; } - /// - /// Simple guard against the exceptions that File.Delete throws on null and empty strings. - /// - /// The path to delete. Unlike File.Delete, this can be null or empty. - /// - /// Note that File.Delete, and by extension SafeDeleteFile, does not throw an exception - /// if the file does not exist. - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SafeDeleteFile(string path) + int score = _MatchImage( frames[ i ], bitDepth, width, height, currentIconBitDepth ); + if( score < bestScore ) { - if (!string.IsNullOrEmpty(path)) - { - - File.Delete(path); - } + bestIndex = i; + bestBpp = currentIconBitDepth; + bestScore = score; } - - /// GDI's DeleteObject - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SafeDeleteObject(ref IntPtr gdiObject) + else if( score == bestScore ) { - IntPtr p = gdiObject; - gdiObject = IntPtr.Zero; - if (IntPtr.Zero != p) - { - NativeMethods.DeleteObject(p); - } + // Tie breaker: choose the higher color depth. If that fails, choose first one. + if( bestBpp < currentIconBitDepth ) + { + bestIndex = i; + bestBpp = currentIconBitDepth; + } } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SafeDestroyIcon(ref IntPtr hicon) - { - IntPtr p = hicon; - hicon = IntPtr.Zero; - if (IntPtr.Zero != p) - { - NativeMethods.DestroyIcon(p); - } - } + return frames[ bestIndex ]; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SafeDestroyWindow(ref IntPtr hwnd) + // This can be cached. It's not going to change under reasonable circumstances. + private static int s_bitDepth; // = 0; + private static int _GetBitDepth() + { + if( s_bitDepth == 0 ) + { + using( SafeDC dc = SafeDC.GetDesktop() ) { - IntPtr p = hwnd; - hwnd = IntPtr.Zero; - if (NativeMethods.IsWindow(p)) - { - NativeMethods.DestroyWindow(p); - } + s_bitDepth = NativeMethods.GetDeviceCaps( dc, DeviceCap.BITSPIXEL ) * NativeMethods.GetDeviceCaps( dc, DeviceCap.PLANES ); } + } + return s_bitDepth; + } + /// + /// Simple guard against the exceptions that File.Delete throws on null and empty strings. + /// + /// The path to delete. Unlike File.Delete, this can be null or empty. + /// + /// Note that File.Delete, and by extension SafeDeleteFile, does not throw an exception + /// if the file does not exist. + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SafeDeleteFile( string path ) + { + if( !string.IsNullOrEmpty( path ) ) + { - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SafeDispose(ref T disposable) where T : IDisposable - { - // Dispose can safely be called on an object multiple times. - IDisposable t = disposable; - disposable = default(T); - if (null != t) - { - t.Dispose(); - } - } - - /// GDI+'s DisposeImage - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void SafeDisposeImage(ref IntPtr gdipImage) - { - IntPtr p = gdipImage; - gdipImage = IntPtr.Zero; - if (IntPtr.Zero != p) - { - NativeMethods.GdipDisposeImage(p); - } - } + File.Delete( path ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public static void SafeCoTaskMemFree(ref IntPtr ptr) - { - IntPtr p = ptr; - ptr = IntPtr.Zero; - if (IntPtr.Zero != p) - { - Marshal.FreeCoTaskMem(p); - } - } + /// GDI's DeleteObject + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SafeDeleteObject( ref IntPtr gdiObject ) + { + IntPtr p = gdiObject; + gdiObject = IntPtr.Zero; + if( IntPtr.Zero != p ) + { + NativeMethods.DeleteObject( p ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public static void SafeFreeHGlobal(ref IntPtr hglobal) - { - IntPtr p = hglobal; - hglobal = IntPtr.Zero; - if (IntPtr.Zero != p) - { - Marshal.FreeHGlobal(p); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SafeDestroyIcon( ref IntPtr hicon ) + { + IntPtr p = hicon; + hicon = IntPtr.Zero; + if( IntPtr.Zero != p ) + { + NativeMethods.DestroyIcon( p ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - public static void SafeRelease(ref T comObject) where T : class - { - T t = comObject; - comObject = default(T); - if (null != t) - { - Assert.IsTrue(Marshal.IsComObject(t)); - Marshal.ReleaseComObject(t); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SafeDestroyWindow( ref IntPtr hwnd ) + { + IntPtr p = hwnd; + hwnd = IntPtr.Zero; + if( NativeMethods.IsWindow( p ) ) + { + NativeMethods.DestroyWindow( p ); + } + } - /// - /// Utility to help classes catenate their properties for implementing ToString(). - /// - /// The StringBuilder to catenate the results into. - /// The name of the property to be catenated. - /// The value of the property to be catenated. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void GeneratePropertyString(StringBuilder source, string propertyName, string value) - { - Assert.IsNotNull(source); - Assert.IsFalse(string.IsNullOrEmpty(propertyName)); - if (0 != source.Length) - { - source.Append(' '); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SafeDispose( ref T disposable ) where T : IDisposable + { + // Dispose can safely be called on an object multiple times. + IDisposable t = disposable; + disposable = default( T ); + if( null != t ) + { + t.Dispose(); + } + } - source.Append(propertyName); - source.Append(": "); - if (string.IsNullOrEmpty(value)) - { - source.Append(""); - } - else - { - source.Append('\"'); - source.Append(value); - source.Append('\"'); - } - } + /// GDI+'s DisposeImage + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void SafeDisposeImage( ref IntPtr gdipImage ) + { + IntPtr p = gdipImage; + gdipImage = IntPtr.Zero; + if( IntPtr.Zero != p ) + { + NativeMethods.GdipDisposeImage( p ); + } + } - /// - /// Generates ToString functionality for a struct. This is an expensive way to do it, - /// it exists for the sake of debugging while classes are in flux. - /// Eventually this should just be removed and the classes should - /// do this without reflection. - /// - /// - /// - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [Obsolete] - public static string GenerateToString(T @object) where T : struct - { - var sbRet = new StringBuilder(); - foreach (PropertyInfo property in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)) - { - if (0 != sbRet.Length) - { - sbRet.Append(", "); - } - Assert.AreEqual(0, property.GetIndexParameters().Length); - object value = property.GetValue(@object, null); - string format = null == value ? "{0}: " : "{0}: \"{1}\""; - sbRet.AppendFormat(format, property.Name, value); - } - return sbRet.ToString(); - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public static void SafeCoTaskMemFree( ref IntPtr ptr ) + { + IntPtr p = ptr; + ptr = IntPtr.Zero; + if( IntPtr.Zero != p ) + { + Marshal.FreeCoTaskMem( p ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void CopyStream(Stream destination, Stream source) - { - Assert.IsNotNull(source); - Assert.IsNotNull(destination); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public static void SafeFreeHGlobal( ref IntPtr hglobal ) + { + IntPtr p = hglobal; + hglobal = IntPtr.Zero; + if( IntPtr.Zero != p ) + { + Marshal.FreeHGlobal( p ); + } + } - destination.Position = 0; + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + public static void SafeRelease( ref T comObject ) where T : class + { + T t = comObject; + comObject = default( T ); + if( null != t ) + { + Assert.IsTrue( Marshal.IsComObject( t ) ); + Marshal.ReleaseComObject( t ); + } + } - // If we're copying from, say, a web stream, don't fail because of this. - if (source.CanSeek) - { - source.Position = 0; + /// + /// Utility to help classes catenate their properties for implementing ToString(). + /// + /// The StringBuilder to catenate the results into. + /// The name of the property to be catenated. + /// The value of the property to be catenated. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void GeneratePropertyString( StringBuilder source, string propertyName, string value ) + { + Assert.IsNotNull( source ); + Assert.IsFalse( string.IsNullOrEmpty( propertyName ) ); + + if( 0 != source.Length ) + { + source.Append( ' ' ); + } + + source.Append( propertyName ); + source.Append( ": " ); + if( string.IsNullOrEmpty( value ) ) + { + source.Append( "" ); + } + else + { + source.Append( '\"' ); + source.Append( value ); + source.Append( '\"' ); + } + } - // Consider that this could throw because - // the source stream doesn't know it's size... - destination.SetLength(source.Length); - } + /// + /// Generates ToString functionality for a struct. This is an expensive way to do it, + /// it exists for the sake of debugging while classes are in flux. + /// Eventually this should just be removed and the classes should + /// do this without reflection. + /// + /// + /// + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [Obsolete] + public static string GenerateToString( T @object ) where T : struct + { + var sbRet = new StringBuilder(); + foreach( PropertyInfo property in typeof( T ).GetProperties( BindingFlags.Public | BindingFlags.Instance ) ) + { + if( 0 != sbRet.Length ) + { + sbRet.Append( ", " ); + } + Assert.AreEqual( 0, property.GetIndexParameters().Length ); + object value = property.GetValue( @object, null ); + string format = null == value ? "{0}: " : "{0}: \"{1}\""; + sbRet.AppendFormat( format, property.Name, value ); + } + return sbRet.ToString(); + } - var buffer = new byte[4096]; - int cbRead; + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void CopyStream( Stream destination, Stream source ) + { + Assert.IsNotNull( source ); + Assert.IsNotNull( destination ); - do - { - cbRead = source.Read(buffer, 0, buffer.Length); - if (0 != cbRead) - { - destination.Write(buffer, 0, cbRead); - } - } - while (buffer.Length == cbRead); + destination.Position = 0; - // Reset the Seek pointer before returning. - destination.Position = 0; - } + // If we're copying from, say, a web stream, don't fail because of this. + if( source.CanSeek ) + { + source.Position = 0; - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static string HashStreamMD5(Stream stm) - { - stm.Position = 0; - var hashBuilder = new StringBuilder(); - using (MD5 md5 = MD5.Create()) - { - foreach (byte b in md5.ComputeHash(stm)) - { - hashBuilder.Append(b.ToString("x2", CultureInfo.InvariantCulture)); - } - } + // Consider that this could throw because + // the source stream doesn't know it's size... + destination.SetLength( source.Length ); + } - return hashBuilder.ToString(); - } + var buffer = new byte[ 4096 ]; + int cbRead; - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static void EnsureDirectory(string path) + do + { + cbRead = source.Read( buffer, 0, buffer.Length ); + if( 0 != cbRead ) { - if (!Directory.Exists(Path.GetDirectoryName(path))) - { - Directory.CreateDirectory(Path.GetDirectoryName(path)); - } + destination.Write( buffer, 0, cbRead ); } + } + while( buffer.Length == cbRead ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static bool MemCmp(byte[] left, byte[] right, int cb) - { - Assert.IsNotNull(left); - Assert.IsNotNull(right); + // Reset the Seek pointer before returning. + destination.Position = 0; + } - Assert.IsTrue(cb <= Math.Min(left.Length, right.Length)); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static string HashStreamMD5( Stream stm ) + { + stm.Position = 0; + var hashBuilder = new StringBuilder(); + using( MD5 md5 = MD5.Create() ) + { + foreach( byte b in md5.ComputeHash( stm ) ) + { + hashBuilder.Append( b.ToString( "x2", CultureInfo.InvariantCulture ) ); + } + } - // pin this buffer - GCHandle handleLeft = GCHandle.Alloc(left, GCHandleType.Pinned); - IntPtr ptrLeft = handleLeft.AddrOfPinnedObject(); + return hashBuilder.ToString(); + } - // pin the other buffer - GCHandle handleRight = GCHandle.Alloc(right, GCHandleType.Pinned); - IntPtr ptrRight = handleRight.AddrOfPinnedObject(); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static void EnsureDirectory( string path ) + { + if( !Directory.Exists( Path.GetDirectoryName( path ) ) ) + { + Directory.CreateDirectory( Path.GetDirectoryName( path ) ); + } + } - bool fRet = _MemCmp(ptrLeft, ptrRight, cb); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static bool MemCmp( byte[] left, byte[] right, int cb ) + { + Assert.IsNotNull( left ); + Assert.IsNotNull( right ); - handleLeft.Free(); - handleRight.Free(); + Assert.IsTrue( cb <= Math.Min( left.Length, right.Length ) ); - return fRet; - } + // pin this buffer + GCHandle handleLeft = GCHandle.Alloc( left, GCHandleType.Pinned ); + IntPtr ptrLeft = handleLeft.AddrOfPinnedObject(); - private class _UrlDecoder - { - private readonly Encoding _encoding; - private readonly char[] _charBuffer; - private readonly byte[] _byteBuffer; - private int _byteCount; - private int _charCount; - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public _UrlDecoder(int size, Encoding encoding) - { - _encoding = encoding; - _charBuffer = new char[size]; - _byteBuffer = new byte[size]; - } + // pin the other buffer + GCHandle handleRight = GCHandle.Alloc( right, GCHandleType.Pinned ); + IntPtr ptrRight = handleRight.AddrOfPinnedObject(); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public void AddByte(byte b) - { - _byteBuffer[_byteCount++] = b; - } + bool fRet = _MemCmp( ptrLeft, ptrRight, cb ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public void AddChar(char ch) - { - _FlushBytes(); - _charBuffer[_charCount++] = ch; - } + handleLeft.Free(); + handleRight.Free(); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private void _FlushBytes() - { - if (_byteCount > 0) - { - _charCount += _encoding.GetChars(_byteBuffer, 0, _byteCount, _charBuffer, _charCount); - _byteCount = 0; - } - } + return fRet; + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public string GetString() - { - _FlushBytes(); - if (_charCount > 0) - { - return new string(_charBuffer, 0, _charCount); - } - return ""; - } + private class _UrlDecoder + { + private readonly Encoding _encoding; + private readonly char[] _charBuffer; + private readonly byte[] _byteBuffer; + private int _byteCount; + private int _charCount; + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public _UrlDecoder( int size, Encoding encoding ) + { + _encoding = encoding; + _charBuffer = new char[ size ]; + _byteBuffer = new byte[ size ]; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public void AddByte( byte b ) + { + _byteBuffer[ _byteCount++ ] = b; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public void AddChar( char ch ) + { + _FlushBytes(); + _charBuffer[ _charCount++ ] = ch; + } + + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + private void _FlushBytes() + { + if( _byteCount > 0 ) + { + _charCount += _encoding.GetChars( _byteBuffer, 0, _byteCount, _charBuffer, _charCount ); + _byteCount = 0; } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static string UrlDecode(string url) + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public string GetString() + { + _FlushBytes(); + if( _charCount > 0 ) { - if (url == null) - { - return null; - } - - var decoder = new _UrlDecoder(url.Length, Encoding.UTF8); - int length = url.Length; - for (int i = 0; i < length; ++i) - { - char ch = url[i]; - - if (ch == '+') - { - decoder.AddByte((byte)' '); - continue; - } - - if (ch == '%' && i < length - 2) - { - // decode %uXXXX into a Unicode character. - if (url[i + 1] == 'u' && i < length - 5) - { - int a = _HexToInt(url[i + 2]); - int b = _HexToInt(url[i + 3]); - int c = _HexToInt(url[i + 4]); - int d = _HexToInt(url[i + 5]); - if (a >= 0 && b >= 0 && c >= 0 && d >= 0) - { - decoder.AddChar((char)((a << 12) | (b << 8) | (c << 4) | d)); - i += 5; - - continue; - } - } - else - { - // decode %XX into a Unicode character. - int a = _HexToInt(url[i + 1]); - int b = _HexToInt(url[i + 2]); - - if (a >= 0 && b >= 0) - { - decoder.AddByte((byte)((a << 4) | b)); - i += 2; - - continue; - } - } - } - - // Add any 7bit character as a byte. - if ((ch & 0xFF80) == 0) - { - decoder.AddByte((byte)ch); - } - else - { - decoder.AddChar(ch); - } - } - - return decoder.GetString(); + return new string( _charBuffer, 0, _charCount ); } + return ""; + } + } - /// - /// Encodes a URL string. Duplicated functionality from System.Web.HttpUtility.UrlEncode. - /// - /// - /// - /// - /// Duplicated from System.Web.HttpUtility because System.Web isn't part of the client profile. - /// URL Encoding replaces ' ' with '+' and unsafe ASCII characters with '%XX'. - /// Safe characters are defined in RFC2396 (http://www.ietf.org/rfc/rfc2396.txt). - /// They are the 7-bit ASCII alphanumerics and the mark characters "-_.!~*'()". - /// This implementation does not treat '~' as a safe character to be consistent with the System.Web version. - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static string UrlEncode(string url) + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static string UrlDecode( string url ) + { + if( url == null ) + { + return null; + } + + var decoder = new _UrlDecoder( url.Length, Encoding.UTF8 ); + int length = url.Length; + for( int i = 0; i < length; ++i ) + { + char ch = url[ i ]; + + if( ch == '+' ) { - if (url == null) - { - return null; - } - - byte[] bytes = Encoding.UTF8.GetBytes(url); - - bool needsEncoding = false; - int unsafeCharCount = 0; - foreach (byte b in bytes) - { - if (b == ' ') - { - needsEncoding = true; - } - else if (!_UrlEncodeIsSafe(b)) - { - ++unsafeCharCount; - needsEncoding = true; - } - } - - if (needsEncoding) - { - var buffer = new byte[bytes.Length + (unsafeCharCount * 2)]; - int writeIndex = 0; - foreach (byte b in bytes) - { - if (_UrlEncodeIsSafe(b)) - { - buffer[writeIndex++] = b; - } - else if (b == ' ') - { - buffer[writeIndex++] = (byte)'+'; - } - else - { - buffer[writeIndex++] = (byte)'%'; - buffer[writeIndex++] = _IntToHex((b >> 4) & 0xF); - buffer[writeIndex++] = _IntToHex(b & 0xF); - } - } - bytes = buffer; - Assert.AreEqual(buffer.Length, writeIndex); - } - - return Encoding.ASCII.GetString(bytes); + decoder.AddByte( ( byte )' ' ); + continue; } - // HttpUtility's UrlEncode is slightly different from the RFC. - // RFC2396 describes unreserved characters as alphanumeric or - // the list "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" - // The System.Web version unnecessarily escapes '~', which should be okay... - // Keeping that same pattern here just to be consistent. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private static bool _UrlEncodeIsSafe(byte b) + if( ch == '%' && i < length - 2 ) { - if (_IsAsciiAlphaNumeric(b)) + // decode %uXXXX into a Unicode character. + if( url[ i + 1 ] == 'u' && i < length - 5 ) + { + int a = _HexToInt( url[ i + 2 ] ); + int b = _HexToInt( url[ i + 3 ] ); + int c = _HexToInt( url[ i + 4 ] ); + int d = _HexToInt( url[ i + 5 ] ); + if( a >= 0 && b >= 0 && c >= 0 && d >= 0 ) { - return true; - } + decoder.AddChar( ( char )( ( a << 12 ) | ( b << 8 ) | ( c << 4 ) | d ) ); + i += 5; - switch ((char)b) - { - case '-': - case '_': - case '.': - case '!': - //case '~': - case '*': - case '\'': - case '(': - case ')': - return true; + continue; } + } + else + { + // decode %XX into a Unicode character. + int a = _HexToInt( url[ i + 1 ] ); + int b = _HexToInt( url[ i + 2 ] ); + + if( a >= 0 && b >= 0 ) + { + decoder.AddByte( ( byte )( ( a << 4 ) | b ) ); + i += 2; - return false; + continue; + } + } } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private static bool _IsAsciiAlphaNumeric(byte b) + // Add any 7bit character as a byte. + if( ( ch & 0xFF80 ) == 0 ) { - return (b >= 'a' && b <= 'z') - || (b >= 'A' && b <= 'Z') - || (b >= '0' && b <= '9'); + decoder.AddByte( ( byte )ch ); } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private static byte _IntToHex(int n) + else { - Assert.BoundedInteger(0, n, 16); - if (n <= 9) - { - return (byte)(n + '0'); - } - return (byte)(n - 10 + 'A'); + decoder.AddChar( ch ); } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private static int _HexToInt(char h) - { - if (h >= '0' && h <= '9') - { - return h - '0'; - } - - if (h >= 'a' && h <= 'f') - { - return h - 'a' + 10; - } - - if (h >= 'A' && h <= 'F') - { - return h - 'A' + 10; - } - - Assert.Fail("Invalid hex character " + h); - return -1; - } + return decoder.GetString(); + } - public static void AddDependencyPropertyChangeListener(object component, DependencyProperty property, EventHandler listener) + /// + /// Encodes a URL string. Duplicated functionality from System.Web.HttpUtility.UrlEncode. + /// + /// + /// + /// + /// Duplicated from System.Web.HttpUtility because System.Web isn't part of the client profile. + /// URL Encoding replaces ' ' with '+' and unsafe ASCII characters with '%XX'. + /// Safe characters are defined in RFC2396 (http://www.ietf.org/rfc/rfc2396.txt). + /// They are the 7-bit ASCII alphanumerics and the mark characters "-_.!~*'()". + /// This implementation does not treat '~' as a safe character to be consistent with the System.Web version. + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + public static string UrlEncode( string url ) + { + if( url == null ) + { + return null; + } + + byte[] bytes = Encoding.UTF8.GetBytes( url ); + + bool needsEncoding = false; + int unsafeCharCount = 0; + foreach( byte b in bytes ) + { + if( b == ' ' ) { - if (component == null) - { - return; - } - Assert.IsNotNull(property); - Assert.IsNotNull(listener); - - DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(property, component.GetType()); - dpd.AddValueChanged(component, listener); + needsEncoding = true; } - - public static void RemoveDependencyPropertyChangeListener(object component, DependencyProperty property, EventHandler listener) + else if( !_UrlEncodeIsSafe( b ) ) { - if (component == null) - { - return; - } - Assert.IsNotNull(property); - Assert.IsNotNull(listener); - - DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(property, component.GetType()); - dpd.RemoveValueChanged(component, listener); + ++unsafeCharCount; + needsEncoding = true; } + } - #region Extension Methods - - public static bool IsThicknessNonNegative(Thickness thickness) + if( needsEncoding ) + { + var buffer = new byte[ bytes.Length + ( unsafeCharCount * 2 ) ]; + int writeIndex = 0; + foreach( byte b in bytes ) { - if (!IsDoubleFiniteAndNonNegative(thickness.Top)) - { - return false; - } + if( _UrlEncodeIsSafe( b ) ) + { + buffer[ writeIndex++ ] = b; + } + else if( b == ' ' ) + { + buffer[ writeIndex++ ] = ( byte )'+'; + } + else + { + buffer[ writeIndex++ ] = ( byte )'%'; + buffer[ writeIndex++ ] = _IntToHex( ( b >> 4 ) & 0xF ); + buffer[ writeIndex++ ] = _IntToHex( b & 0xF ); + } + } + bytes = buffer; + Assert.AreEqual( buffer.Length, writeIndex ); + } - if (!IsDoubleFiniteAndNonNegative(thickness.Left)) - { - return false; - } + return Encoding.ASCII.GetString( bytes ); + } - if (!IsDoubleFiniteAndNonNegative(thickness.Bottom)) - { - return false; - } + // HttpUtility's UrlEncode is slightly different from the RFC. + // RFC2396 describes unreserved characters as alphanumeric or + // the list "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" + // The System.Web version unnecessarily escapes '~', which should be okay... + // Keeping that same pattern here just to be consistent. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + private static bool _UrlEncodeIsSafe( byte b ) + { + if( _IsAsciiAlphaNumeric( b ) ) + { + return true; + } + + switch( ( char )b ) + { + case '-': + case '_': + case '.': + case '!': + //case '~': + case '*': + case '\'': + case '(': + case ')': + return true; + } + + return false; + } - if (!IsDoubleFiniteAndNonNegative(thickness.Right)) - { - return false; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + private static bool _IsAsciiAlphaNumeric( byte b ) + { + return ( b >= 'a' && b <= 'z' ) + || ( b >= 'A' && b <= 'Z' ) + || ( b >= '0' && b <= '9' ); + } - return true; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + private static byte _IntToHex( int n ) + { + Assert.BoundedInteger( 0, n, 16 ); + if( n <= 9 ) + { + return ( byte )( n + '0' ); + } + return ( byte )( n - 10 + 'A' ); + } - public static bool IsCornerRadiusValid(CornerRadius cornerRadius) - { - if (!IsDoubleFiniteAndNonNegative(cornerRadius.TopLeft)) - { - return false; - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + private static int _HexToInt( char h ) + { + if( h >= '0' && h <= '9' ) + { + return h - '0'; + } + + if( h >= 'a' && h <= 'f' ) + { + return h - 'a' + 10; + } + + if( h >= 'A' && h <= 'F' ) + { + return h - 'A' + 10; + } + + Assert.Fail( "Invalid hex character " + h ); + return -1; + } - if (!IsDoubleFiniteAndNonNegative(cornerRadius.TopRight)) - { - return false; - } + public static void AddDependencyPropertyChangeListener( object component, DependencyProperty property, EventHandler listener ) + { + if( component == null ) + { + return; + } + Assert.IsNotNull( property ); + Assert.IsNotNull( listener ); + + DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty( property, component.GetType() ); + dpd.AddValueChanged( component, listener ); + } - if (!IsDoubleFiniteAndNonNegative(cornerRadius.BottomLeft)) - { - return false; - } + public static void RemoveDependencyPropertyChangeListener( object component, DependencyProperty property, EventHandler listener ) + { + if( component == null ) + { + return; + } + Assert.IsNotNull( property ); + Assert.IsNotNull( listener ); + + DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty( property, component.GetType() ); + dpd.RemoveValueChanged( component, listener ); + } - if (!IsDoubleFiniteAndNonNegative(cornerRadius.BottomRight)) - { - return false; - } + #region Extension Methods - return true; - } + public static bool IsThicknessNonNegative( Thickness thickness ) + { + if( !IsDoubleFiniteAndNonNegative( thickness.Top ) ) + { + return false; + } + + if( !IsDoubleFiniteAndNonNegative( thickness.Left ) ) + { + return false; + } + + if( !IsDoubleFiniteAndNonNegative( thickness.Bottom ) ) + { + return false; + } + + if( !IsDoubleFiniteAndNonNegative( thickness.Right ) ) + { + return false; + } + + return true; + } - public static bool IsDoubleFiniteAndNonNegative(double d) - { - if (double.IsNaN(d) || double.IsInfinity(d) || d < 0) - { - return false; - } + public static bool IsCornerRadiusValid( CornerRadius cornerRadius ) + { + if( !IsDoubleFiniteAndNonNegative( cornerRadius.TopLeft ) ) + { + return false; + } + + if( !IsDoubleFiniteAndNonNegative( cornerRadius.TopRight ) ) + { + return false; + } + + if( !IsDoubleFiniteAndNonNegative( cornerRadius.BottomLeft ) ) + { + return false; + } + + if( !IsDoubleFiniteAndNonNegative( cornerRadius.BottomRight ) ) + { + return false; + } + + return true; + } - return true; - } + public static bool IsDoubleFiniteAndNonNegative( double d ) + { + if( double.IsNaN( d ) || double.IsInfinity( d ) || d < 0 ) + { + return false; + } - #endregion + return true; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Verify.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Verify.cs index ea8f3bcc..1d13f3d9 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Verify.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Verify.cs @@ -25,304 +25,304 @@ // might be included in multiple assemblies. namespace Standard { - using System; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.IO; - using System.Threading; + using System; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.IO; + using System.Threading; + /// + /// A static class for retail validated assertions. + /// Instead of breaking into the debugger an exception is thrown. + /// + internal static class Verify + { /// - /// A static class for retail validated assertions. - /// Instead of breaking into the debugger an exception is thrown. + /// Ensure that the current thread's apartment state is what's expected. /// - internal static class Verify + /// + /// The required apartment state for the current thread. + /// + /// + /// The message string for the exception to be thrown if the state is invalid. + /// + /// + /// Thrown if the calling thread's apartment state is not the same as the requiredState. + /// + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void IsApartmentState( ApartmentState requiredState, string message ) { - /// - /// Ensure that the current thread's apartment state is what's expected. - /// - /// - /// The required apartment state for the current thread. - /// - /// - /// The message string for the exception to be thrown if the state is invalid. - /// - /// - /// Thrown if the calling thread's apartment state is not the same as the requiredState. - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void IsApartmentState(ApartmentState requiredState, string message) - { - if (Thread.CurrentThread.GetApartmentState() != requiredState) - { - throw new InvalidOperationException(message); - } - } - - /// - /// Ensure that an argument is neither null nor empty. - /// - /// The string to validate. - /// The name of the parameter that will be presented if an exception is thrown. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [SuppressMessage("Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength")] - [DebuggerStepThrough] - public static void IsNeitherNullNorEmpty(string value, string name) - { - // catch caller errors, mixing up the parameters. Name should never be empty. - Assert.IsNeitherNullNorEmpty(name); + if( Thread.CurrentThread.GetApartmentState() != requiredState ) + { + throw new InvalidOperationException( message ); + } + } - // Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P - const string errorMessage = "The parameter can not be either null or empty."; - if (null == value) - { - throw new ArgumentNullException(name, errorMessage); - } - if ("" == value) - { - throw new ArgumentException(errorMessage, name); - } - } + /// + /// Ensure that an argument is neither null nor empty. + /// + /// The string to validate. + /// The name of the parameter that will be presented if an exception is thrown. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [SuppressMessage( "Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength" )] + [DebuggerStepThrough] + public static void IsNeitherNullNorEmpty( string value, string name ) + { + // catch caller errors, mixing up the parameters. Name should never be empty. + Assert.IsNeitherNullNorEmpty( name ); - /// - /// Ensure that an argument is neither null nor does it consist only of whitespace. - /// - /// The string to validate. - /// The name of the parameter that will be presented if an exception is thrown. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [SuppressMessage("Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength")] - [DebuggerStepThrough] - public static void IsNeitherNullNorWhitespace(string value, string name) - { - // catch caller errors, mixing up the parameters. Name should never be empty. - Assert.IsNeitherNullNorEmpty(name); + // Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P + const string errorMessage = "The parameter can not be either null or empty."; + if( null == value ) + { + throw new ArgumentNullException( name, errorMessage ); + } + if( "" == value ) + { + throw new ArgumentException( errorMessage, name ); + } + } - // Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P - const string errorMessage = "The parameter can not be either null or empty or consist only of white space characters."; - if (null == value) - { - throw new ArgumentNullException(name, errorMessage); - } - if ("" == value.Trim()) - { - throw new ArgumentException(errorMessage, name); - } - } + /// + /// Ensure that an argument is neither null nor does it consist only of whitespace. + /// + /// The string to validate. + /// The name of the parameter that will be presented if an exception is thrown. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [SuppressMessage( "Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength" )] + [DebuggerStepThrough] + public static void IsNeitherNullNorWhitespace( string value, string name ) + { + // catch caller errors, mixing up the parameters. Name should never be empty. + Assert.IsNeitherNullNorEmpty( name ); - /// Verifies that an argument is not null. - /// Type of the object to validate. Must be a class. - /// The object to validate. - /// The name of the parameter that will be presented if an exception is thrown. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void IsNotDefault(T obj, string name) where T : struct - { - if (default(T).Equals(obj)) - { - throw new ArgumentException("The parameter must not be the default value.", name); - } - } + // Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P + const string errorMessage = "The parameter can not be either null or empty or consist only of white space characters."; + if( null == value ) + { + throw new ArgumentNullException( name, errorMessage ); + } + if( "" == value.Trim() ) + { + throw new ArgumentException( errorMessage, name ); + } + } - /// Verifies that an argument is not null. - /// Type of the object to validate. Must be a class. - /// The object to validate. - /// The name of the parameter that will be presented if an exception is thrown. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void IsNotNull(T obj, string name) where T : class - { - if (null == obj) - { - throw new ArgumentNullException(name); - } - } + /// Verifies that an argument is not null. + /// Type of the object to validate. Must be a class. + /// The object to validate. + /// The name of the parameter that will be presented if an exception is thrown. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void IsNotDefault( T obj, string name ) where T : struct + { + if( default( T ).Equals( obj ) ) + { + throw new ArgumentException( "The parameter must not be the default value.", name ); + } + } - /// Verifies that an argument is null. - /// Type of the object to validate. Must be a class. - /// The object to validate. - /// The name of the parameter that will be presented if an exception is thrown. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void IsNull(T obj, string name) where T : class - { - if (null != obj) - { - throw new ArgumentException("The parameter must be null.", name); - } - } + /// Verifies that an argument is not null. + /// Type of the object to validate. Must be a class. + /// The object to validate. + /// The name of the parameter that will be presented if an exception is thrown. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void IsNotNull( T obj, string name ) where T : class + { + if( null == obj ) + { + throw new ArgumentNullException( name ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void PropertyIsNotNull(T obj, string name) where T : class - { - if (null == obj) - { - throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The property {0} cannot be null at this time.", name)); - } - } + /// Verifies that an argument is null. + /// Type of the object to validate. Must be a class. + /// The object to validate. + /// The name of the parameter that will be presented if an exception is thrown. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void IsNull( T obj, string name ) where T : class + { + if( null != obj ) + { + throw new ArgumentException( "The parameter must be null.", name ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void PropertyIsNull(T obj, string name) where T : class - { - if (null != obj) - { - throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The property {0} must be null at this time.", name)); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void PropertyIsNotNull( T obj, string name ) where T : class + { + if( null == obj ) + { + throw new InvalidOperationException( string.Format( CultureInfo.InvariantCulture, "The property {0} cannot be null at this time.", name ) ); + } + } - /// - /// Verifies the specified statement is true. Throws an ArgumentException if it's not. - /// - /// The statement to be verified as true. - /// Name of the parameter to include in the ArgumentException. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void IsTrue(bool statement, string name) - { - if (!statement) - { - throw new ArgumentException("", name); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void PropertyIsNull( T obj, string name ) where T : class + { + if( null != obj ) + { + throw new InvalidOperationException( string.Format( CultureInfo.InvariantCulture, "The property {0} must be null at this time.", name ) ); + } + } - /// - /// Verifies the specified statement is true. Throws an ArgumentException if it's not. - /// - /// The statement to be verified as true. - /// Name of the parameter to include in the ArgumentException. - /// The message to include in the ArgumentException. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void IsTrue(bool statement, string name, string message) - { - if (!statement) - { - throw new ArgumentException(message, name); - } - } + /// + /// Verifies the specified statement is true. Throws an ArgumentException if it's not. + /// + /// The statement to be verified as true. + /// Name of the parameter to include in the ArgumentException. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void IsTrue( bool statement, string name ) + { + if( !statement ) + { + throw new ArgumentException( "", name ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void AreEqual(T expected, T actual, string parameterName, string message) - { - if (null == expected) - { - // Two nulls are considered equal, regardless of type semantics. - if (null != actual && !actual.Equals(expected)) - { - throw new ArgumentException(message, parameterName); - } - } - else if (!expected.Equals(actual)) - { - throw new ArgumentException(message, parameterName); - } - } + /// + /// Verifies the specified statement is true. Throws an ArgumentException if it's not. + /// + /// The statement to be verified as true. + /// Name of the parameter to include in the ArgumentException. + /// The message to include in the ArgumentException. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void IsTrue( bool statement, string name, string message ) + { + if( !statement ) + { + throw new ArgumentException( message, name ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void AreNotEqual(T notExpected, T actual, string parameterName, string message) + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void AreEqual( T expected, T actual, string parameterName, string message ) + { + if( null == expected ) + { + // Two nulls are considered equal, regardless of type semantics. + if( null != actual && !actual.Equals( expected ) ) { - if (null == notExpected) - { - // Two nulls are considered equal, regardless of type semantics. - if (null == actual || actual.Equals(notExpected)) - { - throw new ArgumentException(message, parameterName); - } - } - else if (notExpected.Equals(actual)) - { - throw new ArgumentException(message, parameterName); - } + throw new ArgumentException( message, parameterName ); } + } + else if( !expected.Equals( actual ) ) + { + throw new ArgumentException( message, parameterName ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void UriIsAbsolute(Uri uri, string parameterName) + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void AreNotEqual( T notExpected, T actual, string parameterName, string message ) + { + if( null == notExpected ) + { + // Two nulls are considered equal, regardless of type semantics. + if( null == actual || actual.Equals( notExpected ) ) { - Verify.IsNotNull(uri, parameterName); - if (!uri.IsAbsoluteUri) - { - throw new ArgumentException("The URI must be absolute.", parameterName); - } + throw new ArgumentException( message, parameterName ); } + } + else if( notExpected.Equals( actual ) ) + { + throw new ArgumentException( message, parameterName ); + } + } - /// - /// Verifies that the specified value is within the expected range. The assertion fails if it isn't. - /// - /// The lower bound inclusive value. - /// The value to verify. - /// The upper bound exclusive value. - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void BoundedInteger(int lowerBoundInclusive, int value, int upperBoundExclusive, string parameterName) - { - if (value < lowerBoundInclusive || value >= upperBoundExclusive) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The integer value must be bounded with [{0}, {1})", lowerBoundInclusive, upperBoundExclusive), parameterName); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void UriIsAbsolute( Uri uri, string parameterName ) + { + Verify.IsNotNull( uri, parameterName ); + if( !uri.IsAbsoluteUri ) + { + throw new ArgumentException( "The URI must be absolute.", parameterName ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void BoundedDoubleInc(double lowerBoundInclusive, double value, double upperBoundInclusive, string message, string parameter) - { - if (value < lowerBoundInclusive || value > upperBoundInclusive) - { - throw new ArgumentException(message, parameter); - } - } + /// + /// Verifies that the specified value is within the expected range. The assertion fails if it isn't. + /// + /// The lower bound inclusive value. + /// The value to verify. + /// The upper bound exclusive value. + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void BoundedInteger( int lowerBoundInclusive, int value, int upperBoundExclusive, string parameterName ) + { + if( value < lowerBoundInclusive || value >= upperBoundExclusive ) + { + throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, "The integer value must be bounded with [{0}, {1})", lowerBoundInclusive, upperBoundExclusive ), parameterName ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void TypeSupportsInterface(Type type, Type interfaceType, string parameterName) - { - Assert.IsNeitherNullNorEmpty(parameterName); - Verify.IsNotNull(type, "type"); - Verify.IsNotNull(interfaceType, "interfaceType"); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void BoundedDoubleInc( double lowerBoundInclusive, double value, double upperBoundInclusive, string message, string parameter ) + { + if( value < lowerBoundInclusive || value > upperBoundInclusive ) + { + throw new ArgumentException( message, parameter ); + } + } - if (type.GetInterface(interfaceType.Name) == null) - { - throw new ArgumentException("The type of this parameter does not support a required interface", parameterName); - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void TypeSupportsInterface( Type type, Type interfaceType, string parameterName ) + { + Assert.IsNeitherNullNorEmpty( parameterName ); + Verify.IsNotNull( type, "type" ); + Verify.IsNotNull( interfaceType, "interfaceType" ); - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - public static void FileExists(string filePath, string parameterName) - { - Verify.IsNeitherNullNorEmpty(filePath, parameterName); - if (!File.Exists(filePath)) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "No file exists at \"{0}\"", filePath), parameterName); - } - } + if( type.GetInterface( interfaceType.Name ) == null ) + { + throw new ArgumentException( "The type of this parameter does not support a required interface", parameterName ); + } + } - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DebuggerStepThrough] - internal static void ImplementsInterface(object parameter, Type interfaceType, string parameterName) - { - Assert.IsNotNull(parameter); - Assert.IsNotNull(interfaceType); - Assert.IsTrue(interfaceType.IsInterface); + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + public static void FileExists( string filePath, string parameterName ) + { + Verify.IsNeitherNullNorEmpty( filePath, parameterName ); + if( !File.Exists( filePath ) ) + { + throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, "No file exists at \"{0}\"", filePath ), parameterName ); + } + } - bool isImplemented = false; - foreach (var ifaceType in parameter.GetType().GetInterfaces()) - { - if (ifaceType == interfaceType) - { - isImplemented = true; - break; - } - } + [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + [DebuggerStepThrough] + internal static void ImplementsInterface( object parameter, Type interfaceType, string parameterName ) + { + Assert.IsNotNull( parameter ); + Assert.IsNotNull( interfaceType ); + Assert.IsTrue( interfaceType.IsInterface ); - if (!isImplemented) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The parameter must implement interface {0}.", interfaceType.ToString()), parameterName); - } + bool isImplemented = false; + foreach( var ifaceType in parameter.GetType().GetInterfaces() ) + { + if( ifaceType == interfaceType ) + { + isImplemented = true; + break; } + } + + if( !isImplemented ) + { + throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, "The parameter must implement interface {0}.", interfaceType.ToString() ), parameterName ); + } } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemCommands.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemCommands.cs index 15da4b4a..793fe87a 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemCommands.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemCommands.cs @@ -17,91 +17,106 @@ namespace Microsoft.Windows.Shell { - using System; - using System.Windows; - using System.Windows.Input; - using System.Windows.Interop; - using Standard; + using System; + using System.Windows; + using System.Windows.Input; + using System.Windows.Interop; + using Standard; + + public static class SystemCommands + { + public static RoutedCommand CloseWindowCommand + { + get; private set; + } + public static RoutedCommand MaximizeWindowCommand + { + get; private set; + } + public static RoutedCommand MinimizeWindowCommand + { + get; private set; + } + public static RoutedCommand RestoreWindowCommand + { + get; private set; + } + public static RoutedCommand ShowSystemMenuCommand + { + get; private set; + } + + static SystemCommands() + { + CloseWindowCommand = new RoutedCommand( "CloseWindow", typeof( SystemCommands ) ); + MaximizeWindowCommand = new RoutedCommand( "MaximizeWindow", typeof( SystemCommands ) ); + MinimizeWindowCommand = new RoutedCommand( "MinimizeWindow", typeof( SystemCommands ) ); + RestoreWindowCommand = new RoutedCommand( "RestoreWindow", typeof( SystemCommands ) ); + ShowSystemMenuCommand = new RoutedCommand( "ShowSystemMenu", typeof( SystemCommands ) ); + } + + private static void _PostSystemCommand( Window window, SC command ) + { + IntPtr hwnd = new WindowInteropHelper( window ).Handle; + if( hwnd == IntPtr.Zero || !NativeMethods.IsWindow( hwnd ) ) + { + return; + } + + NativeMethods.PostMessage( hwnd, WM.SYSCOMMAND, new IntPtr( ( int )command ), IntPtr.Zero ); + } + + public static void CloseWindow( Window window ) + { + Verify.IsNotNull( window, "window" ); + _PostSystemCommand( window, SC.CLOSE ); + } + + public static void MaximizeWindow( Window window ) + { + Verify.IsNotNull( window, "window" ); + _PostSystemCommand( window, SC.MAXIMIZE ); + } + + public static void MinimizeWindow( Window window ) + { + Verify.IsNotNull( window, "window" ); + _PostSystemCommand( window, SC.MINIMIZE ); + } + + public static void RestoreWindow( Window window ) + { + Verify.IsNotNull( window, "window" ); + _PostSystemCommand( window, SC.RESTORE ); + } + + /// Display the system menu at a specified location. + /// The location to display the system menu, in logical screen coordinates. + public static void ShowSystemMenu( Window window, Point screenLocation ) + { + Verify.IsNotNull( window, "window" ); + ShowSystemMenuPhysicalCoordinates( window, DpiHelper.LogicalPixelsToDevice( screenLocation ) ); + } - public static class SystemCommands + internal static void ShowSystemMenuPhysicalCoordinates( Window window, Point physicalScreenLocation ) { - public static RoutedCommand CloseWindowCommand { get; private set; } - public static RoutedCommand MaximizeWindowCommand { get; private set; } - public static RoutedCommand MinimizeWindowCommand { get; private set; } - public static RoutedCommand RestoreWindowCommand { get; private set; } - public static RoutedCommand ShowSystemMenuCommand { get; private set; } - - static SystemCommands() - { - CloseWindowCommand = new RoutedCommand("CloseWindow", typeof(SystemCommands)); - MaximizeWindowCommand = new RoutedCommand("MaximizeWindow", typeof(SystemCommands)); - MinimizeWindowCommand = new RoutedCommand("MinimizeWindow", typeof(SystemCommands)); - RestoreWindowCommand = new RoutedCommand("RestoreWindow", typeof(SystemCommands)); - ShowSystemMenuCommand = new RoutedCommand("ShowSystemMenu", typeof(SystemCommands)); - } - - private static void _PostSystemCommand(Window window, SC command) - { - IntPtr hwnd = new WindowInteropHelper(window).Handle; - if (hwnd == IntPtr.Zero || !NativeMethods.IsWindow(hwnd)) - { - return; - } - - NativeMethods.PostMessage(hwnd, WM.SYSCOMMAND, new IntPtr((int)command), IntPtr.Zero); - } - - public static void CloseWindow(Window window) - { - Verify.IsNotNull(window, "window"); - _PostSystemCommand(window, SC.CLOSE); - } - - public static void MaximizeWindow(Window window) - { - Verify.IsNotNull(window, "window"); - _PostSystemCommand(window, SC.MAXIMIZE); - } - - public static void MinimizeWindow(Window window) - { - Verify.IsNotNull(window, "window"); - _PostSystemCommand(window, SC.MINIMIZE); - } - - public static void RestoreWindow(Window window) - { - Verify.IsNotNull(window, "window"); - _PostSystemCommand(window, SC.RESTORE); - } - - /// Display the system menu at a specified location. - /// The location to display the system menu, in logical screen coordinates. - public static void ShowSystemMenu(Window window, Point screenLocation) - { - Verify.IsNotNull(window, "window"); - ShowSystemMenuPhysicalCoordinates(window, DpiHelper.LogicalPixelsToDevice(screenLocation)); - } - - internal static void ShowSystemMenuPhysicalCoordinates(Window window, Point physicalScreenLocation) - { - const uint TPM_RETURNCMD = 0x0100; - const uint TPM_LEFTBUTTON = 0x0; - - Verify.IsNotNull(window, "window"); - IntPtr hwnd = new WindowInteropHelper(window).Handle; - if (hwnd == IntPtr.Zero || !NativeMethods.IsWindow(hwnd)) - { - return; - } - - IntPtr hmenu = NativeMethods.GetSystemMenu(hwnd, false); - - uint cmd = NativeMethods.TrackPopupMenuEx(hmenu, TPM_LEFTBUTTON | TPM_RETURNCMD, (int)physicalScreenLocation.X, (int)physicalScreenLocation.Y, hwnd, IntPtr.Zero); - if (0 != cmd) - { - NativeMethods.PostMessage(hwnd, WM.SYSCOMMAND, new IntPtr(cmd), IntPtr.Zero); - } - } + const uint TPM_RETURNCMD = 0x0100; + const uint TPM_LEFTBUTTON = 0x0; + + Verify.IsNotNull( window, "window" ); + IntPtr hwnd = new WindowInteropHelper( window ).Handle; + if( hwnd == IntPtr.Zero || !NativeMethods.IsWindow( hwnd ) ) + { + return; + } + + IntPtr hmenu = NativeMethods.GetSystemMenu( hwnd, false ); + + uint cmd = NativeMethods.TrackPopupMenuEx( hmenu, TPM_LEFTBUTTON | TPM_RETURNCMD, ( int )physicalScreenLocation.X, ( int )physicalScreenLocation.Y, hwnd, IntPtr.Zero ); + if( 0 != cmd ) + { + NativeMethods.PostMessage( hwnd, WM.SYSCOMMAND, new IntPtr( cmd ), IntPtr.Zero ); + } } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemParameters2.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemParameters2.cs index 9ce6ef42..1ef195c6 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemParameters2.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemParameters2.cs @@ -20,324 +20,324 @@ namespace Microsoft.Windows.Shell { - using System; - using System.Collections.Generic; - using System.ComponentModel; - using System.Diagnostics.CodeAnalysis; - using System.Runtime.InteropServices; - using System.Windows; - using System.Windows.Media; - using Standard; - - [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable")] - public class SystemParameters2 : INotifyPropertyChanged - { - private delegate void _SystemMetricUpdate(IntPtr wParam, IntPtr lParam); - - [ThreadStatic] - private static SystemParameters2 _threadLocalSingleton; - - private MessageWindow _messageHwnd; - - private bool _isGlassEnabled; - private Color _glassColor; - private SolidColorBrush _glassColorBrush; - private Thickness _windowResizeBorderThickness; - private Thickness _windowNonClientFrameThickness; - private double _captionHeight; - private Size _smallIconSize; - private string _uxThemeName; - private string _uxThemeColor; - private bool _isHighContrast; - private CornerRadius _windowCornerRadius; - private Rect _captionButtonLocation; - - private readonly Dictionary> _UpdateTable; - - #region Initialization and Update Methods - - // Most properties exposed here have a way of being queried directly - // and a way of being notified of updates via a window message. - // This region is a grouping of both, for each of the exposed properties. - - private void _InitializeIsGlassEnabled() - { - IsGlassEnabled = NativeMethods.DwmIsCompositionEnabled(); - } - - private void _UpdateIsGlassEnabled(IntPtr wParam, IntPtr lParam) - { - // Neither the wParam or lParam are used in this case. - _InitializeIsGlassEnabled(); - } - - private void _InitializeGlassColor() - { - bool isOpaque; - uint color; - NativeMethods.DwmGetColorizationColor(out color, out isOpaque); - color |= isOpaque ? 0xFF000000 : 0; - - WindowGlassColor = Utility.ColorFromArgbDword(color); - - var glassBrush = new SolidColorBrush(WindowGlassColor); - glassBrush.Freeze(); + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Diagnostics.CodeAnalysis; + using System.Runtime.InteropServices; + using System.Windows; + using System.Windows.Media; + using Standard; + + [SuppressMessage( "Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable" )] + public class SystemParameters2 : INotifyPropertyChanged + { + private delegate void _SystemMetricUpdate( IntPtr wParam, IntPtr lParam ); + + [ThreadStatic] + private static SystemParameters2 _threadLocalSingleton; + + private MessageWindow _messageHwnd; + + private bool _isGlassEnabled; + private Color _glassColor; + private SolidColorBrush _glassColorBrush; + private Thickness _windowResizeBorderThickness; + private Thickness _windowNonClientFrameThickness; + private double _captionHeight; + private Size _smallIconSize; + private string _uxThemeName; + private string _uxThemeColor; + private bool _isHighContrast; + private CornerRadius _windowCornerRadius; + private Rect _captionButtonLocation; + + private readonly Dictionary> _UpdateTable; + + #region Initialization and Update Methods + + // Most properties exposed here have a way of being queried directly + // and a way of being notified of updates via a window message. + // This region is a grouping of both, for each of the exposed properties. + + private void _InitializeIsGlassEnabled() + { + IsGlassEnabled = NativeMethods.DwmIsCompositionEnabled(); + } - WindowGlassBrush = glassBrush; - } + private void _UpdateIsGlassEnabled( IntPtr wParam, IntPtr lParam ) + { + // Neither the wParam or lParam are used in this case. + _InitializeIsGlassEnabled(); + } - private void _UpdateGlassColor(IntPtr wParam, IntPtr lParam) - { - bool isOpaque = lParam != IntPtr.Zero; - uint color = unchecked((uint)(int)wParam.ToInt64()); - color |= isOpaque ? 0xFF000000 : 0; - WindowGlassColor = Utility.ColorFromArgbDword(color); - var glassBrush = new SolidColorBrush(WindowGlassColor); - glassBrush.Freeze(); - WindowGlassBrush = glassBrush; - } + private void _InitializeGlassColor() + { + bool isOpaque; + uint color; + NativeMethods.DwmGetColorizationColor( out color, out isOpaque ); + color |= isOpaque ? 0xFF000000 : 0; - private void _InitializeCaptionHeight() - { - Point ptCaption = new Point(0, NativeMethods.GetSystemMetrics(SM.CYCAPTION)); - WindowCaptionHeight = DpiHelper.DevicePixelsToLogical(ptCaption).Y; - } + WindowGlassColor = Utility.ColorFromArgbDword( color ); - private void _UpdateCaptionHeight(IntPtr wParam, IntPtr lParam) - { - _InitializeCaptionHeight(); - } + var glassBrush = new SolidColorBrush( WindowGlassColor ); + glassBrush.Freeze(); - private void _InitializeWindowResizeBorderThickness() - { - Size frameSize = new Size( - NativeMethods.GetSystemMetrics(SM.CXSIZEFRAME), - NativeMethods.GetSystemMetrics(SM.CYSIZEFRAME)); - Size frameSizeInDips = DpiHelper.DeviceSizeToLogical(frameSize); - WindowResizeBorderThickness = new Thickness(frameSizeInDips.Width, frameSizeInDips.Height, frameSizeInDips.Width, frameSizeInDips.Height); - } - - private void _UpdateWindowResizeBorderThickness(IntPtr wParam, IntPtr lParam) - { - _InitializeWindowResizeBorderThickness(); - } - - private void _InitializeWindowNonClientFrameThickness() - { - Size frameSize = new Size( - NativeMethods.GetSystemMetrics(SM.CXSIZEFRAME), - NativeMethods.GetSystemMetrics(SM.CYSIZEFRAME)); - Size frameSizeInDips = DpiHelper.DeviceSizeToLogical(frameSize); - int captionHeight = NativeMethods.GetSystemMetrics(SM.CYCAPTION); - double captionHeightInDips = DpiHelper.DevicePixelsToLogical(new Point(0, captionHeight)).Y; - WindowNonClientFrameThickness = new Thickness(frameSizeInDips.Width, frameSizeInDips.Height + captionHeightInDips, frameSizeInDips.Width, frameSizeInDips.Height); - } + WindowGlassBrush = glassBrush; + } - private void _UpdateWindowNonClientFrameThickness(IntPtr wParam, IntPtr lParam) - { - _InitializeWindowNonClientFrameThickness(); - } + private void _UpdateGlassColor( IntPtr wParam, IntPtr lParam ) + { + bool isOpaque = lParam != IntPtr.Zero; + uint color = unchecked(( uint )( int )wParam.ToInt64()); + color |= isOpaque ? 0xFF000000 : 0; + WindowGlassColor = Utility.ColorFromArgbDword( color ); + var glassBrush = new SolidColorBrush( WindowGlassColor ); + glassBrush.Freeze(); + WindowGlassBrush = glassBrush; + } - private void _InitializeSmallIconSize() - { - SmallIconSize = new Size( - NativeMethods.GetSystemMetrics(SM.CXSMICON), - NativeMethods.GetSystemMetrics(SM.CYSMICON)); - } + private void _InitializeCaptionHeight() + { + Point ptCaption = new Point( 0, NativeMethods.GetSystemMetrics( SM.CYCAPTION ) ); + WindowCaptionHeight = DpiHelper.DevicePixelsToLogical( ptCaption ).Y; + } - private void _UpdateSmallIconSize(IntPtr wParam, IntPtr lParam) - { - _InitializeSmallIconSize(); - } + private void _UpdateCaptionHeight( IntPtr wParam, IntPtr lParam ) + { + _InitializeCaptionHeight(); + } - private void _LegacyInitializeCaptionButtonLocation() - { - // This calculation isn't quite right, but it's pretty close. - // I expect this is good enough for the scenarios where this is expected to be used. - int captionX = NativeMethods.GetSystemMetrics(SM.CXSIZE); - int captionY = NativeMethods.GetSystemMetrics(SM.CYSIZE); + private void _InitializeWindowResizeBorderThickness() + { + Size frameSize = new Size( + NativeMethods.GetSystemMetrics( SM.CXSIZEFRAME ), + NativeMethods.GetSystemMetrics( SM.CYSIZEFRAME ) ); + Size frameSizeInDips = DpiHelper.DeviceSizeToLogical( frameSize ); + WindowResizeBorderThickness = new Thickness( frameSizeInDips.Width, frameSizeInDips.Height, frameSizeInDips.Width, frameSizeInDips.Height ); + } - int frameX = NativeMethods.GetSystemMetrics(SM.CXSIZEFRAME) + NativeMethods.GetSystemMetrics(SM.CXEDGE); - int frameY = NativeMethods.GetSystemMetrics(SM.CYSIZEFRAME) + NativeMethods.GetSystemMetrics(SM.CYEDGE); + private void _UpdateWindowResizeBorderThickness( IntPtr wParam, IntPtr lParam ) + { + _InitializeWindowResizeBorderThickness(); + } - Rect captionRect = new Rect(0, 0, captionX * 3, captionY); - captionRect.Offset(-frameX - captionRect.Width, frameY); + private void _InitializeWindowNonClientFrameThickness() + { + Size frameSize = new Size( + NativeMethods.GetSystemMetrics( SM.CXSIZEFRAME ), + NativeMethods.GetSystemMetrics( SM.CYSIZEFRAME ) ); + Size frameSizeInDips = DpiHelper.DeviceSizeToLogical( frameSize ); + int captionHeight = NativeMethods.GetSystemMetrics( SM.CYCAPTION ); + double captionHeightInDips = DpiHelper.DevicePixelsToLogical( new Point( 0, captionHeight ) ).Y; + WindowNonClientFrameThickness = new Thickness( frameSizeInDips.Width, frameSizeInDips.Height + captionHeightInDips, frameSizeInDips.Width, frameSizeInDips.Height ); + } - WindowCaptionButtonsLocation = captionRect; - } + private void _UpdateWindowNonClientFrameThickness( IntPtr wParam, IntPtr lParam ) + { + _InitializeWindowNonClientFrameThickness(); + } - [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] - private void _InitializeCaptionButtonLocation() - { - // There is a completely different way to do this on XP. - if (!Utility.IsOSVistaOrNewer || !NativeMethods.IsThemeActive()) - { - _LegacyInitializeCaptionButtonLocation(); - return; - } + private void _InitializeSmallIconSize() + { + SmallIconSize = new Size( + NativeMethods.GetSystemMetrics( SM.CXSMICON ), + NativeMethods.GetSystemMetrics( SM.CYSMICON ) ); + } - var tbix = new TITLEBARINFOEX { cbSize = Marshal.SizeOf(typeof(TITLEBARINFOEX)) }; - IntPtr lParam = Marshal.AllocHGlobal(tbix.cbSize); - try - { - Marshal.StructureToPtr(tbix, lParam, false); - // This might flash a window in the taskbar while being calculated. - // WM_GETTITLEBARINFOEX doesn't work correctly unless the window is visible while processing. - NativeMethods.ShowWindow(_messageHwnd.Handle, SW.SHOW); - NativeMethods.SendMessage(_messageHwnd.Handle, WM.GETTITLEBARINFOEX, IntPtr.Zero, lParam); - tbix = (TITLEBARINFOEX)Marshal.PtrToStructure(lParam, typeof(TITLEBARINFOEX)); - } - finally - { - NativeMethods.ShowWindow(_messageHwnd.Handle, SW.HIDE); - Utility.SafeFreeHGlobal(ref lParam); - } + private void _UpdateSmallIconSize( IntPtr wParam, IntPtr lParam ) + { + _InitializeSmallIconSize(); + } - // TITLEBARINFOEX has information relative to the screen. We need to convert the containing rect - // to instead be relative to the top-right corner of the window. - RECT rcAllCaptionButtons = RECT.Union(tbix.rgrect_CloseButton, tbix.rgrect_MinimizeButton); - // For all known themes, the RECT for the maximize box shouldn't add anything to the union of the minimize and close boxes. - Assert.AreEqual(rcAllCaptionButtons, RECT.Union(rcAllCaptionButtons, tbix.rgrect_MaximizeButton)); + private void _LegacyInitializeCaptionButtonLocation() + { + // This calculation isn't quite right, but it's pretty close. + // I expect this is good enough for the scenarios where this is expected to be used. + int captionX = NativeMethods.GetSystemMetrics( SM.CXSIZE ); + int captionY = NativeMethods.GetSystemMetrics( SM.CYSIZE ); - RECT rcWindow = NativeMethods.GetWindowRect(_messageHwnd.Handle); + int frameX = NativeMethods.GetSystemMetrics( SM.CXSIZEFRAME ) + NativeMethods.GetSystemMetrics( SM.CXEDGE ); + int frameY = NativeMethods.GetSystemMetrics( SM.CYSIZEFRAME ) + NativeMethods.GetSystemMetrics( SM.CYEDGE ); - // Reorient the Top/Right to be relative to the top right edge of the Window. - var deviceCaptionLocation = new Rect( - rcAllCaptionButtons.Left - rcWindow.Width - rcWindow.Left, - rcAllCaptionButtons.Top - rcWindow.Top, - rcAllCaptionButtons.Width, - rcAllCaptionButtons.Height); + Rect captionRect = new Rect( 0, 0, captionX * 3, captionY ); + captionRect.Offset( -frameX - captionRect.Width, frameY ); - Rect logicalCaptionLocation = DpiHelper.DeviceRectToLogical(deviceCaptionLocation); + WindowCaptionButtonsLocation = captionRect; + } - WindowCaptionButtonsLocation = logicalCaptionLocation; - } + [SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )] + private void _InitializeCaptionButtonLocation() + { + // There is a completely different way to do this on XP. + if( !Utility.IsOSVistaOrNewer || !NativeMethods.IsThemeActive() ) + { + _LegacyInitializeCaptionButtonLocation(); + return; + } + + var tbix = new TITLEBARINFOEX { cbSize = Marshal.SizeOf( typeof( TITLEBARINFOEX ) ) }; + IntPtr lParam = Marshal.AllocHGlobal( tbix.cbSize ); + try + { + Marshal.StructureToPtr( tbix, lParam, false ); + // This might flash a window in the taskbar while being calculated. + // WM_GETTITLEBARINFOEX doesn't work correctly unless the window is visible while processing. + NativeMethods.ShowWindow( _messageHwnd.Handle, SW.SHOW ); + NativeMethods.SendMessage( _messageHwnd.Handle, WM.GETTITLEBARINFOEX, IntPtr.Zero, lParam ); + tbix = ( TITLEBARINFOEX )Marshal.PtrToStructure( lParam, typeof( TITLEBARINFOEX ) ); + } + finally + { + NativeMethods.ShowWindow( _messageHwnd.Handle, SW.HIDE ); + Utility.SafeFreeHGlobal( ref lParam ); + } + + // TITLEBARINFOEX has information relative to the screen. We need to convert the containing rect + // to instead be relative to the top-right corner of the window. + RECT rcAllCaptionButtons = RECT.Union( tbix.rgrect_CloseButton, tbix.rgrect_MinimizeButton ); + // For all known themes, the RECT for the maximize box shouldn't add anything to the union of the minimize and close boxes. + Assert.AreEqual( rcAllCaptionButtons, RECT.Union( rcAllCaptionButtons, tbix.rgrect_MaximizeButton ) ); + + RECT rcWindow = NativeMethods.GetWindowRect( _messageHwnd.Handle ); + + // Reorient the Top/Right to be relative to the top right edge of the Window. + var deviceCaptionLocation = new Rect( + rcAllCaptionButtons.Left - rcWindow.Width - rcWindow.Left, + rcAllCaptionButtons.Top - rcWindow.Top, + rcAllCaptionButtons.Width, + rcAllCaptionButtons.Height ); + + Rect logicalCaptionLocation = DpiHelper.DeviceRectToLogical( deviceCaptionLocation ); + + WindowCaptionButtonsLocation = logicalCaptionLocation; + } - private void _UpdateCaptionButtonLocation(IntPtr wParam, IntPtr lParam) - { - _InitializeCaptionButtonLocation(); - } + private void _UpdateCaptionButtonLocation( IntPtr wParam, IntPtr lParam ) + { + _InitializeCaptionButtonLocation(); + } - private void _InitializeHighContrast() - { - HIGHCONTRAST hc = NativeMethods.SystemParameterInfo_GetHIGHCONTRAST(); - HighContrast = (hc.dwFlags & HCF.HIGHCONTRASTON) != 0; - } + private void _InitializeHighContrast() + { + HIGHCONTRAST hc = NativeMethods.SystemParameterInfo_GetHIGHCONTRAST(); + HighContrast = ( hc.dwFlags & HCF.HIGHCONTRASTON ) != 0; + } - private void _UpdateHighContrast(IntPtr wParam, IntPtr lParam) - { - _InitializeHighContrast(); - } + private void _UpdateHighContrast( IntPtr wParam, IntPtr lParam ) + { + _InitializeHighContrast(); + } - private void _InitializeThemeInfo() - { - if (!NativeMethods.IsThemeActive()) - { - UxThemeName = "Classic"; - UxThemeColor = ""; - return; - } - - string name; - string color; - string size; - NativeMethods.GetCurrentThemeName(out name, out color, out size); - - // Consider whether this is the most useful way to expose this... - UxThemeName = System.IO.Path.GetFileNameWithoutExtension(name); - UxThemeColor = color; - } + private void _InitializeThemeInfo() + { + if( !NativeMethods.IsThemeActive() ) + { + UxThemeName = "Classic"; + UxThemeColor = ""; + return; + } + + string name; + string color; + string size; + NativeMethods.GetCurrentThemeName( out name, out color, out size ); + + // Consider whether this is the most useful way to expose this... + UxThemeName = System.IO.Path.GetFileNameWithoutExtension( name ); + UxThemeColor = color; + } - private void _UpdateThemeInfo(IntPtr wParam, IntPtr lParam) - { - _InitializeThemeInfo(); - } + private void _UpdateThemeInfo( IntPtr wParam, IntPtr lParam ) + { + _InitializeThemeInfo(); + } - private void _InitializeWindowCornerRadius() - { - // The radius of window corners isn't exposed as a true system parameter. - // It instead is a logical size that we're approximating based on the current theme. - // There aren't any known variations based on theme color. - Assert.IsNeitherNullNorEmpty(UxThemeName); - - // These radii are approximate. The way WPF does rounding is different than how - // rounded-rectangle HRGNs are created, which is also different than the actual - // round corners on themed Windows. For now we're not exposing anything to - // mitigate the differences. - var cornerRadius = default(CornerRadius); - - // This list is known to be incomplete and very much not future-proof. - // On XP there are at least a couple of shipped themes that this won't catch, - // "Zune" and "Royale", but WPF doesn't know about these either. - // If a new theme was to replace Aero, then this will fall back on "classic" behaviors. - // This isn't ideal, but it's not the end of the world. WPF will generally have problems anyways. - switch (UxThemeName.ToUpperInvariant()) - { - case "LUNA": - cornerRadius = new CornerRadius(6, 6, 0, 0); - break; - case "AERO": - // Aero has two cases. One with glass and one without... - if (NativeMethods.DwmIsCompositionEnabled()) - { - cornerRadius = new CornerRadius(8); - } - else - { - cornerRadius = new CornerRadius(6, 6, 0, 0); - } - break; - case "CLASSIC": - case "ZUNE": - case "ROYALE": - default: - cornerRadius = new CornerRadius(0); - break; - } - - WindowCornerRadius = cornerRadius; - } + private void _InitializeWindowCornerRadius() + { + // The radius of window corners isn't exposed as a true system parameter. + // It instead is a logical size that we're approximating based on the current theme. + // There aren't any known variations based on theme color. + Assert.IsNeitherNullNorEmpty( UxThemeName ); + + // These radii are approximate. The way WPF does rounding is different than how + // rounded-rectangle HRGNs are created, which is also different than the actual + // round corners on themed Windows. For now we're not exposing anything to + // mitigate the differences. + var cornerRadius = default( CornerRadius ); + + // This list is known to be incomplete and very much not future-proof. + // On XP there are at least a couple of shipped themes that this won't catch, + // "Zune" and "Royale", but WPF doesn't know about these either. + // If a new theme was to replace Aero, then this will fall back on "classic" behaviors. + // This isn't ideal, but it's not the end of the world. WPF will generally have problems anyways. + switch( UxThemeName.ToUpperInvariant() ) + { + case "LUNA": + cornerRadius = new CornerRadius( 6, 6, 0, 0 ); + break; + case "AERO": + // Aero has two cases. One with glass and one without... + if( NativeMethods.DwmIsCompositionEnabled() ) + { + cornerRadius = new CornerRadius( 8 ); + } + else + { + cornerRadius = new CornerRadius( 6, 6, 0, 0 ); + } + break; + case "CLASSIC": + case "ZUNE": + case "ROYALE": + default: + cornerRadius = new CornerRadius( 0 ); + break; + } + + WindowCornerRadius = cornerRadius; + } - private void _UpdateWindowCornerRadius(IntPtr wParam, IntPtr lParam) - { - // Neither the wParam or lParam are used in this case. - _InitializeWindowCornerRadius(); - } + private void _UpdateWindowCornerRadius( IntPtr wParam, IntPtr lParam ) + { + // Neither the wParam or lParam are used in this case. + _InitializeWindowCornerRadius(); + } - #endregion + #endregion - /// - /// Private constructor. The public way to access this class is through the static Current property. - /// - private SystemParameters2() - { - // This window gets used for calculations about standard caption button locations - // so it has WS_OVERLAPPEDWINDOW as a style to give it normal caption buttons. - // This window may be shown during calculations of caption bar information, so create it at a location that's likely offscreen. - _messageHwnd = new MessageWindow((CS)0, WS.OVERLAPPEDWINDOW | WS.DISABLED, (WS_EX)0, new Rect(-16000, -16000, 100, 100), "", _WndProc); - _messageHwnd.Dispatcher.ShutdownStarted += (sender, e) => Utility.SafeDispose(ref _messageHwnd); - - // Fixup the default values of the DPs. - _InitializeIsGlassEnabled(); - _InitializeGlassColor(); - _InitializeCaptionHeight(); - _InitializeWindowNonClientFrameThickness(); - _InitializeWindowResizeBorderThickness(); - _InitializeCaptionButtonLocation(); - _InitializeSmallIconSize(); - _InitializeHighContrast(); - _InitializeThemeInfo(); - // WindowCornerRadius isn't exposed by true system parameters, so it requires the theme to be initialized first. - _InitializeWindowCornerRadius(); - - _UpdateTable = new Dictionary> + /// + /// Private constructor. The public way to access this class is through the static Current property. + /// + private SystemParameters2() + { + // This window gets used for calculations about standard caption button locations + // so it has WS_OVERLAPPEDWINDOW as a style to give it normal caption buttons. + // This window may be shown during calculations of caption bar information, so create it at a location that's likely offscreen. + _messageHwnd = new MessageWindow( ( CS )0, WS.OVERLAPPEDWINDOW | WS.DISABLED, ( WS_EX )0, new Rect( -16000, -16000, 100, 100 ), "", _WndProc ); + _messageHwnd.Dispatcher.ShutdownStarted += ( sender, e ) => Utility.SafeDispose( ref _messageHwnd ); + + // Fixup the default values of the DPs. + _InitializeIsGlassEnabled(); + _InitializeGlassColor(); + _InitializeCaptionHeight(); + _InitializeWindowNonClientFrameThickness(); + _InitializeWindowResizeBorderThickness(); + _InitializeCaptionButtonLocation(); + _InitializeSmallIconSize(); + _InitializeHighContrast(); + _InitializeThemeInfo(); + // WindowCornerRadius isn't exposed by true system parameters, so it requires the theme to be initialized first. + _InitializeWindowCornerRadius(); + + _UpdateTable = new Dictionary> { { WM.THEMECHANGED, new List<_SystemMetricUpdate> { - _UpdateThemeInfo, - _UpdateHighContrast, + _UpdateThemeInfo, + _UpdateHighContrast, _UpdateWindowCornerRadius, _UpdateCaptionButtonLocation, } }, { WM.SETTINGCHANGE, @@ -353,221 +353,254 @@ namespace Microsoft.Windows.Shell { WM.DWMCOMPOSITIONCHANGED, new List<_SystemMetricUpdate> { _UpdateIsGlassEnabled } }, { WM.DWMCOLORIZATIONCOLORCHANGED, new List<_SystemMetricUpdate> { _UpdateGlassColor } }, }; - } + } - public static SystemParameters2 Current + public static SystemParameters2 Current + { + get + { + if( _threadLocalSingleton == null ) { - get - { - if (_threadLocalSingleton == null) - { - _threadLocalSingleton = new SystemParameters2(); - } - return _threadLocalSingleton; - } + _threadLocalSingleton = new SystemParameters2(); } + return _threadLocalSingleton; + } + } - private IntPtr _WndProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam) + private IntPtr _WndProc( IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam ) + { + // Don't do this if called within the SystemParameters2 constructor + if( _UpdateTable != null ) + { + List<_SystemMetricUpdate> handlers; + if( _UpdateTable.TryGetValue( msg, out handlers ) ) { - // Don't do this if called within the SystemParameters2 constructor - if (_UpdateTable != null) - { - List<_SystemMetricUpdate> handlers; - if (_UpdateTable.TryGetValue(msg, out handlers)) - { - Assert.IsNotNull(handlers); - foreach (var handler in handlers) - { - handler(wParam, lParam); - } - } - } - - return NativeMethods.DefWindowProc(hwnd, msg, wParam, lParam); + Assert.IsNotNull( handlers ); + foreach( var handler in handlers ) + { + handler( wParam, lParam ); + } } + } - public bool IsGlassEnabled - { - get - { - // return _isGlassEnabled; - // It turns out there may be some lag between someone asking this - // and the window getting updated. It's not too expensive, just always do the check. - return NativeMethods.DwmIsCompositionEnabled(); - } - private set - { - if (value != _isGlassEnabled) - { - _isGlassEnabled = value; - _NotifyPropertyChanged("IsGlassEnabled"); - } - } - } - - public Color WindowGlassColor - { - get { return _glassColor; } - private set - { - if (value != _glassColor) - { - _glassColor = value; - _NotifyPropertyChanged("WindowGlassColor"); - } - } - } + return NativeMethods.DefWindowProc( hwnd, msg, wParam, lParam ); + } - public SolidColorBrush WindowGlassBrush - { - get { return _glassColorBrush; } - private set - { - Assert.IsNotNull(value); - Assert.IsTrue(value.IsFrozen); - if (_glassColorBrush == null || value.Color != _glassColorBrush.Color) - { - _glassColorBrush = value; - _NotifyPropertyChanged("WindowGlassBrush"); - } - } - } + public bool IsGlassEnabled + { + get + { + // return _isGlassEnabled; + // It turns out there may be some lag between someone asking this + // and the window getting updated. It's not too expensive, just always do the check. + return NativeMethods.DwmIsCompositionEnabled(); + } + private set + { + if( value != _isGlassEnabled ) + { + _isGlassEnabled = value; + _NotifyPropertyChanged( "IsGlassEnabled" ); + } + } + } - public Thickness WindowResizeBorderThickness - { - get { return _windowResizeBorderThickness; } - private set - { - if (value != _windowResizeBorderThickness) - { - _windowResizeBorderThickness = value; - _NotifyPropertyChanged("WindowResizeBorderThickness"); - } - } - } + public Color WindowGlassColor + { + get + { + return _glassColor; + } + private set + { + if( value != _glassColor ) + { + _glassColor = value; + _NotifyPropertyChanged( "WindowGlassColor" ); + } + } + } - public Thickness WindowNonClientFrameThickness - { - get { return _windowNonClientFrameThickness; } - private set - { - if (value != _windowNonClientFrameThickness) - { - _windowNonClientFrameThickness = value; - _NotifyPropertyChanged("WindowNonClientFrameThickness"); - } - } - } + public SolidColorBrush WindowGlassBrush + { + get + { + return _glassColorBrush; + } + private set + { + Assert.IsNotNull( value ); + Assert.IsTrue( value.IsFrozen ); + if( _glassColorBrush == null || value.Color != _glassColorBrush.Color ) + { + _glassColorBrush = value; + _NotifyPropertyChanged( "WindowGlassBrush" ); + } + } + } - public double WindowCaptionHeight - { - get { return _captionHeight; } - private set - { - if (value != _captionHeight) - { - _captionHeight = value; - _NotifyPropertyChanged("WindowCaptionHeight"); - } - } - } + public Thickness WindowResizeBorderThickness + { + get + { + return _windowResizeBorderThickness; + } + private set + { + if( value != _windowResizeBorderThickness ) + { + _windowResizeBorderThickness = value; + _NotifyPropertyChanged( "WindowResizeBorderThickness" ); + } + } + } - public Size SmallIconSize - { - get { return new Size(_smallIconSize.Width, _smallIconSize.Height); } - private set - { - if (value != _smallIconSize) - { - _smallIconSize = value; - _NotifyPropertyChanged("SmallIconSize"); - } - } - } + public Thickness WindowNonClientFrameThickness + { + get + { + return _windowNonClientFrameThickness; + } + private set + { + if( value != _windowNonClientFrameThickness ) + { + _windowNonClientFrameThickness = value; + _NotifyPropertyChanged( "WindowNonClientFrameThickness" ); + } + } + } - [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ux")] - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ux")] - public string UxThemeName - { - get { return _uxThemeName; } - private set - { - if (value != _uxThemeName) - { - _uxThemeName = value; - _NotifyPropertyChanged("UxThemeName"); - } - } - } + public double WindowCaptionHeight + { + get + { + return _captionHeight; + } + private set + { + if( value != _captionHeight ) + { + _captionHeight = value; + _NotifyPropertyChanged( "WindowCaptionHeight" ); + } + } + } - [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ux")] - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ux")] - public string UxThemeColor - { - get { return _uxThemeColor; } - private set - { - if (value != _uxThemeColor) - { - _uxThemeColor = value; - _NotifyPropertyChanged("UxThemeColor"); - } - } - } + public Size SmallIconSize + { + get + { + return new Size( _smallIconSize.Width, _smallIconSize.Height ); + } + private set + { + if( value != _smallIconSize ) + { + _smallIconSize = value; + _NotifyPropertyChanged( "SmallIconSize" ); + } + } + } - public bool HighContrast - { - get { return _isHighContrast; } - private set - { - if (value != _isHighContrast) - { - _isHighContrast = value; - _NotifyPropertyChanged("HighContrast"); - } - } - } + [SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ux" )] + [SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ux" )] + public string UxThemeName + { + get + { + return _uxThemeName; + } + private set + { + if( value != _uxThemeName ) + { + _uxThemeName = value; + _NotifyPropertyChanged( "UxThemeName" ); + } + } + } - public CornerRadius WindowCornerRadius - { - get { return _windowCornerRadius; } - private set - { - if (value != _windowCornerRadius) - { - _windowCornerRadius = value; - _NotifyPropertyChanged("WindowCornerRadius"); - } - } - } + [SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ux" )] + [SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ux" )] + public string UxThemeColor + { + get + { + return _uxThemeColor; + } + private set + { + if( value != _uxThemeColor ) + { + _uxThemeColor = value; + _NotifyPropertyChanged( "UxThemeColor" ); + } + } + } - public Rect WindowCaptionButtonsLocation - { - get { return _captionButtonLocation; } - private set - { - if (value != _captionButtonLocation) - { - _captionButtonLocation = value; - _NotifyPropertyChanged("WindowCaptionButtonsLocation"); - } - } - } + public bool HighContrast + { + get + { + return _isHighContrast; + } + private set + { + if( value != _isHighContrast ) + { + _isHighContrast = value; + _NotifyPropertyChanged( "HighContrast" ); + } + } + } - #region INotifyPropertyChanged Members + public CornerRadius WindowCornerRadius + { + get + { + return _windowCornerRadius; + } + private set + { + if( value != _windowCornerRadius ) + { + _windowCornerRadius = value; + _NotifyPropertyChanged( "WindowCornerRadius" ); + } + } + } - private void _NotifyPropertyChanged(string propertyName) - { - Assert.IsNeitherNullNorEmpty(propertyName); - var handler = PropertyChanged; - if (handler != null) - { - handler(this, new PropertyChangedEventArgs(propertyName)); - } - } + public Rect WindowCaptionButtonsLocation + { + get + { + return _captionButtonLocation; + } + private set + { + if( value != _captionButtonLocation ) + { + _captionButtonLocation = value; + _NotifyPropertyChanged( "WindowCaptionButtonsLocation" ); + } + } + } - public event PropertyChangedEventHandler PropertyChanged; + #region INotifyPropertyChanged Members - #endregion + private void _NotifyPropertyChanged( string propertyName ) + { + Assert.IsNeitherNullNorEmpty( propertyName ); + var handler = PropertyChanged; + if( handler != null ) + { + handler( this, new PropertyChangedEventArgs( propertyName ) ); + } } + + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChrome.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChrome.cs index da25da6f..6aa04db8 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChrome.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChrome.cs @@ -20,208 +20,244 @@ namespace Microsoft.Windows.Shell { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Windows; - using System.Windows.Data; - using Standard; - - public class WindowChrome : Freezable + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Windows; + using System.Windows.Data; + using Standard; + + public class WindowChrome : Freezable + { + private struct _SystemParameterBoundProperty { - private struct _SystemParameterBoundProperty - { - public string SystemParameterPropertyName { get; set; } - public DependencyProperty DependencyProperty { get; set; } - } + public string SystemParameterPropertyName + { + get; set; + } + public DependencyProperty DependencyProperty + { + get; set; + } + } - // Named property available for fully extending the glass frame. - public static Thickness GlassFrameCompleteThickness { get { return new Thickness(-1); } } + // Named property available for fully extending the glass frame. + public static Thickness GlassFrameCompleteThickness + { + get + { + return new Thickness( -1 ); + } + } - #region Attached Properties + #region Attached Properties - public static readonly DependencyProperty WindowChromeProperty = DependencyProperty.RegisterAttached( - "WindowChrome", - typeof(WindowChrome), - typeof(WindowChrome), - new PropertyMetadata(null, _OnChromeChanged)); + public static readonly DependencyProperty WindowChromeProperty = DependencyProperty.RegisterAttached( + "WindowChrome", + typeof( WindowChrome ), + typeof( WindowChrome ), + new PropertyMetadata( null, _OnChromeChanged ) ); - private static void _OnChromeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - // The different design tools handle drawing outside their custom window objects differently. - // Rather than try to support this concept in the design surface let the designer draw its own - // chrome anyways. - // There's certainly room for improvement here. - if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(d)) - { - return; - } + private static void _OnChromeChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + // The different design tools handle drawing outside their custom window objects differently. + // Rather than try to support this concept in the design surface let the designer draw its own + // chrome anyways. + // There's certainly room for improvement here. + if( System.ComponentModel.DesignerProperties.GetIsInDesignMode( d ) ) + { + return; + } + + var window = ( Window )d; + var newChrome = ( WindowChrome )e.NewValue; + + Assert.IsNotNull( window ); + + // Update the ChromeWorker with this new object. + + // If there isn't currently a worker associated with the Window then assign a new one. + // There can be a many:1 relationship of to Window to WindowChrome objects, but a 1:1 for a Window and a WindowChromeWorker. + WindowChromeWorker chromeWorker = WindowChromeWorker.GetWindowChromeWorker( window ); + if( chromeWorker == null ) + { + chromeWorker = new WindowChromeWorker(); + WindowChromeWorker.SetWindowChromeWorker( window, chromeWorker ); + } + + chromeWorker.SetWindowChrome( newChrome ); + } - var window = (Window)d; - var newChrome = (WindowChrome)e.NewValue; + [SuppressMessage( "Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0" )] + [SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters" )] + public static WindowChrome GetWindowChrome( Window window ) + { + Verify.IsNotNull( window, "window" ); + return ( WindowChrome )window.GetValue( WindowChromeProperty ); + } - Assert.IsNotNull(window); + [SuppressMessage( "Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0" )] + [SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters" )] + public static void SetWindowChrome( Window window, WindowChrome chrome ) + { + Verify.IsNotNull( window, "window" ); + window.SetValue( WindowChromeProperty, chrome ); + } - // Update the ChromeWorker with this new object. + public static readonly DependencyProperty IsHitTestVisibleInChromeProperty = DependencyProperty.RegisterAttached( + "IsHitTestVisibleInChrome", + typeof( bool ), + typeof( WindowChrome ), + new FrameworkPropertyMetadata( false, FrameworkPropertyMetadataOptions.Inherits ) ); - // If there isn't currently a worker associated with the Window then assign a new one. - // There can be a many:1 relationship of to Window to WindowChrome objects, but a 1:1 for a Window and a WindowChromeWorker. - WindowChromeWorker chromeWorker = WindowChromeWorker.GetWindowChromeWorker(window); - if (chromeWorker == null) - { - chromeWorker = new WindowChromeWorker(); - WindowChromeWorker.SetWindowChromeWorker(window, chromeWorker); - } + [SuppressMessage( "Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0" )] + [SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters" )] + public static bool GetIsHitTestVisibleInChrome( IInputElement inputElement ) + { + Verify.IsNotNull( inputElement, "inputElement" ); + var dobj = inputElement as DependencyObject; + if( dobj == null ) + { + throw new ArgumentException( "The element must be a DependencyObject", "inputElement" ); + } + return ( bool )dobj.GetValue( IsHitTestVisibleInChromeProperty ); + } - chromeWorker.SetWindowChrome(newChrome); - } + [SuppressMessage( "Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0" )] + [SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters" )] + public static void SetIsHitTestVisibleInChrome( IInputElement inputElement, bool hitTestVisible ) + { + Verify.IsNotNull( inputElement, "inputElement" ); + var dobj = inputElement as DependencyObject; + if( dobj == null ) + { + throw new ArgumentException( "The element must be a DependencyObject", "inputElement" ); + } + dobj.SetValue( IsHitTestVisibleInChromeProperty, hitTestVisible ); + } - [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] - [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] - public static WindowChrome GetWindowChrome(Window window) - { - Verify.IsNotNull(window, "window"); - return (WindowChrome)window.GetValue(WindowChromeProperty); - } + #endregion - [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] - [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] - public static void SetWindowChrome(Window window, WindowChrome chrome) - { - Verify.IsNotNull(window, "window"); - window.SetValue(WindowChromeProperty, chrome); - } - - public static readonly DependencyProperty IsHitTestVisibleInChromeProperty = DependencyProperty.RegisterAttached( - "IsHitTestVisibleInChrome", - typeof(bool), - typeof(WindowChrome), - new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits)); - - [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] - [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] - public static bool GetIsHitTestVisibleInChrome(IInputElement inputElement) - { - Verify.IsNotNull(inputElement, "inputElement"); - var dobj = inputElement as DependencyObject; - if (dobj == null) - { - throw new ArgumentException("The element must be a DependencyObject", "inputElement"); - } - return (bool)dobj.GetValue(IsHitTestVisibleInChromeProperty); - } - - [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] - [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] - public static void SetIsHitTestVisibleInChrome(IInputElement inputElement, bool hitTestVisible) - { - Verify.IsNotNull(inputElement, "inputElement"); - var dobj = inputElement as DependencyObject; - if (dobj == null) - { - throw new ArgumentException("The element must be a DependencyObject", "inputElement"); - } - dobj.SetValue(IsHitTestVisibleInChromeProperty, hitTestVisible); - } - - #endregion - - #region Dependency Properties - - public static readonly DependencyProperty CaptionHeightProperty = DependencyProperty.Register( - "CaptionHeight", - typeof(double), - typeof(WindowChrome), - new PropertyMetadata( - 0d, - (d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint()), - value => (double)value >= 0d); - - /// The extent of the top of the window to treat as the caption. - public double CaptionHeight - { - get { return (double)GetValue(CaptionHeightProperty); } - set { SetValue(CaptionHeightProperty, value); } - } - - public static readonly DependencyProperty ResizeBorderThicknessProperty = DependencyProperty.Register( - "ResizeBorderThickness", - typeof(Thickness), - typeof(WindowChrome), - new PropertyMetadata(default(Thickness)), - (value) => Utility.IsThicknessNonNegative((Thickness)value)); - - public Thickness ResizeBorderThickness - { - get { return (Thickness)GetValue(ResizeBorderThicknessProperty); } - set { SetValue(ResizeBorderThicknessProperty, value); } - } - - public static readonly DependencyProperty GlassFrameThicknessProperty = DependencyProperty.Register( - "GlassFrameThickness", - typeof(Thickness), - typeof(WindowChrome), - new PropertyMetadata( - default(Thickness), - (d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint(), - (d, o) => _CoerceGlassFrameThickness((Thickness)o))); - - private static object _CoerceGlassFrameThickness(Thickness thickness) - { - // If it's explicitly set, but set to a thickness with at least one negative side then - // coerce the value to the stock GlassFrameCompleteThickness. - if (!Utility.IsThicknessNonNegative(thickness)) - { - return GlassFrameCompleteThickness; - } + #region Dependency Properties - return thickness; - } - public Thickness GlassFrameThickness - { - get { return (Thickness)GetValue(GlassFrameThicknessProperty); } - set { SetValue(GlassFrameThicknessProperty, value); } - } - - public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register( - "CornerRadius", - typeof(CornerRadius), - typeof(WindowChrome), - new PropertyMetadata( - default(CornerRadius), - (d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint()), - (value) => Utility.IsCornerRadiusValid((CornerRadius)value)); - - public CornerRadius CornerRadius - { - get { return (CornerRadius)GetValue(CornerRadiusProperty); } - set { SetValue(CornerRadiusProperty, value); } - } + public static readonly DependencyProperty CaptionHeightProperty = DependencyProperty.Register( + "CaptionHeight", + typeof( double ), + typeof( WindowChrome ), + new PropertyMetadata( + 0d, + ( d, e ) => ( ( WindowChrome )d )._OnPropertyChangedThatRequiresRepaint() ), + value => ( double )value >= 0d ); - #region ShowSystemMenu + /// The extent of the top of the window to treat as the caption. + public double CaptionHeight + { + get + { + return ( double )GetValue( CaptionHeightProperty ); + } + set + { + SetValue( CaptionHeightProperty, value ); + } + } - /// - /// Gets or sets the ShowSystemMenu property. This dependency property - /// indicates if the system menu should be shown at right click on the caption. - /// - public bool ShowSystemMenu - { - get; - set; - } + public static readonly DependencyProperty ResizeBorderThicknessProperty = DependencyProperty.Register( + "ResizeBorderThickness", + typeof( Thickness ), + typeof( WindowChrome ), + new PropertyMetadata( default( Thickness ) ), + ( value ) => Utility.IsThicknessNonNegative( ( Thickness )value ) ); - #endregion + public Thickness ResizeBorderThickness + { + get + { + return ( Thickness )GetValue( ResizeBorderThicknessProperty ); + } + set + { + SetValue( ResizeBorderThicknessProperty, value ); + } + } + public static readonly DependencyProperty GlassFrameThicknessProperty = DependencyProperty.Register( + "GlassFrameThickness", + typeof( Thickness ), + typeof( WindowChrome ), + new PropertyMetadata( + default( Thickness ), + ( d, e ) => ( ( WindowChrome )d )._OnPropertyChangedThatRequiresRepaint(), + ( d, o ) => _CoerceGlassFrameThickness( ( Thickness )o ) ) ); + private static object _CoerceGlassFrameThickness( Thickness thickness ) + { + // If it's explicitly set, but set to a thickness with at least one negative side then + // coerce the value to the stock GlassFrameCompleteThickness. + if( !Utility.IsThicknessNonNegative( thickness ) ) + { + return GlassFrameCompleteThickness; + } + + return thickness; + } + public Thickness GlassFrameThickness + { + get + { + return ( Thickness )GetValue( GlassFrameThicknessProperty ); + } + set + { + SetValue( GlassFrameThicknessProperty, value ); + } + } - #endregion + public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register( + "CornerRadius", + typeof( CornerRadius ), + typeof( WindowChrome ), + new PropertyMetadata( + default( CornerRadius ), + ( d, e ) => ( ( WindowChrome )d )._OnPropertyChangedThatRequiresRepaint() ), + ( value ) => Utility.IsCornerRadiusValid( ( CornerRadius )value ) ); - protected override Freezable CreateInstanceCore() - { - return new WindowChrome(); - } + public CornerRadius CornerRadius + { + get + { + return ( CornerRadius )GetValue( CornerRadiusProperty ); + } + set + { + SetValue( CornerRadiusProperty, value ); + } + } + + #region ShowSystemMenu + + /// + /// Gets or sets the ShowSystemMenu property. This dependency property + /// indicates if the system menu should be shown at right click on the caption. + /// + public bool ShowSystemMenu + { + get; + set; + } - private static readonly List<_SystemParameterBoundProperty> _BoundProperties = new List<_SystemParameterBoundProperty> + #endregion + + + + #endregion + + protected override Freezable CreateInstanceCore() + { + return new WindowChrome(); + } + + private static readonly List<_SystemParameterBoundProperty> _BoundProperties = new List<_SystemParameterBoundProperty> { new _SystemParameterBoundProperty { DependencyProperty = CornerRadiusProperty, SystemParameterPropertyName = "WindowCornerRadius" }, new _SystemParameterBoundProperty { DependencyProperty = CaptionHeightProperty, SystemParameterPropertyName = "WindowCaptionHeight" }, @@ -229,39 +265,39 @@ namespace Microsoft.Windows.Shell new _SystemParameterBoundProperty { DependencyProperty = GlassFrameThicknessProperty, SystemParameterPropertyName = "WindowNonClientFrameThickness" }, }; - public WindowChrome() - { - // Effective default values for some of these properties are set to be bindings - // that set them to system defaults. - // A more correct way to do this would be to Coerce the value iff the source of the DP was the default value. - // Unfortunately with the current property system we can't detect whether the value being applied at the time - // of the coersion is the default. - foreach (var bp in _BoundProperties) - { - // This list must be declared after the DP's are assigned. - Assert.IsNotNull(bp.DependencyProperty); - BindingOperations.SetBinding( - this, - bp.DependencyProperty, - new Binding - { - Source = SystemParameters2.Current, - Path = new PropertyPath(bp.SystemParameterPropertyName), - Mode = BindingMode.OneWay, - UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, - }); - } - } - - private void _OnPropertyChangedThatRequiresRepaint() - { - var handler = PropertyChangedThatRequiresRepaint; - if (handler != null) + public WindowChrome() + { + // Effective default values for some of these properties are set to be bindings + // that set them to system defaults. + // A more correct way to do this would be to Coerce the value iff the source of the DP was the default value. + // Unfortunately with the current property system we can't detect whether the value being applied at the time + // of the coersion is the default. + foreach( var bp in _BoundProperties ) + { + // This list must be declared after the DP's are assigned. + Assert.IsNotNull( bp.DependencyProperty ); + BindingOperations.SetBinding( + this, + bp.DependencyProperty, + new Binding { - handler(this, EventArgs.Empty); - } - } + Source = SystemParameters2.Current, + Path = new PropertyPath( bp.SystemParameterPropertyName ), + Mode = BindingMode.OneWay, + UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, + } ); + } + } - internal event EventHandler PropertyChangedThatRequiresRepaint; + private void _OnPropertyChangedThatRequiresRepaint() + { + var handler = PropertyChangedThatRequiresRepaint; + if( handler != null ) + { + handler( this, EventArgs.Empty ); + } } + + internal event EventHandler PropertyChangedThatRequiresRepaint; + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChromeWorker.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChromeWorker.cs index e094ea4a..732d94f1 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChromeWorker.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChromeWorker.cs @@ -20,61 +20,60 @@ namespace Microsoft.Windows.Shell { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Runtime.InteropServices; - using System.Threading; - using System.Windows; - using System.Windows.Interop; - using System.Windows.Media; - using System.Windows.Threading; - using Standard; - - using HANDLE_MESSAGE = System.Collections.Generic.KeyValuePair; - using System.Windows.Controls.Primitives; - - internal class WindowChromeWorker : DependencyObject + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Runtime.InteropServices; + using System.Windows; + using System.Windows.Interop; + using System.Windows.Media; + using System.Windows.Threading; + using Standard; + + using HANDLE_MESSAGE = System.Collections.Generic.KeyValuePair; + using System.Windows.Controls.Primitives; + + internal class WindowChromeWorker : DependencyObject + { + // Delegate signature used for Dispatcher.BeginInvoke. + private delegate void _Action(); + + #region Fields + + private const SWP _SwpFlags = SWP.FRAMECHANGED | SWP.NOSIZE | SWP.NOMOVE | SWP.NOZORDER | SWP.NOOWNERZORDER | SWP.NOACTIVATE; + + private readonly List _messageTable; + + /// The Window that's chrome is being modified. + private Window _window; + /// Underlying HWND for the _window. + private IntPtr _hwnd; + private HwndSource _hwndSource = null; + private bool _isHooked = false; + + // These fields are for tracking workarounds for WPF 3.5SP1 behaviors. + private bool _isFixedUp = false; + private bool _isUserResizing = false; + private bool _hasUserMovedWindow = false; + private Point _windowPosAtStartOfUserMove = default( Point ); + + // Field to track attempts to force off Device Bitmaps on Win7. + private int _blackGlassFixupAttemptCount; + + /// Object that describes the current modifications being made to the chrome. + private WindowChrome _chromeInfo; + + // Keep track of this so we can detect when we need to apply changes. Tracking these separately + // as I've seen using just one cause things to get enough out of sync that occasionally the caption will redraw. + private WindowState _lastRoundingState; + private WindowState _lastMenuState; + private bool _isGlassEnabled; + + #endregion + + public WindowChromeWorker() { - // Delegate signature used for Dispatcher.BeginInvoke. - private delegate void _Action(); - - #region Fields - - private const SWP _SwpFlags = SWP.FRAMECHANGED | SWP.NOSIZE | SWP.NOMOVE | SWP.NOZORDER | SWP.NOOWNERZORDER | SWP.NOACTIVATE; - - private readonly List _messageTable; - - /// The Window that's chrome is being modified. - private Window _window; - /// Underlying HWND for the _window. - private IntPtr _hwnd; - private HwndSource _hwndSource = null; - private bool _isHooked = false; - - // These fields are for tracking workarounds for WPF 3.5SP1 behaviors. - private bool _isFixedUp = false; - private bool _isUserResizing = false; - private bool _hasUserMovedWindow = false; - private Point _windowPosAtStartOfUserMove = default(Point); - - // Field to track attempts to force off Device Bitmaps on Win7. - private int _blackGlassFixupAttemptCount; - - /// Object that describes the current modifications being made to the chrome. - private WindowChrome _chromeInfo; - - // Keep track of this so we can detect when we need to apply changes. Tracking these separately - // as I've seen using just one cause things to get enough out of sync that occasionally the caption will redraw. - private WindowState _lastRoundingState; - private WindowState _lastMenuState; - private bool _isGlassEnabled; - - #endregion - - public WindowChromeWorker() - { - _messageTable = new List + _messageTable = new List { new HANDLE_MESSAGE(WM.SETTEXT, _HandleSetTextOrIcon), new HANDLE_MESSAGE(WM.SETICON, _HandleSetTextOrIcon), @@ -84,1135 +83,1146 @@ namespace Microsoft.Windows.Shell new HANDLE_MESSAGE(WM.NCRBUTTONUP, _HandleNCRButtonUp), new HANDLE_MESSAGE(WM.SIZE, _HandleSize), new HANDLE_MESSAGE(WM.WINDOWPOSCHANGED, _HandleWindowPosChanged), - new HANDLE_MESSAGE(WM.DWMCOMPOSITIONCHANGED, _HandleDwmCompositionChanged), + new HANDLE_MESSAGE(WM.DWMCOMPOSITIONCHANGED, _HandleDwmCompositionChanged), }; - if (Utility.IsPresentationFrameworkVersionLessThan4) - { - _messageTable.AddRange(new[] - { + if( Utility.IsPresentationFrameworkVersionLessThan4 ) + { + _messageTable.AddRange( new[] + { new HANDLE_MESSAGE(WM.SETTINGCHANGE, _HandleSettingChange), new HANDLE_MESSAGE(WM.ENTERSIZEMOVE, _HandleEnterSizeMove), new HANDLE_MESSAGE(WM.EXITSIZEMOVE, _HandleExitSizeMove), new HANDLE_MESSAGE(WM.MOVE, _HandleMove), - }); - } - } + } ); + } + } - public void SetWindowChrome(WindowChrome newChrome) - { - VerifyAccess(); - Assert.IsNotNull(_window); + public void SetWindowChrome( WindowChrome newChrome ) + { + VerifyAccess(); + Assert.IsNotNull( _window ); + + if( newChrome == _chromeInfo ) + { + // Nothing's changed. + return; + } + + if( _chromeInfo != null ) + { + _chromeInfo.PropertyChangedThatRequiresRepaint -= _OnChromePropertyChangedThatRequiresRepaint; + } + + _chromeInfo = newChrome; + if( _chromeInfo != null ) + { + _chromeInfo.PropertyChangedThatRequiresRepaint += _OnChromePropertyChangedThatRequiresRepaint; + } + + _ApplyNewCustomChrome(); + } - if (newChrome == _chromeInfo) - { - // Nothing's changed. - return; - } + private void _OnChromePropertyChangedThatRequiresRepaint( object sender, EventArgs e ) + { + _UpdateFrameState( true ); + } - if (_chromeInfo != null) - { - _chromeInfo.PropertyChangedThatRequiresRepaint -= _OnChromePropertyChangedThatRequiresRepaint; - } + public static readonly DependencyProperty WindowChromeWorkerProperty = DependencyProperty.RegisterAttached( + "WindowChromeWorker", + typeof( WindowChromeWorker ), + typeof( WindowChromeWorker ), + new PropertyMetadata( null, _OnChromeWorkerChanged ) ); - _chromeInfo = newChrome; - if (_chromeInfo != null) - { - _chromeInfo.PropertyChangedThatRequiresRepaint += _OnChromePropertyChangedThatRequiresRepaint; - } + private static void _OnChromeWorkerChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + var w = ( Window )d; + var cw = ( WindowChromeWorker )e.NewValue; - _ApplyNewCustomChrome(); - } + // The WindowChromeWorker object should only be set on the window once, and never to null. + Assert.IsNotNull( w ); + Assert.IsNotNull( cw ); + Assert.IsNull( cw._window ); - private void _OnChromePropertyChangedThatRequiresRepaint(object sender, EventArgs e) + cw._SetWindow( w ); + } + + private void _SetWindow( Window window ) + { + Assert.IsNull( _window ); + Assert.IsNotNull( window ); + + _window = window; + + // There are potentially a couple funny states here. + // The window may have been shown and closed, in which case it's no longer usable. + // We shouldn't add any hooks in that case, just exit early. + // If the window hasn't yet been shown, then we need to make sure to remove hooks after it's closed. + _hwnd = new WindowInteropHelper( _window ).Handle; + + if( Utility.IsPresentationFrameworkVersionLessThan4 ) + { + // On older versions of the framework the client size of the window is incorrectly calculated. + // We need to modify the template to fix this on behalf of the user. + Utility.AddDependencyPropertyChangeListener( _window, Window.TemplateProperty, _OnWindowPropertyChangedThatRequiresTemplateFixup ); + Utility.AddDependencyPropertyChangeListener( _window, Window.FlowDirectionProperty, _OnWindowPropertyChangedThatRequiresTemplateFixup ); + } + + _window.Closed += _UnsetWindow; + + // Use whether we can get an HWND to determine if the Window has been loaded. + if( IntPtr.Zero != _hwnd ) + { + // We've seen that the HwndSource can't always be retrieved from the HWND, so cache it early. + // Specifically it seems to sometimes disappear when the OS theme is changing. + _hwndSource = HwndSource.FromHwnd( _hwnd ); + Assert.IsNotNull( _hwndSource ); + _window.ApplyTemplate(); + + if( _chromeInfo != null ) { - _UpdateFrameState(true); + _ApplyNewCustomChrome(); } - - public static readonly DependencyProperty WindowChromeWorkerProperty = DependencyProperty.RegisterAttached( - "WindowChromeWorker", - typeof(WindowChromeWorker), - typeof(WindowChromeWorker), - new PropertyMetadata(null, _OnChromeWorkerChanged)); - - private static void _OnChromeWorkerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + } + else + { + _window.SourceInitialized += ( sender, e ) => { - var w = (Window)d; - var cw = (WindowChromeWorker)e.NewValue; - - // The WindowChromeWorker object should only be set on the window once, and never to null. - Assert.IsNotNull(w); - Assert.IsNotNull(cw); - Assert.IsNull(cw._window); + _hwnd = new WindowInteropHelper( _window ).Handle; + Assert.IsNotDefault( _hwnd ); + _hwndSource = HwndSource.FromHwnd( _hwnd ); + Assert.IsNotNull( _hwndSource ); - cw._SetWindow(w); - } + if( _chromeInfo != null ) + { + _ApplyNewCustomChrome(); + } + }; + } + } - private void _SetWindow(Window window) - { - Assert.IsNull(_window); - Assert.IsNotNull(window); + private void _UnsetWindow( object sender, EventArgs e ) + { + if( Utility.IsPresentationFrameworkVersionLessThan4 ) + { + Utility.RemoveDependencyPropertyChangeListener( _window, Window.TemplateProperty, _OnWindowPropertyChangedThatRequiresTemplateFixup ); + Utility.RemoveDependencyPropertyChangeListener( _window, Window.FlowDirectionProperty, _OnWindowPropertyChangedThatRequiresTemplateFixup ); + } + + if( _chromeInfo != null ) + { + _chromeInfo.PropertyChangedThatRequiresRepaint -= _OnChromePropertyChangedThatRequiresRepaint; + } + + _RestoreStandardChromeState( true ); + } - _window = window; + [SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters" )] + public static WindowChromeWorker GetWindowChromeWorker( Window window ) + { + Verify.IsNotNull( window, "window" ); + return ( WindowChromeWorker )window.GetValue( WindowChromeWorkerProperty ); + } - // There are potentially a couple funny states here. - // The window may have been shown and closed, in which case it's no longer usable. - // We shouldn't add any hooks in that case, just exit early. - // If the window hasn't yet been shown, then we need to make sure to remove hooks after it's closed. - _hwnd = new WindowInteropHelper(_window).Handle; + [SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters" )] + public static void SetWindowChromeWorker( Window window, WindowChromeWorker chrome ) + { + Verify.IsNotNull( window, "window" ); + window.SetValue( WindowChromeWorkerProperty, chrome ); + } - if (Utility.IsPresentationFrameworkVersionLessThan4) - { - // On older versions of the framework the client size of the window is incorrectly calculated. - // We need to modify the template to fix this on behalf of the user. - Utility.AddDependencyPropertyChangeListener(_window, Window.TemplateProperty, _OnWindowPropertyChangedThatRequiresTemplateFixup); - Utility.AddDependencyPropertyChangeListener(_window, Window.FlowDirectionProperty, _OnWindowPropertyChangedThatRequiresTemplateFixup); - } + private void _OnWindowPropertyChangedThatRequiresTemplateFixup( object sender, EventArgs e ) + { + Assert.IsTrue( Utility.IsPresentationFrameworkVersionLessThan4 ); + + if( _chromeInfo != null && _hwnd != IntPtr.Zero ) + { + // Assume that when the template changes it's going to be applied. + // We don't have a good way to externally hook into the template + // actually being applied, so we asynchronously post the fixup operation + // at Loaded priority, so it's expected that the visual tree will be + // updated before _FixupFrameworkIssues is called. + _window.Dispatcher.BeginInvoke( DispatcherPriority.Loaded, ( _Action )_FixupFrameworkIssues ); + } + } - _window.Closed += _UnsetWindow; + private void _ApplyNewCustomChrome() + { + if( _hwnd == IntPtr.Zero ) + { + // Not yet hooked. + return; + } + + if( _chromeInfo == null ) + { + _RestoreStandardChromeState( false ); + return; + } + + if( !_isHooked ) + { + _hwndSource.AddHook( _WndProc ); + _isHooked = true; + } + + _FixupFrameworkIssues(); + + // Force this the first time. + _UpdateSystemMenu( _window.WindowState ); + _UpdateFrameState( true ); + + NativeMethods.SetWindowPos( _hwnd, IntPtr.Zero, 0, 0, 0, 0, _SwpFlags ); + } - // Use whether we can get an HWND to determine if the Window has been loaded. - if (IntPtr.Zero != _hwnd) - { - // We've seen that the HwndSource can't always be retrieved from the HWND, so cache it early. - // Specifically it seems to sometimes disappear when the OS theme is changing. - _hwndSource = HwndSource.FromHwnd(_hwnd); - Assert.IsNotNull(_hwndSource); - _window.ApplyTemplate(); - - if (_chromeInfo != null) - { - _ApplyNewCustomChrome(); - } - } - else - { - _window.SourceInitialized += (sender, e) => - { - _hwnd = new WindowInteropHelper(_window).Handle; - Assert.IsNotDefault(_hwnd); - _hwndSource = HwndSource.FromHwnd(_hwnd); - Assert.IsNotNull(_hwndSource); - - if (_chromeInfo != null) - { - _ApplyNewCustomChrome(); - } - }; - } + private void _FixupFrameworkIssues() + { + Assert.IsNotNull( _chromeInfo ); + Assert.IsNotNull( _window ); + + // This margin is only necessary if the client rect is going to be calculated incorrectly by WPF. + // This bug was fixed in V4 of the framework. + if( !Utility.IsPresentationFrameworkVersionLessThan4 ) + { + return; + } + + if( _window.Template == null ) + { + // Nothing to fixup yet. This will get called again when a template does get set. + return; + } + + // Guard against the visual tree being empty. + if( VisualTreeHelper.GetChildrenCount( _window ) == 0 ) + { + // The template isn't null, but we don't have a visual tree. + // Hope that ApplyTemplate is in the queue and repost this, because there's not much we can do right now. + _window.Dispatcher.BeginInvoke( DispatcherPriority.Loaded, ( _Action )_FixupFrameworkIssues ); + return; + } + + var rootElement = ( FrameworkElement )VisualTreeHelper.GetChild( _window, 0 ); + + RECT rcWindow = NativeMethods.GetWindowRect( _hwnd ); + RECT rcAdjustedClient = _GetAdjustedWindowRect( rcWindow ); + + Rect rcLogicalWindow = DpiHelper.DeviceRectToLogical( new Rect( rcWindow.Left, rcWindow.Top, rcWindow.Width, rcWindow.Height ) ); + Rect rcLogicalClient = DpiHelper.DeviceRectToLogical( new Rect( rcAdjustedClient.Left, rcAdjustedClient.Top, rcAdjustedClient.Width, rcAdjustedClient.Height ) ); + + Thickness nonClientThickness = new Thickness( + rcLogicalWindow.Left - rcLogicalClient.Left, + rcLogicalWindow.Top - rcLogicalClient.Top, + rcLogicalClient.Right - rcLogicalWindow.Right, + rcLogicalClient.Bottom - rcLogicalWindow.Bottom ); + + if( rootElement != null ) + { + rootElement.Margin = new Thickness( + 0, + 0, + -( nonClientThickness.Left + nonClientThickness.Right ), + -( nonClientThickness.Top + nonClientThickness.Bottom ) ); + } + + // The negative thickness on the margin doesn't properly get applied in RTL layouts. + // The width is right, but there is a black bar on the right. + // To fix this we just add an additional RenderTransform to the root element. + // This works fine, but if the window is dynamically changing its FlowDirection then this can have really bizarre side effects. + // This will mostly work if the FlowDirection is dynamically changed, but there aren't many real scenarios that would call for + // that so I'm not addressing the rest of the quirkiness. + if( rootElement != null ) + { + if( _window.FlowDirection == FlowDirection.RightToLeft ) + { + rootElement.RenderTransform = new MatrixTransform( 1, 0, 0, 1, -( nonClientThickness.Left + nonClientThickness.Right ), 0 ); } - - private void _UnsetWindow(object sender, EventArgs e) + else { - if (Utility.IsPresentationFrameworkVersionLessThan4) - { - Utility.RemoveDependencyPropertyChangeListener(_window, Window.TemplateProperty, _OnWindowPropertyChangedThatRequiresTemplateFixup); - Utility.RemoveDependencyPropertyChangeListener(_window, Window.FlowDirectionProperty, _OnWindowPropertyChangedThatRequiresTemplateFixup); - } + rootElement.RenderTransform = null; + } + } - if (_chromeInfo != null) - { - _chromeInfo.PropertyChangedThatRequiresRepaint -= _OnChromePropertyChangedThatRequiresRepaint; - } + if( !_isFixedUp ) + { + _hasUserMovedWindow = false; + _window.StateChanged += _FixupRestoreBounds; - _RestoreStandardChromeState(true); - } + _isFixedUp = true; + } + } - [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] - public static WindowChromeWorker GetWindowChromeWorker(Window window) + // There was a regression in DWM in Windows 7 with regard to handling WM_NCCALCSIZE to effect custom chrome. + // When windows with glass are maximized on a multimonitor setup the glass frame tends to turn black. + // Also when windows are resized they tend to flicker black, sometimes staying that way until resized again. + // + // This appears to be a bug in DWM related to device bitmap optimizations. At least on RTM Win7 we can + // evoke a legacy code path that bypasses the bug by calling an esoteric DWM function. This doesn't affect + // the system, just the application. + // WPF also tends to call this function anyways during animations, so we're just forcing the issue + // consistently and a bit earlier. + [SuppressMessage( "Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes" )] + private void _FixupWindows7Issues() + { + if( _blackGlassFixupAttemptCount > 5 ) + { + // Don't keep trying if there's an endemic problem with this. + return; + } + + if( Utility.IsOSWindows7OrNewer && NativeMethods.DwmIsCompositionEnabled() ) + { + ++_blackGlassFixupAttemptCount; + + bool success = false; + try { - Verify.IsNotNull(window, "window"); - return (WindowChromeWorker)window.GetValue(WindowChromeWorkerProperty); + DWM_TIMING_INFO? dti = NativeMethods.DwmGetCompositionTimingInfo( _hwnd ); + success = dti != null; } - - [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] - public static void SetWindowChromeWorker(Window window, WindowChromeWorker chrome) + catch( Exception ) { - Verify.IsNotNull(window, "window"); - window.SetValue(WindowChromeWorkerProperty, chrome); + // We aren't sure of all the reasons this could fail. + // If we find new ones we should consider making the NativeMethod swallow them as well. + // Since we have a limited number of retries and this method isn't actually critical, just repost. + + // Disabling this for the published code to reduce debug noise. This will get compiled away for retail binaries anyways. + //Assert.Fail(e.Message); } - private void _OnWindowPropertyChangedThatRequiresTemplateFixup(object sender, EventArgs e) + // NativeMethods.DwmGetCompositionTimingInfo swallows E_PENDING. + // If the call wasn't successful, try again later. + if( !success ) { - Assert.IsTrue(Utility.IsPresentationFrameworkVersionLessThan4); - - if (_chromeInfo != null && _hwnd != IntPtr.Zero) - { - // Assume that when the template changes it's going to be applied. - // We don't have a good way to externally hook into the template - // actually being applied, so we asynchronously post the fixup operation - // at Loaded priority, so it's expected that the visual tree will be - // updated before _FixupFrameworkIssues is called. - _window.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, (_Action)_FixupFrameworkIssues); - } + Dispatcher.BeginInvoke( DispatcherPriority.Loaded, ( _Action )_FixupWindows7Issues ); } - - private void _ApplyNewCustomChrome() + else { - if (_hwnd == IntPtr.Zero) - { - // Not yet hooked. - return; - } - - if (_chromeInfo == null) - { - _RestoreStandardChromeState(false); - return; - } - - if (!_isHooked) - { - _hwndSource.AddHook(_WndProc); - _isHooked = true; - } - - _FixupFrameworkIssues(); - - // Force this the first time. - _UpdateSystemMenu(_window.WindowState); - _UpdateFrameState(true); - - NativeMethods.SetWindowPos(_hwnd, IntPtr.Zero, 0, 0, 0, 0, _SwpFlags); + // Reset this. We will want to force this again if DWM composition changes. + _blackGlassFixupAttemptCount = 0; } + } + } - private void _FixupFrameworkIssues() + private void _FixupRestoreBounds( object sender, EventArgs e ) + { + Assert.IsTrue( Utility.IsPresentationFrameworkVersionLessThan4 ); + if( _window.WindowState == WindowState.Maximized || _window.WindowState == WindowState.Minimized ) + { + // Old versions of WPF sometimes force their incorrect idea of the Window's location + // on the Win32 restore bounds. If we have reason to think this is the case, then + // try to undo what WPF did after it has done its thing. + if( _hasUserMovedWindow ) { - Assert.IsNotNull(_chromeInfo); - Assert.IsNotNull(_window); - - // This margin is only necessary if the client rect is going to be calculated incorrectly by WPF. - // This bug was fixed in V4 of the framework. - if (!Utility.IsPresentationFrameworkVersionLessThan4) - { - return; - } + _hasUserMovedWindow = false; + WINDOWPLACEMENT wp = NativeMethods.GetWindowPlacement( _hwnd ); - if (_window.Template == null) - { - // Nothing to fixup yet. This will get called again when a template does get set. - return; - } + RECT adjustedDeviceRc = _GetAdjustedWindowRect( new RECT { Bottom = 100, Right = 100 } ); + Point adjustedTopLeft = DpiHelper.DevicePixelsToLogical( + new Point( + wp.rcNormalPosition.Left - adjustedDeviceRc.Left, + wp.rcNormalPosition.Top - adjustedDeviceRc.Top ) ); - // Guard against the visual tree being empty. - if (VisualTreeHelper.GetChildrenCount(_window) == 0) - { - // The template isn't null, but we don't have a visual tree. - // Hope that ApplyTemplate is in the queue and repost this, because there's not much we can do right now. - _window.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, (_Action)_FixupFrameworkIssues); - return; - } - - var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(_window, 0); - - RECT rcWindow = NativeMethods.GetWindowRect(_hwnd); - RECT rcAdjustedClient = _GetAdjustedWindowRect(rcWindow); - - Rect rcLogicalWindow = DpiHelper.DeviceRectToLogical(new Rect(rcWindow.Left, rcWindow.Top, rcWindow.Width, rcWindow.Height)); - Rect rcLogicalClient = DpiHelper.DeviceRectToLogical(new Rect(rcAdjustedClient.Left, rcAdjustedClient.Top, rcAdjustedClient.Width, rcAdjustedClient.Height)); - - Thickness nonClientThickness = new Thickness( - rcLogicalWindow.Left - rcLogicalClient.Left, - rcLogicalWindow.Top - rcLogicalClient.Top, - rcLogicalClient.Right - rcLogicalWindow.Right, - rcLogicalClient.Bottom - rcLogicalWindow.Bottom); - - rootElement.Margin = new Thickness( - 0, - 0, - -(nonClientThickness.Left + nonClientThickness.Right), - -(nonClientThickness.Top + nonClientThickness.Bottom)); - - // The negative thickness on the margin doesn't properly get applied in RTL layouts. - // The width is right, but there is a black bar on the right. - // To fix this we just add an additional RenderTransform to the root element. - // This works fine, but if the window is dynamically changing its FlowDirection then this can have really bizarre side effects. - // This will mostly work if the FlowDirection is dynamically changed, but there aren't many real scenarios that would call for - // that so I'm not addressing the rest of the quirkiness. - if (_window.FlowDirection == FlowDirection.RightToLeft) - { - rootElement.RenderTransform = new MatrixTransform(1, 0, 0, 1, -(nonClientThickness.Left + nonClientThickness.Right), 0); - } - else - { - rootElement.RenderTransform = null; - } + _window.Top = adjustedTopLeft.Y; + _window.Left = adjustedTopLeft.X; + } + } + } - if (!_isFixedUp) - { - _hasUserMovedWindow = false; - _window.StateChanged += _FixupRestoreBounds; + private RECT _GetAdjustedWindowRect( RECT rcWindow ) + { + // This should only be used to work around issues in the Framework that were fixed in 4.0 + Assert.IsTrue( Utility.IsPresentationFrameworkVersionLessThan4 ); - _isFixedUp = true; - } - } + var style = ( WS )NativeMethods.GetWindowLongPtr( _hwnd, GWL.STYLE ); + var exstyle = ( WS_EX )NativeMethods.GetWindowLongPtr( _hwnd, GWL.EXSTYLE ); - // There was a regression in DWM in Windows 7 with regard to handling WM_NCCALCSIZE to effect custom chrome. - // When windows with glass are maximized on a multimonitor setup the glass frame tends to turn black. - // Also when windows are resized they tend to flicker black, sometimes staying that way until resized again. - // - // This appears to be a bug in DWM related to device bitmap optimizations. At least on RTM Win7 we can - // evoke a legacy code path that bypasses the bug by calling an esoteric DWM function. This doesn't affect - // the system, just the application. - // WPF also tends to call this function anyways during animations, so we're just forcing the issue - // consistently and a bit earlier. - [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - private void _FixupWindows7Issues() - { - if (_blackGlassFixupAttemptCount > 5) - { - // Don't keep trying if there's an endemic problem with this. - return; - } + return NativeMethods.AdjustWindowRectEx( rcWindow, style, false, exstyle ); + } - if (Utility.IsOSWindows7OrNewer && NativeMethods.DwmIsCompositionEnabled()) - { - ++_blackGlassFixupAttemptCount; - - bool success = false; - try - { - DWM_TIMING_INFO? dti = NativeMethods.DwmGetCompositionTimingInfo(_hwnd); - success = dti != null; - } - catch (Exception) - { - // We aren't sure of all the reasons this could fail. - // If we find new ones we should consider making the NativeMethod swallow them as well. - // Since we have a limited number of retries and this method isn't actually critical, just repost. - - // Disabling this for the published code to reduce debug noise. This will get compiled away for retail binaries anyways. - //Assert.Fail(e.Message); - } - - // NativeMethods.DwmGetCompositionTimingInfo swallows E_PENDING. - // If the call wasn't successful, try again later. - if (!success) - { - Dispatcher.BeginInvoke(DispatcherPriority.Loaded, (_Action)_FixupWindows7Issues); - } - else - { - // Reset this. We will want to force this again if DWM composition changes. - _blackGlassFixupAttemptCount = 0; - } - } - } + // Windows tries hard to hide this state from applications. + // Generally you can tell that the window is in a docked position because the restore bounds from GetWindowPlacement + // don't match the current window location and it's not in a maximized or minimized state. + // Because this isn't doced or supported, it's also not incredibly consistent. Sometimes some things get updated in + // different orders, so this isn't absolutely reliable. + private bool _IsWindowDocked + { + get + { + // We're only detecting this state to work around .Net 3.5 issues. + // This logic won't work correctly when those issues are fixed. + Assert.IsTrue( Utility.IsPresentationFrameworkVersionLessThan4 ); - private void _FixupRestoreBounds(object sender, EventArgs e) + if( _window.WindowState != WindowState.Normal ) { - Assert.IsTrue(Utility.IsPresentationFrameworkVersionLessThan4); - if (_window.WindowState == WindowState.Maximized || _window.WindowState == WindowState.Minimized) - { - // Old versions of WPF sometimes force their incorrect idea of the Window's location - // on the Win32 restore bounds. If we have reason to think this is the case, then - // try to undo what WPF did after it has done its thing. - if (_hasUserMovedWindow) - { - _hasUserMovedWindow = false; - WINDOWPLACEMENT wp = NativeMethods.GetWindowPlacement(_hwnd); - - RECT adjustedDeviceRc = _GetAdjustedWindowRect(new RECT { Bottom = 100, Right = 100 }); - Point adjustedTopLeft = DpiHelper.DevicePixelsToLogical( - new Point( - wp.rcNormalPosition.Left - adjustedDeviceRc.Left, - wp.rcNormalPosition.Top - adjustedDeviceRc.Top)); - - _window.Top = adjustedTopLeft.Y; - _window.Left = adjustedTopLeft.X; - } - } + return false; } - private RECT _GetAdjustedWindowRect(RECT rcWindow) - { - // This should only be used to work around issues in the Framework that were fixed in 4.0 - Assert.IsTrue(Utility.IsPresentationFrameworkVersionLessThan4); - - var style = (WS)NativeMethods.GetWindowLongPtr(_hwnd, GWL.STYLE); - var exstyle = (WS_EX)NativeMethods.GetWindowLongPtr(_hwnd, GWL.EXSTYLE); + RECT adjustedOffset = _GetAdjustedWindowRect( new RECT { Bottom = 100, Right = 100 } ); + Point windowTopLeft = new Point( _window.Left, _window.Top ); + windowTopLeft -= ( Vector )DpiHelper.DevicePixelsToLogical( new Point( adjustedOffset.Left, adjustedOffset.Top ) ); - return NativeMethods.AdjustWindowRectEx(rcWindow, style, false, exstyle); - } - - // Windows tries hard to hide this state from applications. - // Generally you can tell that the window is in a docked position because the restore bounds from GetWindowPlacement - // don't match the current window location and it's not in a maximized or minimized state. - // Because this isn't doced or supported, it's also not incredibly consistent. Sometimes some things get updated in - // different orders, so this isn't absolutely reliable. - private bool _IsWindowDocked - { - get - { - // We're only detecting this state to work around .Net 3.5 issues. - // This logic won't work correctly when those issues are fixed. - Assert.IsTrue(Utility.IsPresentationFrameworkVersionLessThan4); + return _window.RestoreBounds.Location != windowTopLeft; + } + } - if (_window.WindowState != WindowState.Normal) - { - return false; - } + #region WindowProc and Message Handlers - RECT adjustedOffset = _GetAdjustedWindowRect(new RECT { Bottom = 100, Right = 100 }); - Point windowTopLeft = new Point(_window.Left, _window.Top); - windowTopLeft -= (Vector)DpiHelper.DevicePixelsToLogical(new Point(adjustedOffset.Left, adjustedOffset.Top)); + private IntPtr _WndProc( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled ) + { + // Only expecting messages for our cached HWND. + Assert.AreEqual( hwnd, _hwnd ); - return _window.RestoreBounds.Location != windowTopLeft; - } + var message = ( WM )msg; + foreach( var handlePair in _messageTable ) + { + if( handlePair.Key == message ) + { + return handlePair.Value( message, wParam, lParam, out handled ); } + } + return IntPtr.Zero; + } - #region WindowProc and Message Handlers + private IntPtr _HandleSetTextOrIcon( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + bool modified = _ModifyStyle( WS.VISIBLE, 0 ); + + // Setting the caption text and icon cause Windows to redraw the caption. + // Letting the default WndProc handle the message without the WS_VISIBLE + // style applied bypasses the redraw. + IntPtr lRet = NativeMethods.DefWindowProc( _hwnd, uMsg, wParam, lParam ); + + // Put back the style we removed. + if( modified ) + { + _ModifyStyle( 0, WS.VISIBLE ); + } + handled = true; + return lRet; + } - private IntPtr _WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) - { - // Only expecting messages for our cached HWND. - Assert.AreEqual(hwnd, _hwnd); + private IntPtr _HandleNCActivate( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + // Despite MSDN's documentation of lParam not being used, + // calling DefWindowProc with lParam set to -1 causes Windows not to draw over the caption. + + // Directly call DefWindowProc with a custom parameter + // which bypasses any other handling of the message. + IntPtr lRet = NativeMethods.DefWindowProc( _hwnd, WM.NCACTIVATE, wParam, new IntPtr( -1 ) ); + handled = true; + return lRet; + } - var message = (WM)msg; - foreach (var handlePair in _messageTable) - { - if (handlePair.Key == message) - { - return handlePair.Value(message, wParam, lParam, out handled); - } - } - return IntPtr.Zero; - } + private IntPtr _HandleNCCalcSize( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + // lParam is an [in, out] that can be either a RECT* (wParam == FALSE) or an NCCALCSIZE_PARAMS*. + // Since the first field of NCCALCSIZE_PARAMS is a RECT and is the only field we care about + // we can unconditionally treat it as a RECT. - private IntPtr _HandleSetTextOrIcon(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) - { - bool modified = _ModifyStyle(WS.VISIBLE, 0); + // Since we always want the client size to equal the window size, we can unconditionally handle it + // without having to modify the parameters. - // Setting the caption text and icon cause Windows to redraw the caption. - // Letting the default WndProc handle the message without the WS_VISIBLE - // style applied bypasses the redraw. - IntPtr lRet = NativeMethods.DefWindowProc(_hwnd, uMsg, wParam, lParam); + handled = true; + return new IntPtr( ( int )WVR.REDRAW ); + } - // Put back the style we removed. - if (modified) - { - _ModifyStyle(0, WS.VISIBLE); - } - handled = true; - return lRet; + private IntPtr _HandleNCHitTest( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + IntPtr lRet = IntPtr.Zero; + handled = false; + + // Give DWM a chance at this first. + if( Utility.IsOSVistaOrNewer && _chromeInfo.GlassFrameThickness != default( Thickness ) && _isGlassEnabled ) + { + // If we're on Vista, give the DWM a chance to handle the message first. + handled = NativeMethods.DwmDefWindowProc( _hwnd, uMsg, wParam, lParam, out lRet ); + } + + // Handle letting the system know if we consider the mouse to be in our effective non-client area. + // If DWM already handled this by way of DwmDefWindowProc, then respect their call. + if( IntPtr.Zero == lRet ) + { + var mousePosScreen = new Point( Utility.GET_X_LPARAM( lParam ), Utility.GET_Y_LPARAM( lParam ) ); + Rect windowPosition = _GetWindowRect(); + + HT ht = _HitTestNca( + DpiHelper.DeviceRectToLogical( windowPosition ), + DpiHelper.DevicePixelsToLogical( mousePosScreen ) ); + + // Don't blindly respect HTCAPTION. + // We want UIElements in the caption area to be actionable so run through a hittest first. + if( ht != HT.CLIENT ) + { + Point mousePosWindow = mousePosScreen; + mousePosWindow.Offset( -windowPosition.X, -windowPosition.Y ); + mousePosWindow = DpiHelper.DevicePixelsToLogical( mousePosWindow ); + IInputElement inputElement = _window.InputHitTest( mousePosWindow ); + if( inputElement != null && WindowChrome.GetIsHitTestVisibleInChrome( inputElement ) ) + { + ht = HT.CLIENT; + } } + handled = true; + lRet = new IntPtr( ( int )ht ); + } + return lRet; + } - private IntPtr _HandleNCActivate(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) + private IntPtr _HandleNCRButtonUp( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + // Emulate the system behavior of clicking the right mouse button over the caption area + // to bring up the system menu. + if( HT.CAPTION == ( HT )wParam.ToInt32() ) + { + if( _window.ContextMenu != null ) { - // Despite MSDN's documentation of lParam not being used, - // calling DefWindowProc with lParam set to -1 causes Windows not to draw over the caption. - - // Directly call DefWindowProc with a custom parameter - // which bypasses any other handling of the message. - IntPtr lRet = NativeMethods.DefWindowProc(_hwnd, WM.NCACTIVATE, wParam, new IntPtr(-1)); - handled = true; - return lRet; + _window.ContextMenu.Placement = PlacementMode.MousePoint; + _window.ContextMenu.IsOpen = true; } + else if( WindowChrome.GetWindowChrome( _window ).ShowSystemMenu ) + SystemCommands.ShowSystemMenuPhysicalCoordinates( _window, new Point( Utility.GET_X_LPARAM( lParam ), Utility.GET_Y_LPARAM( lParam ) ) ); + } + handled = false; + return IntPtr.Zero; + } - private IntPtr _HandleNCCalcSize(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) - { - // lParam is an [in, out] that can be either a RECT* (wParam == FALSE) or an NCCALCSIZE_PARAMS*. - // Since the first field of NCCALCSIZE_PARAMS is a RECT and is the only field we care about - // we can unconditionally treat it as a RECT. + private IntPtr _HandleSize( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + const int SIZE_MAXIMIZED = 2; + + // Force when maximized. + // We can tell what's happening right now, but the Window doesn't yet know it's + // maximized. Not forcing this update will eventually cause the + // default caption to be drawn. + WindowState? state = null; + if( wParam.ToInt32() == SIZE_MAXIMIZED ) + { + state = WindowState.Maximized; + } + _UpdateSystemMenu( state ); + + // Still let the default WndProc handle this. + handled = false; + return IntPtr.Zero; + } - // Since we always want the client size to equal the window size, we can unconditionally handle it - // without having to modify the parameters. + private IntPtr _HandleWindowPosChanged( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + // http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx + // The WM_WINDOWPOSCHANGED message is sent at the end of the window + // state change process. It sort of combines the other state change + // notifications, WM_MOVE, WM_SIZE, and WM_SHOWWINDOW. But it doesn't + // suffer from the same limitations as WM_SHOWWINDOW, so you can + // reliably use it to react to the window being shown or hidden. + + _UpdateSystemMenu( null ); + + if( !_isGlassEnabled ) + { + Assert.IsNotDefault( lParam ); + var wp = ( WINDOWPOS )Marshal.PtrToStructure( lParam, typeof( WINDOWPOS ) ); + _SetRoundingRegion( wp ); + } + + // Still want to pass this to DefWndProc + handled = false; + return IntPtr.Zero; + } - handled = true; - return new IntPtr((int)WVR.REDRAW); - } + private IntPtr _HandleDwmCompositionChanged( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + _UpdateFrameState( false ); - private IntPtr _HandleNCHitTest(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) - { - IntPtr lRet = IntPtr.Zero; - handled = false; + handled = false; + return IntPtr.Zero; + } - // Give DWM a chance at this first. - if (Utility.IsOSVistaOrNewer && _chromeInfo.GlassFrameThickness != default(Thickness) && _isGlassEnabled) - { - // If we're on Vista, give the DWM a chance to handle the message first. - handled = NativeMethods.DwmDefWindowProc(_hwnd, uMsg, wParam, lParam, out lRet); - } + private IntPtr _HandleSettingChange( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + // There are several settings that can cause fixups for the template to become invalid when changed. + // These shouldn't be required on the v4 framework. + Assert.IsTrue( Utility.IsPresentationFrameworkVersionLessThan4 ); - // Handle letting the system know if we consider the mouse to be in our effective non-client area. - // If DWM already handled this by way of DwmDefWindowProc, then respect their call. - if (IntPtr.Zero == lRet) - { - var mousePosScreen = new Point(Utility.GET_X_LPARAM(lParam), Utility.GET_Y_LPARAM(lParam)); - Rect windowPosition = _GetWindowRect(); - - HT ht = _HitTestNca( - DpiHelper.DeviceRectToLogical(windowPosition), - DpiHelper.DevicePixelsToLogical(mousePosScreen)); - - // Don't blindly respect HTCAPTION. - // We want UIElements in the caption area to be actionable so run through a hittest first. - if (ht != HT.CLIENT) - { - Point mousePosWindow = mousePosScreen; - mousePosWindow.Offset(-windowPosition.X, -windowPosition.Y); - mousePosWindow = DpiHelper.DevicePixelsToLogical(mousePosWindow); - IInputElement inputElement = _window.InputHitTest(mousePosWindow); - if (inputElement != null && WindowChrome.GetIsHitTestVisibleInChrome(inputElement)) - { - ht = HT.CLIENT; - } - } - handled = true; - lRet = new IntPtr((int)ht); - } - return lRet; - } + _FixupFrameworkIssues(); + + handled = false; + return IntPtr.Zero; + } - private IntPtr _HandleNCRButtonUp(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) + private IntPtr _HandleEnterSizeMove( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + // This is only intercepted to deal with bugs in Window in .Net 3.5 and below. + Assert.IsTrue( Utility.IsPresentationFrameworkVersionLessThan4 ); + + _isUserResizing = true; + + // On Win7 if the user is dragging the window out of the maximized state then we don't want to use that location + // as a restore point. + Assert.Implies( _window.WindowState == WindowState.Maximized, Utility.IsOSWindows7OrNewer ); + if( _window.WindowState != WindowState.Maximized ) + { + // Check for the docked window case. The window can still be restored when it's in this position so + // try to account for that and not update the start position. + if( !_IsWindowDocked ) { - // Emulate the system behavior of clicking the right mouse button over the caption area - // to bring up the system menu. - if (HT.CAPTION == (HT)wParam.ToInt32()) - { - if (_window.ContextMenu != null) - { - _window.ContextMenu.Placement = PlacementMode.MousePoint; - _window.ContextMenu.IsOpen = true; - } - else if (WindowChrome.GetWindowChrome(_window).ShowSystemMenu) - SystemCommands.ShowSystemMenuPhysicalCoordinates(_window, new Point(Utility.GET_X_LPARAM(lParam), Utility.GET_Y_LPARAM(lParam))); - } - handled = false; - return IntPtr.Zero; + _windowPosAtStartOfUserMove = new Point( _window.Left, _window.Top ); } + // Realistically we also don't want to update the start position when moving from one docked state to another (or to and from maximized), + // but it's tricky to detect and this is already a workaround for a bug that's fixed in newer versions of the framework. + // Not going to try to handle all cases. + } - private IntPtr _HandleSize(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) - { - const int SIZE_MAXIMIZED = 2; - - // Force when maximized. - // We can tell what's happening right now, but the Window doesn't yet know it's - // maximized. Not forcing this update will eventually cause the - // default caption to be drawn. - WindowState? state = null; - if (wParam.ToInt32() == SIZE_MAXIMIZED) - { - state = WindowState.Maximized; - } - _UpdateSystemMenu(state); + handled = false; + return IntPtr.Zero; + } - // Still let the default WndProc handle this. - handled = false; - return IntPtr.Zero; - } + private IntPtr _HandleExitSizeMove( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + // This is only intercepted to deal with bugs in Window in .Net 3.5 and below. + Assert.IsTrue( Utility.IsPresentationFrameworkVersionLessThan4 ); + + _isUserResizing = false; + + // On Win7 the user can change the Window's state by dragging the window to the top of the monitor. + // If they did that, then we need to try to update the restore bounds or else WPF will put the window at the maximized location (e.g. (-8,-8)). + if( _window.WindowState == WindowState.Maximized ) + { + Assert.IsTrue( Utility.IsOSWindows7OrNewer ); + _window.Top = _windowPosAtStartOfUserMove.Y; + _window.Left = _windowPosAtStartOfUserMove.X; + } + + handled = false; + return IntPtr.Zero; + } - private IntPtr _HandleWindowPosChanged(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) - { - // http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx - // The WM_WINDOWPOSCHANGED message is sent at the end of the window - // state change process. It sort of combines the other state change - // notifications, WM_MOVE, WM_SIZE, and WM_SHOWWINDOW. But it doesn't - // suffer from the same limitations as WM_SHOWWINDOW, so you can - // reliably use it to react to the window being shown or hidden. + private IntPtr _HandleMove( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) + { + // This is only intercepted to deal with bugs in Window in .Net 3.5 and below. + Assert.IsTrue( Utility.IsPresentationFrameworkVersionLessThan4 ); - _UpdateSystemMenu(null); + if( _isUserResizing ) + { + _hasUserMovedWindow = true; + } - if (!_isGlassEnabled) - { - Assert.IsNotDefault(lParam); - var wp = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS)); - _SetRoundingRegion(wp); - } - - // Still want to pass this to DefWndProc - handled = false; - return IntPtr.Zero; - } + handled = false; + return IntPtr.Zero; + } - private IntPtr _HandleDwmCompositionChanged(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) - { - _UpdateFrameState(false); + #endregion - handled = false; - return IntPtr.Zero; - } + /// Add and remove a native WindowStyle from the HWND. + /// The styles to be removed. These can be bitwise combined. + /// The styles to be added. These can be bitwise combined. + /// Whether the styles of the HWND were modified as a result of this call. + private bool _ModifyStyle( WS removeStyle, WS addStyle ) + { + Assert.IsNotDefault( _hwnd ); + var dwStyle = ( WS )NativeMethods.GetWindowLongPtr( _hwnd, GWL.STYLE ).ToInt32(); + var dwNewStyle = ( dwStyle & ~removeStyle ) | addStyle; + if( dwStyle == dwNewStyle ) + { + return false; + } + + NativeMethods.SetWindowLongPtr( _hwnd, GWL.STYLE, new IntPtr( ( int )dwNewStyle ) ); + return true; + } - private IntPtr _HandleSettingChange(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) - { - // There are several settings that can cause fixups for the template to become invalid when changed. - // These shouldn't be required on the v4 framework. - Assert.IsTrue(Utility.IsPresentationFrameworkVersionLessThan4); + /// + /// Get the WindowState as the native HWND knows it to be. This isn't necessarily the same as what Window thinks. + /// + private WindowState _GetHwndState() + { + var wpl = NativeMethods.GetWindowPlacement( _hwnd ); + switch( wpl.showCmd ) + { + case SW.SHOWMINIMIZED: + return WindowState.Minimized; + case SW.SHOWMAXIMIZED: + return WindowState.Maximized; + } + return WindowState.Normal; + } - _FixupFrameworkIssues(); + /// + /// Get the bounding rectangle for the window in physical coordinates. + /// + /// The bounding rectangle for the window. + private Rect _GetWindowRect() + { + // Get the window rectangle. + RECT windowPosition = NativeMethods.GetWindowRect( _hwnd ); + return new Rect( windowPosition.Left, windowPosition.Top, windowPosition.Width, windowPosition.Height ); + } - handled = false; - return IntPtr.Zero; - } + /// + /// Update the items in the system menu based on the current, or assumed, WindowState. + /// + /// + /// The state to assume that the Window is in. This can be null to query the Window's state. + /// + /// + /// We want to update the menu while we have some control over whether the caption will be repainted. + /// + private void _UpdateSystemMenu( WindowState? assumeState ) + { + const MF mfEnabled = MF.ENABLED | MF.BYCOMMAND; + const MF mfDisabled = MF.GRAYED | MF.DISABLED | MF.BYCOMMAND; - private IntPtr _HandleEnterSizeMove(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) - { - // This is only intercepted to deal with bugs in Window in .Net 3.5 and below. - Assert.IsTrue(Utility.IsPresentationFrameworkVersionLessThan4); + WindowState state = assumeState ?? _GetHwndState(); - _isUserResizing = true; + if( null != assumeState || _lastMenuState != state ) + { + _lastMenuState = state; - // On Win7 if the user is dragging the window out of the maximized state then we don't want to use that location - // as a restore point. - Assert.Implies(_window.WindowState == WindowState.Maximized, Utility.IsOSWindows7OrNewer); - if (_window.WindowState != WindowState.Maximized) - { - // Check for the docked window case. The window can still be restored when it's in this position so - // try to account for that and not update the start position. - if (!_IsWindowDocked) - { - _windowPosAtStartOfUserMove = new Point(_window.Left, _window.Top); - } - // Realistically we also don't want to update the start position when moving from one docked state to another (or to and from maximized), - // but it's tricky to detect and this is already a workaround for a bug that's fixed in newer versions of the framework. - // Not going to try to handle all cases. - } - - handled = false; - return IntPtr.Zero; + bool modified = _ModifyStyle( WS.VISIBLE, 0 ); + IntPtr hmenu = NativeMethods.GetSystemMenu( _hwnd, false ); + if( IntPtr.Zero != hmenu ) + { + var dwStyle = ( WS )NativeMethods.GetWindowLongPtr( _hwnd, GWL.STYLE ).ToInt32(); + + bool canMinimize = Utility.IsFlagSet( ( int )dwStyle, ( int )WS.MINIMIZEBOX ); + bool canMaximize = Utility.IsFlagSet( ( int )dwStyle, ( int )WS.MAXIMIZEBOX ); + bool canSize = Utility.IsFlagSet( ( int )dwStyle, ( int )WS.THICKFRAME ); + + switch( state ) + { + case WindowState.Maximized: + NativeMethods.EnableMenuItem( hmenu, SC.RESTORE, mfEnabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MOVE, mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.SIZE, mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MINIMIZE, canMinimize ? mfEnabled : mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MAXIMIZE, mfDisabled ); + break; + case WindowState.Minimized: + NativeMethods.EnableMenuItem( hmenu, SC.RESTORE, mfEnabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MOVE, mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.SIZE, mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MINIMIZE, mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MAXIMIZE, canMaximize ? mfEnabled : mfDisabled ); + break; + default: + NativeMethods.EnableMenuItem( hmenu, SC.RESTORE, mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MOVE, mfEnabled ); + NativeMethods.EnableMenuItem( hmenu, SC.SIZE, canSize ? mfEnabled : mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MINIMIZE, canMinimize ? mfEnabled : mfDisabled ); + NativeMethods.EnableMenuItem( hmenu, SC.MAXIMIZE, canMaximize ? mfEnabled : mfDisabled ); + break; + } } - private IntPtr _HandleExitSizeMove(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) + if( modified ) { - // This is only intercepted to deal with bugs in Window in .Net 3.5 and below. - Assert.IsTrue(Utility.IsPresentationFrameworkVersionLessThan4); + _ModifyStyle( 0, WS.VISIBLE ); + } + } + } - _isUserResizing = false; + private void _UpdateFrameState( bool force ) + { + if( IntPtr.Zero == _hwnd ) + { + return; + } - // On Win7 the user can change the Window's state by dragging the window to the top of the monitor. - // If they did that, then we need to try to update the restore bounds or else WPF will put the window at the maximized location (e.g. (-8,-8)). - if (_window.WindowState == WindowState.Maximized) - { - Assert.IsTrue(Utility.IsOSWindows7OrNewer); - _window.Top = _windowPosAtStartOfUserMove.Y; - _window.Left = _windowPosAtStartOfUserMove.X; - } + // Don't rely on SystemParameters2 for this, just make the check ourselves. + bool frameState = NativeMethods.DwmIsCompositionEnabled(); - handled = false; - return IntPtr.Zero; - } + if( force || frameState != _isGlassEnabled ) + { + _isGlassEnabled = frameState && _chromeInfo.GlassFrameThickness != default( Thickness ); - private IntPtr _HandleMove(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled) + if( !_isGlassEnabled ) { - // This is only intercepted to deal with bugs in Window in .Net 3.5 and below. - Assert.IsTrue(Utility.IsPresentationFrameworkVersionLessThan4); - - if (_isUserResizing) - { - _hasUserMovedWindow = true; - } + _SetRoundingRegion( null ); + } + else + { + _ClearRoundingRegion(); + _ExtendGlassFrame(); - handled = false; - return IntPtr.Zero; + _FixupWindows7Issues(); } - #endregion + NativeMethods.SetWindowPos( _hwnd, IntPtr.Zero, 0, 0, 0, 0, _SwpFlags ); + } + } + + private void _ClearRoundingRegion() + { + NativeMethods.SetWindowRgn( _hwnd, IntPtr.Zero, NativeMethods.IsWindowVisible( _hwnd ) ); + } - /// Add and remove a native WindowStyle from the HWND. - /// The styles to be removed. These can be bitwise combined. - /// The styles to be added. These can be bitwise combined. - /// Whether the styles of the HWND were modified as a result of this call. - private bool _ModifyStyle(WS removeStyle, WS addStyle) - { - Assert.IsNotDefault(_hwnd); - var dwStyle = (WS)NativeMethods.GetWindowLongPtr(_hwnd, GWL.STYLE).ToInt32(); - var dwNewStyle = (dwStyle & ~removeStyle) | addStyle; - if (dwStyle == dwNewStyle) - { - return false; - } + private void _SetRoundingRegion( WINDOWPOS? wp ) + { + const int MONITOR_DEFAULTTONEAREST = 0x00000002; - NativeMethods.SetWindowLongPtr(_hwnd, GWL.STYLE, new IntPtr((int)dwNewStyle)); - return true; - } + // We're early - WPF hasn't necessarily updated the state of the window. + // Need to query it ourselves. + WINDOWPLACEMENT wpl = NativeMethods.GetWindowPlacement( _hwnd ); - /// - /// Get the WindowState as the native HWND knows it to be. This isn't necessarily the same as what Window thinks. - /// - private WindowState _GetHwndState() + if( wpl.showCmd == SW.SHOWMAXIMIZED ) + { + int left; + int top; + + if( wp.HasValue ) { - var wpl = NativeMethods.GetWindowPlacement(_hwnd); - switch (wpl.showCmd) - { - case SW.SHOWMINIMIZED: return WindowState.Minimized; - case SW.SHOWMAXIMIZED: return WindowState.Maximized; - } - return WindowState.Normal; + left = wp.Value.x; + top = wp.Value.y; } - - /// - /// Get the bounding rectangle for the window in physical coordinates. - /// - /// The bounding rectangle for the window. - private Rect _GetWindowRect() + else { - // Get the window rectangle. - RECT windowPosition = NativeMethods.GetWindowRect(_hwnd); - return new Rect(windowPosition.Left, windowPosition.Top, windowPosition.Width, windowPosition.Height); + Rect r = _GetWindowRect(); + left = ( int )r.Left; + top = ( int )r.Top; } - /// - /// Update the items in the system menu based on the current, or assumed, WindowState. - /// - /// - /// The state to assume that the Window is in. This can be null to query the Window's state. - /// - /// - /// We want to update the menu while we have some control over whether the caption will be repainted. - /// - private void _UpdateSystemMenu(WindowState? assumeState) - { - const MF mfEnabled = MF.ENABLED | MF.BYCOMMAND; - const MF mfDisabled = MF.GRAYED | MF.DISABLED | MF.BYCOMMAND; + IntPtr hMon = NativeMethods.MonitorFromWindow( _hwnd, MONITOR_DEFAULTTONEAREST ); - WindowState state = assumeState ?? _GetHwndState(); + MONITORINFO mi = NativeMethods.GetMonitorInfo( hMon ); + RECT rcMax = mi.rcWork; + // The location of maximized window takes into account the border that Windows was + // going to remove, so we also need to consider it. + rcMax.Offset( -left, -top ); - if (null != assumeState || _lastMenuState != state) - { - _lastMenuState = state; - - bool modified = _ModifyStyle(WS.VISIBLE, 0); - IntPtr hmenu = NativeMethods.GetSystemMenu(_hwnd, false); - if (IntPtr.Zero != hmenu) - { - var dwStyle = (WS)NativeMethods.GetWindowLongPtr(_hwnd, GWL.STYLE).ToInt32(); - - bool canMinimize = Utility.IsFlagSet((int)dwStyle, (int)WS.MINIMIZEBOX); - bool canMaximize = Utility.IsFlagSet((int)dwStyle, (int)WS.MAXIMIZEBOX); - bool canSize = Utility.IsFlagSet((int)dwStyle, (int)WS.THICKFRAME); - - switch (state) - { - case WindowState.Maximized: - NativeMethods.EnableMenuItem(hmenu, SC.RESTORE, mfEnabled); - NativeMethods.EnableMenuItem(hmenu, SC.MOVE, mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.SIZE, mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.MINIMIZE, canMinimize ? mfEnabled : mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.MAXIMIZE, mfDisabled); - break; - case WindowState.Minimized: - NativeMethods.EnableMenuItem(hmenu, SC.RESTORE, mfEnabled); - NativeMethods.EnableMenuItem(hmenu, SC.MOVE, mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.SIZE, mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.MINIMIZE, mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.MAXIMIZE, canMaximize ? mfEnabled : mfDisabled); - break; - default: - NativeMethods.EnableMenuItem(hmenu, SC.RESTORE, mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.MOVE, mfEnabled); - NativeMethods.EnableMenuItem(hmenu, SC.SIZE, canSize ? mfEnabled : mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.MINIMIZE, canMinimize ? mfEnabled : mfDisabled); - NativeMethods.EnableMenuItem(hmenu, SC.MAXIMIZE, canMaximize ? mfEnabled : mfDisabled); - break; - } - } - - if (modified) - { - _ModifyStyle(0, WS.VISIBLE); - } - } + IntPtr hrgn = IntPtr.Zero; + try + { + hrgn = NativeMethods.CreateRectRgnIndirect( rcMax ); + NativeMethods.SetWindowRgn( _hwnd, hrgn, NativeMethods.IsWindowVisible( _hwnd ) ); + hrgn = IntPtr.Zero; } - - private void _UpdateFrameState(bool force) + finally { - if (IntPtr.Zero == _hwnd) - { - return; - } - - // Don't rely on SystemParameters2 for this, just make the check ourselves. - bool frameState = NativeMethods.DwmIsCompositionEnabled(); - - if (force || frameState != _isGlassEnabled) - { - _isGlassEnabled = frameState && _chromeInfo.GlassFrameThickness != default(Thickness); - - if (!_isGlassEnabled) - { - _SetRoundingRegion(null); - } - else - { - _ClearRoundingRegion(); - _ExtendGlassFrame(); - - _FixupWindows7Issues(); - } - - NativeMethods.SetWindowPos(_hwnd, IntPtr.Zero, 0, 0, 0, 0, _SwpFlags); - } + Utility.SafeDeleteObject( ref hrgn ); } + } + else + { + Size windowSize; - private void _ClearRoundingRegion() + // Use the size if it's specified. + if( null != wp && !Utility.IsFlagSet( wp.Value.flags, ( int )SWP.NOSIZE ) ) { - NativeMethods.SetWindowRgn(_hwnd, IntPtr.Zero, NativeMethods.IsWindowVisible(_hwnd)); + windowSize = new Size( ( double )wp.Value.cx, ( double )wp.Value.cy ); } - - private void _SetRoundingRegion(WINDOWPOS? wp) + else if( null != wp && ( _lastRoundingState == _window.WindowState ) ) { - const int MONITOR_DEFAULTTONEAREST = 0x00000002; - - // We're early - WPF hasn't necessarily updated the state of the window. - // Need to query it ourselves. - WINDOWPLACEMENT wpl = NativeMethods.GetWindowPlacement(_hwnd); - - if (wpl.showCmd == SW.SHOWMAXIMIZED) - { - int left; - int top; - - if (wp.HasValue) - { - left = wp.Value.x; - top = wp.Value.y; - } - else - { - Rect r = _GetWindowRect(); - left = (int)r.Left; - top = (int)r.Top; - } - - IntPtr hMon = NativeMethods.MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST); - - MONITORINFO mi = NativeMethods.GetMonitorInfo(hMon); - RECT rcMax = mi.rcWork; - // The location of maximized window takes into account the border that Windows was - // going to remove, so we also need to consider it. - rcMax.Offset(-left, -top); - - IntPtr hrgn = IntPtr.Zero; - try - { - hrgn = NativeMethods.CreateRectRgnIndirect(rcMax); - NativeMethods.SetWindowRgn(_hwnd, hrgn, NativeMethods.IsWindowVisible(_hwnd)); - hrgn = IntPtr.Zero; - } - finally - { - Utility.SafeDeleteObject(ref hrgn); - } - } - else - { - Size windowSize; - - // Use the size if it's specified. - if (null != wp && !Utility.IsFlagSet(wp.Value.flags, (int)SWP.NOSIZE)) - { - windowSize = new Size((double)wp.Value.cx, (double)wp.Value.cy); - } - else if (null != wp && (_lastRoundingState == _window.WindowState)) - { - return; - } - else - { - windowSize = _GetWindowRect().Size; - } - - _lastRoundingState = _window.WindowState; - - IntPtr hrgn = IntPtr.Zero; - try - { - double shortestDimension = Math.Min(windowSize.Width, windowSize.Height); - - double topLeftRadius = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.CornerRadius.TopLeft, 0)).X; - topLeftRadius = Math.Min(topLeftRadius, shortestDimension / 2); - - if (_IsUniform(_chromeInfo.CornerRadius)) - { - // RoundedRect HRGNs require an additional pixel of padding. - hrgn = _CreateRoundRectRgn(new Rect(windowSize), topLeftRadius); - } - else - { - // We need to combine HRGNs for each of the corners. - // Create one for each quadrant, but let it overlap into the two adjacent ones - // by the radius amount to ensure that there aren't corners etched into the middle - // of the window. - hrgn = _CreateRoundRectRgn(new Rect(0, 0, windowSize.Width / 2 + topLeftRadius, windowSize.Height / 2 + topLeftRadius), topLeftRadius); - - double topRightRadius = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.CornerRadius.TopRight, 0)).X; - topRightRadius = Math.Min(topRightRadius, shortestDimension / 2); - Rect topRightRegionRect = new Rect(0, 0, windowSize.Width / 2 + topRightRadius, windowSize.Height / 2 + topRightRadius); - topRightRegionRect.Offset(windowSize.Width / 2 - topRightRadius, 0); - Assert.AreEqual(topRightRegionRect.Right, windowSize.Width); - - _CreateAndCombineRoundRectRgn(hrgn, topRightRegionRect, topRightRadius); - - double bottomLeftRadius = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.CornerRadius.BottomLeft, 0)).X; - bottomLeftRadius = Math.Min(bottomLeftRadius, shortestDimension / 2); - Rect bottomLeftRegionRect = new Rect(0, 0, windowSize.Width / 2 + bottomLeftRadius, windowSize.Height / 2 + bottomLeftRadius); - bottomLeftRegionRect.Offset(0, windowSize.Height / 2 - bottomLeftRadius); - Assert.AreEqual(bottomLeftRegionRect.Bottom, windowSize.Height); - - _CreateAndCombineRoundRectRgn(hrgn, bottomLeftRegionRect, bottomLeftRadius); - - double bottomRightRadius = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.CornerRadius.BottomRight, 0)).X; - bottomRightRadius = Math.Min(bottomRightRadius, shortestDimension / 2); - Rect bottomRightRegionRect = new Rect(0, 0, windowSize.Width / 2 + bottomRightRadius, windowSize.Height / 2 + bottomRightRadius); - bottomRightRegionRect.Offset(windowSize.Width / 2 - bottomRightRadius, windowSize.Height / 2 - bottomRightRadius); - Assert.AreEqual(bottomRightRegionRect.Right, windowSize.Width); - Assert.AreEqual(bottomRightRegionRect.Bottom, windowSize.Height); - - _CreateAndCombineRoundRectRgn(hrgn, bottomRightRegionRect, bottomRightRadius); - } - - NativeMethods.SetWindowRgn(_hwnd, hrgn, NativeMethods.IsWindowVisible(_hwnd)); - hrgn = IntPtr.Zero; - } - finally - { - // Free the memory associated with the HRGN if it wasn't assigned to the HWND. - Utility.SafeDeleteObject(ref hrgn); - } - } + return; } - - private static IntPtr _CreateRoundRectRgn(Rect region, double radius) + else { - // Round outwards. - - if (DoubleUtilities.AreClose(0, radius)) - { - return NativeMethods.CreateRectRgn( - (int)Math.Floor(region.Left), - (int)Math.Floor(region.Top), - (int)Math.Ceiling(region.Right), - (int)Math.Ceiling(region.Bottom)); - } - - // RoundedRect HRGNs require an additional pixel of padding on the bottom right to look correct. - return NativeMethods.CreateRoundRectRgn( - (int)Math.Floor(region.Left), - (int)Math.Floor(region.Top), - (int)Math.Ceiling(region.Right) + 1, - (int)Math.Ceiling(region.Bottom) + 1, - (int)Math.Ceiling(radius), - (int)Math.Ceiling(radius)); + windowSize = _GetWindowRect().Size; } - [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "HRGNs")] - private static void _CreateAndCombineRoundRectRgn(IntPtr hrgnSource, Rect region, double radius) + _lastRoundingState = _window.WindowState; + + IntPtr hrgn = IntPtr.Zero; + try { - IntPtr hrgn = IntPtr.Zero; - try - { - hrgn = _CreateRoundRectRgn(region, radius); - CombineRgnResult result = NativeMethods.CombineRgn(hrgnSource, hrgnSource, hrgn, RGN.OR); - if (result == CombineRgnResult.ERROR) - { - throw new InvalidOperationException("Unable to combine two HRGNs."); - } - } - catch - { - Utility.SafeDeleteObject(ref hrgn); - throw; - } + double shortestDimension = Math.Min( windowSize.Width, windowSize.Height ); + + double topLeftRadius = DpiHelper.LogicalPixelsToDevice( new Point( _chromeInfo.CornerRadius.TopLeft, 0 ) ).X; + topLeftRadius = Math.Min( topLeftRadius, shortestDimension / 2 ); + + if( _IsUniform( _chromeInfo.CornerRadius ) ) + { + // RoundedRect HRGNs require an additional pixel of padding. + hrgn = _CreateRoundRectRgn( new Rect( windowSize ), topLeftRadius ); + } + else + { + // We need to combine HRGNs for each of the corners. + // Create one for each quadrant, but let it overlap into the two adjacent ones + // by the radius amount to ensure that there aren't corners etched into the middle + // of the window. + hrgn = _CreateRoundRectRgn( new Rect( 0, 0, windowSize.Width / 2 + topLeftRadius, windowSize.Height / 2 + topLeftRadius ), topLeftRadius ); + + double topRightRadius = DpiHelper.LogicalPixelsToDevice( new Point( _chromeInfo.CornerRadius.TopRight, 0 ) ).X; + topRightRadius = Math.Min( topRightRadius, shortestDimension / 2 ); + Rect topRightRegionRect = new Rect( 0, 0, windowSize.Width / 2 + topRightRadius, windowSize.Height / 2 + topRightRadius ); + topRightRegionRect.Offset( windowSize.Width / 2 - topRightRadius, 0 ); + Assert.AreEqual( topRightRegionRect.Right, windowSize.Width ); + + _CreateAndCombineRoundRectRgn( hrgn, topRightRegionRect, topRightRadius ); + + double bottomLeftRadius = DpiHelper.LogicalPixelsToDevice( new Point( _chromeInfo.CornerRadius.BottomLeft, 0 ) ).X; + bottomLeftRadius = Math.Min( bottomLeftRadius, shortestDimension / 2 ); + Rect bottomLeftRegionRect = new Rect( 0, 0, windowSize.Width / 2 + bottomLeftRadius, windowSize.Height / 2 + bottomLeftRadius ); + bottomLeftRegionRect.Offset( 0, windowSize.Height / 2 - bottomLeftRadius ); + Assert.AreEqual( bottomLeftRegionRect.Bottom, windowSize.Height ); + + _CreateAndCombineRoundRectRgn( hrgn, bottomLeftRegionRect, bottomLeftRadius ); + + double bottomRightRadius = DpiHelper.LogicalPixelsToDevice( new Point( _chromeInfo.CornerRadius.BottomRight, 0 ) ).X; + bottomRightRadius = Math.Min( bottomRightRadius, shortestDimension / 2 ); + Rect bottomRightRegionRect = new Rect( 0, 0, windowSize.Width / 2 + bottomRightRadius, windowSize.Height / 2 + bottomRightRadius ); + bottomRightRegionRect.Offset( windowSize.Width / 2 - bottomRightRadius, windowSize.Height / 2 - bottomRightRadius ); + Assert.AreEqual( bottomRightRegionRect.Right, windowSize.Width ); + Assert.AreEqual( bottomRightRegionRect.Bottom, windowSize.Height ); + + _CreateAndCombineRoundRectRgn( hrgn, bottomRightRegionRect, bottomRightRadius ); + } + + NativeMethods.SetWindowRgn( _hwnd, hrgn, NativeMethods.IsWindowVisible( _hwnd ) ); + hrgn = IntPtr.Zero; } - - private static bool _IsUniform(CornerRadius cornerRadius) + finally { - if (!DoubleUtilities.AreClose(cornerRadius.BottomLeft, cornerRadius.BottomRight)) - { - return false; - } - - if (!DoubleUtilities.AreClose(cornerRadius.TopLeft, cornerRadius.TopRight)) - { - return false; - } - - if (!DoubleUtilities.AreClose(cornerRadius.BottomLeft, cornerRadius.TopRight)) - { - return false; - } - - return true; + // Free the memory associated with the HRGN if it wasn't assigned to the HWND. + Utility.SafeDeleteObject( ref hrgn ); } + } + } - private void _ExtendGlassFrame() + private static IntPtr _CreateRoundRectRgn( Rect region, double radius ) + { + // Round outwards. + + if( DoubleUtilities.AreClose( 0, radius ) ) + { + return NativeMethods.CreateRectRgn( + ( int )Math.Floor( region.Left ), + ( int )Math.Floor( region.Top ), + ( int )Math.Ceiling( region.Right ), + ( int )Math.Ceiling( region.Bottom ) ); + } + + // RoundedRect HRGNs require an additional pixel of padding on the bottom right to look correct. + return NativeMethods.CreateRoundRectRgn( + ( int )Math.Floor( region.Left ), + ( int )Math.Floor( region.Top ), + ( int )Math.Ceiling( region.Right ) + 1, + ( int )Math.Ceiling( region.Bottom ) + 1, + ( int )Math.Ceiling( radius ), + ( int )Math.Ceiling( radius ) ); + } + + [SuppressMessage( "Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "HRGNs" )] + private static void _CreateAndCombineRoundRectRgn( IntPtr hrgnSource, Rect region, double radius ) + { + IntPtr hrgn = IntPtr.Zero; + try + { + hrgn = _CreateRoundRectRgn( region, radius ); + CombineRgnResult result = NativeMethods.CombineRgn( hrgnSource, hrgnSource, hrgn, RGN.OR ); + if( result == CombineRgnResult.ERROR ) { - Assert.IsNotNull(_window); + throw new InvalidOperationException( "Unable to combine two HRGNs." ); + } + } + catch + { + Utility.SafeDeleteObject( ref hrgn ); + throw; + } + } - // Expect that this might be called on OSes other than Vista. - if (!Utility.IsOSVistaOrNewer) - { - // Not an error. Just not on Vista so we're not going to get glass. - return; - } + private static bool _IsUniform( CornerRadius cornerRadius ) + { + if( !DoubleUtilities.AreClose( cornerRadius.BottomLeft, cornerRadius.BottomRight ) ) + { + return false; + } + + if( !DoubleUtilities.AreClose( cornerRadius.TopLeft, cornerRadius.TopRight ) ) + { + return false; + } + + if( !DoubleUtilities.AreClose( cornerRadius.BottomLeft, cornerRadius.TopRight ) ) + { + return false; + } + + return true; + } - if (IntPtr.Zero == _hwnd) - { - // Can't do anything with this call until the Window has been shown. - return; - } + private void _ExtendGlassFrame() + { + Assert.IsNotNull( _window ); + + // Expect that this might be called on OSes other than Vista. + if( !Utility.IsOSVistaOrNewer ) + { + // Not an error. Just not on Vista so we're not going to get glass. + return; + } + + if( IntPtr.Zero == _hwnd ) + { + // Can't do anything with this call until the Window has been shown. + return; + } + + // Ensure standard HWND background painting when DWM isn't enabled. + if( !NativeMethods.DwmIsCompositionEnabled() ) + { + _hwndSource.CompositionTarget.BackgroundColor = SystemColors.WindowColor; + } + else + { + // This makes the glass visible at a Win32 level so long as nothing else is covering it. + // The Window's Background needs to be changed independent of this. + + // Apply the transparent background to the HWND + _hwndSource.CompositionTarget.BackgroundColor = Colors.Transparent; + + // Thickness is going to be DIPs, need to convert to system coordinates. + Point deviceTopLeft = DpiHelper.LogicalPixelsToDevice( new Point( _chromeInfo.GlassFrameThickness.Left, _chromeInfo.GlassFrameThickness.Top ) ); + Point deviceBottomRight = DpiHelper.LogicalPixelsToDevice( new Point( _chromeInfo.GlassFrameThickness.Right, _chromeInfo.GlassFrameThickness.Bottom ) ); + + var dwmMargin = new MARGINS + { + // err on the side of pushing in glass an extra pixel. + cxLeftWidth = ( int )Math.Ceiling( deviceTopLeft.X ), + cxRightWidth = ( int )Math.Ceiling( deviceBottomRight.X ), + cyTopHeight = ( int )Math.Ceiling( deviceTopLeft.Y ), + cyBottomHeight = ( int )Math.Ceiling( deviceBottomRight.Y ), + }; - // Ensure standard HWND background painting when DWM isn't enabled. - if (!NativeMethods.DwmIsCompositionEnabled()) - { - _hwndSource.CompositionTarget.BackgroundColor = SystemColors.WindowColor; - } - else - { - // This makes the glass visible at a Win32 level so long as nothing else is covering it. - // The Window's Background needs to be changed independent of this. - - // Apply the transparent background to the HWND - _hwndSource.CompositionTarget.BackgroundColor = Colors.Transparent; - - // Thickness is going to be DIPs, need to convert to system coordinates. - Point deviceTopLeft = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.GlassFrameThickness.Left, _chromeInfo.GlassFrameThickness.Top)); - Point deviceBottomRight = DpiHelper.LogicalPixelsToDevice(new Point(_chromeInfo.GlassFrameThickness.Right, _chromeInfo.GlassFrameThickness.Bottom)); - - var dwmMargin = new MARGINS - { - // err on the side of pushing in glass an extra pixel. - cxLeftWidth = (int)Math.Ceiling(deviceTopLeft.X), - cxRightWidth = (int)Math.Ceiling(deviceBottomRight.X), - cyTopHeight = (int)Math.Ceiling(deviceTopLeft.Y), - cyBottomHeight = (int)Math.Ceiling(deviceBottomRight.Y), - }; - - NativeMethods.DwmExtendFrameIntoClientArea(_hwnd, ref dwmMargin); - } - } + NativeMethods.DwmExtendFrameIntoClientArea( _hwnd, ref dwmMargin ); + } + } - /// - /// Matrix of the HT values to return when responding to NC window messages. - /// - [SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional", MessageId = "Member")] - private static readonly HT[,] _HitTestBorders = new[,] - { + /// + /// Matrix of the HT values to return when responding to NC window messages. + /// + [SuppressMessage( "Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional", MessageId = "Member" )] + private static readonly HT[,] _HitTestBorders = new[ , ] + { { HT.TOPLEFT, HT.TOP, HT.TOPRIGHT }, { HT.LEFT, HT.CLIENT, HT.RIGHT }, { HT.BOTTOMLEFT, HT.BOTTOM, HT.BOTTOMRIGHT }, }; - private HT _HitTestNca(Rect windowPosition, Point mousePosition) - { - // Determine if hit test is for resizing, default middle (1,1). - int uRow = 1; - int uCol = 1; - bool onResizeBorder = false; - - // Determine if the point is at the top or bottom of the window. - if (mousePosition.Y >= windowPosition.Top && mousePosition.Y < windowPosition.Top + _chromeInfo.ResizeBorderThickness.Top + _chromeInfo.CaptionHeight) - { - onResizeBorder = (mousePosition.Y < (windowPosition.Top + _chromeInfo.ResizeBorderThickness.Top)); - uRow = 0; // top (caption or resize border) - } - else if (mousePosition.Y < windowPosition.Bottom && mousePosition.Y >= windowPosition.Bottom - (int)_chromeInfo.ResizeBorderThickness.Bottom) - { - uRow = 2; // bottom - } - - // Determine if the point is at the left or right of the window. - if (mousePosition.X >= windowPosition.Left && mousePosition.X < windowPosition.Left + (int)_chromeInfo.ResizeBorderThickness.Left) - { - uCol = 0; // left side - } - else if (mousePosition.X < windowPosition.Right && mousePosition.X >= windowPosition.Right - _chromeInfo.ResizeBorderThickness.Right) - { - uCol = 2; // right side - } - - // If the cursor is in one of the top edges by the caption bar, but below the top resize border, - // then resize left-right rather than diagonally. - if (uRow == 0 && uCol != 1 && !onResizeBorder) - { - uRow = 1; - } - - HT ht = _HitTestBorders[uRow, uCol]; - - if (ht == HT.TOP && !onResizeBorder) - { - ht = HT.CAPTION; - } + private HT _HitTestNca( Rect windowPosition, Point mousePosition ) + { + // Determine if hit test is for resizing, default middle (1,1). + int uRow = 1; + int uCol = 1; + bool onResizeBorder = false; + + // Determine if the point is at the top or bottom of the window. + if( mousePosition.Y >= windowPosition.Top && mousePosition.Y < windowPosition.Top + _chromeInfo.ResizeBorderThickness.Top + _chromeInfo.CaptionHeight ) + { + onResizeBorder = ( mousePosition.Y < ( windowPosition.Top + _chromeInfo.ResizeBorderThickness.Top ) ); + uRow = 0; // top (caption or resize border) + } + else if( mousePosition.Y < windowPosition.Bottom && mousePosition.Y >= windowPosition.Bottom - ( int )_chromeInfo.ResizeBorderThickness.Bottom ) + { + uRow = 2; // bottom + } + + // Determine if the point is at the left or right of the window. + if( mousePosition.X >= windowPosition.Left && mousePosition.X < windowPosition.Left + ( int )_chromeInfo.ResizeBorderThickness.Left ) + { + uCol = 0; // left side + } + else if( mousePosition.X < windowPosition.Right && mousePosition.X >= windowPosition.Right - _chromeInfo.ResizeBorderThickness.Right ) + { + uCol = 2; // right side + } + + // If the cursor is in one of the top edges by the caption bar, but below the top resize border, + // then resize left-right rather than diagonally. + if( uRow == 0 && uCol != 1 && !onResizeBorder ) + { + uRow = 1; + } + + HT ht = _HitTestBorders[ uRow, uCol ]; + + if( ht == HT.TOP && !onResizeBorder ) + { + ht = HT.CAPTION; + } + + return ht; + } - return ht; - } + #region Remove Custom Chrome Methods - #region Remove Custom Chrome Methods + private void _RestoreStandardChromeState( bool isClosing ) + { + VerifyAccess(); - private void _RestoreStandardChromeState(bool isClosing) - { - VerifyAccess(); + _UnhookCustomChrome(); - _UnhookCustomChrome(); + if( !isClosing ) + { + _RestoreFrameworkIssueFixups(); + _RestoreGlassFrame(); + _RestoreHrgn(); - if (!isClosing) - { - _RestoreFrameworkIssueFixups(); - _RestoreGlassFrame(); - _RestoreHrgn(); + _window.InvalidateMeasure(); + } + } - _window.InvalidateMeasure(); - } - } + private void _UnhookCustomChrome() + { + Assert.IsNotDefault( _hwnd ); + Assert.IsNotNull( _window ); + + if( _isHooked ) + { + _hwndSource.RemoveHook( _WndProc ); + _isHooked = false; + } + } - private void _UnhookCustomChrome() + private void _RestoreFrameworkIssueFixups() + { + // This margin is only necessary if the client rect is going to be calculated incorrectly by WPF. + // This bug was fixed in V4 of the framework. + if( Utility.IsPresentationFrameworkVersionLessThan4 ) + { + Assert.IsTrue( _isFixedUp ); + + var rootElement = ( FrameworkElement )VisualTreeHelper.GetChild( _window, 0 ); + if( rootElement != null ) { - Assert.IsNotDefault(_hwnd); - Assert.IsNotNull(_window); - - if (_isHooked) - { - _hwndSource.RemoveHook(_WndProc); - _isHooked = false; - } + // Undo anything that was done before. + rootElement.Margin = new Thickness(); } - private void _RestoreFrameworkIssueFixups() - { - // This margin is only necessary if the client rect is going to be calculated incorrectly by WPF. - // This bug was fixed in V4 of the framework. - if (Utility.IsPresentationFrameworkVersionLessThan4) - { - Assert.IsTrue(_isFixedUp); - - var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(_window, 0); - // Undo anything that was done before. - rootElement.Margin = new Thickness(); - - _window.StateChanged -= _FixupRestoreBounds; - _isFixedUp = false; - } - } - - private void _RestoreGlassFrame() - { - Assert.IsNull(_chromeInfo); - Assert.IsNotNull(_window); - - // Expect that this might be called on OSes other than Vista - // and if the window hasn't yet been shown, then we don't need to undo anything. - if (!Utility.IsOSVistaOrNewer || _hwnd == IntPtr.Zero) - { - return; - } - - _hwndSource.CompositionTarget.BackgroundColor = SystemColors.WindowColor; - - if (NativeMethods.DwmIsCompositionEnabled()) - { - // If glass is enabled, push it back to the normal bounds. - var dwmMargin = new MARGINS(); - NativeMethods.DwmExtendFrameIntoClientArea(_hwnd, ref dwmMargin); - } - } + _window.StateChanged -= _FixupRestoreBounds; + _isFixedUp = false; + } + } - private void _RestoreHrgn() - { - _ClearRoundingRegion(); - NativeMethods.SetWindowPos(_hwnd, IntPtr.Zero, 0, 0, 0, 0, _SwpFlags); - } + private void _RestoreGlassFrame() + { + Assert.IsNull( _chromeInfo ); + Assert.IsNotNull( _window ); + + // Expect that this might be called on OSes other than Vista + // and if the window hasn't yet been shown, then we don't need to undo anything. + if( !Utility.IsOSVistaOrNewer || _hwnd == IntPtr.Zero ) + { + return; + } + + _hwndSource.CompositionTarget.BackgroundColor = SystemColors.WindowColor; + + if( NativeMethods.DwmIsCompositionEnabled() ) + { + // If glass is enabled, push it back to the normal bounds. + var dwmMargin = new MARGINS(); + NativeMethods.DwmExtendFrameIntoClientArea( _hwnd, ref dwmMargin ); + } + } - #endregion + private void _RestoreHrgn() + { + _ClearRoundingRegion(); + NativeMethods.SetWindowPos( _hwnd, IntPtr.Zero, 0, 0, 0, 0, _SwpFlags ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/TransformExtentions.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/TransformExtentions.cs index 71c80b99..b4b354bc 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/TransformExtentions.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/TransformExtentions.cs @@ -14,113 +14,107 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; using System.Windows.Media; namespace Xceed.Wpf.AvalonDock.Controls { - internal static class TransformExtensions + internal static class TransformExtensions + { + public static Point PointToScreenDPI( this Visual visual, Point pt ) { - public static Point PointToScreenDPI(this Visual visual, Point pt) - { - Point resultPt = visual.PointToScreen(pt); - return TransformToDeviceDPI(visual, resultPt); - } - - public static Point PointToScreenDPIWithoutFlowDirection(this FrameworkElement element, Point point) - { - if (FrameworkElement.GetFlowDirection(element) == FlowDirection.RightToLeft) - { - var actualSize = element.TransformActualSizeToAncestor(); - Point leftToRightPoint = new Point( - actualSize.Width - point.X, - point.Y); - return element.PointToScreenDPI(leftToRightPoint); - } - - return element.PointToScreenDPI(point); - } - - - - public static Rect GetScreenArea(this FrameworkElement element) - { - // return new Rect(element.PointToScreenDPI(new Point()), - // element.TransformActualSizeToAncestor()); - //} - - //public static Rect GetScreenAreaWithoutFlowDirection(this FrameworkElement element) - //{ - var point = element.PointToScreenDPI(new Point()); - if (FrameworkElement.GetFlowDirection(element) == FlowDirection.RightToLeft) - { - var actualSize = element.TransformActualSizeToAncestor(); - Point leftToRightPoint = new Point( - actualSize.Width - point.X, - point.Y); - return new Rect(leftToRightPoint, - actualSize); - } - - return new Rect(point, - element.TransformActualSizeToAncestor()); - } - - public static Point TransformToDeviceDPI(this Visual visual, Point pt) - { - Matrix m = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; - return new Point(pt.X / m.M11, pt.Y / m.M22); - } - - public static Size TransformFromDeviceDPI(this Visual visual, Size size) - { - Matrix m = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; - return new Size(size.Width * m.M11, size.Height * m.M22); - } - - public static Point TransformFromDeviceDPI(this Visual visual, Point pt) - { - Matrix m = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; - return new Point(pt.X * m.M11, pt.Y * m.M22); - } - - public static bool CanTransform(this Visual visual) - { - return PresentationSource.FromVisual(visual) != null; - } - - public static Size TransformActualSizeToAncestor(this FrameworkElement element) - { - if (PresentationSource.FromVisual(element) == null) - return new Size(element.ActualWidth, element.ActualHeight); - - var parentWindow = PresentationSource.FromVisual(element).RootVisual; - var transformToWindow = element.TransformToAncestor(parentWindow); - return transformToWindow.TransformBounds(new Rect(0, 0, element.ActualWidth, element.ActualHeight)).Size; - } - - public static Size TransformSizeToAncestor(this FrameworkElement element, Size sizeToTransform) - { - if (PresentationSource.FromVisual(element) == null) - return sizeToTransform; - - var parentWindow = PresentationSource.FromVisual(element).RootVisual; - var transformToWindow = element.TransformToAncestor(parentWindow); - return transformToWindow.TransformBounds(new Rect(0, 0, sizeToTransform.Width, sizeToTransform.Height)).Size; - } - - public static GeneralTransform TansformToAncestor(this FrameworkElement element) - { - if (PresentationSource.FromVisual(element) == null) - return new MatrixTransform(Matrix.Identity); - - var parentWindow = PresentationSource.FromVisual(element).RootVisual; - return element.TransformToAncestor(parentWindow); - } + Point resultPt = visual.PointToScreen( pt ); + return TransformToDeviceDPI( visual, resultPt ); + } + + public static Point PointToScreenDPIWithoutFlowDirection( this FrameworkElement element, Point point ) + { + if( FrameworkElement.GetFlowDirection( element ) == FlowDirection.RightToLeft ) + { + var actualSize = element.TransformActualSizeToAncestor(); + Point leftToRightPoint = new Point( + actualSize.Width - point.X, + point.Y ); + return element.PointToScreenDPI( leftToRightPoint ); + } + + return element.PointToScreenDPI( point ); + } + + public static Rect GetScreenArea( this FrameworkElement element ) + { + // return new Rect(element.PointToScreenDPI(new Point()), + // element.TransformActualSizeToAncestor()); + //} + + //public static Rect GetScreenAreaWithoutFlowDirection(this FrameworkElement element) + //{ + var point = element.PointToScreenDPI( new Point() ); + if( FrameworkElement.GetFlowDirection( element ) == FlowDirection.RightToLeft ) + { + var actualSize = element.TransformActualSizeToAncestor(); + Point leftToRightPoint = new Point( + actualSize.Width - point.X, + point.Y ); + return new Rect( leftToRightPoint, + actualSize ); + } + + return new Rect( point, + element.TransformActualSizeToAncestor() ); + } + + public static Point TransformToDeviceDPI( this Visual visual, Point pt ) + { + Matrix m = PresentationSource.FromVisual( visual ).CompositionTarget.TransformToDevice; + return new Point( pt.X / m.M11, pt.Y / m.M22 ); + } + + public static Size TransformFromDeviceDPI( this Visual visual, Size size ) + { + Matrix m = PresentationSource.FromVisual( visual ).CompositionTarget.TransformToDevice; + return new Size( size.Width * m.M11, size.Height * m.M22 ); + } + + public static Point TransformFromDeviceDPI( this Visual visual, Point pt ) + { + Matrix m = PresentationSource.FromVisual( visual ).CompositionTarget.TransformToDevice; + return new Point( pt.X * m.M11, pt.Y * m.M22 ); + } + + public static bool CanTransform( this Visual visual ) + { + return PresentationSource.FromVisual( visual ) != null; + } + public static Size TransformActualSizeToAncestor( this FrameworkElement element ) + { + if( PresentationSource.FromVisual( element ) == null ) + return new Size( element.ActualWidth, element.ActualHeight ); + + var parentWindow = PresentationSource.FromVisual( element ).RootVisual; + var transformToWindow = element.TransformToAncestor( parentWindow ); + return transformToWindow.TransformBounds( new Rect( 0, 0, element.ActualWidth, element.ActualHeight ) ).Size; } + + public static Size TransformSizeToAncestor( this FrameworkElement element, Size sizeToTransform ) + { + if( PresentationSource.FromVisual( element ) == null ) + return sizeToTransform; + + var parentWindow = PresentationSource.FromVisual( element ).RootVisual; + var transformToWindow = element.TransformToAncestor( parentWindow ); + return transformToWindow.TransformBounds( new Rect( 0, 0, sizeToTransform.Width, sizeToTransform.Height ) ).Size; + } + + public static GeneralTransform TansformToAncestor( this FrameworkElement element ) + { + if( PresentationSource.FromVisual( element ) == null ) + return new MatrixTransform( Matrix.Identity ); + + var parentWindow = PresentationSource.FromVisual( element ).RootVisual; + return element.TransformToAncestor( parentWindow ); + } + + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WeakDictionary.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WeakDictionary.cs index b87cbc7c..5de2fd00 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WeakDictionary.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WeakDictionary.cs @@ -16,79 +16,93 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Controls { - class WeakDictionary where K : class + internal class WeakDictionary where K : class + { + #region Members + + private List _keys = new List(); + private List _values = new List(); + + #endregion + + #region constructors + + public WeakDictionary() { - public WeakDictionary() - {} + } - List _keys = new List(); - List _values = new List(); + #endregion - public V this[K key] - { - get - { - V valueToReturn; - if (!GetValue(key, out valueToReturn)) - throw new ArgumentException(); - return valueToReturn; - } - set - { - SetValue(key, value); - } - } + #region Public Methods - public bool ContainsKey(K key) - { - CollectGarbage(); - return -1 != _keys.FindIndex(k => k.GetValueOrDefault() == key); - } + public V this[ K key ] + { + get + { + V valueToReturn; + if( !GetValue( key, out valueToReturn ) ) + throw new ArgumentException(); + return valueToReturn; + } + set + { + SetValue( key, value ); + } + } - public void SetValue(K key, V value) - { - CollectGarbage(); - int vIndex = _keys.FindIndex(k => k.GetValueOrDefault() == key); - if (vIndex > -1) - _values[vIndex] = value; - else - { - _values.Add(value); - _keys.Add(new WeakReference(key)); - } - } + public bool ContainsKey( K key ) + { + CollectGarbage(); + return -1 != _keys.FindIndex( k => k.GetValueOrDefault() == key ); + } - public bool GetValue(K key, out V value) - { - CollectGarbage(); - int vIndex = _keys.FindIndex(k => k.GetValueOrDefault() == key); - value = default(V); - if (vIndex == -1) - return false; - value = _values[vIndex]; - return true; - } + public void SetValue( K key, V value ) + { + CollectGarbage(); + int vIndex = _keys.FindIndex( k => k.GetValueOrDefault() == key ); + if( vIndex > -1 ) + _values[ vIndex ] = value; + else + { + _values.Add( value ); + _keys.Add( new WeakReference( key ) ); + } + } + public bool GetValue( K key, out V value ) + { + CollectGarbage(); + int vIndex = _keys.FindIndex( k => k.GetValueOrDefault() == key ); + value = default( V ); + if( vIndex == -1 ) + return false; + value = _values[ vIndex ]; + return true; + } - void CollectGarbage() - { - int vIndex = 0; - - do - { - vIndex = _keys.FindIndex(vIndex, k => !k.IsAlive); - if (vIndex >= 0) - { - _keys.RemoveAt(vIndex); - _values.RemoveAt(vIndex); - } - } - while (vIndex >= 0); + #endregion + + #region Private Methods + + private void CollectGarbage() + { + int vIndex = 0; + + do + { + vIndex = _keys.FindIndex( vIndex, k => !k.IsAlive ); + if( vIndex >= 0 ) + { + _keys.RemoveAt( vIndex ); + _values.RemoveAt( vIndex ); } + } + while( vIndex >= 0 ); } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WindowActivateEventArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WindowActivateEventArgs.cs index c435cdec..e129acd5 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WindowActivateEventArgs.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WindowActivateEventArgs.cs @@ -15,23 +15,28 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Controls { - class WindowActivateEventArgs : EventArgs + internal class WindowActivateEventArgs : EventArgs + { + #region Constructors + + public WindowActivateEventArgs( IntPtr hwndActivating ) { - public WindowActivateEventArgs(IntPtr hwndActivating) - { - HwndActivating = hwndActivating; - } - - public IntPtr HwndActivating - { - get; - private set; - } + HwndActivating = hwndActivating; } + + #endregion + + #region Properties + + public IntPtr HwndActivating + { + get; + private set; + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WindowHookHandler.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WindowHookHandler.cs index eb07e409..799cc477 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WindowHookHandler.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/WindowHookHandler.cs @@ -15,85 +15,102 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; namespace Xceed.Wpf.AvalonDock.Controls { - class FocusChangeEventArgs : EventArgs + internal class FocusChangeEventArgs : EventArgs + { + #region Constructors + + public FocusChangeEventArgs( IntPtr gotFocusWinHandle, IntPtr lostFocusWinHandle ) { - public FocusChangeEventArgs(IntPtr gotFocusWinHandle, IntPtr lostFocusWinHandle) - { - GotFocusWinHandle = gotFocusWinHandle; - LostFocusWinHandle = lostFocusWinHandle; - } + GotFocusWinHandle = gotFocusWinHandle; + LostFocusWinHandle = lostFocusWinHandle; + } - public IntPtr GotFocusWinHandle - { - get; - private set; - } - public IntPtr LostFocusWinHandle - { - get; - private set; - } + #endregion + + #region Properties + + public IntPtr GotFocusWinHandle + { + get; + private set; + } + public IntPtr LostFocusWinHandle + { + get; + private set; } - class WindowHookHandler + #endregion + } + + internal class WindowHookHandler + { + #region Members + + private IntPtr _windowHook; + private Win32Helper.HookProc _hookProc; + private ReentrantFlag _insideActivateEvent = new ReentrantFlag(); + + #endregion + + #region Constructors + + public WindowHookHandler() { - public WindowHookHandler() - { + } - } + #endregion - IntPtr _windowHook; - Win32Helper.HookProc _hookProc; - public void Attach() - { - _hookProc = new Win32Helper.HookProc(this.HookProc); - _windowHook = Win32Helper.SetWindowsHookEx( - Win32Helper.HookType.WH_CBT, - _hookProc, - IntPtr.Zero, - (int)Win32Helper.GetCurrentThreadId()); - } + #region Public Methods + public void Attach() + { + _hookProc = new Win32Helper.HookProc( this.HookProc ); + _windowHook = Win32Helper.SetWindowsHookEx( + Win32Helper.HookType.WH_CBT, + _hookProc, + IntPtr.Zero, + ( int )Win32Helper.GetCurrentThreadId() ); + } - public void Detach() - { - Win32Helper.UnhookWindowsHookEx(_windowHook); - } + public void Detach() + { + Win32Helper.UnhookWindowsHookEx( _windowHook ); + } - public int HookProc(int code, IntPtr wParam, IntPtr lParam) + public int HookProc( int code, IntPtr wParam, IntPtr lParam ) + { + if( code == Win32Helper.HCBT_SETFOCUS ) + { + if( FocusChanged != null ) + FocusChanged( this, new FocusChangeEventArgs( wParam, lParam ) ); + } + else if( code == Win32Helper.HCBT_ACTIVATE ) + { + if( _insideActivateEvent.CanEnter ) { - if (code == Win32Helper.HCBT_SETFOCUS) - { - if (FocusChanged != null) - FocusChanged(this, new FocusChangeEventArgs(wParam, lParam)); - } - else if (code == Win32Helper.HCBT_ACTIVATE) - { - if (_insideActivateEvent.CanEnter) - { - using (_insideActivateEvent.Enter()) - { - //if (Activate != null) - // Activate(this, new WindowActivateEventArgs(wParam)); - } - } - } - - - return Win32Helper.CallNextHookEx(_windowHook, code, wParam, lParam); + using( _insideActivateEvent.Enter() ) + { + //if (Activate != null) + // Activate(this, new WindowActivateEventArgs(wParam)); + } } + } - public event EventHandler FocusChanged; - - //public event EventHandler Activate; - ReentrantFlag _insideActivateEvent = new ReentrantFlag(); + return Win32Helper.CallNextHookEx( _windowHook, code, wParam, lParam ); } + + #endregion + + #region Events + + public event EventHandler FocusChanged; + //public event EventHandler Activate; + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/ActivateCommandLayoutItemFromLayoutModelConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/ActivateCommandLayoutItemFromLayoutModelConverter.cs index 01887b1b..f9225610 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/ActivateCommandLayoutItemFromLayoutModelConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/ActivateCommandLayoutItemFromLayoutModelConverter.cs @@ -15,37 +15,34 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Converters { - public class ActivateCommandLayoutItemFromLayoutModelConverter : IValueConverter + public class ActivateCommandLayoutItemFromLayoutModelConverter : IValueConverter + { + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - //when this converter is called layout could be constructing so many properties here are potentially not valid - var layoutModel = value as LayoutContent; - if (layoutModel == null) - return null; - if (layoutModel.Root == null) - return null; - if (layoutModel.Root.Manager == null) - return null; - - var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel); - if (layoutItemModel == null) - return Binding.DoNothing; - - return layoutItemModel.ActivateCommand; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } + //when this converter is called layout could be constructing so many properties here are potentially not valid + var layoutModel = value as LayoutContent; + if( layoutModel == null ) + return null; + if( layoutModel.Root == null ) + return null; + if( layoutModel.Root.Manager == null ) + return null; + + var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel( layoutModel ); + if( layoutItemModel == null ) + return Binding.DoNothing; + + return layoutItemModel.ActivateCommand; } + + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + throw new NotImplementedException(); + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorSideToAngleConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorSideToAngleConverter.cs index 1282a102..32af544c 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorSideToAngleConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorSideToAngleConverter.cs @@ -15,30 +15,27 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Converters { - [ValueConversion(typeof(AnchorSide), typeof(double))] - public class AnchorSideToAngleConverter : IValueConverter + [ValueConversion( typeof( AnchorSide ), typeof( double ) )] + public class AnchorSideToAngleConverter : IValueConverter + { + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - AnchorSide side = (AnchorSide)value; - if (side == AnchorSide.Left || - side == AnchorSide.Right) - return 90.0; - - return Binding.DoNothing; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } + AnchorSide side = ( AnchorSide )value; + if( side == AnchorSide.Left || + side == AnchorSide.Right ) + return 90.0; + + return Binding.DoNothing; + } + + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + throw new NotImplementedException(); } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorSideToOrientationConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorSideToOrientationConverter.cs index 8ab707cb..9a6e4e5f 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorSideToOrientationConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorSideToOrientationConverter.cs @@ -15,31 +15,28 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using System.Windows.Controls; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Converters { - [ValueConversion(typeof(AnchorSide), typeof(Orientation))] - public class AnchorSideToOrientationConverter : IValueConverter + [ValueConversion( typeof( AnchorSide ), typeof( Orientation ) )] + public class AnchorSideToOrientationConverter : IValueConverter + { + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - AnchorSide side = (AnchorSide)value; - if (side == AnchorSide.Left || - side == AnchorSide.Right) - return Orientation.Vertical; - - return Orientation.Horizontal; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } + AnchorSide side = ( AnchorSide )value; + if( side == AnchorSide.Left || + side == AnchorSide.Right ) + return Orientation.Vertical; + + return Orientation.Horizontal; + } + + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + throw new NotImplementedException(); } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorableContextMenuHideVisibilityConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorableContextMenuHideVisibilityConverter.cs new file mode 100644 index 00000000..7fc71514 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AnchorableContextMenuHideVisibilityConverter.cs @@ -0,0 +1,49 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Globalization; +using System.Linq; +using System.Windows; +using System.Windows.Data; + +namespace Xceed.Wpf.AvalonDock.Converters +{ + public class AnchorableContextMenuHideVisibilityConverter : IMultiValueConverter + { + public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture ) + { + if( ( values.Count() == 2 ) + && ( values[ 0 ] != DependencyProperty.UnsetValue ) + && ( values[ 1 ] != DependencyProperty.UnsetValue ) + && ( values[ 1 ] is bool ) ) + { + var canClose = ( bool )values[ 1 ]; + + return canClose ? Visibility.Collapsed : values[ 0 ]; + } + else + { + return values[ 0 ]; + } + } + + public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture ) + { + throw new NotImplementedException(); + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AutoHideCommandLayoutItemFromLayoutModelConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AutoHideCommandLayoutItemFromLayoutModelConverter.cs index ca89470f..137df6c5 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AutoHideCommandLayoutItemFromLayoutModelConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/AutoHideCommandLayoutItemFromLayoutModelConverter.cs @@ -15,38 +15,35 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using Xceed.Wpf.AvalonDock.Layout; using Xceed.Wpf.AvalonDock.Controls; namespace Xceed.Wpf.AvalonDock.Converters { - public class AutoHideCommandLayoutItemFromLayoutModelConverter : IValueConverter + public class AutoHideCommandLayoutItemFromLayoutModelConverter : IValueConverter + { + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - //when this converter is called layout could be constructing so many properties here are potentially not valid - var layoutModel = value as LayoutContent; - if (layoutModel == null) - return null; - if (layoutModel.Root == null) - return null; - if (layoutModel.Root.Manager == null) - return null; - - var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel) as LayoutAnchorableItem; - if (layoutItemModel == null) - return Binding.DoNothing; - - return layoutItemModel.AutoHideCommand; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } + //when this converter is called layout could be constructing so many properties here are potentially not valid + var layoutModel = value as LayoutContent; + if( layoutModel == null ) + return null; + if( layoutModel.Root == null ) + return null; + if( layoutModel.Root.Manager == null ) + return null; + + var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel( layoutModel ) as LayoutAnchorableItem; + if( layoutItemModel == null ) + return Binding.DoNothing; + + return layoutItemModel.AutoHideCommand; } + + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + throw new NotImplementedException(); + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/BoolToVisibilityConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/BoolToVisibilityConverter.cs index b93e66c7..971614a0 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/BoolToVisibilityConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/BoolToVisibilityConverter.cs @@ -15,78 +15,73 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using System.Windows; namespace Xceed.Wpf.AvalonDock.Converters { - [ValueConversion(typeof(bool), typeof(Visibility))] - public class BoolToVisibilityConverter : IValueConverter - { + [ValueConversion( typeof( bool ), typeof( Visibility ) )] + public class BoolToVisibilityConverter : IValueConverter + { - #region IValueConverter Members - /// - /// Converts a value. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// - /// A converted value. If the method returns null, the valid null value is used. - /// - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value is bool && targetType == typeof(Visibility)) - { - bool val = (bool)value; - if (val) - return Visibility.Visible; - else - if (parameter != null && parameter is Visibility) - return parameter; - else - return Visibility.Collapsed; - } - if (value == null) - { - if (parameter != null && parameter is Visibility) - return parameter; - else - return Visibility.Collapsed; - } - - return Visibility.Visible; - ///throw new ArgumentException("Invalid argument/return type. Expected argument: bool and return type: Visibility"); - } - - /// - /// Converts a value. - /// - /// The value that is produced by the binding target. - /// The type to convert to. - /// The converter parameter to use. - /// The culture to use in the converter. - /// - /// A converted value. If the method returns null, the valid null value is used. - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value is Visibility && targetType == typeof(bool)) - { - Visibility val = (Visibility)value; - if (val == Visibility.Visible) - return true; - else - return false; - } - throw new ArgumentException("Invalid argument/return type. Expected argument: Visibility and return type: bool"); - } - #endregion - } + #region IValueConverter Members + /// + /// Converts a value. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// + /// A converted value. If the method returns null, the valid null value is used. + /// + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + if( value is bool && targetType == typeof( Visibility ) ) + { + bool val = ( bool )value; + if( val ) + return Visibility.Visible; + else + if( parameter != null && parameter is Visibility ) + return parameter; + else + return Visibility.Collapsed; + } + if( value == null ) + { + if( parameter != null && parameter is Visibility ) + return parameter; + else + return Visibility.Collapsed; + } + return Visibility.Visible; + ///throw new ArgumentException("Invalid argument/return type. Expected argument: bool and return type: Visibility"); + } + /// + /// Converts a value. + /// + /// The value that is produced by the binding target. + /// The type to convert to. + /// The converter parameter to use. + /// The culture to use in the converter. + /// + /// A converted value. If the method returns null, the valid null value is used. + /// + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + if( value is Visibility && targetType == typeof( bool ) ) + { + Visibility val = ( Visibility )value; + if( val == Visibility.Visible ) + return true; + else + return false; + } + throw new ArgumentException( "Invalid argument/return type. Expected argument: Visibility and return type: bool" ); + } + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/HideCommandLayoutItemFromLayoutModelConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/HideCommandLayoutItemFromLayoutModelConverter.cs index d2207b14..318a08b6 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/HideCommandLayoutItemFromLayoutModelConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/HideCommandLayoutItemFromLayoutModelConverter.cs @@ -15,38 +15,35 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using Xceed.Wpf.AvalonDock.Layout; using Xceed.Wpf.AvalonDock.Controls; namespace Xceed.Wpf.AvalonDock.Converters { - public class HideCommandLayoutItemFromLayoutModelConverter : IValueConverter + public class HideCommandLayoutItemFromLayoutModelConverter : IValueConverter + { + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - //when this converter is called layout could be constructing so many properties here are potentially not valid - var layoutModel = value as LayoutContent; - if (layoutModel == null) - return null; - if (layoutModel.Root == null) - return null; - if (layoutModel.Root.Manager == null) - return null; - - var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel) as LayoutAnchorableItem; - if (layoutItemModel == null) - return Binding.DoNothing; - - return layoutItemModel.HideCommand; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } + //when this converter is called layout could be constructing so many properties here are potentially not valid + var layoutModel = value as LayoutContent; + if( layoutModel == null ) + return null; + if( layoutModel.Root == null ) + return null; + if( layoutModel.Root.Manager == null ) + return null; + + var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel( layoutModel ) as LayoutAnchorableItem; + if( layoutItemModel == null ) + return Binding.DoNothing; + + return layoutItemModel.HideCommand; } + + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + throw new NotImplementedException(); + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/InverseBoolToVisibilityConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/InverseBoolToVisibilityConverter.cs index 3dd40ef9..b129e989 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/InverseBoolToVisibilityConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/InverseBoolToVisibilityConverter.cs @@ -15,69 +15,64 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using System.Windows; namespace Xceed.Wpf.AvalonDock.Converters { - [ValueConversion(typeof(bool), typeof(Visibility))] - public class InverseBoolToVisibilityConverter : IValueConverter - { - - #region IValueConverter Members - /// - /// Converts a value. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// - /// A converted value. If the method returns null, the valid null value is used. - /// - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value is bool && targetType == typeof(Visibility)) - { - bool val = !(bool)value; - if (val) - return Visibility.Visible; - else - if (parameter != null && parameter is Visibility ) - return parameter; - else - return Visibility.Collapsed; - } - throw new ArgumentException("Invalid argument/return type. Expected argument: bool and return type: Visibility"); - } - - /// - /// Converts a value. - /// - /// The value that is produced by the binding target. - /// The type to convert to. - /// The converter parameter to use. - /// The culture to use in the converter. - /// - /// A converted value. If the method returns null, the valid null value is used. - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value is Visibility && targetType == typeof(bool)) - { - Visibility val = (Visibility)value; - if (val == Visibility.Visible) - return false; - else - return true; - } - throw new ArgumentException("Invalid argument/return type. Expected argument: Visibility and return type: bool"); - } - #endregion - } + [ValueConversion( typeof( bool ), typeof( Visibility ) )] + public class InverseBoolToVisibilityConverter : IValueConverter + { + #region IValueConverter Members + /// + /// Converts a value. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// + /// A converted value. If the method returns null, the valid null value is used. + /// + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + if( value is bool && targetType == typeof( Visibility ) ) + { + bool val = !( bool )value; + if( val ) + return Visibility.Visible; + else + if( parameter != null && parameter is Visibility ) + return parameter; + else + return Visibility.Collapsed; + } + throw new ArgumentException( "Invalid argument/return type. Expected argument: bool and return type: Visibility" ); + } + /// + /// Converts a value. + /// + /// The value that is produced by the binding target. + /// The type to convert to. + /// The converter parameter to use. + /// The culture to use in the converter. + /// + /// A converted value. If the method returns null, the valid null value is used. + /// + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + if( value is Visibility && targetType == typeof( bool ) ) + { + Visibility val = ( Visibility )value; + if( val == Visibility.Visible ) + return false; + else + return true; + } + throw new ArgumentException( "Invalid argument/return type. Expected argument: Visibility and return type: bool" ); + } + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/LayoutItemFromLayoutModelConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/LayoutItemFromLayoutModelConverter.cs index d80e342e..1753097c 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/LayoutItemFromLayoutModelConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/LayoutItemFromLayoutModelConverter.cs @@ -15,36 +15,33 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock.Converters { - public class LayoutItemFromLayoutModelConverter : IValueConverter + public class LayoutItemFromLayoutModelConverter : IValueConverter + { + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - var layoutModel = value as LayoutContent; - if (layoutModel == null) - return null; - if (layoutModel.Root == null) - return null; - if (layoutModel.Root.Manager == null) - return null; - - var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel); - if (layoutItemModel == null) - return Binding.DoNothing; - - return layoutItemModel; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } + var layoutModel = value as LayoutContent; + if( layoutModel == null ) + return null; + if( layoutModel.Root == null ) + return null; + if( layoutModel.Root.Manager == null ) + return null; + + var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel( layoutModel ); + if( layoutItemModel == null ) + return Binding.DoNothing; + + return layoutItemModel; } + + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + throw new NotImplementedException(); + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/NullToDoNothingConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/NullToDoNothingConverter.cs index 2fb9fa91..0944e155 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/NullToDoNothingConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/NullToDoNothingConverter.cs @@ -15,26 +15,23 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; namespace Xceed.Wpf.AvalonDock.Converters { - public class NullToDoNothingConverter : IValueConverter + public class NullToDoNothingConverter : IValueConverter + { + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value == null) - return Binding.DoNothing; - - return value; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } + if( value == null ) + return Binding.DoNothing; + + return value; + } + + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + throw new NotImplementedException(); } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/UriSourceToBitmapImageConverter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/UriSourceToBitmapImageConverter.cs index 7f076bfb..64018b94 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/UriSourceToBitmapImageConverter.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Converters/UriSourceToBitmapImageConverter.cs @@ -15,28 +15,25 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Data; using System.Windows.Media.Imaging; using System.Windows.Controls; namespace Xceed.Wpf.AvalonDock.Converters { - public class UriSourceToBitmapImageConverter : IValueConverter + public class UriSourceToBitmapImageConverter : IValueConverter + { + public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value == null) - return Binding.DoNothing; - //return (Uri)value; - return new Image() { Source = new BitmapImage((Uri)value) } ; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } + if( value == null ) + return Binding.DoNothing; + //return (Uri)value; + return new Image() { Source = new BitmapImage( ( Uri )value ) }; } + + public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) + { + throw new NotImplementedException(); + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DockingManager.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DockingManager.cs index 7c2b845e..2d91dddc 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DockingManager.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DockingManager.cs @@ -17,14 +17,11 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Controls; using System.Windows; using System.Windows.Markup; using System.ComponentModel; using System.Windows.Interop; -using System.Diagnostics; - using Xceed.Wpf.AvalonDock.Layout; using Xceed.Wpf.AvalonDock.Controls; using System.Windows.Input; @@ -32,3208 +29,3309 @@ using System.Collections; using System.Collections.Specialized; using System.Windows.Data; using System.Windows.Threading; -using Xceed.Wpf.AvalonDock.Commands; using Xceed.Wpf.AvalonDock.Themes; namespace Xceed.Wpf.AvalonDock { - [ContentProperty("Layout")] - [TemplatePart(Name="PART_AutoHideArea")] - public class DockingManager : Control, IOverlayWindowHost//, ILogicalChildrenContainer - { - static DockingManager() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(typeof(DockingManager))); - FocusableProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(false)); - HwndSource.DefaultAcquireHwndFocusInMenuMode = false; - } - - - public DockingManager() - { - Layout = new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) }; - - - this.Loaded += new RoutedEventHandler(DockingManager_Loaded); - this.Unloaded += new RoutedEventHandler(DockingManager_Unloaded); - } - - #region Layout - - /// - /// Layout Dependency Property - /// - public static readonly DependencyProperty LayoutProperty = - DependencyProperty.Register("Layout", typeof(LayoutRoot), typeof(DockingManager), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnLayoutChanged), - new CoerceValueCallback(CoerceLayoutValue))); - - /// - /// Gets or sets the Layout property. This dependency property - /// indicates layout tree. - /// - public LayoutRoot Layout - { - get { return (LayoutRoot)GetValue(LayoutProperty); } - set { SetValue(LayoutProperty, value); } - } - - /// - /// Handles changes to the Layout property. - /// - private static void OnLayoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnLayoutChanged(e.OldValue as LayoutRoot, e.NewValue as LayoutRoot); - } - - /// - /// Provides derived classes an opportunity to handle changes to the property. - /// - protected virtual void OnLayoutChanged(LayoutRoot oldLayout, LayoutRoot newLayout) - { - if (oldLayout != null) - { - oldLayout.PropertyChanged -= new PropertyChangedEventHandler(OnLayoutRootPropertyChanged); - oldLayout.Updated -= new EventHandler(OnLayoutRootUpdated); - } - - foreach (var fwc in _fwList.ToArray()) - { - fwc.KeepContentVisibleOnClose = true; - fwc.InternalClose(); - } - - _fwList.Clear(); - - DetachDocumentsSource(oldLayout, DocumentsSource); - DetachAnchorablesSource(oldLayout, AnchorablesSource); - - if (oldLayout != null && - oldLayout.Manager == this) - oldLayout.Manager = null; - - ClearLogicalChildrenList(); - DetachLayoutItems(); - - this.ActiveContent = null; - Layout.Manager = this; - - AttachLayoutItems(); - AttachDocumentsSource(newLayout, DocumentsSource); - AttachAnchorablesSource(newLayout, AnchorablesSource); - - if (IsLoaded) - { - LayoutRootPanel = CreateUIElementForModel(Layout.RootPanel) as LayoutPanelControl; - LeftSidePanel = CreateUIElementForModel(Layout.LeftSide) as LayoutAnchorSideControl; - TopSidePanel = CreateUIElementForModel(Layout.TopSide) as LayoutAnchorSideControl; - RightSidePanel = CreateUIElementForModel(Layout.RightSide) as LayoutAnchorSideControl; - BottomSidePanel = CreateUIElementForModel(Layout.BottomSide) as LayoutAnchorSideControl; - - foreach (var fw in Layout.FloatingWindows.ToArray()) - { - if (fw.IsValid) - _fwList.Add(CreateUIElementForModel(fw) as LayoutFloatingWindowControl); - } - - foreach (var fw in _fwList) - { - //fw.Owner = Window.GetWindow(this); - //fw.SetParentToMainWindowOf(this); - } - } - - - if (newLayout != null) - { - newLayout.PropertyChanged += new PropertyChangedEventHandler(OnLayoutRootPropertyChanged); - newLayout.Updated += new EventHandler(OnLayoutRootUpdated); - } - - if (LayoutChanged != null) - LayoutChanged(this, EventArgs.Empty); - - //if (Layout != null) - // Layout.CollectGarbage(); - - CommandManager.InvalidateRequerySuggested(); - } - - DispatcherOperation _setFocusAsyncOperation = null; - - void OnLayoutRootPropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == "RootPanel") - { - if (IsInitialized) - { - var layoutRootPanel = CreateUIElementForModel(Layout.RootPanel) as LayoutPanelControl; - LayoutRootPanel = layoutRootPanel; - } - } - else if (e.PropertyName == "ActiveContent") - { - if (Layout.ActiveContent != null) - { - //Debug.WriteLine(new StackTrace().ToString()); - - //set focus on active element only after a layout pass is completed - //it's possible that it is not yet visible in the visual tree - if (_setFocusAsyncOperation == null) - { - _setFocusAsyncOperation = Dispatcher.BeginInvoke(new Action(() => - { - if (Layout.ActiveContent != null) - FocusElementManager.SetFocusOnLastElement(Layout.ActiveContent); - _setFocusAsyncOperation = null; - }), DispatcherPriority.Background); - } - } - - if (!_insideInternalSetActiveContent) - ActiveContent = Layout.ActiveContent != null ? - Layout.ActiveContent.Content : null; - } - } - - void OnLayoutRootUpdated(object sender, EventArgs e) - { - CommandManager.InvalidateRequerySuggested(); - } - - - /// - /// Event fired when property changes - /// - public event EventHandler LayoutChanged; - - /// - /// Coerces the value. - /// - private static object CoerceLayoutValue(DependencyObject d, object value) - { - if (value == null) - return new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) }; - - ((DockingManager)d).OnLayoutChanging(value as LayoutRoot); - - return value; - } - - /// - /// Event fired when property is about to be changed - /// - public event EventHandler LayoutChanging; - - void OnLayoutChanging(LayoutRoot newLayout) - { - if (LayoutChanging != null) - LayoutChanging(this, EventArgs.Empty); - } - - - #region LayoutUpdateStrategy - - /// - /// LayoutUpdateStrategy Dependency Property - /// - public static readonly DependencyProperty LayoutUpdateStrategyProperty = - DependencyProperty.Register("LayoutUpdateStrategy", typeof(ILayoutUpdateStrategy), typeof(DockingManager), - new FrameworkPropertyMetadata((ILayoutUpdateStrategy)null)); - - /// - /// Gets or sets the LayoutUpdateStrategy property. This dependency property - /// indicates the strategy class to call when AvalonDock needs to positionate a LayoutAnchorable inside an existing layout. - /// - /// Sometimes it's impossible to automatically insert an anchorable in the layout without specifing the target parent pane. - /// Set this property to an object that will be asked to insert the anchorable to the desidered position. - public ILayoutUpdateStrategy LayoutUpdateStrategy - { - get { return (ILayoutUpdateStrategy)GetValue(LayoutUpdateStrategyProperty); } - set { SetValue(LayoutUpdateStrategyProperty, value); } - } - - #endregion - - - - #endregion - - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - - SetupAutoHideWindow(); - } - - protected override void OnInitialized(EventArgs e) - { - base.OnInitialized(e); - - if (Layout.Manager == this) - { - LayoutRootPanel = CreateUIElementForModel(Layout.RootPanel) as LayoutPanelControl; - LeftSidePanel = CreateUIElementForModel(Layout.LeftSide) as LayoutAnchorSideControl; - TopSidePanel = CreateUIElementForModel(Layout.TopSide) as LayoutAnchorSideControl; - RightSidePanel = CreateUIElementForModel(Layout.RightSide) as LayoutAnchorSideControl; - BottomSidePanel = CreateUIElementForModel(Layout.BottomSide) as LayoutAnchorSideControl; - } - - - } - - void DockingManager_Loaded(object sender, RoutedEventArgs e) - { - if (!DesignerProperties.GetIsInDesignMode(this)) - { - //load windows not already loaded! - foreach (var fw in Layout.FloatingWindows.Where(fw => !_fwList.Any(fwc => fwc.Model == fw))) - _fwList.Add(CreateUIElementForModel(fw) as LayoutFloatingWindowControl); - - //create the overlaywindow if it's possible - if (IsVisible) - CreateOverlayWindow(); - FocusElementManager.SetupFocusManagement(this); - } - } - - void DockingManager_Unloaded(object sender, RoutedEventArgs e) - { - - if (!DesignerProperties.GetIsInDesignMode(this)) - { - _autoHideWindowManager?.HideAutoWindow(); - - foreach (var fw in _fwList.ToArray()) - { - //fw.Owner = null; - fw.SetParentWindowToNull(); - fw.KeepContentVisibleOnClose = true; - fw.Close(); - } - - DestroyOverlayWindow(); - FocusElementManager.FinalizeFocusManagement(this); - } - } - - internal UIElement CreateUIElementForModel(ILayoutElement model) - { - if (model is LayoutPanel) - return new LayoutPanelControl(model as LayoutPanel); - if (model is LayoutAnchorablePaneGroup) - return new LayoutAnchorablePaneGroupControl(model as LayoutAnchorablePaneGroup); - if (model is LayoutDocumentPaneGroup) - return new LayoutDocumentPaneGroupControl(model as LayoutDocumentPaneGroup); - - if (model is LayoutAnchorSide) - { - var templateModelView = new LayoutAnchorSideControl(model as LayoutAnchorSide); - templateModelView.SetBinding(LayoutAnchorSideControl.TemplateProperty, new Binding("AnchorSideTemplate") { Source = this }); - return templateModelView; - } - if (model is LayoutAnchorGroup) - { - var templateModelView = new LayoutAnchorGroupControl(model as LayoutAnchorGroup); - templateModelView.SetBinding(LayoutAnchorGroupControl.TemplateProperty, new Binding("AnchorGroupTemplate") { Source = this }); - return templateModelView; - } - - if (model is LayoutDocumentPane) - { - var templateModelView = new LayoutDocumentPaneControl(model as LayoutDocumentPane); - templateModelView.SetBinding(LayoutDocumentPaneControl.StyleProperty, new Binding("DocumentPaneControlStyle") { Source = this }); - return templateModelView; - } - if (model is LayoutAnchorablePane) - { - var templateModelView = new LayoutAnchorablePaneControl(model as LayoutAnchorablePane); - templateModelView.SetBinding(LayoutAnchorablePaneControl.StyleProperty, new Binding("AnchorablePaneControlStyle") { Source = this }); - return templateModelView; - } - - if (model is LayoutAnchorableFloatingWindow) - { - if (DesignerProperties.GetIsInDesignMode(this)) - return null; - var modelFW = model as LayoutAnchorableFloatingWindow; - var newFW = new LayoutAnchorableFloatingWindowControl(modelFW) - { - //Owner = Window.GetWindow(this) - }; - newFW.SetParentToMainWindowOf(this); - - var paneForExtensions = modelFW.RootPanel.Children.OfType().FirstOrDefault(); - if (paneForExtensions != null) - { - //ensure that floating window position is inside current (or nearest) monitor - paneForExtensions.KeepInsideNearestMonitor(); - - newFW.Left = paneForExtensions.FloatingLeft; - newFW.Top = paneForExtensions.FloatingTop; - newFW.Width = paneForExtensions.FloatingWidth; - newFW.Height = paneForExtensions.FloatingHeight; - } - - newFW.ShowInTaskbar = false; - newFW.Show(); - - // Do not set the WindowState before showing or it will be lost - if (paneForExtensions != null && paneForExtensions.IsMaximized) - { - newFW.WindowState = WindowState.Maximized; - } - - return newFW; - } - - if (model is LayoutDocumentFloatingWindow) - { - if (DesignerProperties.GetIsInDesignMode(this)) - return null; - var modelFW = model as LayoutDocumentFloatingWindow; - var newFW = new LayoutDocumentFloatingWindowControl(modelFW) - { - //Owner = Window.GetWindow(this) - }; - newFW.SetParentToMainWindowOf(this); - - var paneForExtensions = modelFW.RootDocument; - if (paneForExtensions != null) - { - //ensure that floating window position is inside current (or nearest) monitor - paneForExtensions.KeepInsideNearestMonitor(); - - newFW.Left = paneForExtensions.FloatingLeft; - newFW.Top = paneForExtensions.FloatingTop; - newFW.Width = paneForExtensions.FloatingWidth; - newFW.Height = paneForExtensions.FloatingHeight; - } - - newFW.ShowInTaskbar = false; - newFW.Show(); - - // Do not set the WindowState before showing or it will be lost - if (paneForExtensions != null && paneForExtensions.IsMaximized) - { - newFW.WindowState = WindowState.Maximized; - } - - return newFW; - } - - if (model is LayoutDocument) - { - var templateModelView = new LayoutDocumentControl() { Model = model as LayoutDocument }; - return templateModelView; - } - - return null; - } - - - - #region DocumentPaneTemplate - - /// - /// DocumentPaneTemplate Dependency Property - /// - public static readonly DependencyProperty DocumentPaneTemplateProperty = - DependencyProperty.Register("DocumentPaneTemplate", typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((ControlTemplate)null, - new PropertyChangedCallback(OnDocumentPaneTemplateChanged))); - - /// - /// Gets or sets the DocumentPaneDataTemplate property. This dependency property - /// indicates . - /// - public ControlTemplate DocumentPaneTemplate - { - get { return (ControlTemplate)GetValue(DocumentPaneTemplateProperty); } - set { SetValue(DocumentPaneTemplateProperty, value); } - } - - /// - /// Handles changes to the DocumentPaneTemplate property. - /// - private static void OnDocumentPaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentPaneTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentPaneTemplate property. - /// - protected virtual void OnDocumentPaneTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion - - #region AnchorablePaneTemplate - - /// - /// AnchorablePaneTemplate Dependency Property - /// - public static readonly DependencyProperty AnchorablePaneTemplateProperty = - DependencyProperty.Register("AnchorablePaneTemplate", typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((ControlTemplate)null, - new PropertyChangedCallback(OnAnchorablePaneTemplateChanged))); - - /// - /// Gets or sets the AnchorablePaneTemplate property. This dependency property - /// indicates .... - /// - public ControlTemplate AnchorablePaneTemplate - { - get { return (ControlTemplate)GetValue(AnchorablePaneTemplateProperty); } - set { SetValue(AnchorablePaneTemplateProperty, value); } - } - - /// - /// Handles changes to the AnchorablePaneDataTemplate property. - /// - private static void OnAnchorablePaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnAnchorablePaneTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AnchorablePaneDataTemplate property. - /// - protected virtual void OnAnchorablePaneTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion - - #region AnchorSideTemplate - - /// - /// AnchorSideTemplate Dependency Property - /// - public static readonly DependencyProperty AnchorSideTemplateProperty = - DependencyProperty.Register("AnchorSideTemplate", typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((ControlTemplate)null)); - - /// - /// Gets or sets the AnchorSideTemplate property. This dependency property - /// indicates .... - /// - public ControlTemplate AnchorSideTemplate - { - get { return (ControlTemplate)GetValue(AnchorSideTemplateProperty); } - set { SetValue(AnchorSideTemplateProperty, value); } - } - - #endregion - - #region AnchorGroupTemplate - - /// - /// AnchorGroupTemplate Dependency Property - /// - public static readonly DependencyProperty AnchorGroupTemplateProperty = - DependencyProperty.Register("AnchorGroupTemplate", typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((ControlTemplate)null)); - - /// - /// Gets or sets the AnchorGroupTemplate property. This dependency property - /// indicates the template used to render the AnchorGroup control. - /// - public ControlTemplate AnchorGroupTemplate - { - get { return (ControlTemplate)GetValue(AnchorGroupTemplateProperty); } - set { SetValue(AnchorGroupTemplateProperty, value); } - } - - #endregion - - #region AnchorTemplate - - /// - /// AnchorTemplate Dependency Property - /// - public static readonly DependencyProperty AnchorTemplateProperty = - DependencyProperty.Register("AnchorTemplate", typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((ControlTemplate)null)); - - /// - /// Gets or sets the AnchorTemplate property. This dependency property - /// indicates .... - /// - public ControlTemplate AnchorTemplate - { - get { return (ControlTemplate)GetValue(AnchorTemplateProperty); } - set { SetValue(AnchorTemplateProperty, value); } - } - - #endregion - - #region DocumentPaneControlStyle - - /// - /// DocumentPaneControlStyle Dependency Property - /// - public static readonly DependencyProperty DocumentPaneControlStyleProperty = - DependencyProperty.Register("DocumentPaneControlStyle", typeof(Style), typeof(DockingManager), - new FrameworkPropertyMetadata((Style)null, - new PropertyChangedCallback(OnDocumentPaneControlStyleChanged))); - - /// - /// Gets or sets the DocumentPaneControlStyle property. This dependency property - /// indicates .... - /// - public Style DocumentPaneControlStyle - { - get { return (Style)GetValue(DocumentPaneControlStyleProperty); } - set { SetValue(DocumentPaneControlStyleProperty, value); } - } - - /// - /// Handles changes to the DocumentPaneControlStyle property. - /// - private static void OnDocumentPaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentPaneControlStyleChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentPaneControlStyle property. - /// - protected virtual void OnDocumentPaneControlStyleChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion - - #region AnchorablePaneControlStyle - - /// - /// AnchorablePaneControlStyle Dependency Property - /// - public static readonly DependencyProperty AnchorablePaneControlStyleProperty = - DependencyProperty.Register("AnchorablePaneControlStyle", typeof(Style), typeof(DockingManager), - new FrameworkPropertyMetadata((Style)null, - new PropertyChangedCallback(OnAnchorablePaneControlStyleChanged))); - - /// - /// Gets or sets the AnchorablePaneControlStyle property. This dependency property - /// indicates the style to apply to AnchorablePaneControl. - /// - public Style AnchorablePaneControlStyle - { - get { return (Style)GetValue(AnchorablePaneControlStyleProperty); } - set { SetValue(AnchorablePaneControlStyleProperty, value); } - } - - /// - /// Handles changes to the AnchorablePaneControlStyle property. - /// - private static void OnAnchorablePaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnAnchorablePaneControlStyleChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AnchorablePaneControlStyle property. - /// - protected virtual void OnAnchorablePaneControlStyleChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion - - #region DocumentHeaderTemplate - - /// - /// DocumentHeaderTemplate Dependency Property - /// - public static readonly DependencyProperty DocumentHeaderTemplateProperty = - DependencyProperty.Register("DocumentHeaderTemplate", typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, - new PropertyChangedCallback(OnDocumentHeaderTemplateChanged), - new CoerceValueCallback(CoerceDocumentHeaderTemplateValue))); - - /// - /// Gets or sets the DocumentHeaderTemplate property. This dependency property - /// indicates data template to use for document header. - /// - public DataTemplate DocumentHeaderTemplate - { - get { return (DataTemplate)GetValue(DocumentHeaderTemplateProperty); } - set { SetValue(DocumentHeaderTemplateProperty, value); } - } - - /// - /// Handles changes to the DocumentHeaderTemplate property. - /// - private static void OnDocumentHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentHeaderTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplate property. - /// - protected virtual void OnDocumentHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// - /// Coerces the DocumentHeaderTemplate value. - /// - private static object CoerceDocumentHeaderTemplateValue(DependencyObject d, object value) - { - if (value != null && - d.GetValue(DocumentHeaderTemplateSelectorProperty) != null) - return null; - return value; - } - - #endregion - - #region DocumentHeaderTemplateSelector - - /// - /// DocumentHeaderTemplateSelector Dependency Property - /// - public static readonly DependencyProperty DocumentHeaderTemplateSelectorProperty = - DependencyProperty.Register("DocumentHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null, - new PropertyChangedCallback(OnDocumentHeaderTemplateSelectorChanged), - new CoerceValueCallback(CoerceDocumentHeaderTemplateSelectorValue))); - - /// - /// Gets or sets the DocumentHeaderTemplateSelector property. This dependency property - /// indicates the template selector that is used when selcting the data template for the header. - /// - public DataTemplateSelector DocumentHeaderTemplateSelector - { - get { return (DataTemplateSelector)GetValue(DocumentHeaderTemplateSelectorProperty); } - set { SetValue(DocumentHeaderTemplateSelectorProperty, value); } - } - - /// - /// Handles changes to the DocumentHeaderTemplateSelector property. - /// - private static void OnDocumentHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentHeaderTemplateSelectorChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplateSelector property. - /// - protected virtual void OnDocumentHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null && - DocumentHeaderTemplate != null) - DocumentHeaderTemplate = null; - - if (DocumentPaneMenuItemHeaderTemplateSelector == null) - DocumentPaneMenuItemHeaderTemplateSelector = DocumentHeaderTemplateSelector; - - } - - /// - /// Coerces the DocumentHeaderTemplateSelector value. - /// - private static object CoerceDocumentHeaderTemplateSelectorValue(DependencyObject d, object value) - { - return value; - } - - #endregion - - #region DocumentTitleTemplate - - /// - /// DocumentTitleTemplate Dependency Property - /// - public static readonly DependencyProperty DocumentTitleTemplateProperty = - DependencyProperty.Register("DocumentTitleTemplate", typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, - new PropertyChangedCallback(OnDocumentTitleTemplateChanged), - new CoerceValueCallback(CoerceDocumentTitleTemplateValue))); - - /// - /// Gets or sets the DocumentTitleTemplate property. This dependency property - /// indicates the datatemplate to use when creating the title for a document. - /// - public DataTemplate DocumentTitleTemplate - { - get { return (DataTemplate)GetValue(DocumentTitleTemplateProperty); } - set { SetValue(DocumentTitleTemplateProperty, value); } - } - - /// - /// Handles changes to the DocumentTitleTemplate property. - /// - private static void OnDocumentTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentTitleTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplate property. - /// - protected virtual void OnDocumentTitleTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// - /// Coerces the DocumentTitleTemplate value. - /// - private static object CoerceDocumentTitleTemplateValue(DependencyObject d, object value) - { - if (value != null && - d.GetValue(DocumentTitleTemplateSelectorProperty) != null) - return null; - - return value; - } - - #endregion - - #region DocumentTitleTemplateSelector - - /// - /// DocumentTitleTemplateSelector Dependency Property - /// - public static readonly DependencyProperty DocumentTitleTemplateSelectorProperty = - DependencyProperty.Register("DocumentTitleTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null, - new PropertyChangedCallback(OnDocumentTitleTemplateSelectorChanged), - new CoerceValueCallback(CoerceDocumentTitleTemplateSelectorValue))); - - /// - /// Gets or sets the DocumentTitleTemplateSelector property. This dependency property - /// indicates the data template selector to use when creating the data template for the title. - /// - public DataTemplateSelector DocumentTitleTemplateSelector - { - get { return (DataTemplateSelector)GetValue(DocumentTitleTemplateSelectorProperty); } - set { SetValue(DocumentTitleTemplateSelectorProperty, value); } - } - - /// - /// Handles changes to the DocumentTitleTemplateSelector property. - /// - private static void OnDocumentTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentTitleTemplateSelectorChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplateSelector property. - /// - protected virtual void OnDocumentTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null) - DocumentTitleTemplate = null; - } - - /// - /// Coerces the DocumentTitleTemplateSelector value. - /// - private static object CoerceDocumentTitleTemplateSelectorValue(DependencyObject d, object value) - { - return value; - } - - #endregion - - #region AnchorableTitleTemplate - - /// - /// AnchorableTitleTemplate Dependency Property - /// - public static readonly DependencyProperty AnchorableTitleTemplateProperty = - DependencyProperty.Register("AnchorableTitleTemplate", typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, - new PropertyChangedCallback(OnAnchorableTitleTemplateChanged), - new CoerceValueCallback(CoerceAnchorableTitleTemplateValue))); - - /// - /// Gets or sets the AnchorableTitleTemplate property. This dependency property - /// indicates the data template to use for anchorables title. - /// - public DataTemplate AnchorableTitleTemplate - { - get { return (DataTemplate)GetValue(AnchorableTitleTemplateProperty); } - set { SetValue(AnchorableTitleTemplateProperty, value); } - } - - /// - /// Handles changes to the AnchorableTitleTemplate property. - /// - private static void OnAnchorableTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnAnchorableTitleTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplate property. - /// - protected virtual void OnAnchorableTitleTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// - /// Coerces the AnchorableTitleTemplate value. - /// - private static object CoerceAnchorableTitleTemplateValue(DependencyObject d, object value) - { - if (value != null && - d.GetValue(AnchorableTitleTemplateSelectorProperty) != null) - return null; - return value; - } - - #endregion - - #region AnchorableTitleTemplateSelector - - /// - /// AnchorableTitleTemplateSelector Dependency Property - /// - public static readonly DependencyProperty AnchorableTitleTemplateSelectorProperty = - DependencyProperty.Register("AnchorableTitleTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null, - new PropertyChangedCallback(OnAnchorableTitleTemplateSelectorChanged))); - - /// - /// Gets or sets the AnchorableTitleTemplateSelector property. This dependency property - /// indicates selctor to use when selecting data template for the title of anchorables. - /// - public DataTemplateSelector AnchorableTitleTemplateSelector - { - get { return (DataTemplateSelector)GetValue(AnchorableTitleTemplateSelectorProperty); } - set { SetValue(AnchorableTitleTemplateSelectorProperty, value); } - } - - /// - /// Handles changes to the AnchorableTitleTemplateSelector property. - /// - private static void OnAnchorableTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnAnchorableTitleTemplateSelectorChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplateSelector property. - /// - protected virtual void OnAnchorableTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null && - AnchorableTitleTemplate != null) - AnchorableTitleTemplate = null; - } - - #endregion - - #region AnchorableHeaderTemplate - - /// - /// AnchorableHeaderTemplate Dependency Property - /// - public static readonly DependencyProperty AnchorableHeaderTemplateProperty = - DependencyProperty.Register("AnchorableHeaderTemplate", typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, - new PropertyChangedCallback(OnAnchorableHeaderTemplateChanged), - new CoerceValueCallback(CoerceAnchorableHeaderTemplateValue))); - - /// - /// Gets or sets the AnchorableHeaderTemplate property. This dependency property - /// indicates the data template to use for anchorable templates. - /// - public DataTemplate AnchorableHeaderTemplate - { - get { return (DataTemplate)GetValue(AnchorableHeaderTemplateProperty); } - set { SetValue(AnchorableHeaderTemplateProperty, value); } - } - - /// - /// Handles changes to the AnchorableHeaderTemplate property. - /// - private static void OnAnchorableHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnAnchorableHeaderTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplate property. - /// - protected virtual void OnAnchorableHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// - /// Coerces the AnchorableHeaderTemplate value. - /// - private static object CoerceAnchorableHeaderTemplateValue(DependencyObject d, object value) - { - if (value != null && - d.GetValue(AnchorableHeaderTemplateSelectorProperty) != null) - return null; - - return value; - } - - #endregion - - #region AnchorableHeaderTemplateSelector - - /// - /// AnchorableHeaderTemplateSelector Dependency Property - /// - public static readonly DependencyProperty AnchorableHeaderTemplateSelectorProperty = - DependencyProperty.Register("AnchorableHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null, - new PropertyChangedCallback(OnAnchorableHeaderTemplateSelectorChanged))); - - /// - /// Gets or sets the AnchorableHeaderTemplateSelector property. This dependency property - /// indicates the selector to use when selecting the data template for anchorable headers. - /// - public DataTemplateSelector AnchorableHeaderTemplateSelector - { - get { return (DataTemplateSelector)GetValue(AnchorableHeaderTemplateSelectorProperty); } - set { SetValue(AnchorableHeaderTemplateSelectorProperty, value); } - } - - /// - /// Handles changes to the AnchorableHeaderTemplateSelector property. - /// - private static void OnAnchorableHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnAnchorableHeaderTemplateSelectorChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplateSelector property. - /// - protected virtual void OnAnchorableHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null) - AnchorableHeaderTemplate = null; - } - - #endregion - - protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e) - { - //if (e.NewFocus is Grid) - // Trace.WriteLine(string.Format("DockingManager.OnGotKeyboardFocus({0})", e.NewFocus)); - base.OnGotKeyboardFocus(e); - } - - protected override void OnPreviewGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e) - { - Trace.WriteLine( string.Format( "DockingManager.OnPreviewGotKeyboardFocus({0})", e.NewFocus ) ); - - base.OnPreviewGotKeyboardFocus(e); - } - - protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e) - { - Trace.WriteLine( string.Format( "DockingManager.OnPreviewLostKeyboardFocus({0})", e.OldFocus ) ); - base.OnPreviewLostKeyboardFocus(e); - } - - protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) - { - Trace.WriteLine( string.Format( "DockingManager.OnMouseLeftButtonDown([{0}])", e.GetPosition( this ) ) ); - base.OnMouseLeftButtonDown(e); - } - - protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e) - { - //Trace.WriteLine(string.Format("DockingManager.OnMouseMove([{0}])", e.GetPosition(this))); - base.OnMouseMove(e); - } - - - - #region LayoutRootPanel - - /// - /// LayoutRootPanel Dependency Property - /// - public static readonly DependencyProperty LayoutRootPanelProperty = - DependencyProperty.Register("LayoutRootPanel", typeof(LayoutPanelControl), typeof(DockingManager), - new FrameworkPropertyMetadata((LayoutPanelControl)null, - new PropertyChangedCallback(OnLayoutRootPanelChanged))); - - /// - /// Gets or sets the LayoutRootPanel property. This dependency property - /// indicates the layout panel control which is attached to the Layout.Root property. - /// - public LayoutPanelControl LayoutRootPanel - { - get { return (LayoutPanelControl)GetValue(LayoutRootPanelProperty); } - set { SetValue(LayoutRootPanelProperty, value); } - } - - /// - /// Handles changes to the LayoutRootPanel property. - /// - private static void OnLayoutRootPanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnLayoutRootPanelChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the LayoutRootPanel property. - /// - protected virtual void OnLayoutRootPanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion - - #region RightSidePanel - - /// - /// RightSidePanel Dependency Property - /// - public static readonly DependencyProperty RightSidePanelProperty = - DependencyProperty.Register("RightSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager), - new FrameworkPropertyMetadata((LayoutAnchorSideControl)null, - new PropertyChangedCallback(OnRightSidePanelChanged))); - - /// - /// Gets or sets the RightSidePanel property. This dependency property - /// indicates right side anchor panel. - /// - public LayoutAnchorSideControl RightSidePanel - { - get { return (LayoutAnchorSideControl)GetValue(RightSidePanelProperty); } - set { SetValue(RightSidePanelProperty, value); } - } - - /// - /// Handles changes to the RightSidePanel property. - /// - private static void OnRightSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnRightSidePanelChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the RightSidePanel property. - /// - protected virtual void OnRightSidePanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion - - #region LeftSidePanel - - /// - /// LeftSidePanel Dependency Property - /// - public static readonly DependencyProperty LeftSidePanelProperty = - DependencyProperty.Register("LeftSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager), - new FrameworkPropertyMetadata((LayoutAnchorSideControl)null, - new PropertyChangedCallback(OnLeftSidePanelChanged))); - - /// - /// Gets or sets the LeftSidePanel property. This dependency property - /// indicates the left side panel control. - /// - public LayoutAnchorSideControl LeftSidePanel - { - get { return (LayoutAnchorSideControl)GetValue(LeftSidePanelProperty); } - set { SetValue(LeftSidePanelProperty, value); } - } - - /// - /// Handles changes to the LeftSidePanel property. - /// - private static void OnLeftSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnLeftSidePanelChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the LeftSidePanel property. - /// - protected virtual void OnLeftSidePanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion - - #region TopSidePanel - - /// - /// TopSidePanel Dependency Property - /// - public static readonly DependencyProperty TopSidePanelProperty = - DependencyProperty.Register("TopSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager), - new FrameworkPropertyMetadata((LayoutAnchorSideControl)null, - new PropertyChangedCallback(OnTopSidePanelChanged))); - - /// - /// Gets or sets the TopSidePanel property. This dependency property - /// indicates top side control panel. - /// - public LayoutAnchorSideControl TopSidePanel - { - get { return (LayoutAnchorSideControl)GetValue(TopSidePanelProperty); } - set { SetValue(TopSidePanelProperty, value); } - } - - /// - /// Handles changes to the TopSidePanel property. - /// - private static void OnTopSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnTopSidePanelChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the TopSidePanel property. - /// - protected virtual void OnTopSidePanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion - - #region BottomSidePanel - - /// - /// BottomSidePanel Dependency Property - /// - public static readonly DependencyProperty BottomSidePanelProperty = - DependencyProperty.Register("BottomSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager), - new FrameworkPropertyMetadata((LayoutAnchorSideControl)null, - new PropertyChangedCallback(OnBottomSidePanelChanged))); - - /// - /// Gets or sets the BottomSidePanel property. This dependency property - /// indicates bottom side panel control. - /// - public LayoutAnchorSideControl BottomSidePanel - { - get { return (LayoutAnchorSideControl)GetValue(BottomSidePanelProperty); } - set { SetValue(BottomSidePanelProperty, value); } - } - - /// - /// Handles changes to the BottomSidePanel property. - /// - private static void OnBottomSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnBottomSidePanelChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the BottomSidePanel property. - /// - protected virtual void OnBottomSidePanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion - - - #region LogicalChildren - - List _logicalChildren = new List(); - - protected override System.Collections.IEnumerator LogicalChildren - { - get - { - return _logicalChildren.Select(ch => ch.GetValueOrDefault()).GetEnumerator(); - } - } - - - internal void InternalAddLogicalChild(object element) - { - //System.Diagnostics.Trace.WriteLine("[{0}]InternalAddLogicalChild({1})", this, element); + [ContentProperty( "Layout" )] + [TemplatePart( Name = "PART_AutoHideArea" )] + public class DockingManager : Control, IOverlayWindowHost//, ILogicalChildrenContainer + { + #region Members + + private ResourceDictionary currentThemeResourceDictionary; // = null + private AutoHideWindowManager _autoHideWindowManager; + private FrameworkElement _autohideArea; + private List _fwList = new List(); + private OverlayWindow _overlayWindow = null; + private List _areas = null; + private bool _insideInternalSetActiveContent = false; + private List _layoutItems = new List(); + private bool _suspendLayoutItemCreation = false; + private DispatcherOperation _collectLayoutItemsOperations = null; + private NavigatorWindow _navigatorWindow = null; + + internal bool SuspendDocumentsSourceBinding = false; + internal bool SuspendAnchorablesSourceBinding = false; + + #endregion + + #region Constructors + + static DockingManager() + { + DefaultStyleKeyProperty.OverrideMetadata( typeof( DockingManager ), new FrameworkPropertyMetadata( typeof( DockingManager ) ) ); + FocusableProperty.OverrideMetadata( typeof( DockingManager ), new FrameworkPropertyMetadata( false ) ); + HwndSource.DefaultAcquireHwndFocusInMenuMode = false; + } + + + public DockingManager() + { + +#if !VS2008 + Layout = new LayoutRoot() { RootPanel = new LayoutPanel( new LayoutDocumentPaneGroup( new LayoutDocumentPane() ) ) }; +#else + this.SetCurrentValue( DockingManager.LayoutProperty, new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) } ); +#endif + this.Loaded += new RoutedEventHandler( DockingManager_Loaded ); + this.Unloaded += new RoutedEventHandler( DockingManager_Unloaded ); + } + + #endregion + + #region Properties + + #region Layout + + /// + /// Layout Dependency Property + /// + public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register( "Layout", typeof( LayoutRoot ), typeof( DockingManager ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnLayoutChanged ), new CoerceValueCallback( CoerceLayoutValue ) ) ); + + /// + /// Gets or sets the Layout property. This dependency property + /// indicates layout tree. + /// + public LayoutRoot Layout + { + get + { + return ( LayoutRoot )GetValue( LayoutProperty ); + } + set + { + SetValue( LayoutProperty, value ); + } + } + + /// + /// Coerces the value. + /// + private static object CoerceLayoutValue( DependencyObject d, object value ) + { + if( value == null ) + return new LayoutRoot() { RootPanel = new LayoutPanel( new LayoutDocumentPaneGroup( new LayoutDocumentPane() ) ) }; + + ( ( DockingManager )d ).OnLayoutChanging( value as LayoutRoot ); + + return value; + } + + /// + /// Handles changes to the Layout property. + /// + private static void OnLayoutChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnLayoutChanged( e.OldValue as LayoutRoot, e.NewValue as LayoutRoot ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the property. + /// + protected virtual void OnLayoutChanged( LayoutRoot oldLayout, LayoutRoot newLayout ) + { + if( oldLayout != null ) + { + oldLayout.PropertyChanged -= new PropertyChangedEventHandler( OnLayoutRootPropertyChanged ); + oldLayout.Updated -= new EventHandler( OnLayoutRootUpdated ); + } + + foreach( var fwc in _fwList.ToArray() ) + { + fwc.KeepContentVisibleOnClose = true; + fwc.InternalClose(); + } + + _fwList.Clear(); + + DetachDocumentsSource( oldLayout, DocumentsSource ); + DetachAnchorablesSource( oldLayout, AnchorablesSource ); + + if( oldLayout != null && + oldLayout.Manager == this ) + oldLayout.Manager = null; + + ClearLogicalChildrenList(); + DetachLayoutItems(); + + ActiveContent = null; + Layout.Manager = this; + + AttachLayoutItems(); + AttachDocumentsSource( newLayout, DocumentsSource ); + AttachAnchorablesSource( newLayout, AnchorablesSource ); + + if( IsLoaded ) + { + LayoutRootPanel = CreateUIElementForModel( Layout.RootPanel ) as LayoutPanelControl; + LeftSidePanel = CreateUIElementForModel( Layout.LeftSide ) as LayoutAnchorSideControl; + TopSidePanel = CreateUIElementForModel( Layout.TopSide ) as LayoutAnchorSideControl; + RightSidePanel = CreateUIElementForModel( Layout.RightSide ) as LayoutAnchorSideControl; + BottomSidePanel = CreateUIElementForModel( Layout.BottomSide ) as LayoutAnchorSideControl; + + foreach( var fw in Layout.FloatingWindows.ToArray() ) + { + if( fw.IsValid ) + _fwList.Add( CreateUIElementForModel( fw ) as LayoutFloatingWindowControl ); + } + + foreach( var fw in _fwList ) + { + //fw.Owner = Window.GetWindow(this); + //fw.SetParentToMainWindowOf(this); + } + } + + + if( newLayout != null ) + { + newLayout.PropertyChanged += new PropertyChangedEventHandler( OnLayoutRootPropertyChanged ); + newLayout.Updated += new EventHandler( OnLayoutRootUpdated ); + } + + if( LayoutChanged != null ) + LayoutChanged( this, EventArgs.Empty ); + + //if (Layout != null) + // Layout.CollectGarbage(); + + CommandManager.InvalidateRequerySuggested(); + } + + #endregion + + #region LayoutUpdateStrategy + + /// + /// LayoutUpdateStrategy Dependency Property + /// + public static readonly DependencyProperty LayoutUpdateStrategyProperty = DependencyProperty.Register( "LayoutUpdateStrategy", typeof( ILayoutUpdateStrategy ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( ILayoutUpdateStrategy )null ) ); + + /// + /// Gets or sets the LayoutUpdateStrategy property. This dependency property + /// indicates the strategy class to call when AvalonDock needs to positionate a LayoutAnchorable inside an existing layout. + /// + /// Sometimes it's impossible to automatically insert an anchorable in the layout without specifing the target parent pane. + /// Set this property to an object that will be asked to insert the anchorable to the desidered position. + public ILayoutUpdateStrategy LayoutUpdateStrategy + { + get + { + return ( ILayoutUpdateStrategy )GetValue( LayoutUpdateStrategyProperty ); + } + set + { + SetValue( LayoutUpdateStrategyProperty, value ); + } + } + + #endregion + + #region DocumentPaneTemplate + + /// + /// DocumentPaneTemplate Dependency Property + /// + public static readonly DependencyProperty DocumentPaneTemplateProperty = DependencyProperty.Register( "DocumentPaneTemplate", typeof( ControlTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( ControlTemplate )null, new PropertyChangedCallback( OnDocumentPaneTemplateChanged ) ) ); + + /// + /// Gets or sets the DocumentPaneDataTemplate property. This dependency property + /// indicates . + /// + public ControlTemplate DocumentPaneTemplate + { + get + { + return ( ControlTemplate )GetValue( DocumentPaneTemplateProperty ); + } + set + { + SetValue( DocumentPaneTemplateProperty, value ); + } + } + + /// + /// Handles changes to the DocumentPaneTemplate property. + /// + private static void OnDocumentPaneTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentPaneTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentPaneTemplate property. + /// + protected virtual void OnDocumentPaneTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + } + + #endregion + + #region AnchorablePaneTemplate + + /// + /// AnchorablePaneTemplate Dependency Property + /// + public static readonly DependencyProperty AnchorablePaneTemplateProperty = DependencyProperty.Register( "AnchorablePaneTemplate", typeof( ControlTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( ControlTemplate )null, new PropertyChangedCallback( OnAnchorablePaneTemplateChanged ) ) ); + + /// + /// Gets or sets the AnchorablePaneTemplate property. This dependency property + /// indicates .... + /// + public ControlTemplate AnchorablePaneTemplate + { + get + { + return ( ControlTemplate )GetValue( AnchorablePaneTemplateProperty ); + } + set + { + SetValue( AnchorablePaneTemplateProperty, value ); + } + } + + /// + /// Handles changes to the AnchorablePaneDataTemplate property. + /// + private static void OnAnchorablePaneTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnAnchorablePaneTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AnchorablePaneDataTemplate property. + /// + protected virtual void OnAnchorablePaneTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + } + + #endregion + + #region AnchorSideTemplate + + /// + /// AnchorSideTemplate Dependency Property + /// + public static readonly DependencyProperty AnchorSideTemplateProperty = DependencyProperty.Register( "AnchorSideTemplate", typeof( ControlTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( ControlTemplate )null ) ); + + /// + /// Gets or sets the AnchorSideTemplate property. This dependency property + /// indicates .... + /// + public ControlTemplate AnchorSideTemplate + { + get + { + return ( ControlTemplate )GetValue( AnchorSideTemplateProperty ); + } + set + { + SetValue( AnchorSideTemplateProperty, value ); + } + } + + #endregion + + #region AnchorGroupTemplate + + /// + /// AnchorGroupTemplate Dependency Property + /// + public static readonly DependencyProperty AnchorGroupTemplateProperty = DependencyProperty.Register( "AnchorGroupTemplate", typeof( ControlTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( ControlTemplate )null ) ); + + /// + /// Gets or sets the AnchorGroupTemplate property. This dependency property + /// indicates the template used to render the AnchorGroup control. + /// + public ControlTemplate AnchorGroupTemplate + { + get + { + return ( ControlTemplate )GetValue( AnchorGroupTemplateProperty ); + } + set + { + SetValue( AnchorGroupTemplateProperty, value ); + } + } + + #endregion + + #region AnchorTemplate + + /// + /// AnchorTemplate Dependency Property + /// + public static readonly DependencyProperty AnchorTemplateProperty = DependencyProperty.Register( "AnchorTemplate", typeof( ControlTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( ControlTemplate )null ) ); + + /// + /// Gets or sets the AnchorTemplate property. This dependency property + /// indicates .... + /// + public ControlTemplate AnchorTemplate + { + get + { + return ( ControlTemplate )GetValue( AnchorTemplateProperty ); + } + set + { + SetValue( AnchorTemplateProperty, value ); + } + } + + #endregion + + #region DocumentPaneControlStyle + + /// + /// DocumentPaneControlStyle Dependency Property + /// + public static readonly DependencyProperty DocumentPaneControlStyleProperty = DependencyProperty.Register( "DocumentPaneControlStyle", typeof( Style ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnDocumentPaneControlStyleChanged ) ) ); + + /// + /// Gets or sets the DocumentPaneControlStyle property. This dependency property + /// indicates .... + /// + public Style DocumentPaneControlStyle + { + get + { + return ( Style )GetValue( DocumentPaneControlStyleProperty ); + } + set + { + SetValue( DocumentPaneControlStyleProperty, value ); + } + } + + /// + /// Handles changes to the DocumentPaneControlStyle property. + /// + private static void OnDocumentPaneControlStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentPaneControlStyleChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentPaneControlStyle property. + /// + protected virtual void OnDocumentPaneControlStyleChanged( DependencyPropertyChangedEventArgs e ) + { + } + + #endregion + + #region AnchorablePaneControlStyle + + /// + /// AnchorablePaneControlStyle Dependency Property + /// + public static readonly DependencyProperty AnchorablePaneControlStyleProperty = DependencyProperty.Register( "AnchorablePaneControlStyle", typeof( Style ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnAnchorablePaneControlStyleChanged ) ) ); + + /// + /// Gets or sets the AnchorablePaneControlStyle property. This dependency property + /// indicates the style to apply to AnchorablePaneControl. + /// + public Style AnchorablePaneControlStyle + { + get + { + return ( Style )GetValue( AnchorablePaneControlStyleProperty ); + } + set + { + SetValue( AnchorablePaneControlStyleProperty, value ); + } + } + + /// + /// Handles changes to the AnchorablePaneControlStyle property. + /// + private static void OnAnchorablePaneControlStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnAnchorablePaneControlStyleChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AnchorablePaneControlStyle property. + /// + protected virtual void OnAnchorablePaneControlStyleChanged( DependencyPropertyChangedEventArgs e ) + { + } + + #endregion + + #region DocumentHeaderTemplate + + /// + /// DocumentHeaderTemplate Dependency Property + /// + public static readonly DependencyProperty DocumentHeaderTemplateProperty = DependencyProperty.Register( "DocumentHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentHeaderTemplateChanged ), new CoerceValueCallback( CoerceDocumentHeaderTemplateValue ) ) ); + + /// + /// Gets or sets the DocumentHeaderTemplate property. This dependency property + /// indicates data template to use for document header. + /// + public DataTemplate DocumentHeaderTemplate + { + get + { + return ( DataTemplate )GetValue( DocumentHeaderTemplateProperty ); + } + set + { + SetValue( DocumentHeaderTemplateProperty, value ); + } + } + + /// + /// Handles changes to the DocumentHeaderTemplate property. + /// + private static void OnDocumentHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentHeaderTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplate property. + /// + protected virtual void OnDocumentHeaderTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + } + + /// + /// Coerces the DocumentHeaderTemplate value. + /// + private static object CoerceDocumentHeaderTemplateValue( DependencyObject d, object value ) + { + if( value != null && + d.GetValue( DocumentHeaderTemplateSelectorProperty ) != null ) + return null; + return value; + } + + #endregion + + #region DocumentHeaderTemplateSelector + + /// + /// DocumentHeaderTemplateSelector Dependency Property + /// + public static readonly DependencyProperty DocumentHeaderTemplateSelectorProperty = DependencyProperty.Register( "DocumentHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentHeaderTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentHeaderTemplateSelectorValue ) ) ); + + /// + /// Gets or sets the DocumentHeaderTemplateSelector property. This dependency property + /// indicates the template selector that is used when selcting the data template for the header. + /// + public DataTemplateSelector DocumentHeaderTemplateSelector + { + get + { + return ( DataTemplateSelector )GetValue( DocumentHeaderTemplateSelectorProperty ); + } + set + { + SetValue( DocumentHeaderTemplateSelectorProperty, value ); + } + } + + /// + /// Handles changes to the DocumentHeaderTemplateSelector property. + /// + private static void OnDocumentHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentHeaderTemplateSelectorChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplateSelector property. + /// + protected virtual void OnDocumentHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.NewValue != null && + DocumentHeaderTemplate != null ) + DocumentHeaderTemplate = null; + + if( DocumentPaneMenuItemHeaderTemplateSelector == null ) + DocumentPaneMenuItemHeaderTemplateSelector = DocumentHeaderTemplateSelector; + + } + + /// + /// Coerces the DocumentHeaderTemplateSelector value. + /// + private static object CoerceDocumentHeaderTemplateSelectorValue( DependencyObject d, object value ) + { + return value; + } + + #endregion + + #region DocumentTitleTemplate + + /// + /// DocumentTitleTemplate Dependency Property + /// + public static readonly DependencyProperty DocumentTitleTemplateProperty = DependencyProperty.Register( "DocumentTitleTemplate", typeof( DataTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentTitleTemplateChanged ), new CoerceValueCallback( CoerceDocumentTitleTemplateValue ) ) ); + + /// + /// Gets or sets the DocumentTitleTemplate property. This dependency property + /// indicates the datatemplate to use when creating the title for a document. + /// + public DataTemplate DocumentTitleTemplate + { + get + { + return ( DataTemplate )GetValue( DocumentTitleTemplateProperty ); + } + set + { + SetValue( DocumentTitleTemplateProperty, value ); + } + } + + /// + /// Handles changes to the DocumentTitleTemplate property. + /// + private static void OnDocumentTitleTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentTitleTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplate property. + /// + protected virtual void OnDocumentTitleTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + } + + /// + /// Coerces the DocumentTitleTemplate value. + /// + private static object CoerceDocumentTitleTemplateValue( DependencyObject d, object value ) + { + if( value != null && + d.GetValue( DocumentTitleTemplateSelectorProperty ) != null ) + return null; + + return value; + } + + #endregion + + #region DocumentTitleTemplateSelector + + /// + /// DocumentTitleTemplateSelector Dependency Property + /// + public static readonly DependencyProperty DocumentTitleTemplateSelectorProperty = DependencyProperty.Register( "DocumentTitleTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentTitleTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentTitleTemplateSelectorValue ) ) ); + + /// + /// Gets or sets the DocumentTitleTemplateSelector property. This dependency property + /// indicates the data template selector to use when creating the data template for the title. + /// + public DataTemplateSelector DocumentTitleTemplateSelector + { + get + { + return ( DataTemplateSelector )GetValue( DocumentTitleTemplateSelectorProperty ); + } + set + { + SetValue( DocumentTitleTemplateSelectorProperty, value ); + } + } + + /// + /// Handles changes to the DocumentTitleTemplateSelector property. + /// + private static void OnDocumentTitleTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentTitleTemplateSelectorChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplateSelector property. + /// + protected virtual void OnDocumentTitleTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.NewValue != null ) + DocumentTitleTemplate = null; + } + + /// + /// Coerces the DocumentTitleTemplateSelector value. + /// + private static object CoerceDocumentTitleTemplateSelectorValue( DependencyObject d, object value ) + { + return value; + } + + #endregion + + #region AnchorableTitleTemplate + + /// + /// AnchorableTitleTemplate Dependency Property + /// + public static readonly DependencyProperty AnchorableTitleTemplateProperty = DependencyProperty.Register( "AnchorableTitleTemplate", typeof( DataTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnAnchorableTitleTemplateChanged ), new CoerceValueCallback( CoerceAnchorableTitleTemplateValue ) ) ); + + /// + /// Gets or sets the AnchorableTitleTemplate property. This dependency property + /// indicates the data template to use for anchorables title. + /// + public DataTemplate AnchorableTitleTemplate + { + get + { + return ( DataTemplate )GetValue( AnchorableTitleTemplateProperty ); + } + set + { + SetValue( AnchorableTitleTemplateProperty, value ); + } + } + + /// + /// Handles changes to the AnchorableTitleTemplate property. + /// + private static void OnAnchorableTitleTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnAnchorableTitleTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplate property. + /// + protected virtual void OnAnchorableTitleTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + } + + /// + /// Coerces the AnchorableTitleTemplate value. + /// + private static object CoerceAnchorableTitleTemplateValue( DependencyObject d, object value ) + { + if( value != null && + d.GetValue( AnchorableTitleTemplateSelectorProperty ) != null ) + return null; + return value; + } + + #endregion + + #region AnchorableTitleTemplateSelector + + /// + /// AnchorableTitleTemplateSelector Dependency Property + /// + public static readonly DependencyProperty AnchorableTitleTemplateSelectorProperty = DependencyProperty.Register( "AnchorableTitleTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnAnchorableTitleTemplateSelectorChanged ) ) ); + + /// + /// Gets or sets the AnchorableTitleTemplateSelector property. This dependency property + /// indicates selctor to use when selecting data template for the title of anchorables. + /// + public DataTemplateSelector AnchorableTitleTemplateSelector + { + get + { + return ( DataTemplateSelector )GetValue( AnchorableTitleTemplateSelectorProperty ); + } + set + { + SetValue( AnchorableTitleTemplateSelectorProperty, value ); + } + } + + /// + /// Handles changes to the AnchorableTitleTemplateSelector property. + /// + private static void OnAnchorableTitleTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnAnchorableTitleTemplateSelectorChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplateSelector property. + /// + protected virtual void OnAnchorableTitleTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.NewValue != null && + AnchorableTitleTemplate != null ) + AnchorableTitleTemplate = null; + } + + #endregion + + #region AnchorableHeaderTemplate + + /// + /// AnchorableHeaderTemplate Dependency Property + /// + public static readonly DependencyProperty AnchorableHeaderTemplateProperty = DependencyProperty.Register( "AnchorableHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnAnchorableHeaderTemplateChanged ), new CoerceValueCallback( CoerceAnchorableHeaderTemplateValue ) ) ); + + /// + /// Gets or sets the AnchorableHeaderTemplate property. This dependency property + /// indicates the data template to use for anchorable templates. + /// + public DataTemplate AnchorableHeaderTemplate + { + get + { + return ( DataTemplate )GetValue( AnchorableHeaderTemplateProperty ); + } + set + { + SetValue( AnchorableHeaderTemplateProperty, value ); + } + } + + /// + /// Handles changes to the AnchorableHeaderTemplate property. + /// + private static void OnAnchorableHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnAnchorableHeaderTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplate property. + /// + protected virtual void OnAnchorableHeaderTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + } + + /// + /// Coerces the AnchorableHeaderTemplate value. + /// + private static object CoerceAnchorableHeaderTemplateValue( DependencyObject d, object value ) + { + if( value != null && + d.GetValue( AnchorableHeaderTemplateSelectorProperty ) != null ) + return null; + + return value; + } + + #endregion + + #region AnchorableHeaderTemplateSelector + + /// + /// AnchorableHeaderTemplateSelector Dependency Property + /// + public static readonly DependencyProperty AnchorableHeaderTemplateSelectorProperty = DependencyProperty.Register( "AnchorableHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnAnchorableHeaderTemplateSelectorChanged ) ) ); + + /// + /// Gets or sets the AnchorableHeaderTemplateSelector property. This dependency property + /// indicates the selector to use when selecting the data template for anchorable headers. + /// + public DataTemplateSelector AnchorableHeaderTemplateSelector + { + get + { + return ( DataTemplateSelector )GetValue( AnchorableHeaderTemplateSelectorProperty ); + } + set + { + SetValue( AnchorableHeaderTemplateSelectorProperty, value ); + } + } + + /// + /// Handles changes to the AnchorableHeaderTemplateSelector property. + /// + private static void OnAnchorableHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnAnchorableHeaderTemplateSelectorChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplateSelector property. + /// + protected virtual void OnAnchorableHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.NewValue != null ) + AnchorableHeaderTemplate = null; + } + + #endregion + + #region LayoutRootPanel + + /// + /// LayoutRootPanel Dependency Property + /// + public static readonly DependencyProperty LayoutRootPanelProperty = DependencyProperty.Register( "LayoutRootPanel", typeof( LayoutPanelControl ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( LayoutPanelControl )null, new PropertyChangedCallback( OnLayoutRootPanelChanged ) ) ); + + /// + /// Gets or sets the LayoutRootPanel property. This dependency property + /// indicates the layout panel control which is attached to the Layout.Root property. + /// + public LayoutPanelControl LayoutRootPanel + { + get + { + return ( LayoutPanelControl )GetValue( LayoutRootPanelProperty ); + } + set + { + SetValue( LayoutRootPanelProperty, value ); + } + } + + /// + /// Handles changes to the LayoutRootPanel property. + /// + private static void OnLayoutRootPanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnLayoutRootPanelChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the LayoutRootPanel property. + /// + protected virtual void OnLayoutRootPanelChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.OldValue != null ) + InternalRemoveLogicalChild( e.OldValue ); + if( e.NewValue != null ) + InternalAddLogicalChild( e.NewValue ); + } + + #endregion + + #region RightSidePanel + + /// + /// RightSidePanel Dependency Property + /// + public static readonly DependencyProperty RightSidePanelProperty = DependencyProperty.Register( "RightSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnRightSidePanelChanged ) ) ); + + /// + /// Gets or sets the RightSidePanel property. This dependency property + /// indicates right side anchor panel. + /// + public LayoutAnchorSideControl RightSidePanel + { + get + { + return ( LayoutAnchorSideControl )GetValue( RightSidePanelProperty ); + } + set + { + SetValue( RightSidePanelProperty, value ); + } + } + + /// + /// Handles changes to the RightSidePanel property. + /// + private static void OnRightSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnRightSidePanelChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the RightSidePanel property. + /// + protected virtual void OnRightSidePanelChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.OldValue != null ) + InternalRemoveLogicalChild( e.OldValue ); + if( e.NewValue != null ) + InternalAddLogicalChild( e.NewValue ); + } + + #endregion + + #region LeftSidePanel + + /// + /// LeftSidePanel Dependency Property + /// + public static readonly DependencyProperty LeftSidePanelProperty = DependencyProperty.Register( "LeftSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnLeftSidePanelChanged ) ) ); + + /// + /// Gets or sets the LeftSidePanel property. This dependency property + /// indicates the left side panel control. + /// + public LayoutAnchorSideControl LeftSidePanel + { + get + { + return ( LayoutAnchorSideControl )GetValue( LeftSidePanelProperty ); + } + set + { + SetValue( LeftSidePanelProperty, value ); + } + } + + /// + /// Handles changes to the LeftSidePanel property. + /// + private static void OnLeftSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnLeftSidePanelChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the LeftSidePanel property. + /// + protected virtual void OnLeftSidePanelChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.OldValue != null ) + InternalRemoveLogicalChild( e.OldValue ); + if( e.NewValue != null ) + InternalAddLogicalChild( e.NewValue ); + } + + #endregion + + #region TopSidePanel + + /// + /// TopSidePanel Dependency Property + /// + public static readonly DependencyProperty TopSidePanelProperty = DependencyProperty.Register( "TopSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnTopSidePanelChanged ) ) ); + + /// + /// Gets or sets the TopSidePanel property. This dependency property + /// indicates top side control panel. + /// + public LayoutAnchorSideControl TopSidePanel + { + get + { + return ( LayoutAnchorSideControl )GetValue( TopSidePanelProperty ); + } + set + { + SetValue( TopSidePanelProperty, value ); + } + } + + /// + /// Handles changes to the TopSidePanel property. + /// + private static void OnTopSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnTopSidePanelChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the TopSidePanel property. + /// + protected virtual void OnTopSidePanelChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.OldValue != null ) + InternalRemoveLogicalChild( e.OldValue ); + if( e.NewValue != null ) + InternalAddLogicalChild( e.NewValue ); + } + + #endregion + + #region BottomSidePanel + + /// + /// BottomSidePanel Dependency Property + /// + public static readonly DependencyProperty BottomSidePanelProperty = DependencyProperty.Register( "BottomSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnBottomSidePanelChanged ) ) ); + + /// + /// Gets or sets the BottomSidePanel property. This dependency property + /// indicates bottom side panel control. + /// + public LayoutAnchorSideControl BottomSidePanel + { + get + { + return ( LayoutAnchorSideControl )GetValue( BottomSidePanelProperty ); + } + set + { + SetValue( BottomSidePanelProperty, value ); + } + } + + /// + /// Handles changes to the BottomSidePanel property. + /// + private static void OnBottomSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnBottomSidePanelChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the BottomSidePanel property. + /// + protected virtual void OnBottomSidePanelChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.OldValue != null ) + InternalRemoveLogicalChild( e.OldValue ); + if( e.NewValue != null ) + InternalAddLogicalChild( e.NewValue ); + } + + #endregion + + #region LogicalChildren + + List _logicalChildren = new List(); + + protected override System.Collections.IEnumerator LogicalChildren + { + get + { + return _logicalChildren.Select( ch => ch.GetValueOrDefault() ).GetEnumerator(); + } + } + + public System.Collections.IEnumerator LogicalChildrenPublic + { + get + { + return this.LogicalChildren; + } + } + + + internal void InternalAddLogicalChild( object element ) + { #if DEBUG - if (_logicalChildren.Select(ch => ch.GetValueOrDefault()).Contains(element)) - new InvalidOperationException(); + if( _logicalChildren.Select( ch => ch.GetValueOrDefault() ).Contains( element ) ) + new InvalidOperationException(); #endif - if (_logicalChildren.Select(ch => ch.GetValueOrDefault()).Contains(element)) - return; - - if (((FrameworkElement)element).Parent != null) - { - (((FrameworkElement)element).Parent as DockingManager).InternalRemoveLogicalChild(element); - } - - _logicalChildren.Add(new WeakReference(element)); - AddLogicalChild(element); - } - - internal void InternalRemoveLogicalChild(object element) - { - //System.Diagnostics.Trace.WriteLine("[{0}]InternalRemoveLogicalChild({1})", this, element); - - var wrToRemove = _logicalChildren.FirstOrDefault(ch => ch.GetValueOrDefault() == element); - if (wrToRemove != null) - _logicalChildren.Remove(wrToRemove); - RemoveLogicalChild(element); - } - - void ClearLogicalChildrenList() - { - foreach (var child in _logicalChildren.Select(ch => ch.GetValueOrDefault()).ToArray()) - RemoveLogicalChild(child); - _logicalChildren.Clear(); - } - - #endregion - - #region AutoHide window - internal void ShowAutoHideWindow(LayoutAnchorControl anchor) - { - _autoHideWindowManager.ShowAutoHideWindow(anchor); - //if (_autohideArea == null) - // return; - - //if (AutoHideWindow != null && AutoHideWindow.Model == anchor.Model) - // return; - - //Trace.WriteLine("ShowAutoHideWindow()"); - - //_currentAutohiddenAnchor = new WeakReference(anchor); - - //HideAutoHideWindow(anchor); - - //SetAutoHideWindow(new LayoutAutoHideWindowControl(anchor)); - //AutoHideWindow.Show(); - } - - internal void HideAutoHideWindow(LayoutAnchorControl anchor) - { - _autoHideWindowManager.HideAutoWindow(anchor); - } - - - void SetupAutoHideWindow() - { - _autohideArea = GetTemplateChild("PART_AutoHideArea") as FrameworkElement; - - if (_autoHideWindowManager != null) - _autoHideWindowManager.HideAutoWindow(); - else - _autoHideWindowManager = new AutoHideWindowManager(this); - - if (AutoHideWindow != null) - AutoHideWindow.Dispose(); - - SetAutoHideWindow(new LayoutAutoHideWindowControl()); - } - - AutoHideWindowManager _autoHideWindowManager; - - FrameworkElement _autohideArea; - internal FrameworkElement GetAutoHideAreaElement() - { - return _autohideArea; - } - - #region AutoHideWindow - - /// - /// AutoHideWindow Read-Only Dependency Property - /// - private static readonly DependencyPropertyKey AutoHideWindowPropertyKey - = DependencyProperty.RegisterReadOnly("AutoHideWindow", typeof(LayoutAutoHideWindowControl), typeof(DockingManager), - new FrameworkPropertyMetadata((LayoutAutoHideWindowControl)null, - new PropertyChangedCallback(OnAutoHideWindowChanged))); - - public static readonly DependencyProperty AutoHideWindowProperty - = AutoHideWindowPropertyKey.DependencyProperty; - - /// - /// Gets the AutoHideWindow property. This dependency property - /// indicates the currently shown autohide window. - /// - public LayoutAutoHideWindowControl AutoHideWindow - { - get { return (LayoutAutoHideWindowControl)GetValue(AutoHideWindowProperty); } - } - - /// - /// Provides a secure method for setting the AutoHideWindow property. - /// This dependency property indicates the currently shown autohide window. - /// - /// The new value for the property. - protected void SetAutoHideWindow(LayoutAutoHideWindowControl value) - { - SetValue(AutoHideWindowPropertyKey, value); - } - - /// - /// Handles changes to the AutoHideWindow property. - /// - private static void OnAutoHideWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnAutoHideWindowChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AutoHideWindow property. - /// - protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - - } - - #endregion - - - - #endregion - // #region AutoHide window - //WeakReference _currentAutohiddenAnchor = null; - //internal void ShowAutoHideWindow(LayoutAnchorControl anchor) - //{ - // if (_autohideArea == null) - // return; - - // if (AutoHideWindow != null && AutoHideWindow.Model == anchor.Model) - // return; - - // Trace.WriteLine("ShowAutoHideWindow()"); - - // _currentAutohiddenAnchor = new WeakReference(anchor); - - // HideAutoHideWindow(anchor); - - // SetAutoHideWindow(new LayoutAutoHideWindowControl(anchor)); - //} - - //internal void HideAutoHideWindow(LayoutAnchorControl anchor) - //{ - // if (AutoHideWindow != null) - // { - // if (anchor == _currentAutohiddenAnchor.GetValueOrDefault()) - // { - // Trace.WriteLine("AutoHideWindow()"); - // AutoHideWindow.Dispose(); - // SetAutoHideWindow(null); - // } - // } - //} - - //FrameworkElement _autohideArea; - //internal FrameworkElement GetAutoHideAreaElement() - //{ - // return _autohideArea; - //} - - //void SetupAutoHideArea() - //{ - // _autohideArea = GetTemplateChild("PART_AutoHideArea") as FrameworkElement; - //} - - // #region AutoHideWindow - - ///// - ///// AutoHideWindow Read-Only Dependency Property - ///// - //private static readonly DependencyPropertyKey AutoHideWindowPropertyKey - // = DependencyProperty.RegisterReadOnly("AutoHideWindow", typeof(LayoutAutoHideWindowControl), typeof(DockingManager), - // new FrameworkPropertyMetadata((LayoutAutoHideWindowControl)null, - // new PropertyChangedCallback(OnAutoHideWindowChanged))); - - //public static readonly DependencyProperty AutoHideWindowProperty - // = AutoHideWindowPropertyKey.DependencyProperty; - - ///// - ///// Gets the AutoHideWindow property. This dependency property - ///// indicates the currently shown autohide window. - ///// - //public LayoutAutoHideWindowControl AutoHideWindow - //{ - // get { return (LayoutAutoHideWindowControl)GetValue(AutoHideWindowProperty); } - //} - - ///// - ///// Provides a secure method for setting the AutoHideWindow property. - ///// This dependency property indicates the currently shown autohide window. - ///// - ///// The new value for the property. - //protected void SetAutoHideWindow(LayoutAutoHideWindowControl value) - //{ - // SetValue(AutoHideWindowPropertyKey, value); - //} - - ///// - ///// Handles changes to the AutoHideWindow property. - ///// - //private static void OnAutoHideWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - //{ - // ((DockingManager)d).OnAutoHideWindowChanged(e); - //} - - ///// - ///// Provides derived classes an opportunity to handle changes to the AutoHideWindow property. - ///// - //protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArgs e) - //{ - // if (e.OldValue != null) - // ((ILogicalChildrenContainer)this).InternalRemoveLogicalChild(e.OldValue); - // if (e.NewValue != null) - // ((ILogicalChildrenContainer)this).InternalAddLogicalChild(e.NewValue); - //} - - // #endregion - - - - // #endregion - - #region Floating Windows - List _fwList = new List(); - - internal void StartDraggingFloatingWindowForContent(LayoutContent contentModel, bool startDrag = true) - { - if (!contentModel.CanFloat) - return; - var contentModelAsAnchorable = contentModel as LayoutAnchorable; - if (contentModelAsAnchorable != null && - contentModelAsAnchorable.IsAutoHidden) - contentModelAsAnchorable.ToggleAutoHide(); - - var parentPane = contentModel.Parent as ILayoutPane; - var parentPaneAsPositionableElement = contentModel.Parent as ILayoutPositionableElement; - var parentPaneAsWithActualSize = contentModel.Parent as ILayoutPositionableElementWithActualSize; - var contentModelParentChildrenIndex = parentPane.Children.ToList().IndexOf(contentModel); - - if (contentModel.FindParent() == null) - { - ((ILayoutPreviousContainer)contentModel).PreviousContainer = parentPane; - contentModel.PreviousContainerIndex = contentModelParentChildrenIndex; - } - - parentPane.RemoveChildAt(contentModelParentChildrenIndex); - - double fwWidth = contentModel.FloatingWidth; - double fwHeight = contentModel.FloatingHeight; - - if (fwWidth == 0.0) - fwWidth = parentPaneAsPositionableElement.FloatingWidth; - if (fwHeight == 0.0) - fwHeight = parentPaneAsPositionableElement.FloatingHeight; - - if (fwWidth == 0.0) - fwWidth = parentPaneAsWithActualSize.ActualWidth; - if (fwHeight == 0.0) - fwHeight = parentPaneAsWithActualSize.ActualHeight; - - LayoutFloatingWindow fw; - LayoutFloatingWindowControl fwc; - if (contentModel is LayoutAnchorable) - { - var anchorableContent = contentModel as LayoutAnchorable; - fw = new LayoutAnchorableFloatingWindow() - { - RootPanel = new LayoutAnchorablePaneGroup( - new LayoutAnchorablePane(anchorableContent) - { - DockWidth = parentPaneAsPositionableElement.DockWidth, - DockHeight = parentPaneAsPositionableElement.DockHeight, - DockMinHeight = parentPaneAsPositionableElement.DockMinHeight, - DockMinWidth = parentPaneAsPositionableElement.DockMinWidth, - FloatingLeft = parentPaneAsPositionableElement.FloatingLeft, - FloatingTop = parentPaneAsPositionableElement.FloatingTop, - FloatingWidth = parentPaneAsPositionableElement.FloatingWidth, - FloatingHeight = parentPaneAsPositionableElement.FloatingHeight, - }) - }; - - Layout.FloatingWindows.Add(fw); - - fwc = new LayoutAnchorableFloatingWindowControl( - fw as LayoutAnchorableFloatingWindow) - { - Width = fwWidth, - Height = fwHeight, - Left = contentModel.FloatingLeft, - Top = contentModel.FloatingTop - }; - } - else - { - var anchorableDocument = contentModel as LayoutDocument; - fw = new LayoutDocumentFloatingWindow() - { - RootDocument = anchorableDocument - }; - - Layout.FloatingWindows.Add(fw); - - fwc = new LayoutDocumentFloatingWindowControl( - fw as LayoutDocumentFloatingWindow) - { - Width = fwWidth, - Height = fwHeight, - Left = contentModel.FloatingLeft, - Top = contentModel.FloatingTop - }; - } - - - //fwc.Owner = Window.GetWindow(this); - //fwc.SetParentToMainWindowOf(this); - - - _fwList.Add(fwc); - - Layout.CollectGarbage(); - - UpdateLayout(); - - Dispatcher.BeginInvoke(new Action(() => - { - if (startDrag) - fwc.AttachDrag(); - fwc.Show(); - }), DispatcherPriority.Send); - } - - internal void StartDraggingFloatingWindowForPane(LayoutAnchorablePane paneModel) - { - if (paneModel.Children.Any(c => !c.CanFloat)) - return; - var paneAsPositionableElement = paneModel as ILayoutPositionableElement; - var paneAsWithActualSize = paneModel as ILayoutPositionableElementWithActualSize; - - double fwWidth = paneAsPositionableElement.FloatingWidth; - double fwHeight = paneAsPositionableElement.FloatingHeight; - double fwLeft = paneAsPositionableElement.FloatingLeft; - double fwTop = paneAsPositionableElement.FloatingTop; - - - - if (fwWidth == 0.0) - fwWidth = paneAsWithActualSize.ActualWidth; - if (fwHeight == 0.0) - fwHeight = paneAsWithActualSize.ActualHeight; - - var destPane = new LayoutAnchorablePane() - { - DockWidth = paneAsPositionableElement.DockWidth, - DockHeight = paneAsPositionableElement.DockHeight, - DockMinHeight = paneAsPositionableElement.DockMinHeight, - DockMinWidth = paneAsPositionableElement.DockMinWidth, - FloatingLeft = paneAsPositionableElement.FloatingLeft, - FloatingTop = paneAsPositionableElement.FloatingTop, - FloatingWidth = paneAsPositionableElement.FloatingWidth, - FloatingHeight = paneAsPositionableElement.FloatingHeight, - }; - - bool savePreviousContainer = paneModel.FindParent() == null; - int currentSelectedContentIndex = paneModel.SelectedContentIndex; - while (paneModel.Children.Count > 0) - { - var contentModel = paneModel.Children[paneModel.Children.Count - 1] as LayoutAnchorable; - - if (savePreviousContainer) - { - var contentModelAsPreviousContainer = contentModel as ILayoutPreviousContainer; - contentModelAsPreviousContainer.PreviousContainer = paneModel; - contentModel.PreviousContainerIndex = paneModel.Children.Count - 1; - } - - paneModel.RemoveChildAt(paneModel.Children.Count - 1); - destPane.Children.Insert(0, contentModel); - } - - if (destPane.Children.Count > 0) - { - destPane.SelectedContentIndex = currentSelectedContentIndex; - } - - - LayoutFloatingWindow fw; - LayoutFloatingWindowControl fwc; - fw = new LayoutAnchorableFloatingWindow() - { - RootPanel = new LayoutAnchorablePaneGroup( - destPane) - { - DockHeight = destPane.DockHeight, - DockWidth = destPane.DockWidth, - DockMinHeight = destPane.DockMinHeight, - DockMinWidth = destPane.DockMinWidth, - } - }; - - Layout.FloatingWindows.Add(fw); - - fwc = new LayoutAnchorableFloatingWindowControl( - fw as LayoutAnchorableFloatingWindow) - { - Width = fwWidth, - Height = fwHeight - }; - - - - //fwc.Owner = Window.GetWindow(this); - //fwc.SetParentToMainWindowOf(this); - - - _fwList.Add(fwc); - - Layout.CollectGarbage(); - - InvalidateArrange(); - - fwc.AttachDrag(); - fwc.Show(); - - } - - internal IEnumerable GetFloatingWindowsByZOrder() - { - var parentWindow = Window.GetWindow(this); - - if (parentWindow == null) - yield break; - - IntPtr windowParentHanlde = new WindowInteropHelper(parentWindow).Handle; - - IntPtr currentHandle = Win32Helper.GetWindow(windowParentHanlde, (uint)Win32Helper.GetWindow_Cmd.GW_HWNDFIRST); - while (currentHandle != IntPtr.Zero) - { - LayoutFloatingWindowControl ctrl = _fwList.FirstOrDefault(fw => new WindowInteropHelper(fw).Handle == currentHandle); - if (ctrl != null && ctrl.Model.Root.Manager == this) - yield return ctrl; - - currentHandle = Win32Helper.GetWindow(currentHandle, (uint)Win32Helper.GetWindow_Cmd.GW_HWNDNEXT); - } - } - - internal void RemoveFloatingWindow(LayoutFloatingWindowControl floatingWindow) - { - _fwList.Remove(floatingWindow); - } - - public IEnumerable FloatingWindows - { - get { return _fwList; } - } - #endregion - - #region OverlayWindow - - bool IOverlayWindowHost.HitTest(Point dragPoint) - { - if (!this.IsVisible) return false; - Rect detectionRect = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor()); - return detectionRect.Contains(dragPoint); - } - - DockingManager IOverlayWindowHost.Manager - { - get { return this; } - } - - OverlayWindow _overlayWindow = null; - void CreateOverlayWindow() - { - if (_overlayWindow == null) - { - _overlayWindow = new OverlayWindow(this); - } - Rect rectWindow = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor()); - _overlayWindow.Left = rectWindow.Left; - _overlayWindow.Top = rectWindow.Top; - _overlayWindow.Width = rectWindow.Width; - _overlayWindow.Height = rectWindow.Height; - } - - void DestroyOverlayWindow() - { - if (_overlayWindow != null) - { - _overlayWindow.Close(); - _overlayWindow = null; - } - } - - IOverlayWindow IOverlayWindowHost.ShowOverlayWindow(LayoutFloatingWindowControl draggingWindow) - { - //Trace.WriteLine("ShowOverlayWindow"); - CreateOverlayWindow(); - if (draggingWindow.Model.Root.ActiveContent.CanDock) - { - _overlayWindow.Owner = draggingWindow; - _overlayWindow.EnableDropTargets(); - _overlayWindow.Show(); - } - return _overlayWindow; - } - - void IOverlayWindowHost.HideOverlayWindow() - { - //Trace.WriteLine("HideOverlayWindow"); - _areas = null; - _overlayWindow.Owner = null; - _overlayWindow.HideDropTargets(); - } - - List _areas = null; - - IEnumerable IOverlayWindowHost.GetDropAreas(LayoutFloatingWindowControl draggingWindow) - { - if (_areas != null) - return _areas; - - bool isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow; - - _areas = new List(); - - if (!isDraggingDocuments) - { - _areas.Add(new DropArea( - this, - DropAreaType.DockingManager)); - - foreach (var areaHost in this.FindVisualChildren()) - { - if (areaHost.Model.Descendents().Any()) - { - _areas.Add(new DropArea( - areaHost, - DropAreaType.AnchorablePane)); - } - } - } - - foreach (var areaHost in this.FindVisualChildren()) - { - _areas.Add(new DropArea( - areaHost, - DropAreaType.DocumentPane)); - } - - foreach (var areaHost in this.FindVisualChildren()) - { - var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup; - if (documentGroupModel.Children.Where(c => c.IsVisible).Count() == 0) - { - _areas.Add(new DropArea( - areaHost, - DropAreaType.DocumentPaneGroup)); - } - } - - return _areas; - } - - protected override Size ArrangeOverride(Size arrangeBounds) - { - _areas = null; - return base.ArrangeOverride(arrangeBounds); - } - - #endregion - - #region LayoutDocument & LayoutAnchorable Templates - - #region LayoutItemTemplate - - /// - /// LayoutItemTemplate Dependency Property - /// - public static readonly DependencyProperty LayoutItemTemplateProperty = - DependencyProperty.Register("LayoutItemTemplate", typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, - new PropertyChangedCallback(OnLayoutItemTemplateChanged))); - - /// - /// Gets or sets the AnchorableTemplate property. This dependency property - /// indicates the template to use to render anchorable and document contents. - /// - public DataTemplate LayoutItemTemplate - { - get { return (DataTemplate)GetValue(LayoutItemTemplateProperty); } - set { SetValue(LayoutItemTemplateProperty, value); } - } - - /// - /// Handles changes to the AnchorableTemplate property. - /// - private static void OnLayoutItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnLayoutItemTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AnchorableTemplate property. - /// - protected virtual void OnLayoutItemTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion - - #region LayoutItemTemplateSelector - - /// - /// LayoutItemTemplateSelector Dependency Property - /// - public static readonly DependencyProperty LayoutItemTemplateSelectorProperty = - DependencyProperty.Register("LayoutItemTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null, - new PropertyChangedCallback(OnLayoutItemTemplateSelectorChanged))); - - /// - /// Gets or sets the LayoutItemTemplateSelector property. This dependency property - /// indicates selector object to use for anchorable templates. - /// - public DataTemplateSelector LayoutItemTemplateSelector - { - get { return (DataTemplateSelector)GetValue(LayoutItemTemplateSelectorProperty); } - set { SetValue(LayoutItemTemplateSelectorProperty, value); } - } - - /// - /// Handles changes to the LayoutItemTemplateSelector property. - /// - private static void OnLayoutItemTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnLayoutItemTemplateSelectorChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the LayoutItemTemplateSelector property. - /// - protected virtual void OnLayoutItemTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion - - - #endregion - - #region DocumentsSource - - /// - /// DocumentsSource Dependency Property - /// - public static readonly DependencyProperty DocumentsSourceProperty = - DependencyProperty.Register("DocumentsSource", typeof(IEnumerable), typeof(DockingManager), - new FrameworkPropertyMetadata((IEnumerable)null, - new PropertyChangedCallback(OnDocumentsSourceChanged))); - - /// - /// Gets or sets the DocumentsSource property. This dependency property - /// indicates the source collection of documents. - /// - public IEnumerable DocumentsSource - { - get { return (IEnumerable)GetValue(DocumentsSourceProperty); } - set { SetValue(DocumentsSourceProperty, value); } - } - - /// - /// Handles changes to the DocumentsSource property. - /// - private static void OnDocumentsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentsSourceChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentsSource property. - /// - protected virtual void OnDocumentsSourceChanged(DependencyPropertyChangedEventArgs e) - { - DetachDocumentsSource(Layout, e.OldValue as IEnumerable); - AttachDocumentsSource(Layout, e.NewValue as IEnumerable); - } - - - void AttachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource) - { - if (documentsSource == null) - return; - - if (layout == null) - return; - - //if (layout.Descendents().OfType().Any()) - // throw new InvalidOperationException("Unable to set the DocumentsSource property if LayoutDocument objects are already present in the model"); - var documentsImported = layout.Descendents().OfType().Select(d => d.Content).ToArray(); - var documents = documentsSource as IEnumerable; - var listOfDocumentsToImport = new List(documents.OfType()); - - foreach (var document in listOfDocumentsToImport.ToArray()) - { - if (documentsImported.Contains(document)) - listOfDocumentsToImport.Remove(document); - } - - - LayoutDocumentPane documentPane = null; - if (layout.LastFocusedDocument != null) - { - documentPane = layout.LastFocusedDocument.Parent as LayoutDocumentPane; - } - - if (documentPane == null) - { - documentPane = layout.Descendents().OfType().FirstOrDefault(); - } - - //if (documentPane == null) - // throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); - - _suspendLayoutItemCreation = true; - foreach (var documentContentToImport in listOfDocumentsToImport) - { - - //documentPane.Children.Add(new LayoutDocument() { Content = documentToImport }); - - var documentToImport = new LayoutDocument() - { - Content = documentContentToImport - }; - - bool added = false; - if (LayoutUpdateStrategy != null) - { - added = LayoutUpdateStrategy.BeforeInsertDocument(layout, documentToImport, documentPane); - } - - if (!added) - { - if (documentPane == null) - throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); - - documentPane.Children.Add(documentToImport); - added = true; - } - - if (LayoutUpdateStrategy != null) - LayoutUpdateStrategy.AfterInsertDocument(layout, documentToImport); - - - CreateDocumentLayoutItem(documentToImport); - - } - _suspendLayoutItemCreation = true; - - - var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged; - if (documentsSourceAsNotifier != null) - documentsSourceAsNotifier.CollectionChanged += new NotifyCollectionChangedEventHandler(documentsSourceElementsChanged); - } - - internal bool SuspendDocumentsSourceBinding = false; - - void documentsSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e) - { - if (Layout == null) - return; - - //When deserializing documents are created automatically by the deserializer - if (SuspendDocumentsSourceBinding) - return; - - //handle remove - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) - { - if (e.OldItems != null) - { - var documentsToRemove = Layout.Descendents().OfType().Where(d => e.OldItems.Contains(d.Content)).ToArray(); - foreach (var documentToRemove in documentsToRemove) - { - (documentToRemove.Parent as ILayoutContainer).RemoveChild( - documentToRemove); - } - } - } - - //handle add - if (e.NewItems != null && - (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)) - { - if (e.NewItems != null) - { - LayoutDocumentPane documentPane = null; - if (Layout.LastFocusedDocument != null) - { - documentPane = Layout.LastFocusedDocument.Parent as LayoutDocumentPane; - } - - if (documentPane == null) - { - documentPane = Layout.Descendents().OfType().FirstOrDefault(); - } - - //if (documentPane == null) - // throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); - - _suspendLayoutItemCreation = true; - - foreach (var documentContentToImport in e.NewItems) - { - var documentToImport = new LayoutDocument() - { - Content = documentContentToImport - }; - - bool added = false; - if (LayoutUpdateStrategy != null) - { - added = LayoutUpdateStrategy.BeforeInsertDocument(Layout, documentToImport, documentPane); - } - - if (!added) - { - if (documentPane == null) - throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); - - documentPane.Children.Add(documentToImport); - added = true; - } - - if (LayoutUpdateStrategy != null) - { - LayoutUpdateStrategy.AfterInsertDocument(Layout, documentToImport); - } - - - var root = documentToImport.Root; - - if (root != null && root.Manager == this) - { - CreateDocumentLayoutItem(documentToImport); - } - } - _suspendLayoutItemCreation = false; - } - } - - if (e.Action == NotifyCollectionChangedAction.Reset) - { - //NOTE: I'm going to clear every document present in layout but - //some documents may have been added directly to the layout, for now I clear them too - var documentsToRemove = Layout.Descendents().OfType().ToArray(); - foreach (var documentToRemove in documentsToRemove) - { - (documentToRemove.Parent as ILayoutContainer).RemoveChild( - documentToRemove); - } - } - - if (Layout != null) - { - Layout.CollectGarbage(); - } - } - - void DetachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource) - { - if (documentsSource == null) - return; - - if (layout == null) - return; - - var documentsToRemove = layout.Descendents().OfType() - .Where(d => documentsSource.Contains(d.Content)).ToArray(); - - foreach (var documentToRemove in documentsToRemove) - { - (documentToRemove.Parent as ILayoutContainer).RemoveChild( - documentToRemove); - } - - var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged; - if (documentsSourceAsNotifier != null) - documentsSourceAsNotifier.CollectionChanged -= new NotifyCollectionChangedEventHandler(documentsSourceElementsChanged); - } - - - #endregion - - #region DocumentCloseCommand - - internal void _ExecuteCloseCommand(LayoutDocument document) - { - if (DocumentClosing != null) - { - var evargs = new DocumentClosingEventArgs(document); - DocumentClosing(this, evargs); - if (evargs.Cancel) - return; - } - - if (!document.TestCanClose()) - return; - - document.Close(); - - if (DocumentClosed != null) - { - var evargs = new DocumentClosedEventArgs(document); - DocumentClosed(this, evargs); - } - } - - /// - /// Event fired when a document is about to be closed - /// - /// Subscribers have the opportuniy to cancel the operation. - public event EventHandler DocumentClosing; - - /// - /// Event fired after a document is closed - /// - public event EventHandler DocumentClosed; - - - - #endregion - - internal void _ExecuteCloseAllButThisCommand(LayoutContent contentSelected) - { - foreach (var contentToClose in Layout.Descendents().OfType().Where(d => d != contentSelected && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray()) - { - if (!contentToClose.CanClose) - continue; - - var layoutItem = GetLayoutItemFromModel(contentToClose); - if (layoutItem.CloseCommand != null) - { - if (layoutItem.CloseCommand.CanExecute(null)) - layoutItem.CloseCommand.Execute(null); - } - else - { - if (contentToClose is LayoutDocument) - _ExecuteCloseCommand(contentToClose as LayoutDocument); - else if (contentToClose is LayoutAnchorable) - _ExecuteCloseCommand(contentToClose as LayoutAnchorable); - } - } - } - - #region DocumentContextMenu - - /// - /// DocumentContextMenu Dependency Property - /// - public static readonly DependencyProperty DocumentContextMenuProperty = - DependencyProperty.Register("DocumentContextMenu", typeof(ContextMenu), typeof(DockingManager), - new FrameworkPropertyMetadata((ContextMenu)null)); - - /// - /// Gets or sets the DocumentContextMenu property. This dependency property - /// indicates context menu to show for documents. - /// - public ContextMenu DocumentContextMenu - { - get { return (ContextMenu)GetValue(DocumentContextMenuProperty); } - set { SetValue(DocumentContextMenuProperty, value); } - } - - #endregion - - #region AnchorablesSource - - /// - /// AnchorablesSource Dependency Property - /// - public static readonly DependencyProperty AnchorablesSourceProperty = - DependencyProperty.Register("AnchorablesSource", typeof(IEnumerable), typeof(DockingManager), - new FrameworkPropertyMetadata((IEnumerable)null, - new PropertyChangedCallback(OnAnchorablesSourceChanged))); - - /// - /// Gets or sets the AnchorablesSource property. This dependency property - /// indicates source collection of anchorables. - /// - public IEnumerable AnchorablesSource - { - get { return (IEnumerable)GetValue(AnchorablesSourceProperty); } - set { SetValue(AnchorablesSourceProperty, value); } - } - - /// - /// Handles changes to the AnchorablesSource property. - /// - private static void OnAnchorablesSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnAnchorablesSourceChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the AnchorablesSource property. - /// - protected virtual void OnAnchorablesSourceChanged(DependencyPropertyChangedEventArgs e) - { - DetachAnchorablesSource(Layout, e.OldValue as IEnumerable); - AttachAnchorablesSource(Layout, e.NewValue as IEnumerable); - } - - void AttachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource) - { - if (anchorablesSource == null) - return; - - if (layout == null) - return; - - //if (layout.Descendents().OfType().Any()) - // throw new InvalidOperationException("Unable to set the AnchorablesSource property if LayoutAnchorable objects are already present in the model"); - var anchorablesImported = layout.Descendents().OfType().Select(d => d.Content).ToArray(); - var anchorables = anchorablesSource as IEnumerable; - var listOfAnchorablesToImport = new List(anchorables.OfType()); - - foreach (var document in listOfAnchorablesToImport.ToArray()) - { - if (anchorablesImported.Contains(document)) - listOfAnchorablesToImport.Remove(document); - } - - LayoutAnchorablePane anchorablePane = null; - if (layout.ActiveContent != null) - { - //look for active content parent pane - anchorablePane = layout.ActiveContent.Parent as LayoutAnchorablePane; - } - - if (anchorablePane == null) - { - //look for a pane on the right side - anchorablePane = layout.Descendents().OfType().Where(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right).FirstOrDefault(); - } - - if (anchorablePane == null) - { - //look for an available pane - anchorablePane = layout.Descendents().OfType().FirstOrDefault(); - } - - _suspendLayoutItemCreation = true; - foreach (var anchorableContentToImport in listOfAnchorablesToImport) - { - var anchorableToImport = new LayoutAnchorable() - { - Content = anchorableContentToImport - }; - - bool added = false; - if (LayoutUpdateStrategy != null) - { - added = LayoutUpdateStrategy.BeforeInsertAnchorable(layout, anchorableToImport, anchorablePane); - } - - if (!added) - { - if (anchorablePane == null) - { - var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal }; - if (layout.RootPanel != null) - { - mainLayoutPanel.Children.Add(layout.RootPanel); - } - - layout.RootPanel = mainLayoutPanel; - anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength(200.0, GridUnitType.Pixel) }; - mainLayoutPanel.Children.Add(anchorablePane); - } - - anchorablePane.Children.Add(anchorableToImport); - added = true; - } - - if (LayoutUpdateStrategy != null) - LayoutUpdateStrategy.AfterInsertAnchorable(layout, anchorableToImport); - - - CreateAnchorableLayoutItem(anchorableToImport); - - } - - _suspendLayoutItemCreation = false; - - var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged; - if (anchorablesSourceAsNotifier != null) - anchorablesSourceAsNotifier.CollectionChanged += new NotifyCollectionChangedEventHandler(anchorablesSourceElementsChanged); - } - - internal bool SuspendAnchorablesSourceBinding = false; - - void anchorablesSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e) - { - if (Layout == null) - return; - - //When deserializing documents are created automatically by the deserializer - if (SuspendAnchorablesSourceBinding) - return; - - //handle remove - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) - { - if (e.OldItems != null) - { - var anchorablesToRemove = Layout.Descendents().OfType().Where(d => e.OldItems.Contains(d.Content)).ToArray(); - foreach (var anchorableToRemove in anchorablesToRemove) - { - (anchorableToRemove.Parent as ILayoutContainer).RemoveChild( - anchorableToRemove); - } - } - } - - //handle add - if (e.NewItems != null && - (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)) - { - if (e.NewItems != null) - { - LayoutAnchorablePane anchorablePane = null; - - if (Layout.ActiveContent != null) - { - //look for active content parent pane - anchorablePane = Layout.ActiveContent.Parent as LayoutAnchorablePane; - } - - if (anchorablePane == null) - { - //look for a pane on the right side - anchorablePane = Layout.Descendents().OfType().Where(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right).FirstOrDefault(); - } - - if (anchorablePane == null) - { - //look for an available pane - anchorablePane = Layout.Descendents().OfType().FirstOrDefault(); - } - - _suspendLayoutItemCreation = true; - foreach (var anchorableContentToImport in e.NewItems) - { - var anchorableToImport = new LayoutAnchorable() - { - Content = anchorableContentToImport - }; - - bool added = false; - if (LayoutUpdateStrategy != null) - { - added = LayoutUpdateStrategy.BeforeInsertAnchorable(Layout, anchorableToImport, anchorablePane); - } - - if (!added) - { - if (anchorablePane == null) - { - var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal }; - if (Layout.RootPanel != null) - { - mainLayoutPanel.Children.Add(Layout.RootPanel); - } - - Layout.RootPanel = mainLayoutPanel; - anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength(200.0, GridUnitType.Pixel) }; - mainLayoutPanel.Children.Add(anchorablePane); - } - - anchorablePane.Children.Add(anchorableToImport); - added = true; - } - - if (LayoutUpdateStrategy != null) - { - LayoutUpdateStrategy.AfterInsertAnchorable(Layout, anchorableToImport); - } - - var root = anchorableToImport.Root; - - if (root != null && root.Manager == this) - { - CreateAnchorableLayoutItem(anchorableToImport); - } - - } - _suspendLayoutItemCreation = false; - } - } - - if (e.Action == NotifyCollectionChangedAction.Reset) - { - //NOTE: I'm going to clear every anchorable present in layout but - //some anchorable may have been added directly to the layout, for now I clear them too - var anchorablesToRemove = Layout.Descendents().OfType().ToArray(); - foreach (var anchorableToRemove in anchorablesToRemove) - { - (anchorableToRemove.Parent as ILayoutContainer).RemoveChild( - anchorableToRemove); - } - } - - if (Layout != null) - Layout.CollectGarbage(); - } - - void DetachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource) - { - if (anchorablesSource == null) - return; - - if (layout == null) - return; - - var anchorablesToRemove = layout.Descendents().OfType() - .Where(d => anchorablesSource.Contains(d.Content)).ToArray(); - - foreach (var anchorableToRemove in anchorablesToRemove) - { - (anchorableToRemove.Parent as ILayoutContainer).RemoveChild( - anchorableToRemove); - } - - var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged; - if (anchorablesSourceAsNotifier != null) - anchorablesSourceAsNotifier.CollectionChanged -= new NotifyCollectionChangedEventHandler(anchorablesSourceElementsChanged); - } - - #endregion - - internal void _ExecuteCloseCommand(LayoutAnchorable anchorable) - { - var model = anchorable as LayoutAnchorable; - if (model != null && model.TestCanClose()) - { - if (model.IsAutoHidden) - model.ToggleAutoHide(); - - model.Close(); - return; - } - } - - internal void _ExecuteHideCommand(LayoutAnchorable anchorable) - { - var model = anchorable as LayoutAnchorable; - if (model != null) - { - //by default hide the anchorable - model.Hide(); - } - } - - internal void _ExecuteAutoHideCommand(LayoutAnchorable _anchorable) - { - _anchorable.ToggleAutoHide(); - } - - internal void _ExecuteFloatCommand(LayoutContent contentToFloat) - { - contentToFloat.Float(); - } - - internal void _ExecuteDockCommand(LayoutAnchorable anchorable) - { - anchorable.Dock(); - } - - internal void _ExecuteDockAsDocumentCommand(LayoutContent content) - { - content.DockAsDocument(); - } - - #region ActiveContent - - /// - /// ActiveContent Dependency Property - /// - public static readonly DependencyProperty ActiveContentProperty = - DependencyProperty.Register("ActiveContent", typeof(object), typeof(DockingManager), - new FrameworkPropertyMetadata((object)null, - new PropertyChangedCallback(OnActiveContentChanged))); - - /// - /// Gets or sets the ActiveContent property. This dependency property - /// indicates the content currently active. - /// - public object ActiveContent - { - get { return (object)GetValue(ActiveContentProperty); } - set { SetValue(ActiveContentProperty, value); } - } - - /// - /// Handles changes to the ActiveContent property. - /// - private static void OnActiveContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).InternalSetActiveContent(e.NewValue); - ((DockingManager)d).OnActiveContentChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the ActiveContent property. - /// - protected virtual void OnActiveContentChanged(DependencyPropertyChangedEventArgs e) - { - if (ActiveContentChanged != null) - ActiveContentChanged(this, EventArgs.Empty); - } - - - bool _insideInternalSetActiveContent = false; - void InternalSetActiveContent(object contentObject) - { - var layoutContent = Layout.Descendents().OfType().FirstOrDefault(lc => lc == contentObject || lc.Content == contentObject); - _insideInternalSetActiveContent = true; - Layout.ActiveContent = layoutContent; - _insideInternalSetActiveContent = false; - } - - public event EventHandler ActiveContentChanged; - - #endregion - - #region AnchorableContextMenu - - /// - /// AnchorableContextMenu Dependency Property - /// - public static readonly DependencyProperty AnchorableContextMenuProperty = - DependencyProperty.Register("AnchorableContextMenu", typeof(ContextMenu), typeof(DockingManager), - new FrameworkPropertyMetadata((ContextMenu)null)); - - /// - /// Gets or sets the AnchorableContextMenu property. This dependency property - /// indicates the context menu to show up for anchorables. - /// - public ContextMenu AnchorableContextMenu - { - get { return (ContextMenu)GetValue(AnchorableContextMenuProperty); } - set { SetValue(AnchorableContextMenuProperty, value); } - } - - #endregion - - #region Theme - - /// - /// Theme Dependency Property - /// - public static readonly DependencyProperty ThemeProperty = - DependencyProperty.Register("Theme", typeof(Theme), typeof(DockingManager), - new FrameworkPropertyMetadata(null, - new PropertyChangedCallback(OnThemeChanged))); - - /// - /// Gets or sets the Theme property. This dependency property - /// indicates the theme to use for AvalonDock controls. - /// - public Theme Theme - { - get { return (Theme)GetValue(ThemeProperty); } - set { SetValue(ThemeProperty, value); } - } - - /// - /// Handles changes to the Theme property. - /// - private static void OnThemeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnThemeChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the Theme property. - /// - protected virtual void OnThemeChanged(DependencyPropertyChangedEventArgs e) - { - var oldTheme = e.OldValue as Theme; - var newTheme = e.NewValue as Theme; - var resources = Application.Current == null ? this.Resources : Application.Current.Resources; - if (oldTheme != null) - { - var resourceDictionaryToRemove = - resources.MergedDictionaries.FirstOrDefault(r => r.Source == oldTheme.GetResourceUri()); - if (resourceDictionaryToRemove != null) - resources.MergedDictionaries.Remove( - resourceDictionaryToRemove); - } - - if (newTheme != null) - { - resources.MergedDictionaries.Add(new ResourceDictionary() { Source = newTheme.GetResourceUri() }); - } - - if (Application.Current == null) - { - foreach (var fwc in _fwList) - fwc.UpdateThemeResources(oldTheme); - - if (_navigatorWindow != null) - _navigatorWindow.UpdateThemeResources(); - - if (_overlayWindow != null) - _overlayWindow.UpdateThemeResources(); - } - } - - #endregion - - #region GridSplitterWidth - - /// - /// GridSplitterWidth Dependency Property - /// - public static readonly DependencyProperty GridSplitterWidthProperty = - DependencyProperty.Register("GridSplitterWidth", typeof(double), typeof(DockingManager), - new FrameworkPropertyMetadata((double)6.0)); - - /// - /// Gets or sets the GridSplitterWidth property. This dependency property - /// indicates width of grid splitters. - /// - public double GridSplitterWidth - { - get { return (double)GetValue(GridSplitterWidthProperty); } - set { SetValue(GridSplitterWidthProperty, value); } - } - - #endregion - - #region GridSplitterHeight - - /// - /// GridSplitterHeight Dependency Property - /// - public static readonly DependencyProperty GridSplitterHeightProperty = - DependencyProperty.Register("GridSplitterHeight", typeof(double), typeof(DockingManager), - new FrameworkPropertyMetadata((double)6.0)); - - /// - /// Gets or sets the GridSplitterHeight property. This dependency property - /// indicates height of grid splitters. - /// - public double GridSplitterHeight - { - get { return (double)GetValue(GridSplitterHeightProperty); } - set { SetValue(GridSplitterHeightProperty, value); } - } - - #endregion - - internal void _ExecuteContentActivateCommand(LayoutContent content) - { - content.IsActive = true; - } - - #region DocumentPaneMenuItemHeaderTemplate - - /// - /// DocumentPaneMenuItemHeaderTemplate Dependency Property - /// - public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateProperty = - DependencyProperty.Register("DocumentPaneMenuItemHeaderTemplate", typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, - new PropertyChangedCallback(OnDocumentPaneMenuItemHeaderTemplateChanged), - new CoerceValueCallback(CoerceDocumentPaneMenuItemHeaderTemplateValue))); - - /// - /// Gets or sets the DocumentPaneMenuItemHeaderTemplate property. This dependency property - /// indicates the header template to use while creating menu items for the document panes. - /// - public DataTemplate DocumentPaneMenuItemHeaderTemplate - { - get { return (DataTemplate)GetValue(DocumentPaneMenuItemHeaderTemplateProperty); } - set { SetValue(DocumentPaneMenuItemHeaderTemplateProperty, value); } - } - - /// - /// Handles changes to the DocumentPaneMenuItemHeaderTemplate property. - /// - private static void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplate property. - /// - protected virtual void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// - /// Coerces the DocumentPaneMenuItemHeaderTemplate value. - /// - private static object CoerceDocumentPaneMenuItemHeaderTemplateValue(DependencyObject d, object value) - { - if (value != null && - d.GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty) != null) - return null; - if (value == null) - return d.GetValue(DocumentHeaderTemplateProperty); - - return value; - } - - #endregion - - #region DocumentPaneMenuItemHeaderTemplateSelector - - /// - /// DocumentPaneMenuItemHeaderTemplateSelector Dependency Property - /// - public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateSelectorProperty = - DependencyProperty.Register("DocumentPaneMenuItemHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null, - new PropertyChangedCallback(OnDocumentPaneMenuItemHeaderTemplateSelectorChanged), - new CoerceValueCallback(CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue))); - - /// - /// Gets or sets the DocumentPaneMenuItemHeaderTemplateSelector property. This dependency property - /// indicates the data template selector to use for the menu items show when user select the DocumentPane document switch context menu. - /// - public DataTemplateSelector DocumentPaneMenuItemHeaderTemplateSelector - { - get { return (DataTemplateSelector)GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty); } - set { SetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty, value); } - } - - /// - /// Handles changes to the DocumentPaneMenuItemHeaderTemplateSelector property. - /// - private static void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplateSelector property. - /// - protected virtual void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null && - DocumentPaneMenuItemHeaderTemplate != null) - DocumentPaneMenuItemHeaderTemplate = null; - - } - - /// - /// Coerces the DocumentPaneMenuItemHeaderTemplateSelector value. - /// - private static object CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue(DependencyObject d, object value) - { - return value; - } - - #endregion - - #region IconContentTemplate - - /// - /// IconContentTemplate Dependency Property - /// - public static readonly DependencyProperty IconContentTemplateProperty = - DependencyProperty.Register("IconContentTemplate", typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null)); - - /// - /// Gets or sets the IconContentTemplate property. This dependency property - /// indicates the data template to use while extracting the icon from model. - /// - public DataTemplate IconContentTemplate - { - get { return (DataTemplate)GetValue(IconContentTemplateProperty); } - set { SetValue(IconContentTemplateProperty, value); } - } - - #endregion - - #region IconContentTemplateSelector - - /// - /// IconContentTemplateSelector Dependency Property - /// - public static readonly DependencyProperty IconContentTemplateSelectorProperty = - DependencyProperty.Register("IconContentTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null)); - - /// - /// Gets or sets the IconContentTemplateSelector property. This dependency property - /// indicates data template selector to use while selecting the datatamplate for content icons. - /// - public DataTemplateSelector IconContentTemplateSelector - { - get { return (DataTemplateSelector)GetValue(IconContentTemplateSelectorProperty); } - set { SetValue(IconContentTemplateSelectorProperty, value); } - } - - #endregion - - #region LayoutItems - - List _layoutItems = new List(); - - public List LayoutItems => _layoutItems; - - bool _suspendLayoutItemCreation = false; - - void DetachLayoutItems() - { - if (Layout != null) - { - _layoutItems.ForEach(i => i.Detach()); - _layoutItems.Clear(); - Layout.ElementAdded -= new EventHandler(Layout_ElementAdded); - Layout.ElementRemoved -= new EventHandler(Layout_ElementRemoved); - } - } - - void Layout_ElementRemoved(object sender, LayoutElementEventArgs e) - { - if (_suspendLayoutItemCreation) - return; - - CollectLayoutItemsDeleted(); - } - - void Layout_ElementAdded(object sender, LayoutElementEventArgs e) - { - if (_suspendLayoutItemCreation) - return; - - foreach (var content in Layout.Descendents().OfType()) - { - if (content is LayoutDocument) - CreateDocumentLayoutItem(content as LayoutDocument); - else //if (content is LayoutAnchorable) - CreateAnchorableLayoutItem(content as LayoutAnchorable); - } - - CollectLayoutItemsDeleted(); - } - - - DispatcherOperation _collectLayoutItemsOperations = null; - void CollectLayoutItemsDeleted() - { - if (_collectLayoutItemsOperations != null) - return; - _collectLayoutItemsOperations = Dispatcher.BeginInvoke(new Action(() => - { - _collectLayoutItemsOperations = null; - foreach (var itemToRemove in _layoutItems.Where(item => item.LayoutElement.Root != Layout).ToArray()) - { - - if (itemToRemove != null && - itemToRemove.Model != null && - itemToRemove.Model is UIElement) - { - //((ILogicalChildrenContainer)this).InternalRemoveLogicalChild(itemToRemove.Model as UIElement); - } - - itemToRemove.Detach(); - _layoutItems.Remove(itemToRemove); - - } - })); - } - - - void AttachLayoutItems() - { - if (Layout != null) - { - foreach (var document in Layout.Descendents().OfType().ToArray()) - { - CreateDocumentLayoutItem(document); - //var documentItem = new LayoutDocumentItem(); - //documentItem.Attach(document); - //ApplyStyleToLayoutItem(documentItem); - //_layoutItems.Add(documentItem); - } - foreach (var anchorable in Layout.Descendents().OfType().ToArray()) - { - CreateAnchorableLayoutItem(anchorable); - //var anchorableItem = new LayoutAnchorableItem(); - //anchorableItem.Attach(anchorable); - //ApplyStyleToLayoutItem(anchorableItem); - //_layoutItems.Add(anchorableItem); - } - - Layout.ElementAdded += new EventHandler(Layout_ElementAdded); - Layout.ElementRemoved += new EventHandler(Layout_ElementRemoved); - } - } - - void ApplyStyleToLayoutItem(LayoutItem layoutItem) - { - layoutItem._ClearDefaultBindings(); - if (LayoutItemContainerStyle != null) - layoutItem.Style = LayoutItemContainerStyle; - else if (LayoutItemContainerStyleSelector != null) - layoutItem.Style = LayoutItemContainerStyleSelector.SelectStyle(layoutItem.Model, layoutItem); - layoutItem._SetDefaultBindings(); - } - - void CreateAnchorableLayoutItem(LayoutAnchorable contentToAttach) - { - if (_layoutItems.Any(item => item.LayoutElement == contentToAttach)) - return; - - var layoutItem = new LayoutAnchorableItem(); - layoutItem.Attach(contentToAttach); - ApplyStyleToLayoutItem(layoutItem); - _layoutItems.Add(layoutItem); - - if (contentToAttach != null && - contentToAttach.Content != null && - contentToAttach.Content is UIElement) - { - InternalAddLogicalChild(contentToAttach.Content); - } - - } - - void CreateDocumentLayoutItem(LayoutDocument contentToAttach) - { - if (_layoutItems.Any(item => item.LayoutElement == contentToAttach)) - return; - - var layoutItem = new LayoutDocumentItem(); - layoutItem.Attach(contentToAttach); - ApplyStyleToLayoutItem(layoutItem); - _layoutItems.Add(layoutItem); - - if (contentToAttach != null && - contentToAttach.Content != null && - contentToAttach.Content is UIElement) - { - InternalAddLogicalChild(contentToAttach.Content); - } - - } - - #region LayoutItemContainerStyle - - /// - /// LayoutItemContainerStyle Dependency Property - /// - public static readonly DependencyProperty LayoutItemContainerStyleProperty = - DependencyProperty.Register("LayoutItemContainerStyle", typeof(Style), typeof(DockingManager), - new FrameworkPropertyMetadata((Style)null, - new PropertyChangedCallback(OnLayoutItemContainerStyleChanged))); - - /// - /// Gets or sets the LayoutItemContainerStyle property. This dependency property - /// indicates the style to apply to LayoutDocumentItem objects. A LayoutDocumentItem object is created when a new LayoutDocument is created inside the current Layout. - /// - public Style LayoutItemContainerStyle - { - get { return (Style)GetValue(LayoutItemContainerStyleProperty); } - set { SetValue(LayoutItemContainerStyleProperty, value); } - } - - /// - /// Handles changes to the LayoutItemContainerStyle property. - /// - private static void OnLayoutItemContainerStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnLayoutItemContainerStyleChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyle property. - /// - protected virtual void OnLayoutItemContainerStyleChanged(DependencyPropertyChangedEventArgs e) - { - AttachLayoutItems(); - } - - #endregion - - #region LayoutItemContainerStyleSelector - - /// - /// LayoutItemContainerStyleSelector Dependency Property - /// - public static readonly DependencyProperty LayoutItemContainerStyleSelectorProperty = - DependencyProperty.Register("LayoutItemContainerStyleSelector", typeof(StyleSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((StyleSelector)null, - new PropertyChangedCallback(OnLayoutItemContainerStyleSelectorChanged))); - - /// - /// Gets or sets the LayoutItemContainerStyleSelector property. This dependency property - /// indicates style selector of the LayoutDocumentItemStyle. - /// - public StyleSelector LayoutItemContainerStyleSelector - { - get { return (StyleSelector)GetValue(LayoutItemContainerStyleSelectorProperty); } - set { SetValue(LayoutItemContainerStyleSelectorProperty, value); } - } - - /// - /// Handles changes to the LayoutItemContainerStyleSelector property. - /// - private static void OnLayoutItemContainerStyleSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnLayoutItemContainerStyleSelectorChanged(e); - } - - /// - /// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyleSelector property. - /// - protected virtual void OnLayoutItemContainerStyleSelectorChanged(DependencyPropertyChangedEventArgs e) - { - AttachLayoutItems(); - } - - #endregion - - /// - /// Return the LayoutItem wrapper for the content passed as argument - /// - /// LayoutContent to search - /// Either a LayoutAnchorableItem or LayoutDocumentItem which contains the LayoutContent passed as argument - public LayoutItem GetLayoutItemFromModel(LayoutContent content) - { - return _layoutItems.FirstOrDefault(item => item.LayoutElement == content); - } - #endregion - - #region NavigatorWindow - NavigatorWindow _navigatorWindow = null; - - void ShowNavigatorWindow() - { - if (_navigatorWindow == null) - { - _navigatorWindow = new NavigatorWindow(this) - { - Owner = Window.GetWindow(this), - WindowStartupLocation = WindowStartupLocation.CenterOwner - }; - } - - _navigatorWindow.ShowDialog(); - _navigatorWindow = null; - - Trace.WriteLine( "ShowNavigatorWindow()" ); - } - - bool IsNavigatorWindowActive - { - get { return _navigatorWindow != null; } - } - - - protected override void OnPreviewKeyDown(KeyEventArgs e) - { - Trace.WriteLine( string.Format( "OnPreviewKeyDown({0})", e.Key ) ); - if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) - { - if (e.IsDown && e.Key == Key.Tab) - { - if (!IsNavigatorWindowActive) - { - ShowNavigatorWindow(); - e.Handled = true; - } - } - } - - base.OnPreviewKeyDown(e); - } - - #endregion - - #region ShowSystemMenu - - /// - /// ShowSystemMenu Dependency Property - /// - public static readonly DependencyProperty ShowSystemMenuProperty = - DependencyProperty.Register("ShowSystemMenu", typeof(bool), typeof(DockingManager), - new FrameworkPropertyMetadata((bool)true)); - - /// - /// Gets or sets the ShowSystemMenu property. This dependency property - /// indicates if floating windows should show the system menu when a custom context menu is not defined. - /// - public bool ShowSystemMenu - { - get { return (bool)GetValue(ShowSystemMenuProperty); } - set { SetValue(ShowSystemMenuProperty, value); } - } - - #endregion - - #region AllowMixedOrientation - - /// - /// AllowMixedOrientation Dependency Property - /// - public static readonly DependencyProperty AllowMixedOrientationProperty = - DependencyProperty.Register("AllowMixedOrientation", typeof(bool), typeof(DockingManager), - new FrameworkPropertyMetadata((bool)false)); - - /// - /// Gets or sets the AllowMixedOrientation property. This dependency property - /// indicates if the manager should allow mixed orientation for document panes. - /// - public bool AllowMixedOrientation - { - get { return (bool)GetValue(AllowMixedOrientationProperty); } - set { SetValue(AllowMixedOrientationProperty, value); } - } - - #endregion - - - } + if( _logicalChildren.Select( ch => ch.GetValueOrDefault() ).Contains( element ) ) + return; + + if (((FrameworkElement)element).Parent != null) + { + (((FrameworkElement)element).Parent as DockingManager).InternalRemoveLogicalChild(element); + } + + _logicalChildren.Add( new WeakReference( element ) ); + AddLogicalChild( element ); + } + + internal void InternalRemoveLogicalChild( object element ) + { + var wrToRemove = _logicalChildren.FirstOrDefault( ch => ch.GetValueOrDefault() == element ); + if( wrToRemove != null ) + _logicalChildren.Remove( wrToRemove ); + RemoveLogicalChild( element ); + } + + private void ClearLogicalChildrenList() + { + foreach( var child in _logicalChildren.Select( ch => ch.GetValueOrDefault() ).ToArray() ) + RemoveLogicalChild( child ); + _logicalChildren.Clear(); + } + + #endregion + + #region AutoHideWindow + + /// + /// AutoHideWindow Read-Only Dependency Property + /// + private static readonly DependencyPropertyKey AutoHideWindowPropertyKey = DependencyProperty.RegisterReadOnly( "AutoHideWindow", typeof( LayoutAutoHideWindowControl ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( LayoutAutoHideWindowControl )null, new PropertyChangedCallback( OnAutoHideWindowChanged ) ) ); + + public static readonly DependencyProperty AutoHideWindowProperty = AutoHideWindowPropertyKey.DependencyProperty; + + /// + /// Gets the AutoHideWindow property. This dependency property + /// indicates the currently shown autohide window. + /// + public LayoutAutoHideWindowControl AutoHideWindow + { + get + { + return ( LayoutAutoHideWindowControl )GetValue( AutoHideWindowProperty ); + } + } + + /// + /// Provides a secure method for setting the AutoHideWindow property. + /// This dependency property indicates the currently shown autohide window. + /// + /// The new value for the property. + protected void SetAutoHideWindow( LayoutAutoHideWindowControl value ) + { + SetValue( AutoHideWindowPropertyKey, value ); + } + + /// + /// Handles changes to the AutoHideWindow property. + /// + private static void OnAutoHideWindowChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnAutoHideWindowChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AutoHideWindow property. + /// + protected virtual void OnAutoHideWindowChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.OldValue != null ) + InternalRemoveLogicalChild( e.OldValue ); + if( e.NewValue != null ) + InternalAddLogicalChild( e.NewValue ); + + } + + #endregion + + #region Floating Windows + + public IEnumerable FloatingWindows + { + get + { + return _fwList; + } + } + + #endregion + + #region LayoutItemTemplate + + /// + /// LayoutItemTemplate Dependency Property + /// + public static readonly DependencyProperty LayoutItemTemplateProperty = DependencyProperty.Register( "LayoutItemTemplate", typeof( DataTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnLayoutItemTemplateChanged ) ) ); + + /// + /// Gets or sets the AnchorableTemplate property. This dependency property + /// indicates the template to use to render anchorable and document contents. + /// + public DataTemplate LayoutItemTemplate + { + get + { + return ( DataTemplate )GetValue( LayoutItemTemplateProperty ); + } + set + { + SetValue( LayoutItemTemplateProperty, value ); + } + } + + /// + /// Handles changes to the AnchorableTemplate property. + /// + private static void OnLayoutItemTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnLayoutItemTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AnchorableTemplate property. + /// + protected virtual void OnLayoutItemTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + } + + #endregion + + #region LayoutItemTemplateSelector + + /// + /// LayoutItemTemplateSelector Dependency Property + /// + public static readonly DependencyProperty LayoutItemTemplateSelectorProperty = DependencyProperty.Register( "LayoutItemTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnLayoutItemTemplateSelectorChanged ) ) ); + + /// + /// Gets or sets the LayoutItemTemplateSelector property. This dependency property + /// indicates selector object to use for anchorable templates. + /// + public DataTemplateSelector LayoutItemTemplateSelector + { + get + { + return ( DataTemplateSelector )GetValue( LayoutItemTemplateSelectorProperty ); + } + set + { + SetValue( LayoutItemTemplateSelectorProperty, value ); + } + } + + /// + /// Handles changes to the LayoutItemTemplateSelector property. + /// + private static void OnLayoutItemTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnLayoutItemTemplateSelectorChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the LayoutItemTemplateSelector property. + /// + protected virtual void OnLayoutItemTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) + { + } + + #endregion + + #region DocumentsSource + + /// + /// DocumentsSource Dependency Property + /// + public static readonly DependencyProperty DocumentsSourceProperty = DependencyProperty.Register( "DocumentsSource", typeof( IEnumerable ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( IEnumerable )null, new PropertyChangedCallback( OnDocumentsSourceChanged ) ) ); + + /// + /// Gets or sets the DocumentsSource property. This dependency property + /// indicates the source collection of documents. + /// + public IEnumerable DocumentsSource + { + get + { + return ( IEnumerable )GetValue( DocumentsSourceProperty ); + } + set + { + SetValue( DocumentsSourceProperty, value ); + } + } + + /// + /// Handles changes to the DocumentsSource property. + /// + private static void OnDocumentsSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentsSourceChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentsSource property. + /// + protected virtual void OnDocumentsSourceChanged( DependencyPropertyChangedEventArgs e ) + { + DetachDocumentsSource( Layout, e.OldValue as IEnumerable ); + AttachDocumentsSource( Layout, e.NewValue as IEnumerable ); + } + + #endregion + + #region DocumentContextMenu + + /// + /// DocumentContextMenu Dependency Property + /// + public static readonly DependencyProperty DocumentContextMenuProperty = DependencyProperty.Register( "DocumentContextMenu", typeof( ContextMenu ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( ContextMenu )null ) ); + + /// + /// Gets or sets the DocumentContextMenu property. This dependency property + /// indicates context menu to show for documents. + /// + public ContextMenu DocumentContextMenu + { + get + { + return ( ContextMenu )GetValue( DocumentContextMenuProperty ); + } + set + { + SetValue( DocumentContextMenuProperty, value ); + } + } + + #endregion + + #region AnchorablesSource + + /// + /// AnchorablesSource Dependency Property + /// + public static readonly DependencyProperty AnchorablesSourceProperty = DependencyProperty.Register( "AnchorablesSource", typeof( IEnumerable ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( IEnumerable )null, new PropertyChangedCallback( OnAnchorablesSourceChanged ) ) ); + + /// + /// Gets or sets the AnchorablesSource property. This dependency property + /// indicates source collection of anchorables. + /// + public IEnumerable AnchorablesSource + { + get + { + return ( IEnumerable )GetValue( AnchorablesSourceProperty ); + } + set + { + SetValue( AnchorablesSourceProperty, value ); + } + } + + /// + /// Handles changes to the AnchorablesSource property. + /// + private static void OnAnchorablesSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnAnchorablesSourceChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the AnchorablesSource property. + /// + protected virtual void OnAnchorablesSourceChanged( DependencyPropertyChangedEventArgs e ) + { + DetachAnchorablesSource( Layout, e.OldValue as IEnumerable ); + AttachAnchorablesSource( Layout, e.NewValue as IEnumerable ); + } + + + + #endregion + + #region ActiveContent + + /// + /// ActiveContent Dependency Property + /// + public static readonly DependencyProperty ActiveContentProperty = DependencyProperty.Register( "ActiveContent", typeof( object ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( object )null, new PropertyChangedCallback( OnActiveContentChanged ) ) ); + + /// + /// Gets or sets the ActiveContent property. This dependency property + /// indicates the content currently active. + /// + public object ActiveContent + { + get + { + return ( object )GetValue( ActiveContentProperty ); + } + set + { + SetValue( ActiveContentProperty, value ); + } + } + + /// + /// Handles changes to the ActiveContent property. + /// + private static void OnActiveContentChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).InternalSetActiveContent( e.NewValue ); + ( ( DockingManager )d ).OnActiveContentChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the ActiveContent property. + /// + protected virtual void OnActiveContentChanged( DependencyPropertyChangedEventArgs e ) + { + if( ActiveContentChanged != null ) + ActiveContentChanged( this, EventArgs.Empty ); + } + + #endregion + + #region AnchorableContextMenu + + /// + /// AnchorableContextMenu Dependency Property + /// + public static readonly DependencyProperty AnchorableContextMenuProperty = DependencyProperty.Register( "AnchorableContextMenu", typeof( ContextMenu ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( ContextMenu )null ) ); + + /// + /// Gets or sets the AnchorableContextMenu property. This dependency property + /// indicates the context menu to show up for anchorables. + /// + public ContextMenu AnchorableContextMenu + { + get + { + return ( ContextMenu )GetValue( AnchorableContextMenuProperty ); + } + set + { + SetValue( AnchorableContextMenuProperty, value ); + } + } + + #endregion + + #region Theme + + /// + /// Theme Dependency Property + /// + public static readonly DependencyProperty ThemeProperty = DependencyProperty.Register( "Theme", typeof( Theme ), typeof( DockingManager ), + new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnThemeChanged ) ) ); + + /// + /// Gets or sets the Theme property. This dependency property + /// indicates the theme to use for AvalonDock controls. + /// + public Theme Theme + { + get + { + return ( Theme )GetValue( ThemeProperty ); + } + set + { + SetValue( ThemeProperty, value ); + } + } + + /// + /// Handles changes to the Theme property. + /// + private static void OnThemeChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnThemeChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the Theme property. + /// + protected virtual void OnThemeChanged( DependencyPropertyChangedEventArgs e ) + { + var oldTheme = e.OldValue as Theme; + var newTheme = e.NewValue as Theme; + var resources = Application.Current == null ? this.Resources : Application.Current.Resources; + if ( oldTheme != null ) + { + if( oldTheme is DictionaryTheme ) + { + if( currentThemeResourceDictionary != null ) + { + resources.MergedDictionaries.Remove( currentThemeResourceDictionary ); + currentThemeResourceDictionary = null; + } + } + else + { + var resourceDictionaryToRemove = + resources.MergedDictionaries.FirstOrDefault( r => r.Source == oldTheme.GetResourceUri() ); + if( resourceDictionaryToRemove != null ) + resources.MergedDictionaries.Remove( + resourceDictionaryToRemove ); + } + } + + if( newTheme != null ) + { + if( newTheme is DictionaryTheme ) + { + currentThemeResourceDictionary = ( ( DictionaryTheme )newTheme ).ThemeResourceDictionary; + resources.MergedDictionaries.Add( currentThemeResourceDictionary ); + } + else + { + resources.MergedDictionaries.Add( new ResourceDictionary() { Source = newTheme.GetResourceUri() } ); + } + } + + if (Application.Current == null) + { + foreach (var fwc in _fwList) + fwc.UpdateThemeResources(oldTheme); + + if (_navigatorWindow != null) + _navigatorWindow.UpdateThemeResources(); + + if (_overlayWindow != null) + _overlayWindow.UpdateThemeResources(); + } + } + + #endregion + + #region GridSplitterWidth + + /// + /// GridSplitterWidth Dependency Property + /// + public static readonly DependencyProperty GridSplitterWidthProperty = DependencyProperty.Register( "GridSplitterWidth", typeof( double ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( double )6.0 ) ); + + /// + /// Gets or sets the GridSplitterWidth property. This dependency property + /// indicates width of grid splitters. + /// + public double GridSplitterWidth + { + get + { + return ( double )GetValue( GridSplitterWidthProperty ); + } + set + { + SetValue( GridSplitterWidthProperty, value ); + } + } + + #endregion + + #region GridSplitterHeight + + /// + /// GridSplitterHeight Dependency Property + /// + public static readonly DependencyProperty GridSplitterHeightProperty = DependencyProperty.Register( "GridSplitterHeight", typeof( double ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( double )6.0 ) ); + + /// + /// Gets or sets the GridSplitterHeight property. This dependency property + /// indicates height of grid splitters. + /// + public double GridSplitterHeight + { + get + { + return ( double )GetValue( GridSplitterHeightProperty ); + } + set + { + SetValue( GridSplitterHeightProperty, value ); + } + } + + #endregion + + #region DocumentPaneMenuItemHeaderTemplate + + /// + /// DocumentPaneMenuItemHeaderTemplate Dependency Property + /// + public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateProperty = DependencyProperty.Register( "DocumentPaneMenuItemHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentPaneMenuItemHeaderTemplateChanged ), new CoerceValueCallback( CoerceDocumentPaneMenuItemHeaderTemplateValue ) ) ); + + /// + /// Gets or sets the DocumentPaneMenuItemHeaderTemplate property. This dependency property + /// indicates the header template to use while creating menu items for the document panes. + /// + public DataTemplate DocumentPaneMenuItemHeaderTemplate + { + get + { + return ( DataTemplate )GetValue( DocumentPaneMenuItemHeaderTemplateProperty ); + } + set + { + SetValue( DocumentPaneMenuItemHeaderTemplateProperty, value ); + } + } + + /// + /// Handles changes to the DocumentPaneMenuItemHeaderTemplate property. + /// + private static void OnDocumentPaneMenuItemHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentPaneMenuItemHeaderTemplateChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplate property. + /// + protected virtual void OnDocumentPaneMenuItemHeaderTemplateChanged( DependencyPropertyChangedEventArgs e ) + { + } + + /// + /// Coerces the DocumentPaneMenuItemHeaderTemplate value. + /// + private static object CoerceDocumentPaneMenuItemHeaderTemplateValue( DependencyObject d, object value ) + { + if( value != null && + d.GetValue( DocumentPaneMenuItemHeaderTemplateSelectorProperty ) != null ) + return null; + if( value == null ) + return d.GetValue( DocumentHeaderTemplateProperty ); + + return value; + } + + #endregion + + #region DocumentPaneMenuItemHeaderTemplateSelector + + /// + /// DocumentPaneMenuItemHeaderTemplateSelector Dependency Property + /// + public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateSelectorProperty = DependencyProperty.Register( "DocumentPaneMenuItemHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentPaneMenuItemHeaderTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue ) ) ); + + /// + /// Gets or sets the DocumentPaneMenuItemHeaderTemplateSelector property. This dependency property + /// indicates the data template selector to use for the menu items show when user select the DocumentPane document switch context menu. + /// + public DataTemplateSelector DocumentPaneMenuItemHeaderTemplateSelector + { + get + { + return ( DataTemplateSelector )GetValue( DocumentPaneMenuItemHeaderTemplateSelectorProperty ); + } + set + { + SetValue( DocumentPaneMenuItemHeaderTemplateSelectorProperty, value ); + } + } + + /// + /// Handles changes to the DocumentPaneMenuItemHeaderTemplateSelector property. + /// + private static void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplateSelector property. + /// + protected virtual void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) + { + if( e.NewValue != null && + DocumentPaneMenuItemHeaderTemplate != null ) + DocumentPaneMenuItemHeaderTemplate = null; + + } + + /// + /// Coerces the DocumentPaneMenuItemHeaderTemplateSelector value. + /// + private static object CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue( DependencyObject d, object value ) + { + return value; + } + + #endregion + + #region IconContentTemplate + + /// + /// IconContentTemplate Dependency Property + /// + public static readonly DependencyProperty IconContentTemplateProperty = DependencyProperty.Register( "IconContentTemplate", typeof( DataTemplate ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplate )null ) ); + + /// + /// Gets or sets the IconContentTemplate property. This dependency property + /// indicates the data template to use while extracting the icon from model. + /// + public DataTemplate IconContentTemplate + { + get + { + return ( DataTemplate )GetValue( IconContentTemplateProperty ); + } + set + { + SetValue( IconContentTemplateProperty, value ); + } + } + + #endregion + + #region IconContentTemplateSelector + + /// + /// IconContentTemplateSelector Dependency Property + /// + public static readonly DependencyProperty IconContentTemplateSelectorProperty = DependencyProperty.Register( "IconContentTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( DataTemplateSelector )null ) ); + + /// + /// Gets or sets the IconContentTemplateSelector property. This dependency property + /// indicates data template selector to use while selecting the datatamplate for content icons. + /// + public DataTemplateSelector IconContentTemplateSelector + { + get + { + return ( DataTemplateSelector )GetValue( IconContentTemplateSelectorProperty ); + } + set + { + SetValue( IconContentTemplateSelectorProperty, value ); + } + } + + #endregion + + #region LayoutItemContainerStyle + + /// + /// LayoutItemContainerStyle Dependency Property + /// + public static readonly DependencyProperty LayoutItemContainerStyleProperty = DependencyProperty.Register( "LayoutItemContainerStyle", typeof( Style ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnLayoutItemContainerStyleChanged ) ) ); + + /// + /// Gets or sets the LayoutItemContainerStyle property. This dependency property + /// indicates the style to apply to LayoutDocumentItem objects. A LayoutDocumentItem object is created when a new LayoutDocument is created inside the current Layout. + /// + public Style LayoutItemContainerStyle + { + get + { + return ( Style )GetValue( LayoutItemContainerStyleProperty ); + } + set + { + SetValue( LayoutItemContainerStyleProperty, value ); + } + } + + /// + /// Handles changes to the LayoutItemContainerStyle property. + /// + private static void OnLayoutItemContainerStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnLayoutItemContainerStyleChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyle property. + /// + protected virtual void OnLayoutItemContainerStyleChanged( DependencyPropertyChangedEventArgs e ) + { + AttachLayoutItems(); + } + + #endregion + + #region LayoutItemContainerStyleSelector + + /// + /// LayoutItemContainerStyleSelector Dependency Property + /// + public static readonly DependencyProperty LayoutItemContainerStyleSelectorProperty = DependencyProperty.Register( "LayoutItemContainerStyleSelector", typeof( StyleSelector ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( StyleSelector )null, new PropertyChangedCallback( OnLayoutItemContainerStyleSelectorChanged ) ) ); + + /// + /// Gets or sets the LayoutItemContainerStyleSelector property. This dependency property + /// indicates style selector of the LayoutDocumentItemStyle. + /// + public StyleSelector LayoutItemContainerStyleSelector + { + get + { + return ( StyleSelector )GetValue( LayoutItemContainerStyleSelectorProperty ); + } + set + { + SetValue( LayoutItemContainerStyleSelectorProperty, value ); + } + } + + /// + /// Handles changes to the LayoutItemContainerStyleSelector property. + /// + private static void OnLayoutItemContainerStyleSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) + { + ( ( DockingManager )d ).OnLayoutItemContainerStyleSelectorChanged( e ); + } + + /// + /// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyleSelector property. + /// + protected virtual void OnLayoutItemContainerStyleSelectorChanged( DependencyPropertyChangedEventArgs e ) + { + AttachLayoutItems(); + } + + #endregion + + #region ShowSystemMenu + + /// + /// ShowSystemMenu Dependency Property + /// + public static readonly DependencyProperty ShowSystemMenuProperty = DependencyProperty.Register( "ShowSystemMenu", typeof( bool ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( bool )true ) ); + + /// + /// Gets or sets the ShowSystemMenu property. This dependency property + /// indicates if floating windows should show the system menu when a custom context menu is not defined. + /// + public bool ShowSystemMenu + { + get + { + return ( bool )GetValue( ShowSystemMenuProperty ); + } + set + { + SetValue( ShowSystemMenuProperty, value ); + } + } + + #endregion + + #region AllowMixedOrientation + + /// + /// AllowMixedOrientation Dependency Property + /// + public static readonly DependencyProperty AllowMixedOrientationProperty = DependencyProperty.Register( "AllowMixedOrientation", typeof( bool ), typeof( DockingManager ), + new FrameworkPropertyMetadata( ( bool )false ) ); + + /// + /// Gets or sets the AllowMixedOrientation property. This dependency property + /// indicates if the manager should allow mixed orientation for document panes. + /// + public bool AllowMixedOrientation + { + get + { + return ( bool )GetValue( AllowMixedOrientationProperty ); + } + set + { + SetValue( AllowMixedOrientationProperty, value ); + } + } + + #endregion + + #endregion + + #region Private Properties + + private bool IsNavigatorWindowActive + { + get + { + return _navigatorWindow != null; + } + } + + #endregion + + #region Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + + _autohideArea = GetTemplateChild( "PART_AutoHideArea" ) as FrameworkElement; + } + + protected override void OnInitialized( EventArgs e ) + { + base.OnInitialized( e ); + } + + + protected override Size ArrangeOverride( Size arrangeBounds ) + { + _areas = null; + return base.ArrangeOverride( arrangeBounds ); + } + + protected override void OnPreviewKeyDown( KeyEventArgs e ) + { + if( Keyboard.IsKeyDown( Key.LeftCtrl ) || Keyboard.IsKeyDown( Key.RightCtrl ) ) + { + if( e.IsDown && e.Key == Key.Tab ) + { + if( !IsNavigatorWindowActive ) + { + ShowNavigatorWindow(); + e.Handled = true; + } + } + } + + base.OnPreviewKeyDown( e ); + } + + #endregion + + #region Public Methods + + /// + /// Return the LayoutItem wrapper for the content passed as argument + /// + /// LayoutContent to search + /// Either a LayoutAnchorableItem or LayoutDocumentItem which contains the LayoutContent passed as argument + public LayoutItem GetLayoutItemFromModel( LayoutContent content ) + { + return _layoutItems.FirstOrDefault( item => item.LayoutElement == content ); + } + + #endregion + + #region Internal Methods + + internal UIElement CreateUIElementForModel( ILayoutElement model ) + { + if( model is LayoutPanel ) + return new LayoutPanelControl( model as LayoutPanel ); + if( model is LayoutAnchorablePaneGroup ) + return new LayoutAnchorablePaneGroupControl( model as LayoutAnchorablePaneGroup ); + if( model is LayoutDocumentPaneGroup ) + return new LayoutDocumentPaneGroupControl( model as LayoutDocumentPaneGroup ); + + if( model is LayoutAnchorSide ) + { + var templateModelView = new LayoutAnchorSideControl( model as LayoutAnchorSide ); + templateModelView.SetBinding( LayoutAnchorSideControl.TemplateProperty, new Binding( "AnchorSideTemplate" ) { Source = this } ); + return templateModelView; + } + if( model is LayoutAnchorGroup ) + { + var templateModelView = new LayoutAnchorGroupControl( model as LayoutAnchorGroup ); + templateModelView.SetBinding( LayoutAnchorGroupControl.TemplateProperty, new Binding( "AnchorGroupTemplate" ) { Source = this } ); + return templateModelView; + } + + if( model is LayoutDocumentPane ) + { + var templateModelView = new LayoutDocumentPaneControl( model as LayoutDocumentPane ); + templateModelView.SetBinding( LayoutDocumentPaneControl.StyleProperty, new Binding( "DocumentPaneControlStyle" ) { Source = this } ); + return templateModelView; + } + if( model is LayoutAnchorablePane ) + { + var templateModelView = new LayoutAnchorablePaneControl( model as LayoutAnchorablePane ); + templateModelView.SetBinding( LayoutAnchorablePaneControl.StyleProperty, new Binding( "AnchorablePaneControlStyle" ) { Source = this } ); + return templateModelView; + } + + if( model is LayoutAnchorableFloatingWindow ) + { + if( DesignerProperties.GetIsInDesignMode( this ) ) + return null; + var modelFW = model as LayoutAnchorableFloatingWindow; + var newFW = new LayoutAnchorableFloatingWindowControl( modelFW ) + { + //Owner = Window.GetWindow(this) + }; + newFW.SetParentToMainWindowOf( this ); + + var paneForExtensions = modelFW.RootPanel.Children.OfType().FirstOrDefault(); + if( paneForExtensions != null ) + { + //ensure that floating window position is inside current (or nearest) monitor + paneForExtensions.KeepInsideNearestMonitor(); + + newFW.Left = paneForExtensions.FloatingLeft; + newFW.Top = paneForExtensions.FloatingTop; + newFW.Width = paneForExtensions.FloatingWidth; + newFW.Height = paneForExtensions.FloatingHeight; + } + + newFW.ShowInTaskbar = false; + newFW.Show(); + // Do not set the WindowState before showing or it will be lost + if( paneForExtensions != null && paneForExtensions.IsMaximized ) + { + newFW.WindowState = WindowState.Maximized; + } + return newFW; + } + + if( model is LayoutDocumentFloatingWindow ) + { + if( DesignerProperties.GetIsInDesignMode( this ) ) + return null; + var modelFW = model as LayoutDocumentFloatingWindow; + var newFW = new LayoutDocumentFloatingWindowControl( modelFW ) + { + //Owner = Window.GetWindow(this) + }; + newFW.SetParentToMainWindowOf( this ); + + var paneForExtensions = modelFW.RootDocument; + if( paneForExtensions != null ) + { + //ensure that floating window position is inside current (or nearest) monitor + paneForExtensions.KeepInsideNearestMonitor(); + + newFW.Left = paneForExtensions.FloatingLeft; + newFW.Top = paneForExtensions.FloatingTop; + newFW.Width = paneForExtensions.FloatingWidth; + newFW.Height = paneForExtensions.FloatingHeight; + } + + newFW.ShowInTaskbar = false; + newFW.Show(); + // Do not set the WindowState before showing or it will be lost + if( paneForExtensions != null && paneForExtensions.IsMaximized ) + { + newFW.WindowState = WindowState.Maximized; + } + return newFW; + } + + if( model is LayoutDocument ) + { + var templateModelView = new LayoutDocumentControl() { Model = model as LayoutDocument }; + return templateModelView; + } + + return null; + } + + internal void ShowAutoHideWindow( LayoutAnchorControl anchor ) + { + _autoHideWindowManager.ShowAutoHideWindow( anchor ); + //if (_autohideArea == null) + // return; + + //if (AutoHideWindow != null && AutoHideWindow.Model == anchor.Model) + // return; + + //Trace.WriteLine("ShowAutoHideWindow()"); + + //_currentAutohiddenAnchor = new WeakReference(anchor); + + //HideAutoHideWindow(anchor); + + //SetAutoHideWindow(new LayoutAutoHideWindowControl(anchor)); + //AutoHideWindow.Show(); + } + + internal void HideAutoHideWindow( LayoutAnchorControl anchor ) + { + _autoHideWindowManager.HideAutoWindow( anchor ); + } + + internal FrameworkElement GetAutoHideAreaElement() + { + return _autohideArea; + } + + internal void StartDraggingFloatingWindowForContent( LayoutContent contentModel, bool startDrag = true ) + { + if( !contentModel.CanFloat ) + return; + var contentModelAsAnchorable = contentModel as LayoutAnchorable; + if( contentModelAsAnchorable != null && + contentModelAsAnchorable.IsAutoHidden ) + contentModelAsAnchorable.ToggleAutoHide(); + + var parentPane = contentModel.Parent as ILayoutPane; + var parentPaneAsPositionableElement = contentModel.Parent as ILayoutPositionableElement; + var parentPaneAsWithActualSize = contentModel.Parent as ILayoutPositionableElementWithActualSize; + var contentModelParentChildrenIndex = parentPane.Children.ToList().IndexOf( contentModel ); + + if( contentModel.FindParent() == null ) + { + ( ( ILayoutPreviousContainer )contentModel ).PreviousContainer = parentPane; + contentModel.PreviousContainerIndex = contentModelParentChildrenIndex; + } + + parentPane.RemoveChildAt( contentModelParentChildrenIndex ); + + double fwWidth = contentModel.FloatingWidth; + double fwHeight = contentModel.FloatingHeight; + + if( fwWidth == 0.0 ) + fwWidth = parentPaneAsPositionableElement.FloatingWidth; + if( fwHeight == 0.0 ) + fwHeight = parentPaneAsPositionableElement.FloatingHeight; + + if( fwWidth == 0.0 ) + fwWidth = parentPaneAsWithActualSize.ActualWidth + 10; //10 includes BorderThickness and Margins inside LayoutDocumentFloatingWindowControl. + if( fwHeight == 0.0 ) + fwHeight = parentPaneAsWithActualSize.ActualHeight + 10; //10 includes BorderThickness and Margins inside LayoutDocumentFloatingWindowControl. + + LayoutFloatingWindow fw; + LayoutFloatingWindowControl fwc; + if( contentModel is LayoutAnchorable ) + { + var anchorableContent = contentModel as LayoutAnchorable; + fw = new LayoutAnchorableFloatingWindow() + { + RootPanel = new LayoutAnchorablePaneGroup( + new LayoutAnchorablePane( anchorableContent ) + { + DockWidth = parentPaneAsPositionableElement.DockWidth, + DockHeight = parentPaneAsPositionableElement.DockHeight, + DockMinHeight = parentPaneAsPositionableElement.DockMinHeight, + DockMinWidth = parentPaneAsPositionableElement.DockMinWidth, + FloatingLeft = parentPaneAsPositionableElement.FloatingLeft, + FloatingTop = parentPaneAsPositionableElement.FloatingTop, + FloatingWidth = parentPaneAsPositionableElement.FloatingWidth, + FloatingHeight = parentPaneAsPositionableElement.FloatingHeight, + } ) + }; + + Layout.FloatingWindows.Add( fw ); + + fwc = new LayoutAnchorableFloatingWindowControl( + fw as LayoutAnchorableFloatingWindow ) + { + Width = fwWidth, + Height = fwHeight, + Left = contentModel.FloatingLeft, + Top = contentModel.FloatingTop + }; + } + else + { + var anchorableDocument = contentModel as LayoutDocument; + fw = new LayoutDocumentFloatingWindow() + { + RootDocument = anchorableDocument + }; + + Layout.FloatingWindows.Add( fw ); + + fwc = new LayoutDocumentFloatingWindowControl( + fw as LayoutDocumentFloatingWindow ) + { + Width = fwWidth, + Height = fwHeight, + Left = contentModel.FloatingLeft, + Top = contentModel.FloatingTop + }; + } + + + //fwc.Owner = Window.GetWindow(this); + //fwc.SetParentToMainWindowOf(this); + + + _fwList.Add( fwc ); + + Layout.CollectGarbage(); + + UpdateLayout(); + + Dispatcher.BeginInvoke( new Action( () => + { + if( startDrag ) + fwc.AttachDrag(); + fwc.Show(); + } ), DispatcherPriority.Send ); + } + + internal void StartDraggingFloatingWindowForPane( LayoutAnchorablePane paneModel ) + { + if( paneModel.Children.Any( c => !c.CanFloat ) ) + return; + var paneAsPositionableElement = paneModel as ILayoutPositionableElement; + var paneAsWithActualSize = paneModel as ILayoutPositionableElementWithActualSize; + + double fwWidth = paneAsPositionableElement.FloatingWidth; + double fwHeight = paneAsPositionableElement.FloatingHeight; + double fwLeft = paneAsPositionableElement.FloatingLeft; + double fwTop = paneAsPositionableElement.FloatingTop; + + if( fwWidth == 0.0 ) + fwWidth = paneAsWithActualSize.ActualWidth + 10; //10 includes BorderThickness and Margins inside LayoutAnchorableFloatingWindowControl. + if( fwHeight == 0.0 ) + fwHeight = paneAsWithActualSize.ActualHeight + 10; //10 includes BorderThickness and Margins inside LayoutAnchorableFloatingWindowControl. + + var destPane = new LayoutAnchorablePane() + { + DockWidth = paneAsPositionableElement.DockWidth, + DockHeight = paneAsPositionableElement.DockHeight, + DockMinHeight = paneAsPositionableElement.DockMinHeight, + DockMinWidth = paneAsPositionableElement.DockMinWidth, + FloatingLeft = paneAsPositionableElement.FloatingLeft, + FloatingTop = paneAsPositionableElement.FloatingTop, + FloatingWidth = paneAsPositionableElement.FloatingWidth, + FloatingHeight = paneAsPositionableElement.FloatingHeight, + }; + + bool savePreviousContainer = paneModel.FindParent() == null; + int currentSelectedContentIndex = paneModel.SelectedContentIndex; + while( paneModel.Children.Count > 0 ) + { + var contentModel = paneModel.Children[ paneModel.Children.Count - 1 ] as LayoutAnchorable; + + if( savePreviousContainer ) + { + var contentModelAsPreviousContainer = contentModel as ILayoutPreviousContainer; + contentModelAsPreviousContainer.PreviousContainer = paneModel; + contentModel.PreviousContainerIndex = paneModel.Children.Count - 1; + } + + paneModel.RemoveChildAt( paneModel.Children.Count - 1 ); + destPane.Children.Insert( 0, contentModel ); + } + + if( destPane.Children.Count > 0 ) + { + destPane.SelectedContentIndex = currentSelectedContentIndex; + } + + + LayoutFloatingWindow fw; + LayoutFloatingWindowControl fwc; + fw = new LayoutAnchorableFloatingWindow() + { + RootPanel = new LayoutAnchorablePaneGroup( + destPane ) + { + DockHeight = destPane.DockHeight, + DockWidth = destPane.DockWidth, + DockMinHeight = destPane.DockMinHeight, + DockMinWidth = destPane.DockMinWidth, + } + }; + + Layout.FloatingWindows.Add( fw ); + + fwc = new LayoutAnchorableFloatingWindowControl( + fw as LayoutAnchorableFloatingWindow ) + { + Width = fwWidth, + Height = fwHeight + }; + + + + //fwc.Owner = Window.GetWindow(this); + //fwc.SetParentToMainWindowOf(this); + + + _fwList.Add( fwc ); + + Layout.CollectGarbage(); + + InvalidateArrange(); + + fwc.AttachDrag(); + fwc.Show(); + + } + + internal IEnumerable GetFloatingWindowsByZOrder() + { + var parentWindow = Window.GetWindow( this ); + + if( parentWindow == null ) + yield break; + + IntPtr windowParentHanlde = new WindowInteropHelper( parentWindow ).Handle; + + IntPtr currentHandle = Win32Helper.GetWindow( windowParentHanlde, ( uint )Win32Helper.GetWindow_Cmd.GW_HWNDFIRST ); + while( currentHandle != IntPtr.Zero ) + { + LayoutFloatingWindowControl ctrl = _fwList.FirstOrDefault( fw => new WindowInteropHelper( fw ).Handle == currentHandle ); + if( ctrl != null && ctrl.Model.Root.Manager == this ) + yield return ctrl; + + currentHandle = Win32Helper.GetWindow( currentHandle, ( uint )Win32Helper.GetWindow_Cmd.GW_HWNDNEXT ); + } + } + + internal void RemoveFloatingWindow( LayoutFloatingWindowControl floatingWindow ) + { + _fwList.Remove( floatingWindow ); + } + + internal void _ExecuteCloseCommand( LayoutDocument document ) + { + if( DocumentClosing != null ) + { + var evargs = new DocumentClosingEventArgs( document ); + DocumentClosing( this, evargs ); + if( evargs.Cancel ) + return; + } + + if( document.CloseDocument() ) + { + this.RemoveViewFromLogicalChild( document ); + + if( DocumentClosed != null ) + { + var evargs = new DocumentClosedEventArgs( document ); + DocumentClosed( this, evargs ); + } + } + } + + internal void _ExecuteCloseAllButThisCommand( LayoutContent contentSelected ) + { + foreach( var contentToClose in Layout.Descendents().OfType().Where( d => d != contentSelected && ( d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow ) ).ToArray() ) + { + this.Close( contentToClose ); + } + } + + internal void _ExecuteCloseAllCommand( LayoutContent contentSelected ) + { + foreach( var contentToClose in Layout.Descendents().OfType().Where( d => ( d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow ) ).ToArray() ) + { + this.Close( contentToClose ); + } + } + + internal void _ExecuteCloseCommand( LayoutAnchorable anchorable ) + { + var model = anchorable as LayoutAnchorable; + if( model != null ) + { + model.CloseAnchorable(); + this.RemoveViewFromLogicalChild( anchorable ); + } + } + + internal void _ExecuteHideCommand( LayoutAnchorable anchorable ) + { + var model = anchorable as LayoutAnchorable; + if( model != null ) + { + model.Hide(); + } + } + + internal void _ExecuteAutoHideCommand( LayoutAnchorable _anchorable ) + { + _anchorable.ToggleAutoHide(); + } + + + internal void _ExecuteFloatCommand( LayoutContent contentToFloat ) + { + contentToFloat.Float(); + } + + internal void _ExecuteDockCommand( LayoutAnchorable anchorable ) + { + anchorable.Dock(); + } + + internal void _ExecuteDockAsDocumentCommand( LayoutContent content ) + { + content.DockAsDocument(); + } + + internal void _ExecuteContentActivateCommand( LayoutContent content ) + { + content.IsActive = true; + } + + #endregion + + #region Private Methods + + private void OnLayoutRootPropertyChanged( object sender, PropertyChangedEventArgs e ) + { + if( e.PropertyName == "RootPanel" ) + { + if( IsInitialized ) + { + var layoutRootPanel = CreateUIElementForModel( Layout.RootPanel ) as LayoutPanelControl; + LayoutRootPanel = layoutRootPanel; + } + } + else if( e.PropertyName == "ActiveContent" ) + { + if( Layout.ActiveContent != null ) + { + //Debug.WriteLine(new StackTrace().ToString()); + + //set focus on active element only after a layout pass is completed + //it's possible that it is not yet visible in the visual tree + //if (_setFocusAsyncOperation == null) + //{ + // _setFocusAsyncOperation = Dispatcher.BeginInvoke(new Action(() => + // { + if( Layout.ActiveContent != null ) + FocusElementManager.SetFocusOnLastElement( Layout.ActiveContent ); + //_setFocusAsyncOperation = null; + // } ), DispatcherPriority.Input ); + //} + } + + //if (!_insideInternalSetActiveContent) + // ActiveContent = Layout.ActiveContent != null ? + // Layout.ActiveContent.Content : null; + if( !_insideInternalSetActiveContent && ( Layout.ActiveContent != null ) ) + { + this.ActiveContent = Layout.ActiveContent.Content; + } + } + } + + private void OnLayoutRootUpdated( object sender, EventArgs e ) + { + CommandManager.InvalidateRequerySuggested(); + } + + private void OnLayoutChanging( LayoutRoot newLayout ) + { + if( LayoutChanging != null ) + LayoutChanging( this, EventArgs.Empty ); + } + + private void DockingManager_Loaded( object sender, RoutedEventArgs e ) + { + if( !DesignerProperties.GetIsInDesignMode( this ) ) + { + if( Layout.Manager == this ) + { + LayoutRootPanel = CreateUIElementForModel( Layout.RootPanel ) as LayoutPanelControl; + LeftSidePanel = CreateUIElementForModel( Layout.LeftSide ) as LayoutAnchorSideControl; + TopSidePanel = CreateUIElementForModel( Layout.TopSide ) as LayoutAnchorSideControl; + RightSidePanel = CreateUIElementForModel( Layout.RightSide ) as LayoutAnchorSideControl; + BottomSidePanel = CreateUIElementForModel( Layout.BottomSide ) as LayoutAnchorSideControl; + } + + SetupAutoHideWindow(); + + //load windows not already loaded! + foreach( var fw in Layout.FloatingWindows.Where( fw => !_fwList.Any( fwc => fwc.Model == fw ) ) ) + _fwList.Add( CreateUIElementForModel( fw ) as LayoutFloatingWindowControl ); + + //create the overlaywindow if it's possible + if( IsVisible ) + CreateOverlayWindow(); + FocusElementManager.SetupFocusManagement( this ); + } + } + + private void DockingManager_Unloaded( object sender, RoutedEventArgs e ) + { + + if( !DesignerProperties.GetIsInDesignMode( this ) ) + { + if( _autoHideWindowManager != null ) + { + _autoHideWindowManager.HideAutoWindow(); + } + + if( AutoHideWindow != null ) + AutoHideWindow.Dispose(); + + foreach( var fw in _fwList.ToArray() ) + { + //fw.Owner = null; + fw.SetParentWindowToNull(); + fw.KeepContentVisibleOnClose = true; + fw.Close(); + } + + DestroyOverlayWindow(); + FocusElementManager.FinalizeFocusManagement( this ); + } + } + + private void SetupAutoHideWindow() + { + if( _autoHideWindowManager != null ) + _autoHideWindowManager.HideAutoWindow(); + else + _autoHideWindowManager = new AutoHideWindowManager( this ); + + if( AutoHideWindow != null ) + AutoHideWindow.Dispose(); + + SetAutoHideWindow( new LayoutAutoHideWindowControl() ); + } + + private void CreateOverlayWindow() + { + if( _overlayWindow == null ) + { + _overlayWindow = new OverlayWindow( this ); + } + Rect rectWindow = new Rect( this.PointToScreenDPIWithoutFlowDirection( new Point() ), this.TransformActualSizeToAncestor() ); + _overlayWindow.Left = rectWindow.Left; + _overlayWindow.Top = rectWindow.Top; + _overlayWindow.Width = rectWindow.Width; + _overlayWindow.Height = rectWindow.Height; + } + + private void DestroyOverlayWindow() + { + if( _overlayWindow != null ) + { + _overlayWindow.Close(); + _overlayWindow = null; + } + } + + private void AttachDocumentsSource( LayoutRoot layout, IEnumerable documentsSource ) + { + if( documentsSource == null ) + return; + + if( layout == null ) + return; + + //if (layout.Descendents().OfType().Any()) + // throw new InvalidOperationException("Unable to set the DocumentsSource property if LayoutDocument objects are already present in the model"); + var documentsImported = layout.Descendents().OfType().Select( d => d.Content ).ToArray(); + var documents = documentsSource as IEnumerable; + var listOfDocumentsToImport = new List( documents.OfType() ); + + foreach( var document in listOfDocumentsToImport.ToArray() ) + { + if( documentsImported.Contains( document ) ) + listOfDocumentsToImport.Remove( document ); + } + + + LayoutDocumentPane documentPane = null; + if( layout.LastFocusedDocument != null ) + { + documentPane = layout.LastFocusedDocument.Parent as LayoutDocumentPane; + } + + if( documentPane == null ) + { + documentPane = layout.Descendents().OfType().FirstOrDefault(); + } + + //if (documentPane == null) + // throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); + + _suspendLayoutItemCreation = true; + foreach( var documentContentToImport in listOfDocumentsToImport ) + { + + //documentPane.Children.Add(new LayoutDocument() { Content = documentToImport }); + + var documentToImport = new LayoutDocument() + { + Content = documentContentToImport + }; + + bool added = false; + if( LayoutUpdateStrategy != null ) + { + added = LayoutUpdateStrategy.BeforeInsertDocument( layout, documentToImport, documentPane ); + } + + if( !added ) + { + if( documentPane == null ) + throw new InvalidOperationException( "Layout must contains at least one LayoutDocumentPane in order to host documents" ); + + documentPane.Children.Add( documentToImport ); + added = true; + } + + if( LayoutUpdateStrategy != null ) + LayoutUpdateStrategy.AfterInsertDocument( layout, documentToImport ); + + + CreateDocumentLayoutItem( documentToImport ); + + } + _suspendLayoutItemCreation = false; + + + var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged; + if( documentsSourceAsNotifier != null ) + documentsSourceAsNotifier.CollectionChanged += new NotifyCollectionChangedEventHandler( documentsSourceElementsChanged ); + } + + private void documentsSourceElementsChanged( object sender, NotifyCollectionChangedEventArgs e ) + { + if( Layout == null ) + return; + + //When deserializing documents are created automatically by the deserializer + if( SuspendDocumentsSourceBinding ) + return; + + //handle remove + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) + { + if( e.OldItems != null ) + { + var documentsToRemove = Layout.Descendents().OfType().Where( d => e.OldItems.Contains( d.Content ) ).ToArray(); + foreach( var documentToRemove in documentsToRemove ) + { + ( documentToRemove.Parent as ILayoutContainer ).RemoveChild( + documentToRemove ); + this.RemoveViewFromLogicalChild( documentToRemove ); + } + } + } + + //handle add + if( e.NewItems != null && + ( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) ) + { + if( e.NewItems != null ) + { + LayoutDocumentPane documentPane = null; + if( Layout.LastFocusedDocument != null ) + { + documentPane = Layout.LastFocusedDocument.Parent as LayoutDocumentPane; + } + + if( documentPane == null ) + { + documentPane = Layout.Descendents().OfType().FirstOrDefault(); + } + + //if (documentPane == null) + // throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); + + _suspendLayoutItemCreation = true; + + foreach( var documentContentToImport in e.NewItems ) + { + var documentToImport = new LayoutDocument() + { + Content = documentContentToImport + }; + + bool added = false; + if( LayoutUpdateStrategy != null ) + { + added = LayoutUpdateStrategy.BeforeInsertDocument( Layout, documentToImport, documentPane ); + } + + if( !added ) + { + if( documentPane == null ) + throw new InvalidOperationException( "Layout must contains at least one LayoutDocumentPane in order to host documents" ); + + documentPane.Children.Add( documentToImport ); + added = true; + } + + if( LayoutUpdateStrategy != null ) + { + LayoutUpdateStrategy.AfterInsertDocument( Layout, documentToImport ); + } + + + var root = documentToImport.Root; + + if( root != null && root.Manager == this ) + { + CreateDocumentLayoutItem( documentToImport ); + } + } + _suspendLayoutItemCreation = false; + } + } + + if( e.Action == NotifyCollectionChangedAction.Reset ) + { + //NOTE: I'm going to clear every document present in layout but + //some documents may have been added directly to the layout, for now I clear them too + var documentsToRemove = Layout.Descendents().OfType().ToArray(); + foreach( var documentToRemove in documentsToRemove ) + { + ( documentToRemove.Parent as ILayoutContainer ).RemoveChild( + documentToRemove ); + this.RemoveViewFromLogicalChild( documentToRemove ); + } + } + + if( Layout != null ) + { + Layout.CollectGarbage(); + } + } + + private void DetachDocumentsSource( LayoutRoot layout, IEnumerable documentsSource ) + { + if( documentsSource == null ) + return; + + if( layout == null ) + return; + + var documentsToRemove = layout.Descendents().OfType() + .Where( d => documentsSource.Contains( d.Content ) ).ToArray(); + + foreach( var documentToRemove in documentsToRemove ) + { + ( documentToRemove.Parent as ILayoutContainer ).RemoveChild( + documentToRemove ); + this.RemoveViewFromLogicalChild( documentToRemove ); + } + + var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged; + if( documentsSourceAsNotifier != null ) + documentsSourceAsNotifier.CollectionChanged -= new NotifyCollectionChangedEventHandler( documentsSourceElementsChanged ); + } + + private void Close( LayoutContent contentToClose ) + { + if( !contentToClose.CanClose ) + return; + + var layoutItem = GetLayoutItemFromModel( contentToClose ); + if( layoutItem.CloseCommand != null ) + { + if( layoutItem.CloseCommand.CanExecute( null ) ) + layoutItem.CloseCommand.Execute( null ); + } + else + { + if( contentToClose is LayoutDocument ) + _ExecuteCloseCommand( contentToClose as LayoutDocument ); + else if( contentToClose is LayoutAnchorable ) + _ExecuteCloseCommand( contentToClose as LayoutAnchorable ); + } + } + + private void AttachAnchorablesSource( LayoutRoot layout, IEnumerable anchorablesSource ) + { + if( anchorablesSource == null ) + return; + + if( layout == null ) + return; + + //if (layout.Descendents().OfType().Any()) + // throw new InvalidOperationException("Unable to set the AnchorablesSource property if LayoutAnchorable objects are already present in the model"); + var anchorablesImported = layout.Descendents().OfType().Select( d => d.Content ).ToArray(); + var anchorables = anchorablesSource as IEnumerable; + var listOfAnchorablesToImport = new List( anchorables.OfType() ); + + foreach( var document in listOfAnchorablesToImport.ToArray() ) + { + if( anchorablesImported.Contains( document ) ) + listOfAnchorablesToImport.Remove( document ); + } + + LayoutAnchorablePane anchorablePane = null; + if( layout.ActiveContent != null ) + { + //look for active content parent pane + anchorablePane = layout.ActiveContent.Parent as LayoutAnchorablePane; + } + + if( anchorablePane == null ) + { + //look for a pane on the right side + anchorablePane = layout.Descendents().OfType().Where( pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right ).FirstOrDefault(); + } + + if( anchorablePane == null ) + { + //look for an available pane + anchorablePane = layout.Descendents().OfType().FirstOrDefault(); + } + + _suspendLayoutItemCreation = true; + foreach( var anchorableContentToImport in listOfAnchorablesToImport ) + { + var anchorableToImport = new LayoutAnchorable() + { + Content = anchorableContentToImport + }; + + bool added = false; + if( LayoutUpdateStrategy != null ) + { + added = LayoutUpdateStrategy.BeforeInsertAnchorable( layout, anchorableToImport, anchorablePane ); + } + + if( !added ) + { + if( anchorablePane == null ) + { + var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal }; + if( layout.RootPanel != null ) + { + mainLayoutPanel.Children.Add( layout.RootPanel ); + } + + layout.RootPanel = mainLayoutPanel; + anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength( 200.0, GridUnitType.Pixel ) }; + mainLayoutPanel.Children.Add( anchorablePane ); + } + + anchorablePane.Children.Add( anchorableToImport ); + added = true; + } + + if( LayoutUpdateStrategy != null ) + LayoutUpdateStrategy.AfterInsertAnchorable( layout, anchorableToImport ); + + + CreateAnchorableLayoutItem( anchorableToImport ); + + } + + _suspendLayoutItemCreation = false; + + var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged; + if( anchorablesSourceAsNotifier != null ) + anchorablesSourceAsNotifier.CollectionChanged += new NotifyCollectionChangedEventHandler( anchorablesSourceElementsChanged ); + } + + private void anchorablesSourceElementsChanged( object sender, NotifyCollectionChangedEventArgs e ) + { + if( Layout == null ) + return; + + //When deserializing documents are created automatically by the deserializer + if( SuspendAnchorablesSourceBinding ) + return; + + //handle remove + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) + { + if( e.OldItems != null ) + { + var anchorablesToRemove = Layout.Descendents().OfType().Where( d => e.OldItems.Contains( d.Content ) ).ToArray(); + foreach( var anchorableToRemove in anchorablesToRemove ) + { + anchorableToRemove.Content = null; + ( anchorableToRemove.Parent as ILayoutContainer ).RemoveChild( + anchorableToRemove ); + this.RemoveViewFromLogicalChild( anchorableToRemove ); + } + } + } + + //handle add + if( e.NewItems != null && + ( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) ) + { + if( e.NewItems != null ) + { + LayoutAnchorablePane anchorablePane = null; + + if( Layout.ActiveContent != null ) + { + //look for active content parent pane + anchorablePane = Layout.ActiveContent.Parent as LayoutAnchorablePane; + } + + if( anchorablePane == null ) + { + //look for a pane on the right side + anchorablePane = Layout.Descendents().OfType().Where( pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right ).FirstOrDefault(); + } + + if( anchorablePane == null ) + { + //look for an available pane + anchorablePane = Layout.Descendents().OfType().FirstOrDefault(); + } + + _suspendLayoutItemCreation = true; + foreach( var anchorableContentToImport in e.NewItems ) + { + var anchorableToImport = new LayoutAnchorable() + { + Content = anchorableContentToImport + }; + + bool added = false; + if( LayoutUpdateStrategy != null ) + { + added = LayoutUpdateStrategy.BeforeInsertAnchorable( Layout, anchorableToImport, anchorablePane ); + } + + if( !added ) + { + if( anchorablePane == null ) + { + var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal }; + if( Layout.RootPanel != null ) + { + mainLayoutPanel.Children.Add( Layout.RootPanel ); + } + + Layout.RootPanel = mainLayoutPanel; + anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength( 200.0, GridUnitType.Pixel ) }; + mainLayoutPanel.Children.Add( anchorablePane ); + } + + anchorablePane.Children.Add( anchorableToImport ); + added = true; + } + + if( LayoutUpdateStrategy != null ) + { + LayoutUpdateStrategy.AfterInsertAnchorable( Layout, anchorableToImport ); + } + + var root = anchorableToImport.Root; + + if( root != null && root.Manager == this ) + { + CreateAnchorableLayoutItem( anchorableToImport ); + } + + } + _suspendLayoutItemCreation = false; + } + } + + if( e.Action == NotifyCollectionChangedAction.Reset ) + { + //NOTE: I'm going to clear every anchorable present in layout but + //some anchorable may have been added directly to the layout, for now I clear them too + var anchorablesToRemove = Layout.Descendents().OfType().ToArray(); + foreach( var anchorableToRemove in anchorablesToRemove ) + { + ( anchorableToRemove.Parent as ILayoutContainer ).RemoveChild( + anchorableToRemove ); + this.RemoveViewFromLogicalChild( anchorableToRemove ); + } + } + + if( Layout != null ) + Layout.CollectGarbage(); + } + + private void DetachAnchorablesSource( LayoutRoot layout, IEnumerable anchorablesSource ) + { + if( anchorablesSource == null ) + return; + + if( layout == null ) + return; + + var anchorablesToRemove = layout.Descendents().OfType() + .Where( d => anchorablesSource.Contains( d.Content ) ).ToArray(); + + foreach( var anchorableToRemove in anchorablesToRemove ) + { + ( anchorableToRemove.Parent as ILayoutContainer ).RemoveChild( + anchorableToRemove ); + this.RemoveViewFromLogicalChild( anchorableToRemove ); + } + + var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged; + if( anchorablesSourceAsNotifier != null ) + anchorablesSourceAsNotifier.CollectionChanged -= new NotifyCollectionChangedEventHandler( anchorablesSourceElementsChanged ); + } + + private void RemoveViewFromLogicalChild( LayoutContent layoutContent ) + { + if( layoutContent == null ) + return; + + var layoutItem = this.GetLayoutItemFromModel( layoutContent ); + if( layoutItem != null ) + { + if( layoutItem.IsViewExists() ) + { + this.InternalRemoveLogicalChild( layoutItem.View ); + } + } + } + + private void InternalSetActiveContent( object contentObject ) + { + var layoutContent = Layout.Descendents().OfType().FirstOrDefault( lc => lc == contentObject || lc.Content == contentObject ); + _insideInternalSetActiveContent = true; + Layout.ActiveContent = layoutContent; + _insideInternalSetActiveContent = false; + } + + private void DetachLayoutItems() + { + if( Layout != null ) + { + _layoutItems.ForEach( i => i.Detach() ); + _layoutItems.Clear(); + Layout.ElementAdded -= new EventHandler( Layout_ElementAdded ); + Layout.ElementRemoved -= new EventHandler( Layout_ElementRemoved ); + } + } + + private void Layout_ElementRemoved( object sender, LayoutElementEventArgs e ) + { + if( _suspendLayoutItemCreation ) + return; + + CollectLayoutItemsDeleted(); + } + + private void Layout_ElementAdded( object sender, LayoutElementEventArgs e ) + { + if( _suspendLayoutItemCreation ) + return; + + foreach( var content in Layout.Descendents().OfType() ) + { + if( content is LayoutDocument ) + CreateDocumentLayoutItem( content as LayoutDocument ); + else //if (content is LayoutAnchorable) + CreateAnchorableLayoutItem( content as LayoutAnchorable ); + } + + CollectLayoutItemsDeleted(); + } + + private void CollectLayoutItemsDeleted() + { + if( _collectLayoutItemsOperations != null ) + return; + _collectLayoutItemsOperations = Dispatcher.BeginInvoke( new Action( () => + { + _collectLayoutItemsOperations = null; + foreach( var itemToRemove in _layoutItems.Where( item => item.LayoutElement.Root != Layout ).ToArray() ) + { + + if( itemToRemove != null && + itemToRemove.Model != null && + itemToRemove.Model is UIElement ) + { + //((ILogicalChildrenContainer)this).InternalRemoveLogicalChild(itemToRemove.Model as UIElement); + } + + itemToRemove.Detach(); + _layoutItems.Remove( itemToRemove ); + + } + } ) ); + } + + private void AttachLayoutItems() + { + if( Layout != null ) + { + foreach( var document in Layout.Descendents().OfType().ToArray() ) + { + CreateDocumentLayoutItem( document ); + //var documentItem = new LayoutDocumentItem(); + //documentItem.Attach(document); + //ApplyStyleToLayoutItem(documentItem); + //_layoutItems.Add(documentItem); + } + foreach( var anchorable in Layout.Descendents().OfType().ToArray() ) + { + CreateAnchorableLayoutItem( anchorable ); + //var anchorableItem = new LayoutAnchorableItem(); + //anchorableItem.Attach(anchorable); + //ApplyStyleToLayoutItem(anchorableItem); + //_layoutItems.Add(anchorableItem); + } + + Layout.ElementAdded += new EventHandler( Layout_ElementAdded ); + Layout.ElementRemoved += new EventHandler( Layout_ElementRemoved ); + } + } + + private void ApplyStyleToLayoutItem( LayoutItem layoutItem ) + { + layoutItem._ClearDefaultBindings(); + if( LayoutItemContainerStyle != null ) + layoutItem.Style = LayoutItemContainerStyle; + else if( LayoutItemContainerStyleSelector != null ) + layoutItem.Style = LayoutItemContainerStyleSelector.SelectStyle( layoutItem.Model, layoutItem ); + layoutItem._SetDefaultBindings(); + } + + private void CreateAnchorableLayoutItem( LayoutAnchorable contentToAttach ) + { + if( _layoutItems.Any( item => item.LayoutElement == contentToAttach ) ) + { + foreach( var item in _layoutItems ) + { + ApplyStyleToLayoutItem( item ); + } + return; + } + + var layoutItem = new LayoutAnchorableItem(); + layoutItem.Attach( contentToAttach ); + ApplyStyleToLayoutItem( layoutItem ); + _layoutItems.Add( layoutItem ); + + if( contentToAttach != null && + contentToAttach.Content != null && + contentToAttach.Content is UIElement ) + { + InternalAddLogicalChild( contentToAttach.Content ); + } + + } + + private void CreateDocumentLayoutItem( LayoutDocument contentToAttach ) + { + if( _layoutItems.Any( item => item.LayoutElement == contentToAttach ) ) + { + foreach( var item in _layoutItems ) + { + ApplyStyleToLayoutItem( item ); + } + return; + } + + var layoutItem = new LayoutDocumentItem(); + layoutItem.Attach( contentToAttach ); + ApplyStyleToLayoutItem( layoutItem ); + _layoutItems.Add( layoutItem ); + + if( contentToAttach != null && + contentToAttach.Content != null && + contentToAttach.Content is UIElement ) + { + InternalAddLogicalChild( contentToAttach.Content ); + } + + } + + private void ShowNavigatorWindow() + { + if( _navigatorWindow == null ) + { + _navigatorWindow = new NavigatorWindow( this ) + { + Owner = Window.GetWindow( this ), + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; + } + + _navigatorWindow.ShowDialog(); + _navigatorWindow = null; + } + + #endregion + + #region Events + + /// + /// Event fired when property changes + /// + public event EventHandler LayoutChanged; + + /// + /// Event fired when property is about to be changed + /// + public event EventHandler LayoutChanging; + + /// + /// Event fired when a document is about to be closed + /// + /// Subscribers have the opportuniy to cancel the operation. + public event EventHandler DocumentClosing; + + /// + /// Event fired after a document is closed + /// + public event EventHandler DocumentClosed; + + public event EventHandler ActiveContentChanged; + + #endregion + + #region IOverlayWindowHost Interface + + bool IOverlayWindowHost.HitTest( Point dragPoint ) + { + if (!this.IsVisible) return false; + Rect detectionRect = new Rect( this.PointToScreenDPIWithoutFlowDirection( new Point() ), this.TransformActualSizeToAncestor() ); + return detectionRect.Contains( dragPoint ); + } + + DockingManager IOverlayWindowHost.Manager + { + get + { + return this; + } + } + + IOverlayWindow IOverlayWindowHost.ShowOverlayWindow( LayoutFloatingWindowControl draggingWindow ) + { + CreateOverlayWindow(); + if (draggingWindow.Model.Root.ActiveContent.CanDock) + { + _overlayWindow.Owner = draggingWindow; + _overlayWindow.EnableDropTargets(); + _overlayWindow.Show(); + } + return _overlayWindow; + } + + void IOverlayWindowHost.HideOverlayWindow() + { + _areas = null; + _overlayWindow.Owner = null; + _overlayWindow.HideDropTargets(); + } + + IEnumerable IOverlayWindowHost.GetDropAreas( LayoutFloatingWindowControl draggingWindow ) + { + if( _areas != null ) + return _areas; + + bool isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow; + + _areas = new List(); + + if( !isDraggingDocuments ) + { + _areas.Add( new DropArea( + this, + DropAreaType.DockingManager ) ); + + foreach( var areaHost in this.FindVisualChildren() ) + { + if( areaHost.Model.Descendents().Any() ) + { + _areas.Add( new DropArea( + areaHost, + DropAreaType.AnchorablePane ) ); + } + } + } + + foreach( var areaHost in this.FindVisualChildren() ) + { + _areas.Add( new DropArea( + areaHost, + DropAreaType.DocumentPane ) ); + } + + foreach( var areaHost in this.FindVisualChildren() ) + { + var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup; + if( documentGroupModel.Children.Where( c => c.IsVisible ).Count() == 0 ) + { + _areas.Add( new DropArea( + areaHost, + DropAreaType.DocumentPaneGroup ) ); + } + } + + return _areas; + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DocumentClosedEventArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DocumentClosedEventArgs.cs index 980bb0be..42b645e4 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DocumentClosedEventArgs.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DocumentClosedEventArgs.cs @@ -15,24 +15,21 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock { - public class DocumentClosedEventArgs : EventArgs + public class DocumentClosedEventArgs : EventArgs + { + public DocumentClosedEventArgs( LayoutDocument document ) { - public DocumentClosedEventArgs(LayoutDocument document) - { - Document = document; - } - - public LayoutDocument Document - { - get; - private set; - } + Document = document; } + + public LayoutDocument Document + { + get; + private set; + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DocumentClosingEventArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DocumentClosingEventArgs.cs index 5c87d960..f7201e9b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DocumentClosingEventArgs.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DocumentClosingEventArgs.cs @@ -14,26 +14,22 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.ComponentModel; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock { - public class DocumentClosingEventArgs : CancelEventArgs + public class DocumentClosingEventArgs : CancelEventArgs + { + public DocumentClosingEventArgs( LayoutDocument document ) { - public DocumentClosingEventArgs(LayoutDocument document) - { - Document = document; - } - - public LayoutDocument Document - { - get; - private set; - } + Document = document; } + + public LayoutDocument Document + { + get; + private set; + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Extentions.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Extentions.cs index 5f998ee0..d31c0e33 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Extentions.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Extentions.cs @@ -16,45 +16,43 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Collections; namespace Xceed.Wpf.AvalonDock { - internal static class Extensions + internal static class Extensions + { + public static bool Contains( this IEnumerable collection, object item ) { - public static bool Contains(this IEnumerable collection, object item) - { - foreach (var o in collection) - if (o == item) - return true; - - return false; - } - - - public static void ForEach(this IEnumerable collection, Action action) - { - foreach (T v in collection) - action(v); - } - - - public static int IndexOf(this T[] array, T value) where T : class - { - for (int i = 0; i < array.Length; i++) - if (array[i] == value) - return i; - - return -1; - } - - public static V GetValueOrDefault(this WeakReference wr) - { - if (wr == null || !wr.IsAlive) - return default(V); - return (V)wr.Target; - } + foreach( var o in collection ) + if( o == item ) + return true; + + return false; + } + + + public static void ForEach( this IEnumerable collection, Action action ) + { + foreach( T v in collection ) + action( v ); + } + + + public static int IndexOf( this T[] array, T value ) where T : class + { + for( int i = 0; i < array.Length; i++ ) + if( array[ i ] == value ) + return i; + + return -1; + } + + public static V GetValueOrDefault( this WeakReference wr ) + { + if( wr == null || !wr.IsAlive ) + return default( V ); + return ( V )wr.Target; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/AnchorSide.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/AnchorSide.cs index d024cb2c..c56c5572 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/AnchorSide.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/AnchorSide.cs @@ -14,21 +14,13 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Layout { - public enum AnchorSide - { - Left, - - Top, - - Right, - - Bottom - } + public enum AnchorSide + { + Left, + Top, + Right, + Bottom + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/AnchorableShowStrategy.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/AnchorableShowStrategy.cs index 5b758db8..e3531984 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/AnchorableShowStrategy.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/AnchorableShowStrategy.cs @@ -15,19 +15,16 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Layout { - [Flags] - public enum AnchorableShowStrategy : byte - { - Most = 0x0001, - Left = 0x0002, - Right = 0x0004, - Top = 0x0010, - Bottom= 0x0020, - } + [Flags] + public enum AnchorableShowStrategy : byte + { + Most = 0x0001, + Left = 0x0002, + Right = 0x0004, + Top = 0x0010, + Bottom = 0x0020, + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ChildrenTreeChangedEventArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ChildrenTreeChangedEventArgs.cs index d36b9c51..f71fd05d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ChildrenTreeChangedEventArgs.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ChildrenTreeChangedEventArgs.cs @@ -15,32 +15,32 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Layout { - public enum ChildrenTreeChange + public enum ChildrenTreeChange + { + /// + /// Direct insert/remove operation has been perfomed to the group + /// + DirectChildrenChanged, + + /// + /// An element below in the hierarchy as been added/removed + /// + TreeChanged + } + + public class ChildrenTreeChangedEventArgs : EventArgs + { + public ChildrenTreeChangedEventArgs( ChildrenTreeChange change ) { - /// - /// Direct insert/remove operation has been perfomed to the group - /// - DirectChildrenChanged, - - /// - /// An element below in the hierarchy as been added/removed - /// - TreeChanged + Change = change; } - public class ChildrenTreeChangedEventArgs : EventArgs + public ChildrenTreeChange Change { - public ChildrenTreeChangedEventArgs(ChildrenTreeChange change) - { - Change = change; - } - - public ChildrenTreeChange Change { get; private set; } + get; private set; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Extentions.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Extentions.cs index 8cb5ac3e..ce491425 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Extentions.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Extentions.cs @@ -14,156 +14,149 @@ ***********************************************************************************/ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Media; -using System.Windows.Media.Media3D; using System.Diagnostics; using System.Runtime.InteropServices; namespace Xceed.Wpf.AvalonDock.Layout { - public static class Extensions + public static class Extensions + { + #region Public Methods + + public static IEnumerable Descendents( this ILayoutElement element ) { - public static IEnumerable Descendents(this ILayoutElement element) + var container = element as ILayoutContainer; + if( container != null ) + { + foreach( var childElement in container.Children ) { - var container = element as ILayoutContainer; - if (container != null) - { - foreach (var childElement in container.Children) - { - yield return childElement; - foreach (var childChildElement in childElement.Descendents()) - yield return childChildElement; - } - } + yield return childElement; + foreach( var childChildElement in childElement.Descendents() ) + yield return childChildElement; } + } + } - public static T FindParent(this ILayoutElement element) //where T : ILayoutContainer - { - var parent = element.Parent; - while (parent != null && - !(parent is T)) - parent = parent.Parent; + public static T FindParent( this ILayoutElement element ) //where T : ILayoutContainer + { + var parent = element.Parent; + while( parent != null && + !( parent is T ) ) + parent = parent.Parent; - return (T)parent; - } + return ( T )parent; + } - public static ILayoutRoot GetRoot(this ILayoutElement element) //where T : ILayoutContainer - { - if (element is ILayoutRoot) - return element as ILayoutRoot; + public static ILayoutRoot GetRoot( this ILayoutElement element ) //where T : ILayoutContainer + { + if( element is ILayoutRoot ) + return element as ILayoutRoot; - var parent = element.Parent; - while (parent != null && - !(parent is ILayoutRoot)) - parent = parent.Parent; + var parent = element.Parent; + while( parent != null && + !( parent is ILayoutRoot ) ) + parent = parent.Parent; - return (ILayoutRoot)parent; - } + return ( ILayoutRoot )parent; + } - public static bool ContainsChildOfType(this ILayoutContainer element) - { - foreach (var childElement in element.Descendents()) - if (childElement is T) - return true; + public static bool ContainsChildOfType( this ILayoutContainer element ) + { + foreach( var childElement in element.Descendents() ) + if( childElement is T ) + return true; - return false; - } + return false; + } - public static bool ContainsChildOfType(this ILayoutContainer container) - { - foreach (var childElement in container.Descendents()) - if (childElement is T || childElement is S) - return true; + public static bool ContainsChildOfType( this ILayoutContainer container ) + { + foreach( var childElement in container.Descendents() ) + if( childElement is T || childElement is S ) + return true; - return false; - } + return false; + } - public static bool IsOfType(this ILayoutContainer container) + public static bool IsOfType( this ILayoutContainer container ) + { + return container is T || container is S; + } + + public static AnchorSide GetSide( this ILayoutElement element ) + { + var parentContainer = element.Parent as ILayoutOrientableGroup; + if( parentContainer != null ) + { + var layoutPanel = parentContainer as LayoutPanel; + if( layoutPanel == null ) { - return container is T || container is S; + layoutPanel = parentContainer.FindParent(); } - public static AnchorSide GetSide(this ILayoutElement element) + if( (layoutPanel != null) && ( layoutPanel.Children.Count > 0 ) ) { - var parentContainer = element.Parent as ILayoutOrientableGroup; - if (parentContainer != null) - { - if (!parentContainer.ContainsChildOfType()) - return GetSide(parentContainer); - - foreach (var childElement in parentContainer.Children) - { - if (childElement == element || - childElement.Descendents().Contains(element)) - return parentContainer.Orientation == System.Windows.Controls.Orientation.Horizontal ? - AnchorSide.Left : AnchorSide.Top; - - var childElementAsContainer = childElement as ILayoutContainer; - if (childElementAsContainer != null && - (childElementAsContainer.IsOfType() || - childElementAsContainer.ContainsChildOfType())) - { - return parentContainer.Orientation == System.Windows.Controls.Orientation.Horizontal ? - AnchorSide.Right : AnchorSide.Bottom; - } - } - } - - Debug.Fail("Unable to find the side for an element, possible layout problem!"); - return AnchorSide.Right; + if( layoutPanel.Orientation == System.Windows.Controls.Orientation.Horizontal ) + return layoutPanel.Children[ 0 ].Descendents().Contains( element ) ? AnchorSide.Left : AnchorSide.Right; + return layoutPanel.Children[ 0 ].Descendents().Contains( element ) ? AnchorSide.Top : AnchorSide.Bottom; } + } + Debug.Fail( "Unable to find the side for an element, possible layout problem!" ); + return AnchorSide.Right; + } - internal static void KeepInsideNearestMonitor(this ILayoutElementForFloatingWindow paneInsideFloatingWindow) - { - Win32Helper.RECT r = new Win32Helper.RECT(); - r.Left = (int)paneInsideFloatingWindow.FloatingLeft; - r.Top = (int)paneInsideFloatingWindow.FloatingTop; - r.Bottom = r.Top + (int)paneInsideFloatingWindow.FloatingHeight; - r.Right = r.Left + (int)paneInsideFloatingWindow.FloatingWidth; - - uint MONITOR_DEFAULTTONEAREST = 0x00000002; - uint MONITOR_DEFAULTTONULL = 0x00000000; - - System.IntPtr monitor = Win32Helper.MonitorFromRect(ref r, MONITOR_DEFAULTTONULL); - if (monitor == System.IntPtr.Zero) - { - System.IntPtr nearestmonitor = Win32Helper.MonitorFromRect(ref r, MONITOR_DEFAULTTONEAREST); - if (nearestmonitor != System.IntPtr.Zero) - { - Win32Helper.MonitorInfo monitorInfo = new Win32Helper.MonitorInfo(); - monitorInfo.Size = Marshal.SizeOf(monitorInfo); - Win32Helper.GetMonitorInfo(nearestmonitor, monitorInfo); - - if (paneInsideFloatingWindow.FloatingLeft < monitorInfo.Work.Left) - { - paneInsideFloatingWindow.FloatingLeft = monitorInfo.Work.Left + 10; - } - - if (paneInsideFloatingWindow.FloatingLeft + paneInsideFloatingWindow.FloatingWidth > monitorInfo.Work.Right) - { - paneInsideFloatingWindow.FloatingLeft = monitorInfo.Work.Right - (paneInsideFloatingWindow.FloatingWidth + 10); - } - - if (paneInsideFloatingWindow.FloatingTop < monitorInfo.Work.Top) - { - paneInsideFloatingWindow.FloatingTop = monitorInfo.Work.Top + 10; - } - - if (paneInsideFloatingWindow.FloatingTop + paneInsideFloatingWindow.FloatingHeight > monitorInfo.Work.Bottom) - { - paneInsideFloatingWindow.FloatingTop = monitorInfo.Work.Bottom - (paneInsideFloatingWindow.FloatingHeight + 10); - } - } - } + #endregion + + #region Internal Methods + internal static void KeepInsideNearestMonitor( this ILayoutElementForFloatingWindow paneInsideFloatingWindow ) + { + Win32Helper.RECT r = new Win32Helper.RECT(); + r.Left = ( int )paneInsideFloatingWindow.FloatingLeft; + r.Top = ( int )paneInsideFloatingWindow.FloatingTop; + r.Bottom = r.Top + ( int )paneInsideFloatingWindow.FloatingHeight; + r.Right = r.Left + ( int )paneInsideFloatingWindow.FloatingWidth; + + uint MONITOR_DEFAULTTONEAREST = 0x00000002; + uint MONITOR_DEFAULTTONULL = 0x00000000; + + System.IntPtr monitor = Win32Helper.MonitorFromRect( ref r, MONITOR_DEFAULTTONULL ); + if( monitor == System.IntPtr.Zero ) + { + System.IntPtr nearestmonitor = Win32Helper.MonitorFromRect( ref r, MONITOR_DEFAULTTONEAREST ); + if( nearestmonitor != System.IntPtr.Zero ) + { + Win32Helper.MonitorInfo monitorInfo = new Win32Helper.MonitorInfo(); + monitorInfo.Size = Marshal.SizeOf( monitorInfo ); + Win32Helper.GetMonitorInfo( nearestmonitor, monitorInfo ); + + if( paneInsideFloatingWindow.FloatingLeft < monitorInfo.Work.Left ) + { + paneInsideFloatingWindow.FloatingLeft = monitorInfo.Work.Left + 10; + } + + if( paneInsideFloatingWindow.FloatingLeft + paneInsideFloatingWindow.FloatingWidth > monitorInfo.Work.Right ) + { + paneInsideFloatingWindow.FloatingLeft = monitorInfo.Work.Right - ( paneInsideFloatingWindow.FloatingWidth + 10 ); + } + + if( paneInsideFloatingWindow.FloatingTop < monitorInfo.Work.Top ) + { + paneInsideFloatingWindow.FloatingTop = monitorInfo.Work.Top + 10; + } + + if( paneInsideFloatingWindow.FloatingTop + paneInsideFloatingWindow.FloatingHeight > monitorInfo.Work.Bottom ) + { + paneInsideFloatingWindow.FloatingTop = monitorInfo.Work.Bottom - ( paneInsideFloatingWindow.FloatingHeight + 10 ); + } } + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutAnchorablePane.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutAnchorablePane.cs index feacc288..f720726f 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutAnchorablePane.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutAnchorablePane.cs @@ -14,14 +14,10 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutAnchorablePane : ILayoutPanelElement, ILayoutPane - { - } + public interface ILayoutAnchorablePane : ILayoutPanelElement, ILayoutPane + { + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutContainer.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutContainer.cs index 78d765d8..542122aa 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutContainer.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutContainer.cs @@ -14,18 +14,32 @@ ***********************************************************************************/ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutContainer : ILayoutElement + public interface ILayoutContainer : ILayoutElement + { + #region Properties + + IEnumerable Children { - IEnumerable Children { get; } - void RemoveChild(ILayoutElement element); - void ReplaceChild(ILayoutElement oldElement, ILayoutElement newElement); - int ChildrenCount { get; } + get; } + + int ChildrenCount + { + get; + } + + #endregion + + #region Methods + + void RemoveChild( ILayoutElement element ); + + void ReplaceChild( ILayoutElement oldElement, ILayoutElement newElement ); + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutContentSelector.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutContentSelector.cs index ea01b9d5..da71a637 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutContentSelector.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutContentSelector.cs @@ -14,19 +14,28 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutContentSelector - { - int SelectedContentIndex { get; set; } + public interface ILayoutContentSelector + { + #region Properties - int IndexOf(LayoutContent content); + int SelectedContentIndex + { + get; set; + } - LayoutContent SelectedContent { get; } + LayoutContent SelectedContent + { + get; } + + #endregion + + #region Methods + + int IndexOf( LayoutContent content ); + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutControl.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutControl.cs index b6555122..8d6d120a 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutControl.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutControl.cs @@ -14,15 +14,13 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutControl + public interface ILayoutControl + { + ILayoutElement Model { - ILayoutElement Model { get; } + get; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutDocumentPane.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutDocumentPane.cs index 239f9361..af7a89c7 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutDocumentPane.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutDocumentPane.cs @@ -14,14 +14,9 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutDocumentPane : ILayoutPanelElement, ILayoutPane - { - } + public interface ILayoutDocumentPane : ILayoutPanelElement, ILayoutPane + { + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutElement.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutElement.cs index 605144d0..4bbf399d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutElement.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutElement.cs @@ -14,17 +14,19 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.ComponentModel; namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutElement : INotifyPropertyChanged, INotifyPropertyChanging + public interface ILayoutElement : INotifyPropertyChanged, INotifyPropertyChanging + { + ILayoutContainer Parent { - ILayoutContainer Parent { get; } - ILayoutRoot Root { get; } + get; } + ILayoutRoot Root + { + get; + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutElementWithVisibility.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutElementWithVisibility.cs index c65178b7..26227a40 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutElementWithVisibility.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutElementWithVisibility.cs @@ -14,15 +14,10 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutElementWithVisibility - { - void ComputeVisibility(); - } + public interface ILayoutElementWithVisibility + { + void ComputeVisibility(); + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutGroup.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutGroup.cs index eab626a8..ea933786 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutGroup.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutGroup.cs @@ -15,18 +15,16 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutGroup : ILayoutContainer - { - int IndexOfChild(ILayoutElement element); - void InsertChildAt(int index, ILayoutElement element); - void RemoveChildAt(int index); - void ReplaceChildAt(int index, ILayoutElement element); - event EventHandler ChildrenCollectionChanged; - } + public interface ILayoutGroup : ILayoutContainer + { + int IndexOfChild( ILayoutElement element ); + void InsertChildAt( int index, ILayoutElement element ); + void RemoveChildAt( int index ); + void ReplaceChildAt( int index, ILayoutElement element ); + + event EventHandler ChildrenCollectionChanged; + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutOrientableElement.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutOrientableElement.cs index 88e36611..80088c02 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutOrientableElement.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutOrientableElement.cs @@ -14,16 +14,15 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Controls; namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutOrientableGroup : ILayoutGroup + public interface ILayoutOrientableGroup : ILayoutGroup + { + Orientation Orientation { - Orientation Orientation { get; set; } + get; set; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPane.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPane.cs index a65de4ba..36de7a57 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPane.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPane.cs @@ -14,17 +14,12 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutPane : ILayoutContainer, ILayoutElementWithVisibility - { - void MoveChild(int oldIndex, int newIndex); + public interface ILayoutPane : ILayoutContainer, ILayoutElementWithVisibility + { + void MoveChild( int oldIndex, int newIndex ); - void RemoveChildAt(int childIndex); - } + void RemoveChildAt( int childIndex ); + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPaneSerializable.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPaneSerializable.cs index eba7e08e..0f76e247 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPaneSerializable.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPaneSerializable.cs @@ -14,15 +14,14 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Layout { - interface ILayoutPaneSerializable + interface ILayoutPaneSerializable + { + string Id { - string Id { get; set; } + get; set; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPanelElement.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPanelElement.cs index 7da961af..234a813a 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPanelElement.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPanelElement.cs @@ -14,16 +14,14 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutPanelElement : ILayoutElement + public interface ILayoutPanelElement : ILayoutElement + { + bool IsVisible { - bool IsVisible { get; } + get; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPositionableElement.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPositionableElement.cs index 95b1e5db..34ef183c 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPositionableElement.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPositionableElement.cs @@ -14,49 +14,78 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Layout { - internal interface ILayoutPositionableElement : ILayoutElement, ILayoutElementForFloatingWindow + internal interface ILayoutPositionableElement : ILayoutElement, ILayoutElementForFloatingWindow + { + GridLength DockWidth { - GridLength DockWidth - { - get; - set; - } - - GridLength DockHeight - { - get; - set; - } + get; + set; + } - double DockMinWidth { get; set; } - double DockMinHeight { get; set; } + GridLength DockHeight + { + get; + set; + } + double DockMinWidth + { + get; set; + } + double DockMinHeight + { + get; set; + } + bool AllowDuplicateContent + { + get; set; + } - bool IsVisible { get; } + bool IsVisible + { + get; } + } - internal interface ILayoutPositionableElementWithActualSize + internal interface ILayoutPositionableElementWithActualSize + { + double ActualWidth { - double ActualWidth { get; set; } - double ActualHeight { get; set; } + get; set; } + double ActualHeight + { + get; set; + } + } - internal interface ILayoutElementForFloatingWindow + internal interface ILayoutElementForFloatingWindow + { + double FloatingWidth + { + get; set; + } + double FloatingHeight + { + get; set; + } + double FloatingLeft + { + get; set; + } + double FloatingTop + { + get; set; + } + bool IsMaximized { - double FloatingWidth { get; set; } - double FloatingHeight { get; set; } - double FloatingLeft { get; set; } - double FloatingTop { get; set; } - bool IsMaximized { get; set; } + get; set; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPreviousContainer.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPreviousContainer.cs index 76a56212..805d254b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPreviousContainer.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutPreviousContainer.cs @@ -14,17 +14,18 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Layout { - interface ILayoutPreviousContainer + interface ILayoutPreviousContainer + { + ILayoutContainer PreviousContainer { - ILayoutContainer PreviousContainer { get; set; } + get; set; + } - string PreviousContainerId { get; set; } + string PreviousContainerId + { + get; set; } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutRoot.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutRoot.cs index 0eeb48b7..4408366c 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutRoot.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutRoot.cs @@ -14,30 +14,53 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Collections.ObjectModel; namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutRoot + public interface ILayoutRoot + { + DockingManager Manager { - DockingManager Manager { get; } - - LayoutPanel RootPanel { get; } + get; + } - LayoutAnchorSide TopSide { get; } - LayoutAnchorSide LeftSide { get; } - LayoutAnchorSide RightSide { get; } - LayoutAnchorSide BottomSide { get; } + LayoutPanel RootPanel + { + get; + } - LayoutContent ActiveContent { get; set; } + LayoutAnchorSide TopSide + { + get; + } + LayoutAnchorSide LeftSide + { + get; + } + LayoutAnchorSide RightSide + { + get; + } + LayoutAnchorSide BottomSide + { + get; + } - void CollectGarbage(); + LayoutContent ActiveContent + { + get; set; + } - ObservableCollection FloatingWindows { get; } - ObservableCollection Hidden { get; } + ObservableCollection FloatingWindows + { + get; + } + ObservableCollection Hidden + { + get; } + + void CollectGarbage(); + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutUpdateStrategy.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutUpdateStrategy.cs index 409fe509..eb31dceb 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutUpdateStrategy.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/ILayoutUpdateStrategy.cs @@ -14,32 +14,27 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace Xceed.Wpf.AvalonDock.Layout { - public interface ILayoutUpdateStrategy - { - bool BeforeInsertAnchorable( - LayoutRoot layout, - LayoutAnchorable anchorableToShow, - ILayoutContainer destinationContainer); - - void AfterInsertAnchorable( - LayoutRoot layout, - LayoutAnchorable anchorableShown); - - - bool BeforeInsertDocument( - LayoutRoot layout, - LayoutDocument anchorableToShow, - ILayoutContainer destinationContainer); - - void AfterInsertDocument( - LayoutRoot layout, - LayoutDocument anchorableShown); - } + public interface ILayoutUpdateStrategy + { + bool BeforeInsertAnchorable( + LayoutRoot layout, + LayoutAnchorable anchorableToShow, + ILayoutContainer destinationContainer ); + + void AfterInsertAnchorable( + LayoutRoot layout, + LayoutAnchorable anchorableShown ); + + + bool BeforeInsertDocument( + LayoutRoot layout, + LayoutDocument anchorableToShow, + ILayoutContainer destinationContainer ); + + void AfterInsertDocument( + LayoutRoot layout, + LayoutDocument anchorableShown ); + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorGroup.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorGroup.cs index 6af4f25b..00b0412e 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorGroup.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorGroup.cs @@ -15,97 +15,111 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections.ObjectModel; using System.Windows.Markup; using System.Xml.Serialization; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("Children")] - [Serializable] - public class LayoutAnchorGroup : LayoutGroup, ILayoutPreviousContainer, ILayoutPaneSerializable + [ContentProperty( "Children" )] + [Serializable] + public class LayoutAnchorGroup : LayoutGroup, ILayoutPreviousContainer, ILayoutPaneSerializable + { + #region Constructors + + public LayoutAnchorGroup() { - public LayoutAnchorGroup() - { - } + } - protected override bool GetVisibility() - { - return Children.Count > 0; - } + #endregion + #region Overrides - #region PreviousContainer + protected override bool GetVisibility() + { + return Children.Count > 0; + } - [field:NonSerialized] - private ILayoutContainer _previousContainer = null; - [XmlIgnore] - ILayoutContainer ILayoutPreviousContainer.PreviousContainer + public override void WriteXml( System.Xml.XmlWriter writer ) + { + if( _id != null ) + writer.WriteAttributeString( "Id", _id ); + if( _previousContainer != null ) + { + var paneSerializable = _previousContainer as ILayoutPaneSerializable; + if( paneSerializable != null ) { - get { return _previousContainer; } - set - { - if (_previousContainer != value) - { - _previousContainer = value; - RaisePropertyChanged("PreviousContainer"); - var paneSerializable = _previousContainer as ILayoutPaneSerializable; - if (paneSerializable != null && - paneSerializable.Id == null) - paneSerializable.Id = Guid.NewGuid().ToString(); - } - } + writer.WriteAttributeString( "PreviousContainerId", paneSerializable.Id ); } + } - #endregion + base.WriteXml( writer ); + } - string _id; - string ILayoutPaneSerializable.Id - { - get - { - return _id; - } - set - { - _id = value; - } - } + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "Id" ) ) + _id = reader.Value; + if( reader.MoveToAttribute( "PreviousContainerId" ) ) + ( ( ILayoutPreviousContainer )this ).PreviousContainerId = reader.Value; - string ILayoutPreviousContainer.PreviousContainerId - { - get; - set; - } - public override void WriteXml(System.Xml.XmlWriter writer) + base.ReadXml( reader ); + } + + #endregion + + #region ILayoutPreviousContainer Interface + + #region PreviousContainer + + [field: NonSerialized] + private ILayoutContainer _previousContainer = null; + [XmlIgnore] + ILayoutContainer ILayoutPreviousContainer.PreviousContainer + { + get + { + return _previousContainer; + } + set + { + if( _previousContainer != value ) { - if (_id != null) - writer.WriteAttributeString("Id", _id); - if (_previousContainer != null) - { - var paneSerializable = _previousContainer as ILayoutPaneSerializable; - if (paneSerializable != null) - { - writer.WriteAttributeString("PreviousContainerId", paneSerializable.Id); - } - } - - base.WriteXml(writer); + _previousContainer = value; + RaisePropertyChanged( "PreviousContainer" ); + var paneSerializable = _previousContainer as ILayoutPaneSerializable; + if( paneSerializable != null && + paneSerializable.Id == null ) + paneSerializable.Id = Guid.NewGuid().ToString(); } + } + } - public override void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("Id")) - _id = reader.Value; - if (reader.MoveToAttribute("PreviousContainerId")) - ((ILayoutPreviousContainer)this).PreviousContainerId = reader.Value; + #endregion + string ILayoutPreviousContainer.PreviousContainerId + { + get; + set; + } - base.ReadXml(reader); - } + #endregion + + #region ILayoutPaneSerializable Interface + + string _id; + string ILayoutPaneSerializable.Id + { + get + { + return _id; + } + set + { + _id = value; + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorSide.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorSide.cs index 60908226..1f995b80 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorSide.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorSide.cs @@ -15,69 +15,79 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections.ObjectModel; using System.Windows.Markup; -using Xceed.Wpf.AvalonDock.Controls; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("Children")] - [Serializable] - public class LayoutAnchorSide : LayoutGroup - { - public LayoutAnchorSide() - { - } + [ContentProperty( "Children" )] + [Serializable] + public class LayoutAnchorSide : LayoutGroup + { + #region Constructors - protected override bool GetVisibility() - { - return Children.Count > 0; - } + public LayoutAnchorSide() + { + } + #endregion - protected override void OnParentChanged(ILayoutContainer oldValue, ILayoutContainer newValue) - { - base.OnParentChanged(oldValue, newValue); + #region Properties - UpdateSide(); - } + #region Side - private void UpdateSide() + private AnchorSide _side; + public AnchorSide Side + { + get + { + return _side; + } + private set + { + if( _side != value ) { - if (Root.LeftSide == this) - Side = AnchorSide.Left; - else if (Root.TopSide == this) - Side = AnchorSide.Top; - else if (Root.RightSide == this) - Side = AnchorSide.Right; - else if (Root.BottomSide == this) - Side = AnchorSide.Bottom; + RaisePropertyChanging( "Side" ); + _side = value; + RaisePropertyChanged( "Side" ); } + } + } + #endregion - #region Side + #endregion - private AnchorSide _side; - public AnchorSide Side - { - get { return _side; } - private set - { - if (_side != value) - { - RaisePropertyChanging("Side"); - _side = value; - RaisePropertyChanged("Side"); - } - } - } + #region Overrides - #endregion + protected override bool GetVisibility() + { + return Children.Count > 0; + } + protected override void OnParentChanged( ILayoutContainer oldValue, ILayoutContainer newValue ) + { + base.OnParentChanged( oldValue, newValue ); + UpdateSide(); } + + #endregion + + #region Private Methods + + private void UpdateSide() + { + if( Root.LeftSide == this ) + Side = AnchorSide.Left; + else if( Root.TopSide == this ) + Side = AnchorSide.Top; + else if( Root.RightSide == this ) + Side = AnchorSide.Right; + else if( Root.BottomSide == this ) + Side = AnchorSide.Bottom; + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorable.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorable.cs index 0d891995..4502e764 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorable.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorable.cs @@ -15,9 +15,7 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; using System.Xml.Serialization; using System.Windows.Controls; @@ -26,610 +24,726 @@ using System.ComponentModel; namespace Xceed.Wpf.AvalonDock.Layout { - [Serializable] - public class LayoutAnchorable : LayoutContent + [Serializable] + public class LayoutAnchorable : LayoutContent + { + #region Members + + private double _autohideWidth = 0.0; + private double _autohideMinWidth = 100.0; + private double _autohideHeight = 0.0; + private double _autohideMinHeight = 100.0; + private bool _canHide = true; + private bool _canAutoHide = true; + private bool _canCloseValueBeforeInternalSet; + + #endregion + + #region Constructors + + public LayoutAnchorable() { - #region IsVisible - [XmlIgnore] - public bool IsVisible - { - get - { - return Parent != null && !(Parent is LayoutRoot); - } - set - { - if (value) - { - Show(); - } - else - { - Hide(); - } - } - } + // LayoutAnchorable will hide by default, not close. + _canClose = false; + } - public event EventHandler IsVisibleChanged; + #endregion - void NotifyIsVisibleChanged() - { - if (IsVisibleChanged != null) - IsVisibleChanged(this, EventArgs.Empty); - } + #region Properties - [XmlIgnore] - public bool IsHidden - { - get - { - return (Parent is LayoutRoot); - } - } + #region AutoHideWidth - protected override void OnParentChanged(ILayoutContainer oldValue, ILayoutContainer newValue) + public double AutoHideWidth + { + get + { + return _autohideWidth; + } + set + { + if( _autohideWidth != value ) { - UpdateParentVisibility(); - RaisePropertyChanged("IsVisible"); - NotifyIsVisibleChanged(); - RaisePropertyChanged("IsHidden"); - RaisePropertyChanged("IsAutoHidden"); - base.OnParentChanged(oldValue, newValue); + RaisePropertyChanging( "AutoHideWidth" ); + value = Math.Max( value, _autohideMinWidth ); + _autohideWidth = value; + RaisePropertyChanged( "AutoHideWidth" ); } + } + } + + #endregion + + #region AutoHideMinWidth - void UpdateParentVisibility() + public double AutoHideMinWidth + { + get + { + return _autohideMinWidth; + } + set + { + if( _autohideMinWidth != value ) { - var parentPane = Parent as ILayoutElementWithVisibility; - if (parentPane != null) - parentPane.ComputeVisibility(); + RaisePropertyChanging( "AutoHideMinWidth" ); + if( value < 0 ) + throw new ArgumentException( "value" ); + _autohideMinWidth = value; + RaisePropertyChanged( "AutoHideMinWidth" ); } + } + } - #endregion + #endregion - #region AutoHideWidth + #region AutoHideHeight - private double _autohideWidth = 0.0; - public double AutoHideWidth + public double AutoHideHeight + { + get + { + return _autohideHeight; + } + set + { + if( _autohideHeight != value ) { - get { return _autohideWidth; } - set - { - if (_autohideWidth != value) - { - RaisePropertyChanging("AutoHideWidth"); - value = Math.Max(value, _autohideMinWidth); - _autohideWidth = value; - RaisePropertyChanged("AutoHideWidth"); - } - } + RaisePropertyChanging( "AutoHideHeight" ); + value = Math.Max( value, _autohideMinHeight ); + _autohideHeight = value; + RaisePropertyChanged( "AutoHideHeight" ); } + } + } - #endregion + #endregion - #region AutoHideMinWidth + #region AutoHideMinHeight - private double _autohideMinWidth = 100.0; - public double AutoHideMinWidth + public double AutoHideMinHeight + { + get + { + return _autohideMinHeight; + } + set + { + if( _autohideMinHeight != value ) { - get { return _autohideMinWidth; } - set - { - if (_autohideMinWidth != value) - { - RaisePropertyChanging("AutoHideMinWidth"); - if (value < 0) - throw new ArgumentException("value"); - _autohideMinWidth = value; - RaisePropertyChanged("AutoHideMinWidth"); - } - } + RaisePropertyChanging( "AutoHideMinHeight" ); + if( value < 0 ) + throw new ArgumentException( "value" ); + _autohideMinHeight = value; + RaisePropertyChanged( "AutoHideMinHeight" ); } + } + } - #endregion + #endregion - #region AutoHideHeight + #region CanHide - private double _autohideHeight = 0.0; - public double AutoHideHeight + public bool CanHide + { + get + { + return _canHide; + } + set + { + if( _canHide != value ) { - get { return _autohideHeight; } - set - { - if (_autohideHeight != value) - { - RaisePropertyChanging("AutoHideHeight"); - value = Math.Max(value, _autohideMinHeight); - _autohideHeight = value; - RaisePropertyChanged("AutoHideHeight"); - } - } + _canHide = value; + RaisePropertyChanged( "CanHide" ); } + } + } - #endregion + #endregion - #region AutoHideMinHeight + #region CanAutoHide - private double _autohideMinHeight = 100.0; - public double AutoHideMinHeight + public bool CanAutoHide + { + get + { + return _canAutoHide; + } + set + { + if( _canAutoHide != value ) { - get { return _autohideMinHeight; } - set - { - if (_autohideMinHeight != value) - { - RaisePropertyChanging("AutoHideMinHeight"); - if (value < 0) - throw new ArgumentException("value"); - _autohideMinHeight = value; - RaisePropertyChanged("AutoHideMinHeight"); - } - } + _canAutoHide = value; + RaisePropertyChanged( "CanAutoHide" ); } + } + } - #endregion + #endregion - /// - /// Hide this contents - /// - /// Add this content to collection of parent root. - public void Hide(bool cancelable = true) - { - if (!IsVisible) - { - IsSelected = true; - IsActive = true; - return; - } + #region IsAutoHidden - if (cancelable) - { - CancelEventArgs args = new CancelEventArgs(); - OnHiding(args); - if (args.Cancel) - return; - } + /// + /// Get a value indicating if the anchorable is anchored to a border in an autohide status + /// + public bool IsAutoHidden + { + get + { + return Parent != null && Parent is LayoutAnchorGroup; + } + } - RaisePropertyChanging("IsHidden"); - RaisePropertyChanging("IsVisible"); - //if (Parent is ILayoutPane) - { - var parentAsGroup = Parent as ILayoutGroup; - PreviousContainer = parentAsGroup; - PreviousContainerIndex = parentAsGroup.IndexOfChild(this); - } - Root.Hidden.Add(this); - RaisePropertyChanged("IsVisible"); - RaisePropertyChanged("IsHidden"); - NotifyIsVisibleChanged(); - } + #endregion - public event EventHandler Hiding; + #region IsHidden - protected virtual void OnHiding(CancelEventArgs args) - { - if (Hiding != null) - Hiding(this, args); - } + [XmlIgnore] + public bool IsHidden + { + get + { + return ( Parent is LayoutRoot ); + } + } + + #endregion + #region IsVisible - /// - /// Show the content - /// - /// Try to show the content where it was previously hidden. - public void Show() + [XmlIgnore] + public bool IsVisible + { + get + { + return Parent != null && !( Parent is LayoutRoot ); + } + set + { + if( value ) + { + Show(); + } + else { - if (IsVisible) - return; + Hide(); + } + } + } - if (!IsHidden) - throw new InvalidOperationException(); + #endregion - RaisePropertyChanging("IsHidden"); - RaisePropertyChanging("IsVisible"); + #endregion - bool added = false; - var root = Root; - if (root != null && root.Manager != null) - { - if (root.Manager.LayoutUpdateStrategy != null) - added = root.Manager.LayoutUpdateStrategy.BeforeInsertAnchorable(root as LayoutRoot, this, PreviousContainer); - } + #region Events - if (!added && PreviousContainer != null) - { - var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup; - if (PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount) - previousContainerAsLayoutGroup.InsertChildAt(PreviousContainerIndex, this); - else - previousContainerAsLayoutGroup.InsertChildAt(previousContainerAsLayoutGroup.ChildrenCount, this); - IsSelected = true; - IsActive = true; - } + public event EventHandler IsVisibleChanged; + public event EventHandler Hiding; - if (root != null && root.Manager != null) - { - if (root.Manager.LayoutUpdateStrategy != null) - { - root.Manager.LayoutUpdateStrategy.AfterInsertAnchorable(root as LayoutRoot, this); - } - } + #endregion - PreviousContainer = null; - PreviousContainerIndex = -1; + #region Overrides - RaisePropertyChanged("IsVisible"); - RaisePropertyChanged("IsHidden"); - NotifyIsVisibleChanged(); - } + protected override void OnParentChanged( ILayoutContainer oldValue, ILayoutContainer newValue ) + { + UpdateParentVisibility(); + RaisePropertyChanged( "IsVisible" ); + NotifyIsVisibleChanged(); + RaisePropertyChanged( "IsHidden" ); + RaisePropertyChanged( "IsAutoHidden" ); + base.OnParentChanged( oldValue, newValue ); + } - protected override void InternalDock() + protected override void InternalDock() + { + var root = Root as LayoutRoot; + LayoutAnchorablePane anchorablePane = null; + + if( root.ActiveContent != null && + root.ActiveContent != this ) + { + //look for active content parent pane + anchorablePane = root.ActiveContent.Parent as LayoutAnchorablePane; + } + + if( anchorablePane == null ) + { + //look for a pane on the right side + anchorablePane = root.Descendents().OfType().Where( pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right ).FirstOrDefault(); + } + + if( anchorablePane == null ) + { + //look for an available pane + anchorablePane = root.Descendents().OfType().FirstOrDefault(); + } + + + bool added = false; + if( root.Manager.LayoutUpdateStrategy != null ) + { + added = root.Manager.LayoutUpdateStrategy.BeforeInsertAnchorable( root, this, anchorablePane ); + } + + if( !added ) + { + if( anchorablePane == null ) { - var root = Root as LayoutRoot; - LayoutAnchorablePane anchorablePane = null; - - if (root.ActiveContent != null && - root.ActiveContent != this) - { - //look for active content parent pane - anchorablePane = root.ActiveContent.Parent as LayoutAnchorablePane; - } + var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal }; + if( root.RootPanel != null ) + { + mainLayoutPanel.Children.Add( root.RootPanel ); + } + + root.RootPanel = mainLayoutPanel; + anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength( 200.0, GridUnitType.Pixel ) }; + mainLayoutPanel.Children.Add( anchorablePane ); + } - if (anchorablePane == null) - { - //look for a pane on the right side - anchorablePane = root.Descendents().OfType().Where(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right).FirstOrDefault(); - } + anchorablePane.Children.Add( this ); + added = true; + } - if (anchorablePane == null) - { - //look for an available pane - anchorablePane = root.Descendents().OfType().FirstOrDefault(); - } + if( root.Manager.LayoutUpdateStrategy != null ) + { + root.Manager.LayoutUpdateStrategy.AfterInsertAnchorable( root, this ); + } + base.InternalDock(); + } - bool added = false; - if (root.Manager.LayoutUpdateStrategy != null) - { - added = root.Manager.LayoutUpdateStrategy.BeforeInsertAnchorable(root, this, anchorablePane); - } + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "CanHide" ) ) + CanHide = bool.Parse( reader.Value ); + if( reader.MoveToAttribute( "CanAutoHide" ) ) + CanAutoHide = bool.Parse( reader.Value ); + if( reader.MoveToAttribute( "AutoHideWidth" ) ) + AutoHideWidth = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "AutoHideHeight" ) ) + AutoHideHeight = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "AutoHideMinWidth" ) ) + AutoHideMinWidth = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "AutoHideMinHeight" ) ) + AutoHideMinHeight = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + + base.ReadXml( reader ); + } - if (!added) - { - if (anchorablePane == null) - { - var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal }; - if (root.RootPanel != null) - { - mainLayoutPanel.Children.Add(root.RootPanel); - } - - root.RootPanel = mainLayoutPanel; - anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength(200.0, GridUnitType.Pixel) }; - mainLayoutPanel.Children.Add(anchorablePane); - } - - anchorablePane.Children.Add(this); - added = true; - } + public override void WriteXml( System.Xml.XmlWriter writer ) + { + if( !CanHide ) + writer.WriteAttributeString( "CanHide", CanHide.ToString() ); + if( !CanAutoHide ) + writer.WriteAttributeString( "CanAutoHide", CanAutoHide.ToString( CultureInfo.InvariantCulture ) ); + if( AutoHideWidth > 0 ) + writer.WriteAttributeString( "AutoHideWidth", AutoHideWidth.ToString( CultureInfo.InvariantCulture ) ); + if( AutoHideHeight > 0 ) + writer.WriteAttributeString( "AutoHideHeight", AutoHideHeight.ToString( CultureInfo.InvariantCulture ) ); + if( AutoHideMinWidth != 25.0 ) + writer.WriteAttributeString( "AutoHideMinWidth", AutoHideMinWidth.ToString( CultureInfo.InvariantCulture ) ); + if( AutoHideMinHeight != 25.0 ) + writer.WriteAttributeString( "AutoHideMinHeight", AutoHideMinHeight.ToString( CultureInfo.InvariantCulture ) ); + + + base.WriteXml( writer ); + } - if (root.Manager.LayoutUpdateStrategy != null) - { - root.Manager.LayoutUpdateStrategy.AfterInsertAnchorable(root, this); - } + public override void Close() + { + this.CloseAnchorable(); + } - base.InternalDock(); +#if TRACE + public override void ConsoleDump(int tab) + { + System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) ); + System.Diagnostics.Trace.WriteLine( "Anchorable()" ); } +#endif - /// - /// Add the anchorable to a DockingManager layout - /// - /// - /// - public void AddToLayout(DockingManager manager, AnchorableShowStrategy strategy) - { - if (IsVisible || - IsHidden) - throw new InvalidOperationException(); - - - bool most = (strategy & AnchorableShowStrategy.Most) == AnchorableShowStrategy.Most; - bool left = (strategy & AnchorableShowStrategy.Left) == AnchorableShowStrategy.Left; - bool right = (strategy & AnchorableShowStrategy.Right) == AnchorableShowStrategy.Right; - bool top = (strategy & AnchorableShowStrategy.Top) == AnchorableShowStrategy.Top; - bool bottom = (strategy & AnchorableShowStrategy.Bottom) == AnchorableShowStrategy.Bottom; - - if (!most) - { - var side = AnchorSide.Left; - if (left) - side = AnchorSide.Left; - if (right) - side = AnchorSide.Right; - if (top) - side = AnchorSide.Top; - if (bottom) - side = AnchorSide.Bottom; - - var anchorablePane = manager.Layout.Descendents().OfType().FirstOrDefault(p => p.GetSide() == side); - if (anchorablePane != null) - anchorablePane.Children.Add(this); - else - most = true; - } + #endregion + #region Public Methods - if (most) - { - if (manager.Layout.RootPanel == null) - manager.Layout.RootPanel = new LayoutPanel() { Orientation = (left || right ? Orientation.Horizontal : Orientation.Vertical) }; - - if (left || right) - { - if (manager.Layout.RootPanel.Orientation == Orientation.Vertical && - manager.Layout.RootPanel.ChildrenCount > 1) - { - manager.Layout.RootPanel = new LayoutPanel(manager.Layout.RootPanel); - } - - manager.Layout.RootPanel.Orientation = Orientation.Horizontal; - - if (left) - manager.Layout.RootPanel.Children.Insert(0, new LayoutAnchorablePane(this)); - else - manager.Layout.RootPanel.Children.Add(new LayoutAnchorablePane(this)); - } - else - { - if (manager.Layout.RootPanel.Orientation == Orientation.Horizontal && - manager.Layout.RootPanel.ChildrenCount > 1) - { - manager.Layout.RootPanel = new LayoutPanel(manager.Layout.RootPanel); - } - - manager.Layout.RootPanel.Orientation = Orientation.Vertical; - - if (top) - manager.Layout.RootPanel.Children.Insert(0, new LayoutAnchorablePane(this)); - else - manager.Layout.RootPanel.Children.Add(new LayoutAnchorablePane(this)); - } + /// + /// Hide this contents + /// + /// Add this content to collection of parent root. + public void Hide( bool cancelable = true ) + { + if( !IsVisible ) + { + IsSelected = true; + IsActive = true; + return; + } + + if( cancelable ) + { + CancelEventArgs args = new CancelEventArgs(); + OnHiding( args ); + if( args.Cancel ) + return; + } + + RaisePropertyChanging( "IsHidden" ); + RaisePropertyChanging( "IsVisible" ); + //if (Parent is ILayoutPane) + { + var parentAsGroup = Parent as ILayoutGroup; + PreviousContainer = parentAsGroup; + PreviousContainerIndex = parentAsGroup.IndexOfChild( this ); + } + Root.Hidden.Add( this ); + RaisePropertyChanged( "IsVisible" ); + RaisePropertyChanged( "IsHidden" ); + NotifyIsVisibleChanged(); + } - } + + /// + /// Show the content + /// + /// Try to show the content where it was previously hidden. + public void Show() + { + if( IsVisible ) + return; + + if( !IsHidden ) + throw new InvalidOperationException(); + + RaisePropertyChanging( "IsHidden" ); + RaisePropertyChanging( "IsVisible" ); + + bool added = false; + var root = Root; + if( root != null && root.Manager != null ) + { + if( root.Manager.LayoutUpdateStrategy != null ) + added = root.Manager.LayoutUpdateStrategy.BeforeInsertAnchorable( root as LayoutRoot, this, PreviousContainer ); + } + + if( !added && PreviousContainer != null ) + { + var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup; + if( PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount ) + previousContainerAsLayoutGroup.InsertChildAt( PreviousContainerIndex, this ); + else + previousContainerAsLayoutGroup.InsertChildAt( previousContainerAsLayoutGroup.ChildrenCount, this ); + IsSelected = true; + IsActive = true; + } + + if( root != null && root.Manager != null ) + { + if( root.Manager.LayoutUpdateStrategy != null ) + { + root.Manager.LayoutUpdateStrategy.AfterInsertAnchorable( root as LayoutRoot, this ); } + } + + PreviousContainer = null; + PreviousContainerIndex = -1; + + RaisePropertyChanged( "IsVisible" ); + RaisePropertyChanged( "IsHidden" ); + NotifyIsVisibleChanged(); + } - /// - /// Get a value indicating if the anchorable is anchored to a border in an autohide status - /// - public bool IsAutoHidden + /// + /// Add the anchorable to a DockingManager layout + /// + /// + /// + public void AddToLayout( DockingManager manager, AnchorableShowStrategy strategy ) + { + if( IsVisible || + IsHidden ) + throw new InvalidOperationException(); + + + bool most = ( strategy & AnchorableShowStrategy.Most ) == AnchorableShowStrategy.Most; + bool left = ( strategy & AnchorableShowStrategy.Left ) == AnchorableShowStrategy.Left; + bool right = ( strategy & AnchorableShowStrategy.Right ) == AnchorableShowStrategy.Right; + bool top = ( strategy & AnchorableShowStrategy.Top ) == AnchorableShowStrategy.Top; + bool bottom = ( strategy & AnchorableShowStrategy.Bottom ) == AnchorableShowStrategy.Bottom; + + if( !most ) + { + var side = AnchorSide.Left; + if( left ) + side = AnchorSide.Left; + if( right ) + side = AnchorSide.Right; + if( top ) + side = AnchorSide.Top; + if( bottom ) + side = AnchorSide.Bottom; + + var anchorablePane = manager.Layout.Descendents().OfType().FirstOrDefault( p => p.GetSide() == side ); + if( anchorablePane != null ) + anchorablePane.Children.Add( this ); + else + most = true; + } + + + if( most ) + { + if( manager.Layout.RootPanel == null ) + manager.Layout.RootPanel = new LayoutPanel() { Orientation = ( left || right ? Orientation.Horizontal : Orientation.Vertical ) }; + + if( left || right ) + { + if( manager.Layout.RootPanel.Orientation == Orientation.Vertical && + manager.Layout.RootPanel.ChildrenCount > 1 ) + { + manager.Layout.RootPanel = new LayoutPanel( manager.Layout.RootPanel ); + } + + manager.Layout.RootPanel.Orientation = Orientation.Horizontal; + + if( left ) + manager.Layout.RootPanel.Children.Insert( 0, new LayoutAnchorablePane( this ) ); + else + manager.Layout.RootPanel.Children.Add( new LayoutAnchorablePane( this ) ); + } + else { - get { return Parent != null && Parent is LayoutAnchorGroup; } + if( manager.Layout.RootPanel.Orientation == Orientation.Horizontal && + manager.Layout.RootPanel.ChildrenCount > 1 ) + { + manager.Layout.RootPanel = new LayoutPanel( manager.Layout.RootPanel ); + } + + manager.Layout.RootPanel.Orientation = Orientation.Vertical; + + if( top ) + manager.Layout.RootPanel.Children.Insert( 0, new LayoutAnchorablePane( this ) ); + else + manager.Layout.RootPanel.Children.Add( new LayoutAnchorablePane( this ) ); } + } + } - #region AutoHide - public void ToggleAutoHide() + public void ToggleAutoHide() + { + #region Anchorable is already auto hidden + if( IsAutoHidden ) + { + var parentGroup = Parent as LayoutAnchorGroup; + var parentSide = parentGroup.Parent as LayoutAnchorSide; + var previousContainer = ( ( ILayoutPreviousContainer )parentGroup ).PreviousContainer as LayoutAnchorablePane; + + if( previousContainer == null ) { - #region Anchorable is already auto hidden - if (IsAutoHidden) - { - var parentGroup = Parent as LayoutAnchorGroup; - var parentSide = parentGroup.Parent as LayoutAnchorSide; - var previousContainer = ((ILayoutPreviousContainer)parentGroup).PreviousContainer as LayoutAnchorablePane; - - if (previousContainer == null) - { - AnchorSide side = (parentGroup.Parent as LayoutAnchorSide).Side; - switch (side) - { - case AnchorSide.Right: - if (parentGroup.Root.RootPanel.Orientation == Orientation.Horizontal) - { - previousContainer = new LayoutAnchorablePane(); - parentGroup.Root.RootPanel.Children.Add(previousContainer); - } - else - { - previousContainer = new LayoutAnchorablePane(); - LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Horizontal }; - LayoutRoot root = parentGroup.Root as LayoutRoot; - LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel; - root.RootPanel = panel; - panel.Children.Add(oldRootPanel); - panel.Children.Add(previousContainer); - } - break; - case AnchorSide.Left: - if (parentGroup.Root.RootPanel.Orientation == Orientation.Horizontal) - { - previousContainer = new LayoutAnchorablePane(); - parentGroup.Root.RootPanel.Children.Insert(0, previousContainer); - } - else - { - previousContainer = new LayoutAnchorablePane(); - LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Horizontal }; - LayoutRoot root = parentGroup.Root as LayoutRoot; - LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel; - root.RootPanel = panel; - panel.Children.Add(previousContainer); - panel.Children.Add(oldRootPanel); - } - break; - case AnchorSide.Top: - if (parentGroup.Root.RootPanel.Orientation == Orientation.Vertical) - { - previousContainer = new LayoutAnchorablePane(); - parentGroup.Root.RootPanel.Children.Insert(0, previousContainer); - } - else - { - previousContainer = new LayoutAnchorablePane(); - LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Vertical }; - LayoutRoot root = parentGroup.Root as LayoutRoot; - LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel; - root.RootPanel = panel; - panel.Children.Add(previousContainer); - panel.Children.Add(oldRootPanel); - } - break; - case AnchorSide.Bottom: - if (parentGroup.Root.RootPanel.Orientation == Orientation.Vertical) - { - previousContainer = new LayoutAnchorablePane(); - parentGroup.Root.RootPanel.Children.Add(previousContainer); - } - else - { - previousContainer = new LayoutAnchorablePane(); - LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Vertical }; - LayoutRoot root = parentGroup.Root as LayoutRoot; - LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel; - root.RootPanel = panel; - panel.Children.Add(oldRootPanel); - panel.Children.Add(previousContainer); - } - break; - } - } - else - { - //I'm about to remove parentGroup, redirect any content (ie hidden contents) that point to it - //to previousContainer - LayoutRoot root = parentGroup.Root as LayoutRoot; - foreach (var cnt in root.Descendents().OfType().Where(c => c.PreviousContainer == parentGroup)) - { - cnt.PreviousContainer = previousContainer; - } - } - - - foreach (var anchorableToToggle in parentGroup.Children.ToArray()) - { - previousContainer.Children.Add(anchorableToToggle); - } - - parentSide.Children.Remove(parentGroup); - } - #endregion - #region Anchorable is docked - else if (Parent is LayoutAnchorablePane) - { - var root = Root; - var parentPane = Parent as LayoutAnchorablePane; - - var newAnchorGroup = new LayoutAnchorGroup(); - - ((ILayoutPreviousContainer)newAnchorGroup).PreviousContainer = parentPane; - - foreach (var anchorableToImport in parentPane.Children.ToArray()) - newAnchorGroup.Children.Add(anchorableToImport); - - //detect anchor side for the pane - var anchorSide = parentPane.GetSide(); - - switch (anchorSide) - { - case AnchorSide.Right: - root.RightSide.Children.Add(newAnchorGroup); - break; - case AnchorSide.Left: - root.LeftSide.Children.Add(newAnchorGroup); - break; - case AnchorSide.Top: - root.TopSide.Children.Add(newAnchorGroup); - break; - case AnchorSide.Bottom: - root.BottomSide.Children.Add(newAnchorGroup); - break; - } - } - #endregion + AnchorSide side = ( parentGroup.Parent as LayoutAnchorSide ).Side; + switch( side ) + { + case AnchorSide.Right: + if( parentGroup.Root.RootPanel.Orientation == Orientation.Horizontal ) + { + previousContainer = new LayoutAnchorablePane(); + previousContainer.DockMinWidth = this.AutoHideMinWidth; + parentGroup.Root.RootPanel.Children.Add( previousContainer ); + } + else + { + previousContainer = new LayoutAnchorablePane(); + LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Horizontal }; + LayoutRoot root = parentGroup.Root as LayoutRoot; + LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel; + root.RootPanel = panel; + panel.Children.Add( oldRootPanel ); + panel.Children.Add( previousContainer ); + } + break; + case AnchorSide.Left: + if( parentGroup.Root.RootPanel.Orientation == Orientation.Horizontal ) + { + previousContainer = new LayoutAnchorablePane(); + previousContainer.DockMinWidth = this.AutoHideMinWidth; + parentGroup.Root.RootPanel.Children.Insert( 0, previousContainer ); + } + else + { + previousContainer = new LayoutAnchorablePane(); + LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Horizontal }; + LayoutRoot root = parentGroup.Root as LayoutRoot; + LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel; + root.RootPanel = panel; + panel.Children.Add( previousContainer ); + panel.Children.Add( oldRootPanel ); + } + break; + case AnchorSide.Top: + if( parentGroup.Root.RootPanel.Orientation == Orientation.Vertical ) + { + previousContainer = new LayoutAnchorablePane(); + previousContainer.DockMinHeight = this.AutoHideMinHeight; + parentGroup.Root.RootPanel.Children.Insert( 0, previousContainer ); + } + else + { + previousContainer = new LayoutAnchorablePane(); + LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Vertical }; + LayoutRoot root = parentGroup.Root as LayoutRoot; + LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel; + root.RootPanel = panel; + panel.Children.Add( previousContainer ); + panel.Children.Add( oldRootPanel ); + } + break; + case AnchorSide.Bottom: + if( parentGroup.Root.RootPanel.Orientation == Orientation.Vertical ) + { + previousContainer = new LayoutAnchorablePane(); + previousContainer.DockMinHeight = this.AutoHideMinHeight; + parentGroup.Root.RootPanel.Children.Add( previousContainer ); + } + else + { + previousContainer = new LayoutAnchorablePane(); + LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Vertical }; + LayoutRoot root = parentGroup.Root as LayoutRoot; + LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel; + root.RootPanel = panel; + panel.Children.Add( oldRootPanel ); + panel.Children.Add( previousContainer ); + } + break; + } + } + else + { + //I'm about to remove parentGroup, redirect any content (ie hidden contents) that point to it + //to previousContainer + LayoutRoot root = parentGroup.Root as LayoutRoot; + foreach( var cnt in root.Descendents().OfType().Where( c => c.PreviousContainer == parentGroup ) ) + { + cnt.PreviousContainer = previousContainer; + } } - #endregion + foreach( var anchorableToToggle in parentGroup.Children.ToArray() ) + { + previousContainer.Children.Add( anchorableToToggle ); + } - #region CanHide + parentSide.Children.Remove( parentGroup ); - private bool _canHide = true; - public bool CanHide + var parent = previousContainer.Parent as LayoutGroupBase; + while( ( parent != null ) ) { - get { return _canHide; } - set - { - if (_canHide != value) - { - _canHide = value; - RaisePropertyChanged("CanHide"); - } - } + if( parent is LayoutGroup ) + { + ( ( LayoutGroup )parent ).ComputeVisibility(); + } + parent = parent.Parent as LayoutGroupBase; } + } + #endregion + + #region Anchorable is docked + else if( Parent is LayoutAnchorablePane ) + { + var root = Root; + var parentPane = Parent as LayoutAnchorablePane; + + var newAnchorGroup = new LayoutAnchorGroup(); + + ( ( ILayoutPreviousContainer )newAnchorGroup ).PreviousContainer = parentPane; - #endregion + foreach( var anchorableToImport in parentPane.Children.ToArray() ) + newAnchorGroup.Children.Add( anchorableToImport ); - #region CanAutoHide + //detect anchor side for the pane + var anchorSide = parentPane.GetSide(); - private bool _canAutoHide = true; - public bool CanAutoHide + switch( anchorSide ) { - get { return _canAutoHide; } - set + case AnchorSide.Right: + if( root.RightSide != null ) + { + root.RightSide.Children.Add( newAnchorGroup ); + } + break; + case AnchorSide.Left: + if( root.LeftSide != null ) + { + root.LeftSide.Children.Add( newAnchorGroup ); + } + break; + case AnchorSide.Top: + if( root.TopSide != null ) + { + root.TopSide.Children.Add( newAnchorGroup ); + } + break; + case AnchorSide.Bottom: + if( root.BottomSide != null ) { - if (_canAutoHide != value) - { - _canAutoHide = value; - RaisePropertyChanged("CanAutoHide"); - } + root.BottomSide.Children.Add( newAnchorGroup ); } + break; } + } + #endregion + } - #endregion + #endregion + #region Internal Methods - public override void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("CanHide")) - CanHide = bool.Parse(reader.Value); - if (reader.MoveToAttribute("CanAutoHide")) - CanAutoHide = bool.Parse(reader.Value); - if (reader.MoveToAttribute("AutoHideWidth")) - AutoHideWidth = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("AutoHideHeight")) - AutoHideHeight = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("AutoHideMinWidth")) - AutoHideMinWidth = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("AutoHideMinHeight")) - AutoHideMinHeight = double.Parse(reader.Value, CultureInfo.InvariantCulture); - - base.ReadXml(reader); - } + protected virtual void OnHiding( CancelEventArgs args ) + { + if( Hiding != null ) + Hiding( this, args ); + } - public override void WriteXml(System.Xml.XmlWriter writer) - { - if (!CanHide) - writer.WriteAttributeString("CanHide", CanHide.ToString()); - if (!CanAutoHide) - writer.WriteAttributeString("CanAutoHide", CanAutoHide.ToString(CultureInfo.InvariantCulture)); - if (AutoHideWidth > 0) - writer.WriteAttributeString("AutoHideWidth", AutoHideWidth.ToString(CultureInfo.InvariantCulture)); - if (AutoHideHeight > 0) - writer.WriteAttributeString("AutoHideHeight", AutoHideHeight.ToString(CultureInfo.InvariantCulture)); - if (AutoHideMinWidth != 25.0) - writer.WriteAttributeString("AutoHideMinWidth", AutoHideMinWidth.ToString(CultureInfo.InvariantCulture)); - if (AutoHideMinHeight != 25.0) - writer.WriteAttributeString("AutoHideMinHeight", AutoHideMinHeight.ToString(CultureInfo.InvariantCulture)); - - - base.WriteXml(writer); - } + internal void CloseAnchorable() + { + if( this.TestCanClose() ) + { + if( this.IsAutoHidden ) + this.ToggleAutoHide(); + + this.CloseInternal(); + } + } + internal void SetCanCloseInternal( bool canClose ) + { + _canCloseValueBeforeInternalSet = _canClose; + _canClose = canClose; + } -#if TRACE - public override void ConsoleDump(int tab) - { - System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) ); - System.Diagnostics.Trace.WriteLine( "Anchorable()" ); - } -#endif + internal void ResetCanCloseInternal() + { + _canClose = _canCloseValueBeforeInternalSet; + } + + #endregion + + #region Private Methods + + private void NotifyIsVisibleChanged() + { + if( IsVisibleChanged != null ) + IsVisibleChanged( this, EventArgs.Empty ); } + + private void UpdateParentVisibility() + { + var parentPane = Parent as ILayoutElementWithVisibility; + if( parentPane != null ) + parentPane.ComputeVisibility(); + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorableFloatingWindow.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorableFloatingWindow.cs index 12500be7..2dc51092 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorableFloatingWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorableFloatingWindow.cs @@ -17,157 +17,216 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Markup; using System.Diagnostics; using System.Xml.Serialization; +using System.Xml; namespace Xceed.Wpf.AvalonDock.Layout { - [Serializable] - [ContentProperty("RootPanel")] - public class LayoutAnchorableFloatingWindow : LayoutFloatingWindow, ILayoutElementWithVisibility + [Serializable] + [ContentProperty( "RootPanel" )] + public class LayoutAnchorableFloatingWindow : LayoutFloatingWindow, ILayoutElementWithVisibility + { + #region Members + + private LayoutAnchorablePaneGroup _rootPanel = null; + [NonSerialized] + private bool _isVisible = true; + + #endregion + + #region Constructors + + public LayoutAnchorableFloatingWindow() { - public LayoutAnchorableFloatingWindow() - { + } - } + #endregion - #region RootPanel + #region Properties - private LayoutAnchorablePaneGroup _rootPanel = null; - public LayoutAnchorablePaneGroup RootPanel - { - get { return _rootPanel; } - set - { - if (_rootPanel != value) - { - RaisePropertyChanging("RootPanel"); - - if (_rootPanel != null) - _rootPanel.ChildrenTreeChanged -= new EventHandler(_rootPanel_ChildrenTreeChanged); - - _rootPanel = value; - if (_rootPanel != null) - _rootPanel.Parent = this; - - if (_rootPanel != null) - _rootPanel.ChildrenTreeChanged += new EventHandler(_rootPanel_ChildrenTreeChanged); - - RaisePropertyChanged("RootPanel"); - RaisePropertyChanged("IsSinglePane"); - RaisePropertyChanged("SinglePane"); - RaisePropertyChanged("Children"); - RaisePropertyChanged("ChildrenCount"); - ((ILayoutElementWithVisibility)this).ComputeVisibility(); - } - } - } + #region IsSinglePane - void _rootPanel_ChildrenTreeChanged(object sender, ChildrenTreeChangedEventArgs e) - { - RaisePropertyChanged("IsSinglePane"); - RaisePropertyChanged("SinglePane"); + public bool IsSinglePane + { + get + { + return RootPanel != null && RootPanel.Descendents().OfType().Where( p => p.IsVisible ).Count() == 1; + } + } - } + #endregion - public bool IsSinglePane - { - get - { - return RootPanel != null && RootPanel.Descendents().OfType().Where(p => p.IsVisible).Count() == 1; - } - } + #region IsVisible - public ILayoutAnchorablePane SinglePane + [XmlIgnore] + public bool IsVisible + { + get + { + return _isVisible; + } + private set + { + if( _isVisible != value ) { - get - { - if (!IsSinglePane) - return null; - - var singlePane = RootPanel.Descendents().OfType().Single(p => p.IsVisible); - singlePane.UpdateIsDirectlyHostedInFloatingWindow(); - return singlePane; - } + RaisePropertyChanging( "IsVisible" ); + _isVisible = value; + RaisePropertyChanged( "IsVisible" ); + if( IsVisibleChanged != null ) + IsVisibleChanged( this, EventArgs.Empty ); } + } + } - #endregion + #endregion - public override IEnumerable Children + #region RootPanel + + public LayoutAnchorablePaneGroup RootPanel + { + get + { + return _rootPanel; + } + set + { + if( _rootPanel != value ) { - get - { - if (ChildrenCount == 1) - yield return RootPanel; + RaisePropertyChanging( "RootPanel" ); - yield break; - } - } + if( _rootPanel != null ) + _rootPanel.ChildrenTreeChanged -= new EventHandler( _rootPanel_ChildrenTreeChanged ); - public override void RemoveChild(ILayoutElement element) - { - Debug.Assert(element == RootPanel && element != null); - RootPanel = null; - } + _rootPanel = value; + if( _rootPanel != null ) + _rootPanel.Parent = this; - public override void ReplaceChild(ILayoutElement oldElement, ILayoutElement newElement) - { - Debug.Assert(oldElement == RootPanel && oldElement != null); - RootPanel = newElement as LayoutAnchorablePaneGroup; - } + if( _rootPanel != null ) + _rootPanel.ChildrenTreeChanged += new EventHandler( _rootPanel_ChildrenTreeChanged ); - public override int ChildrenCount - { - get - { - if (RootPanel == null) - return 0; - return 1; - } + RaisePropertyChanged( "RootPanel" ); + RaisePropertyChanged( "IsSinglePane" ); + RaisePropertyChanged( "SinglePane" ); + RaisePropertyChanged( "Children" ); + RaisePropertyChanged( "ChildrenCount" ); + ( ( ILayoutElementWithVisibility )this ).ComputeVisibility(); } + } + } - #region IsVisible - [NonSerialized] - private bool _isVisible = true; + #endregion - [XmlIgnore] - public bool IsVisible - { - get { return _isVisible; } - private set - { - if (_isVisible != value) - { - RaisePropertyChanging("IsVisible"); - _isVisible = value; - RaisePropertyChanged("IsVisible"); - if (IsVisibleChanged != null) - IsVisibleChanged(this, EventArgs.Empty); - } - } - } + #region SinglePane + + public ILayoutAnchorablePane SinglePane + { + get + { + if( !IsSinglePane ) + return null; + + var singlePane = RootPanel.Descendents().OfType().Single( p => p.IsVisible ); + singlePane.UpdateIsDirectlyHostedInFloatingWindow(); + return singlePane; + } + } + + #endregion + + #endregion + + #region Overrides + + public override IEnumerable Children + { + get + { + if( ChildrenCount == 1 ) + yield return RootPanel; - public event EventHandler IsVisibleChanged; + yield break; + } + } - #endregion + public override void RemoveChild( ILayoutElement element ) + { + Debug.Assert( element == RootPanel && element != null ); + RootPanel = null; + } + + public override void ReplaceChild( ILayoutElement oldElement, ILayoutElement newElement ) + { + Debug.Assert( oldElement == RootPanel && oldElement != null ); + RootPanel = newElement as LayoutAnchorablePaneGroup; + } + + public override int ChildrenCount + { + get + { + if( RootPanel == null ) + return 0; + return 1; + } + } + public override bool IsValid + { + get + { + return RootPanel != null; + } + } - void ILayoutElementWithVisibility.ComputeVisibility() + public override void ReadXml( XmlReader reader ) + { + reader.MoveToContent(); + if( reader.IsEmptyElement ) + { + reader.Read(); + ComputeVisibility(); + return; + } + + var localName = reader.LocalName; + reader.Read(); + + while( true ) + { + if( reader.LocalName.Equals( localName ) && ( reader.NodeType == XmlNodeType.EndElement ) ) { - if (RootPanel != null) - IsVisible = RootPanel.IsVisible; - else - IsVisible = false; + break; + } + if( reader.NodeType == XmlNodeType.Whitespace ) + { + reader.Read(); + continue; } - public override bool IsValid + XmlSerializer serializer; + if( reader.LocalName.Equals( "LayoutAnchorablePaneGroup" ) ) { - get { return RootPanel != null; } + serializer = new XmlSerializer( typeof( LayoutAnchorablePaneGroup ) ); + } + else + { + var type = LayoutRoot.FindType( reader.LocalName ); + if( type == null ) + { + throw new ArgumentException( "AvalonDock.LayoutAnchorableFloatingWindow doesn't know how to deserialize " + reader.LocalName ); + } + serializer = new XmlSerializer( type ); } + RootPanel = ( LayoutAnchorablePaneGroup )serializer.Deserialize( reader ); + } + + reader.ReadEndElement(); + } + #if TRACE public override void ConsoleDump(int tab) { @@ -176,6 +235,41 @@ namespace Xceed.Wpf.AvalonDock.Layout RootPanel.ConsoleDump(tab + 1); } -#endif +#endif + + #endregion + + #region Private Methods + + private void _rootPanel_ChildrenTreeChanged( object sender, ChildrenTreeChangedEventArgs e ) + { + RaisePropertyChanged( "IsSinglePane" ); + RaisePropertyChanged( "SinglePane" ); } + + private void ComputeVisibility() + { + if( RootPanel != null ) + IsVisible = RootPanel.IsVisible; + else + IsVisible = false; + } + + #endregion + + #region Events + + public event EventHandler IsVisibleChanged; + + #endregion + + #region ILayoutElementWithVisibility Interface + + void ILayoutElementWithVisibility.ComputeVisibility() + { + ComputeVisibility(); + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorablePane.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorablePane.cs index 0a277bbf..abb9ef29 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorablePane.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorablePane.cs @@ -15,243 +15,221 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Collections.ObjectModel; using System.Windows.Markup; -using System.ComponentModel; using System.Xml.Serialization; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("Children")] - [Serializable] - public class LayoutAnchorablePane : LayoutPositionableGroup, ILayoutAnchorablePane, ILayoutPositionableElement, ILayoutContentSelector, ILayoutPaneSerializable + [ContentProperty( "Children" )] + [Serializable] + public class LayoutAnchorablePane : LayoutPositionableGroup, ILayoutAnchorablePane, ILayoutPositionableElement, ILayoutContentSelector, ILayoutPaneSerializable + { + #region Members + + private int _selectedIndex = -1; + [XmlIgnore] + private bool _autoFixSelectedContent = true; + private string _name = null; + + #endregion + + #region Constructors + + public LayoutAnchorablePane() { - public LayoutAnchorablePane() - { - } + } - public LayoutAnchorablePane(LayoutAnchorable anchorable) - { - Children.Add(anchorable); - } + public LayoutAnchorablePane( LayoutAnchorable anchorable ) + { + Children.Add( anchorable ); + } - protected override bool GetVisibility() - { - return Children.Count > 0 && Children.Any(c => c.IsVisible); - } + #endregion - #region SelectedContentIndex + #region Properties - private int _selectedIndex = -1; - public int SelectedContentIndex - { - get { return _selectedIndex; } - set - { - if (value < 0 || - value >= Children.Count) - value = -1; - - if (_selectedIndex != value) - { - RaisePropertyChanging("SelectedContentIndex"); - RaisePropertyChanging("SelectedContent"); - if (_selectedIndex >= 0 && - _selectedIndex < Children.Count) - Children[_selectedIndex].IsSelected = false; - - _selectedIndex = value; - - if (_selectedIndex >= 0 && - _selectedIndex < Children.Count) - Children[_selectedIndex].IsSelected = true; - - RaisePropertyChanged("SelectedContentIndex"); - RaisePropertyChanged("SelectedContent"); - } - } - } + #region CanHide - protected override void ChildMoved(int oldIndex, int newIndex) - { - if (_selectedIndex == oldIndex) - { - RaisePropertyChanging("SelectedContentIndex"); - _selectedIndex = newIndex; - RaisePropertyChanged("SelectedContentIndex"); - } + public bool CanHide + { + get + { + return Children.All( a => a.CanHide ); + } + } + #endregion - base.ChildMoved(oldIndex, newIndex); - } + #region CanClose - public LayoutContent SelectedContent - { - get - { - return _selectedIndex == -1 ? null : Children[_selectedIndex]; - } - } - #endregion + public bool CanClose + { + get + { + return Children.All( a => a.CanClose ); + } + } - protected override void OnChildrenCollectionChanged() - { - AutoFixSelectedContent(); - for (int i = 0; i < Children.Count; i++) - { - if (Children[i].IsSelected) - { - SelectedContentIndex = i; - break; - } - } - - RaisePropertyChanged("CanClose"); - RaisePropertyChanged("CanHide"); - RaisePropertyChanged("IsDirectlyHostedInFloatingWindow"); - base.OnChildrenCollectionChanged(); - } + #endregion - [XmlIgnore] - bool _autoFixSelectedContent = true; - void AutoFixSelectedContent() - { - if (_autoFixSelectedContent) - { - if (SelectedContentIndex >= ChildrenCount) - SelectedContentIndex = Children.Count - 1; - - if (SelectedContentIndex == -1 && ChildrenCount > 0) - SelectedContentIndex = 0; - } - } + #region IsHostedInFloatingWindow - public int IndexOf(LayoutContent content) - { - var anchorableChild = content as LayoutAnchorable; - if (anchorableChild == null) - return -1; + public bool IsHostedInFloatingWindow + { + get + { + return this.FindParent() != null; + } + } - return Children.IndexOf(anchorableChild); - } + #endregion + #region Name - public bool IsDirectlyHostedInFloatingWindow + public string Name + { + get + { + return _name; + } + set + { + if( _name != value ) { - get - { - var parentFloatingWindow = this.FindParent(); - if (parentFloatingWindow != null) - return parentFloatingWindow.IsSinglePane; - - return false; - //return Parent != null && Parent.ChildrenCount == 1 && Parent.Parent is LayoutFloatingWindow; - } + _name = value; + RaisePropertyChanged( "Name" ); } + } + } - internal void UpdateIsDirectlyHostedInFloatingWindow() - { - RaisePropertyChanged("IsDirectlyHostedInFloatingWindow"); - } + #endregion - public bool IsHostedInFloatingWindow - { - get - { - return this.FindParent() != null; - } - } + #region SelectedContentIndex - protected override void OnParentChanged(ILayoutContainer oldValue, ILayoutContainer newValue) + public int SelectedContentIndex + { + get + { + return _selectedIndex; + } + set + { + if( value < 0 || + value >= Children.Count ) + value = -1; + + if( _selectedIndex != value ) { - var oldGroup = oldValue as ILayoutGroup; - if (oldGroup != null) - oldGroup.ChildrenCollectionChanged -= new EventHandler(OnParentChildrenCollectionChanged); + RaisePropertyChanging( "SelectedContentIndex" ); + RaisePropertyChanging( "SelectedContent" ); + if( _selectedIndex >= 0 && + _selectedIndex < Children.Count ) + Children[ _selectedIndex ].IsSelected = false; - RaisePropertyChanged("IsDirectlyHostedInFloatingWindow"); + _selectedIndex = value; - var newGroup = newValue as ILayoutGroup; - if (newGroup != null) - newGroup.ChildrenCollectionChanged += new EventHandler(OnParentChildrenCollectionChanged); + if( _selectedIndex >= 0 && + _selectedIndex < Children.Count ) + Children[ _selectedIndex ].IsSelected = true; - base.OnParentChanged(oldValue, newValue); + RaisePropertyChanged( "SelectedContentIndex" ); + RaisePropertyChanged( "SelectedContent" ); } + } + } - void OnParentChildrenCollectionChanged(object sender, EventArgs e) - { - RaisePropertyChanged("IsDirectlyHostedInFloatingWindow"); - } + #endregion - string _id; + #region SelectedContent - string ILayoutPaneSerializable.Id - { - get - { - return _id; - } - set - { - _id = value; - } - } + public LayoutContent SelectedContent + { + get + { + return _selectedIndex == -1 ? null : Children[ _selectedIndex ]; + } + } - #region Name + #endregion - private string _name = null; - public string Name - { - get { return _name; } - set - { - if (_name != value) - { - _name = value; - RaisePropertyChanged("Name"); - } - } - } + #endregion - #endregion + #region Overrides + protected override bool GetVisibility() + { + return Children.Count > 0 && Children.Any( c => c.IsVisible ); + } + protected override void ChildMoved( int oldIndex, int newIndex ) + { + if( _selectedIndex == oldIndex ) + { + RaisePropertyChanging( "SelectedContentIndex" ); + _selectedIndex = newIndex; + RaisePropertyChanged( "SelectedContentIndex" ); + } - public override void WriteXml(System.Xml.XmlWriter writer) - { - if (_id != null) - writer.WriteAttributeString("Id", _id); - if (_name != null) - writer.WriteAttributeString("Name", _name); - base.WriteXml(writer); - } + base.ChildMoved( oldIndex, newIndex ); + } - public override void ReadXml(System.Xml.XmlReader reader) + protected override void OnChildrenCollectionChanged() + { + AutoFixSelectedContent(); + for( int i = 0; i < Children.Count; i++ ) + { + if( Children[ i ].IsSelected ) { - if (reader.MoveToAttribute("Id")) - _id = reader.Value; - if (reader.MoveToAttribute("Name")) - _name = reader.Value; - - _autoFixSelectedContent = false; - base.ReadXml(reader); - _autoFixSelectedContent = true; - AutoFixSelectedContent(); + SelectedContentIndex = i; + break; } + } + RaisePropertyChanged( "CanClose" ); + RaisePropertyChanged( "CanHide" ); + RaisePropertyChanged( "IsDirectlyHostedInFloatingWindow" ); + base.OnChildrenCollectionChanged(); + } - public bool CanHide - { - get { return Children.All(a => a.CanHide); } - } + protected override void OnParentChanged( ILayoutContainer oldValue, ILayoutContainer newValue ) + { + var oldGroup = oldValue as ILayoutGroup; + if( oldGroup != null ) + oldGroup.ChildrenCollectionChanged -= new EventHandler( OnParentChildrenCollectionChanged ); - public bool CanClose - { - get { return Children.All(a => a.CanClose);} - } + RaisePropertyChanged( "IsDirectlyHostedInFloatingWindow" ); + + var newGroup = newValue as ILayoutGroup; + if( newGroup != null ) + newGroup.ChildrenCollectionChanged += new EventHandler( OnParentChildrenCollectionChanged ); + + base.OnParentChanged( oldValue, newValue ); + } + + public override void WriteXml( System.Xml.XmlWriter writer ) + { + if( _id != null ) + writer.WriteAttributeString( "Id", _id ); + if( _name != null ) + writer.WriteAttributeString( "Name", _name ); + + base.WriteXml( writer ); + } + + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "Id" ) ) + _id = reader.Value; + if( reader.MoveToAttribute( "Name" ) ) + _name = reader.Value; + + _autoFixSelectedContent = false; + base.ReadXml( reader ); + _autoFixSelectedContent = true; + AutoFixSelectedContent(); + } #if TRACE public override void ConsoleDump(int tab) @@ -263,5 +241,94 @@ namespace Xceed.Wpf.AvalonDock.Layout child.ConsoleDump(tab + 1); } #endif + + #endregion + + #region Public Methods + + public int IndexOf( LayoutContent content ) + { + var anchorableChild = content as LayoutAnchorable; + if( anchorableChild == null ) + return -1; + + return Children.IndexOf( anchorableChild ); + } + + public bool IsDirectlyHostedInFloatingWindow + { + get + { + var parentFloatingWindow = this.FindParent(); + if( parentFloatingWindow != null ) + return parentFloatingWindow.IsSinglePane; + + return false; + //return Parent != null && Parent.ChildrenCount == 1 && Parent.Parent is LayoutFloatingWindow; + } } + + #endregion + + #region Internal Methods + + internal void SetNextSelectedIndex() + { + SelectedContentIndex = -1; + for( int i = 0; i < this.Children.Count; ++i ) + { + if( Children[ i ].IsEnabled ) + { + SelectedContentIndex = i; + return; + } + } + } + + internal void UpdateIsDirectlyHostedInFloatingWindow() + { + RaisePropertyChanged( "IsDirectlyHostedInFloatingWindow" ); + } + + #endregion + + #region Private Methods + + private void AutoFixSelectedContent() + { + if( _autoFixSelectedContent ) + { + if( SelectedContentIndex >= ChildrenCount ) + SelectedContentIndex = Children.Count - 1; + + if( SelectedContentIndex == -1 && ChildrenCount > 0 ) + SetNextSelectedIndex(); + } + } + + private void OnParentChildrenCollectionChanged( object sender, EventArgs e ) + { + RaisePropertyChanged( "IsDirectlyHostedInFloatingWindow" ); + } + + #endregion + + #region ILayoutPaneSerializable Interface + + string _id; + + string ILayoutPaneSerializable.Id + { + get + { + return _id; + } + set + { + _id = value; + } + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorablePaneGroup.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorablePaneGroup.cs index fb4253d8..f00808f0 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorablePaneGroup.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutAnchorablePaneGroup.cs @@ -15,102 +15,104 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Collections.ObjectModel; -using System.Windows; using System.Windows.Controls; using System.Windows.Markup; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("Children")] - [Serializable] - public class LayoutAnchorablePaneGroup : LayoutPositionableGroup, ILayoutAnchorablePane, ILayoutOrientableGroup + [ContentProperty( "Children" )] + [Serializable] + public class LayoutAnchorablePaneGroup : LayoutPositionableGroup, ILayoutAnchorablePane, ILayoutOrientableGroup + { + #region Constructors + + public LayoutAnchorablePaneGroup() { - public LayoutAnchorablePaneGroup() - { - } + } - public LayoutAnchorablePaneGroup(LayoutAnchorablePane firstChild) - { - Children.Add(firstChild); - } + public LayoutAnchorablePaneGroup( LayoutAnchorablePane firstChild ) + { + Children.Add( firstChild ); + } - #region Orientation + #endregion - private Orientation _orientation; - public Orientation Orientation - { - get { return _orientation; } - set - { - if (_orientation != value) - { - RaisePropertyChanging("Orientation"); - _orientation = value; - RaisePropertyChanged("Orientation"); - } - } - } + #region Properties - #endregion + #region Orientation - protected override bool GetVisibility() + private Orientation _orientation; + public Orientation Orientation + { + get + { + return _orientation; + } + set + { + if( _orientation != value ) { - return Children.Count > 0 && Children.Any(c => c.IsVisible); + RaisePropertyChanging( "Orientation" ); + _orientation = value; + RaisePropertyChanged( "Orientation" ); } + } + } - protected override void OnIsVisibleChanged() - { - UpdateParentVisibility(); - base.OnIsVisibleChanged(); - } + #endregion - void UpdateParentVisibility() - { - var parentPane = Parent as ILayoutElementWithVisibility; - if (parentPane != null) - parentPane.ComputeVisibility(); - } + #endregion - protected override void OnDockWidthChanged() - { - if (DockWidth.IsAbsolute && ChildrenCount == 1) - ((ILayoutPositionableElement)Children[0]).DockWidth = DockWidth; + #region Overrides - base.OnDockWidthChanged(); - } + protected override bool GetVisibility() + { + return Children.Count > 0 && Children.Any( c => c.IsVisible ); + } - protected override void OnDockHeightChanged() - { - if (DockHeight.IsAbsolute && ChildrenCount == 1) - ((ILayoutPositionableElement)Children[0]).DockHeight = DockHeight; - base.OnDockHeightChanged(); - } + protected override void OnIsVisibleChanged() + { + UpdateParentVisibility(); + base.OnIsVisibleChanged(); + } - protected override void OnChildrenCollectionChanged() - { - if (DockWidth.IsAbsolute && ChildrenCount == 1) - ((ILayoutPositionableElement)Children[0]).DockWidth = DockWidth; - if (DockHeight.IsAbsolute && ChildrenCount == 1) - ((ILayoutPositionableElement)Children[0]).DockHeight = DockHeight; - base.OnChildrenCollectionChanged(); - } + protected override void OnDockWidthChanged() + { + if( DockWidth.IsAbsolute && ChildrenCount == 1 ) + ( ( ILayoutPositionableElement )Children[ 0 ] ).DockWidth = DockWidth; - public override void WriteXml(System.Xml.XmlWriter writer) - { - writer.WriteAttributeString("Orientation", Orientation.ToString()); - base.WriteXml(writer); - } + base.OnDockWidthChanged(); + } - public override void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("Orientation")) - Orientation = (Orientation)Enum.Parse(typeof(Orientation), reader.Value, true); - base.ReadXml(reader); - } + protected override void OnDockHeightChanged() + { + if( DockHeight.IsAbsolute && ChildrenCount == 1 ) + ( ( ILayoutPositionableElement )Children[ 0 ] ).DockHeight = DockHeight; + base.OnDockHeightChanged(); + } + + protected override void OnChildrenCollectionChanged() + { + if( DockWidth.IsAbsolute && ChildrenCount == 1 ) + ( ( ILayoutPositionableElement )Children[ 0 ] ).DockWidth = DockWidth; + if( DockHeight.IsAbsolute && ChildrenCount == 1 ) + ( ( ILayoutPositionableElement )Children[ 0 ] ).DockHeight = DockHeight; + base.OnChildrenCollectionChanged(); + } + + public override void WriteXml( System.Xml.XmlWriter writer ) + { + writer.WriteAttributeString( "Orientation", Orientation.ToString() ); + base.WriteXml( writer ); + } + + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "Orientation" ) ) + Orientation = ( Orientation )Enum.Parse( typeof( Orientation ), reader.Value, true ); + base.ReadXml( reader ); + } #if TRACE public override void ConsoleDump(int tab) @@ -123,7 +125,17 @@ namespace Xceed.Wpf.AvalonDock.Layout } #endif + #endregion + #region Private Methods + + private void UpdateParentVisibility() + { + var parentPane = Parent as ILayoutElementWithVisibility; + if( parentPane != null ) + parentPane.ComputeVisibility(); } + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutContent.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutContent.cs index 958fae75..65d8c74f 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutContent.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutContent.cs @@ -15,670 +15,779 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Markup; using System.Xml.Serialization; using System.Windows; using System.Globalization; using System.Windows.Media; using System.ComponentModel; +using Xceed.Wpf.AvalonDock.Controls; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("Content")] - [Serializable] - public abstract class LayoutContent : LayoutElement, IXmlSerializable, ILayoutElementForFloatingWindow, IComparable, ILayoutPreviousContainer - { - internal LayoutContent() - { } - - #region Title - - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register("Title", typeof(string), typeof(LayoutContent), new UIPropertyMetadata(null, OnTitlePropertyChanged, CoerceTitleValue)); - - public string Title - { - get { return (string)GetValue(TitleProperty); } - set { SetValue(TitleProperty, value); } - } - - private static object CoerceTitleValue(DependencyObject obj, object value) - { - var lc = (LayoutContent)obj; - if (((string)value) != lc.Title) - { - lc.RaisePropertyChanging(LayoutContent.TitleProperty.Name); - } - return value; - } - - private static void OnTitlePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) - { - ((LayoutContent)obj).RaisePropertyChanged(LayoutContent.TitleProperty.Name); - } - - #endregion - - #region Content - [NonSerialized] - private object _content = null; - [XmlIgnore] - public object Content - { - get { return _content; } - set - { - if (_content != value) - { - RaisePropertyChanging("Content"); - _content = value; - RaisePropertyChanged("Content"); - } - } - } - - #endregion - - #region ContentId - - private string _contentId = null; - public string ContentId - { - get - { - if (_contentId == null) - { - var contentAsControl = _content as FrameworkElement; - if (contentAsControl != null && !string.IsNullOrWhiteSpace(contentAsControl.Name)) - return contentAsControl.Name; - } - return _contentId; - } - set - { - if (_contentId != value) - { - _contentId = value; - RaisePropertyChanged("ContentId"); - } - } - } - - #endregion - - #region IsSelected - - private bool _isSelected = false; - public bool IsSelected - { - get { return _isSelected; } - set - { - if (_isSelected != value) - { - bool oldValue = _isSelected; - RaisePropertyChanging("IsSelected"); - _isSelected = value; - var parentSelector = (Parent as ILayoutContentSelector); - if (parentSelector != null) - parentSelector.SelectedContentIndex = _isSelected ? parentSelector.IndexOf(this) : -1; - OnIsSelectedChanged(oldValue, value); - RaisePropertyChanged("IsSelected"); - } - } - } - - /// - /// Provides derived classes an opportunity to handle changes to the IsSelected property. - /// - protected virtual void OnIsSelectedChanged(bool oldValue, bool newValue) - { - if (IsSelectedChanged != null) - IsSelectedChanged(this, EventArgs.Empty); - } - - public event EventHandler IsSelectedChanged; - - #endregion - - #region IsActive - - [field: NonSerialized] - private bool _isActive = false; - [XmlIgnore] - public bool IsActive - { - get { return _isActive; } - set - { - if (_isActive != value) - { - RaisePropertyChanging("IsActive"); - bool oldValue = _isActive; - - _isActive = value; - - var root = Root; - if (root != null && _isActive) - root.ActiveContent = this; - - if (_isActive) - IsSelected = true; - - OnIsActiveChanged(oldValue, value); - RaisePropertyChanged("IsActive"); - } - } - } - - /// - /// Provides derived classes an opportunity to handle changes to the IsActive property. - /// - protected virtual void OnIsActiveChanged(bool oldValue, bool newValue) - { - if (newValue) - LastActivationTimeStamp = DateTime.Now; - - if (IsActiveChanged != null) - IsActiveChanged(this, EventArgs.Empty); - } - - public event EventHandler IsActiveChanged; - - #endregion - - #region IsLastFocusedDocument - - private bool _isLastFocusedDocument = false; - public bool IsLastFocusedDocument - { - get { return _isLastFocusedDocument; } - internal set - { - if (_isLastFocusedDocument != value) - { - RaisePropertyChanging("IsLastFocusedDocument"); - _isLastFocusedDocument = value; - RaisePropertyChanged("IsLastFocusedDocument"); - } - } - } + [ContentProperty( "Content" )] + [Serializable] + public abstract class LayoutContent : LayoutElement, IXmlSerializable, ILayoutElementForFloatingWindow, IComparable, ILayoutPreviousContainer + { + #region Constructors + + internal LayoutContent() + { + } + + #endregion + + #region Properties + + #region Title + + public static readonly DependencyProperty TitleProperty = DependencyProperty.Register( "Title", typeof( string ), typeof( LayoutContent ), new UIPropertyMetadata( null, OnTitlePropertyChanged, CoerceTitleValue ) ); + + public string Title + { + get + { + return ( string )GetValue( TitleProperty ); + } + set + { + SetValue( TitleProperty, value ); + } + } + + private static object CoerceTitleValue( DependencyObject obj, object value ) + { + var lc = ( LayoutContent )obj; + if( ( ( string )value ) != lc.Title ) + { + lc.RaisePropertyChanging( LayoutContent.TitleProperty.Name ); + } + return value; + } + + private static void OnTitlePropertyChanged( DependencyObject obj, DependencyPropertyChangedEventArgs args ) + { + ( ( LayoutContent )obj ).RaisePropertyChanged( LayoutContent.TitleProperty.Name ); + } + + #endregion //Title + + #region Content + [NonSerialized] + private object _content = null; + [XmlIgnore] + public object Content + { + get + { + return _content; + } + set + { + if( _content != value ) + { + RaisePropertyChanging( "Content" ); + _content = value; + RaisePropertyChanged( "Content" ); + } + } + } + + #endregion + + #region ContentId + + private string _contentId = null; + public string ContentId + { + get + { + if( _contentId == null ) + { + var contentAsControl = _content as FrameworkElement; + if( contentAsControl != null && !string.IsNullOrWhiteSpace( contentAsControl.Name ) ) + return contentAsControl.Name; + } + return _contentId; + } + set + { + if( _contentId != value ) + { + _contentId = value; + RaisePropertyChanged( "ContentId" ); + } + } + } + + #endregion + + #region IsSelected + + private bool _isSelected = false; + public bool IsSelected + { + get + { + return _isSelected; + } + set + { + if( _isSelected != value ) + { + bool oldValue = _isSelected; + RaisePropertyChanging( "IsSelected" ); + _isSelected = value; + var parentSelector = ( Parent as ILayoutContentSelector ); + if( parentSelector != null ) + parentSelector.SelectedContentIndex = _isSelected ? parentSelector.IndexOf( this ) : -1; + OnIsSelectedChanged( oldValue, value ); + RaisePropertyChanged( "IsSelected" ); + LayoutAnchorableTabItem.CancelMouseLeave(); + } + } + } + + /// + /// Provides derived classes an opportunity to handle changes to the IsSelected property. + /// + protected virtual void OnIsSelectedChanged( bool oldValue, bool newValue ) + { + if( IsSelectedChanged != null ) + IsSelectedChanged( this, EventArgs.Empty ); + } + + public event EventHandler IsSelectedChanged; + + #endregion + + #region IsActive + + [field: NonSerialized] + private bool _isActive = false; + [XmlIgnore] + public bool IsActive + { + get + { + return _isActive; + } + set + { + if( _isActive != value ) + { + RaisePropertyChanging( "IsActive" ); + bool oldValue = _isActive; + + _isActive = value; + + var root = Root; + if( root != null && _isActive ) + root.ActiveContent = this; + + if( _isActive ) + IsSelected = true; + + OnIsActiveChanged( oldValue, value ); + RaisePropertyChanged( "IsActive" ); + } + } + } + + /// + /// Provides derived classes an opportunity to handle changes to the IsActive property. + /// + protected virtual void OnIsActiveChanged( bool oldValue, bool newValue ) + { + if( newValue ) + LastActivationTimeStamp = DateTime.Now; + + if( IsActiveChanged != null ) + IsActiveChanged( this, EventArgs.Empty ); + } + + public event EventHandler IsActiveChanged; + + #endregion + + #region IsLastFocusedDocument + + private bool _isLastFocusedDocument = false; + public bool IsLastFocusedDocument + { + get + { + return _isLastFocusedDocument; + } + internal set + { + if( _isLastFocusedDocument != value ) + { + RaisePropertyChanging( "IsLastFocusedDocument" ); + _isLastFocusedDocument = value; + RaisePropertyChanged( "IsLastFocusedDocument" ); + } + } + } + + #endregion + + #region PreviousContainer + + [field: NonSerialized] + private ILayoutContainer _previousContainer = null; + + [XmlIgnore] + ILayoutContainer ILayoutPreviousContainer.PreviousContainer + { + get + { + return _previousContainer; + } + set + { + if( _previousContainer != value ) + { + _previousContainer = value; + RaisePropertyChanged( "PreviousContainer" ); + + var paneSerializable = _previousContainer as ILayoutPaneSerializable; + if( paneSerializable != null && + paneSerializable.Id == null ) + paneSerializable.Id = Guid.NewGuid().ToString(); + } + } + } + + protected ILayoutContainer PreviousContainer + { + get + { + return ( ( ILayoutPreviousContainer )this ).PreviousContainer; + } + set + { + ( ( ILayoutPreviousContainer )this ).PreviousContainer = value; + } + } + + [XmlIgnore] + string ILayoutPreviousContainer.PreviousContainerId + { + get; + set; + } + + protected string PreviousContainerId + { + get + { + return ( ( ILayoutPreviousContainer )this ).PreviousContainerId; + } + set + { + ( ( ILayoutPreviousContainer )this ).PreviousContainerId = value; + } + } + + #endregion + + #region PreviousContainerIndex + [field: NonSerialized] + private int _previousContainerIndex = -1; + [XmlIgnore] + public int PreviousContainerIndex + { + get + { + return _previousContainerIndex; + } + set + { + if( _previousContainerIndex != value ) + { + _previousContainerIndex = value; + RaisePropertyChanged( "PreviousContainerIndex" ); + } + } + } + + #endregion + + #region LastActivationTimeStamp + + private DateTime? _lastActivationTimeStamp = null; + public DateTime? LastActivationTimeStamp + { + get + { + return _lastActivationTimeStamp; + } + set + { + if( _lastActivationTimeStamp != value ) + { + _lastActivationTimeStamp = value; + RaisePropertyChanged( "LastActivationTimeStamp" ); + } + } + } + + #endregion + + #region FloatingWidth + + private double _floatingWidth = 0.0; + public double FloatingWidth + { + get + { + return _floatingWidth; + } + set + { + if( _floatingWidth != value ) + { + RaisePropertyChanging( "FloatingWidth" ); + _floatingWidth = value; + RaisePropertyChanged( "FloatingWidth" ); + } + } + } + + #endregion + + #region FloatingHeight + + private double _floatingHeight = 0.0; + public double FloatingHeight + { + get + { + return _floatingHeight; + } + set + { + if( _floatingHeight != value ) + { + RaisePropertyChanging( "FloatingHeight" ); + _floatingHeight = value; + RaisePropertyChanged( "FloatingHeight" ); + } + } + } + + #endregion + + #region FloatingLeft + + private double _floatingLeft = 0.0; + public double FloatingLeft + { + get + { + return _floatingLeft; + } + set + { + if( _floatingLeft != value ) + { + RaisePropertyChanging( "FloatingLeft" ); + _floatingLeft = value; + RaisePropertyChanged( "FloatingLeft" ); + } + } + } + + #endregion + + #region FloatingTop + + private double _floatingTop = 0.0; + public double FloatingTop + { + get + { + return _floatingTop; + } + set + { + if( _floatingTop != value ) + { + RaisePropertyChanging( "FloatingTop" ); + _floatingTop = value; + RaisePropertyChanged( "FloatingTop" ); + } + } + } + + #endregion + + #region IsMaximized + + private bool _isMaximized = false; + public bool IsMaximized + { + get + { + return _isMaximized; + } + set + { + if( _isMaximized != value ) + { + RaisePropertyChanging( "IsMaximized" ); + _isMaximized = value; + RaisePropertyChanged( "IsMaximized" ); + } + } + } + + #endregion + + #region ToolTip + + private object _toolTip = null; + public object ToolTip + { + get + { + return _toolTip; + } + set + { + if( _toolTip != value ) + { + _toolTip = value; + RaisePropertyChanged( "ToolTip" ); + } + } + } + + #endregion + + #region IsFloating + public bool IsFloating + { + get + { + return this.FindParent() != null; + } + } + + #endregion + + #region IconSource + + private ImageSource _iconSource = null; + public ImageSource IconSource + { + get + { + return _iconSource; + } + set + { + if( _iconSource != value ) + { + _iconSource = value; + RaisePropertyChanged( "IconSource" ); + } + } + } + + #endregion + + #region CanClose + + internal bool _canClose = true; + public bool CanClose + { + get + { + return _canClose; + } + set + { + if( _canClose != value ) + { + _canClose = value; + RaisePropertyChanged( "CanClose" ); + } + } + } + + #endregion + + #region CanFloat + + private bool _canFloat = true; + public bool CanFloat + { + get + { + return _canFloat; + } + set + { + if( _canFloat != value ) + { + _canFloat = value; + RaisePropertyChanged( "CanFloat" ); + } + } + } #endregion - #region PreviousContainer - - [field: NonSerialized] - private ILayoutContainer _previousContainer = null; - - [XmlIgnore] - ILayoutContainer ILayoutPreviousContainer.PreviousContainer - { - get { return _previousContainer; } - set - { - if (_previousContainer != value) - { - _previousContainer = value; - RaisePropertyChanged("PreviousContainer"); - - var paneSerializable = _previousContainer as ILayoutPaneSerializable; - if (paneSerializable != null && - paneSerializable.Id == null) - paneSerializable.Id = Guid.NewGuid().ToString(); - } - } - } - - protected ILayoutContainer PreviousContainer - { - get { return ((ILayoutPreviousContainer)this).PreviousContainer; } - set { ((ILayoutPreviousContainer)this).PreviousContainer = value; } - } - - [XmlIgnore] - string ILayoutPreviousContainer.PreviousContainerId - { - get; - set; - } - - protected string PreviousContainerId - { - get { return ((ILayoutPreviousContainer)this).PreviousContainerId; } - set { ((ILayoutPreviousContainer)this).PreviousContainerId = value; } - } - - #endregion - - #region PreviousContainerIndex - [field: NonSerialized] - private int _previousContainerIndex = -1; - [XmlIgnore] - public int PreviousContainerIndex - { - get { return _previousContainerIndex; } - set - { - if (_previousContainerIndex != value) - { - _previousContainerIndex = value; - RaisePropertyChanged("PreviousContainerIndex"); - } - } - } - - #endregion - - #region LastActivationTimeStamp - - private DateTime? _lastActivationTimeStamp = null; - public DateTime? LastActivationTimeStamp - { - get { return _lastActivationTimeStamp; } - set - { - if (_lastActivationTimeStamp != value) - { - _lastActivationTimeStamp = value; - RaisePropertyChanged("LastActivationTimeStamp"); - } - } - } - - #endregion - - protected override void OnParentChanging(ILayoutContainer oldValue, ILayoutContainer newValue) - { - var root = Root; - - if (oldValue != null) - IsSelected = false; - - //if (root != null && _isActive && newValue == null) - // root.ActiveContent = null; - - base.OnParentChanging(oldValue, newValue); - } - - protected override void OnParentChanged(ILayoutContainer oldValue, ILayoutContainer newValue) - { - if (IsSelected && Parent != null && Parent is ILayoutContentSelector) - { - var parentSelector = (Parent as ILayoutContentSelector); - parentSelector.SelectedContentIndex = parentSelector.IndexOf(this); - } - - //var root = Root; - //if (root != null && _isActive) - // root.ActiveContent = this; - - base.OnParentChanged(oldValue, newValue); - } - - /// - /// Test if the content can be closed - /// - /// - internal bool TestCanClose() - { - CancelEventArgs args = new CancelEventArgs(); - - OnClosing(args); - - if (args.Cancel) - return false; - - return true; - } - - /// - /// Close the content - /// - /// Please note that usually the anchorable is only hidden (not closed). By default when user click the X button it only hides the content. - public void Close() - { - var root = Root; - var parentAsContainer = Parent as ILayoutContainer; - parentAsContainer.RemoveChild(this); - - // Dispose if necessary - var content = this.Content as IDisposable; - if (content != null) - { - content.Dispose(); - } - - if (root != null) - root.CollectGarbage(); - - OnClosed(); - } - - /// - /// Event fired when the content is closed (i.e. removed definitely from the layout) - /// - public event EventHandler Closed; - - protected virtual void OnClosed() - { - if (Closed != null) - Closed(this, EventArgs.Empty); - } - - /// - /// Event fired when the content is about to be closed (i.e. removed definitely from the layout) - /// - /// Please note that LayoutAnchorable also can be hidden. Usually user hide anchorables when click the 'X' button. To completely close - /// an anchorable the user should click the 'Close' menu item from the context menu. When an LayoutAnchorable is hidden its visibility changes to false and - /// IsHidden property is set to true. - /// Hanlde the Hiding event for the LayoutAnchorable to cancel the hide operation. - public event EventHandler Closing; - - protected virtual void OnClosing(CancelEventArgs args) - { - if (Closing != null) - Closing(this, args); - } - - public System.Xml.Schema.XmlSchema GetSchema() - { - return null; - } - - public virtual void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("Title")) - Title = reader.Value; - //if (reader.MoveToAttribute("IconSource")) - // IconSource = new Uri(reader.Value, UriKind.RelativeOrAbsolute); - - if (reader.MoveToAttribute("IsSelected")) - IsSelected = bool.Parse(reader.Value); - if (reader.MoveToAttribute("ContentId")) - ContentId = reader.Value; - if (reader.MoveToAttribute("IsLastFocusedDocument")) - IsLastFocusedDocument = bool.Parse(reader.Value); - if (reader.MoveToAttribute("PreviousContainerId")) - PreviousContainerId = reader.Value; - if (reader.MoveToAttribute("PreviousContainerIndex")) - PreviousContainerIndex = int.Parse(reader.Value); - - if (reader.MoveToAttribute("FloatingLeft")) - FloatingLeft = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("FloatingTop")) - FloatingTop = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("FloatingWidth")) - FloatingWidth = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("FloatingHeight")) - FloatingHeight = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("IsMaximized")) - IsMaximized = bool.Parse(reader.Value); - if (reader.MoveToAttribute("CanClose")) - CanClose = bool.Parse(reader.Value); - if (reader.MoveToAttribute("CanFloat")) - CanFloat = bool.Parse(reader.Value); - if (reader.MoveToAttribute("LastActivationTimeStamp")) - LastActivationTimeStamp = DateTime.Parse(reader.Value, CultureInfo.InvariantCulture); - - reader.Read(); - } - - public virtual void WriteXml(System.Xml.XmlWriter writer) - { - if (!string.IsNullOrWhiteSpace(Title)) - writer.WriteAttributeString("Title", Title); - - //if (IconSource != null) - // writer.WriteAttributeString("IconSource", IconSource.ToString()); - - if (IsSelected) - writer.WriteAttributeString("IsSelected", IsSelected.ToString()); - - if (IsLastFocusedDocument) - writer.WriteAttributeString("IsLastFocusedDocument", IsLastFocusedDocument.ToString()); - - if (!string.IsNullOrWhiteSpace(ContentId)) - writer.WriteAttributeString("ContentId", ContentId); - - - if (ToolTip != null && ToolTip is string) - if (!string.IsNullOrWhiteSpace((string)ToolTip)) - writer.WriteAttributeString("ToolTip", (string)ToolTip); - - if (FloatingLeft != 0.0) - writer.WriteAttributeString("FloatingLeft", FloatingLeft.ToString(CultureInfo.InvariantCulture)); - if (FloatingTop != 0.0) - writer.WriteAttributeString("FloatingTop", FloatingTop.ToString(CultureInfo.InvariantCulture)); - if (FloatingWidth != 0.0) - writer.WriteAttributeString("FloatingWidth", FloatingWidth.ToString(CultureInfo.InvariantCulture)); - if (FloatingHeight != 0.0) - writer.WriteAttributeString("FloatingHeight", FloatingHeight.ToString(CultureInfo.InvariantCulture)); - - if (IsMaximized) - writer.WriteAttributeString("IsMaximized", IsMaximized.ToString()); - if (!CanClose) - writer.WriteAttributeString("CanClose", CanClose.ToString()); - if (!CanFloat) - writer.WriteAttributeString("CanFloat", CanFloat.ToString()); - - if (LastActivationTimeStamp != null) - writer.WriteAttributeString("LastActivationTimeStamp", LastActivationTimeStamp.Value.ToString(CultureInfo.InvariantCulture)); - - if (_previousContainer != null) - { - var paneSerializable = _previousContainer as ILayoutPaneSerializable; - if (paneSerializable != null) - { - writer.WriteAttributeString("PreviousContainerId", paneSerializable.Id); - writer.WriteAttributeString("PreviousContainerIndex", _previousContainerIndex.ToString()); - } - } - - } - - #region FloatingWidth + #region CanDock - private double _floatingWidth = 0.0; - public double FloatingWidth + private bool _canDock = true; + public bool CanDock { - get { return _floatingWidth; } + get { return _canDock; } set { - if (_floatingWidth != value) + if (_canDock != value) { - RaisePropertyChanging("FloatingWidth"); - _floatingWidth = value; - RaisePropertyChanged("FloatingWidth"); + _canDock = value; + RaisePropertyChanged("CanDock"); } } } #endregion - #region FloatingHeight - - private double _floatingHeight = 0.0; - public double FloatingHeight - { - get { return _floatingHeight; } - set - { - if (_floatingHeight != value) - { - RaisePropertyChanging("FloatingHeight"); - _floatingHeight = value; - RaisePropertyChanged("FloatingHeight"); - } - } - } + #region IsEnabled + + private bool _isEnabled = true; + public bool IsEnabled + { + get + { + return _isEnabled; + } + set + { + if( _isEnabled != value ) + { + _isEnabled = value; + RaisePropertyChanged( "IsEnabled" ); + } + } + } #endregion - #region FloatingLeft - private double _floatingLeft = 0.0; - public double FloatingLeft - { - get { return _floatingLeft; } - set - { - if (_floatingLeft != value) - { - RaisePropertyChanging("FloatingLeft"); - _floatingLeft = value; - RaisePropertyChanged("FloatingLeft"); - } - } - } - #endregion - #region FloatingTop - private double _floatingTop = 0.0; - public double FloatingTop - { - get { return _floatingTop; } - set - { - if (_floatingTop != value) - { - RaisePropertyChanging("FloatingTop"); - _floatingTop = value; - RaisePropertyChanged("FloatingTop"); - } - } - } - - #endregion - #region IsMaximized - - private bool _isMaximized = false; - public bool IsMaximized - { - get { return _isMaximized; } - set - { - if (_isMaximized != value) - { - RaisePropertyChanging("IsMaximized"); - _isMaximized = value; - RaisePropertyChanged("IsMaximized"); - } - } - } #endregion - #region ToolTip - - private object _toolTip = null; - public object ToolTip - { - get { return _toolTip; } - set - { - if (_toolTip != value) - { - _toolTip = value; - RaisePropertyChanged("ToolTip"); - } - } - } - - #endregion - - public bool IsFloating - { - get { return this.FindParent() != null; } - } - - #region IconSource - - private ImageSource _iconSource = null; - public ImageSource IconSource - { - get { return _iconSource; } - set - { - if (_iconSource != value) - { - _iconSource = value; - RaisePropertyChanged("IconSource"); - } - } - } - - #endregion - - public int CompareTo(LayoutContent other) - { - var contentAsComparable = Content as IComparable; - if (contentAsComparable != null) - { - return contentAsComparable.CompareTo(other.Content); - } - - return string.Compare(Title, other.Title); - } - - /// - /// Float the content in a popup window - /// - public void Float() - { - if (PreviousContainer != null && - PreviousContainer.FindParent() != null) - { - - var currentContainer = Parent as ILayoutPane; - var currentContainerIndex = (currentContainer as ILayoutGroup).IndexOfChild(this); - var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup; - - if (PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount) - previousContainerAsLayoutGroup.InsertChildAt(PreviousContainerIndex, this); - else - previousContainerAsLayoutGroup.InsertChildAt(previousContainerAsLayoutGroup.ChildrenCount, this); - - PreviousContainer = currentContainer; - PreviousContainerIndex = currentContainerIndex; - - IsSelected = true; - IsActive = true; - - Root.CollectGarbage(); - } - else - { - Root.Manager.StartDraggingFloatingWindowForContent(this, false); - - IsSelected = true; - IsActive = true; - } - - } - - /// - /// Dock the content as document - /// - public void DockAsDocument() - { - var root = Root as LayoutRoot; - if (root == null) - throw new InvalidOperationException(); - if (Parent is LayoutDocumentPane) - return; - - if (PreviousContainer is LayoutDocumentPane) - { - Dock(); - return; - } + #region Overrides + + protected override void OnParentChanging( ILayoutContainer oldValue, ILayoutContainer newValue ) + { + var root = Root; + + if( oldValue != null ) + IsSelected = false; + + //if (root != null && _isActive && newValue == null) + // root.ActiveContent = null; + + base.OnParentChanging( oldValue, newValue ); + } + + protected override void OnParentChanged( ILayoutContainer oldValue, ILayoutContainer newValue ) + { + if( IsSelected && Parent != null && Parent is ILayoutContentSelector ) + { + var parentSelector = ( Parent as ILayoutContentSelector ); + parentSelector.SelectedContentIndex = parentSelector.IndexOf( this ); + } + + //var root = Root; + //if (root != null && _isActive) + // root.ActiveContent = this; + + base.OnParentChanged( oldValue, newValue ); + } + + #endregion + + #region Public Methods + + /// + /// Close the content + /// + /// Please note that usually the anchorable is only hidden (not closed). By default when user click the X button it only hides the content. + public abstract void Close(); + + public System.Xml.Schema.XmlSchema GetSchema() + { + return null; + } + + public virtual void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "Title" ) ) + Title = reader.Value; + //if (reader.MoveToAttribute("IconSource")) + // IconSource = new Uri(reader.Value, UriKind.RelativeOrAbsolute); + + if( reader.MoveToAttribute( "IsSelected" ) ) + IsSelected = bool.Parse( reader.Value ); + if( reader.MoveToAttribute( "ContentId" ) ) + ContentId = reader.Value; + if( reader.MoveToAttribute( "IsLastFocusedDocument" ) ) + IsLastFocusedDocument = bool.Parse( reader.Value ); + if( reader.MoveToAttribute( "PreviousContainerId" ) ) + PreviousContainerId = reader.Value; + if( reader.MoveToAttribute( "PreviousContainerIndex" ) ) + PreviousContainerIndex = int.Parse( reader.Value ); + + if( reader.MoveToAttribute( "FloatingLeft" ) ) + FloatingLeft = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "FloatingTop" ) ) + FloatingTop = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "FloatingWidth" ) ) + FloatingWidth = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "FloatingHeight" ) ) + FloatingHeight = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "IsMaximized" ) ) + IsMaximized = bool.Parse( reader.Value ); + if( reader.MoveToAttribute( "CanClose" ) ) + CanClose = bool.Parse( reader.Value ); + if( reader.MoveToAttribute( "CanFloat" ) ) + CanFloat = bool.Parse( reader.Value ); + if( reader.MoveToAttribute( "LastActivationTimeStamp" ) ) + LastActivationTimeStamp = DateTime.Parse( reader.Value, CultureInfo.InvariantCulture ); + + reader.Read(); + } + + public virtual void WriteXml( System.Xml.XmlWriter writer ) + { + if( !string.IsNullOrWhiteSpace( Title ) ) + writer.WriteAttributeString( "Title", Title ); + + //if (IconSource != null) + // writer.WriteAttributeString("IconSource", IconSource.ToString()); + + if( IsSelected ) + writer.WriteAttributeString( "IsSelected", IsSelected.ToString() ); + + if( IsLastFocusedDocument ) + writer.WriteAttributeString( "IsLastFocusedDocument", IsLastFocusedDocument.ToString() ); + + if( !string.IsNullOrWhiteSpace( ContentId ) ) + writer.WriteAttributeString( "ContentId", ContentId ); + + + if( ToolTip != null && ToolTip is string ) + if( !string.IsNullOrWhiteSpace( ( string )ToolTip ) ) + writer.WriteAttributeString( "ToolTip", ( string )ToolTip ); + + if( FloatingLeft != 0.0 ) + writer.WriteAttributeString( "FloatingLeft", FloatingLeft.ToString( CultureInfo.InvariantCulture ) ); + if( FloatingTop != 0.0 ) + writer.WriteAttributeString( "FloatingTop", FloatingTop.ToString( CultureInfo.InvariantCulture ) ); + if( FloatingWidth != 0.0 ) + writer.WriteAttributeString( "FloatingWidth", FloatingWidth.ToString( CultureInfo.InvariantCulture ) ); + if( FloatingHeight != 0.0 ) + writer.WriteAttributeString( "FloatingHeight", FloatingHeight.ToString( CultureInfo.InvariantCulture ) ); + + if( IsMaximized ) + writer.WriteAttributeString( "IsMaximized", IsMaximized.ToString() ); + if( !CanClose ) + writer.WriteAttributeString( "CanClose", CanClose.ToString() ); + if( !CanFloat ) + writer.WriteAttributeString( "CanFloat", CanFloat.ToString() ); + + + if( LastActivationTimeStamp != null ) + writer.WriteAttributeString( "LastActivationTimeStamp", LastActivationTimeStamp.Value.ToString( CultureInfo.InvariantCulture ) ); + + if( _previousContainer != null ) + { + var paneSerializable = _previousContainer as ILayoutPaneSerializable; + if( paneSerializable != null ) + { + writer.WriteAttributeString( "PreviousContainerId", paneSerializable.Id ); + writer.WriteAttributeString( "PreviousContainerIndex", _previousContainerIndex.ToString() ); + } + } + + } + + public int CompareTo( LayoutContent other ) + { + var contentAsComparable = Content as IComparable; + if( contentAsComparable != null ) + { + return contentAsComparable.CompareTo( other.Content ); + } + + return string.Compare( Title, other.Title ); + } + + /// + /// Float the content in a popup window + /// + public void Float() + { + if( PreviousContainer != null && + PreviousContainer.FindParent() != null ) + { + + var currentContainer = Parent as ILayoutPane; + var currentContainerIndex = ( currentContainer as ILayoutGroup ).IndexOfChild( this ); + var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup; + + if( PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount ) + previousContainerAsLayoutGroup.InsertChildAt( PreviousContainerIndex, this ); + else + previousContainerAsLayoutGroup.InsertChildAt( previousContainerAsLayoutGroup.ChildrenCount, this ); + + PreviousContainer = currentContainer; + PreviousContainerIndex = currentContainerIndex; + + IsSelected = true; + IsActive = true; + + Root.CollectGarbage(); + } + else + { + Root.Manager.StartDraggingFloatingWindowForContent( this, false ); + + IsSelected = true; + IsActive = true; + } + + } + + /// + /// Dock the content as document + /// + public void DockAsDocument() + { + var root = Root as LayoutRoot; + if( root == null ) + throw new InvalidOperationException(); + if( Parent is LayoutDocumentPane ) + return; + + if( PreviousContainer is LayoutDocumentPane ) + { + Dock(); + return; + } LayoutDocumentPane newParentPane; if (root.LastFocusedDocument != null) @@ -697,114 +806,129 @@ namespace Xceed.Wpf.AvalonDock.Layout newParentPane = root.Descendents().OfType().FirstOrDefault(); } - if (newParentPane != null) - { - newParentPane.Children.Add(this); - root.CollectGarbage(); - } + if( newParentPane != null ) + { + newParentPane.Children.Add( this ); + root.CollectGarbage(); + } - IsSelected = true; - IsActive = true; - } + IsSelected = true; + IsActive = true; + } - /// - /// Re-dock the content to its previous container - /// - public void Dock() - { - if (PreviousContainer != null) - { - var currentContainer = Parent as ILayoutContainer; - var currentContainerIndex = (currentContainer is ILayoutGroup) ? (currentContainer as ILayoutGroup).IndexOfChild(this) : -1; - var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup; + /// + /// Re-dock the content to its previous container + /// + public void Dock() + { + if( PreviousContainer != null ) + { + var currentContainer = Parent as ILayoutContainer; + var currentContainerIndex = ( currentContainer is ILayoutGroup ) ? ( currentContainer as ILayoutGroup ).IndexOfChild( this ) : -1; + var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup; - if (PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount) - previousContainerAsLayoutGroup.InsertChildAt(PreviousContainerIndex, this); - else - previousContainerAsLayoutGroup.InsertChildAt(previousContainerAsLayoutGroup.ChildrenCount, this); + if( PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount ) + previousContainerAsLayoutGroup.InsertChildAt( PreviousContainerIndex, this ); + else + previousContainerAsLayoutGroup.InsertChildAt( previousContainerAsLayoutGroup.ChildrenCount, this ); - if (currentContainerIndex > -1) - { - PreviousContainer = currentContainer; - PreviousContainerIndex = currentContainerIndex; - } - else - { - PreviousContainer = null; - PreviousContainerIndex = 0; - } + if( currentContainerIndex > -1 ) + { + PreviousContainer = currentContainer; + PreviousContainerIndex = currentContainerIndex; + } + else + { + PreviousContainer = null; + PreviousContainerIndex = 0; + } - IsSelected = true; - IsActive = true; - } - else - { - InternalDock(); - } + IsSelected = true; + IsActive = true; + } + else + { + InternalDock(); + } - Root.CollectGarbage(); + Root.CollectGarbage(); - } + } - protected virtual void InternalDock() - { - } - #region CanClose - private bool _canClose = true; - public bool CanClose - { - get { return _canClose; } - set - { - if (_canClose != value) - { - _canClose = value; - RaisePropertyChanged("CanClose"); - } - } - } + #endregion - #endregion + #region Internal Methods - #region CanFloat + /// + /// Test if the content can be closed + /// + /// + internal bool TestCanClose() + { + CancelEventArgs args = new CancelEventArgs(); - private bool _canFloat = true; - public bool CanFloat - { - get { return _canFloat; } - set - { - if (_canFloat != value) - { - _canFloat = value; - RaisePropertyChanged("CanFloat"); - } - } - } + OnClosing( args ); - #endregion + if( args.Cancel ) + return false; - #region CanDock + return true; + } - private bool _canDock = true; - public bool CanDock - { - get { return _canDock; } - set - { - if (_canDock != value) - { - _canDock = value; - RaisePropertyChanged("CanDock"); - } - } - } + internal void CloseInternal() + { + var root = Root; + var parentAsContainer = Parent as ILayoutContainer; + parentAsContainer.RemoveChild( this ); - #endregion - } + if (Content is IDisposable contentAsDisposable) + contentAsDisposable.Dispose(); + + if ( root != null ) + root.CollectGarbage(); + + OnClosed(); + } + + protected virtual void OnClosed() + { + if( Closed != null ) + Closed( this, EventArgs.Empty ); + } + + protected virtual void OnClosing( CancelEventArgs args ) + { + if( Closing != null ) + Closing( this, args ); + } + + protected virtual void InternalDock() + { + } + + #endregion + + #region Events + + /// + /// Event fired when the content is closed (i.e. removed definitely from the layout) + /// + public event EventHandler Closed; + + /// + /// Event fired when the content is about to be closed (i.e. removed definitely from the layout) + /// + /// Please note that LayoutAnchorable also can be hidden. Usually user hide anchorables when click the 'X' button. To completely close + /// an anchorable the user should click the 'Close' menu item from the context menu. When an LayoutAnchorable is hidden its visibility changes to false and + /// IsHidden property is set to true. + /// Hanlde the Hiding event for the LayoutAnchorable to cancel the hide operation. + public event EventHandler Closing; + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocument.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocument.cs index b47c8386..07d4b075 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocument.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocument.cs @@ -15,56 +15,87 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Globalization; +using System.Linq; namespace Xceed.Wpf.AvalonDock.Layout { - [Serializable] - public class LayoutDocument : LayoutContent + [Serializable] + public class LayoutDocument : LayoutContent + { + #region Properties + + #region IsVisible + + public bool IsVisible { - public bool IsVisible - { - get { return true; } - } + get + { + return _isVisible; + } + internal set + { + _isVisible = value; + } + } + + private bool _isVisible = true; - #region Description + #endregion - private string _description = null; - public string Description + #region Description + + private string _description = null; + public string Description + { + get + { + return _description; + } + set + { + if( _description != value ) { - get { return _description; } - set - { - if (_description != value) - { - _description = value; - RaisePropertyChanged("Description"); - } - } + _description = value; + RaisePropertyChanged( "Description" ); } + } + } - #endregion + #endregion - public override void WriteXml(System.Xml.XmlWriter writer) - { - base.WriteXml(writer); + #endregion - if (!string.IsNullOrWhiteSpace(Description)) - writer.WriteAttributeString("Description", Description); + #region Overrides - } + public override void WriteXml( System.Xml.XmlWriter writer ) + { + base.WriteXml( writer ); - public override void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("Description")) - Description = reader.Value; + if( !string.IsNullOrWhiteSpace( this.Description ) ) + writer.WriteAttributeString( "Description", this.Description ); + } - base.ReadXml(reader); - } + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "Description" ) ) + this.Description = reader.Value; + + base.ReadXml( reader ); + } + public override void Close() + { + if( ( this.Root != null ) && ( this.Root.Manager != null ) ) + { + var dockingManager = this.Root.Manager; + dockingManager._ExecuteCloseCommand( this ); + } + else + { + this.CloseDocument(); + } + } #if TRACE public override void ConsoleDump(int tab) @@ -74,45 +105,61 @@ namespace Xceed.Wpf.AvalonDock.Layout } #endif + protected override void InternalDock() + { + var root = Root as LayoutRoot; + LayoutDocumentPane documentPane = null; + if( root.LastFocusedDocument != null && + root.LastFocusedDocument != this ) + { + documentPane = root.LastFocusedDocument.Parent as LayoutDocumentPane; + } + + if( documentPane == null ) + { + documentPane = root.Descendents().OfType().FirstOrDefault(); + } + + + bool added = false; + if( root.Manager.LayoutUpdateStrategy != null ) + { + added = root.Manager.LayoutUpdateStrategy.BeforeInsertDocument( root, this, documentPane ); + } + + if( !added ) + { + if( documentPane == null ) + throw new InvalidOperationException( "Layout must contains at least one LayoutDocumentPane in order to host documents" ); + + documentPane.Children.Add( this ); + added = true; + } + + if( root.Manager.LayoutUpdateStrategy != null ) + { + root.Manager.LayoutUpdateStrategy.AfterInsertDocument( root, this ); + } + + + base.InternalDock(); + } - protected override void InternalDock() - { - var root = Root as LayoutRoot; - LayoutDocumentPane documentPane = null; - if (root.LastFocusedDocument != null && - root.LastFocusedDocument != this) - { - documentPane = root.LastFocusedDocument.Parent as LayoutDocumentPane; - } - - if (documentPane == null) - { - documentPane = root.Descendents().OfType().FirstOrDefault(); - } - - - bool added = false; - if (root.Manager.LayoutUpdateStrategy != null) - { - added = root.Manager.LayoutUpdateStrategy.BeforeInsertDocument(root, this, documentPane); - } - - if (!added) - { - if (documentPane == null) - throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); - - documentPane.Children.Add(this); - added = true; - } - - if (root.Manager.LayoutUpdateStrategy != null) - { - root.Manager.LayoutUpdateStrategy.AfterInsertDocument(root, this); - } - - - base.InternalDock(); - } + #endregion + + #region Internal Methods + + internal bool CloseDocument() + { + if( this.TestCanClose() ) + { + this.CloseInternal(); + return true; + } + + return false; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentFloatingWindow.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentFloatingWindow.cs index db08fadd..aa71ef3a 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentFloatingWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentFloatingWindow.cs @@ -16,82 +16,142 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Markup; using System.Diagnostics; +using System.Xml.Serialization; +using System.Xml; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("RootDocument")] - [Serializable] - public class LayoutDocumentFloatingWindow : LayoutFloatingWindow + [ContentProperty( "RootDocument" )] + [Serializable] + public class LayoutDocumentFloatingWindow : LayoutFloatingWindow + { + #region Constructors + + public LayoutDocumentFloatingWindow() { - public LayoutDocumentFloatingWindow() - { + } - } + #endregion - #region RootDocument + #region Properties - private LayoutDocument _rootDocument = null; - public LayoutDocument RootDocument + #region RootDocument + + private LayoutDocument _rootDocument = null; + public LayoutDocument RootDocument + { + get + { + return _rootDocument; + } + set + { + if( _rootDocument != value ) { - get { return _rootDocument; } - set - { - if (_rootDocument != value) - { - RaisePropertyChanging("RootDocument"); - _rootDocument = value; - if (_rootDocument != null) - _rootDocument.Parent = this; - RaisePropertyChanged("RootDocument"); - - if (RootDocumentChanged != null) - RootDocumentChanged(this, EventArgs.Empty); - } - } + RaisePropertyChanging( "RootDocument" ); + _rootDocument = value; + if( _rootDocument != null ) + _rootDocument.Parent = this; + RaisePropertyChanged( "RootDocument" ); + + if( RootDocumentChanged != null ) + RootDocumentChanged( this, EventArgs.Empty ); } + } + } + #endregion - public event EventHandler RootDocumentChanged; + #endregion - #endregion + #region Overrides - public override IEnumerable Children - { - get - { - if (RootDocument == null) - yield break; + public override IEnumerable Children + { + get + { + if( RootDocument == null ) + yield break; - yield return RootDocument; - } - } + yield return RootDocument; + } + } + + public override void RemoveChild( ILayoutElement element ) + { + Debug.Assert( element == RootDocument && element != null ); + RootDocument = null; + } - public override void RemoveChild(ILayoutElement element) + public override void ReplaceChild( ILayoutElement oldElement, ILayoutElement newElement ) + { + Debug.Assert( oldElement == RootDocument && oldElement != null ); + RootDocument = newElement as LayoutDocument; + } + + public override int ChildrenCount + { + get + { + return RootDocument != null ? 1 : 0; + } + } + + public override bool IsValid + { + get + { + return RootDocument != null; + } + } + + public override void ReadXml( XmlReader reader ) + { + reader.MoveToContent(); + if( reader.IsEmptyElement ) + { + reader.Read(); + return; + } + + var localName = reader.LocalName; + reader.Read(); + + while( true ) + { + if( reader.LocalName.Equals( localName ) && ( reader.NodeType == XmlNodeType.EndElement ) ) { - Debug.Assert(element == RootDocument && element != null); - RootDocument = null; + break; } - public override void ReplaceChild(ILayoutElement oldElement, ILayoutElement newElement) + if( reader.NodeType == XmlNodeType.Whitespace ) { - Debug.Assert(oldElement == RootDocument && oldElement != null); - RootDocument = newElement as LayoutDocument; + reader.Read(); + continue; } - public override int ChildrenCount + XmlSerializer serializer; + if( reader.LocalName.Equals( "LayoutDocument" ) ) { - get { return RootDocument != null ? 1 : 0; } + serializer = new XmlSerializer( typeof( LayoutDocument ) ); } - - public override bool IsValid + else { - get { return RootDocument != null; } + var type = LayoutRoot.FindType( reader.LocalName ); + if( type == null ) + { + throw new ArgumentException( "AvalonDock.LayoutDocumentFloatingWindow doesn't know how to deserialize " + reader.LocalName ); + } + serializer = new XmlSerializer( type ); } + RootDocument = ( LayoutDocument )serializer.Deserialize( reader ); + } + + reader.ReadEndElement(); + } #if TRACE public override void ConsoleDump(int tab) @@ -102,6 +162,13 @@ namespace Xceed.Wpf.AvalonDock.Layout RootDocument.ConsoleDump(tab + 1); } #endif - } + #endregion + + #region Events + + public event EventHandler RootDocumentChanged; + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentPane.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentPane.cs index 3f4fa330..35589ba8 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentPane.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentPane.cs @@ -17,161 +17,186 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Collections.ObjectModel; using System.Windows.Markup; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("Children")] - [Serializable] - public class LayoutDocumentPane : LayoutPositionableGroup, ILayoutDocumentPane, ILayoutPositionableElement, ILayoutContentSelector, ILayoutPaneSerializable + [ContentProperty( "Children" )] + [Serializable] + public class LayoutDocumentPane : LayoutPositionableGroup, ILayoutDocumentPane, ILayoutPositionableElement, ILayoutContentSelector, ILayoutPaneSerializable + { + #region Constructors + + public LayoutDocumentPane() { - public LayoutDocumentPane() - { - } - public LayoutDocumentPane(LayoutContent firstChild) - { - Children.Add(firstChild); - } + } + public LayoutDocumentPane( LayoutContent firstChild ) + { + this.Children.Add( firstChild ); + } - protected override bool GetVisibility() - { - if (Parent is LayoutDocumentPaneGroup) - return ChildrenCount > 0; + #endregion - return true; - } + #region Properties - #region SelectedContentIndex + #region ShowHeader - private int _selectedIndex = -1; - public int SelectedContentIndex + private bool _showHeader = true; + public bool ShowHeader + { + get + { + return _showHeader; + } + set + { + if( value != _showHeader ) { - get { return _selectedIndex; } - set - { - if (value < 0 || - value >= Children.Count) - value = -1; - - if (_selectedIndex != value) - { - RaisePropertyChanging("SelectedContentIndex"); - RaisePropertyChanging("SelectedContent"); - if (_selectedIndex >= 0 && - _selectedIndex < Children.Count) - Children[_selectedIndex].IsSelected = false; - - _selectedIndex = value; - - if (_selectedIndex >= 0 && - _selectedIndex < Children.Count) - Children[_selectedIndex].IsSelected = true; - - RaisePropertyChanged("SelectedContentIndex"); - RaisePropertyChanged("SelectedContent"); - } - } + _showHeader = value; + RaisePropertyChanged( "ShowHeader" ); } + } + } + + #endregion + + #region SelectedContentIndex - protected override void ChildMoved(int oldIndex, int newIndex) + private int _selectedIndex = -1; + public int SelectedContentIndex + { + get + { + return _selectedIndex; + } + set + { + if( value < 0 || + value >= Children.Count ) + value = -1; + + if( _selectedIndex != value ) { - if (_selectedIndex == oldIndex) - { - RaisePropertyChanging("SelectedContentIndex"); - _selectedIndex = newIndex; - RaisePropertyChanged("SelectedContentIndex"); - } + RaisePropertyChanging( "SelectedContentIndex" ); + RaisePropertyChanging( "SelectedContent" ); + if( _selectedIndex >= 0 && + _selectedIndex < Children.Count ) + Children[ _selectedIndex ].IsSelected = false; + _selectedIndex = value; - base.ChildMoved(oldIndex, newIndex); - } + if( _selectedIndex >= 0 && + _selectedIndex < Children.Count ) + Children[ _selectedIndex ].IsSelected = true; - public LayoutContent SelectedContent - { - get { return _selectedIndex == -1 ? null : Children[_selectedIndex]; } + RaisePropertyChanged( "SelectedContentIndex" ); + RaisePropertyChanged( "SelectedContent" ); } - #endregion + } + } - protected override void OnChildrenCollectionChanged() - { - if (SelectedContentIndex >= ChildrenCount) - SelectedContentIndex = Children.Count - 1; - if (SelectedContentIndex == -1 && ChildrenCount > 0) - { - if (Root == null)//if I'm not yet connected just switch to first document - SelectedContentIndex = 0; - else - { - var childrenToSelect = Children.OrderByDescending(c => c.LastActivationTimeStamp.GetValueOrDefault()).First(); - SelectedContentIndex = Children.IndexOf(childrenToSelect); - childrenToSelect.IsActive = true; - } - } - - base.OnChildrenCollectionChanged(); - - RaisePropertyChanged("ChildrenSorted"); - } + #endregion - public int IndexOf(LayoutContent content) - { - return Children.IndexOf(content); - } + #region SelectedContent - protected override void OnIsVisibleChanged() - { - UpdateParentVisibility(); - base.OnIsVisibleChanged(); - } + public LayoutContent SelectedContent + { + get + { + return _selectedIndex == -1 ? null : Children[ _selectedIndex ]; + } + } - void UpdateParentVisibility() - { - var parentPane = Parent as ILayoutElementWithVisibility; - if (parentPane != null) - parentPane.ComputeVisibility(); - } + #endregion + + #region ChildrenSorted + + public IEnumerable ChildrenSorted + { + get + { + var listSorted = this.Children.ToList(); + listSorted.Sort(); + return listSorted; + } + } + + #endregion + + #endregion + + #region Overrides + + protected override bool GetVisibility() + { + if( this.Parent is LayoutDocumentPaneGroup ) + return ( this.ChildrenCount > 0 ) && this.Children.Any( c => ( c is LayoutDocument && ( ( LayoutDocument )c ).IsVisible ) || ( c is LayoutAnchorable ) ); + + return true; + } + + protected override void ChildMoved( int oldIndex, int newIndex ) + { + if( _selectedIndex == oldIndex ) + { + RaisePropertyChanging( "SelectedContentIndex" ); + _selectedIndex = newIndex; + RaisePropertyChanged( "SelectedContentIndex" ); + } - public IEnumerable ChildrenSorted + + base.ChildMoved( oldIndex, newIndex ); + } + + protected override void OnChildrenCollectionChanged() + { + if( this.SelectedContentIndex >= this.ChildrenCount ) + this.SelectedContentIndex = this.Children.Count - 1; + if( this.SelectedContentIndex == -1 && this.ChildrenCount > 0 ) + { + if( this.Root == null ) { - get - { - var listSorted = Children.ToList(); - listSorted.Sort(); - return listSorted; - } + this.SetNextSelectedIndex(); } - - string _id; - string ILayoutPaneSerializable.Id + else { - get - { - return _id; - } - set - { - _id = value; - } + var childrenToSelect = this.Children.OrderByDescending( c => c.LastActivationTimeStamp.GetValueOrDefault() ).First(); + this.SelectedContentIndex = this.Children.IndexOf( childrenToSelect ); + childrenToSelect.IsActive = true; } + } - public override void WriteXml(System.Xml.XmlWriter writer) - { - if (_id != null) - writer.WriteAttributeString("Id", _id); + base.OnChildrenCollectionChanged(); - base.WriteXml(writer); - } + RaisePropertyChanged( "ChildrenSorted" ); + } - public override void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("Id")) - _id = reader.Value; + protected override void OnIsVisibleChanged() + { + this.UpdateParentVisibility(); + base.OnIsVisibleChanged(); + } + public override void WriteXml( System.Xml.XmlWriter writer ) + { + if( _id != null ) + writer.WriteAttributeString( "Id", _id ); + if( !_showHeader ) + writer.WriteAttributeString( "ShowHeader", _showHeader.ToString() ); + + base.WriteXml( writer ); + } + + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "Id" ) ) + _id = reader.Value; + if( reader.MoveToAttribute( "ShowHeader" ) ) + _showHeader = bool.Parse( reader.Value ); - base.ReadXml(reader); - } + + base.ReadXml( reader ); + } #if TRACE @@ -185,5 +210,60 @@ namespace Xceed.Wpf.AvalonDock.Layout } #endif + #endregion + + #region Public Methods + + public int IndexOf( LayoutContent content ) + { + return Children.IndexOf( content ); + } + + #endregion + + #region Internal Methods + + internal void SetNextSelectedIndex() + { + this.SelectedContentIndex = -1; + for( int i = 0; i < this.Children.Count; ++i ) + { + if( this.Children[ i ].IsEnabled ) + { + this.SelectedContentIndex = i; + return; + } + } + } + + #endregion + + #region Private Methods + + private void UpdateParentVisibility() + { + var parentPane = this.Parent as ILayoutElementWithVisibility; + if( parentPane != null ) + parentPane.ComputeVisibility(); + } + + #endregion + + #region ILayoutPaneSerializable Interface + + string _id; + string ILayoutPaneSerializable.Id + { + get + { + return _id; + } + set + { + _id = value; + } } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentPaneGroup.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentPaneGroup.cs index c751e2d1..495c7a96 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentPaneGroup.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutDocumentPaneGroup.cs @@ -15,65 +15,73 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections.ObjectModel; -using System.Windows; using System.Windows.Controls; using System.Windows.Markup; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("Children")] - [Serializable] - public class LayoutDocumentPaneGroup : LayoutPositionableGroup, ILayoutDocumentPane, ILayoutOrientableGroup + [ContentProperty( "Children" )] + [Serializable] + public class LayoutDocumentPaneGroup : LayoutPositionableGroup, ILayoutDocumentPane, ILayoutOrientableGroup + { + #region Constructors + + public LayoutDocumentPaneGroup() { - public LayoutDocumentPaneGroup() - { - } + } - public LayoutDocumentPaneGroup(LayoutDocumentPane documentPane) - { - Children.Add(documentPane); - } + public LayoutDocumentPaneGroup( LayoutDocumentPane documentPane ) + { + Children.Add( documentPane ); + } - #region Orientation + #endregion - private Orientation _orientation; - public Orientation Orientation - { - get { return _orientation; } - set - { - if (_orientation != value) - { - RaisePropertyChanging("Orientation"); - _orientation = value; - RaisePropertyChanged("Orientation"); - } - } - } + #region Properties - #endregion + #region Orientation - protected override bool GetVisibility() + private Orientation _orientation; + public Orientation Orientation + { + get + { + return _orientation; + } + set + { + if( _orientation != value ) { - return true; + RaisePropertyChanging( "Orientation" ); + _orientation = value; + RaisePropertyChanged( "Orientation" ); } + } + } - public override void WriteXml(System.Xml.XmlWriter writer) - { - writer.WriteAttributeString("Orientation", Orientation.ToString()); - base.WriteXml(writer); - } + #endregion - public override void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("Orientation")) - Orientation = (Orientation)Enum.Parse(typeof(Orientation), reader.Value, true); - base.ReadXml(reader); - } + #endregion + + #region Overrides + + protected override bool GetVisibility() + { + return true; + } + + public override void WriteXml( System.Xml.XmlWriter writer ) + { + writer.WriteAttributeString( "Orientation", Orientation.ToString() ); + base.WriteXml( writer ); + } + + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "Orientation" ) ) + Orientation = ( Orientation )Enum.Parse( typeof( Orientation ), reader.Value, true ); + base.ReadXml( reader ); + } #if TRACE public override void ConsoleDump(int tab) @@ -85,5 +93,7 @@ namespace Xceed.Wpf.AvalonDock.Layout child.ConsoleDump(tab + 1); } #endif - } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutElement.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutElement.cs index 8cda2f83..e3965f1b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutElement.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutElement.cs @@ -15,117 +15,91 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; using System.ComponentModel; using System.Xml.Serialization; namespace Xceed.Wpf.AvalonDock.Layout { - [Serializable] - public abstract class LayoutElement : DependencyObject, ILayoutElement - { - internal LayoutElement() - { } + [Serializable] + public abstract class LayoutElement : DependencyObject, ILayoutElement + { + #region Members - #region Parent + [NonSerialized] + private ILayoutContainer _parent = null; + [NonSerialized] + private ILayoutRoot _root = null; - [NonSerialized] - private ILayoutContainer _parent = null; - [NonSerialized] - private ILayoutRoot _root = null; - [XmlIgnore] - public ILayoutContainer Parent - { - get { return _parent; } - set - { - if (_parent != value) - { - ILayoutContainer oldValue = _parent; - ILayoutRoot oldRoot = _root; - RaisePropertyChanging("Parent"); - OnParentChanging(oldValue, value); - _parent = value; - OnParentChanged(oldValue, value); - - _root = Root; - if (oldRoot != _root) - OnRootChanged(oldRoot, _root); - - RaisePropertyChanged("Parent"); - - var root = Root as LayoutRoot; - if (root != null) - root.FireLayoutUpdated(); - } - } - } + #endregion - /// - /// Provides derived classes an opportunity to handle execute code before to the Parent property changes. - /// - protected virtual void OnParentChanging(ILayoutContainer oldValue, ILayoutContainer newValue) - { - } + #region Constructors - /// - /// Provides derived classes an opportunity to handle changes to the Parent property. - /// - protected virtual void OnParentChanged(ILayoutContainer oldValue, ILayoutContainer newValue) - { + internal LayoutElement() + { + } - } + #endregion + #region Properties - protected virtual void OnRootChanged(ILayoutRoot oldRoot, ILayoutRoot newRoot) + #region Parent + + [XmlIgnore] + public ILayoutContainer Parent + { + get + { + return _parent; + } + set + { + if( _parent != value ) { - if (oldRoot != null) - ((LayoutRoot)oldRoot).OnLayoutElementRemoved(this); - if (newRoot != null) - ((LayoutRoot)newRoot).OnLayoutElementAdded(this); + ILayoutContainer oldValue = _parent; + ILayoutRoot oldRoot = _root; + RaisePropertyChanging( "Parent" ); + OnParentChanging( oldValue, value ); + _parent = value; + OnParentChanged( oldValue, value ); + + _root = Root; + if( oldRoot != _root ) + OnRootChanged( oldRoot, _root ); + + RaisePropertyChanged( "Parent" ); + + var root = Root as LayoutRoot; + if( root != null ) + root.FireLayoutUpdated(); } + } + } + #endregion - #endregion - - [field: NonSerialized] - [field: XmlIgnore] - public event PropertyChangedEventHandler PropertyChanged; - - protected virtual void RaisePropertyChanged(string propertyName) - { - if (PropertyChanged != null) - PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } + #region Root - [field: NonSerialized] - [field: XmlIgnore] - public event PropertyChangingEventHandler PropertyChanging; + public ILayoutRoot Root + { + get + { + var parent = Parent; - protected virtual void RaisePropertyChanging(string propertyName) + while( parent != null && ( !( parent is ILayoutRoot ) ) ) { - if (PropertyChanging != null) - PropertyChanging(this, new System.ComponentModel.PropertyChangingEventArgs(propertyName)); + parent = parent.Parent; } - public ILayoutRoot Root - { - get - { - var parent = Parent; + return parent as ILayoutRoot; + } + } - while (parent != null && (!(parent is ILayoutRoot))) - { - parent = parent.Parent; - } + #endregion - return parent as ILayoutRoot; - } - } + #endregion + #region Public Methods #if TRACE public virtual void ConsoleDump(int tab) @@ -134,5 +108,58 @@ namespace Xceed.Wpf.AvalonDock.Layout System.Diagnostics.Trace.WriteLine( this.ToString() ); } #endif + + #endregion + + #region Internal Methods + + /// + /// Provides derived classes an opportunity to handle execute code before to the Parent property changes. + /// + protected virtual void OnParentChanging( ILayoutContainer oldValue, ILayoutContainer newValue ) + { + } + + /// + /// Provides derived classes an opportunity to handle changes to the Parent property. + /// + protected virtual void OnParentChanged( ILayoutContainer oldValue, ILayoutContainer newValue ) + { } + + + protected virtual void OnRootChanged( ILayoutRoot oldRoot, ILayoutRoot newRoot ) + { + if( oldRoot != null ) + ( ( LayoutRoot )oldRoot ).OnLayoutElementRemoved( this ); + if( newRoot != null ) + ( ( LayoutRoot )newRoot ).OnLayoutElementAdded( this ); + } + + protected virtual void RaisePropertyChanged( string propertyName ) + { + if( PropertyChanged != null ) + PropertyChanged( this, new System.ComponentModel.PropertyChangedEventArgs( propertyName ) ); + } + + protected virtual void RaisePropertyChanging( string propertyName ) + { + if( PropertyChanging != null ) + PropertyChanging( this, new System.ComponentModel.PropertyChangingEventArgs( propertyName ) ); + } + + #endregion + + #region Events + + [field: NonSerialized] + [field: XmlIgnore] + public event PropertyChangedEventHandler PropertyChanged; + + [field: NonSerialized] + [field: XmlIgnore] + public event PropertyChangingEventHandler PropertyChanging; + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutElementEventArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutElementEventArgs.cs index 44c336d8..d5189321 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutElementEventArgs.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutElementEventArgs.cs @@ -15,24 +15,28 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Layout { - public class LayoutElementEventArgs : EventArgs + public class LayoutElementEventArgs : EventArgs + { + #region Constructors + + public LayoutElementEventArgs( LayoutElement element ) { - public LayoutElementEventArgs(LayoutElement element) - { - Element = element; - } + Element = element; + } + + #endregion + #region Properties - public LayoutElement Element - { - get; - private set; - } + public LayoutElement Element + { + get; + private set; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutFloatingWindow.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutFloatingWindow.cs index 6f174897..f41e479d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutFloatingWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutFloatingWindow.cs @@ -16,37 +16,77 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Markup; -using System.Windows; using System.Xml.Serialization; +using System.Xml.Schema; +using System.Xml; namespace Xceed.Wpf.AvalonDock.Layout { - [Serializable] - [XmlInclude(typeof(LayoutAnchorableFloatingWindow))] - [XmlInclude(typeof(LayoutDocumentFloatingWindow))] - public abstract class LayoutFloatingWindow : LayoutElement, ILayoutContainer + [Serializable] + public abstract class LayoutFloatingWindow : LayoutElement, ILayoutContainer, IXmlSerializable + { + #region Constructors + + public LayoutFloatingWindow() { - public LayoutFloatingWindow() - { + } + + #endregion - } + #region Properties + #region Children + + public abstract IEnumerable Children + { + get; + } - public abstract IEnumerable Children { get; } + #endregion - public abstract void RemoveChild(ILayoutElement element); + #region ChildrenCount - public abstract void ReplaceChild(ILayoutElement oldElement, ILayoutElement newElement); + public abstract int ChildrenCount + { + get; + } - public abstract int ChildrenCount { get; } + #endregion - public abstract bool IsValid { get; } + #region IsValid + public abstract bool IsValid + { + get; + } + #endregion + #endregion + #region Public Methods + + public abstract void RemoveChild( ILayoutElement element ); + + public abstract void ReplaceChild( ILayoutElement oldElement, ILayoutElement newElement ); + + public XmlSchema GetSchema() + { + return null; } + + public abstract void ReadXml( XmlReader reader ); + + public virtual void WriteXml( XmlWriter writer ) + { + foreach( var child in Children ) + { + var type = child.GetType(); + var serializer = new XmlSerializer( type ); + serializer.Serialize( writer, child ); + } + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutGroup.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutGroup.cs index 1ff57128..179a373f 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutGroup.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutGroup.cs @@ -17,228 +17,301 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Collections.ObjectModel; using System.Xml.Serialization; namespace Xceed.Wpf.AvalonDock.Layout { - [Serializable] - public abstract class LayoutGroup : LayoutGroupBase, ILayoutContainer, ILayoutGroup, IXmlSerializable where T : class, ILayoutElement + [Serializable] + public abstract class LayoutGroup : LayoutGroupBase, ILayoutContainer, ILayoutGroup, IXmlSerializable where T : class, ILayoutElement + { + #region Members + + ObservableCollection _children = new ObservableCollection(); + + #endregion + + #region Constructors + + internal LayoutGroup() { - internal LayoutGroup() - { - _children.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_children_CollectionChanged); - } + _children.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( _children_CollectionChanged ); + } - void _children_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) - { - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) - { - if (e.OldItems != null) - { - foreach (LayoutElement element in e.OldItems) - { - if (element.Parent == this) - element.Parent = null; - } - } - } + #endregion - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) - { - if (e.NewItems != null) - { - foreach (LayoutElement element in e.NewItems) - { - if (element.Parent != this) - { - if (element.Parent != null) - element.Parent.RemoveChild(element); - element.Parent = this; - } - - } - } - } + #region Properties - ComputeVisibility(); - OnChildrenCollectionChanged(); - NotifyChildrenTreeChanged(ChildrenTreeChange.DirectChildrenChanged); - RaisePropertyChanged("ChildrenCount"); - } + #region Children - ObservableCollection _children = new ObservableCollection(); + public ObservableCollection Children + { + get + { + return _children; + } + } - public ObservableCollection Children - { - get { return _children; } - } + #endregion - IEnumerable ILayoutContainer.Children + #region IsVisible + + private bool _isVisible = true; + public bool IsVisible + { + get + { + return _isVisible; + } + protected set + { + if( _isVisible != value ) { - get { return _children.Cast(); } + RaisePropertyChanging( "IsVisible" ); + _isVisible = value; + OnIsVisibleChanged(); + RaisePropertyChanged( "IsVisible" ); } + } + } + #endregion - #region IsVisible + #region ChildrenCount - private bool _isVisible = true; - public bool IsVisible - { - get { return _isVisible; } - protected set - { - if (_isVisible != value) - { - RaisePropertyChanging("IsVisible"); - _isVisible = value; - OnIsVisibleChanged(); - RaisePropertyChanged("IsVisible"); - } - } - } + public int ChildrenCount + { + get + { + return _children.Count; + } + } - protected virtual void OnIsVisibleChanged() - { - UpdateParentVisibility(); - } + #endregion - void UpdateParentVisibility() - { - var parentPane = Parent as ILayoutElementWithVisibility; - if (parentPane != null) - parentPane.ComputeVisibility(); - } + #endregion + #region Overrides - public void ComputeVisibility() - { - IsVisible = GetVisibility(); - } + protected override void OnParentChanged( ILayoutContainer oldValue, ILayoutContainer newValue ) + { + base.OnParentChanged( oldValue, newValue ); - protected abstract bool GetVisibility(); + ComputeVisibility(); + } - protected override void OnParentChanged(ILayoutContainer oldValue, ILayoutContainer newValue) - { - base.OnParentChanged(oldValue, newValue); + #endregion - ComputeVisibility(); - } + #region Public Methods - #endregion + public void ComputeVisibility() + { + IsVisible = GetVisibility(); + } + public void MoveChild( int oldIndex, int newIndex ) + { + if( oldIndex == newIndex ) + return; + _children.Move( oldIndex, newIndex ); + ChildMoved( oldIndex, newIndex ); + } - public void MoveChild(int oldIndex, int newIndex) - { - if (oldIndex == newIndex) - return; - _children.Move(oldIndex, newIndex); - ChildMoved(oldIndex, newIndex); - } + public void RemoveChildAt( int childIndex ) + { + _children.RemoveAt( childIndex ); + } - protected virtual void ChildMoved(int oldIndex, int newIndex) - { + public int IndexOfChild( ILayoutElement element ) + { + return _children.Cast().ToList().IndexOf( element ); + } - } + public void InsertChildAt( int index, ILayoutElement element ) + { + _children.Insert( index, ( T )element ); + } - public void RemoveChildAt(int childIndex) - { - _children.RemoveAt(childIndex); - } + public void RemoveChild( ILayoutElement element ) + { + _children.Remove( ( T )element ); + } - public int IndexOfChild(ILayoutElement element) - { - return _children.Cast().ToList().IndexOf(element); - } + public void ReplaceChild( ILayoutElement oldElement, ILayoutElement newElement ) + { + int index = _children.IndexOf( ( T )oldElement ); + _children.Insert( index, ( T )newElement ); + _children.RemoveAt( index + 1 ); + } - public void InsertChildAt(int index, ILayoutElement element) - { - _children.Insert(index, (T)element); - } + public void ReplaceChildAt( int index, ILayoutElement element ) + { + _children[ index ] = ( T )element; + } - public void RemoveChild(ILayoutElement element) - { - _children.Remove((T)element); - } - public void ReplaceChild(ILayoutElement oldElement, ILayoutElement newElement) + public System.Xml.Schema.XmlSchema GetSchema() + { + return null; + } + + public virtual void ReadXml( System.Xml.XmlReader reader ) + { + reader.MoveToContent(); + if( reader.IsEmptyElement ) + { + reader.Read(); + ComputeVisibility(); + return; + } + string localName = reader.LocalName; + reader.Read(); + while( true ) + { + if( ( reader.LocalName == localName ) && + ( reader.NodeType == System.Xml.XmlNodeType.EndElement ) ) { - int index = _children.IndexOf((T)oldElement); - _children.Insert(index, (T)newElement); - _children.RemoveAt(index + 1); + break; } - - public int ChildrenCount + if( reader.NodeType == System.Xml.XmlNodeType.Whitespace ) { - get { return _children.Count; } + reader.Read(); + continue; } - public void ReplaceChildAt(int index, ILayoutElement element) + XmlSerializer serializer = null; + if( reader.LocalName == "LayoutAnchorablePaneGroup" ) + serializer = new XmlSerializer( typeof( LayoutAnchorablePaneGroup ) ); + else if( reader.LocalName == "LayoutAnchorablePane" ) + serializer = new XmlSerializer( typeof( LayoutAnchorablePane ) ); + else if( reader.LocalName == "LayoutAnchorable" ) + serializer = new XmlSerializer( typeof( LayoutAnchorable ) ); + else if( reader.LocalName == "LayoutDocumentPaneGroup" ) + serializer = new XmlSerializer( typeof( LayoutDocumentPaneGroup ) ); + else if( reader.LocalName == "LayoutDocumentPane" ) + serializer = new XmlSerializer( typeof( LayoutDocumentPane ) ); + else if( reader.LocalName == "LayoutDocument" ) + serializer = new XmlSerializer( typeof( LayoutDocument ) ); + else if( reader.LocalName == "LayoutAnchorGroup" ) + serializer = new XmlSerializer( typeof( LayoutAnchorGroup ) ); + else if( reader.LocalName == "LayoutPanel" ) + serializer = new XmlSerializer( typeof( LayoutPanel ) ); + else { - _children[index] = (T)element; + Type type = this.FindType( reader.LocalName ); + if( type == null ) + throw new ArgumentException( "AvalonDock.LayoutGroup doesn't know how to deserialize " + reader.LocalName ); + serializer = new XmlSerializer( type ); } + Children.Add( ( T )serializer.Deserialize( reader ) ); + } + + reader.ReadEndElement(); + } + + public virtual void WriteXml( System.Xml.XmlWriter writer ) + { + foreach( var child in Children ) + { + var type = child.GetType(); + XmlSerializer serializer = new XmlSerializer( type ); + serializer.Serialize( writer, child ); + } + + } + + #endregion + + #region Internal Methods + + protected virtual void OnIsVisibleChanged() + { + UpdateParentVisibility(); + } + + protected abstract bool GetVisibility(); + + protected virtual void ChildMoved( int oldIndex, int newIndex ) + { + } + + #endregion + + #region Private Methods - public System.Xml.Schema.XmlSchema GetSchema() + private void _children_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e ) + { + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) + { + if( e.OldItems != null ) { - return null; + foreach( LayoutElement element in e.OldItems ) + { + if( element.Parent == this ) + element.Parent = null; + } } + } - public virtual void ReadXml(System.Xml.XmlReader reader) + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) + { + if( e.NewItems != null ) { - reader.MoveToContent(); - if (reader.IsEmptyElement) - { - reader.Read(); - ComputeVisibility(); - return; - } - string localName = reader.LocalName; - reader.Read(); - while (true) + foreach( LayoutElement element in e.NewItems ) + { + if( element.Parent != this ) { - if (reader.LocalName == localName && - reader.NodeType == System.Xml.XmlNodeType.EndElement) - { - break; - } - - XmlSerializer serializer = null; - if (reader.LocalName == "LayoutAnchorablePaneGroup") - serializer = new XmlSerializer(typeof(LayoutAnchorablePaneGroup)); - else if (reader.LocalName == "LayoutAnchorablePane") - serializer = new XmlSerializer(typeof(LayoutAnchorablePane)); - else if (reader.LocalName == "LayoutAnchorable") - serializer = new XmlSerializer(typeof(LayoutAnchorable)); - else if (reader.LocalName == "LayoutDocumentPaneGroup") - serializer = new XmlSerializer(typeof(LayoutDocumentPaneGroup)); - else if (reader.LocalName == "LayoutDocumentPane") - serializer = new XmlSerializer(typeof(LayoutDocumentPane)); - else if (reader.LocalName == "LayoutDocument") - serializer = new XmlSerializer(typeof(LayoutDocument)); - else if (reader.LocalName == "LayoutAnchorGroup") - serializer = new XmlSerializer(typeof(LayoutAnchorGroup)); - else if (reader.LocalName == "LayoutPanel") - serializer = new XmlSerializer(typeof(LayoutPanel)); - - Children.Add((T)serializer.Deserialize(reader)); + if( element.Parent != null ) + element.Parent.RemoveChild( element ); + element.Parent = this; } - reader.ReadEndElement(); + } } + } - public virtual void WriteXml(System.Xml.XmlWriter writer) - { - foreach (var child in Children) - { - var type = child.GetType(); - XmlSerializer serializer = new XmlSerializer(type); - serializer.Serialize(writer, child); - } + ComputeVisibility(); + OnChildrenCollectionChanged(); + NotifyChildrenTreeChanged( ChildrenTreeChange.DirectChildrenChanged ); + RaisePropertyChanged( "ChildrenCount" ); + } + + private void UpdateParentVisibility() + { + var parentPane = Parent as ILayoutElementWithVisibility; + if( parentPane != null ) + parentPane.ComputeVisibility(); + } + private Type FindType( string name ) + { + foreach( var a in AppDomain.CurrentDomain.GetAssemblies() ) + { + foreach( var t in a.GetTypes() ) + { + if( t.Name.Equals( name ) ) + return t; } + } + return null; } + + #endregion + + #region ILayoutContainer Interface + + IEnumerable ILayoutContainer.Children + { + get + { + return _children.Cast(); + } + } + + #endregion + + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutGroupBase.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutGroupBase.cs index 9e7e93ce..f0e0bb51 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutGroupBase.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutGroupBase.cs @@ -15,44 +15,47 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Xml.Serialization; namespace Xceed.Wpf.AvalonDock.Layout { - [Serializable] - public abstract class LayoutGroupBase : LayoutElement + [Serializable] + public abstract class LayoutGroupBase : LayoutElement + { + #region Internal Methods + + protected virtual void OnChildrenCollectionChanged() { - [field: NonSerialized] - [field: XmlIgnore] - public event EventHandler ChildrenCollectionChanged; - - protected virtual void OnChildrenCollectionChanged() - { - if (ChildrenCollectionChanged != null) - ChildrenCollectionChanged(this, EventArgs.Empty); - } - - protected void NotifyChildrenTreeChanged(ChildrenTreeChange change) - { - OnChildrenTreeChanged(change); - var parentGroup = Parent as LayoutGroupBase; - if (parentGroup != null) - parentGroup.NotifyChildrenTreeChanged(ChildrenTreeChange.TreeChanged); - } - - [field: NonSerialized] - [field: XmlIgnore] - public event EventHandler ChildrenTreeChanged; - - protected virtual void OnChildrenTreeChanged(ChildrenTreeChange change) - { - if (ChildrenTreeChanged != null) - ChildrenTreeChanged(this, new ChildrenTreeChangedEventArgs(change)); - } + if( ChildrenCollectionChanged != null ) + ChildrenCollectionChanged( this, EventArgs.Empty ); + } + protected void NotifyChildrenTreeChanged( ChildrenTreeChange change ) + { + OnChildrenTreeChanged( change ); + var parentGroup = Parent as LayoutGroupBase; + if( parentGroup != null ) + parentGroup.NotifyChildrenTreeChanged( ChildrenTreeChange.TreeChanged ); + } + protected virtual void OnChildrenTreeChanged( ChildrenTreeChange change ) + { + if( ChildrenTreeChanged != null ) + ChildrenTreeChanged( this, new ChildrenTreeChangedEventArgs( change ) ); } + + #endregion + + #region Events + + [field: NonSerialized] + [field: XmlIgnore] + public event EventHandler ChildrenCollectionChanged; + + [field: NonSerialized] + [field: XmlIgnore] + public event EventHandler ChildrenTreeChanged; + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutPanel.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutPanel.cs index 6cde4784..5d9c36b1 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutPanel.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutPanel.cs @@ -15,68 +15,74 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows.Markup; -using System.Collections.ObjectModel; -using System.Windows; using System.Windows.Controls; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("Children")] - [Serializable] - public class LayoutPanel : LayoutPositionableGroup, ILayoutPanelElement, ILayoutOrientableGroup + [ContentProperty( "Children" )] + [Serializable] + public class LayoutPanel : LayoutPositionableGroup, ILayoutPanelElement, ILayoutOrientableGroup + { + #region Constructors + + public LayoutPanel() { - public LayoutPanel() - { + } - } + public LayoutPanel( ILayoutPanelElement firstChild ) + { + Children.Add( firstChild ); + } - public LayoutPanel(ILayoutPanelElement firstChild) - { - Children.Add(firstChild); - } + #endregion + #region Properties - #region Orientation + #region Orientation - private Orientation _orientation; - public Orientation Orientation + private Orientation _orientation; + public Orientation Orientation + { + get + { + return _orientation; + } + set + { + if( _orientation != value ) { - get { return _orientation; } - set - { - if (_orientation != value) - { - RaisePropertyChanging("Orientation"); - _orientation = value; - RaisePropertyChanged("Orientation"); - } - } + RaisePropertyChanging( "Orientation" ); + _orientation = value; + RaisePropertyChanged( "Orientation" ); } + } + } - #endregion + #endregion + #endregion - protected override bool GetVisibility() - { - return Children.Any(c => c.IsVisible); - } + #region Overrides - public override void WriteXml(System.Xml.XmlWriter writer) - { - writer.WriteAttributeString("Orientation", Orientation.ToString()); - base.WriteXml(writer); - } + protected override bool GetVisibility() + { + return Children.Any( c => c.IsVisible ); + } - public override void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("Orientation")) - Orientation = (Orientation)Enum.Parse(typeof(Orientation), reader.Value, true); - base.ReadXml(reader); - } + public override void WriteXml( System.Xml.XmlWriter writer ) + { + writer.WriteAttributeString( "Orientation", Orientation.ToString() ); + base.WriteXml( writer ); + } + + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "Orientation" ) ) + Orientation = ( Orientation )Enum.Parse( typeof( Orientation ), reader.Value, true ); + base.ReadXml( reader ); + } #if TRACE public override void ConsoleDump(int tab) @@ -88,5 +94,7 @@ namespace Xceed.Wpf.AvalonDock.Layout child.ConsoleDump(tab + 1); } #endif - } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutPositionableGroup.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutPositionableGroup.cs index 73baf589..9818face 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutPositionableGroup.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutPositionableGroup.cs @@ -15,286 +15,388 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; using System.Globalization; namespace Xceed.Wpf.AvalonDock.Layout { - [Serializable] - public abstract class LayoutPositionableGroup : LayoutGroup, ILayoutPositionableElement, ILayoutPositionableElementWithActualSize where T : class, ILayoutElement - { - public LayoutPositionableGroup() - { } - - GridLength _dockWidth = new GridLength(1.0, GridUnitType.Star); - public GridLength DockWidth - { - get - { - return _dockWidth; - } - set - { - if (DockWidth != value) - { - RaisePropertyChanging("DockWidth"); - _dockWidth = value; - RaisePropertyChanged("DockWidth"); - - OnDockWidthChanged(); - } - } - } - - - protected virtual void OnDockWidthChanged() - { - - } - - GridLength _dockHeight = new GridLength(1.0, GridUnitType.Star); - public GridLength DockHeight - { - get - { - return _dockHeight; - } - set - { - if (DockHeight != value) - { - RaisePropertyChanging("DockHeight"); - _dockHeight = value; - RaisePropertyChanged("DockHeight"); - - OnDockHeightChanged(); - } - } - } - - protected virtual void OnDockHeightChanged() - { - - } - - - #region DockMinWidth - - private double _dockMinWidth = 25.0; - public double DockMinWidth - { - get { return _dockMinWidth; } - set - { - if (_dockMinWidth != value) - { - MathHelper.AssertIsPositiveOrZero(value); - RaisePropertyChanging("DockMinWidth"); - _dockMinWidth = value; - RaisePropertyChanged("DockMinWidth"); - } - } - } - - #endregion - - #region DockMinHeight - - private double _dockMinHeight = 25.0; - public double DockMinHeight - { - get { return _dockMinHeight; } - set - { - if (_dockMinHeight != value) - { - MathHelper.AssertIsPositiveOrZero(value); - RaisePropertyChanging("DockMinHeight"); - _dockMinHeight = value; - RaisePropertyChanged("DockMinHeight"); - } - } - } - - #endregion - - #region FloatingWidth - - private double _floatingWidth = 0.0; - public double FloatingWidth - { - get { return _floatingWidth; } - set - { - if (_floatingWidth != value) - { - RaisePropertyChanging("FloatingWidth"); - _floatingWidth = value; - RaisePropertyChanged("FloatingWidth"); - } - } - } - - #endregion - - #region FloatingHeight - - private double _floatingHeight = 0.0; - public double FloatingHeight - { - get { return _floatingHeight; } - set - { - if (_floatingHeight != value) - { - RaisePropertyChanging("FloatingHeight"); - _floatingHeight = value; - RaisePropertyChanged("FloatingHeight"); - } - } - } - - #endregion - - #region FloatingLeft - - private double _floatingLeft = 0.0; - public double FloatingLeft - { - get { return _floatingLeft; } - set - { - if (_floatingLeft != value) - { - RaisePropertyChanging("FloatingLeft"); - _floatingLeft = value; - RaisePropertyChanged("FloatingLeft"); - } - } - } - - #endregion - - #region FloatingTop - - private double _floatingTop = 0.0; - public double FloatingTop - { - get { return _floatingTop; } - set - { - if (_floatingTop != value) - { - RaisePropertyChanging("FloatingTop"); - _floatingTop = value; - RaisePropertyChanged("FloatingTop"); - } - } - } - - #endregion - - #region IsMaximized - - private bool _isMaximized = false; - public bool IsMaximized - { - get { return _isMaximized; } - set - { - if (_isMaximized != value) - { - _isMaximized = value; - RaisePropertyChanged("IsMaximized"); - } - } - } - - #endregion - - - [NonSerialized] - double _actualWidth; - double ILayoutPositionableElementWithActualSize.ActualWidth - { - get - { - return _actualWidth; - } - set - { - _actualWidth = value; - } - } - - [NonSerialized] - double _actualHeight; - double ILayoutPositionableElementWithActualSize.ActualHeight - { - get - { - return _actualHeight; - } - set - { - _actualHeight = value; - } - } - - public override void WriteXml(System.Xml.XmlWriter writer) - { - if (DockWidth.Value != 1.0 || !DockWidth.IsStar) - writer.WriteAttributeString("DockWidth", _gridLengthConverter.ConvertToInvariantString(DockWidth)); - if (DockHeight.Value != 1.0 || !DockHeight.IsStar) - writer.WriteAttributeString("DockHeight", _gridLengthConverter.ConvertToInvariantString(DockHeight)); - - if (DockMinWidth != 25.0) - writer.WriteAttributeString("DocMinWidth", DockMinWidth.ToString(CultureInfo.InvariantCulture)); - if (DockMinHeight != 25.0) - writer.WriteAttributeString("DockMinHeight", DockMinHeight.ToString(CultureInfo.InvariantCulture)); - - if (FloatingWidth != 0.0) - writer.WriteAttributeString("FloatingWidth", FloatingWidth.ToString(CultureInfo.InvariantCulture)); - if (FloatingHeight != 0.0) - writer.WriteAttributeString("FloatingHeight", FloatingHeight.ToString(CultureInfo.InvariantCulture)); - if (FloatingLeft != 0.0) - writer.WriteAttributeString("FloatingLeft", FloatingLeft.ToString(CultureInfo.InvariantCulture)); - if (FloatingTop != 0.0) - writer.WriteAttributeString("FloatingTop", FloatingTop.ToString(CultureInfo.InvariantCulture)); - if (IsMaximized) - writer.WriteAttributeString("IsMaximized", IsMaximized.ToString()); - - base.WriteXml(writer); - } - - static GridLengthConverter _gridLengthConverter = new GridLengthConverter(); - public override void ReadXml(System.Xml.XmlReader reader) - { - if (reader.MoveToAttribute("DockWidth")) - _dockWidth = (GridLength)_gridLengthConverter.ConvertFromInvariantString(reader.Value); - if (reader.MoveToAttribute("DockHeight")) - _dockHeight = (GridLength)_gridLengthConverter.ConvertFromInvariantString(reader.Value); - - if (reader.MoveToAttribute("DocMinWidth")) - _dockMinWidth = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("DocMinHeight")) - _dockMinHeight = double.Parse(reader.Value, CultureInfo.InvariantCulture); - - if (reader.MoveToAttribute("FloatingWidth")) - _floatingWidth = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("FloatingHeight")) - _floatingHeight = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("FloatingLeft")) - _floatingLeft = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("FloatingTop")) - _floatingTop = double.Parse(reader.Value, CultureInfo.InvariantCulture); - if (reader.MoveToAttribute("IsMaximized")) - _isMaximized = bool.Parse(reader.Value); - - base.ReadXml(reader); - } - } + [Serializable] + public abstract class LayoutPositionableGroup : LayoutGroup, ILayoutPositionableElement, ILayoutPositionableElementWithActualSize where T : class, ILayoutElement + { + #region Members + + private static GridLengthConverter _gridLengthConverter = new GridLengthConverter(); + + #endregion + + #region Constructors + + public LayoutPositionableGroup() + { + } + + #endregion + + #region Properties + + #region DockWidth + + GridLength _dockWidth = new GridLength( 1.0, GridUnitType.Star ); + public GridLength DockWidth + { + get + { + return _dockWidth; + } + set + { + if( DockWidth != value ) + { + RaisePropertyChanging( "DockWidth" ); + _dockWidth = value; + RaisePropertyChanged( "DockWidth" ); + + OnDockWidthChanged(); + } + } + } + + #endregion + + #region DockHeight + + GridLength _dockHeight = new GridLength( 1.0, GridUnitType.Star ); + public GridLength DockHeight + { + get + { + return _dockHeight; + } + set + { + if( DockHeight != value ) + { + RaisePropertyChanging( "DockHeight" ); + _dockHeight = value; + RaisePropertyChanged( "DockHeight" ); + + OnDockHeightChanged(); + } + } + } + + #endregion + + #region AllowDuplicateContent + + private bool _allowDuplicateContent = true; + /// + /// Gets or sets the AllowDuplicateContent property. + /// When this property is true, then the LayoutDocumentPane or LayoutAnchorablePane allows dropping + /// duplicate content (according to its Title and ContentId). When this dependency property is false, + /// then the LayoutDocumentPane or LayoutAnchorablePane hides the OverlayWindow.DropInto button to prevent dropping of duplicate content. + /// + public bool AllowDuplicateContent + { + get + { + return _allowDuplicateContent; + } + set + { + if( _allowDuplicateContent != value ) + { + RaisePropertyChanging( "AllowDuplicateContent" ); + _allowDuplicateContent = value; + RaisePropertyChanged( "AllowDuplicateContent" ); + } + } + } + + #endregion + + #region CanRepositionItems + + private bool _canRepositionItems = true; + public bool CanRepositionItems + { + get + { + return _canRepositionItems; + } + set + { + if( _canRepositionItems != value ) + { + RaisePropertyChanging( "CanRepositionItems" ); + _canRepositionItems = value; + RaisePropertyChanged( "CanRepositionItems" ); + } + } + } + + #endregion + + #region DockMinWidth + + private double _dockMinWidth = 25.0; + public double DockMinWidth + { + get + { + return _dockMinWidth; + } + set + { + if( _dockMinWidth != value ) + { + MathHelper.AssertIsPositiveOrZero( value ); + RaisePropertyChanging( "DockMinWidth" ); + _dockMinWidth = value; + RaisePropertyChanged( "DockMinWidth" ); + } + } + } + + #endregion + + #region DockMinHeight + + private double _dockMinHeight = 25.0; + public double DockMinHeight + { + get + { + return _dockMinHeight; + } + set + { + if( _dockMinHeight != value ) + { + MathHelper.AssertIsPositiveOrZero( value ); + RaisePropertyChanging( "DockMinHeight" ); + _dockMinHeight = value; + RaisePropertyChanged( "DockMinHeight" ); + } + } + } + + #endregion + + #region FloatingWidth + + private double _floatingWidth = 0.0; + public double FloatingWidth + { + get + { + return _floatingWidth; + } + set + { + if( _floatingWidth != value ) + { + RaisePropertyChanging( "FloatingWidth" ); + _floatingWidth = value; + RaisePropertyChanged( "FloatingWidth" ); + } + } + } + + #endregion + + #region FloatingHeight + + private double _floatingHeight = 0.0; + public double FloatingHeight + { + get + { + return _floatingHeight; + } + set + { + if( _floatingHeight != value ) + { + RaisePropertyChanging( "FloatingHeight" ); + _floatingHeight = value; + RaisePropertyChanged( "FloatingHeight" ); + } + } + } + + #endregion + + #region FloatingLeft + + private double _floatingLeft = 0.0; + public double FloatingLeft + { + get + { + return _floatingLeft; + } + set + { + if( _floatingLeft != value ) + { + RaisePropertyChanging( "FloatingLeft" ); + _floatingLeft = value; + RaisePropertyChanged( "FloatingLeft" ); + } + } + } + + #endregion + + #region FloatingTop + + private double _floatingTop = 0.0; + public double FloatingTop + { + get + { + return _floatingTop; + } + set + { + if( _floatingTop != value ) + { + RaisePropertyChanging( "FloatingTop" ); + _floatingTop = value; + RaisePropertyChanged( "FloatingTop" ); + } + } + } + + #endregion + + #region IsMaximized + + private bool _isMaximized = false; + public bool IsMaximized + { + get + { + return _isMaximized; + } + set + { + if( _isMaximized != value ) + { + _isMaximized = value; + RaisePropertyChanged( "IsMaximized" ); + } + } + } + + #endregion + + #region ActualWidth + + [NonSerialized] + double _actualWidth; + double ILayoutPositionableElementWithActualSize.ActualWidth + { + get + { + return _actualWidth; + } + set + { + _actualWidth = value; + } + } + + #endregion + + #region ActualHeight + + [NonSerialized] + double _actualHeight; + double ILayoutPositionableElementWithActualSize.ActualHeight + { + get + { + return _actualHeight; + } + set + { + _actualHeight = value; + } + } + + #endregion + + #endregion + + #region Overrides + + public override void WriteXml( System.Xml.XmlWriter writer ) + { + if( DockWidth.Value != 1.0 || !DockWidth.IsStar ) + writer.WriteAttributeString( "DockWidth", _gridLengthConverter.ConvertToInvariantString( DockWidth ) ); + if( DockHeight.Value != 1.0 || !DockHeight.IsStar ) + writer.WriteAttributeString( "DockHeight", _gridLengthConverter.ConvertToInvariantString( DockHeight ) ); + + if( DockMinWidth != 25.0 ) + writer.WriteAttributeString( "DocMinWidth", DockMinWidth.ToString( CultureInfo.InvariantCulture ) ); + if( DockMinHeight != 25.0 ) + writer.WriteAttributeString( "DockMinHeight", DockMinHeight.ToString( CultureInfo.InvariantCulture ) ); + + if( FloatingWidth != 0.0 ) + writer.WriteAttributeString( "FloatingWidth", FloatingWidth.ToString( CultureInfo.InvariantCulture ) ); + if( FloatingHeight != 0.0 ) + writer.WriteAttributeString( "FloatingHeight", FloatingHeight.ToString( CultureInfo.InvariantCulture ) ); + if( FloatingLeft != 0.0 ) + writer.WriteAttributeString( "FloatingLeft", FloatingLeft.ToString( CultureInfo.InvariantCulture ) ); + if( FloatingTop != 0.0 ) + writer.WriteAttributeString( "FloatingTop", FloatingTop.ToString( CultureInfo.InvariantCulture ) ); + if( IsMaximized ) + writer.WriteAttributeString( "IsMaximized", IsMaximized.ToString() ); + + base.WriteXml( writer ); + } + + + public override void ReadXml( System.Xml.XmlReader reader ) + { + if( reader.MoveToAttribute( "DockWidth" ) ) + _dockWidth = ( GridLength )_gridLengthConverter.ConvertFromInvariantString( reader.Value ); + if( reader.MoveToAttribute( "DockHeight" ) ) + _dockHeight = ( GridLength )_gridLengthConverter.ConvertFromInvariantString( reader.Value ); + + if( reader.MoveToAttribute( "DocMinWidth" ) ) + _dockMinWidth = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "DocMinHeight" ) ) + _dockMinHeight = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + + if( reader.MoveToAttribute( "FloatingWidth" ) ) + _floatingWidth = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "FloatingHeight" ) ) + _floatingHeight = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "FloatingLeft" ) ) + _floatingLeft = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "FloatingTop" ) ) + _floatingTop = double.Parse( reader.Value, CultureInfo.InvariantCulture ); + if( reader.MoveToAttribute( "IsMaximized" ) ) + _isMaximized = bool.Parse( reader.Value ); + + base.ReadXml( reader ); + } + + #endregion + + #region Internal Methods + + protected virtual void OnDockWidthChanged() + { + } + + protected virtual void OnDockHeightChanged() + { + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutRoot.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutRoot.cs index 61c376ee..f2fa1de9 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutRoot.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutRoot.cs @@ -23,667 +23,1042 @@ using System.Collections.ObjectModel; using System.Windows.Markup; using System.Xml.Serialization; using Standard; +using System.Xml; +using System.Xml.Schema; +using System.Windows.Controls; namespace Xceed.Wpf.AvalonDock.Layout { - [ContentProperty("RootPanel")] - [Serializable] - public class LayoutRoot : LayoutElement, ILayoutContainer, ILayoutRoot + [ContentProperty( "RootPanel" )] + [Serializable] + public class LayoutRoot : LayoutElement, ILayoutContainer, ILayoutRoot, IXmlSerializable + { + #region Constructors + + public LayoutRoot() { - public LayoutRoot() - { - RightSide = new LayoutAnchorSide(); - LeftSide = new LayoutAnchorSide(); - TopSide = new LayoutAnchorSide(); - BottomSide = new LayoutAnchorSide(); - RootPanel = new LayoutPanel(new LayoutDocumentPane()); - } + RightSide = new LayoutAnchorSide(); + LeftSide = new LayoutAnchorSide(); + TopSide = new LayoutAnchorSide(); + BottomSide = new LayoutAnchorSide(); + RootPanel = new LayoutPanel( new LayoutDocumentPane() ); + } + + #endregion + #region Properties - #region RootPanel + #region RootPanel - private LayoutPanel _rootPanel; - public LayoutPanel RootPanel + private LayoutPanel _rootPanel; + public LayoutPanel RootPanel + { + get + { + return _rootPanel; + } + set + { + if( _rootPanel != value ) { - get { return _rootPanel; } - set - { - if (_rootPanel != value) - { - RaisePropertyChanging("RootPanel"); - if (_rootPanel != null && - _rootPanel.Parent == this) - _rootPanel.Parent = null; - _rootPanel = value; - - if (_rootPanel == null) - _rootPanel = new LayoutPanel(new LayoutDocumentPane()); - - if (_rootPanel != null) - _rootPanel.Parent = this; - RaisePropertyChanged("RootPanel"); - } - } + RaisePropertyChanging( "RootPanel" ); + if( _rootPanel != null && + _rootPanel.Parent == this ) + _rootPanel.Parent = null; + _rootPanel = value; + + if( _rootPanel == null ) + _rootPanel = new LayoutPanel( new LayoutDocumentPane() ); + + if( _rootPanel != null ) + _rootPanel.Parent = this; + RaisePropertyChanged( "RootPanel" ); } + } + } - #endregion + #endregion - #region TopSide + #region TopSide - private LayoutAnchorSide _topSide = null; - public LayoutAnchorSide TopSide + private LayoutAnchorSide _topSide = null; + public LayoutAnchorSide TopSide + { + get + { + return _topSide; + } + set + { + if( _topSide != value ) { - get { return _topSide; } - set - { - if (_topSide != value) - { - RaisePropertyChanging("TopSide"); - _topSide = value; - if (_topSide != null) - _topSide.Parent = this; - RaisePropertyChanged("TopSide"); - } - } + RaisePropertyChanging( "TopSide" ); + _topSide = value; + if( _topSide != null ) + _topSide.Parent = this; + RaisePropertyChanged( "TopSide" ); } + } + } - #endregion + #endregion - #region RightSide + #region RightSide - private LayoutAnchorSide _rightSide; - public LayoutAnchorSide RightSide + private LayoutAnchorSide _rightSide; + public LayoutAnchorSide RightSide + { + get + { + return _rightSide; + } + set + { + if( _rightSide != value ) { - get { return _rightSide; } - set - { - if (_rightSide != value) - { - RaisePropertyChanging("RightSide"); - _rightSide = value; - if (_rightSide != null) - _rightSide.Parent = this; - RaisePropertyChanged("RightSide"); - } - } + RaisePropertyChanging( "RightSide" ); + _rightSide = value; + if( _rightSide != null ) + _rightSide.Parent = this; + RaisePropertyChanged( "RightSide" ); } + } + } - #endregion + #endregion - #region LeftSide + #region LeftSide - private LayoutAnchorSide _leftSide = null; - public LayoutAnchorSide LeftSide + private LayoutAnchorSide _leftSide = null; + public LayoutAnchorSide LeftSide + { + get + { + return _leftSide; + } + set + { + if( _leftSide != value ) { - get { return _leftSide; } - set - { - if (_leftSide != value) - { - RaisePropertyChanging("LeftSide"); - _leftSide = value; - if (_leftSide != null) - _leftSide.Parent = this; - RaisePropertyChanged("LeftSide"); - } - } + RaisePropertyChanging( "LeftSide" ); + _leftSide = value; + if( _leftSide != null ) + _leftSide.Parent = this; + RaisePropertyChanged( "LeftSide" ); } + } + } - #endregion + #endregion - #region BottomSide + #region BottomSide - private LayoutAnchorSide _bottomSide = null; - public LayoutAnchorSide BottomSide + private LayoutAnchorSide _bottomSide = null; + public LayoutAnchorSide BottomSide + { + get + { + return _bottomSide; + } + set + { + if( _bottomSide != value ) { - get { return _bottomSide; } - set - { - if (_bottomSide != value) - { - RaisePropertyChanging("BottomSide"); - _bottomSide = value; - if (_bottomSide != null) - _bottomSide.Parent = this; - RaisePropertyChanged("BottomSide"); - } - } + RaisePropertyChanging( "BottomSide" ); + _bottomSide = value; + if( _bottomSide != null ) + _bottomSide.Parent = this; + RaisePropertyChanged( "BottomSide" ); } + } + } - #endregion + #endregion - #region FloatingWindows - ObservableCollection _floatingWindows = null; + #region FloatingWindows - public ObservableCollection FloatingWindows - { - get - { - if (_floatingWindows == null) - { - _floatingWindows = new ObservableCollection(); - _floatingWindows.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_floatingWindows_CollectionChanged); - } + ObservableCollection _floatingWindows = null; - return _floatingWindows; - } + public ObservableCollection FloatingWindows + { + get + { + if( _floatingWindows == null ) + { + _floatingWindows = new ObservableCollection(); + _floatingWindows.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( _floatingWindows_CollectionChanged ); } - void _floatingWindows_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + return _floatingWindows; + } + } + + #endregion + + #region HiddenAnchorables + + ObservableCollection _hiddenAnchorables = null; + + public ObservableCollection Hidden + { + get + { + if( _hiddenAnchorables == null ) { - if (e.OldItems != null && (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)) - { - foreach (LayoutFloatingWindow element in e.OldItems) - { - if (element.Parent == this) - element.Parent = null; - } - } - - if (e.NewItems != null && (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)) - { - foreach (LayoutFloatingWindow element in e.NewItems) - element.Parent = this; - } + _hiddenAnchorables = new ObservableCollection(); + _hiddenAnchorables.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( _hiddenAnchorables_CollectionChanged ); } - #endregion - #region HiddenAnchorables + return _hiddenAnchorables; + } + } - ObservableCollection _hiddenAnchorables = null; + #endregion - public ObservableCollection Hidden - { - get - { - if (_hiddenAnchorables == null) - { - _hiddenAnchorables = new ObservableCollection(); - _hiddenAnchorables.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_hiddenAnchorables_CollectionChanged); - } + #region Children - return _hiddenAnchorables; - } + public IEnumerable Children + { + get + { + if( RootPanel != null ) + yield return RootPanel; + if( _floatingWindows != null ) + { + foreach( var floatingWindow in _floatingWindows ) + yield return floatingWindow; } - - void _hiddenAnchorables_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + if( TopSide != null ) + yield return TopSide; + if( RightSide != null ) + yield return RightSide; + if( BottomSide != null ) + yield return BottomSide; + if( LeftSide != null ) + yield return LeftSide; + if( _hiddenAnchorables != null ) { - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) - { - if (e.OldItems != null) - { - foreach (LayoutAnchorable element in e.OldItems) - { - if (element.Parent == this) - element.Parent = null; - } - } - } + foreach( var hiddenAnchorable in _hiddenAnchorables ) + yield return hiddenAnchorable; + } + } + } - if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || - e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) - { - if (e.NewItems != null) - { - foreach (LayoutAnchorable element in e.NewItems) - { - if (element.Parent != this) - { - if (element.Parent != null) - element.Parent.RemoveChild(element); - element.Parent = this; - } - - } - } - } + #endregion + #region ChildrenCount + public int ChildrenCount + { + get + { + return 5 + + ( _floatingWindows != null ? _floatingWindows.Count : 0 ) + + ( _hiddenAnchorables != null ? _hiddenAnchorables.Count : 0 ); + } + } - } + #endregion - #endregion + #region ActiveContent - #region Children - public IEnumerable Children + [field: NonSerialized] + private WeakReference _activeContent = null; + private bool _activeContentSet = false; + + [XmlIgnore] + public LayoutContent ActiveContent + { + get + { + return _activeContent.GetValueOrDefault(); + } + set + { + var currentValue = ActiveContent; + if( currentValue != value ) { - get - { - if (RootPanel != null) - yield return RootPanel; - if (_floatingWindows != null) - { - foreach (var floatingWindow in _floatingWindows) - yield return floatingWindow; - } - if (TopSide != null) - yield return TopSide; - if (RightSide != null) - yield return RightSide; - if (BottomSide != null) - yield return BottomSide; - if (LeftSide != null) - yield return LeftSide; - if (_hiddenAnchorables != null) - { - foreach (var hiddenAnchorable in _hiddenAnchorables) - yield return hiddenAnchorable; - } - } + InternalSetActiveContent( currentValue, value ); } - public void RemoveChild(ILayoutElement element) - { - if (element == RootPanel) - RootPanel = null; - else if (_floatingWindows != null && _floatingWindows.Contains(element)) - _floatingWindows.Remove(element as LayoutFloatingWindow); - else if (_hiddenAnchorables != null && _hiddenAnchorables.Contains(element)) - _hiddenAnchorables.Remove(element as LayoutAnchorable); - else if (element == TopSide) - TopSide = null; - else if (element == RightSide) - RightSide = null; - else if (element == BottomSide) - BottomSide = null; - else if (element == LeftSide) - LeftSide = null; + } + } - } - public void ReplaceChild(ILayoutElement oldElement, ILayoutElement newElement) - { - if (oldElement == RootPanel) - RootPanel = (LayoutPanel)newElement; - else if (_floatingWindows != null && _floatingWindows.Contains(oldElement)) - { - int index = _floatingWindows.IndexOf(oldElement as LayoutFloatingWindow); - _floatingWindows.Remove(oldElement as LayoutFloatingWindow); - _floatingWindows.Insert(index, newElement as LayoutFloatingWindow); - } - else if (_hiddenAnchorables != null && _hiddenAnchorables.Contains(oldElement)) - { - int index = _hiddenAnchorables.IndexOf(oldElement as LayoutAnchorable); - _hiddenAnchorables.Remove(oldElement as LayoutAnchorable); - _hiddenAnchorables.Insert(index, newElement as LayoutAnchorable); - } - else if (oldElement == TopSide) - TopSide = (LayoutAnchorSide)newElement; - else if (oldElement == RightSide) - RightSide = (LayoutAnchorSide)newElement; - else if (oldElement == BottomSide) - BottomSide = (LayoutAnchorSide)newElement; - else if (oldElement == LeftSide) - LeftSide = (LayoutAnchorSide)newElement; - } + #endregion + + #region LastFocusedDocument - public int ChildrenCount + [field: NonSerialized] + private WeakReference _lastFocusedDocument = null; + [field: NonSerialized] + private bool _lastFocusedDocumentSet = false; + + [XmlIgnore] + public LayoutContent LastFocusedDocument + { + get + { + return _lastFocusedDocument.GetValueOrDefault(); + } + private set + { + var currentValue = LastFocusedDocument; + if( currentValue != value ) { - get - { - return 5 + - (_floatingWindows != null ? _floatingWindows.Count : 0) + - (_hiddenAnchorables != null ? _hiddenAnchorables.Count : 0); - } + RaisePropertyChanging( "LastFocusedDocument" ); + if( currentValue != null ) + currentValue.IsLastFocusedDocument = false; + _lastFocusedDocument = new WeakReference( value ); + currentValue = LastFocusedDocument; + if( currentValue != null ) + currentValue.IsLastFocusedDocument = true; + _lastFocusedDocumentSet = currentValue != null; + RaisePropertyChanged( "LastFocusedDocument" ); } - #endregion + } + } - #region ActiveContent + #endregion - [field:NonSerialized] - private WeakReference _activeContent = null; - private bool _activeContentSet = false; + #region Manager - [XmlIgnore] - public LayoutContent ActiveContent - { - get { return _activeContent.GetValueOrDefault(); } - set - { - var currentValue = ActiveContent; - if (currentValue != value) - { - InternalSetActiveContent(currentValue, value); - } - } - } - void InternalSetActiveContent(LayoutContent currentValue, LayoutContent newActiveContent) - { - RaisePropertyChanging("ActiveContent"); - if (currentValue != null) - currentValue.IsActive = false; - _activeContent = new WeakReference(newActiveContent); - currentValue = ActiveContent; - if (currentValue != null) - currentValue.IsActive = true; - RaisePropertyChanged("ActiveContent"); - _activeContentSet = currentValue != null; - if (currentValue != null) - { - if (currentValue.Parent is LayoutDocumentPane || currentValue is LayoutDocument) - LastFocusedDocument = currentValue; - } - else - LastFocusedDocument = null; - } + [NonSerialized] + private DockingManager _manager = null; - void UpdateActiveContentProperty() + [XmlIgnore] + public DockingManager Manager + { + get + { + return _manager; + } + internal set + { + if( _manager != value ) { - var activeContent = ActiveContent; - if (_activeContentSet && (activeContent == null || activeContent.Root != this)) - { - _activeContentSet = false; - InternalSetActiveContent(activeContent, null); - } + RaisePropertyChanging( "Manager" ); + _manager = value; + RaisePropertyChanged( "Manager" ); } - #endregion + } + } - #region LastFocusedDocument + #endregion - [field: NonSerialized] - private WeakReference _lastFocusedDocument = null; - [field: NonSerialized] - private bool _lastFocusedDocumentSet = false; + #endregion - [XmlIgnore] - public LayoutContent LastFocusedDocument + #region Overrides + +#if TRACE + public override void ConsoleDump(int tab) { - get { return _lastFocusedDocument.GetValueOrDefault(); } - private set - { - var currentValue = LastFocusedDocument; - if (currentValue != value) - { - RaisePropertyChanging("LastFocusedDocument"); - if (currentValue != null) - currentValue.IsLastFocusedDocument = false; - _lastFocusedDocument = new WeakReference(value); - currentValue = LastFocusedDocument; - if (currentValue != null) - currentValue.IsLastFocusedDocument = true; - _lastFocusedDocumentSet = currentValue != null; - RaisePropertyChanged("LastFocusedDocument"); - } - } + System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) ); + System.Diagnostics.Trace.WriteLine( "RootPanel()" ); + + RootPanel.ConsoleDump(tab + 1); + + System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) ); + System.Diagnostics.Trace.WriteLine( "FloatingWindows()" ); + + foreach (LayoutFloatingWindow fw in FloatingWindows) + fw.ConsoleDump(tab + 1); + + System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) ); + System.Diagnostics.Trace.WriteLine( "Hidden()" ); + + foreach (LayoutAnchorable hidden in Hidden) + hidden.ConsoleDump(tab + 1); } +#endif - #endregion + #endregion - #region Manager + #region Public Methods + public void RemoveChild( ILayoutElement element ) + { + if( element == RootPanel ) + RootPanel = null; + else if( _floatingWindows != null && _floatingWindows.Contains( element ) ) + _floatingWindows.Remove( element as LayoutFloatingWindow ); + else if( _hiddenAnchorables != null && _hiddenAnchorables.Contains( element ) ) + _hiddenAnchorables.Remove( element as LayoutAnchorable ); + else if( element == TopSide ) + TopSide = null; + else if( element == RightSide ) + RightSide = null; + else if( element == BottomSide ) + BottomSide = null; + else if( element == LeftSide ) + LeftSide = null; + + } + + public void ReplaceChild( ILayoutElement oldElement, ILayoutElement newElement ) + { + if( oldElement == RootPanel ) + RootPanel = ( LayoutPanel )newElement; + else if( _floatingWindows != null && _floatingWindows.Contains( oldElement ) ) + { + int index = _floatingWindows.IndexOf( oldElement as LayoutFloatingWindow ); + _floatingWindows.Remove( oldElement as LayoutFloatingWindow ); + _floatingWindows.Insert( index, newElement as LayoutFloatingWindow ); + } + else if( _hiddenAnchorables != null && _hiddenAnchorables.Contains( oldElement ) ) + { + int index = _hiddenAnchorables.IndexOf( oldElement as LayoutAnchorable ); + _hiddenAnchorables.Remove( oldElement as LayoutAnchorable ); + _hiddenAnchorables.Insert( index, newElement as LayoutAnchorable ); + } + else if( oldElement == TopSide ) + TopSide = ( LayoutAnchorSide )newElement; + else if( oldElement == RightSide ) + RightSide = ( LayoutAnchorSide )newElement; + else if( oldElement == BottomSide ) + BottomSide = ( LayoutAnchorSide )newElement; + else if( oldElement == LeftSide ) + LeftSide = ( LayoutAnchorSide )newElement; + } + + /// + /// Removes any empty container not directly referenced by other layout items + /// + public void CollectGarbage() + { + bool exitFlag = true; - [NonSerialized] - private DockingManager _manager = null; + #region collect empty panes + do + { + exitFlag = true; - [XmlIgnore] - public DockingManager Manager + //for each content that references via PreviousContainer a disconnected Pane set the property to null + foreach( var content in this.Descendents().OfType().Where( c => c.PreviousContainer != null && + ( c.PreviousContainer.Parent == null || c.PreviousContainer.Parent.Root != this ) ) ) { - get { return _manager; } - internal set - { - if (_manager != value) - { - RaisePropertyChanging("Manager"); - _manager = value; - RaisePropertyChanged("Manager"); - } - } + content.PreviousContainer = null; } - #endregion + //for each pane that is empty + foreach( var emptyPane in this.Descendents().OfType().Where( p => p.ChildrenCount == 0 ) ) + { + //...set null any reference coming from contents not yet hosted in a floating window + foreach( var contentReferencingEmptyPane in this.Descendents().OfType() + .Where( c => ( ( ILayoutPreviousContainer )c ).PreviousContainer == emptyPane && !c.IsFloating ) ) + { + if( contentReferencingEmptyPane is LayoutAnchorable && + !( ( LayoutAnchorable )contentReferencingEmptyPane ).IsVisible ) + continue; + + ( ( ILayoutPreviousContainer )contentReferencingEmptyPane ).PreviousContainer = null; + contentReferencingEmptyPane.PreviousContainerIndex = -1; + } + + //...if this pane is the only documentpane present in the layout than skip it + if( emptyPane is LayoutDocumentPane && + this.Descendents().OfType().Count( c => c != emptyPane ) == 0 ) + continue; + + //...if this empty panes is not referenced by anyone, than removes it from its parent container + if( !this.Descendents().OfType().Any( c => c.PreviousContainer == emptyPane ) ) + { + var parentGroup = emptyPane.Parent as ILayoutContainer; + parentGroup.RemoveChild( emptyPane ); + exitFlag = false; + break; + } + } - #region CollectGarbage + if( !exitFlag ) + { + //removes any empty anchorable pane group + foreach( var emptyPaneGroup in this.Descendents().OfType().Where( p => p.ChildrenCount == 0 ) ) + { + var parentGroup = emptyPaneGroup.Parent as ILayoutContainer; + parentGroup.RemoveChild( emptyPaneGroup ); + exitFlag = false; + break; + } + } - /// - /// Removes any empty container not directly referenced by other layout items - /// - public void CollectGarbage() + if( !exitFlag ) { - bool exitFlag = true; + //removes any empty layout panel + foreach( var emptyPaneGroup in this.Descendents().OfType().Where( p => p.ChildrenCount == 0 ) ) + { + var parentGroup = emptyPaneGroup.Parent as ILayoutContainer; + parentGroup.RemoveChild( emptyPaneGroup ); + exitFlag = false; + break; + } + } - #region collect empty panes - do - { - exitFlag = true; - - //for each content that references via PreviousContainer a disconnected Pane set the property to null - foreach (var content in this.Descendents().OfType().Where(c => c.PreviousContainer != null && - (c.PreviousContainer.Parent == null || c.PreviousContainer.Parent.Root != this))) - { - content.PreviousContainer = null; - } - - //for each pane that is empty - foreach (var emptyPane in this.Descendents().OfType().Where(p => p.ChildrenCount == 0)) - { - //...set null any reference coming from contents not yet hosted in a floating window - foreach (var contentReferencingEmptyPane in this.Descendents().OfType() - .Where(c => ((ILayoutPreviousContainer)c).PreviousContainer == emptyPane && !c.IsFloating)) - { - if (contentReferencingEmptyPane is LayoutAnchorable && - !((LayoutAnchorable)contentReferencingEmptyPane).IsVisible) - continue; - - ((ILayoutPreviousContainer)contentReferencingEmptyPane).PreviousContainer = null; - contentReferencingEmptyPane.PreviousContainerIndex = -1; - } - - //...if this pane is the only documentpane present in the layout than skip it - if (emptyPane is LayoutDocumentPane && - this.Descendents().OfType().Count(c => c != emptyPane) == 0) - continue; - - //...if this empty panes is not referenced by anyone, than removes it from its parent container - if (!this.Descendents().OfType().Any(c => c.PreviousContainer == emptyPane)) - { - var parentGroup = emptyPane.Parent as ILayoutContainer; - parentGroup.RemoveChild(emptyPane); - exitFlag = false; - break; - } - } - - if (!exitFlag) - { - //removes any empty anchorable pane group - foreach (var emptyPaneGroup in this.Descendents().OfType().Where(p => p.ChildrenCount == 0)) - { - var parentGroup = emptyPaneGroup.Parent as ILayoutContainer; - parentGroup.RemoveChild(emptyPaneGroup); - exitFlag = false; - break; - } - } - - if (!exitFlag) - { - //removes any empty layout panel - foreach (var emptyPaneGroup in this.Descendents().OfType().Where(p => p.ChildrenCount == 0)) - { - var parentGroup = emptyPaneGroup.Parent as ILayoutContainer; - parentGroup.RemoveChild(emptyPaneGroup); - exitFlag = false; - break; - } - } - - if (!exitFlag) - { - //removes any empty floating window - foreach (var emptyPaneGroup in this.Descendents().OfType().Where(p => p.ChildrenCount == 0)) - { - var parentGroup = emptyPaneGroup.Parent as ILayoutContainer; - parentGroup.RemoveChild(emptyPaneGroup); - exitFlag = false; - break; - } - } - - if (!exitFlag) - { - //removes any empty anchor group - foreach (var emptyPaneGroup in this.Descendents().OfType().Where(p => p.ChildrenCount == 0)) - { - var parentGroup = emptyPaneGroup.Parent as ILayoutContainer; - parentGroup.RemoveChild(emptyPaneGroup); - exitFlag = false; - break; - } - } + if( !exitFlag ) + { + //removes any empty floating window + foreach( var emptyPaneGroup in this.Descendents().OfType().Where( p => p.ChildrenCount == 0 ) ) + { + var parentGroup = emptyPaneGroup.Parent as ILayoutContainer; + parentGroup.RemoveChild( emptyPaneGroup ); + exitFlag = false; + break; + } + } - } - while (!exitFlag); - #endregion + if( !exitFlag ) + { + //removes any empty anchor group + foreach( var emptyPaneGroup in this.Descendents().OfType().Where( p => p.ChildrenCount == 0 ) ) + { + var parentGroup = emptyPaneGroup.Parent as ILayoutContainer; + parentGroup.RemoveChild( emptyPaneGroup ); + exitFlag = false; + break; + } + } - #region collapse single child anchorable pane groups - do - { - exitFlag = true; - //for each pane that is empty - foreach (var paneGroupToCollapse in this.Descendents().OfType().Where(p => p.ChildrenCount == 1 && p.Children[0] is LayoutAnchorablePaneGroup).ToArray()) - { - var singleChild = paneGroupToCollapse.Children[0] as LayoutAnchorablePaneGroup; - paneGroupToCollapse.Orientation = singleChild.Orientation; - paneGroupToCollapse.RemoveChild(singleChild); - while (singleChild.ChildrenCount > 0) - { - paneGroupToCollapse.InsertChildAt( - paneGroupToCollapse.ChildrenCount, singleChild.Children[0]); - } - - exitFlag = false; - break; - } + } + while( !exitFlag ); + #endregion - } - while (!exitFlag); + #region collapse single child anchorable pane groups + do + { + exitFlag = true; + //for each pane that is empty + foreach( var paneGroupToCollapse in this.Descendents().OfType().Where( p => p.ChildrenCount == 1 && p.Children[ 0 ] is LayoutAnchorablePaneGroup ).ToArray() ) + { + var singleChild = paneGroupToCollapse.Children[ 0 ] as LayoutAnchorablePaneGroup; + paneGroupToCollapse.Orientation = singleChild.Orientation; + paneGroupToCollapse.RemoveChild( singleChild ); + while( singleChild.ChildrenCount > 0 ) + { + paneGroupToCollapse.InsertChildAt( + paneGroupToCollapse.ChildrenCount, singleChild.Children[ 0 ] ); + } + + exitFlag = false; + break; + } + } + while( !exitFlag ); - #endregion - #region collapse single child document pane groups - do - { - exitFlag = true; - //for each pane that is empty - foreach (var paneGroupToCollapse in this.Descendents().OfType().Where(p => p.ChildrenCount == 1 && p.Children[0] is LayoutDocumentPaneGroup).ToArray()) - { - var singleChild = paneGroupToCollapse.Children[0] as LayoutDocumentPaneGroup; - paneGroupToCollapse.Orientation = singleChild.Orientation; - paneGroupToCollapse.RemoveChild(singleChild); - while (singleChild.ChildrenCount > 0) - { - paneGroupToCollapse.InsertChildAt( - paneGroupToCollapse.ChildrenCount, singleChild.Children[0]); - } - - exitFlag = false; - break; - } + #endregion - } - while (!exitFlag); + #region collapse single child document pane groups + do + { + exitFlag = true; + //for each pane that is empty + foreach( var paneGroupToCollapse in this.Descendents().OfType().Where( p => p.ChildrenCount == 1 && p.Children[ 0 ] is LayoutDocumentPaneGroup ).ToArray() ) + { + var singleChild = paneGroupToCollapse.Children[ 0 ] as LayoutDocumentPaneGroup; + paneGroupToCollapse.Orientation = singleChild.Orientation; + paneGroupToCollapse.RemoveChild( singleChild ); + while( singleChild.ChildrenCount > 0 ) + { + paneGroupToCollapse.InsertChildAt( + paneGroupToCollapse.ChildrenCount, singleChild.Children[ 0 ] ); + } + + exitFlag = false; + break; + } + } + while( !exitFlag ); - #endregion - #region collapse single child layout panels - do - { - exitFlag = true; - //for each panel that has only one child - foreach (var panelToCollapse in this.Descendents().OfType().Where(p => p.ChildrenCount == 1 && p.Children[0] is LayoutPanel).ToArray()) - { - var singleChild = panelToCollapse.Children[0] as LayoutPanel; - panelToCollapse.Orientation = singleChild.Orientation; - panelToCollapse.RemoveChild(singleChild); - while (singleChild.ChildrenCount > 0) - { - panelToCollapse.InsertChildAt( - panelToCollapse.ChildrenCount, singleChild.Children[0]); - } - - exitFlag = false; - break; - } + #endregion - } - while (!exitFlag); - #endregion + //do + //{ + // exitFlag = true; + // //for each panel that has only one child + // foreach( var panelToCollapse in this.Descendents().OfType().Where( p => p.ChildrenCount == 1 && p.Children[ 0 ] is LayoutPanel ).ToArray() ) + // { + // var singleChild = panelToCollapse.Children[ 0 ] as LayoutPanel; + // panelToCollapse.Orientation = singleChild.Orientation; + // panelToCollapse.RemoveChild( singleChild ); + // ILayoutPanelElement[] singleChildChildren = new ILayoutPanelElement[ singleChild.ChildrenCount ]; + // singleChild.Children.CopyTo( singleChildChildren, 0 ); + // while( singleChild.ChildrenCount > 0 ) + // { + // panelToCollapse.InsertChildAt( + // panelToCollapse.ChildrenCount, singleChildChildren[ panelToCollapse.ChildrenCount ] ); + // } - #region Update ActiveContent and LastFocusedDocument properties - UpdateActiveContentProperty(); - #endregion + // exitFlag = false; + // break; + // } + + //} + //while( !exitFlag ); + + #region Update ActiveContent and LastFocusedDocument properties + UpdateActiveContentProperty(); + #endregion #if DEBUG - System.Diagnostics.Debug.Assert( - !this.Descendents().OfType().Any(a => a.ChildrenCount == 0 && a.IsVisible)); + System.Diagnostics.Debug.Assert( + !this.Descendents().OfType().Any( a => a.ChildrenCount == 0 && a.IsVisible ) ); #if TRACE RootPanel.ConsoleDump(4); #endif #endif + } + + public XmlSchema GetSchema() + { + return null; + } + + public void ReadXml( XmlReader reader ) + { + reader.MoveToContent(); + if( reader.IsEmptyElement ) + { + reader.Read(); + return; + } + + Orientation orientation; + var layoutPanelElements = this.ReadRootPanel( reader, out orientation ); + if( layoutPanelElements != null ) + { + this.RootPanel = new LayoutPanel() { Orientation = orientation }; + //Add all children to RootPanel + for( int i = 0; i < layoutPanelElements.Count; ++i ) + { + this.RootPanel.Children.Add( layoutPanelElements[ i ] ); } + } + + this.TopSide = new LayoutAnchorSide(); + if( this.ReadElement( reader ) != null ) + { + this.FillLayoutAnchorSide( reader, TopSide ); + } + this.RightSide = new LayoutAnchorSide(); + if( this.ReadElement( reader ) != null ) + { + this.FillLayoutAnchorSide( reader, RightSide ); + } + this.LeftSide = new LayoutAnchorSide(); + if( this.ReadElement( reader ) != null ) + { + this.FillLayoutAnchorSide( reader, LeftSide ); + } + this.BottomSide = new LayoutAnchorSide(); + if( this.ReadElement( reader ) != null ) + { + this.FillLayoutAnchorSide( reader, BottomSide ); + } + + this.FloatingWindows.Clear(); + var floatingWindows = this.ReadElementList( reader, true ); + foreach( var floatingWindow in floatingWindows ) + { + this.FloatingWindows.Add( ( LayoutFloatingWindow )floatingWindow ); + } + + this.Hidden.Clear(); + var hidden = this.ReadElementList( reader, false ); + foreach( var hiddenObject in hidden ) + { + this.Hidden.Add( ( LayoutAnchorable )hiddenObject ); + } + } - #endregion + public void WriteXml( XmlWriter writer ) + { + writer.WriteStartElement( "RootPanel" ); + if( this.RootPanel != null ) + { + this.RootPanel.WriteXml( writer ); + } + writer.WriteEndElement(); + + writer.WriteStartElement( "TopSide" ); + if( this.TopSide != null ) + { + this.TopSide.WriteXml( writer ); + } + writer.WriteEndElement(); + + writer.WriteStartElement( "RightSide" ); + if( this.RightSide != null ) + { + this.RightSide.WriteXml( writer ); + } + writer.WriteEndElement(); + + writer.WriteStartElement( "LeftSide" ); + if( this.LeftSide != null ) + { + this.LeftSide.WriteXml( writer ); + } + writer.WriteEndElement(); + + writer.WriteStartElement( "BottomSide" ); + if( this.BottomSide != null ) + { + this.BottomSide.WriteXml( writer ); + } + writer.WriteEndElement(); + + // Write all floating windows (can be LayoutDocumentFloatingWindow or LayoutAnchorableFloatingWindow). + // To prevent "can not create instance of abstract type", the type is retrieved with GetType().Name + writer.WriteStartElement( "FloatingWindows" ); + foreach( var layoutFloatingWindow in FloatingWindows ) + { + writer.WriteStartElement( layoutFloatingWindow.GetType().Name ); + layoutFloatingWindow.WriteXml( writer ); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteStartElement( "Hidden" ); + foreach( var layoutAnchorable in Hidden ) + { + writer.WriteStartElement( layoutAnchorable.GetType().Name ); + layoutAnchorable.WriteXml( writer ); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } - public event EventHandler Updated; + #endregion - internal void FireLayoutUpdated() + #region Internal Methods + + internal static Type FindType( string name ) + { + foreach( var assembly in AppDomain.CurrentDomain.GetAssemblies() ) + { + foreach( var type in assembly.GetTypes() ) { - if (Updated != null) - Updated(this, EventArgs.Empty); + if( type.Name.Equals( name ) ) + return type; } + } + return null; + } - #region LayoutElement Added/Removed events + internal void FireLayoutUpdated() + { + if( Updated != null ) + Updated( this, EventArgs.Empty ); + } + + internal void OnLayoutElementAdded( LayoutElement element ) + { + if( ElementAdded != null ) + ElementAdded( this, new LayoutElementEventArgs( element ) ); + } + + internal void OnLayoutElementRemoved( LayoutElement element ) + { + if( element.Descendents().OfType().Any( c => c == LastFocusedDocument ) ) + LastFocusedDocument = null; + if( element.Descendents().OfType().Any( c => c == ActiveContent ) ) + ActiveContent = null; + if( ElementRemoved != null ) + ElementRemoved( this, new LayoutElementEventArgs( element ) ); + } - internal void OnLayoutElementAdded(LayoutElement element) + #endregion + + #region Private Methods + + private void _floatingWindows_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e ) + { + if( e.OldItems != null && ( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) ) + { + foreach( LayoutFloatingWindow element in e.OldItems ) { - if (ElementAdded != null) - ElementAdded(this, new LayoutElementEventArgs(element)); + if( element.Parent == this ) + element.Parent = null; } + } + + if( e.NewItems != null && ( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) ) + { + foreach( LayoutFloatingWindow element in e.NewItems ) + element.Parent = this; + } + } - public event EventHandler ElementAdded; + private void _hiddenAnchorables_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e ) + { + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) + { + if( e.OldItems != null ) + { + foreach( LayoutAnchorable element in e.OldItems ) + { + if( element.Parent == this ) + element.Parent = null; + } + } + } - internal void OnLayoutElementRemoved(LayoutElement element) + if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || + e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) + { + if( e.NewItems != null ) { - if (element.Descendents().OfType().Any(c => c == LastFocusedDocument)) - LastFocusedDocument = null; - if (element.Descendents().OfType().Any(c => c == ActiveContent)) - ActiveContent = null; - if (ElementRemoved != null) - ElementRemoved(this, new LayoutElementEventArgs(element)); + foreach( LayoutAnchorable element in e.NewItems ) + { + if( element.Parent != this ) + { + if( element.Parent != null ) + element.Parent.RemoveChild( element ); + element.Parent = this; + } + + } } + } - public event EventHandler ElementRemoved; - #endregion -#if TRACE - public override void ConsoleDump(int tab) + } + + private void InternalSetActiveContent( LayoutContent currentValue, LayoutContent newActiveContent ) + { + RaisePropertyChanging( "ActiveContent" ); + if( currentValue != null ) + currentValue.IsActive = false; + _activeContent = new WeakReference( newActiveContent ); + currentValue = ActiveContent; + if( currentValue != null ) + currentValue.IsActive = true; + RaisePropertyChanged( "ActiveContent" ); + _activeContentSet = currentValue != null; + if( currentValue != null ) + { + if( currentValue.Parent is LayoutDocumentPane || currentValue is LayoutDocument ) + LastFocusedDocument = currentValue; + } + else + LastFocusedDocument = null; + } + + private void UpdateActiveContentProperty() + { + var activeContent = ActiveContent; + if( _activeContentSet && ( activeContent == null || activeContent.Root != this ) ) + { + _activeContentSet = false; + InternalSetActiveContent( activeContent, null ); + } + } + + private void FillLayoutAnchorSide( XmlReader reader, LayoutAnchorSide layoutAnchorSide ) + { + var result = new List(); + + while( true ) + { + //Read all layoutAnchorSide children + var element = ReadElement( reader ) as LayoutAnchorGroup; + if( element != null ) { - System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) ); - System.Diagnostics.Trace.WriteLine( "RootPanel()" ); + result.Add( element ); + } + else if( reader.NodeType == XmlNodeType.EndElement ) + { + break; + } + } - RootPanel.ConsoleDump(tab + 1); + reader.ReadEndElement(); + foreach( var las in result ) + { + layoutAnchorSide.Children.Add( las ); + } + } - System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) ); - System.Diagnostics.Trace.WriteLine( "FloatingWindows()" ); + private List ReadRootPanel( XmlReader reader, out Orientation orientation ) + { + orientation = Orientation.Horizontal; + var result = new List(); + + var startElementName = reader.LocalName; + reader.Read(); + if( reader.LocalName.Equals( startElementName ) && ( reader.NodeType == XmlNodeType.EndElement ) ) + { + return null; + } + + while( reader.NodeType == XmlNodeType.Whitespace ) + { + reader.Read(); + } + + if( reader.LocalName.Equals( "RootPanel" ) ) + { + orientation = (reader.GetAttribute( "Orientation" ) == "Vertical") ? Orientation.Vertical : Orientation.Horizontal; + reader.Read(); + + while( true ) + { + //Read all RootPanel children + var element = ReadElement( reader ) as ILayoutPanelElement; + if( element != null ) + { + result.Add( element ); + } + else if( reader.NodeType == XmlNodeType.EndElement ) + { + break; + } + } + } - foreach (LayoutFloatingWindow fw in FloatingWindows) - fw.ConsoleDump(tab + 1); + reader.ReadEndElement(); - System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) ); - System.Diagnostics.Trace.WriteLine( "Hidden()" ); + return result; + } - foreach (LayoutAnchorable hidden in Hidden) - hidden.ConsoleDump(tab + 1); + private List ReadElementList( XmlReader reader, bool isFloatingWindow ) + { + var resultList = new List(); + + while( reader.NodeType == XmlNodeType.Whitespace ) + { + reader.Read(); + } + + if( reader.IsEmptyElement ) + { + reader.Read(); + return resultList; + } + + var startElementName = reader.LocalName; + reader.Read(); + if( reader.LocalName.Equals( startElementName ) && ( reader.NodeType == XmlNodeType.EndElement ) ) + { + return null; + } + + while( reader.NodeType == XmlNodeType.Whitespace ) + { + reader.Read(); + } + + while( true ) + { + if( isFloatingWindow ) + { + var result = this.ReadElement( reader ) as LayoutFloatingWindow; + if( result == null ) + { + break; + } + resultList.Add( result ); } -#endif + else + { + var result = this.ReadElement( reader ) as LayoutAnchorable; + if( result == null ) + { + break; + } + resultList.Add( result ); + } + } + reader.ReadEndElement(); + return resultList; } + + private object ReadElement( XmlReader reader ) + { + while( reader.NodeType == XmlNodeType.Whitespace ) + { + reader.Read(); + } + + if( reader.NodeType == XmlNodeType.EndElement ) + { + return null; + } + + XmlSerializer serializer; + switch( reader.LocalName ) + { + case "LayoutAnchorablePaneGroup": + serializer = new XmlSerializer( typeof( LayoutAnchorablePaneGroup ) ); + break; + case "LayoutAnchorablePane": + serializer = new XmlSerializer( typeof( LayoutAnchorablePane ) ); + break; + case "LayoutAnchorable": + serializer = new XmlSerializer( typeof( LayoutAnchorable ) ); + break; + case "LayoutDocumentPaneGroup": + serializer = new XmlSerializer( typeof( LayoutDocumentPaneGroup ) ); + break; + case "LayoutDocumentPane": + serializer = new XmlSerializer( typeof( LayoutDocumentPane ) ); + break; + case "LayoutDocument": + serializer = new XmlSerializer( typeof( LayoutDocument ) ); + break; + case "LayoutAnchorGroup": + serializer = new XmlSerializer( typeof( LayoutAnchorGroup ) ); + break; + case "LayoutPanel": + serializer = new XmlSerializer( typeof( LayoutPanel ) ); + break; + case "LayoutDocumentFloatingWindow": + serializer = new XmlSerializer( typeof( LayoutDocumentFloatingWindow ) ); + break; + case "LayoutAnchorableFloatingWindow": + serializer = new XmlSerializer( typeof( LayoutAnchorableFloatingWindow ) ); + break; + case "LeftSide": + case "RightSide": + case "TopSide": + case "BottomSide": + if( reader.IsEmptyElement ) + { + reader.Read(); + return null; + } + return reader.Read(); + default: + var type = LayoutRoot.FindType( reader.LocalName ); + if( type == null ) + { + throw new ArgumentException( "AvalonDock.LayoutRoot doesn't know how to deserialize " + reader.LocalName ); + } + serializer = new XmlSerializer( type ); + break; + } + + return serializer.Deserialize( reader ); + } + + #endregion + + #region Events + + public event EventHandler Updated; + public event EventHandler ElementAdded; + public event EventHandler ElementRemoved; + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/LayoutSerializationCallbackEventArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/LayoutSerializationCallbackEventArgs.cs index 554e2964..24ceb24b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/LayoutSerializationCallbackEventArgs.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/LayoutSerializationCallbackEventArgs.cs @@ -14,25 +14,35 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.ComponentModel; namespace Xceed.Wpf.AvalonDock.Layout.Serialization { - public class LayoutSerializationCallbackEventArgs : CancelEventArgs + public class LayoutSerializationCallbackEventArgs : CancelEventArgs + { + #region constructor + + public LayoutSerializationCallbackEventArgs( LayoutContent model, object previousContent ) { - public LayoutSerializationCallbackEventArgs(LayoutContent model, object previousContent) - { - Cancel = false; - Model = model; - Content = previousContent; - } + Cancel = false; + Model = model; + Content = previousContent; + } + + #endregion + + #region Properties - public LayoutContent Model { get; private set; } + public LayoutContent Model + { + get; private set; + } - public object Content { get; set; } + public object Content + { + get; set; } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/LayoutSerializer.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/LayoutSerializer.cs index 5b9a2d66..ede976fd 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/LayoutSerializer.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/LayoutSerializer.cs @@ -15,119 +15,136 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.IO; -using Xceed.Wpf.AvalonDock.Controls; -using System.Windows; namespace Xceed.Wpf.AvalonDock.Layout.Serialization { - public abstract class LayoutSerializer + public abstract class LayoutSerializer + { + #region Members + + private DockingManager _manager; + private LayoutAnchorable[] _previousAnchorables = null; + private LayoutDocument[] _previousDocuments = null; + + #endregion + + #region Constructors + + public LayoutSerializer( DockingManager manager ) { - DockingManager _manager; + if( manager == null ) + throw new ArgumentNullException( "manager" ); - public LayoutSerializer(DockingManager manager) - { - if (manager == null) - throw new ArgumentNullException("manager"); + _manager = manager; + _previousAnchorables = _manager.Layout.Descendents().OfType().ToArray(); + _previousDocuments = _manager.Layout.Descendents().OfType().ToArray(); + } - _manager = manager; - _previousAnchorables = _manager.Layout.Descendents().OfType().ToArray(); - _previousDocuments = _manager.Layout.Descendents().OfType().ToArray(); - } + #endregion + + #region Properties + + public DockingManager Manager + { + get + { + return _manager; + } + } + + #endregion + + #region Events + + public event EventHandler LayoutSerializationCallback; + + #endregion - LayoutAnchorable[] _previousAnchorables = null; - LayoutDocument[] _previousDocuments = null; + #region Methods - public DockingManager Manager + protected virtual void FixupLayout( LayoutRoot layout ) + { + //fix container panes + foreach( var lcToAttach in layout.Descendents().OfType().Where( lc => lc.PreviousContainerId != null ) ) + { + var paneContainerToAttach = layout.Descendents().OfType().FirstOrDefault( lps => lps.Id == lcToAttach.PreviousContainerId ); + if( paneContainerToAttach == null ) + throw new ArgumentException( string.Format( "Unable to find a pane with id ='{0}'", lcToAttach.PreviousContainerId ) ); + + lcToAttach.PreviousContainer = paneContainerToAttach as ILayoutContainer; + } + + + //now fix the content of the layoutcontents + foreach( var lcToFix in layout.Descendents().OfType().Where( lc => lc.Content == null ).ToArray() ) + { + LayoutAnchorable previousAchorable = null; + if( lcToFix.ContentId != null ) + { + //try find the content in replaced layout + previousAchorable = _previousAnchorables.FirstOrDefault( a => a.ContentId == lcToFix.ContentId ); + } + + if( LayoutSerializationCallback != null ) { - get { return _manager; } + var args = new LayoutSerializationCallbackEventArgs( lcToFix, previousAchorable != null ? previousAchorable.Content : null ); + LayoutSerializationCallback( this, args ); + if( args.Cancel ) + lcToFix.Close(); + else if( args.Content != null ) + lcToFix.Content = args.Content; + else if( args.Model.Content != null ) + lcToFix.Hide( false ); } + else if( previousAchorable == null ) + lcToFix.Hide( false ); + else + { + lcToFix.Content = previousAchorable.Content; + lcToFix.IconSource = previousAchorable.IconSource; + } + } - public event EventHandler LayoutSerializationCallback; - protected virtual void FixupLayout(LayoutRoot layout) + foreach( var lcToFix in layout.Descendents().OfType().Where( lc => lc.Content == null ).ToArray() ) + { + LayoutDocument previousDocument = null; + if( lcToFix.ContentId != null ) { - //fix container panes - foreach (var lcToAttach in layout.Descendents().OfType().Where(lc => lc.PreviousContainerId != null)) - { - var paneContainerToAttach = layout.Descendents().OfType().FirstOrDefault(lps => lps.Id == lcToAttach.PreviousContainerId); - if (paneContainerToAttach == null) - throw new ArgumentException(string.Format("Unable to find a pane with id ='{0}'", lcToAttach.PreviousContainerId)); - - lcToAttach.PreviousContainer = paneContainerToAttach as ILayoutContainer; - } - - - //now fix the content of the layoutcontents - foreach (var lcToFix in layout.Descendents().OfType().Where(lc => lc.Content == null).ToArray()) - { - LayoutAnchorable previousAchorable = null; - if (lcToFix.ContentId != null) - { - //try find the content in replaced layout - previousAchorable = _previousAnchorables.FirstOrDefault(a => a.ContentId == lcToFix.ContentId); - } - - if (LayoutSerializationCallback != null) - { - var args = new LayoutSerializationCallbackEventArgs(lcToFix, previousAchorable != null ? previousAchorable.Content : null); - LayoutSerializationCallback(this, args); - if (args.Cancel) - lcToFix.Close(); - else if (args.Content != null) - lcToFix.Content = args.Content; - else if (args.Model.Content != null) - lcToFix.Hide(false); - } - else if (previousAchorable == null) - lcToFix.Hide(false); - else - { - lcToFix.Content = previousAchorable.Content; - lcToFix.IconSource = previousAchorable.IconSource; - } - } - - - foreach (var lcToFix in layout.Descendents().OfType().Where(lc => lc.Content == null).ToArray()) - { - LayoutDocument previousDocument = null; - if (lcToFix.ContentId != null) - { - //try find the content in replaced layout - previousDocument = _previousDocuments.FirstOrDefault(a => a.ContentId == lcToFix.ContentId); - } - - if (LayoutSerializationCallback != null) - { - var args = new LayoutSerializationCallbackEventArgs(lcToFix, previousDocument != null ? previousDocument.Content : null); - LayoutSerializationCallback(this, args); - - if (args.Cancel) - lcToFix.Close(); - else if (args.Content != null) - lcToFix.Content = args.Content; - else if (args.Model.Content != null) - lcToFix.Close(); - } - else if (previousDocument == null) - lcToFix.Close(); - else - lcToFix.Content = previousDocument.Content; - } - - - layout.CollectGarbage(); + //try find the content in replaced layout + previousDocument = _previousDocuments.FirstOrDefault( a => a.ContentId == lcToFix.ContentId ); } - protected void StartDeserialization() + if( LayoutSerializationCallback != null ) + { + var args = new LayoutSerializationCallbackEventArgs( lcToFix, previousDocument != null ? previousDocument.Content : null ); + LayoutSerializationCallback( this, args ); + + if( args.Cancel ) + lcToFix.Close(); + else if( args.Content != null ) + lcToFix.Content = args.Content; + else if( args.Model.Content != null ) + lcToFix.Close(); + } + else if( previousDocument == null ) + lcToFix.Close(); + else { - Manager.SuspendDocumentsSourceBinding = true; - Manager.SuspendAnchorablesSourceBinding = true; + lcToFix.Content = previousDocument.Content; + lcToFix.IconSource = previousDocument.IconSource; } + } + + layout.CollectGarbage(); + } + + protected void StartDeserialization() + { + Manager.SuspendDocumentsSourceBinding = true; + Manager.SuspendAnchorablesSourceBinding = true; + } protected void EndDeserialization() { @@ -135,33 +152,6 @@ namespace Xceed.Wpf.AvalonDock.Layout.Serialization Manager.SuspendAnchorablesSourceBinding = false; } - #region Virtual Serialize and Deserialize methods - - public virtual void Serialize(System.Xml.XmlWriter writer) - { - } - public virtual void Serialize(System.IO.TextWriter writer) - { - } - public virtual void Serialize(System.IO.Stream stream) - { - } - public virtual void Serialize(string filepath) - { - } - public virtual void Deserialize(System.IO.Stream stream) - { - } - public virtual void Deserialize(System.IO.TextReader reader) - { - } - public virtual void Deserialize(System.Xml.XmlReader reader) - { - } - public virtual void Deserialize(string filepath) - { - } - #endregion - } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/XmlLayoutSerializer.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/XmlLayoutSerializer.cs index 16a01876..05d3321e 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/XmlLayoutSerializer.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/Serialization/XmlLayoutSerializer.cs @@ -14,97 +14,102 @@ ***********************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Xml.Serialization; using System.IO; namespace Xceed.Wpf.AvalonDock.Layout.Serialization { - public class XmlLayoutSerializer : LayoutSerializer + public class XmlLayoutSerializer : LayoutSerializer + { + #region Constructors + + public XmlLayoutSerializer( DockingManager manager ) + : base( manager ) + { + } + + #endregion + + #region Public Methods + + public void Serialize( System.Xml.XmlWriter writer ) + { + var serializer = new XmlSerializer( typeof( LayoutRoot ) ); + serializer.Serialize( writer, Manager.Layout ); + } + + public void Serialize( System.IO.TextWriter writer ) + { + var serializer = new XmlSerializer( typeof( LayoutRoot ) ); + serializer.Serialize( writer, Manager.Layout ); + } + + public void Serialize( System.IO.Stream stream ) + { + var serializer = new XmlSerializer( typeof( LayoutRoot ) ); + serializer.Serialize( stream, Manager.Layout ); + } + + public void Serialize( string filepath ) + { + using( var stream = new StreamWriter( filepath ) ) + Serialize( stream ); + } + + public void Deserialize( System.IO.Stream stream ) + { + try + { + StartDeserialization(); + var serializer = new XmlSerializer( typeof( LayoutRoot ) ); + var layout = serializer.Deserialize( stream ) as LayoutRoot; + FixupLayout( layout ); + Manager.Layout = layout; + } + finally + { + EndDeserialization(); + } + } + + public void Deserialize( System.IO.TextReader reader ) { - public XmlLayoutSerializer(DockingManager manager) - : base(manager) - { - - } - - public override void Serialize(System.Xml.XmlWriter writer) - { - var serializer = new XmlSerializer(typeof(LayoutRoot)); - serializer.Serialize(writer, Manager.Layout); - } - public override void Serialize(System.IO.TextWriter writer) - { - var serializer = new XmlSerializer(typeof(LayoutRoot)); - serializer.Serialize(writer, Manager.Layout); - } - public override void Serialize(System.IO.Stream stream) - { - var serializer = new XmlSerializer(typeof(LayoutRoot)); - serializer.Serialize(stream, Manager.Layout); - } - - public override void Serialize(string filepath) - { - using (var stream = new StreamWriter(filepath)) - Serialize(stream); - } - - public override void Deserialize(System.IO.Stream stream) - { - try - { - StartDeserialization(); - var serializer = new XmlSerializer(typeof(LayoutRoot)); - var layout = serializer.Deserialize(stream) as LayoutRoot; - FixupLayout(layout); - Manager.Layout = layout; - } - finally - { - EndDeserialization(); - } - } - - public override void Deserialize(System.IO.TextReader reader) - { - try - { - StartDeserialization(); - var serializer = new XmlSerializer(typeof(LayoutRoot)); - var layout = serializer.Deserialize(reader) as LayoutRoot; - FixupLayout(layout); - Manager.Layout = layout; - } - finally - { - EndDeserialization(); - } - } - - public override void Deserialize(System.Xml.XmlReader reader) - { - try - { - StartDeserialization(); - var serializer = new XmlSerializer(typeof(LayoutRoot)); - var layout = serializer.Deserialize(reader) as LayoutRoot; - FixupLayout(layout); - Manager.Layout = layout; - } - finally - { - EndDeserialization(); - } - } - - public override void Deserialize(string filepath) - { - using (var stream = new StreamReader(filepath)) - Deserialize(stream); - } + try + { + StartDeserialization(); + var serializer = new XmlSerializer( typeof( LayoutRoot ) ); + var layout = serializer.Deserialize( reader ) as LayoutRoot; + FixupLayout( layout ); + Manager.Layout = layout; + } + finally + { + EndDeserialization(); + } } + + public void Deserialize( System.Xml.XmlReader reader ) + { + try + { + StartDeserialization(); + var serializer = new XmlSerializer( typeof( LayoutRoot ) ); + var layout = serializer.Deserialize( reader ) as LayoutRoot; + FixupLayout( layout ); + Manager.Layout = layout; + } + finally + { + EndDeserialization(); + } + } + + public void Deserialize( string filepath ) + { + using( var stream = new StreamReader( filepath ) ) + Deserialize( stream ); + } + + #endregion + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/LayoutEventArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/LayoutEventArgs.cs index 25a6aa5c..81201acb 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/LayoutEventArgs.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/LayoutEventArgs.cs @@ -15,24 +15,21 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using Xceed.Wpf.AvalonDock.Layout; namespace Xceed.Wpf.AvalonDock { - class LayoutEventArgs : EventArgs + class LayoutEventArgs : EventArgs + { + public LayoutEventArgs( LayoutRoot layoutRoot ) { - public LayoutEventArgs(LayoutRoot layoutRoot) - { - LayoutRoot = layoutRoot; - } - - public LayoutRoot LayoutRoot - { - get; - private set; - } + LayoutRoot = layoutRoot; } + + public LayoutRoot LayoutRoot + { + get; + private set; + } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/MathHelper.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/MathHelper.cs index 261f37fb..d059d55d 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/MathHelper.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/MathHelper.cs @@ -15,32 +15,28 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock { - internal static class MathHelper + internal static class MathHelper + { + public static double MinMax( double value, double min, double max ) { + if( min > max ) + throw new ArgumentException( "min>max" ); - public static double MinMax(double value, double min, double max) - { - if (min > max) - throw new ArgumentException("min>max"); + if( value < min ) + return min; + if( value > max ) + return max; - if (value < min) - return min; - if (value > max) - return max; - - return value; - } + return value; + } - public static void AssertIsPositiveOrZero(double value) - { - if (value < 0.0) - throw new ArgumentException("Invalid value, must be a positive number or equal to zero"); - } + public static void AssertIsPositiveOrZero( double value ) + { + if( value < 0.0 ) + throw new ArgumentException( "Invalid value, must be a positive number or equal to zero" ); } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/AssemblyInfo.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/AssemblyInfo.cs index 0c7fe702..3800cc83 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/AssemblyInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/AssemblyInfo.cs @@ -25,12 +25,12 @@ using System; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle( "Xceed Extended WPF Toolkit - AvalonDock" )] +[assembly: AssemblyTitle( "Xceed Toolkit for WPF - AvalonDock" )] [assembly: AssemblyDescription( "This assembly implements the Xceed.Wpf.AvalonDock namespace, a docking layout system for the Windows Presentation Framework." )] [assembly: AssemblyCompany( "Xceed Software Inc." )] -[assembly: AssemblyProduct( "Xceed Extended WPF Toolkit - AvalonDock" )] -[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2007-2013" )] +[assembly: AssemblyProduct( "Xceed Toolkit for WPF - AvalonDock" )] +[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2007-2017" )] [assembly: AssemblyCulture( "" )] @@ -52,7 +52,7 @@ using System; [assembly: ThemeInfo( - ResourceDictionaryLocation.SourceAssembly, //where theme specific resource dictionaries are located + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located //(used if a resource is not found in the page, // or application resource dictionaries) ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.Designer.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.Designer.cs index 92766506..620c95db 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.Designer.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.Designer.cs @@ -17,7 +17,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.296 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -140,7 +140,7 @@ namespace Xceed.Wpf.AvalonDock.Properties { } /// - /// Looks up a localized string similar to Close. + /// Looks up a localized string similar to Hide. /// public static string Anchorable_Hide { get { @@ -148,6 +148,15 @@ namespace Xceed.Wpf.AvalonDock.Properties { } } + /// + /// Looks up a localized string similar to Toggle Pin status. + /// + public static string Document_BtnPinned_Hint { + get { + return ResourceManager.GetString("Document_BtnPinned_Hint", resourceCulture); + } + } + /// /// Looks up a localized string similar to Close. /// @@ -157,6 +166,15 @@ namespace Xceed.Wpf.AvalonDock.Properties { } } + /// + /// Looks up a localized string similar to Close All. + /// + public static string Document_CloseAll { + get { + return ResourceManager.GetString("Document_CloseAll", resourceCulture); + } + } + /// /// Looks up a localized string similar to Close All But This. /// diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.de.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.de.resx index aa2df0fc..b0800844 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.de.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.de.resx @@ -1,103 +1,122 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Automatisch im Hintergrund @@ -122,9 +141,15 @@ Schließen + + Pin-Status umschalten + Schließen + + Schließen Sie alle + Alle ausser diesem schließen @@ -154,6 +179,5 @@ Wiederherstellen - - + \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.es.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.es.resx index 5403ddcc..9b2cf65c 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.es.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.es.resx @@ -1,105 +1,123 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Esconder Automáticamente @@ -121,11 +139,17 @@ Ventana Flotante - Cerrar + Esconder + + + Activar el estado del pin Cerrar + + Cerca de todo + Cerrar Todo, Pero Este @@ -156,5 +180,4 @@ Restaurar - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.fr.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.fr.resx index 5e50b1a5..8acbf362 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.fr.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.fr.resx @@ -1,159 +1,183 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Cacher Automatiquement - - - Cacher Automatiquement - - - Cacher - - - Position de la Fenêtre - - - Ancrer - - - Ancrer comme Onglet de Document - - - Flottante - - - Fermer - - - Fermer - - - Fermer Tout Sauf Ceci - - - Position de la Fenêtre - - - Ancrer Comme Onglet de Document - - - Flottante - - - Déplacer Vers Le Groupe d'Onglets Suivant - - - Déplacer Vers Le Groupe d'Onglets Précédent - - - Nouveau Groupe d'Onglets Horizontal - - - Nouveau Groupe d'Onglets Vertical - - - Plein Écran - - - Restaurer - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Cacher Automatiquement + + + Cacher Automatiquement + + + Cacher + + + Position de la Fenêtre + + + Ancrer + + + Ancrer comme Onglet de Document + + + Flottante + + + Cacher + + + Ancrer / désancrer + + + Fermer + + + Fermer tout + + + Fermer Tout Sauf Ceci + + + Position de la Fenêtre + + + Ancrer Comme Onglet de Document + + + Flottante + + + Déplacer Vers Le Groupe d'Onglets Suivant + + + Déplacer Vers Le Groupe d'Onglets Précédent + + + Nouveau Groupe d'Onglets Horizontal + + + Nouveau Groupe d'Onglets Vertical + + + Plein Écran + + + Restaurer + \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.hu.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.hu.resx index 57cf54bd..54d0bcae 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.hu.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.hu.resx @@ -1,103 +1,122 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Automatikus elrejtés @@ -122,9 +141,15 @@ Elrejtés + + Toggle Pin állapot + Bezárás + + Zárjon be minden + Ennek kivételével az összes bezárása diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.it.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.it.resx index 886be28e..d72bc67a 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.it.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.it.resx @@ -139,11 +139,17 @@ Finestra Mobile - Chiudi + Nascondi + + + Stato Toggle Pin Chiudi + + Chiudere tutte le + Chiudi Tutti Tranne Questo diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.pt-BR.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.pt-BR.resx index f34cf1e8..5e2b95aa 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.pt-BR.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.pt-BR.resx @@ -1,103 +1,122 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Esconder Automaticamente @@ -120,11 +139,14 @@ Flutuar - Fechar + Esconder Fechar + + Feche todos os + Fechar Todos Menos Este @@ -155,4 +177,4 @@ Recuperar - \ No newline at end of file + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.resx index 0a2edd6c..67b1d132 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.resx @@ -139,11 +139,17 @@ Float - Close + Hide + + + Toggle Pin status Close + + Close All + Close All But This diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.ro.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.ro.resx index 3df62322..db258c18 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.ro.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.ro.resx @@ -1,103 +1,122 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Ascunde automat @@ -120,11 +139,17 @@ Plutește - Închide + Ascunde + + + Starea de comutare Pin Închide + + Aproape toate + Închide tot fără documentul curent @@ -155,5 +180,4 @@ Restaurează - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.ru.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.ru.resx index 37850c46..247500ec 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.ru.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.ru.resx @@ -1,103 +1,122 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Скрывать Автоматически @@ -120,11 +139,17 @@ Отсоединить - Закрыть + Скрыть + + + Статус Переключение Pin Закрыть + + Закрыть все + Закрыть Все кроме Этого diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.sv.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.sv.resx index df40f57a..cccac740 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.sv.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.sv.resx @@ -1,103 +1,122 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Dölj automatiskt @@ -120,11 +139,17 @@ Koppla loss - Stäng + Dölj + + + Toggle Pin status Stäng + + Stäng alla + Stäng alla andra diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.zh-Hans.resx b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.zh-Hans.resx index 0ecbde1d..9cc57795 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.zh-Hans.resx +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Properties/Resources.zh-Hans.resx @@ -1,103 +1,122 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 自动隐藏 @@ -120,11 +139,17 @@ 漂浮 - 关闭 + 隐藏 + + + 切換引腳狀態 关闭 + + 關閉所有 + 留此,关闭其他 @@ -155,5 +180,4 @@ 恢复 - \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/DictionaryTheme.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/DictionaryTheme.cs new file mode 100644 index 00000000..6857768b --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/DictionaryTheme.cs @@ -0,0 +1,56 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Windows; + +namespace Xceed.Wpf.AvalonDock.Themes +{ + public abstract class DictionaryTheme : Theme + { + #region Constructors + + public DictionaryTheme() + { + } + + public DictionaryTheme( ResourceDictionary themeResourceDictionary ) + { + this.ThemeResourceDictionary = themeResourceDictionary; + } + + #endregion + + #region Properties + + public ResourceDictionary ThemeResourceDictionary + { + get; + private set; + } + + #endregion + + #region Overrides + + public override Uri GetResourceUri() + { + return null; + } + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/GenericTheme.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/GenericTheme.cs index cdcb007e..857cd20c 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/GenericTheme.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/GenericTheme.cs @@ -15,9 +15,6 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Xceed.Wpf.AvalonDock.Themes { @@ -25,9 +22,7 @@ namespace Xceed.Wpf.AvalonDock.Themes { public override Uri GetResourceUri() { - return new Uri( - "/Xceed.Wpf.AvalonDock;component/Themes/generic.xaml", - UriKind.Relative ); + return new Uri( "/Xceed.Wpf.AvalonDock;component/Themes/generic.xaml", UriKind.Relative ); } } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/Theme.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/Theme.cs index dabd93c2..88abbfc0 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/Theme.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/Theme.cs @@ -15,22 +15,16 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; namespace Xceed.Wpf.AvalonDock.Themes { - public abstract class Theme : DependencyObject + public abstract class Theme : DependencyObject + { + public Theme() { - public Theme() - { - - } - - public abstract Uri GetResourceUri(); - - } + + public abstract Uri GetResourceUri(); + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/generic.xaml b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/generic.xaml index 0c87ada5..89dab4dd 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/generic.xaml @@ -21,482 +21,791 @@ xmlns:avalonDockLayout="clr-namespace:Xceed.Wpf.AvalonDock.Layout" xmlns:avalonDockControls="clr-namespace:Xceed.Wpf.AvalonDock.Controls" xmlns:avalonDockConverters="clr-namespace:Xceed.Wpf.AvalonDock.Converters" - xmlns:avalonDockProperties="clr-namespace:Xceed.Wpf.AvalonDock.Properties" - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:avalonDockProperties="clr-namespace:Xceed.Wpf.AvalonDock.Properties"> - - - - - - - - + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + - + + + + + - + + + + + - + + + + + + + + - + + + + + + - + + + + + + - + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + - + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Win32Helper.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Win32Helper.cs index 63f3b9a7..2106dd9b 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Win32Helper.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Win32Helper.cs @@ -15,451 +15,479 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Runtime.InteropServices; using System.Windows; namespace Xceed.Wpf.AvalonDock { - internal static class Win32Helper + internal static class Win32Helper + { + [DllImport( "user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode )] + internal static extern IntPtr CreateWindowEx( int dwExStyle, + string lpszClassName, + string lpszWindowName, + int style, + int x, int y, + int width, int height, + IntPtr hwndParent, + IntPtr hMenu, + IntPtr hInst, + [MarshalAs( UnmanagedType.AsAny )] object pvParam ); + internal const int + WS_CHILD = 0x40000000, + WS_VISIBLE = 0x10000000, + WS_VSCROLL = 0x00200000, + WS_BORDER = 0x00800000, + WS_CLIPSIBLINGS = 0x04000000, + WS_CLIPCHILDREN = 0x02000000, + WS_TABSTOP = 0x00010000, + WS_GROUP = 0x00020000; + + + /// + /// SetWindowPos Flags + /// + [Flags()] + internal enum SetWindowPosFlags : uint { - [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)] - internal static extern IntPtr CreateWindowEx(int dwExStyle, - string lpszClassName, - string lpszWindowName, - int style, - int x, int y, - int width, int height, - IntPtr hwndParent, - IntPtr hMenu, - IntPtr hInst, - [MarshalAs(UnmanagedType.AsAny)] object pvParam); - internal const int - WS_CHILD = 0x40000000, - WS_VISIBLE = 0x10000000, - WS_VSCROLL = 0x00200000, - WS_BORDER = 0x00800000, - WS_CLIPSIBLINGS = 0x04000000, - WS_CLIPCHILDREN = 0x02000000, - WS_TABSTOP = 0x00010000, - WS_GROUP = 0x00020000; - - - /// - /// SetWindowPos Flags - /// - [Flags()] - internal enum SetWindowPosFlags : uint - { - /// If the calling thread and the thread that owns the window are attached to different input queues, - /// the system posts the request to the thread that owns the window. This prevents the calling thread from - /// blocking its execution while other threads process the request. - /// SWP_ASYNCWINDOWPOS - SynchronousWindowPosition = 0x4000, - /// Prevents generation of the WM_SYNCPAINT message. - /// SWP_DEFERERASE - DeferErase = 0x2000, - /// Draws a frame (defined in the window's class description) around the window. - /// SWP_DRAWFRAME - DrawFrame = 0x0020, - /// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to - /// the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE - /// is sent only when the window's size is being changed. - /// SWP_FRAMECHANGED - FrameChanged = 0x0020, - /// Hides the window. - /// SWP_HIDEWINDOW - HideWindow = 0x0080, - /// Does not activate the window. If this flag is not set, the window is activated and moved to the - /// top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter - /// parameter). - /// SWP_NOACTIVATE - DoNotActivate = 0x0010, - /// Discards the entire contents of the client area. If this flag is not specified, the valid - /// contents of the client area are saved and copied back into the client area after the window is sized or - /// repositioned. - /// SWP_NOCOPYBITS - DoNotCopyBits = 0x0100, - /// Retains the current position (ignores X and Y parameters). - /// SWP_NOMOVE - IgnoreMove = 0x0002, - /// Does not change the owner window's position in the Z order. - /// SWP_NOOWNERZORDER - DoNotChangeOwnerZOrder = 0x0200, - /// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to - /// the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent - /// window uncovered as a result of the window being moved. When this flag is set, the application must - /// explicitly invalidate or redraw any parts of the window and parent window that need redrawing. - /// SWP_NOREDRAW - DoNotRedraw = 0x0008, - /// Same as the SWP_NOOWNERZORDER flag. - /// SWP_NOREPOSITION - DoNotReposition = 0x0200, - /// Prevents the window from receiving the WM_WINDOWPOSCHANGING message. - /// SWP_NOSENDCHANGING - DoNotSendChangingEvent = 0x0400, - /// Retains the current size (ignores the cx and cy parameters). - /// SWP_NOSIZE - IgnoreResize = 0x0001, - /// Retains the current Z order (ignores the hWndInsertAfter parameter). - /// SWP_NOZORDER - IgnoreZOrder = 0x0004, - /// Displays the window. - /// SWP_SHOWWINDOW - ShowWindow = 0x0040, - } + /// If the calling thread and the thread that owns the window are attached to different input queues, + /// the system posts the request to the thread that owns the window. This prevents the calling thread from + /// blocking its execution while other threads process the request. + /// SWP_ASYNCWINDOWPOS + SynchronousWindowPosition = 0x4000, + /// Prevents generation of the WM_SYNCPAINT message. + /// SWP_DEFERERASE + DeferErase = 0x2000, + /// Draws a frame (defined in the window's class description) around the window. + /// SWP_DRAWFRAME + DrawFrame = 0x0020, + /// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to + /// the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE + /// is sent only when the window's size is being changed. + /// SWP_FRAMECHANGED + FrameChanged = 0x0020, + /// Hides the window. + /// SWP_HIDEWINDOW + HideWindow = 0x0080, + /// Does not activate the window. If this flag is not set, the window is activated and moved to the + /// top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter + /// parameter). + /// SWP_NOACTIVATE + DoNotActivate = 0x0010, + /// Discards the entire contents of the client area. If this flag is not specified, the valid + /// contents of the client area are saved and copied back into the client area after the window is sized or + /// repositioned. + /// SWP_NOCOPYBITS + DoNotCopyBits = 0x0100, + /// Retains the current position (ignores X and Y parameters). + /// SWP_NOMOVE + IgnoreMove = 0x0002, + /// Does not change the owner window's position in the Z order. + /// SWP_NOOWNERZORDER + DoNotChangeOwnerZOrder = 0x0200, + /// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to + /// the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent + /// window uncovered as a result of the window being moved. When this flag is set, the application must + /// explicitly invalidate or redraw any parts of the window and parent window that need redrawing. + /// SWP_NOREDRAW + DoNotRedraw = 0x0008, + /// Same as the SWP_NOOWNERZORDER flag. + /// SWP_NOREPOSITION + DoNotReposition = 0x0200, + /// Prevents the window from receiving the WM_WINDOWPOSCHANGING message. + /// SWP_NOSENDCHANGING + DoNotSendChangingEvent = 0x0400, + /// Retains the current size (ignores the cx and cy parameters). + /// SWP_NOSIZE + IgnoreResize = 0x0001, + /// Retains the current Z order (ignores the hWndInsertAfter parameter). + /// SWP_NOZORDER + IgnoreZOrder = 0x0004, + /// Displays the window. + /// SWP_SHOWWINDOW + ShowWindow = 0x0040, + } - /// - /// Special window handles - /// - internal static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); - internal static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); - internal static readonly IntPtr HWND_TOP = new IntPtr(0); - internal static readonly IntPtr HWND_BOTTOM = new IntPtr(1); + /// + /// Special window handles + /// + internal static readonly IntPtr HWND_TOPMOST = new IntPtr( -1 ); + internal static readonly IntPtr HWND_NOTOPMOST = new IntPtr( -2 ); + internal static readonly IntPtr HWND_TOP = new IntPtr( 0 ); + internal static readonly IntPtr HWND_BOTTOM = new IntPtr( 1 ); - [StructLayout(LayoutKind.Sequential)] - internal class WINDOWPOS - { - public IntPtr hwnd; - public IntPtr hwndInsertAfter; - public int x; - public int y; - public int cx; - public int cy; - public int flags; - }; - - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags); - - [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] - internal static extern bool IsChild(IntPtr hWndParent, IntPtr hwnd); - - [DllImport("user32.dll")] - internal static extern IntPtr SetFocus(IntPtr hWnd); - - internal const int WM_WINDOWPOSCHANGED = 0x0047; - internal const int WM_WINDOWPOSCHANGING = 0x0046; - internal const int WM_NCMOUSEMOVE = 0xa0; - internal const int WM_NCLBUTTONDOWN = 0xA1; - internal const int WM_NCLBUTTONUP = 0xA2; - internal const int WM_NCLBUTTONDBLCLK = 0xA3; - internal const int WM_NCRBUTTONDOWN = 0xA4; - internal const int WM_NCRBUTTONUP = 0xA5; - internal const int WM_CAPTURECHANGED = 0x0215; - internal const int WM_EXITSIZEMOVE = 0x0232; - internal const int WM_ENTERSIZEMOVE = 0x0231; - internal const int WM_MOVE = 0x0003; - internal const int WM_MOVING = 0x0216; - internal const int WM_KILLFOCUS = 0x0008; - internal const int WM_SETFOCUS = 0x0007; - internal const int WM_ACTIVATE = 0x0006; - internal const int WM_NCHITTEST = 0x0084; - internal const int WM_INITMENUPOPUP = 0x0117; - internal const int WM_KEYDOWN = 0x0100; - internal const int WM_KEYUP = 0x0101; - - internal const int WA_INACTIVE = 0x0000; - - internal const int WM_SYSCOMMAND = 0x0112; - // These are the wParam of WM_SYSCOMMAND - internal const int SC_MAXIMIZE = 0xF030; - internal const int SC_RESTORE = 0xF120; - - internal const int - WM_CREATE = 0x0001; - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr SetActiveWindow(IntPtr hWnd); - - [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)] - internal static extern bool DestroyWindow(IntPtr hwnd); - - internal const int HT_CAPTION = 0x2; - - [DllImportAttribute("user32.dll")] - internal static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); - [DllImportAttribute("user32.dll")] - internal static extern int PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); - - - [DllImport("user32.dll")] - static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); - [DllImport("user32.dll")] - internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); - - // Hook Types - public enum HookType : int - { - WH_JOURNALRECORD = 0, - WH_JOURNALPLAYBACK = 1, - WH_KEYBOARD = 2, - WH_GETMESSAGE = 3, - WH_CALLWNDPROC = 4, - WH_CBT = 5, - WH_SYSMSGFILTER = 6, - WH_MOUSE = 7, - WH_HARDWARE = 8, - WH_DEBUG = 9, - WH_SHELL = 10, - WH_FOREGROUNDIDLE = 11, - WH_CALLWNDPROCRET = 12, - WH_KEYBOARD_LL = 13, - WH_MOUSE_LL = 14 - } + [StructLayout( LayoutKind.Sequential )] + internal class WINDOWPOS + { + public IntPtr hwnd; + public IntPtr hwndInsertAfter; + public int x; + public int y; + public int cx; + public int cy; + public int flags; + }; + + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + internal static extern bool SetWindowPos( IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags ); + + [DllImport( "user32.dll", CharSet = CharSet.Auto, ExactSpelling = true )] + internal static extern bool IsChild( IntPtr hWndParent, IntPtr hwnd ); + + [DllImport( "user32.dll" )] + internal static extern IntPtr SetFocus( IntPtr hWnd ); + + internal const int WM_WINDOWPOSCHANGED = 0x0047; + internal const int WM_WINDOWPOSCHANGING = 0x0046; + internal const int WM_NCMOUSEMOVE = 0xa0; + internal const int WM_NCLBUTTONDOWN = 0xA1; + internal const int WM_NCLBUTTONUP = 0xA2; + internal const int WM_NCLBUTTONDBLCLK = 0xA3; + internal const int WM_NCRBUTTONDOWN = 0xA4; + internal const int WM_NCRBUTTONUP = 0xA5; + internal const int WM_CAPTURECHANGED = 0x0215; + internal const int WM_EXITSIZEMOVE = 0x0232; + internal const int WM_ENTERSIZEMOVE = 0x0231; + internal const int WM_MOVE = 0x0003; + internal const int WM_MOVING = 0x0216; + internal const int WM_KILLFOCUS = 0x0008; + internal const int WM_SETFOCUS = 0x0007; + internal const int WM_ACTIVATE = 0x0006; + internal const int WM_NCHITTEST = 0x0084; + internal const int WM_INITMENUPOPUP = 0x0117; + internal const int WM_KEYDOWN = 0x0100; + internal const int WM_KEYUP = 0x0101; + + internal const int WA_INACTIVE = 0x0000; + + internal const int WM_SYSCOMMAND = 0x0112; + // These are the wParam of WM_SYSCOMMAND + internal const int SC_MAXIMIZE = 0xF030; + internal const int SC_RESTORE = 0xF120; + + internal const int + WM_CREATE = 0x0001; + + [DllImport( "user32.dll", SetLastError = true )] + public static extern IntPtr SetActiveWindow( IntPtr hWnd ); + + [DllImport( "user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode )] + internal static extern bool DestroyWindow( IntPtr hwnd ); + + internal const int HT_CAPTION = 0x2; + + [DllImportAttribute( "user32.dll" )] + internal static extern int SendMessage( IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam ); + [DllImportAttribute( "user32.dll" )] + internal static extern int PostMessage( IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam ); + + + [DllImport( "user32.dll" )] + static extern bool GetClientRect( IntPtr hWnd, out RECT lpRect ); + [DllImport( "user32.dll" )] + internal static extern bool GetWindowRect( IntPtr hWnd, out RECT lpRect ); + + // Hook Types + public enum HookType : int + { + WH_JOURNALRECORD = 0, + WH_JOURNALPLAYBACK = 1, + WH_KEYBOARD = 2, + WH_GETMESSAGE = 3, + WH_CALLWNDPROC = 4, + WH_CBT = 5, + WH_SYSMSGFILTER = 6, + WH_MOUSE = 7, + WH_HARDWARE = 8, + WH_DEBUG = 9, + WH_SHELL = 10, + WH_FOREGROUNDIDLE = 11, + WH_CALLWNDPROCRET = 12, + WH_KEYBOARD_LL = 13, + WH_MOUSE_LL = 14 + } - public const int HCBT_SETFOCUS = 9; - public const int HCBT_ACTIVATE = 5; + public const int HCBT_SETFOCUS = 9; + public const int HCBT_ACTIVATE = 5; - [DllImport("kernel32.dll")] - public static extern uint GetCurrentThreadId(); + [DllImport( "kernel32.dll" )] + public static extern uint GetCurrentThreadId(); - public delegate int HookProc(int code, IntPtr wParam, - IntPtr lParam); + public delegate int HookProc( int code, IntPtr wParam, + IntPtr lParam ); - [DllImport("user32.dll")] - public static extern IntPtr SetWindowsHookEx(HookType code, - HookProc func, - IntPtr hInstance, - int threadID); - [DllImport("user32.dll")] - public static extern int UnhookWindowsHookEx(IntPtr hhook); - [DllImport("user32.dll")] - public static extern int CallNextHookEx(IntPtr hhook, - int code, IntPtr wParam, IntPtr lParam); + [DllImport( "user32.dll" )] + public static extern IntPtr SetWindowsHookEx( HookType code, + HookProc func, + IntPtr hInstance, + int threadID ); + [DllImport( "user32.dll" )] + public static extern int UnhookWindowsHookEx( IntPtr hhook ); + [DllImport( "user32.dll" )] + public static extern int CallNextHookEx( IntPtr hhook, + int code, IntPtr wParam, IntPtr lParam ); - [Serializable, StructLayout(LayoutKind.Sequential)] - internal struct RECT + [Serializable, StructLayout( LayoutKind.Sequential )] + internal struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + public RECT( int left_, int top_, int right_, int bottom_ ) + { + Left = left_; + Top = top_; + Right = right_; + Bottom = bottom_; + } + + public int Height + { + get { - public int Left; - public int Top; - public int Right; - public int Bottom; - public RECT(int left_, int top_, int right_, int bottom_) - { - Left = left_; Top = top_; Right = right_; Bottom = bottom_; - } - - public int Height - { - get { return Bottom - Top; } - } - - public int Width - { - get { return Right - Left; } - } - public Size Size { get { return new Size(Width, Height); } } - public Point Location { get { return new Point(Left, Top); } } - // Handy method for converting to a System.Drawing.Rectangle - public Rect ToRectangle() { return new Rect(Left, Top, Right, Bottom); } - public static RECT FromRectangle(Rect rectangle) - { return new Rect(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom); } - public override int GetHashCode() - { return Left ^ ((Top << 13) | (Top >> 0x13)) ^ ((Width << 0x1a) | (Width >> 6)) ^ ((Height << 7) | (Height >> 0x19)); } - - #region Operator overloads - public static implicit operator Rect(RECT rect) { return rect.ToRectangle(); } public static implicit operator RECT(Rect rect) { return FromRectangle(rect); } - #endregion + return Bottom - Top; } + } - internal static RECT GetClientRect(IntPtr hWnd) + public int Width + { + get { - RECT result = new RECT(); - GetClientRect(hWnd, out result); - return result; + return Right - Left; } - internal static RECT GetWindowRect(IntPtr hWnd) + } + public Size Size + { + get { - RECT result = new RECT(); - GetWindowRect(hWnd, out result); - return result; + return new Size( Width, Height ); } + } + public Point Location + { + get + { + return new Point( Left, Top ); + } + } + // Handy method for converting to a System.Drawing.Rectangle + public Rect ToRectangle() + { + return new Rect( Left, Top, Right, Bottom ); + } + public static RECT FromRectangle( Rect rectangle ) + { + return new Rect( rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom ); + } + public override int GetHashCode() + { + return Left ^ ( ( Top << 13 ) | ( Top >> 0x13 ) ) ^ ( ( Width << 0x1a ) | ( Width >> 6 ) ) ^ ( ( Height << 7 ) | ( Height >> 0x19 ) ); + } + + #region Operator overloads + public static implicit operator Rect( RECT rect ) + { + return rect.ToRectangle(); + } + public static implicit operator RECT( Rect rect ) + { + return FromRectangle( rect ); + } + #endregion + } - [DllImport("user32.dll")] - internal static extern IntPtr GetTopWindow(IntPtr hWnd); - - internal const uint GW_HWNDNEXT = 2; - internal const uint GW_HWNDPREV = 3; - + internal static RECT GetClientRect( IntPtr hWnd ) + { + RECT result = new RECT(); + GetClientRect( hWnd, out result ); + return result; + } + internal static RECT GetWindowRect( IntPtr hWnd ) + { + RECT result = new RECT(); + GetWindowRect( hWnd, out result ); + return result; + } - [DllImport("user32.dll", SetLastError = true)] - internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); + [DllImport( "user32.dll" )] + internal static extern IntPtr GetTopWindow( IntPtr hWnd ); - internal enum GetWindow_Cmd : uint - { - GW_HWNDFIRST = 0, - GW_HWNDLAST = 1, - GW_HWNDNEXT = 2, - GW_HWNDPREV = 3, - GW_OWNER = 4, - GW_CHILD = 5, - GW_ENABLEDPOPUP = 6 - } - - internal static int MakeLParam(int LoWord, int HiWord) - { + internal const uint GW_HWNDNEXT = 2; + internal const uint GW_HWNDPREV = 3; - //System.Diagnostics.Trace.WriteLine("LoWord: " + LoWord2(((HiWord << 16) | - //(LoWord & 0xffff)))); - return (int) ((HiWord << 16) | (LoWord & 0xffff)); - } + [DllImport( "user32.dll", SetLastError = true )] + internal static extern IntPtr GetWindow( IntPtr hWnd, uint uCmd ); + internal enum GetWindow_Cmd : uint + { + GW_HWNDFIRST = 0, + GW_HWNDLAST = 1, + GW_HWNDNEXT = 2, + GW_HWNDPREV = 3, + GW_OWNER = 4, + GW_CHILD = 5, + GW_ENABLEDPOPUP = 6 + } - internal const int WM_MOUSEMOVE = 0x200; - internal const int WM_LBUTTONDOWN = 0x201; - internal const int WM_LBUTTONUP = 0x202; - internal const int WM_LBUTTONDBLCLK = 0x203; - internal const int WM_RBUTTONDOWN = 0x204; - internal const int WM_RBUTTONUP = 0x205; - internal const int WM_RBUTTONDBLCLK = 0x206; - internal const int WM_MBUTTONDOWN = 0x207; - internal const int WM_MBUTTONUP = 0x208; - internal const int WM_MBUTTONDBLCLK = 0x209; - internal const int WM_MOUSEWHEEL = 0x20A; - internal const int WM_MOUSEHWHEEL = 0x20E; + internal static int MakeLParam( int LoWord, int HiWord ) + { + return ( int )( ( HiWord << 16 ) | ( LoWord & 0xffff ) ); + } - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool GetCursorPos(ref Win32Point pt); + internal const int WM_MOUSEMOVE = 0x200; + internal const int WM_LBUTTONDOWN = 0x201; + internal const int WM_LBUTTONUP = 0x202; + internal const int WM_LBUTTONDBLCLK = 0x203; + internal const int WM_RBUTTONDOWN = 0x204; + internal const int WM_RBUTTONUP = 0x205; + internal const int WM_RBUTTONDBLCLK = 0x206; + internal const int WM_MBUTTONDOWN = 0x207; + internal const int WM_MBUTTONUP = 0x208; + internal const int WM_MBUTTONDBLCLK = 0x209; + internal const int WM_MOUSEWHEEL = 0x20A; + internal const int WM_MOUSEHWHEEL = 0x20E; - [StructLayout(LayoutKind.Sequential)] - internal struct Win32Point - { - public Int32 X; - public Int32 Y; - }; - internal static Point GetMousePosition() - { - Win32Point w32Mouse = new Win32Point(); - GetCursorPos(ref w32Mouse); - return new Point(w32Mouse.X, w32Mouse.Y); - } + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + internal static extern bool GetCursorPos( ref Win32Point pt ); - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool IsWindowVisible(IntPtr hWnd); - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool IsWindowEnabled(IntPtr hWnd); + [StructLayout( LayoutKind.Sequential )] + internal struct Win32Point + { + public Int32 X; + public Int32 Y; + }; + internal static Point GetMousePosition() + { + Win32Point w32Mouse = new Win32Point(); + GetCursorPos( ref w32Mouse ); + return new Point( w32Mouse.X, w32Mouse.Y ); + } - [DllImport("user32.dll")] - internal static extern IntPtr GetFocus(); - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool BringWindowToTop(IntPtr hWnd); + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + internal static extern bool IsWindowVisible( IntPtr hWnd ); + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + internal static extern bool IsWindowEnabled( IntPtr hWnd ); - [DllImport("user32.dll", SetLastError = true)] - internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); + [DllImport( "user32.dll" )] + internal static extern IntPtr GetFocus(); - [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] - internal static extern IntPtr GetParent(IntPtr hWnd); + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + internal static extern bool BringWindowToTop( IntPtr hWnd ); - /// - /// Changes an attribute of the specified window. The function also sets the 32-bit (long) value at the specified offset into the extra window memory. - /// - /// A handle to the window and, indirectly, the class to which the window belongs.. - /// The zero-based offset to the value to be set. Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer. To set any other value, specify one of the following values: GWL_EXSTYLE, GWL_HINSTANCE, GWL_ID, GWL_STYLE, GWL_USERDATA, GWL_WNDPROC - /// The replacement value. - /// If the function succeeds, the return value is the previous value of the specified 32-bit integer. - /// If the function fails, the return value is zero. To get extended error information, call GetLastError. - [DllImport("user32.dll")] - static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + [DllImport( "user32.dll", SetLastError = true )] + internal static extern IntPtr SetParent( IntPtr hWndChild, IntPtr hWndNewParent ); - [DllImport("user32.dll", SetLastError = true)] - static extern int GetWindowLong(IntPtr hWnd, int nIndex); + [DllImport( "user32.dll", ExactSpelling = true, CharSet = CharSet.Auto )] + internal static extern IntPtr GetParent( IntPtr hWnd ); - public static void SetOwner(IntPtr childHandle, IntPtr ownerHandle) - { - SetWindowLong( - childHandle, - -8, // GWL_HWNDPARENT - ownerHandle.ToInt32()); - } + /// + /// Changes an attribute of the specified window. The function also sets the 32-bit (long) value at the specified offset into the extra window memory. + /// + /// A handle to the window and, indirectly, the class to which the window belongs.. + /// The zero-based offset to the value to be set. Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer. To set any other value, specify one of the following values: GWL_EXSTYLE, GWL_HINSTANCE, GWL_ID, GWL_STYLE, GWL_USERDATA, GWL_WNDPROC + /// The replacement value. + /// If the function succeeds, the return value is the previous value of the specified 32-bit integer. + /// If the function fails, the return value is zero. To get extended error information, call GetLastError. + [DllImport( "user32.dll" )] + static extern int SetWindowLong( IntPtr hWnd, int nIndex, int dwNewLong ); - public static IntPtr GetOwner(IntPtr childHandle) - { - return new IntPtr(GetWindowLong(childHandle, -8)); - } + [DllImport( "user32.dll", SetLastError = true )] + static extern int GetWindowLong( IntPtr hWnd, int nIndex ); + public static void SetOwner( IntPtr childHandle, IntPtr ownerHandle ) + { + SetWindowLong( + childHandle, + -8, // GWL_HWNDPARENT + ownerHandle.ToInt32() ); + } - //Monitor Patch #13440 - - /// - /// The MonitorFromRect function retrieves a handle to the display monitor that - /// has the largest area of intersection with a specified rectangle. - /// - /// Pointer to a RECT structure that specifies the rectangle of interest in - /// virtual-screen coordinates - /// Determines the function's return value if the rectangle does not intersect - /// any display monitor - /// - /// If the rectangle intersects one or more display monitor rectangles, the return value - /// is an HMONITOR handle to the display monitor that has the largest area of intersection with the rectangle. - /// If the rectangle does not intersect a display monitor, the return value depends on the value of dwFlags. - /// - [DllImport("user32.dll")] - public static extern IntPtr MonitorFromRect([In] ref RECT lprc, uint dwFlags); - - /// - /// The MonitorFromWindow function retrieves a handle to the display monitor that has the largest area of intersection with the bounding rectangle of a specified window. - /// - /// A handle to the window of interest. - /// Determines the function's return value if the window does not intersect any display monitor. - /// If the window intersects one or more display monitor rectangles, the return value is an HMONITOR handle to the display monitor that has the largest area of intersection with the window. - /// If the window does not intersect a display monitor, the return value depends on the value of dwFlags. - /// - [DllImport("user32.dll")] - public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags); - - - /// - /// The MONITORINFO structure contains information about a display monitor. - /// - [StructLayout(LayoutKind.Sequential)] - public class MonitorInfo - { - /// - /// The size of the structure, in bytes. - /// - public int Size = Marshal.SizeOf(typeof(MonitorInfo)); - /// - /// A RECT structure that specifies the display monitor rectangle, expressed - /// in virtual-screen coordinates. - /// Note that if the monitor is not the primary display monitor, - /// some of the rectangle's coordinates may be negative values. - /// - public RECT Monitor; - /// - /// A RECT structure that specifies the work area rectangle of the display monitor, - /// expressed in virtual-screen coordinates. Note that if the monitor is not the primary - /// display monitor, some of the rectangle's coordinates may be negative values. - /// - public RECT Work; - /// - /// A set of flags that represent attributes of the display monitor. - /// - public uint Flags; - } + public static IntPtr GetOwner( IntPtr childHandle ) + { + return new IntPtr( GetWindowLong( childHandle, -8 ) ); + } - /// - /// The GetMonitorInfo function retrieves information about a display monitor. - /// - /// Handle to the display monitor of interest. - /// Pointer to a MONITORINFO or MONITORINFOEX structure that receives - /// information about the specified display monitor - /// If the function succeeds, the return value is nonzero. - /// If the function fails, the return value is zero. - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetMonitorInfo(IntPtr hMonitor, [In, Out] MonitorInfo lpmi); + //Monitor Patch #13440 + + /// + /// The MonitorFromRect function retrieves a handle to the display monitor that + /// has the largest area of intersection with a specified rectangle. + /// + /// Pointer to a RECT structure that specifies the rectangle of interest in + /// virtual-screen coordinates + /// Determines the function's return value if the rectangle does not intersect + /// any display monitor + /// + /// If the rectangle intersects one or more display monitor rectangles, the return value + /// is an HMONITOR handle to the display monitor that has the largest area of intersection with the rectangle. + /// If the rectangle does not intersect a display monitor, the return value depends on the value of dwFlags. + /// + [DllImport( "user32.dll" )] + public static extern IntPtr MonitorFromRect( [In] ref RECT lprc, uint dwFlags ); + + /// + /// The MonitorFromWindow function retrieves a handle to the display monitor that has the largest area of intersection with the bounding rectangle of a specified window. + /// + /// A handle to the window of interest. + /// Determines the function's return value if the window does not intersect any display monitor. + /// If the window intersects one or more display monitor rectangles, the return value is an HMONITOR handle to the display monitor that has the largest area of intersection with the window. + /// If the window does not intersect a display monitor, the return value depends on the value of dwFlags. + /// + [DllImport( "user32.dll" )] + public static extern IntPtr MonitorFromWindow( IntPtr hwnd, uint dwFlags ); + + + /// + /// The MONITORINFO structure contains information about a display monitor. + /// + [StructLayout( LayoutKind.Sequential )] + public class MonitorInfo + { + /// + /// The size of the structure, in bytes. + /// + public int Size = Marshal.SizeOf( typeof( MonitorInfo ) ); + /// + /// A RECT structure that specifies the display monitor rectangle, expressed + /// in virtual-screen coordinates. + /// Note that if the monitor is not the primary display monitor, + /// some of the rectangle's coordinates may be negative values. + /// + public RECT Monitor; + /// + /// A RECT structure that specifies the work area rectangle of the display monitor, + /// expressed in virtual-screen coordinates. Note that if the monitor is not the primary + /// display monitor, some of the rectangle's coordinates may be negative values. + /// + public RECT Work; + /// + /// A set of flags that represent attributes of the display monitor. + /// + public uint Flags; } + + /// + /// The GetMonitorInfo function retrieves information about a display monitor. + /// + /// Handle to the display monitor of interest. + /// Pointer to a MONITORINFO or MONITORINFOEX structure that receives + /// information about the specified display monitor + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero. + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool GetMonitorInfo( IntPtr hMonitor, [In, Out] MonitorInfo lpmi ); + + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/WindowHelper.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/WindowHelper.cs index 91bb2d74..efd95082 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/WindowHelper.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/WindowHelper.cs @@ -15,66 +15,63 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Media; using System.Windows; using System.Windows.Interop; namespace Xceed.Wpf.AvalonDock { - static class WindowHelper + static class WindowHelper + { + public static bool IsAttachedToPresentationSource( this Visual element ) { - public static bool IsAttachedToPresentationSource(this Visual element) - { - return PresentationSource.FromVisual(element as Visual) != null; - } + return PresentationSource.FromVisual( element as Visual ) != null; + } - public static void SetParentToMainWindowOf(this Window window, Visual element) - { - var wndParent = Window.GetWindow(element); - if (wndParent != null) - window.Owner = wndParent; - else - { - IntPtr parentHwnd; - if (GetParentWindowHandle(element, out parentHwnd)) - Win32Helper.SetOwner(new WindowInteropHelper(window).Handle, parentHwnd); - } - } + public static void SetParentToMainWindowOf( this Window window, Visual element ) + { + var wndParent = Window.GetWindow( element ); + if( wndParent != null ) + window.Owner = wndParent; + else + { + IntPtr parentHwnd; + if( GetParentWindowHandle( element, out parentHwnd ) ) + Win32Helper.SetOwner( new WindowInteropHelper( window ).Handle, parentHwnd ); + } + } - public static IntPtr GetParentWindowHandle(this Window window) - { - if (window.Owner != null) - return new WindowInteropHelper(window.Owner).Handle; - else - return Win32Helper.GetOwner(new WindowInteropHelper(window).Handle); - } + public static IntPtr GetParentWindowHandle( this Window window ) + { + if( window.Owner != null ) + return new WindowInteropHelper( window.Owner ).Handle; + else + return Win32Helper.GetOwner( new WindowInteropHelper( window ).Handle ); + } - public static bool GetParentWindowHandle(this Visual element, out IntPtr hwnd) - { - hwnd = IntPtr.Zero; - HwndSource wpfHandle = PresentationSource.FromVisual(element) as HwndSource; + public static bool GetParentWindowHandle( this Visual element, out IntPtr hwnd ) + { + hwnd = IntPtr.Zero; + HwndSource wpfHandle = PresentationSource.FromVisual( element ) as HwndSource; - if (wpfHandle == null) - return false; + if( wpfHandle == null ) + return false; - hwnd = Win32Helper.GetParent(wpfHandle.Handle); - if (hwnd == IntPtr.Zero) - hwnd = wpfHandle.Handle; - return true; - } + hwnd = Win32Helper.GetParent( wpfHandle.Handle ); + if( hwnd == IntPtr.Zero ) + hwnd = wpfHandle.Handle; + return true; + } - public static void SetParentWindowToNull(this Window window) - { - if (window.Owner != null) - window.Owner = null; - else - { - Win32Helper.SetOwner(new WindowInteropHelper(window).Handle, IntPtr.Zero); - } - } + public static void SetParentWindowToNull( this Window window ) + { + if( window.Owner != null ) + window.Owner = null; + else + { + Win32Helper.SetOwner( new WindowInteropHelper( window ).Handle, IntPtr.Zero ); + } } + } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Xceed.Wpf.AvalonDock.csproj b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Xceed.Wpf.AvalonDock.csproj index a39006f3..ee1c01a5 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Xceed.Wpf.AvalonDock.csproj +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Xceed.Wpf.AvalonDock.csproj @@ -100,6 +100,7 @@ + @@ -253,6 +254,7 @@ True Resources.zh-Hans.resx + @@ -349,6 +351,12 @@ MSBuild:Compile + + + {72e591d6-8f83-4d8c-8f67-9c325e623234} + Xceed.Wpf.Toolkit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + AutomationProperties.AutomationId="DatePickerEditor" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DefaultCellEditorSelector.xaml.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DefaultCellEditorSelector.xaml.cs index 42f0f29e..dfe27fa9 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DefaultCellEditorSelector.xaml.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DefaultCellEditorSelector.xaml.cs @@ -15,195 +15,215 @@ ***********************************************************************************/ using System; +using System.Collections; using System.Collections.Generic; -using System.Text; +using System.Diagnostics; using System.Windows; -using System.Collections; +using System.Windows.Threading; namespace Xceed.Wpf.DataGrid { internal partial class DefaultCellEditorSelector : FrameworkElement { - #region Constructors + #region Static Fields - static DefaultCellEditorSelector() - { - Instance = new DefaultCellEditorSelector(); - } + private static DefaultCellEditorSelector s_instance = default( DefaultCellEditorSelector ); + private static readonly List s_instances = new List( 1 ); + + #endregion private DefaultCellEditorSelector() { this.InitializeComponent(); } - #endregion - - #region Static Fields + #region ForeignKeyCellEditor Public Static Property - private static readonly DefaultCellEditorSelector Instance; + public static CellEditor ForeignKeyCellEditor + { + get + { + return DefaultCellEditorSelector.GetCellEditor( "foreignKeyCellEditor" ); + } + } #endregion #region TextBoxEditor Public Static Property - public static CellEditor TextBoxEditorCache; - public static CellEditor TextBoxEditor { get { - if( TextBoxEditorCache == null ) - TextBoxEditorCache = DefaultCellEditorSelector.SelectCellEditor( typeof( string ) ); - - return TextBoxEditorCache; + return DefaultCellEditorSelector.SelectCellEditor( typeof( string ) ); } - } + } #endregion #region CheckBoxEditor Public Static Property - public static CellEditor CheckBoxEditorCache; - public static CellEditor CheckBoxEditor { get { - if( CheckBoxEditorCache == null ) - CheckBoxEditorCache = DefaultCellEditorSelector.SelectCellEditor( typeof( bool ) ); - - return CheckBoxEditorCache; + return DefaultCellEditorSelector.SelectCellEditor( typeof( bool ) ); } - } + } #endregion #region DateTimeEditor Public Static Editor - public static CellEditor DateTimeEditorCache; - public static CellEditor DateTimeEditor { get { - if( DateTimeEditorCache == null ) - DateTimeEditorCache = DefaultCellEditorSelector.SelectCellEditor( typeof( DateTime ) ); - - return DateTimeEditorCache; + return DefaultCellEditorSelector.SelectCellEditor( typeof( DateTime ) ); } } #endregion - #region ForeignKeyCellEditor Public Static Property - - private static CellEditor ForeignKeyEditorCache; - - public static CellEditor ForeignKeyCellEditor + public static CellEditor SelectCellEditor( Type dataType ) { - get - { - if( ForeignKeyEditorCache == null ) - { - ForeignKeyEditorCache = DefaultCellEditorSelector.ThreadSafeFindResource( "foreignKeyCellEditor" ) as CellEditor; - ForeignKeyEditorCache.EditTemplate.Seal(); - } + if( dataType == null ) + return null; - return ForeignKeyEditorCache; + if( dataType.IsGenericType && ( dataType.GetGenericTypeDefinition() == typeof( Nullable<> ) ) ) + { + dataType = Nullable.GetUnderlyingType( dataType ); } - } - #endregion + var editor = default( CellEditor ); + if( DefaultCellEditorSelector.TryGetCellEditor( dataType.FullName, out editor ) ) + return editor; - #region LinqCellEditor Public Static Editor + return null; + } - private static CellEditor LinqCellEditorCache; + private static DataTemplate GetDataTemplate( object key ) + { + var resource = default( DataTemplate ); + if( !DefaultCellEditorSelector.TryGetDataTemplate( key, out resource ) ) + throw new KeyNotFoundException( "Resource not found" ); - public static CellEditor LinqCellEditor + return resource; + } + + private static bool TryGetDataTemplate( object key, out DataTemplate value ) { - get + var resource = default( object ); + if( !DefaultCellEditorSelector.TryGetResource( key, out resource ) ) { - if( LinqCellEditorCache == null ) - { - LinqCellEditorCache = DefaultCellEditorSelector.ThreadSafeFindResource( "linqCellEditor" ) as CellEditor; - LinqCellEditorCache.EditTemplate.Seal(); - } - - return LinqCellEditorCache; + value = default( DataTemplate ); + return false; + } + else + { + value = DefaultCellEditorSelector.TrySeal( resource as DataTemplate ); + return ( value != null ); } } - #endregion + private static CellEditor GetCellEditor( object key ) + { + var resource = default( CellEditor ); + if( !DefaultCellEditorSelector.TryGetCellEditor( key, out resource ) ) + throw new KeyNotFoundException( "Resource not found" ); - #region Public Methods + return resource; + } - public static CellEditor SelectCellEditor( Type dataType ) + private static bool TryGetCellEditor( object key, out CellEditor value ) { - CellEditor cellEditor = null; - - if( dataType != null ) + var resource = default( object ); + if( !DefaultCellEditorSelector.TryGetResource( key, out resource ) ) { - if( ( dataType.IsGenericType ) && ( dataType.GetGenericTypeDefinition() == typeof( Nullable<> ) ) ) - dataType = Nullable.GetUnderlyingType( dataType ); - - cellEditor = DefaultCellEditorSelector.ThreadSafeTryFindResource( dataType.FullName ) as CellEditor; - - if( cellEditor != null ) - DefaultCellEditorSelector.ThreadSafeTryFreezeEditor( cellEditor ); + value = default( CellEditor ); + return false; + } + else + { + value = DefaultCellEditorSelector.TryFreeze( resource as CellEditor ); + return ( value != null ); } + } - return cellEditor; - } + private static bool TryGetResource( object key, out object value ) + { + value = null; - #endregion + var dispatcher = Dispatcher.CurrentDispatcher; + if( dispatcher == null ) + return false; - #region Private Methods + var target = default( DefaultCellEditorSelector ); - private static object ThreadSafeTryFindResource( string key ) - { - Func func = ( resourceKey => DefaultCellEditorSelector.Instance.TryFindResource( resourceKey ) ); + lock( ( ( ICollection )s_instances ).SyncRoot ) + { + for( int i = s_instances.Count - 1; i >= 0; i-- ) + { + var instance = s_instances[ i ].Target as DefaultCellEditorSelector; + + if( instance == null ) + { + s_instances.RemoveAt( i ); + } + else if( instance.Dispatcher == dispatcher ) + { + target = instance; + + // We could exit the loop but we don't because we want to clean up the list + // and keep it small. We don't want it to become large with lots of empty + // WeakReference. + //break; + } + } - if( DefaultCellEditorSelector.Instance.CheckAccess() ) - return func( key ); + if( target == null ) + { + target = new DefaultCellEditorSelector(); + s_instances.Add( new WeakReference( target ) ); + } - return DefaultCellEditorSelector.Instance.Dispatcher.Invoke( func, key ); - } + // We keep a strong reference on the target instance to prevent that instance + // from being garbage collected. We assume that we will need that instance + // again for other calls. We don't want to have to create a new instance to + // query for a single resource. + s_instance = target; + } - private static object ThreadSafeFindResource( string key ) - { - Func func = ( resourceKey => DefaultCellEditorSelector.Instance.FindResource( resourceKey ) ); + Debug.Assert( target != null ); - if( DefaultCellEditorSelector.Instance.CheckAccess() ) - return func( key ); + value = target.TryFindResource( key ); - return DefaultCellEditorSelector.Instance.Dispatcher.Invoke( func, key ); + return ( value != null ); } - private static void ThreadSafeTryFreezeEditor( CellEditor cellEditor ) + private static DataTemplate TrySeal( DataTemplate template ) { - if( cellEditor == null ) - throw new ArgumentNullException( "cellEditor" ); - - if( DefaultCellEditorSelector.Instance.CheckAccess() ) + if( ( template != null ) && !template.IsSealed ) { - if( cellEditor.IsFrozen ) - return; - - if( ( cellEditor.EditTemplate != null ) && ( !cellEditor.EditTemplate.IsSealed ) ) - cellEditor.EditTemplate.Seal(); + template.Seal(); + } - System.Diagnostics.Debug.Assert( cellEditor.CanFreeze ); + return template; + } - if( cellEditor.CanFreeze ) - cellEditor.Freeze(); - } - else + private static CellEditor TryFreeze( CellEditor editor ) + { + if( ( editor != null ) && !editor.IsFrozen ) { - DefaultCellEditorSelector.Instance.Dispatcher.Invoke( - new Action( DefaultCellEditorSelector.ThreadSafeTryFreezeEditor ), cellEditor ); + DefaultCellEditorSelector.TrySeal( editor.EditTemplate ); + + if( editor.CanFreeze ) + { + editor.Freeze(); + } } - } - #endregion + return editor; + } } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DefaultDetailConfiguration.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DefaultDetailConfiguration.cs index f7a5f4c3..7701f8f0 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DefaultDetailConfiguration.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DefaultDetailConfiguration.cs @@ -26,8 +26,6 @@ namespace Xceed.Wpf.DataGrid { public class DefaultDetailConfiguration : DependencyObject { - #region Constructors - static DefaultDetailConfiguration() { HeadersProperty = HeadersPropertyKey.DependencyProperty; @@ -38,9 +36,7 @@ namespace Xceed.Wpf.DataGrid { this.SetHeaders( new ObservableCollection() ); this.SetFooters( new ObservableCollection() ); - } - - #endregion + } #region AllowDetailToggle Property @@ -50,11 +46,11 @@ namespace Xceed.Wpf.DataGrid { get { - return (bool)this.GetValue(DefaultDetailConfiguration.AllowDetailToggleProperty); + return ( bool )this.GetValue( DefaultDetailConfiguration.AllowDetailToggleProperty ); } set { - this.SetValue(DefaultDetailConfiguration.AllowDetailToggleProperty, value); + this.SetValue( DefaultDetailConfiguration.AllowDetailToggleProperty, value ); } } @@ -68,11 +64,11 @@ namespace Xceed.Wpf.DataGrid { get { - return (GroupConfiguration)this.GetValue(DefaultDetailConfiguration.DefaultGroupConfigurationProperty); + return ( GroupConfiguration )this.GetValue( DefaultDetailConfiguration.DefaultGroupConfigurationProperty ); } set { - this.SetValue(DefaultDetailConfiguration.DefaultGroupConfigurationProperty, value); + this.SetValue( DefaultDetailConfiguration.DefaultGroupConfigurationProperty, value ); } } @@ -86,11 +82,11 @@ namespace Xceed.Wpf.DataGrid { get { - return (GroupConfigurationSelector)this.GetValue(DefaultDetailConfiguration.GroupConfigurationSelectorProperty); + return ( GroupConfigurationSelector )this.GetValue( DefaultDetailConfiguration.GroupConfigurationSelectorProperty ); } set { - this.SetValue(DefaultDetailConfiguration.GroupConfigurationSelectorProperty, value); + this.SetValue( DefaultDetailConfiguration.GroupConfigurationSelectorProperty, value ); } } @@ -98,17 +94,17 @@ namespace Xceed.Wpf.DataGrid #region ItemContainerStyle Property - public static readonly DependencyProperty ItemContainerStyleProperty = DataGridControl.ItemContainerStyleProperty.AddOwner( typeof( DefaultDetailConfiguration ) ) ; + public static readonly DependencyProperty ItemContainerStyleProperty = DataGridControl.ItemContainerStyleProperty.AddOwner( typeof( DefaultDetailConfiguration ) ); public Style ItemContainerStyle { get { - return (Style)this.GetValue(DefaultDetailConfiguration.ItemContainerStyleProperty); + return ( Style )this.GetValue( DefaultDetailConfiguration.ItemContainerStyleProperty ); } set { - this.SetValue(DefaultDetailConfiguration.ItemContainerStyleProperty, value); + this.SetValue( DefaultDetailConfiguration.ItemContainerStyleProperty, value ); } } @@ -116,17 +112,17 @@ namespace Xceed.Wpf.DataGrid #region ItemContainerStyleSelector Property - public static readonly DependencyProperty ItemContainerStyleSelectorProperty = DataGridControl.ItemContainerStyleSelectorProperty.AddOwner( typeof(DefaultDetailConfiguration ) ); + public static readonly DependencyProperty ItemContainerStyleSelectorProperty = DataGridControl.ItemContainerStyleSelectorProperty.AddOwner( typeof( DefaultDetailConfiguration ) ); public StyleSelector ItemContainerStyleSelector { get { - return (StyleSelector)this.GetValue(DefaultDetailConfiguration.ItemContainerStyleSelectorProperty); + return ( StyleSelector )this.GetValue( DefaultDetailConfiguration.ItemContainerStyleSelectorProperty ); } set { - this.SetValue(DefaultDetailConfiguration.ItemContainerStyleSelectorProperty, value); + this.SetValue( DefaultDetailConfiguration.ItemContainerStyleSelectorProperty, value ); } } @@ -140,11 +136,11 @@ namespace Xceed.Wpf.DataGrid { get { - return (Style)this.GetValue(DefaultDetailConfiguration.DetailIndicatorStyleProperty); + return ( Style )this.GetValue( DefaultDetailConfiguration.DetailIndicatorStyleProperty ); } set { - this.SetValue(DefaultDetailConfiguration.DetailIndicatorStyleProperty, value); + this.SetValue( DefaultDetailConfiguration.DetailIndicatorStyleProperty, value ); } } @@ -153,7 +149,7 @@ namespace Xceed.Wpf.DataGrid #region Headers Property private static readonly DependencyPropertyKey HeadersPropertyKey = - DependencyProperty.RegisterReadOnly("Headers", typeof(ObservableCollection), typeof(DefaultDetailConfiguration), new FrameworkPropertyMetadata(null)); + DependencyProperty.RegisterReadOnly( "Headers", typeof( ObservableCollection ), typeof( DefaultDetailConfiguration ), new FrameworkPropertyMetadata( null ) ); public static readonly DependencyProperty HeadersProperty; @@ -161,13 +157,13 @@ namespace Xceed.Wpf.DataGrid { get { - return (ObservableCollection)this.GetValue(DefaultDetailConfiguration.HeadersProperty); + return ( ObservableCollection )this.GetValue( DefaultDetailConfiguration.HeadersProperty ); } } - private void SetHeaders(ObservableCollection headers) + private void SetHeaders( ObservableCollection headers ) { - this.SetValue(DefaultDetailConfiguration.HeadersPropertyKey, headers); + this.SetValue( DefaultDetailConfiguration.HeadersPropertyKey, headers ); } #endregion Headers Property @@ -175,7 +171,7 @@ namespace Xceed.Wpf.DataGrid #region Footers Property private static readonly DependencyPropertyKey FootersPropertyKey = - DependencyProperty.RegisterReadOnly("Footers", typeof(ObservableCollection), typeof(DefaultDetailConfiguration), new FrameworkPropertyMetadata(null)); + DependencyProperty.RegisterReadOnly( "Footers", typeof( ObservableCollection ), typeof( DefaultDetailConfiguration ), new FrameworkPropertyMetadata( null ) ); public static readonly DependencyProperty FootersProperty; @@ -183,13 +179,13 @@ namespace Xceed.Wpf.DataGrid { get { - return (ObservableCollection)this.GetValue(DefaultDetailConfiguration.FootersProperty); + return ( ObservableCollection )this.GetValue( DefaultDetailConfiguration.FootersProperty ); } } - private void SetFooters(ObservableCollection footers) + private void SetFooters( ObservableCollection footers ) { - this.SetValue(DefaultDetailConfiguration.FootersPropertyKey, footers); + this.SetValue( DefaultDetailConfiguration.FootersPropertyKey, footers ); } #endregion Footers Property @@ -232,17 +228,17 @@ namespace Xceed.Wpf.DataGrid #region UseDefaultHeadersFooters Property - public static readonly DependencyProperty UseDefaultHeadersFootersProperty = DetailConfiguration.UseDefaultHeadersFootersProperty.AddOwner(typeof(DefaultDetailConfiguration)); + public static readonly DependencyProperty UseDefaultHeadersFootersProperty = DetailConfiguration.UseDefaultHeadersFootersProperty.AddOwner( typeof( DefaultDetailConfiguration ) ); public bool UseDefaultHeadersFooters { get { - return (bool)this.GetValue(DefaultDetailConfiguration.UseDefaultHeadersFootersProperty); + return ( bool )this.GetValue( DefaultDetailConfiguration.UseDefaultHeadersFootersProperty ); } set { - this.SetValue(DefaultDetailConfiguration.UseDefaultHeadersFootersProperty, value); + this.SetValue( DefaultDetailConfiguration.UseDefaultHeadersFootersProperty, value ); } } @@ -250,8 +246,8 @@ namespace Xceed.Wpf.DataGrid #region IsDeleteCommandEnabled Property - public static readonly DependencyProperty IsDeleteCommandEnabledProperty = DetailConfiguration.IsDeleteCommandEnabledProperty.AddOwner( - typeof( DefaultDetailConfiguration ), + public static readonly DependencyProperty IsDeleteCommandEnabledProperty = DetailConfiguration.IsDeleteCommandEnabledProperty.AddOwner( + typeof( DefaultDetailConfiguration ), new FrameworkPropertyMetadata( false, new PropertyChangedCallback( DefaultDetailConfiguration.OnIsDeleteCommandEnabledChanged ) ) ); public bool IsDeleteCommandEnabled @@ -273,25 +269,14 @@ namespace Xceed.Wpf.DataGrid #endregion IsDeleteCommandEnabled Property - #region Internal Methods - internal void AddDefaultHeadersFooters() { if( m_defaultHeadersFootersAdded ) return; m_defaultHeadersFootersAdded = true; + } - DetailConfiguration.AddDefaultHeadersFooters( this.Headers, this.Footers ); - } - - #endregion - - #region Private Fields - - private bool m_defaultHeadersFootersAdded = false; - - #endregion - + private bool m_defaultHeadersFootersAdded = false; } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DeletingSelectedItemErrorRoutedEventArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DeletingSelectedItemErrorRoutedEventArgs.cs deleted file mode 100644 index db57f500..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DeletingSelectedItemErrorRoutedEventArgs.cs +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; - -namespace Xceed.Wpf.DataGrid -{ - public delegate void DeletingSelectedItemErrorRoutedEventHandler( object sender, DeletingSelectedItemErrorRoutedEventArgs e ); - - public class DeletingSelectedItemErrorRoutedEventArgs : RoutedEventArgs - { - #region CONSTRUCTORS - - public DeletingSelectedItemErrorRoutedEventArgs( object item, Exception exception ) - : base() - { - m_item = item; - m_exception = exception; - } - - public DeletingSelectedItemErrorRoutedEventArgs( object item, Exception exception, RoutedEvent routedEvent ) - : base( routedEvent ) - { - m_item = item; - m_exception = exception; - } - - public DeletingSelectedItemErrorRoutedEventArgs( object item, Exception exception, RoutedEvent routedEvent, object source ) - : base( routedEvent, source ) - { - m_item = item; - m_exception = exception; - } - - #endregion CONSTRUCTORS - - #region Item Property - - public object Item - { - get - { - return m_item; - } - } - - #endregion Item Property - - #region Exception Property - - public Exception Exception - { - get - { - return m_exception; - } - } - - #endregion Exception Property - - #region Action Property - - public DeletingSelectedItemErrorAction Action - { - get - { - return m_action; - } - set - { - m_action = value; - } - } - - #endregion Action Property - - #region PRIVATE FIELDS - - private object m_item; - private Exception m_exception; - private DeletingSelectedItemErrorAction m_action = DeletingSelectedItemErrorAction.Skip; - - #endregion PRIVATE FIELDS - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfiguration.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfiguration.cs index 78daf234..86423d25 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfiguration.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfiguration.cs @@ -15,26 +15,31 @@ ***********************************************************************************/ using System; +using System.Collections; using System.Collections.Generic; -using System.Text; -using System.Windows; -using System.Windows.Controls; using System.Collections.ObjectModel; using System.Collections.Specialized; -using System.Collections; -using System.Diagnostics; -using Xceed.Wpf.DataGrid.Views; using System.ComponentModel; -using Xceed.Wpf.DataGrid.Markup; +using System.Diagnostics; +using System.Linq; +using System.Windows; +using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; -using System.Windows.Media; +using Xceed.Wpf.DataGrid.Markup; +using Xceed.Wpf.DataGrid.Utils; +using Xceed.Wpf.DataGrid.Views; namespace Xceed.Wpf.DataGrid { internal sealed class DetailConfiguration : DependencyObject, IWeakEventListener, ISupportInitialize, INotifyPropertyChanged { - #region Constructors + #region Static Fields + + internal static readonly string DataGridControlPropertyName = PropertyHelper.GetPropertyName( ( DetailConfiguration d ) => d.DataGridControl ); + internal static readonly string DetailDescriptionPropertyName = PropertyHelper.GetPropertyName( ( DetailConfiguration d ) => d.DetailDescription ); + + #endregion static DetailConfiguration() { @@ -48,54 +53,30 @@ namespace Xceed.Wpf.DataGrid DetailConfiguration.BuildDefaultTemplates(); } - internal DetailConfiguration( bool isSynchronizedWithParent ) + public DetailConfiguration() { - if( !isSynchronizedWithParent ) - { - this.SetColumns( new ColumnCollection( this.DataGridControl, this ) ); - this.Columns.CollectionChanged += new NotifyCollectionChangedEventHandler( this.OnColumnsCollectionChanged ); - VisibilityChangedEventManager.AddListener( this.Columns, this ); + var columns = new ColumnCollection( null, this ); - this.SetVisibleColumns( new ReadOnlyColumnCollection() ); + m_columnManager = new ColumnHierarchyManager( columns ); - m_columnsByVisiblePosition = new HashedLinkedList(); + this.SetColumns( columns ); + this.SetVisibleColumns( m_columnManager.VisibleColumns ); - this.SetGroupLevelDescriptions( new GroupLevelDescriptionCollection() ); - } + m_columnSynchronizationManager = new ColumnSynchronizationManager( this ); + m_columnManagerRowConfiguration = new ColumnManagerRowConfiguration(); this.SetHeaders( new ObservableCollection() ); this.SetFooters( new ObservableCollection() ); - this.SetDetailConfigurations( new DetailConfigurationCollection( this.DataGridControl, this ) ); + this.SetGroupLevelDescriptions( new GroupLevelDescriptionCollection() ); + this.SetDetailConfigurations( new DetailConfigurationCollection( null, this ) ); + columns.CollectionChanged += new NotifyCollectionChangedEventHandler( this.OnColumnsCollectionChanged ); CollectionChangedEventManager.AddListener( this.DetailConfigurations, this ); - } - - internal DetailConfiguration( DataGridContext synchronizedParent ) - : this( true ) - { - m_shouldCreateColumns = false; - - this.SetColumns( synchronizedParent.Columns ); - this.SetVisibleColumns( synchronizedParent.VisibleColumns ); - m_columnsByVisiblePosition = synchronizedParent.ColumnsByVisiblePosition; - - m_sortDescriptions = synchronizedParent.Items.SortDescriptions; - m_groupDescriptions = synchronizedParent.Items.GroupDescriptions; - this.SetGroupLevelDescriptions( synchronizedParent.GroupLevelDescriptions ); + this.BeginInit(); } - public DetailConfiguration() - : this( false ) - { - } - - - #endregion - - #region Static Fields - private static void BuildDefaultTemplates() { //Defining the FrameworkElementFactory variables I will use below. @@ -171,65 +152,12 @@ namespace Xceed.Wpf.DataGrid private static DataTemplate DefaultColumnManagerRowTemplate; private static DataTemplate DefaultGroupByControlTemplate; - #endregion - - #region Static Methods - - internal static void AddDefaultHeadersFooters( ObservableCollection headersCollection, ObservableCollection footersCollection ) + internal static void AddDefaultHeadersFooters( ObservableCollection headersCollection, int mergedHeadersCount, bool areDetailsFlatten ) { - headersCollection.Insert( 0, DetailConfiguration.DefaultColumnManagerRowTemplate ); - headersCollection.Insert( 0, DetailConfiguration.DefaultHeaderSpacerTemplate ); - } - - internal static void SynchronizeDetailConfigurations( - DataGridDetailDescriptionCollection dataGridDetailDescriptionCollection, - DetailConfigurationCollection detailConfigurationCollection, - bool autoCreateDetailConfigurations, - bool autoCreateForeignKeyConfigurations, - bool autoRemoveUnassociated ) - { - HashSet detailConfigWithAssociation = new HashSet(); - DetailConfiguration detailConfig; - - foreach( DataGridDetailDescription detailDescription in dataGridDetailDescriptionCollection ) - { - detailConfig = detailConfigurationCollection[ detailDescription.RelationName ]; - - if( detailConfig == null ) - { - if( autoCreateDetailConfigurations ) - { - detailConfig = new DetailConfiguration(); - - detailConfig.SetIsAutoCreated( true ); - detailConfig.RelationName = detailDescription.RelationName; - detailConfig.AutoCreateForeignKeyConfigurations = autoCreateForeignKeyConfigurations; - detailConfig.AutoRemoveColumnsAndDetailConfigurations = autoRemoveUnassociated; - detailConfigurationCollection.Add( detailConfig ); - } - } - - if( detailConfig != null ) - { - detailConfigWithAssociation.Add( detailConfig ); - detailConfig.SynchronizeWithDetailDescription( detailDescription ); - } - } - - for( int i = detailConfigurationCollection.Count - 1; i >= 0; i-- ) + if( !areDetailsFlatten ) { - detailConfig = detailConfigurationCollection[ i ]; - - if( !detailConfigWithAssociation.Contains( detailConfig ) ) - { - detailConfig.DetachFromDetailDescription(); - - if( ( autoRemoveUnassociated ) && ( detailConfig.IsAutoCreated ) ) - { - DetailConfiguration.CleanupDetailConfigurations( detailConfig.DetailConfigurations, autoRemoveUnassociated ); - detailConfigurationCollection.RemoveAt( i ); - } - } + headersCollection.Insert( 0, DetailConfiguration.DefaultColumnManagerRowTemplate ); + headersCollection.Insert( 0, DetailConfiguration.DefaultHeaderSpacerTemplate ); } } @@ -263,10 +191,6 @@ namespace Xceed.Wpf.DataGrid } } - #endregion - - // PUBLIC PROPERTIES - #region RelationName Property public static readonly DependencyProperty RelationNameProperty = @@ -336,44 +260,6 @@ namespace Xceed.Wpf.DataGrid #endregion AutoCreateColumns Property - #region AutoCreateDetailConfigurations Property - - public static readonly DependencyProperty AutoCreateDetailConfigurationsProperty = - DataGridControl.AutoCreateDetailConfigurationsProperty.AddOwner( typeof( DetailConfiguration ), new FrameworkPropertyMetadata( true ) ); - - public bool AutoCreateDetailConfigurations - { - get - { - return ( bool )this.GetValue( DetailConfiguration.AutoCreateDetailConfigurationsProperty ); - } - set - { - this.SetValue( DetailConfiguration.AutoCreateDetailConfigurationsProperty, value ); - } - } - - #endregion AutoCreateColumns Property - - #region AutoRemoveColumnsAndDetailConfigurations Property - - public static readonly DependencyProperty AutoRemoveColumnsAndDetailConfigurationsProperty = - DataGridControl.AutoRemoveColumnsAndDetailConfigurationsProperty.AddOwner( typeof( DetailConfiguration ) ); - - public bool AutoRemoveColumnsAndDetailConfigurations - { - get - { - return ( bool )this.GetValue( DataGridControl.AutoRemoveColumnsAndDetailConfigurationsProperty ); - } - set - { - this.SetValue( DataGridControl.AutoRemoveColumnsAndDetailConfigurationsProperty, value ); - } - } - - #endregion AutoRemoveColumnsAndDetailConfigurations Property - #region Columns Read-Only Property internal static readonly DependencyPropertyKey ColumnsPropertyKey = @@ -394,7 +280,7 @@ namespace Xceed.Wpf.DataGrid this.SetValue( DetailConfiguration.ColumnsPropertyKey, value ); } - #endregion Columns Read-Only Property + #endregion #region DefaultDetailConfiguration Property @@ -812,16 +698,16 @@ namespace Xceed.Wpf.DataGrid #endregion + #region ForeignKeysUpdatedOnAutoCreate Property - #region Events - - internal event EventHandler RequestingDelayBringIntoViewAndFocusCurrent; + internal bool ForeignKeysUpdatedOnAutoCreate + { + get; + set; + } #endregion - - // INTERNAL PROPERTIES - #region CurrentColumn Property internal ColumnBase CurrentColumn @@ -854,29 +740,23 @@ namespace Xceed.Wpf.DataGrid { get { - return m_columnsByVisiblePosition; + return m_columnManager.ColumnsByVisiblePosition; } } - private HashedLinkedList m_columnsByVisiblePosition; - #endregion - #region ItemsSourceFieldDescriptors Property + #region ItemsSourcePropertyDescriptions Internal Property - internal Dictionary ItemsSourceFieldDescriptors + internal PropertyDescriptionRouteDictionary ItemsSourcePropertyDescriptions { get { - return m_itemsSourceFieldDescriptors; - } - set - { - m_itemsSourceFieldDescriptors = value; + return m_itemsSourcePropertyDescriptions; } } - private Dictionary m_itemsSourceFieldDescriptors; // = null + private readonly PropertyDescriptionRouteDictionary m_itemsSourcePropertyDescriptions = new PropertyDescriptionRouteDictionary(); #endregion @@ -910,6 +790,7 @@ namespace Xceed.Wpf.DataGrid { m_sortDescriptionsSyncContext = new SortDescriptionsSyncContext(); } + return m_sortDescriptionsSyncContext; } } @@ -928,6 +809,8 @@ namespace Xceed.Wpf.DataGrid } } + private SortDescriptionCollection m_sortDescriptions; // = null + #endregion #region GroupDescriptions Read-Only Property @@ -940,24 +823,100 @@ namespace Xceed.Wpf.DataGrid } } + private ObservableCollection m_groupDescriptions; // = null + #endregion - #region DataGridControl Property + #region DataGridControl Internal Property internal DataGridControl DataGridControl { get { - if( m_containingCollection == null ) - return null; + return m_dataGridControl; + } + private set + { + if( value == m_dataGridControl ) + return; + + var oldDataGridControl = m_dataGridControl; + + if( m_dataGridControl != null ) + { + ViewChangedEventManager.RemoveListener( m_dataGridControl, this ); + } + + m_dataGridControl = value; + + if( m_dataGridControl != null ) + { + ViewChangedEventManager.AddListener( m_dataGridControl, this ); + } + + if( value != null ) + { + m_columnManager.Initialize( value ); + m_columnManager.SetFixedColumnCount( TableView.GetFixedColumnCount( this ) ); + } + else + { + m_columnManager.Clear(); + } + + var detailConfigurations = this.DetailConfigurations; + if( detailConfigurations != null ) + { + detailConfigurations.DataGridControl = value; + } + + this.InitializeItemPropertyMap( this.DataGridControl, this.DetailDescription ); + this.OnPropertyChanged( DetailConfiguration.DataGridControlPropertyName ); + + if( m_dataGridControl == null ) + { + this.BeginInit(); + } + else if( oldDataGridControl == null ) + { + this.EndInit(); + } + } + } + + private DataGridControl m_dataGridControl; + + #endregion + + #region DataGridContext Property - return m_containingCollection.DataGridControl; + internal DataGridContext DataGridContext + { + get + { + return m_dataGridContexts.FirstOrDefault(); } } - #endregion DataGridControl Property + internal void AddDataGridContext( DataGridContext dataGridContext ) + { + Debug.Assert( dataGridContext != null ); + + m_dataGridContexts.Add( dataGridContext ); + } + + internal void RemoveDataGridContext( DataGridContext dataGridContext ) + { + var oldCount = m_dataGridContexts.Count; + m_dataGridContexts.Remove( dataGridContext ); + var newCount = m_dataGridContexts.Count; + } + + private readonly ICollection m_dataGridContexts = new HashSet(); + + #endregion - #region ParentDetailConfiguration Property + #region ParentDetailConfiguration Internal Property internal DetailConfiguration ParentDetailConfiguration { @@ -970,9 +929,23 @@ namespace Xceed.Wpf.DataGrid } } - #endregion ParentDetailConfiguration Property + #endregion + + #region ColumnManagerRowConfiguration Internal Property + + internal ColumnManagerRowConfiguration ColumnManagerRowConfiguration + { + get + { + return m_columnManagerRowConfiguration; + } + } + + private readonly ColumnManagerRowConfiguration m_columnManagerRowConfiguration; + + #endregion - #region IsAutoCreated Property + #region IsAutoCreated Internal Property internal bool IsAutoCreated { @@ -980,27 +953,80 @@ namespace Xceed.Wpf.DataGrid { return m_isAutoCreated; } + private set + { + m_isAutoCreated = value; + } } - internal void SetIsAutoCreated( bool newValue ) + private bool m_isAutoCreated = false; + + #endregion + + #region IsCreatedFromSelector Property + + private bool IsCreatedFromSelector { - m_isAutoCreated = newValue; + get; + set; } - private bool m_isAutoCreated = false; + #endregion + + #region ItemPropertyMap Internal Property + + internal DataGridItemPropertyMap ItemPropertyMap + { + get + { + return m_itemPropertyMap; + } + } + + private readonly DataGridItemPropertyMap m_itemPropertyMap = new DataGridItemPropertyMap(); #endregion - #region RecyclingManager Read-Only property + #region UpdateColumnSortCommand Internal Property - internal RecyclingManager RecyclingManager + internal UpdateColumnSortCommand UpdateColumnSortCommand { get { - return m_recyclingManager; + if( m_updateColumnSortCommand == null ) + { + m_updateColumnSortCommand = new DetailConfigurationUpdateColumnSortCommand( this ); + } + + Debug.Assert( m_updateColumnSortCommand != null ); + + return m_updateColumnSortCommand; + } + } + + private UpdateColumnSortCommand m_updateColumnSortCommand; + + #endregion + + #region AddGroupCommand Internal Property + + internal ColumnAddGroupCommand AddGroupCommand + { + get + { + if( m_addGroupCommand == null ) + { + m_addGroupCommand = new DetailConfigurationAddGroupCommand( this ); + } + + Debug.Assert( m_addGroupCommand != null ); + + return m_addGroupCommand; } } + private ColumnAddGroupCommand m_addGroupCommand; + #endregion #region IsDeleteCommandEnabled Property @@ -1030,134 +1056,267 @@ namespace Xceed.Wpf.DataGrid #endregion IsDeleteCommandEnabled Property - #region Protected Methods + #region DetailDescription Internal Property - protected override void OnPropertyChanged( DependencyPropertyChangedEventArgs e ) + internal DataGridDetailDescription DetailDescription { - base.OnPropertyChanged( e ); - - if( e.Property == DetailConfiguration.GroupConfigurationSelectorProperty ) + get { - if( this.GroupConfigurationSelectorChanged != null ) - { - this.GroupConfigurationSelectorChanged( this, EventArgs.Empty ); - } + return m_detailDescription; + } + private set + { + if( value == m_detailDescription ) + return; + + m_detailDescription = value; + this.OnPropertyChanged( DetailConfiguration.DetailDescriptionPropertyName ); } } + private DataGridDetailDescription m_detailDescription; // = null + #endregion - #region Internal Methods + #region ContainingCollection Private Property - internal void AddDefaultHeadersFooters() + private DetailConfigurationCollection ContainingCollection { - if( m_defaultHeadersFootersAdded ) - return; + get + { + return m_containingCollection; + } + set + { + if( value == m_containingCollection ) + return; - m_defaultHeadersFootersAdded = true; + if( ( m_containingCollection != null ) && ( value != null ) ) + throw new InvalidOperationException( "The DetailConfiguration is already contained in another DetailConfigurationCollection." ); - DetailConfiguration.AddDefaultHeadersFooters( this.Headers, this.Footers ); + if( m_containingCollection != null ) + { + ( ( INotifyPropertyChanged )m_containingCollection ).PropertyChanged -= new PropertyChangedEventHandler( this.OnContainingCollectionPropertyChanged ); + } + + m_containingCollection = value; + + if( m_containingCollection != null ) + { + ( ( INotifyPropertyChanged )m_containingCollection ).PropertyChanged += new PropertyChangedEventHandler( this.OnContainingCollectionPropertyChanged ); + + this.DataGridControl = m_containingCollection.DataGridControl; + } + else + { + this.DataGridControl = null; + } + } } - internal void SynchronizeForeignKeyConfigurations() + private void OnContainingCollectionPropertyChanged( object sender, PropertyChangedEventArgs e ) { - if( m_detailDescription == null ) - return; + var containingCollection = ( DetailConfigurationCollection )sender; + Debug.Assert( containingCollection == this.ContainingCollection ); - ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( - this.Columns.FieldNameToColumnDictionary, - m_detailDescription.ItemProperties, - this.AutoCreateForeignKeyConfigurations ); + var propertyName = e.PropertyName; + bool mayHaveChanged = string.IsNullOrEmpty( propertyName ); + + if( mayHaveChanged || ( propertyName == "DataGridControl" ) ) + { + this.DataGridControl = containingCollection.DataGridControl; + } } + private DetailConfigurationCollection m_containingCollection; // = null + #endregion - #region Private Methods + #region ColumnSynchronizationManager Private Read-Only Property - private void SynchronizeWithDetailDescription( DataGridDetailDescription detailDescription ) + private ColumnSynchronizationManager ColumnSynchronizationManager { - if( detailDescription != m_detailDescription ) + get { - this.DetachFromDetailDescription(); + return m_columnSynchronizationManager; + } + } - m_shouldCreateColumns = true; - m_detailDescription = detailDescription; + private readonly ColumnSynchronizationManager m_columnSynchronizationManager; - DataGridSortDescriptionCollection dataGridSortDescriptionCollection = null; + #endregion - if( detailDescription != null ) - { - //register to the collectionchanged of the DataGridDetailDescription collection of the detailDescription matching this one. - dataGridSortDescriptionCollection = detailDescription.DataGridSortDescriptions; - m_groupDescriptions = detailDescription.GroupDescriptions; + #region ColumnManager Internal Property - CollectionChangedEventManager.AddListener( detailDescription.ItemProperties, this ); - CollectionChangedEventManager.AddListener( detailDescription.DetailDescriptions, this ); - } - else - { - dataGridSortDescriptionCollection = new DataGridSortDescriptionCollection(); - m_groupDescriptions = new GroupDescriptionCollection(); - } + internal ColumnHierarchyManager ColumnManager + { + get + { + return m_columnManager; + } + } - m_sortDescriptions = dataGridSortDescriptionCollection; - m_sortDescriptionsSyncContext = null; //clear it, if it was ever set! + private readonly ColumnHierarchyManager m_columnManager; + #endregion - //This update is required since there might be some columns in the Columns collection after the XAML parsing of the DetailConfiguration - DataGridContext.SynchronizeSortProperties( dataGridSortDescriptionCollection.SyncContext, m_sortDescriptions, this.Columns ); + public IDisposable DeferColumnsUpdate() + { + return ColumnHierarchyManagerHelper.DeferColumnsUpdate( this ); + } - //This update is required since we want the GroupLevelDescriptions to be created if DetailConfiguration in XAML - //contains GroupDescriptions - DataGridContext.UpdateGroupLevelDescriptions( this.GroupLevelDescriptions, new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ), this.GroupDescriptions, this.Columns ); + public bool MoveColumnBefore( ColumnBase current, ColumnBase next ) + { + return ColumnHierarchyManagerHelper.MoveColumnBefore( this, current, next ); + } - CollectionChangedEventManager.AddListener( m_sortDescriptions, this ); - CollectionChangedEventManager.AddListener( m_groupDescriptions, this ); + public bool MoveColumnAfter( ColumnBase current, ColumnBase previous ) + { + return ColumnHierarchyManagerHelper.MoveColumnAfter( this, current, previous ); + } - if( detailDescription != null ) + public bool MoveColumnUnder( ColumnBase current, ColumnBase parent ) + { + return ColumnHierarchyManagerHelper.MoveColumnUnder( this, current, parent ); + } + + protected override void OnPropertyChanged( DependencyPropertyChangedEventArgs e ) + { + base.OnPropertyChanged( e ); + + if( e.Property == DetailConfiguration.GroupConfigurationSelectorProperty ) + { + var handler = this.GroupConfigurationSelectorChanged; + if( handler != null ) { - if( this.ReadLocalValue( DetailConfiguration.TitleProperty ) == DependencyProperty.UnsetValue ) + handler.Invoke( this, EventArgs.Empty ); + } + } + + this.OnPropertyChanged( e.Property.Name ); + } + + internal void AddDefaultHeadersFooters() + { + if( m_defaultHeadersFootersAdded ) + return; + + m_defaultHeadersFootersAdded = true; + + DetailConfiguration.AddDefaultHeadersFooters( this.Headers, 0, this.DataGridControl.AreDetailsFlatten ); + } + + internal void SynchronizeForeignKeyConfigurations() + { + var detailDescription = this.DetailDescription; + if( detailDescription == null ) + return; + + ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( + this.Columns, + detailDescription.ItemProperties, + this.AutoCreateForeignKeyConfigurations ); + } + + internal void AttachToContainingCollection( DetailConfigurationCollection detailConfigurationCollection ) + { + if( detailConfigurationCollection == null ) + throw new ArgumentNullException( "detailConfigurationCollection" ); + + this.ContainingCollection = detailConfigurationCollection; + } + + internal void DetachFromContainingCollection() + { + this.ContainingCollection = null; + } + + private void SynchronizeWithDetailDescription( DataGridDetailDescription detailDescription ) + { + if( detailDescription == this.DetailDescription ) + return; + + this.DetachFromDetailDescription( false ); + + m_shouldCreateColumns = true; + this.DetailDescription = detailDescription; + + DataGridSortDescriptionCollection dataGridSortDescriptionCollection; + ObservableCollection groupDescriptionCollection; + + if( detailDescription != null ) + { + groupDescriptionCollection = detailDescription.GroupDescriptions; + + //register to the collectionchanged of the DataGridDetailDescription collection of the detailDescription matching this one. + dataGridSortDescriptionCollection = detailDescription.DataGridSortDescriptions; + + this.RegisterItemProperties( detailDescription.ItemProperties ); + + CollectionChangedEventManager.AddListener( detailDescription.DetailDescriptions, this ); + } + else + { + groupDescriptionCollection = new GroupDescriptionCollection(); + dataGridSortDescriptionCollection = new DataGridSortDescriptionCollection(); + } + + m_groupDescriptions = groupDescriptionCollection; + m_sortDescriptions = dataGridSortDescriptionCollection; + m_sortDescriptionsSyncContext = null; //clear it, if it was ever set! + + this.InitializeItemPropertyMap( this.DataGridControl, detailDescription ); + + //This update is required since there might be some columns in the columns collection after the XAML parsing of the DetailConfiguration + this.UpdateColumnSortOrder(); + + //This update is required since we want the GroupLevelDescriptions to be created if DetailConfiguration in XAML + //contains GroupDescriptions + DataGridContext.UpdateGroupLevelDescriptions( this.GroupLevelDescriptions, + new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ), + this.GroupDescriptions, + this.Columns ); + + CollectionChangedEventManager.AddListener( m_sortDescriptions, this ); + CollectionChangedEventManager.AddListener( m_groupDescriptions, this ); + + if( detailDescription != null ) + { + if( this.ReadLocalValue( DetailConfiguration.TitleProperty ) == DependencyProperty.UnsetValue ) + { + if( detailDescription.Title == null ) { - if( detailDescription.Title == null ) - { - this.Title = detailDescription.RelationName; - } - else - { - this.Title = detailDescription.Title; - } + this.Title = detailDescription.RelationName; } - - if( ( this.ReadLocalValue( DetailConfiguration.TitleTemplateProperty ) == DependencyProperty.UnsetValue ) - && ( detailDescription.TitleTemplate != null ) ) + else { - this.TitleTemplate = detailDescription.TitleTemplate; + this.Title = detailDescription.Title; } + } - DetailConfiguration.SynchronizeDetailConfigurations( - detailDescription.DetailDescriptions, - this.DetailConfigurations, - this.AutoCreateDetailConfigurations, - this.AutoCreateForeignKeyConfigurations, - this.AutoRemoveColumnsAndDetailConfigurations ); + if( ( this.ReadLocalValue( DetailConfiguration.TitleTemplateProperty ) == DependencyProperty.UnsetValue ) + && ( detailDescription.TitleTemplate != null ) ) + { + this.TitleTemplate = detailDescription.TitleTemplate; } } - if( detailDescription != null ) - { - ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( - this.Columns.FieldNameToColumnDictionary, - detailDescription.ItemProperties, - this.AutoCreateForeignKeyConfigurations ); - } + this.UpdateColumns(); } private void DetachFromDetailDescription() { - if( m_detailDescription != null ) + this.DetachFromDetailDescription( true ); + } + + private void DetachFromDetailDescription( bool synchronizeColumns ) + { + var detailDescription = this.DetailDescription; + if( detailDescription != null ) { - CollectionChangedEventManager.RemoveListener( m_detailDescription.ItemProperties, this ); - CollectionChangedEventManager.RemoveListener( m_detailDescription.DetailDescriptions, this ); + this.UnregisterItemProperties( detailDescription.ItemProperties ); + + CollectionChangedEventManager.RemoveListener( detailDescription.DetailDescriptions, this ); } if( m_sortDescriptions != null ) @@ -1172,32 +1331,135 @@ namespace Xceed.Wpf.DataGrid m_sortDescriptions = null; m_groupDescriptions = null; - m_detailDescription = null; + m_itemsSourcePropertyDescriptions.Clear(); + + this.InitializeItemPropertyMap( this.DataGridControl, null ); + this.DetailDescription = null; - m_recyclingManager.Clear(); + if( synchronizeColumns ) + { + m_columnSynchronizationManager.Refresh(); + } } - private void SortDescriptions_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e ) + private void InitializeItemPropertyMap( DataGridControl dataGridControl, DataGridDetailDescription detailDescription ) { - bool runSynchronization = true; + using( m_itemPropertyMap.DeferMappingChanged() ) + { + if( ( dataGridControl == null ) || ( detailDescription == null ) || !dataGridControl.AreDetailsFlatten ) + { + m_itemPropertyMap.MasterItemProperties = null; + m_itemPropertyMap.DetailItemProperties = null; + } + else + { + var collectionView = dataGridControl.Items.SourceCollection as DataGridCollectionViewBase; + if( collectionView != null ) + { + m_itemPropertyMap.MasterItemProperties = collectionView.ItemProperties; + m_itemPropertyMap.DetailItemProperties = detailDescription.ItemProperties; + } + else + { + m_itemPropertyMap.MasterItemProperties = null; + m_itemPropertyMap.DetailItemProperties = null; + } + } + } + } + + private void UpdateColumns() + { + var detailDescription = this.DetailDescription; + var dataGridControl = this.DataGridControl; + var dataGridContext = this.DataGridContext; + + if( ( detailDescription != null ) && ( dataGridControl != null ) && ( dataGridContext != null ) ) + { + ItemsSourceHelper.ResetPropertyDescriptions( m_itemsSourcePropertyDescriptions, m_itemPropertyMap, dataGridControl, dataGridContext.Items ); + + if( this.AutoCreateColumns ) + { + ItemsSourceHelper.UpdateColumnsFromPropertyDescriptions( m_columnManager, dataGridControl.DefaultCellEditors, m_itemsSourcePropertyDescriptions, this.AutoCreateForeignKeyConfigurations ); + } + } + else + { + m_itemsSourcePropertyDescriptions.Clear(); + } + + if( detailDescription != null ) + { + // Ensure to update ForeignKeyDescriptions and ForeignKeyConfigurations when ItemProperties change on DetailDescription. + ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( + this.Columns, + detailDescription.ItemProperties, + this.AutoCreateForeignKeyConfigurations ); + } + } + + private void RegisterItemProperties( DataGridItemPropertyCollection itemProperties ) + { + if( itemProperties == null ) + return; + + CollectionChangedEventManager.AddListener( itemProperties, this ); - this.RequestDelayBringIntoViewAndFocusCurrent(); + foreach( var itemProperty in itemProperties ) + { + this.RegisterItemProperty( itemProperty ); + } + } - //If the resort is defered, it's because another section of code is already taking care of the update... Do not process the change notification - DataGridSortDescriptionCollection dataGridSortDescriptions = m_sortDescriptions as DataGridSortDescriptionCollection; - if( dataGridSortDescriptions != null ) - runSynchronization = !dataGridSortDescriptions.IsResortDefered; + private void UnregisterItemProperties( DataGridItemPropertyCollection itemProperties ) + { + if( itemProperties == null ) + return; - if( runSynchronization == true ) + foreach( var itemProperty in itemProperties ) { - //No need to protect against SortDescriptions being null, since this reacts to the sort descriptions changes - DataGridContext.SynchronizeSortProperties( this.SortDescriptionsSyncContext, m_sortDescriptions, this.Columns ); + this.UnregisterItemProperty( itemProperty ); } + + CollectionChangedEventManager.RemoveListener( itemProperties, this ); + } + + private void RegisterItemProperty( DataGridItemPropertyBase itemProperty ) + { + if( itemProperty == null ) + return; + + PropertyChangedEventManager.AddListener( itemProperty, this, DataGridItemPropertyBase.ItemPropertiesInternalPropertyName ); + this.RegisterItemProperties( itemProperty.ItemPropertiesInternal ); + } + + private void UnregisterItemProperty( DataGridItemPropertyBase itemProperty ) + { + if( itemProperty == null ) + return; + + this.UnregisterItemProperties( itemProperty.ItemPropertiesInternal ); + PropertyChangedEventManager.RemoveListener( itemProperty, this, DataGridItemPropertyBase.ItemPropertiesInternalPropertyName ); + } + + private void UpdateColumnSortOrder() + { + var updateColumnSortCommand = this.UpdateColumnSortCommand; + if( updateColumnSortCommand.CanExecute() ) + { + this.UpdateColumnSortCommand.Execute(); + } + } + + private void SortDescriptions_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e ) + { + this.RequestDelayBringIntoViewAndFocusCurrent( AutoScrollCurrentItemSourceTriggers.SortChanged ); + this.UpdateColumnSortOrder(); } private void GroupDescriptions_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e ) { - this.RequestDelayBringIntoViewAndFocusCurrent(); + this.RequestDelayBringIntoViewAndFocusCurrent( AutoScrollCurrentItemSourceTriggers.GroupChanged ); DataGridContext.UpdateGroupLevelDescriptions( this.GroupLevelDescriptions, e, m_groupDescriptions, this.Columns ); } @@ -1206,91 +1468,138 @@ namespace Xceed.Wpf.DataGrid //call the method that will detect if the CurrentColumn should be removed based on the changes in the Columns collection. this.HandleCurrentColumnRemove( e ); - this.RequestDelayBringIntoViewAndFocusCurrent(); + this.RequestDelayBringIntoViewAndFocusCurrent( AutoScrollCurrentItemSourceTriggers.ColumnsCollectionChanged ); + this.UpdateColumnSortOrder(); - //Then call the method that will update the VisibleColumns - DataGridContext.HandleColumnsCollectionChanged( e, this.Columns, - this.VisibleColumns as ReadOnlyColumnCollection, - this.ColumnsByVisiblePosition, - this.SortDescriptionsSyncContext, - m_sortDescriptions ); - - if( m_detailDescription != null ) + var detailDescription = this.DetailDescription; + if( detailDescription != null ) { switch( e.Action ) { + case NotifyCollectionChangedAction.Add: + case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Reset: { ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( - this.Columns.FieldNameToColumnDictionary, - m_detailDescription.ItemProperties, + this.Columns, + detailDescription.ItemProperties, this.AutoCreateForeignKeyConfigurations ); - - break; } + break; - case NotifyCollectionChangedAction.Add: - case NotifyCollectionChangedAction.Replace: - { - IList newItems = e.NewItems; - int count = newItems.Count; - Dictionary newColumns = new Dictionary( count ); + default: + break; + } + } + } - for( int i = 0; i < count; i++ ) - { - ColumnBase column = newItems[ i ] as ColumnBase; - newColumns.Add( column.FieldName, column ); - } + private void OnItemPropertiesCollectionChanged( DataGridItemPropertyCollection collection, NotifyCollectionChangedEventArgs e ) + { + var detailDescription = this.DetailDescription; + if( detailDescription == null ) + return; - ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( - newColumns, - m_detailDescription.ItemProperties, - this.AutoCreateForeignKeyConfigurations ); + var rootCollection = ItemsSourceHelper.GetRootCollection( collection ); + if( rootCollection == null ) + return; - break; - } + if( rootCollection == detailDescription.ItemProperties ) + { + if( e.Action == NotifyCollectionChangedAction.Reset ) + throw new NotSupportedException(); + + if( e.Action == NotifyCollectionChangedAction.Move ) + return; + + if( e.OldItems != null ) + { + foreach( DataGridItemPropertyBase itemProperty in e.OldItems ) + { + this.UnregisterItemProperty( itemProperty ); + } + } + + if( e.NewItems != null ) + { + foreach( DataGridItemPropertyBase itemProperty in e.NewItems ) + { + this.RegisterItemProperty( itemProperty ); + } + } + + this.UpdateColumns(); + } + else + { + Debug.Fail( "The collection is not linked to the detail configuration's item properties." ); + this.UnregisterItemProperties( collection ); + } + } + + private void OnItemPropertyPropertyChanged( DataGridItemPropertyBase itemProperty, PropertyChangedEventArgs e ) + { + var detailDescription = this.DetailDescription; + if( detailDescription == null ) + return; + + var rootCollection = ItemsSourceHelper.GetRootCollection( itemProperty ); + if( rootCollection == null ) + return; + + if( rootCollection != detailDescription.ItemProperties ) + { + Debug.Fail( "The collection is not linked to the detail configuration's item properties." ); + this.UnregisterItemProperty( itemProperty ); + return; + } + + if( string.IsNullOrEmpty( e.PropertyName ) || ( e.PropertyName == DataGridItemPropertyBase.ItemPropertiesInternalPropertyName ) ) + { + var itemProperties = itemProperty.ItemPropertiesInternal; + if( itemProperties != null ) + { + this.UnregisterItemProperties( itemProperties ); + this.RegisterItemProperties( itemProperties ); + this.UpdateColumns(); } } } private void HandleCurrentColumnRemove( NotifyCollectionChangedEventArgs e ) { - bool removeCurrentColumn = false; - ColumnBase currentColumn = this.CurrentColumn; + var currentColumn = this.CurrentColumn; + if( currentColumn == null ) + return; + + var removeCurrentColumn = false; if( e.Action == NotifyCollectionChangedAction.Reset ) { - //Reset means that collection was cleared. - removeCurrentColumn = true; + removeCurrentColumn = !this.Columns.Contains( currentColumn ); } - else if( ( e.Action == NotifyCollectionChangedAction.Remove ) && ( e.OldItems.Contains( currentColumn ) == true ) ) + else if( ( e.Action == NotifyCollectionChangedAction.Remove ) && ( e.OldItems.Contains( currentColumn ) ) ) { //Remove of at least the current column removeCurrentColumn = true; } - else if( ( e.Action == NotifyCollectionChangedAction.Replace ) && ( e.OldItems.Contains( currentColumn ) == true ) - && ( e.NewItems.Contains( currentColumn ) == false ) ) + else if( ( e.Action == NotifyCollectionChangedAction.Replace ) && ( e.OldItems.Contains( currentColumn ) ) && ( !e.NewItems.Contains( currentColumn ) ) ) { //Replace in which at least the current column was "replaced" by another (current column not present in new items ) removeCurrentColumn = true; } //If we computed that current columns should be cleared - if( removeCurrentColumn == true ) + if( removeCurrentColumn ) { //reset current column. this.CurrentColumn = DataGridContext.GetClosestColumn( currentColumn, this.ColumnsByVisiblePosition ); } - } private void OnDetailConfigurationsChanged( object sender, NotifyCollectionChangedEventArgs e ) { - DataGridDetailDescriptionCollection detailDescriptions = null; - if( m_detailDescription != null ) - { - detailDescriptions = m_detailDescription.DetailDescriptions; - } + var detailDescription = this.DetailDescription; + var detailDescriptions = ( detailDescription != null ) ? detailDescription.DetailDescriptions : null; switch( e.Action ) { @@ -1306,81 +1615,63 @@ namespace Xceed.Wpf.DataGrid } } - private void RequestDelayBringIntoViewAndFocusCurrent() + private void RequestDelayBringIntoViewAndFocusCurrent( AutoScrollCurrentItemSourceTriggers trigger ) { - if( this.RequestingDelayBringIntoViewAndFocusCurrent != null ) - { - this.RequestingDelayBringIntoViewAndFocusCurrent( this, EventArgs.Empty ); - } } - #endregion - #region IWeakEventListener Members bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e ) + { + return this.OnReceiveWeakEvent( managerType, sender, e ); + } + + private bool OnReceiveWeakEvent( Type managerType, object sender, EventArgs e ) { //check if the event comes from a INotifyCollectionChanged collection if( managerType == typeof( CollectionChangedEventManager ) ) { - NotifyCollectionChangedEventArgs ncce = ( NotifyCollectionChangedEventArgs )e; + var eventArgs = ( NotifyCollectionChangedEventArgs )e; if( sender is DetailConfigurationCollection ) { - this.OnDetailConfigurationsChanged( sender, ncce ); - return true; + this.OnDetailConfigurationsChanged( sender, eventArgs ); } else if( sender is SortDescriptionCollection ) { - this.SortDescriptions_CollectionChanged( sender, ncce ); - return true; + this.SortDescriptions_CollectionChanged( sender, eventArgs ); } else if( sender is ObservableCollection ) { - this.GroupDescriptions_CollectionChanged( sender, ncce ); - return true; + this.GroupDescriptions_CollectionChanged( sender, eventArgs ); } else if( sender is DataGridDetailDescriptionCollection ) { - if( m_detailDescription != null ) - { - DetailConfiguration.SynchronizeDetailConfigurations( - m_detailDescription.DetailDescriptions, - this.DetailConfigurations, - this.AutoCreateDetailConfigurations, - this.AutoCreateForeignKeyConfigurations, - this.AutoRemoveColumnsAndDetailConfigurations ); - } - - return true; } else if( sender is DataGridItemPropertyCollection ) { - // Ensure to update ForeignKeyDescriptions and ForeignKeyConfigurations - // when ItemProperties change on DetailDescription - if( m_detailDescription != null ) - { - ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( - this.Columns.FieldNameToColumnDictionary, - m_detailDescription.ItemProperties, - this.AutoCreateForeignKeyConfigurations ); - } - return true; + this.OnItemPropertiesCollectionChanged( ( DataGridItemPropertyCollection )sender, eventArgs ); } } - - if( managerType == typeof( VisibilityChangedEventManager ) ) + else if( managerType == typeof( PropertyChangedEventManager ) ) { - var wrappedEventArgs = ( ColumnCollection.WrappedEventEventArgs )e; - - DataGridContext.UpdateVisibleColumns( - this.Columns, this.VisibleColumns as ReadOnlyColumnCollection, this.ColumnsByVisiblePosition, - new object[] { wrappedEventArgs.WrappedSender }, wrappedEventArgs.WrappedEventArgs as ColumnVisiblePositionChangedEventArgs ); + var eventArgs = ( PropertyChangedEventArgs )e; - return true; + if( sender is DataGridItemPropertyBase ) + { + this.OnItemPropertyPropertyChanged( ( DataGridItemPropertyBase )sender, eventArgs ); + } + } + else if( managerType == typeof( ViewChangedEventManager ) ) + { + this.InitializeItemPropertyMap( this.DataGridControl, this.DetailDescription ); + } + else + { + return false; } - return false; + return true; } #endregion @@ -1389,31 +1680,35 @@ namespace Xceed.Wpf.DataGrid public void BeginInit() { - m_beginInitCount++; + m_initCount++; + if( m_initCount != 1 ) + return; - //It is determined at construction of the DetailConfiguration if it is synchronized with its parent, therefore, I can assume it is set appropriatly here - if( m_columnsInitDisposable == null ) - { - m_columnsInitDisposable = this.Columns.DeferColumnAdditionMessages(); - } + Debug.Assert( m_deferColumnsLayoutUpdate == null ); + m_deferColumnsLayoutUpdate = m_columnManager.DeferUpdate(); + + m_deferColumnsNotifications = this.Columns.DeferNotifications(); } public void EndInit() { - if( m_beginInitCount > 0 ) - m_beginInitCount--; + m_initCount--; + if( m_initCount != 0 ) + return; - if( m_beginInitCount == 0 ) - { - if( m_columnsInitDisposable != null ) - { - m_columnsInitDisposable.Dispose(); - m_columnsInitDisposable = null; - } - } + var columnsNotificationsDisposable = m_deferColumnsNotifications; + m_deferColumnsNotifications = null; + columnsNotificationsDisposable.Dispose(); + + Debug.Assert( m_deferColumnsLayoutUpdate != null ); + var columnsUpdateDisposable = m_deferColumnsLayoutUpdate; + m_deferColumnsLayoutUpdate = null; + columnsUpdateDisposable.Dispose(); } - private int m_beginInitCount = 0; + private int m_initCount = 0; + private IDisposable m_deferColumnsLayoutUpdate; //null + private IDisposable m_deferColumnsNotifications; //null #endregion @@ -1423,67 +1718,353 @@ namespace Xceed.Wpf.DataGrid private void OnPropertyChanged( string propertyName ) { - if( this.PropertyChanged != null ) - { - this.PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) ); - } + var handler = this.PropertyChanged; + if( handler == null ) + return; + + handler.Invoke( this, new PropertyChangedEventArgs( propertyName ) ); } #endregion - #region ContainingCollection Methods + private bool m_shouldCreateColumns = true; + private bool m_defaultHeadersFootersAdded; // = false - internal void AttachToContainingCollection( DetailConfigurationCollection detailConfigurationCollection ) + private sealed class DetailConfigurationUpdateColumnSortCommand : UpdateColumnSortCommand { - if( m_containingCollection == detailConfigurationCollection ) - return; + private static void ThrowIfDetailsNotFlatten( DetailConfiguration detailConfiguration ) + { + Debug.Assert( detailConfiguration != null ); - Debug.Assert( detailConfigurationCollection != null, "For clarity purposes, you should use Detach in this context... or remove this assert." ); + var dataGridControl = detailConfiguration.DataGridControl; + if( ( dataGridControl != null ) && ( !dataGridControl.AreDetailsFlatten ) ) + throw new InvalidOperationException( "This method cannot be invoked when details are not flattened." ); + } - if( detailConfigurationCollection == null ) + internal DetailConfigurationUpdateColumnSortCommand( DetailConfiguration detailConfiguration ) { - this.DetachFromContainingCollection(); + DetailConfigurationUpdateColumnSortCommand.ThrowIfNull( detailConfiguration, "detailConfiguration" ); + + m_detailConfiguration = new WeakReference( detailConfiguration ); } - else + + #region SortDescriptionsSyncContext Protected Property + + protected override SortDescriptionsSyncContext SortDescriptionsSyncContext + { + get + { + var detailConfiguration = this.DetailConfiguration; + if( detailConfiguration == null ) + return null; + + return detailConfiguration.SortDescriptionsSyncContext; + } + } + + #endregion + + #region DetailConfiguration Private Property + + private DetailConfiguration DetailConfiguration + { + get + { + return m_detailConfiguration.Target as DetailConfiguration; + } + } + + private readonly WeakReference m_detailConfiguration; + + #endregion + + protected override bool CanExecuteCore() + { + var detailConfiguration = this.DetailConfiguration; + if( detailConfiguration == null ) + return false; + + var dataGridControl = detailConfiguration.DataGridControl; + if( dataGridControl == null ) + return false; + + var detailDescription = detailConfiguration.DetailDescription; + if( detailDescription == null ) + return false; + + return true; + } + + protected override void ExecuteCore() + { + DetailConfiguration detailConfiguration = this.DetailConfiguration; + if( detailConfiguration == null ) + return; + + var dataGridControl = detailConfiguration.DataGridControl; + if( dataGridControl == null ) + return; + + using( var synchronizationContext = this.StartSynchronizing( detailConfiguration.SortDescriptionsSyncContext ) ) + { + // The SortDescription collection is already being updated. + if( !synchronizationContext.Own ) + return; + + // The sort order of the flatten details is driven by the master. Flatten details are not + // allowed to modify the sort order at their level. + if( dataGridControl.AreDetailsFlatten ) + { + this.SynchronizeDetailSortDescriptions( synchronizationContext, detailConfiguration ); + } + + this.SynchronizeColumnSort( + synchronizationContext, + detailConfiguration.SortDescriptions, + detailConfiguration.Columns ); + } + } + + private static IEnumerable GetDataGridContexts( DetailConfiguration detailConfiguration ) { - m_containingCollection = detailConfigurationCollection; + Debug.Assert( detailConfiguration != null ); + + var dataGridControl = detailConfiguration.DataGridControl; + Debug.Assert( dataGridControl != null ); - if( this.Columns != null ) - this.Columns.DataGridControl = this.DataGridControl; + var queue = new Queue(); + queue.Enqueue( dataGridControl.DataGridContext ); - if( this.DetailConfigurations != null ) - this.DetailConfigurations.DataGridControl = this.DataGridControl; + while( queue.Count > 0 ) + { + DataGridContext dataGridContext = queue.Dequeue(); + + if( dataGridContext.SourceDetailConfiguration == detailConfiguration ) + { + yield return dataGridContext; + } + else + { + foreach( var childContext in dataGridContext.GetChildContexts() ) + { + queue.Enqueue( childContext ); + } + } + } + } + + private IDisposable DeferResortHelper( DetailConfiguration detailConfiguration ) + { + ColumnSortCommand.ThrowIfNull( detailConfiguration, "detailConfiguration" ); + + IDisposable defer; + if( this.TryDeferResort( detailConfiguration, out defer ) ) + return defer; + + var disposer = new Disposer(); + + foreach( var dataGridContext in DetailConfigurationUpdateColumnSortCommand.GetDataGridContexts( detailConfiguration ) ) + { + disposer.Add( this.DeferResortHelper( dataGridContext.ItemsSourceCollection, dataGridContext.Items ), DisposableType.DeferResort ); + } + + return disposer; + } + + private void SynchronizeDetailSortDescriptions( SynchronizationContext synchronizationContext, DetailConfiguration detailConfiguration ) + { + ColumnSortCommand.ThrowIfNull( synchronizationContext, "synchronizationContext" ); + ColumnSortCommand.ThrowIfNull( detailConfiguration, "detailConfiguration" ); + DetailConfigurationUpdateColumnSortCommand.ThrowIfDetailsNotFlatten( detailConfiguration ); + + if( !synchronizationContext.Own ) + return; + + if( detailConfiguration.DetailDescription == null ) + return; + + var dataGridControl = detailConfiguration.DataGridControl; + if( dataGridControl == null ) + return; + + var rootDataGridContext = dataGridControl.DataGridContext; + var masterSortDescriptions = rootDataGridContext.Items.SortDescriptions; + var detailSortDescriptions = detailConfiguration.SortDescriptions; + + // There is nothing to synchronize. + if( ( masterSortDescriptions.Count == 0 ) && ( detailSortDescriptions.Count == 0 ) ) + return; + + using( this.DeferResortHelper( detailConfiguration ) ) + { + this.SynchronizeDetailSortDescriptions( masterSortDescriptions, detailSortDescriptions, detailConfiguration ); + } + } + + private void SynchronizeDetailSortDescriptions( SortDescriptionCollection masterSortDescriptions, SortDescriptionCollection detailSortDescriptions, DetailConfiguration detailConfiguration ) + { + ColumnSortCommand.ThrowIfNull( masterSortDescriptions, "masterSortDescriptions" ); + ColumnSortCommand.ThrowIfNull( detailSortDescriptions, "detailSortDescriptions" ); + + var itemPropertyMap = detailConfiguration.ItemPropertyMap; + ColumnSortCommand.ThrowIfNull( itemPropertyMap, "itemPropertyMap" ); + + var masterSortDescriptionsCount = masterSortDescriptions.Count; + if( masterSortDescriptionsCount > 0 ) + { + var insertionIndex = 0; + + for( int i = 0; i < masterSortDescriptionsCount; i++ ) + { + var sortDescription = masterSortDescriptions[ i ]; + var detailPropertyName = default( string ); + + if( !DataGridItemPropertyMapHelper.TryGetDetailColumnName( itemPropertyMap, sortDescription.PropertyName, out detailPropertyName ) ) + continue; + + var detailDirection = sortDescription.Direction; + + if( insertionIndex < detailSortDescriptions.Count ) + { + var detailSortDescription = detailSortDescriptions[ insertionIndex ]; + + if( ( detailSortDescription.PropertyName != detailPropertyName ) || ( detailSortDescription.Direction != detailDirection ) ) + { + detailSortDescriptions[ insertionIndex ] = new SortDescription( detailPropertyName, detailDirection ); + } + } + else + { + detailSortDescriptions.Add( new SortDescription( detailPropertyName, detailDirection ) ); + } + + insertionIndex++; + } + + while( insertionIndex < detailSortDescriptions.Count ) + { + detailSortDescriptions.RemoveAt( insertionIndex ); + } + } + else if( detailSortDescriptions.Count > 0 ) + { + detailSortDescriptions.Clear(); + } } } - internal void DetachFromContainingCollection() + private sealed class DetailConfigurationAddGroupCommand : ColumnAddGroupCommand { - m_containingCollection = null; + internal DetailConfigurationAddGroupCommand( DetailConfiguration detailConfiguration ) + { + DetailConfigurationAddGroupCommand.ThrowIfNull( detailConfiguration, "detailConfiguration" ); - if( this.Columns != null ) - this.Columns.DataGridControl = this.DataGridControl; + m_detailConfiguration = new WeakReference( detailConfiguration ); + } - if( this.DetailConfigurations != null ) - this.DetailConfigurations.DataGridControl = this.DataGridControl; - } + #region GroupDescriptions Protected Property - #endregion ContainingCollection Methods + protected override ObservableCollection GroupDescriptions + { + get + { + var detailConfiguration = this.DetailConfiguration; + if( detailConfiguration == null ) + return null; - #region Private Fields + return detailConfiguration.GroupDescriptions; + } + } - private DetailConfigurationCollection m_containingCollection; // = null + #endregion - private SortDescriptionCollection m_sortDescriptions; // = null - private ObservableCollection m_groupDescriptions; // = null + #region DetailConfiguration Private Property - private bool m_shouldCreateColumns = true; - private IDisposable m_columnsInitDisposable; // = null - private bool m_defaultHeadersFootersAdded; // = false + private DetailConfiguration DetailConfiguration + { + get + { + return m_detailConfiguration.Target as DetailConfiguration; + } + } - private readonly RecyclingManager m_recyclingManager = new RecyclingManager(); + private readonly WeakReference m_detailConfiguration; - private DataGridDetailDescription m_detailDescription; // = null + #endregion - #endregion + protected override string GetColumnName( ColumnBase column ) + { + var detailConfiguration = this.DetailConfiguration; + if( ( detailConfiguration == null ) || ( column == null ) ) + return null; + + var itemPropertyMap = detailConfiguration.ItemPropertyMap; + if( ( itemPropertyMap != null ) && itemPropertyMap.IsMapping ) + { + string fieldName; + if( DataGridItemPropertyMapHelper.TryGetDetailColumnName( itemPropertyMap, column.FieldName, out fieldName ) ) + return fieldName; + } + else + { + return column.FieldName; + } + + return null; + } + + protected override GroupDescription GetGroupDescription( ColumnBase column ) + { + var detailConfiguration = this.DetailConfiguration; + if( detailConfiguration == null ) + return null; + + return base.GetGroupDescription( column ); + } + + protected override GroupConfiguration GetGroupConfiguration( ColumnBase column ) + { + var detailConfiguration = this.DetailConfiguration; + if( detailConfiguration == null ) + return null; + + return base.GetGroupConfiguration( column ); + } + + protected override bool CanExecuteCore( ColumnBase column, int index ) + { + if( this.DetailConfiguration == null ) + return false; + + return base.CanExecuteCore( column, index ); + } + + protected override void ExecuteCore( ColumnBase column, int index ) + { + var detailConfig = this.DetailConfiguration; + if( detailConfig == null ) + return; + + var dataGridControl = detailConfig.DataGridControl; + IDisposable disposable = null; + + try + { + if( dataGridControl != null ) + { + disposable = dataGridControl.SetQueueBringIntoViewRestrictions( AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged ); + } + + base.ExecuteCore( column, index ); + } + finally + { + if( disposable != null ) + { + disposable.Dispose(); + } + } + } + } } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfigurationCollection.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfigurationCollection.cs index be1a210e..22632842 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfigurationCollection.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfigurationCollection.cs @@ -15,18 +15,14 @@ ***********************************************************************************/ using System; -using System.Collections.Generic; -using System.Text; using System.Collections.ObjectModel; +using System.ComponentModel; using System.Windows; -using System.Collections.Specialized; namespace Xceed.Wpf.DataGrid { internal class DetailConfigurationCollection : ObservableCollection, IWeakEventListener { - #region CONSTRUCTORS - internal DetailConfigurationCollection( DataGridControl dataGridControl, DetailConfiguration parentDetailConfiguration ) : base() { @@ -34,9 +30,40 @@ namespace Xceed.Wpf.DataGrid this.ParentDetailConfiguration = parentDetailConfiguration; } - #endregion CONSTRUCTORS + #region DataGridControl Property + + internal DataGridControl DataGridControl + { + get + { + return m_dataGridControl; + } + set + { + if( m_dataGridControl == value ) + return; + + m_dataGridControl = value; + + this.OnPropertyChanged( new PropertyChangedEventArgs( "DataGridControl" ) ); + } + } + + private DataGridControl m_dataGridControl; + + #endregion + + #region ParentDetailConfiguration Property + + internal DetailConfiguration ParentDetailConfiguration + { + get; + set; + } + + #endregion - public DetailConfiguration this[ string relationName] + public DetailConfiguration this[ string relationName ] { get { @@ -109,6 +136,11 @@ namespace Xceed.Wpf.DataGrid internal event EventHandler DetailVisibilityChanged; bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e ) + { + return this.OnReceiveWeakEvent( managerType, sender, e ); + } + + protected virtual bool OnReceiveWeakEvent( Type managerType, object sender, EventArgs e ) { if( managerType == typeof( DetailVisibilityChangedEventManager ) ) { @@ -123,49 +155,5 @@ namespace Xceed.Wpf.DataGrid } #endregion - - #region DataGridControl Property - - internal DataGridControl DataGridControl - { - get - { - return m_dataGridControl; - } - set - { - if( m_dataGridControl == value ) - return; - - m_dataGridControl = value; - - foreach( DetailConfiguration detail in this.Items ) - { - if( detail.Columns != null ) - { - detail.Columns.DataGridControl = value; - } - - if( detail.DetailConfigurations != null ) - { - detail.DetailConfigurations.DataGridControl = value; - } - } - } - } - - private DataGridControl m_dataGridControl; - - #endregion DataGridControl Property - - #region ParentDetailConfiguration Property - - internal DetailConfiguration ParentDetailConfiguration - { - get; - set; - } - - #endregion ParentDetailConfiguration Property } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfigurationSelector.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfigurationSelector.cs new file mode 100644 index 00000000..fca7f661 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailConfigurationSelector.cs @@ -0,0 +1,26 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +namespace Xceed.Wpf.DataGrid +{ + public abstract class DetailConfigurationSelector + { + internal virtual DetailConfiguration SelectDetailConfiguration( string relationName, DataGridDetailDescription dataGridDetailDescription ) + { + return null; + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailVisibilityChangedEventManager.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailVisibilityChangedEventManager.cs deleted file mode 100644 index de159e5a..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailVisibilityChangedEventManager.cs +++ /dev/null @@ -1,96 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; - -namespace Xceed.Wpf.DataGrid -{ - internal class DetailVisibilityChangedEventManager : WeakEventManager - { - private DetailVisibilityChangedEventManager() - { - } - - public static void AddListener( object source, IWeakEventListener listener ) - { - CurrentManager.ProtectedAddListener( source, listener ); - } - - public static void RemoveListener( object source, IWeakEventListener listener ) - { - CurrentManager.ProtectedRemoveListener( source, listener ); - } - - protected override void StartListening( object source ) - { - DetailConfiguration detailConfig = source as DetailConfiguration; - if( detailConfig != null ) - { - detailConfig.VisibilityChanged += new EventHandler( this.OnVisibilityChanged ); - return; - } - - DetailConfigurationCollection detailConfigCollection = source as DetailConfigurationCollection; - if( detailConfigCollection != null ) - { - detailConfigCollection.DetailVisibilityChanged += new EventHandler( this.OnVisibilityChanged ); - } - - } - - protected override void StopListening( object source ) - { - DetailConfiguration detailConfig = source as DetailConfiguration; - if( detailConfig != null ) - { - detailConfig.VisibilityChanged -= new EventHandler( this.OnVisibilityChanged ); - return; - } - - DetailConfigurationCollection detailConfigCollection = source as DetailConfigurationCollection; - if( detailConfigCollection != null ) - { - detailConfigCollection.DetailVisibilityChanged -= new EventHandler( this.OnVisibilityChanged ); - } - } - - private static DetailVisibilityChangedEventManager CurrentManager - { - get - { - Type managerType = typeof( DetailVisibilityChangedEventManager ); - DetailVisibilityChangedEventManager currentManager = ( DetailVisibilityChangedEventManager )WeakEventManager.GetCurrentManager( managerType ); - - if( currentManager == null ) - { - currentManager = new DetailVisibilityChangedEventManager(); - WeakEventManager.SetCurrentManager( managerType, currentManager ); - } - - return currentManager; - } - } - - private void OnVisibilityChanged( object sender, EventArgs e ) - { - this.DeliverEvent( sender, e ); - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailsChangedEventManager.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailsChangedEventManager.cs deleted file mode 100644 index 958a9c6a..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DetailsChangedEventManager.cs +++ /dev/null @@ -1,104 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows; - -namespace Xceed.Wpf.DataGrid -{ - internal class DetailsChangedEventManager : WeakEventManager - { - private DetailsChangedEventManager() - { - } - - public static void AddListener( object source, IWeakEventListener listener ) - { - CurrentManager.ProtectedAddListener( source, listener ); - } - - public static void RemoveListener( object source, IWeakEventListener listener ) - { - CurrentManager.ProtectedRemoveListener( source, listener ); - } - - protected override void StartListening( object source ) - { - DataGridControl dataGridControl = source as DataGridControl; - if( dataGridControl != null ) - { - dataGridControl.DetailsChanged += this.OnDetailsChanged; - return; - } - else - { - CustomItemContainerGenerator generator = source as CustomItemContainerGenerator; - if( generator != null ) - { - generator.DetailsChanged += this.OnDetailsChanged; - return; - } - } - - throw new InvalidOperationException( "An attempt was made to use a source other than a DataGridControl or CustomItemContainerGenerator." ); - } - - protected override void StopListening( object source ) - { - DataGridControl dataGridControl = source as DataGridControl; - if( dataGridControl != null ) - { - dataGridControl.DetailsChanged -= this.OnDetailsChanged; - return; - } - else - { - CustomItemContainerGenerator generator = source as CustomItemContainerGenerator; - if( generator != null ) - { - generator.DetailsChanged -= this.OnDetailsChanged; - return; - } - } - - throw new InvalidOperationException( "An attempt was made to use a source other than a DataGridControl or CustomItemContainerGenerator." ); - } - - private static DetailsChangedEventManager CurrentManager - { - get - { - Type managerType = typeof( DetailsChangedEventManager ); - DetailsChangedEventManager currentManager = ( DetailsChangedEventManager )WeakEventManager.GetCurrentManager( managerType ); - - if( currentManager == null ) - { - currentManager = new DetailsChangedEventManager(); - WeakEventManager.SetCurrentManager( managerType, currentManager ); - } - - return currentManager; - } - } - - private void OnDetailsChanged( object sender, EventArgs args ) - { - this.DeliverEvent( sender, args ); - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridControlTraceSources.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridControlTraceSources.cs new file mode 100644 index 00000000..1e48c1d8 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridControlTraceSources.cs @@ -0,0 +1,68 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System.Diagnostics; +using System.Threading; + +namespace Xceed.Wpf.DataGrid.Diagnostics +{ + internal static class DataGridControlTraceSources + { + #region CollectionViewSource Property + + internal static DataGridTraceSource CollectionViewSource + { + get + { + return DataGridControlTraceSources.DataGridTraceSource; + } + } + + #endregion + + #region ItemContainerGeneratorSource Property + + internal static DataGridTraceSource ItemContainerGeneratorSource + { + get + { + return DataGridControlTraceSources.DataGridTraceSource; + } + } + + #endregion + + #region DataSource Private Property + + private static DataGridTraceSource DataGridTraceSource + { + get + { + if( s_traceSource == null ) + { + var source = new DataGridTraceSource( new TraceSource( "Xceed.Wpf.DataGrid" ) ); + Interlocked.CompareExchange( ref s_traceSource, source, null ); + } + + return s_traceSource; + } + } + + private static DataGridTraceSource s_traceSource; //null + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArg.Generic.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArg.Generic.cs new file mode 100644 index 00000000..ffff83e2 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArg.Generic.cs @@ -0,0 +1,86 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Globalization; +using System.Windows; + +namespace Xceed.Wpf.DataGrid.Diagnostics +{ + internal class DataGridTraceArg : DataGridTraceArg + { + internal DataGridTraceArg( T value ) + { + m_value = value; + } + + protected override string FormatOutput( CultureInfo culture ) + { + if( object.ReferenceEquals( m_value, null ) ) + return ""; + + var formattable = m_value as IFormattable; + if( formattable != null ) + return formattable.ToString( null, culture ); + + var valueType = m_value.GetType(); + if( valueType.IsGenericType && ( valueType.GetGenericTypeDefinition() == typeof( Nullable<> ) ) ) + { + valueType = Nullable.GetUnderlyingType( valueType ); + } + + if( valueType.IsEnum ) + return m_value.ToString(); + + if( valueType.IsPrimitive || ( typeof( string ) == valueType ) ) + return string.Format( culture, "{0}", m_value ); + + var hashCode = m_value.GetHashCode(); + var name = default( string ); + + if( m_value is DataGridControl ) + { + var dataGridControl = m_value as DataGridControl; + + name = dataGridControl.GridUniqueName; + + if( string.IsNullOrEmpty( name ) ) + { + name = dataGridControl.Name; + } + } + else if( m_value is FrameworkElement ) + { + var fe = m_value as FrameworkElement; + + name = fe.Name; + } + else if( m_value is FrameworkContentElement ) + { + var fce = m_value as FrameworkContentElement; + + name = fce.Name; + } + + if( !string.IsNullOrEmpty( name ) ) + return string.Format( culture, "('{2}' -> {0}, <{1}>)", hashCode, valueType, name ); + + return string.Format( culture, "({0}, <{1}>)", hashCode, valueType ); + } + + private readonly T m_value; + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArg.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArg.cs new file mode 100644 index 00000000..328b0853 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArg.cs @@ -0,0 +1,34 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System.Globalization; + +namespace Xceed.Wpf.DataGrid.Diagnostics +{ + internal abstract class DataGridTraceArg + { + protected abstract string FormatOutput( CultureInfo culture ); + + public sealed override string ToString() + { + var output = this.FormatOutput( CultureInfo.InvariantCulture ); + if( string.IsNullOrEmpty( output ) ) + return string.Empty; + + return output; + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArgs.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArgs.cs new file mode 100644 index 00000000..0297d39f --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceArgs.cs @@ -0,0 +1,145 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System.Globalization; + +namespace Xceed.Wpf.DataGrid.Diagnostics +{ + internal static class DataGridTraceArgs + { + internal static DataGridTraceArg Action( T value ) + { + return new TraceArg( "Action", value ); + } + + internal static DataGridTraceArg DataSource( T value ) + { + return new TraceArg( "DataSource", value ); + } + + internal static DataGridTraceArg DataGridControl( T value ) + { + return new TraceArg( "DataGridControl", value ); + } + + internal static DataGridTraceArg Generator( T value ) + { + return new TraceArg( "ItemContainerGenerator", value ); + } + + internal static DataGridTraceArg Count( T value ) + { + return new TraceArg( "Count", value ); + } + + internal static DataGridTraceArg ItemCount( T value ) + { + return new TraceArg( "ItemCount", value ); + } + + internal static DataGridTraceArg Container( T value ) + { + return new TraceArg( "Container", value ); + } + + internal static DataGridTraceArg Group( T value ) + { + return new TraceArg( "Group", value ); + } + + internal static DataGridTraceArg Index( T value ) + { + return new TraceArg( "Index", value ); + } + + internal static DataGridTraceArg GeneratorIndex( T value ) + { + return new TraceArg( "GIndex", value ); + } + + internal static DataGridTraceArg From( T value ) + { + return new TraceArg( "From", value ); + } + + internal static DataGridTraceArg To( T value ) + { + return new TraceArg( "To", value ); + } + + internal static DataGridTraceArg Item( T value ) + { + return new TraceArg( "Item", value ); + } + + internal static DataGridTraceArg Node( T value ) + { + return new TraceArg( "Node", value ); + } + + internal static DataGridTraceArg NextNode( T value ) + { + return new TraceArg( "NNode", value ); + } + + internal static DataGridTraceArg PreviousNode( T value ) + { + return new TraceArg( "PNode", value ); + } + + internal static DataGridTraceArg LastNode( T value ) + { + return new TraceArg( "LNode", value ); + } + + internal static DataGridTraceArg Value( T value ) + { + return new TraceArg( "Value", value ); + } + + #region TraceArg Private Class + + private sealed class TraceArg : DataGridTraceArg + { + internal TraceArg( string label, T value ) + : base( value ) + { + m_label = label; + } + + protected sealed override string FormatOutput( CultureInfo culture ) + { + var label = m_label; + var value = base.FormatOutput( culture ); + + if( string.IsNullOrEmpty( label ) ) + return value; + + if( value == null ) + return string.Format( "{0}: ", label ); + + if( value.Length == 0 ) + return string.Format( "{0}: ''", label ); + + return string.Format( "{0}: {1}", label, value ); + } + + private readonly string m_label; + } + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceEventIdEnum.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceEventIdEnum.cs new file mode 100644 index 00000000..3fd28a1e --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceEventIdEnum.cs @@ -0,0 +1,80 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + + +namespace Xceed.Wpf.DataGrid.Diagnostics +{ + internal enum DataGridTraceEventId + { + CustomItemContainerGenerator_ApplyGroupChanges = 0, + CustomItemContainerGenerator_CleanupGenerator, + CustomItemContainerGenerator_CloseDetailsForItem, + CustomItemContainerGenerator_CollapseDetails, + CustomItemContainerGenerator_CollapseGroup, + CustomItemContainerGenerator_ContainerFromIndex, + CustomItemContainerGenerator_ContainerFromItem, + CustomItemContainerGenerator_CreateDetailsForItem, + CustomItemContainerGenerator_CreateDetailsHelper, + CustomItemContainerGenerator_EnsureNodeTreeCreated, + CustomItemContainerGenerator_ExpandDetails, + CustomItemContainerGenerator_ExpandGroup, + CustomItemContainerGenerator_FindIndexForItem, + CustomItemContainerGenerator_GenerateNextLocalContainer, + CustomItemContainerGenerator_GenerateStickyFootersForDetail, + CustomItemContainerGenerator_GenerateStickyHeadersForDetail, + CustomItemContainerGenerator_GenPosArraysRemoveAt, + CustomItemContainerGenerator_GetGroupFromItem, + CustomItemContainerGenerator_GetGroupIndex, + CustomItemContainerGenerator_GetRealizedContainerForIndex, + CustomItemContainerGenerator_GetRealizedIndexForContainer, + CustomItemContainerGenerator_HandleDetailReset, + CustomItemContainerGenerator_HandleGlobalItemsReset, + CustomItemContainerGenerator_HandleHeadersFootersAddition, + CustomItemContainerGenerator_HandleHeadersFootersRemoveMoveReplace, + CustomItemContainerGenerator_HandleItemAddition, + CustomItemContainerGenerator_HandleItemReset, + CustomItemContainerGenerator_HandleSameLevelGroupAddition, + CustomItemContainerGenerator_HandleSameLevelGroupMove, + CustomItemContainerGenerator_HandleSameLevelGroupRemove, + CustomItemContainerGenerator_HandleSameLevelGroupReset, + CustomItemContainerGenerator_IItemContainerGenerator_GenerateNext, + CustomItemContainerGenerator_IItemContainerGenerator_Remove, + CustomItemContainerGenerator_IndexFromItem, + CustomItemContainerGenerator_IsGroupExpanded, + CustomItemContainerGenerator_ItemFromContainer, + CustomItemContainerGenerator_ItemFromIndex, + CustomItemContainerGenerator_MoveGeneratorBackward, + CustomItemContainerGenerator_MoveGeneratorForward, + CustomItemContainerGenerator_OnDetailConfigurationsChanged, + CustomItemContainerGenerator_OnDetailGeneratorContentChanged, + CustomItemContainerGenerator_OnGeneratorNodeExpansionStateChanged, + CustomItemContainerGenerator_OnGeneratorNodeGroupsCollectionChanged, + CustomItemContainerGenerator_OnGeneratorNodeHeadersFootersCollectionChanged, + CustomItemContainerGenerator_OnGeneratorNodeItemsCollectionChanged, + CustomItemContainerGenerator_OnGroupGeneratorNodeIsExpandedChanged, + CustomItemContainerGenerator_OnGroupGeneratorNodeIsExpandedChanging, + CustomItemContainerGenerator_OnGroupsChanged, + CustomItemContainerGenerator_OnItemsChanged, + CustomItemContainerGenerator_ProcessGroupRemoval, + CustomItemContainerGenerator_RemapFloatingDetails, + CustomItemContainerGenerator_SetupInitialItemsNodes, + CustomItemContainerGenerator_ToggleDetails, + CustomItemContainerGenerator_ToggleGroupExpansion, + CustomItemContainerGenerator_UpdateFooters, + CustomItemContainerGenerator_UpdateGenPosToIndexList, + CustomItemContainerGenerator_UpdateHeaders, + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceMessages.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceMessages.cs new file mode 100644 index 00000000..a1d04d9b --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceMessages.cs @@ -0,0 +1,71 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Xceed.Wpf.DataGrid.Diagnostics +{ + internal static class DataGridTraceMessages + { + internal const string CannotCollapseDetail = "Cannot collapse the detail."; + internal const string CannotExpandDetail = "Cannot expand the detail."; + internal const string CannotProcessOnReset = "Cannot process while resetting."; + internal const string CannotRemapDetails = "Cannot remap details when deferred."; + internal const string CollapsedItemAdded = "Item(s) added under a collapsed node."; + internal const string CollapsingDetail = "Collapsing a detail."; + internal const string ContainerAdded = "The container was added."; + internal const string ContainerFound = "The container was found."; + internal const string ContainerGenerated = "A container was generated."; + internal const string ContainerIsInDetail = "The container is located in a detail."; + internal const string ContainerNotFound = "The container was not found."; + internal const string ContainerRemoved = "The container was removed."; + internal const string DetailAlreadyCollapsed = "The detail is already collapsed."; + internal const string DetailAlreadyExpanded = "The detail is already expanded."; + internal const string DetailExpanded = "The detail was expanded."; + internal const string DetailCollapsed = "The detail was collapsed."; + internal const string DetailExpected = "Detail expected."; + internal const string DetailIsFloating = "The detail is floating."; + internal const string DetailNodeAdded = "Detail node(s) added."; + internal const string DetailNodeNotFound = "The detail node was not found."; + internal const string DetailNotFound = "The detail was not found."; + internal const string DetailNotSupported = "Details are not supported."; + internal const string EmptyTree = "There is no node."; + internal const string GroupFound = "The group was found."; + internal const string GroupNodeAdded = "Group node(s) added."; + internal const string GroupNodeRemoved = "Group node(s) removed."; + internal const string GroupNotFound = "The group was not found."; + internal const string InhibiterAlreadySet = "An inhibiter is already set."; + internal const string IndexFound = "The index was found."; + internal const string IndexUpdated = "The index was updated."; + internal const string ItemAdded = "Item(s) added."; + internal const string ItemFound = "The item was found."; + internal const string ItemNotBelongingToGenerator = "The item does not belong to the generator."; + internal const string ItemNotBelongingToNode = "The item does not belong to the node."; + internal const string ItemNotFound = "The item was not found."; + internal const string ItemNotFoundOrCollapsed = "The item was not found or is under a collapsed node."; + internal const string NewStartNode = "New start node."; + internal const string NewTreeCreated = "New tree node created."; + internal const string NodeFound = "The node was found."; + internal const string NodeIsCollapsed = "The node is collapsed."; + internal const string NodeIsNotTheCurrentNode = "Node is not the current one."; + internal const string RemapDetailNodes = "Remap details nodes."; + internal const string RemapZombieDetail = "Master item not found for detail."; + internal const string UnexpectedNode = "Unexpected node."; + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceSource.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceSource.cs new file mode 100644 index 00000000..647f3c32 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Diagnostics/DataGridTraceSource.cs @@ -0,0 +1,201 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; + +namespace Xceed.Wpf.DataGrid.Diagnostics +{ + internal class DataGridTraceSource + { + #region Static Fields + + internal readonly IDisposable NoTrace = new EmptyDisposable(); + + #endregion + + internal DataGridTraceSource( TraceSource traceSource ) + { + if( traceSource == null ) + throw new ArgumentNullException( "traceSource" ); + + m_traceSource = traceSource; + } + + internal bool ShouldTrace( TraceEventType eventType ) + { +#if TRACE + var listeners = m_traceSource.Listeners; + if( ( listeners == null ) || ( listeners.Count <= 0 ) ) + return false; + + var sourceSwitch = m_traceSource.Switch; + + return ( sourceSwitch != null ) + && ( sourceSwitch.ShouldTrace( eventType ) ); +#else + return false; +#endif + } + + internal bool ShouldTraceBlock() + { + return ( this.ShouldTrace( TraceEventType.Start ) ) + || ( this.ShouldTrace( TraceEventType.Stop ) ); + } + + internal IDisposable TraceBlock( DataGridTraceEventId eventId, string message, IEnumerable args ) + { + if( this.ShouldTrace( TraceEventType.Start ) ) + { + this.TraceEventCore( TraceEventType.Start, eventId, message, args ); + } + + if( this.ShouldTrace( TraceEventType.Stop ) ) + return new TraceBlockEndDisposable( this, eventId, message, args ); + + return this.NoTrace; + } + + [Conditional( "TRACE" )] + internal void TraceEvent( TraceEventType eventType, DataGridTraceEventId eventId, string message, IEnumerable args ) + { + if( !this.ShouldTrace( eventType ) ) + return; + + this.TraceEventCore( eventType, eventId, message, args ); + } + + private void TraceEventCore( TraceEventType eventType, DataGridTraceEventId eventId, string message, IEnumerable args ) + { + var format = DataGridTraceSource.Format( args ); + + if( string.IsNullOrEmpty( message ) ) + { + if( string.IsNullOrEmpty( format ) ) + { + DataGridTraceSource.TraceEvent( m_traceSource, eventType, ( int )eventId, null ); + } + else + { + DataGridTraceSource.TraceEvent( m_traceSource, eventType, ( int )eventId, format ); + } + } + else + { + if( string.IsNullOrEmpty( format ) ) + { + DataGridTraceSource.TraceEvent( m_traceSource, eventType, ( int )eventId, message ); + } + else + { + DataGridTraceSource.TraceEvent( m_traceSource, eventType, ( int )eventId, message + " | " + format ); + } + } + } + + private static void TraceEvent( TraceSource source, TraceEventType eventType, int eventId, string message ) + { + if( string.IsNullOrEmpty( message ) ) + { + source.TraceEvent( eventType, eventId ); + } + else + { + source.TraceEvent( eventType, eventId, message ); + } + + if( Debugger.IsAttached ) + { + source.Flush(); + } + } + + private static string Format( IEnumerable args ) + { + if( ( args == null ) || !args.Any() ) + return null; + + var sb = new StringBuilder( 128 ); + + foreach( var arg in args ) + { + var value = arg.ToString(); + + if( string.IsNullOrEmpty( value ) ) + continue; + + if( sb.Length > 0 ) + { + sb.Append( "; " ); + } + + sb.Append( value ); + } + + return sb.ToString(); + } + + private readonly TraceSource m_traceSource; + + #region TraceBlockEndDisposable Private Class + + private sealed class TraceBlockEndDisposable : IDisposable + { + internal TraceBlockEndDisposable( DataGridTraceSource owner, DataGridTraceEventId eventId, string message, IEnumerable args ) + { + if( owner == null ) + throw new ArgumentNullException( "owner" ); + + m_owner = owner; + m_eventId = eventId; + m_message = message; + m_args = args; + } + + void IDisposable.Dispose() + { + var owner = Interlocked.Exchange( ref m_owner, null ); + if( owner == null ) + return; + + owner.TraceEventCore( TraceEventType.Stop, m_eventId, m_message, m_args ); + } + + private DataGridTraceSource m_owner; + private readonly DataGridTraceEventId m_eventId; + private readonly string m_message; + private readonly IEnumerable m_args; + } + + #endregion + + #region EmptyDisposable Private Class + + private sealed class EmptyDisposable : IDisposable + { + void IDisposable.Dispose() + { + } + } + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DropMarkAdorner.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DropMarkAdorner.cs index 9ad2463c..a4707270 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DropMarkAdorner.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DropMarkAdorner.cs @@ -23,38 +23,27 @@ using Xceed.Wpf.DataGrid.Views; namespace Xceed.Wpf.DataGrid { - internal class DropMarkAdorner : Adorner + internal sealed class DropMarkAdorner : Adorner { // A null value for the pen parameter means that the adorner will not show any visual cue. - public DropMarkAdorner( UIElement adornedElement, Pen pen, DropMarkOrientation orientation ) + internal DropMarkAdorner( UIElement adornedElement, Pen pen, DropMarkOrientation orientation ) : base( adornedElement ) { Debug.Assert( orientation != DropMarkOrientation.Default, "A DropMarkAdorner without a specific orientation should virtually never happen. The only known way to do this would be to have a grid element not hosted in a DataGridControl. The DropMarkAdorner should react well to this nonetheless." ); m_pen = pen; m_orientation = orientation; + m_render = ( pen != null ); this.IsHitTestVisible = false; } - public DropMarkAlignment Alignment - { - get - { - return m_alignment; - } - } - - // This Property does not use the Alignment paradigm. It allows to manually set the - // position of the drop mark. #region HorizontalPosition Property public static readonly DependencyProperty HorizontalPositionProperty = DependencyProperty.Register( "HorizontalPosition", typeof( double ), typeof( DropMarkAdorner ), - new FrameworkPropertyMetadata( - 0d, - new PropertyChangedCallback( DropMarkAdorner.OnHorizontalPositionChanged ) ) ); + new FrameworkPropertyMetadata( 0d, new PropertyChangedCallback( DropMarkAdorner.OnHorizontalPositionChanged ) ) ); public double HorizontalPosition { @@ -70,169 +59,140 @@ namespace Xceed.Wpf.DataGrid private static void OnHorizontalPositionChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e ) { - DropMarkAdorner adorner = sender as DropMarkAdorner; - - if( adorner == null ) + var self = sender as DropMarkAdorner; + if( self == null ) return; - adorner.UpdatePosition(); + self.Update(); } #endregion + #region Alignment Property - public void ForceAlignment( DropMarkAlignment alignment ) + internal DropMarkAlignment Alignment { - m_alignment = alignment; - } - - public void UpdateAlignment( Point mousePosition ) - { - DropMarkAlignment alignment = DropMarkAlignment.Near; - - if( m_orientation == DropMarkOrientation.Horizontal ) + get { - // A horizontal drop mark is either displayed at the top or at the bottom of the AdornedElement. - Rect hitTestRect = new Rect( 0d, 0d, this.AdornedElement.RenderSize.Width, this.AdornedElement.RenderSize.Height / 2 ); - - if( hitTestRect.Contains( mousePosition ) ) - { - alignment = DropMarkAlignment.Near; - } - else - { - alignment = DropMarkAlignment.Far; - } + return m_alignment; } - else + set { - // A vertical drop mark is either displayed at the left or at the right of the AdornedElement. - Rect hitTestRect = new Rect( 0d, 0d, this.AdornedElement.RenderSize.Width / 2, this.AdornedElement.RenderSize.Height ); - - if( hitTestRect.Contains( mousePosition ) ) - { - alignment = DropMarkAlignment.Near; - } - else - { - alignment = DropMarkAlignment.Far; - } - } + if( value == m_alignment ) + return; - if( alignment != m_alignment ) - { - m_alignment = alignment; - this.UpdatePosition(); + m_alignment = value; + + this.Update(); } } - protected override Size MeasureOverride( Size constraint ) - { - this.AdornedElement.Measure( constraint ); + private DropMarkAlignment m_alignment = DropMarkAlignment.ExplicitPosition; + + #endregion - Size size = Size.Empty; + #region AdornerLayout Private Property - if( m_pen != null ) + private AdornerLayer AdornerLayer + { + get { - switch( m_orientation ) - { - case DropMarkOrientation.Default: - case DropMarkOrientation.Vertical: - size = new Size( m_pen.Thickness, this.AdornedElement.RenderSize.Height ); - break; - case DropMarkOrientation.Horizontal: - size = new Size( this.AdornedElement.RenderSize.Width, m_pen.Thickness ); - break; - default: - throw new DataGridInternalException(); - } + return ( this.Parent as AdornerLayer ); } - - return size; } - public override GeneralTransform GetDesiredTransform( GeneralTransform transform ) + #endregion + + protected override void OnRender( DrawingContext drawingContext ) { - double offsetX = this.HorizontalPosition; - double offsetY = 0d; + base.OnRender( drawingContext ); - if( m_pen != null ) + if( !m_render || ( m_pen == null ) ) + return; + + var renderSize = this.AdornedElement.RenderSize; + + Point startPoint = new Point( this.HorizontalPosition, 0d ); + Point endPoint; + + switch( m_orientation ) { - switch( m_orientation ) - { - case DropMarkOrientation.Default: - case DropMarkOrientation.Vertical: - offsetX -= m_pen.Thickness / 2; - break; - case DropMarkOrientation.Horizontal: - offsetY -= m_pen.Thickness / 2; - break; - } - - if( m_alignment == DropMarkAlignment.Far ) - { - if( m_orientation == DropMarkOrientation.Vertical ) + case DropMarkOrientation.Default: + case DropMarkOrientation.Vertical: { - // A "far" vertical drop mark is displayed at the right - offsetX += this.AdornedElement.RenderSize.Width; + if( m_alignment == DropMarkAlignment.Far ) + { + startPoint.X += renderSize.Width; + } + + endPoint = new Point( startPoint.X, renderSize.Height ); } - else + break; + case DropMarkOrientation.Horizontal: { - // A "far" horizontal drop mark is displayed at the bottom - offsetY += this.AdornedElement.RenderSize.Height; + if( m_alignment == DropMarkAlignment.Far ) + { + startPoint.Y += renderSize.Height; + } + + endPoint = new Point( renderSize.Width, startPoint.Y ); } - } + break; + default: + return; } - GeneralTransformGroup transformGroup = new GeneralTransformGroup(); + drawingContext.DrawLine( m_pen, startPoint, endPoint ); + } - transformGroup.Children.Add( base.GetDesiredTransform( transform ) ); - transformGroup.Children.Add( new TranslateTransform( offsetX, offsetY ) ); + internal void UpdateAlignment( RelativePoint mousePosition ) + { + var relativePosition = mousePosition.GetPoint( this.AdornedElement ); + var elementSize = this.AdornedElement.RenderSize; - return transformGroup; + if( m_orientation == DropMarkOrientation.Horizontal ) + { + this.Alignment = ( relativePosition.Y < elementSize.Height / 2d ) ? DropMarkAlignment.Near : DropMarkAlignment.Far; + } + else + { + this.Alignment = ( relativePosition.X < elementSize.Width / 2d ) ? DropMarkAlignment.Near : DropMarkAlignment.Far; + } } - protected override void OnRender( DrawingContext drawingContext ) + private void Update() { - if( m_pen != null ) - { - Size renderSize = this.RenderSize; - Point startPoint; - Point endPoint; - - switch( m_orientation ) - { - case DropMarkOrientation.Default: - case DropMarkOrientation.Vertical: - startPoint = new Point( renderSize.Width / 2, 0d ); - endPoint = new Point( startPoint.X, renderSize.Height ); - break; - case DropMarkOrientation.Horizontal: - startPoint = new Point( 0d, renderSize.Height / 2 ); - endPoint = new Point( renderSize.Width, startPoint.Y ); - break; - default: - throw new DataGridInternalException(); - } + if( !m_render ) + return; - drawingContext.DrawLine( m_pen, startPoint, endPoint ); - } + if( !this.InvalidateAdornerLayer() ) + return; - base.OnRender( drawingContext ); + m_render = false; + this.LayoutUpdated += new EventHandler( this.OnLayoutUpdated ); } - private void UpdatePosition() + private bool InvalidateAdornerLayer() { - AdornerLayer adornerLayer = this.Parent as AdornerLayer; + var adornerLayer = this.AdornerLayer; + if( adornerLayer == null ) + return false; - if( adornerLayer != null ) - { - adornerLayer.Update( this.AdornedElement ); - } + adornerLayer.Update( this.AdornedElement ); + return true; } - private DropMarkAlignment m_alignment = DropMarkAlignment.ExplicitPosition; - private Pen m_pen; - private DropMarkOrientation m_orientation; + private void OnLayoutUpdated( object sender, EventArgs e ) + { + m_render = true; + + this.LayoutUpdated -= new EventHandler( this.OnLayoutUpdated ); + this.InvalidateVisual(); + this.InvalidateAdornerLayer(); + } + + private readonly DropMarkOrientation m_orientation; + private readonly Pen m_pen; + private bool m_render; } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/CF_HtmlStream.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/CF_HtmlStream.cs new file mode 100644 index 00000000..13a6e738 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/CF_HtmlStream.cs @@ -0,0 +1,201 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Diagnostics; +using System.Globalization; + +namespace Xceed.Wpf.DataGrid.Export +{ + // Class used to format data into the CF_HTML Clipbard Format + // http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx + internal sealed class CF_HtmlStream : Stream + { + public CF_HtmlStream( Stream innerStream ) + { + if( innerStream == null ) + throw new ArgumentNullException( "innerStream" ); + + if( innerStream.CanWrite == false ) + throw new InvalidOperationException( "An attempt was made to use a non-writable stream." ); + + if( innerStream.CanSeek == false ) + throw new InvalidOperationException( "An attempt was made to use a non-seekable stream." ); + + m_innerStream = innerStream; + + StringBuilder headerStringBuilder = new StringBuilder(); + headerStringBuilder.Append( "Version:1.0" ); + headerStringBuilder.Append( Environment.NewLine ); + headerStringBuilder.Append( "StartHTML:-1" ); // This is optional according to MSDN documentation + headerStringBuilder.Append( Environment.NewLine ); + headerStringBuilder.Append( "EndHTML:-1" ); // This is optional according to MSDN documentation + headerStringBuilder.Append( Environment.NewLine ); + headerStringBuilder.Append( "StartFragment:0000000109" ); // Always 109 bytes from start of Version to the end of tag + headerStringBuilder.Append( Environment.NewLine ); + + // Get the offset of the EndFragment: tag to be able to modify the 10 digits + m_endFragmentOffset = headerStringBuilder.ToString().Length; + + Debug.Assert( m_endFragmentOffset == 65 ); + + headerStringBuilder.Append( "EndFragment:0000000000" ); // We write 0000000000 and we will update this field when the Stream is closed + headerStringBuilder.Append( Environment.NewLine ); + headerStringBuilder.Append( "" ); + + string headerString = headerStringBuilder.ToString(); + + byte[] tempBuffer = Encoding.UTF8.GetBytes( headerString ); + + m_headerBytesLength = headerStringBuilder.Length; + + Debug.Assert( m_headerBytesLength == tempBuffer.Length ); + Debug.Assert( tempBuffer.Length == 109 ); + + m_innerStream.Write( tempBuffer, 0, m_headerBytesLength ); + m_HtmlContentByteCount = 0; + } + + public override bool CanRead + { + get + { + return false; + } + } + + public override bool CanSeek + { + get + { + return false; + } + } + + public override bool CanWrite + { + get + { + return true; + } + } + + public override long Length + { + get + { + return m_headerBytesLength + m_HtmlContentByteCount + s_footerBytes.Length; + } + } + + public override long Position + { + get + { + throw new NotSupportedException(); + } + set + { + throw new NotSupportedException(); + } + } + + public override void Close() + { + // Already closed, nothing to do + if( m_closed ) + return; + + // Update the value of EndFragment field in the header + string endFragmentOffset = ( m_HtmlContentByteCount + m_headerBytesLength ).ToString( "0000000000", CultureInfo.InvariantCulture ); + + m_innerStream.Seek( m_endFragmentOffset, SeekOrigin.Begin ); + + byte[] tempBuffer = Encoding.UTF8.GetBytes( "EndFragment:" + endFragmentOffset ); + Debug.Assert( tempBuffer.Length == 22 ); + m_innerStream.Write( tempBuffer, 0, tempBuffer.Length ); + + // Append the final end line and EndFragment tag + m_innerStream.Seek( 0, SeekOrigin.End ); + m_innerStream.Write( s_footerBytes, 0, s_footerBytes.Length ); + m_innerStream.Flush(); + + m_closed = true; + } + + protected override void Dispose( bool disposing ) + { + this.Close(); + } + + public override void Flush() + { + m_innerStream.Flush(); + } + + public override int Read( byte[] buffer, int offset, int count ) + { + throw new NotSupportedException(); + } + + public override int ReadByte() + { + throw new NotSupportedException(); + } + + public override long Seek( long offset, SeekOrigin origin ) + { + throw new NotSupportedException(); + } + + public override void SetLength( long value ) + { + throw new NotSupportedException(); + } + + public override void WriteByte( byte value ) + { + this.CheckIfClosed(); + m_HtmlContentByteCount++; + m_innerStream.WriteByte( value ); + } + + public override void Write( byte[] buffer, int offset, int count ) + { + this.CheckIfClosed(); + m_HtmlContentByteCount += count; + m_innerStream.Write( buffer, offset, count ); + } + + private void CheckIfClosed() + { + if( m_closed ) + throw new InvalidOperationException( "An attempt was made to access a closed stream." ); + } + + private bool m_closed; // = false; + private int m_endFragmentOffset; // = 0; + private int m_headerBytesLength; // = 0; + private long m_HtmlContentByteCount; // = 0; + private Stream m_innerStream; // = null; + + private static byte[] s_footerBytes = Encoding.UTF8.GetBytes( Environment.NewLine + "" ); + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/ClipboardExporterBase.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/ClipboardExporterBase.cs index 8a075453..0603d1b0 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/ClipboardExporterBase.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/ClipboardExporterBase.cs @@ -16,29 +16,20 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Diagnostics; -using System.IO; -using System.Collections; using System.Collections.ObjectModel; -using System.Windows.Data; +using System.Diagnostics; +using System.Windows; namespace Xceed.Wpf.DataGrid.Export { public abstract class ClipboardExporterBase { - #region CONSTRUCTORS - protected ClipboardExporterBase() { this.UseFieldNamesInHeader = false; } - #endregion - - #region PUBLIC PROPERTIES + #region IncludeColumnHeaders Property public bool IncludeColumnHeaders { @@ -46,6 +37,10 @@ namespace Xceed.Wpf.DataGrid.Export set; } + #endregion + + #region UseFieldNamesInHeader Property + public bool UseFieldNamesInHeader { get; @@ -54,7 +49,7 @@ namespace Xceed.Wpf.DataGrid.Export #endregion - #region PROTECTED PROPERTIES + #region ClipboardData Property protected abstract object ClipboardData { @@ -63,8 +58,6 @@ namespace Xceed.Wpf.DataGrid.Export #endregion - #region PROTECTED METHODS - protected virtual void Indent() { } @@ -117,10 +110,6 @@ namespace Xceed.Wpf.DataGrid.Export { } - #endregion - - #region INTERNAL STATIC METHODS - internal static IDataObject CreateDataObject( DataGridControl dataGridControl ) { if( dataGridControl == null ) @@ -158,7 +147,9 @@ namespace Xceed.Wpf.DataGrid.Export keyPair.Value.EndExporter( keyPair.Key ); if( dataObject == null ) + { dataObject = new XceedDataObject(); + } object clipboardExporterValue = keyPair.Value.ClipboardData; @@ -184,14 +175,8 @@ namespace Xceed.Wpf.DataGrid.Export return null; } - #endregion - - #region PRIVATE CLASS ManualExporter - private class ManualExporter : IDisposable { - #region PUBLIC CONSTRUCTORS - public ManualExporter( IEnumerable clipboardExporters ) { m_columnToBindingPathExtractor = new Dictionary(); @@ -200,8 +185,6 @@ namespace Xceed.Wpf.DataGrid.Export m_visitedDetailVisibleColumnsCache = new Dictionary(); } - #endregion - #region HasItems Property public bool HasItems @@ -210,38 +193,119 @@ namespace Xceed.Wpf.DataGrid.Export set; } - #endregion HasItems Property + #endregion + + internal void Export( DataGridContext dataGridContext ) + { + if( dataGridContext == null ) + return; + + // Get the detail level for the current DataGridContext + int detailLevel = dataGridContext.DetailLevel; + + // Update indentation of ClipboardExporters for this detail level + this.UpdateExporterIndentation( detailLevel ); + + // Get master indexes that have mapped expanded details + List indexesToMasterItemList = dataGridContext.CustomItemContainerGenerator.GetMasterIndexesWithExpandedDetails(); + + // Get the index of the next detail to export in case + // it is expanded before the first selected index of the + // current dataGridContext + int nextDetailIndex = ( indexesToMasterItemList.Count > 0 ) ? indexesToMasterItemList[ 0 ] : -1; + + // Get informations on columns, visible positions and selected item indexes + // for this dataGridContext + int[] exportedVisiblePositions = this.GetVisiblePositionsForContext( dataGridContext ); + ColumnBase[] columnsByVisiblePosition = this.GetVisibleColumnsArrayForContext( dataGridContext ); + SelectionRange[] selectedItemsRanges = this.GetSelectedItemsStoreForDataGridContext( dataGridContext ); + + Debug.Assert( exportedVisiblePositions != null ); + Debug.Assert( columnsByVisiblePosition != null ); + Debug.Assert( selectedItemsRanges != null ); + + int selectedItemsRangesCount = selectedItemsRanges.Length; + + // Ensure to flag the exporter has items + this.HasItems = this.HasItems || ( selectedItemsRangesCount > 0 ); + + for( int i = 0; i < selectedItemsRangesCount; i++ ) + { + // For the first level, ensure to export the headers + // before anything else + if( detailLevel == 0 ) + { + this.ExportHeaders( dataGridContext, detailLevel, exportedVisiblePositions, columnsByVisiblePosition ); + } + + SelectionRange range = selectedItemsRanges[ i ]; + + int startIndex = range.StartIndex; + int endIndex = range.EndIndex; + + // If range is inverted + if( startIndex > endIndex ) + { + startIndex = range.EndIndex; + endIndex = range.StartIndex; + } + + // For each index in the range + for( int itemIndex = startIndex; itemIndex <= endIndex; itemIndex++ ) + { + // Export details that are before the itemIndex + while( ( nextDetailIndex != -1 ) && ( itemIndex > nextDetailIndex ) ) + { + this.ExportDetailForMasterIndex( dataGridContext, detailLevel, nextDetailIndex ); + + // Remove it since the detail is processed + indexesToMasterItemList.Remove( nextDetailIndex ); + + nextDetailIndex = ( indexesToMasterItemList.Count > 0 ) ? indexesToMasterItemList[ 0 ] : -1; + } + + // Ensure to re-export the headers if a detail was previously exported + this.ExportHeaders( dataGridContext, detailLevel, exportedVisiblePositions, columnsByVisiblePosition ); + + object exportedItem = dataGridContext.Items.GetItemAt( itemIndex ); + + this.ExportDataItem( dataGridContext, itemIndex, exportedItem, detailLevel, exportedVisiblePositions, columnsByVisiblePosition ); + } + } + + nextDetailIndex = ( indexesToMasterItemList.Count > 0 ) ? indexesToMasterItemList[ 0 ] : -1; + + // Export all remaining details since none are before the context's + // selected index ranges + while( nextDetailIndex != -1 ) + { + this.ExportDetailForMasterIndex( dataGridContext, detailLevel, nextDetailIndex ); + + // Remove it since the detail is processed + indexesToMasterItemList.Remove( nextDetailIndex ); - #region PRIVATE METHODS + nextDetailIndex = ( indexesToMasterItemList.Count > 0 ) ? indexesToMasterItemList[ 0 ] : -1; + } + } - private void ExportDataItemCore( - DataGridContext dataGridContext, - ClipboardExporterBase clipboardExporter, - int itemIndex, - object item, - int[] exportedVisiblePositions, - ColumnBase[] columnsByVisiblePosition ) + private void ExportDataItemCore( DataGridContext dataGridContext, ClipboardExporterBase clipboardExporter, int itemIndex, object item, + int[] exportedVisiblePositions, ColumnBase[] columnsByVisiblePosition ) { - DataGridCollectionViewBase dataGridCollectionViewBase = - dataGridContext.ItemsSourceCollection as DataGridCollectionViewBase; + var dataGridCollectionViewBase = dataGridContext.ItemsSourceCollection as DataGridCollectionViewBase; clipboardExporter.StartDataItem( dataGridContext, item ); // Ensure the count does not exceeds the columns count - int exportedVisiblePositionsCount = exportedVisiblePositions.Length; + var exportedVisiblePositionsCount = exportedVisiblePositions.Length; exportedVisiblePositionsCount = Math.Min( exportedVisiblePositionsCount, columnsByVisiblePosition.Length ); - HashSet intersectedIndexes = this.GetIntersectedRangesForIndex( dataGridContext, - itemIndex, - exportedVisiblePositions, - exportedVisiblePositionsCount ); - - object fieldValue = null; - Column column = null; + var intersectedIndexes = this.GetIntersectedRangesForIndex( dataGridContext, itemIndex, exportedVisiblePositions, exportedVisiblePositionsCount ); for( int i = 0; i < exportedVisiblePositionsCount; i++ ) { - int visiblePosition = exportedVisiblePositions[ i ]; + var fieldValue = default( object ); + var column = default( Column ); + var visiblePosition = exportedVisiblePositions[ i ]; // Export null if not intersected by a SelectionRange if( intersectedIndexes.Contains( visiblePosition ) ) @@ -252,30 +316,25 @@ namespace Xceed.Wpf.DataGrid.Export if( column == null ) continue; - // Reset field value - fieldValue = null; + // Use DataGridCollectionView directly since the DataGridItemProperty uses PropertyDescriptor which increase the read of the field value + var dataGridItemProperty = default( DataGridItemPropertyBase ); - // Use DataGridCollectionView directly since the DataGridItemProperty uses PropertyDescriptor which increase - // the read of the field value - DataGridItemPropertyBase dataGridItemProperty = null; - - // Try to get a DataGridItemProperty matching the column FieldName - // and get the value from it + // Try to get a DataGridItemProperty matching the column FieldName and get the value from it if( dataGridCollectionViewBase != null ) { - dataGridItemProperty = dataGridCollectionViewBase.ItemProperties[ column.FieldName ]; + dataGridItemProperty = ItemsSourceHelper.GetItemPropertyFromProperty( dataGridCollectionViewBase.ItemProperties, column.FieldName ); if( dataGridItemProperty != null ) - fieldValue = dataGridItemProperty.GetValue( item ); + { + fieldValue = ItemsSourceHelper.GetValueFromItemProperty( dataGridItemProperty, item ); + } } // If none was found, create a BindingPathValueExtractor from this column if( ( dataGridCollectionViewBase == null ) || ( dataGridItemProperty == null ) ) { - // We don't have a DataGridCollectionView, use a BindingPathValueExtractor - // to create a binding to help us get the value for the Column in the - // data item - BindingPathValueExtractor extractorForRead = null; + // We don't have a DataGridCollectionView, use a BindingPathValueExtractor to create a binding to help us get the value for the Column in the data item + var extractorForRead = default( BindingPathValueExtractor ); if( m_columnToBindingPathExtractor.TryGetValue( column, out extractorForRead ) == false ) { @@ -287,6 +346,33 @@ namespace Xceed.Wpf.DataGrid.Export } } + if( fieldValue != null ) + { + //Verify if the value should be converted to the displayed value for exporting. + var foreignKeyConfiguration = column.ForeignKeyConfiguration; + if( foreignKeyConfiguration != null && foreignKeyConfiguration.UseDisplayedValueWhenExporting ) + { + fieldValue = foreignKeyConfiguration.GetDisplayMemberValue( fieldValue ); + } + else + { + var valueConverter = column.DisplayedValueConverter; + if( valueConverter != null ) + { + fieldValue = valueConverter.Convert( fieldValue, typeof( object ), column.DisplayedValueConverterParameter, + column.GetCulture( column.DisplayedValueConverterCulture ) ); + } + else + { + var valueFormat = column.CellContentStringFormat; + if( !string.IsNullOrEmpty( valueFormat ) ) + { + fieldValue = string.Format( column.GetCulture(), valueFormat, fieldValue ); + } + } + } + } + clipboardExporter.StartDataItemField( dataGridContext, column, fieldValue ); clipboardExporter.EndDataItemField( dataGridContext, column, fieldValue ); } @@ -294,11 +380,8 @@ namespace Xceed.Wpf.DataGrid.Export clipboardExporter.EndDataItem( dataGridContext, item ); } - private void ExportHeadersCore( - DataGridContext dataGridContext, - ClipboardExporterBase clipboardExporter, - int[] exportedVisiblePositions, - ColumnBase[] columnsByVisiblePosition ) + private void ExportHeadersCore( DataGridContext dataGridContext, ClipboardExporterBase clipboardExporter, int[] exportedVisiblePositions, + ColumnBase[] columnsByVisiblePosition ) { clipboardExporter.StartHeader( dataGridContext ); @@ -323,11 +406,7 @@ namespace Xceed.Wpf.DataGrid.Export clipboardExporter.EndHeader( dataGridContext ); } - private HashSet GetIntersectedRangesForIndex( - DataGridContext dataGridContext, - int itemIndex, - int[] exportedVisiblePositions, - int correctedExportedVisiblePositionsCount ) + private HashSet GetIntersectedRangesForIndex( DataGridContext dataGridContext, int itemIndex, int[] exportedVisiblePositions, int correctedExportedVisiblePositionsCount ) { HashSet intersectedIndexes = null; @@ -344,13 +423,10 @@ namespace Xceed.Wpf.DataGrid.Export { intersectedIndexes = new HashSet(); - SelectionCellRange columnsRange = new SelectionCellRange( itemIndex, - exportedVisiblePositions[ 0 ], - itemIndex, - exportedVisiblePositions[ correctedExportedVisiblePositionsCount - 1 ] ); + SelectionCellRange columnsRange = new SelectionCellRange( itemIndex, exportedVisiblePositions[ 0 ], itemIndex, + exportedVisiblePositions[ correctedExportedVisiblePositionsCount - 1 ] ); - List intersectedRanges = - dataGridContext.SelectedCellsStore.GetIntersectedColumnRanges( columnsRange ); + IEnumerable intersectedRanges = dataGridContext.SelectedCellsStore.GetIntersectedColumnRanges( columnsRange ); foreach( SelectionRange range in intersectedRanges ) { @@ -366,7 +442,9 @@ namespace Xceed.Wpf.DataGrid.Export for( int i = startIndex; i <= endIndex; i++ ) { if( !intersectedIndexes.Contains( i ) ) + { intersectedIndexes.Add( i ); + } } } } @@ -374,18 +452,17 @@ namespace Xceed.Wpf.DataGrid.Export return intersectedIndexes; } - private void GetAllVisibleColumnsVisiblePosition( - DataGridContext dataGridContext, - ref HashSet exportedColumnPositions ) + private void GetAllVisibleColumnsVisiblePosition( DataGridContext dataGridContext, ref HashSet exportedColumnPositions ) { if( exportedColumnPositions == null ) + { exportedColumnPositions = new HashSet(); + } if( dataGridContext == null ) return; - ReadOnlyObservableCollection visibleColumns = - dataGridContext.VisibleColumns; + ReadOnlyObservableCollection visibleColumns = dataGridContext.VisibleColumns; int visibleColumnsCount = visibleColumns.Count; @@ -400,32 +477,17 @@ namespace Xceed.Wpf.DataGrid.Export } } - private void ExportDataItem( - DataGridContext dataGridContext, - int itemIndex, - object item, - int detailLevel, - int[] exportedVisiblePositions, - ColumnBase[] columnsByVisiblePosition ) + private void ExportDataItem( DataGridContext dataGridContext, int itemIndex, object item, int detailLevel, int[] exportedVisiblePositions, + ColumnBase[] columnsByVisiblePosition ) { - Debug.WriteLine( string.Format( "ExportDataItem for detail level {0}, itemIndex {1}", detailLevel, itemIndex ) ); foreach( ClipboardExporterBase clipboardExporter in m_clipboardExporters ) { - this.ExportDataItemCore( dataGridContext, - clipboardExporter, - itemIndex, - item, - exportedVisiblePositions, - columnsByVisiblePosition ); + this.ExportDataItemCore( dataGridContext, clipboardExporter, itemIndex, item, exportedVisiblePositions, columnsByVisiblePosition ); } } - private void ExportHeaders( - DataGridContext dataGridContext, - int detailLevel, - int[] exportedVisiblePositions, - ColumnBase[] columnsByVisiblePosition ) + private void ExportHeaders( DataGridContext dataGridContext, int detailLevel, int[] exportedVisiblePositions, ColumnBase[] columnsByVisiblePosition ) { // Master level was already exported, only update the lastExportedHeaderDetailLevel if( ( m_lastExportedHeaderDetailLevel != -1 ) && ( detailLevel == 0 ) ) @@ -438,32 +500,24 @@ namespace Xceed.Wpf.DataGrid.Export if( m_lastExportedHeaderDetailLevel == detailLevel ) return; - Debug.WriteLine( string.Format( "ExportHeaders for detail level {0}", detailLevel ) ); foreach( ClipboardExporterBase clipboardExporter in m_clipboardExporters ) { // We always add the headers for detail levels every time if( clipboardExporter.IncludeColumnHeaders ) { - this.ExportHeadersCore( dataGridContext, - clipboardExporter, - exportedVisiblePositions, - columnsByVisiblePosition ); + this.ExportHeadersCore( dataGridContext, clipboardExporter, exportedVisiblePositions, columnsByVisiblePosition ); } } m_lastExportedHeaderDetailLevel = detailLevel; } - private void ExportDetailForMasterIndex( - DataGridContext dataGridContext, - int detailLevel, - int masterIndexForDetail ) + private void ExportDetailForMasterIndex( DataGridContext dataGridContext, int detailLevel, int masterIndexForDetail ) { object item = dataGridContext.Items.GetItemAt( masterIndexForDetail ); - IEnumerable dataGridContexts = - dataGridContext.CustomItemContainerGenerator.GetChildContextsForMasterItem( item ); + IEnumerable dataGridContexts = dataGridContext.CustomItemContainerGenerator.GetChildContextsForMasterItem( item ); foreach( DataGridContext childContext in dataGridContexts ) { @@ -473,8 +527,7 @@ namespace Xceed.Wpf.DataGrid.Export this.UpdateExporterIndentation( detailLevel ); } - private ColumnBase[] GetVisibleColumnsArrayForContext( - DataGridContext dataGridContext ) + private ColumnBase[] GetVisibleColumnsArrayForContext( DataGridContext dataGridContext ) { if( dataGridContext == null ) throw new ArgumentNullException( "sourceContext" ); @@ -482,9 +535,7 @@ namespace Xceed.Wpf.DataGrid.Export int detailLevel = dataGridContext.DetailLevel; if( m_visitedDetailVisibleColumnsCache.ContainsKey( detailLevel ) ) - { return m_visitedDetailVisibleColumnsCache[ detailLevel ]; - } int columnsByVisiblePositionCount = dataGridContext.ColumnsByVisiblePosition.Count; ColumnBase[] columnsByVisiblePosition = new ColumnBase[ columnsByVisiblePositionCount ]; @@ -495,8 +546,7 @@ namespace Xceed.Wpf.DataGrid.Export return columnsByVisiblePosition; } - private int[] GetVisiblePositionsForContext( - DataGridContext dataGridContext ) + private int[] GetVisiblePositionsForContext( DataGridContext dataGridContext ) { if( dataGridContext == null ) throw new ArgumentNullException( "dataGridContext" ); @@ -511,9 +561,7 @@ namespace Xceed.Wpf.DataGrid.Export DataGridContext rootDataGridContext = dataGridContext.DataGridControl.DataGridContext; - this.GetVisiblePositionsForContextDetailLevel( rootDataGridContext, - detailLevel, - exportedColumnPositions ); + this.GetVisiblePositionsForContextDetailLevel( rootDataGridContext, detailLevel, exportedColumnPositions ); int exportedColumnPositionsCount = exportedColumnPositions.Count; int[] exportedVisiblePositionsArray = null; @@ -528,10 +576,7 @@ namespace Xceed.Wpf.DataGrid.Export } // Parse all the expanded details recursively - private void GetVisiblePositionsForContextDetailLevel( - DataGridContext dataGridContext, - int desiredDetailLevel, - HashSet exportedColumnPositions ) + private void GetVisiblePositionsForContextDetailLevel( DataGridContext dataGridContext, int desiredDetailLevel, HashSet exportedColumnPositions ) { int dataGridContextDetailLevel = dataGridContext.DetailLevel; @@ -546,15 +591,13 @@ namespace Xceed.Wpf.DataGrid.Export if( parentDataGridContext == null ) { - this.GetVisibleColumnsVisiblePositionForDataGridContext( dataGridContext, - exportedColumnPositions ); + this.GetVisibleColumnsVisiblePositionForDataGridContext( dataGridContext, exportedColumnPositions ); } else { foreach( DataGridContext childContext in parentDataGridContext.GetChildContexts() ) { - if( this.GetVisibleColumnsVisiblePositionForDataGridContext( childContext, - exportedColumnPositions ) ) + if( this.GetVisibleColumnsVisiblePositionForDataGridContext( childContext, exportedColumnPositions ) ) { // All columns need to be exported, stop parsing child DataGridContexts break; @@ -567,20 +610,17 @@ namespace Xceed.Wpf.DataGrid.Export // The detail level differs, parse the child contexts recursively foreach( DataGridContext childContext in dataGridContext.GetChildContexts() ) { - this.GetVisiblePositionsForContextDetailLevel( childContext, - desiredDetailLevel, - exportedColumnPositions ); + this.GetVisiblePositionsForContextDetailLevel( childContext, desiredDetailLevel, exportedColumnPositions ); } } } - private SelectionRange[] GetSelectedItemsStoreForDataGridContext( - DataGridContext dataGridContext ) + private SelectionRange[] GetSelectedItemsStoreForDataGridContext( DataGridContext dataGridContext ) { if( dataGridContext == null ) return null; - SelectedItemsStorage itemStorage = new SelectedItemsStorage( null, 16 ); + SelectedItemsStorage itemStorage = new SelectedItemsStorage( null ); foreach( SelectionRange range in dataGridContext.SelectedItemRanges ) { @@ -589,11 +629,12 @@ namespace Xceed.Wpf.DataGrid.Export foreach( SelectionCellRange range in dataGridContext.SelectedCellRanges ) { - SelectionRangeWithItems itemRange = - new SelectionRangeWithItems( range.ItemRange, null ); + SelectionRangeWithItems itemRange = new SelectionRangeWithItems( range.ItemRange, null ); if( !itemStorage.Contains( itemRange ) ) + { itemStorage.Add( itemRange ); + } } SelectionRange[] itemStorageArray = itemStorage.ToSelectionRangeArray(); @@ -602,22 +643,21 @@ namespace Xceed.Wpf.DataGrid.Export return itemStorageArray; } - private bool GetVisibleColumnsVisiblePositionForDataGridContext( - DataGridContext dataGridContext, - HashSet exportedColumnPositions ) + private bool GetVisibleColumnsVisiblePositionForDataGridContext( DataGridContext dataGridContext, HashSet exportedColumnPositions ) { if( dataGridContext == null ) return false; if( exportedColumnPositions == null ) + { exportedColumnPositions = new HashSet(); + } // At least 1 row was completely selected, add // all VisibleColumns' VisiblePosition if( dataGridContext.SelectedItemRanges.Count > 0 ) { - this.GetAllVisibleColumnsVisiblePosition( dataGridContext, - ref exportedColumnPositions ); + this.GetAllVisibleColumnsVisiblePosition( dataGridContext, ref exportedColumnPositions ); // Ensure to set the allColumnExported return true; @@ -641,7 +681,9 @@ namespace Xceed.Wpf.DataGrid.Export for( int i = startIndex; i <= endIndex; i++ ) { if( !exportedColumnPositions.Contains( i ) ) + { exportedColumnPositions.Add( i ); + } } } @@ -657,7 +699,9 @@ namespace Xceed.Wpf.DataGrid.Export while( m_currentIndentationLevel < detailLevel ) { foreach( ClipboardExporterBase clipboardExporter in m_clipboardExporters ) + { clipboardExporter.Indent(); + } Debug.Indent(); m_currentIndentationLevel++; @@ -670,7 +714,9 @@ namespace Xceed.Wpf.DataGrid.Export while( m_currentIndentationLevel > detailLevel ) { foreach( ClipboardExporterBase clipboardExporter in m_clipboardExporters ) + { clipboardExporter.Unindent(); + } Debug.Unindent(); m_currentIndentationLevel--; @@ -682,8 +728,6 @@ namespace Xceed.Wpf.DataGrid.Export return false; } - #endregion PRIVATE METHODS - #region IDisposable Members public void Dispose() @@ -696,135 +740,12 @@ namespace Xceed.Wpf.DataGrid.Export #endregion IDisposable Members - #region PRIVATE FIELDS - private Dictionary m_columnToBindingPathExtractor; // = null; private Dictionary m_visitedDetailExportedVisiblePositions; // = null; private Dictionary m_visitedDetailVisibleColumnsCache; // = null; private List m_clipboardExporters; // = null; private int m_currentIndentationLevel; // = 0; private int m_lastExportedHeaderDetailLevel = -1; - - #endregion PRIVATE FIELDS - - internal void Export( DataGridContext dataGridContext ) - { - if( dataGridContext == null ) - return; - - // Get the detail level for the current DataGridContext - int detailLevel = dataGridContext.DetailLevel; - - // Update indentation of ClipboardExporters for this detail level - this.UpdateExporterIndentation( detailLevel ); - - // Get master indexes that have mapped expanded details - List indexesToMasterItemList = - dataGridContext.CustomItemContainerGenerator.GetMasterIndexexWithExpandedDetails(); - - // Get the index of the next detail to export in case - // it is expanded before the first selected index of the - // current dataGridContext - int nextDetailIndex = ( indexesToMasterItemList.Count > 0 ) - ? indexesToMasterItemList[ 0 ] - : -1; - - // Get informations on columns, visible positions and selected item indexes - // for this dataGridContext - int[] exportedVisiblePositions = this.GetVisiblePositionsForContext( dataGridContext ); - ColumnBase[] columnsByVisiblePosition = this.GetVisibleColumnsArrayForContext( dataGridContext ); - SelectionRange[] selectedItemsRanges = this.GetSelectedItemsStoreForDataGridContext( dataGridContext ); - - Debug.Assert( exportedVisiblePositions != null ); - Debug.Assert( columnsByVisiblePosition != null ); - Debug.Assert( selectedItemsRanges != null ); - - int selectedItemsRangesCount = selectedItemsRanges.Length; - - // Ensure to flag the exporter has items - this.HasItems |= ( selectedItemsRangesCount > 0 ); - - for( int i = 0; i < selectedItemsRangesCount; i++ ) - { - // For the first level, ensure to export the headers - // before anything else - if( detailLevel == 0 ) - { - this.ExportHeaders( dataGridContext, - detailLevel, - exportedVisiblePositions, - columnsByVisiblePosition ); - } - - SelectionRange range = selectedItemsRanges[ i ]; - - int startIndex = range.StartIndex; - int endIndex = range.EndIndex; - - // If range is inverted - if( startIndex > endIndex ) - { - startIndex = range.EndIndex; - endIndex = range.StartIndex; - } - - // For each index in the range - for( int itemIndex = startIndex; itemIndex <= endIndex; itemIndex++ ) - { - // Export details that are before the itemIndex - while( ( nextDetailIndex != -1 ) && ( itemIndex > nextDetailIndex ) ) - { - this.ExportDetailForMasterIndex( dataGridContext, - detailLevel, - nextDetailIndex ); - - // Remove it since the detail is processed - indexesToMasterItemList.Remove( nextDetailIndex ); - - nextDetailIndex = ( indexesToMasterItemList.Count > 0 ) - ? indexesToMasterItemList[ 0 ] - : -1; - } - - // Ensure to re-export the headers if a detail was previously exported - this.ExportHeaders( dataGridContext, - detailLevel, - exportedVisiblePositions, - columnsByVisiblePosition ); - - object exportedItem = dataGridContext.Items.GetItemAt( itemIndex ); - - this.ExportDataItem( dataGridContext, - itemIndex, - exportedItem, - detailLevel, - exportedVisiblePositions, - columnsByVisiblePosition ); - } - } - - nextDetailIndex = ( indexesToMasterItemList.Count > 0 ) - ? indexesToMasterItemList[ 0 ] - : -1; - - // Export all remaining details since none are before the context's - // selected index ranges - while( nextDetailIndex != -1 ) - { - this.ExportDetailForMasterIndex( dataGridContext, - detailLevel, - nextDetailIndex ); - - // Remove it since the detail is processed - indexesToMasterItemList.Remove( nextDetailIndex ); - - nextDetailIndex = ( indexesToMasterItemList.Count > 0 ) - ? indexesToMasterItemList[ 0 ] - : -1; - } - } } - - #endregion } } diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/HtmlClipboardExporter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/HtmlClipboardExporter.cs new file mode 100644 index 00000000..f8529bf1 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/HtmlClipboardExporter.cs @@ -0,0 +1,217 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel; +using System.IO; +using System.Diagnostics; + +namespace Xceed.Wpf.DataGrid.Export +{ + public class HtmlClipboardExporter : ClipboardExporterBase + { + #region PUBLIC CONSTRUCTORS + + public HtmlClipboardExporter() + : base() + { + this.IncludeColumnHeaders = true; + this.FormatSettings = new HtmlFormatSettings(); + m_indentationString = string.Empty; + + // We keep a reference to the innerStream to return it when clipboard export is finished + m_memoryStream = new MemoryStream(); + m_baseStream = new CF_HtmlStream( m_memoryStream ); + } + + #endregion + + #region PUBLIC PROPERTIES + + public HtmlFormatSettings FormatSettings + { + get; + private set; + } + + #endregion + + #region PROTECTED OVERRIDES + + protected override object ClipboardData + { + get + { + // Return the innerStream of the CF_HtmlStream which contains the CF_HTML formatted data + return m_memoryStream; + } + } + + protected override void Indent() + { + string startDelimiter = this.FormatSettings.FieldStartDelimiter; + string endDelimiter = this.FormatSettings.FieldEndDelimiter; + + if( startDelimiter == null ) + startDelimiter = string.Empty; + + if( endDelimiter == null ) + endDelimiter = string.Empty; + + // By default, we suppose indentation as an empty field + m_indentationString += startDelimiter + endDelimiter; + } + + protected override void Unindent() + { + string startDelimiter = this.FormatSettings.FieldStartDelimiter; + string endDelimiter = this.FormatSettings.FieldEndDelimiter; + + if( startDelimiter == null ) + startDelimiter = string.Empty; + + if( endDelimiter == null ) + endDelimiter = string.Empty; + + if( m_indentationString == null ) + { + Debug.Fail( "Indentation must at least be string.empty when unindenting." ); + + // We initalize the indentation string and return + m_indentationString = string.Empty; + } + else + { + int emptyFieldLength = startDelimiter.Length + endDelimiter.Length; + int indentationLength = m_indentationString.Length; + + // If there are less characters in indentationString than in the empty field, just set indentation + // as string.empty + if( indentationLength < emptyFieldLength ) + { + m_indentationString = string.Empty; + } + else + { + m_indentationString = m_indentationString.Substring( 0, indentationLength - emptyFieldLength ); + } + } + } + + protected override void ResetExporter() + { + m_tempBuffer = null; + m_indentationString = string.Empty; + + // We must NOT close or dispose the previous MemoryStream since we pass this + // instance to the Clipboard directly and it becomes responsible of + // closing/disposing it + m_memoryStream = new MemoryStream(); + m_baseStream = new CF_HtmlStream( m_memoryStream ); + } + + protected override void StartExporter( string dataFormat ) + { + this.WriteToBaseStream( this.FormatSettings.ExporterStartDelimiter ); + } + + protected override void EndExporter( string dataFormat ) + { + this.WriteToBaseStream( this.FormatSettings.ExporterEndDelimiter ); + + // Force the header to be updated with length of HTML data and add the footer + m_baseStream.Close(); + } + + protected override void StartHeader( DataGridContext dataGridContext ) + { + this.WriteToBaseStream( this.FormatSettings.HeaderDataStartDelimiter ); + + if( string.IsNullOrEmpty( m_indentationString ) == false ) + { + this.WriteToBaseStream( m_indentationString ); + } + } + + protected override void StartHeaderField( DataGridContext dataGridContext, Column column ) + { + this.WriteToBaseStream( this.FormatSettings.HeaderFieldStartDelimiter ); + + object columnHeader = ( ( this.UseFieldNamesInHeader ) || ( column.Title == null ) ) ? column.FieldName : column.Title; + + string fieldValueString = FormatHelper.FormatHtmlFieldData( null, columnHeader, this.FormatSettings ); + + this.WriteToBaseStream( fieldValueString ); + this.WriteToBaseStream( this.FormatSettings.HeaderFieldEndDelimiter ); + } + + protected override void EndHeader( DataGridContext dataGridContext ) + { + this.WriteToBaseStream( this.FormatSettings.HeaderDataEndDelimiter ); + } + + protected override void StartDataItem( DataGridContext dataGridContext, object dataItem ) + { + this.WriteToBaseStream( this.FormatSettings.DataStartDelimiter ); + + if( string.IsNullOrEmpty( m_indentationString ) == false ) + { + this.WriteToBaseStream( m_indentationString ); + } + } + + protected override void StartDataItemField( DataGridContext dataGridContext, Column column, object fieldValue ) + { + this.WriteToBaseStream( this.FormatSettings.FieldStartDelimiter ); + string fieldValueString = FormatHelper.FormatHtmlFieldData( null, fieldValue, this.FormatSettings ); + this.WriteToBaseStream( fieldValueString ); + this.WriteToBaseStream( this.FormatSettings.FieldEndDelimiter ); + } + + protected override void EndDataItem( DataGridContext dataGridContext, object dataItem ) + { + this.WriteToBaseStream( this.FormatSettings.DataEndDelimiter ); + } + + #endregion + + #region PRIVATE METHODS + + private void WriteToBaseStream( string value ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + m_tempBuffer = Encoding.UTF8.GetBytes( value ); + + m_baseStream.Write( m_tempBuffer, 0, m_tempBuffer.Length ); + } + + #endregion + + #region PRIVATE FIELDS + + private string m_indentationString; // = null; + private MemoryStream m_memoryStream; // = null; + private CF_HtmlStream m_baseStream; // = null; + private byte[] m_tempBuffer; // = null; + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/HtmlFormatSettings.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/HtmlFormatSettings.cs new file mode 100644 index 00000000..59bb495f --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/HtmlFormatSettings.cs @@ -0,0 +1,106 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Xceed.Wpf.DataGrid.Export +{ + public class HtmlFormatSettings : FormatSettingsBase + { + public HtmlFormatSettings() + { + this.ExporterStartDelimiter = ""; + this.ExporterEndDelimiter = "
"; + + this.HeaderFieldStartDelimiter = ""; + this.HeaderFieldEndDelimiter = ""; + this.HeaderDataStartDelimiter = ""; + this.HeaderDataEndDelimiter = ""; + + this.FieldStartDelimiter = ""; + this.FieldEndDelimiter = ""; + this.DataStartDelimiter = ""; + this.DataEndDelimiter = ""; + } + + #region PUBLIC PROPERTIES + + public string ExporterStartDelimiter + { + get; + set; + } + + public string ExporterEndDelimiter + { + get; + set; + } + + public string HeaderFieldStartDelimiter + { + get; + set; + } + + public string HeaderFieldEndDelimiter + { + get; + set; + } + + public string HeaderDataStartDelimiter + { + get; + set; + } + + public string HeaderDataEndDelimiter + { + get; + set; + } + + public string FieldStartDelimiter + { + get; + set; + } + + public string FieldEndDelimiter + { + get; + set; + } + + public string DataStartDelimiter + { + get; + set; + } + + public string DataEndDelimiter + { + get; + set; + } + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/UnicodeCsvClipboardExporter.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/UnicodeCsvClipboardExporter.cs new file mode 100644 index 00000000..534d6db8 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/(Clipboard)/UnicodeCsvClipboardExporter.cs @@ -0,0 +1,338 @@ +/************************************************************************************* + + Extended WPF Toolkit + + Copyright (C) 2007-2013 Xceed Software Inc. + + This program is provided to you under the terms of the Microsoft Public + License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license + + For more features, controls, and fast professional support, + pick up the Plus Edition at http://xceed.com/wpf_toolkit + + Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids + + ***********************************************************************************/ + +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; + +namespace Xceed.Wpf.DataGrid.Export +{ + public class UnicodeCsvClipboardExporter : ClipboardExporterBase + { + public UnicodeCsvClipboardExporter() + { + this.IncludeColumnHeaders = true; + this.FormatSettings = new CsvFormatSettings(); + m_indentationString = string.Empty; + m_baseStream = new ToStringMemoryStream(); + } + + #region PUBLIC PROPERTIES + + public CsvFormatSettings FormatSettings + { + get; + private set; + } + + #endregion + + #region PROTECTED OVERRIDES + + protected override object ClipboardData + { + get + { + return m_baseStream; + } + } + + protected override void Indent() + { + char separator = this.FormatSettings.Separator; + m_indentationString += separator; + } + + protected override void Unindent() + { + char separator = this.FormatSettings.Separator; + + if( m_indentationString == null ) + { + Debug.Fail( "Indentation must at least be string.empty when unindenting." ); + m_indentationString = string.Empty; + } + else + { + int separatorLength = 1; + int indentationLength = m_indentationString.Length; + + // If there are less characters in indentationString than in the empty field, just set indentation + // as string.empty + if( indentationLength < separatorLength ) + { + m_indentationString = string.Empty; + } + else + { + m_indentationString = m_indentationString.Substring( 0, indentationLength - separatorLength ); + } + } + } + + protected override void ResetExporter() + { + m_baseStream = new ToStringMemoryStream(); + m_indentationString = string.Empty; + } + + protected override void StartHeader( DataGridContext dataGridContext ) + { + if( string.IsNullOrEmpty( m_indentationString ) == false ) + this.WriteToBaseStream( m_indentationString ); + + // The next StartDataItemField will be considered as first column + m_isFirstColumn = true; + } + + protected override void StartHeaderField( DataGridContext dataGridContext, Column column ) + { + // We always insert the separator before the value except for the first item + if( !m_isFirstColumn ) + { + this.WriteToBaseStream( this.FormatSettings.Separator ); + } + else + { + m_isFirstColumn = false; + } + + object columnHeader = ( ( this.UseFieldNamesInHeader ) || ( column.Title == null ) ) ? column.FieldName : column.Title; + string fieldValueString = UnicodeCsvClipboardExporter.FormatCsvData( null, columnHeader, this.FormatSettings ); + + this.WriteToBaseStream( fieldValueString ); + } + + protected override void EndHeader( DataGridContext dataGridContext ) + { + this.WriteToBaseStream( this.FormatSettings.NewLine ); + } + + protected override void StartDataItem( DataGridContext dataGridContext, object dataItem ) + { + if( string.IsNullOrEmpty( m_indentationString ) == false ) + this.WriteToBaseStream( m_indentationString ); + + // The next StartDataItemField will be considered as first column + m_isFirstColumn = true; + } + + protected override void StartDataItemField( DataGridContext dataGridContext, Column column, object fieldValue ) + { + // We always insert the separator before the value except for the first item + if( !m_isFirstColumn ) + { + this.WriteToBaseStream( this.FormatSettings.Separator ); + } + else + { + m_isFirstColumn = false; + } + + string fieldValueString = UnicodeCsvClipboardExporter.FormatCsvData( null, fieldValue, this.FormatSettings ); + + this.WriteToBaseStream( fieldValueString ); + } + + protected override void EndDataItem( DataGridContext dataGridContext, object dataItem ) + { + this.WriteToBaseStream( this.FormatSettings.NewLine ); + } + + #endregion + + #region PRIVATE METHODS + + private void WriteToBaseStream( char value ) + { + byte[] tempBuffer = Encoding.Unicode.GetBytes( new char[] { value } ); + m_baseStream.Write( tempBuffer, 0, tempBuffer.Length ); + } + + private void WriteToBaseStream( string value ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + byte[] tempBuffer = Encoding.Unicode.GetBytes( value ); + m_baseStream.Write( tempBuffer, 0, tempBuffer.Length ); + } + + #endregion + + #region Private Static Methods + + private static string FormatCsvData( Type dataType, object dataValue, CsvFormatSettings formatSettings ) + { + string outputString = null; + bool checkWhitespace = true; + + if( ( dataValue != null ) && ( !Convert.IsDBNull( dataValue ) ) && ( !( dataValue is Array ) ) ) + { + if( dataType == null ) + dataType = dataValue.GetType(); + + if( dataType == typeof( string ) ) + { + if( formatSettings.TextQualifier == '\0' ) + { + outputString = ( string )dataValue; + } + else + { + outputString = formatSettings.TextQualifier + ( string )dataValue + formatSettings.TextQualifier; + } + + checkWhitespace = false; + } + else if( dataType == typeof( DateTime ) ) + { + if( !string.IsNullOrEmpty( formatSettings.DateTimeFormat ) ) + { + if( formatSettings.Culture == null ) + { + outputString = ( ( DateTime )dataValue ).ToString( formatSettings.DateTimeFormat, CultureInfo.InvariantCulture ); + } + else + { + outputString = ( ( DateTime )dataValue ).ToString( formatSettings.DateTimeFormat, formatSettings.Culture ); + } + } + } + else if( ( dataType == typeof( double ) ) || + ( dataType == typeof( decimal ) ) || + ( dataType == typeof( float ) ) || + ( dataType == typeof( int ) ) || + ( dataType == typeof( double ) ) || + ( dataType == typeof( decimal ) ) || + ( dataType == typeof( float ) ) || + ( dataType == typeof( short ) ) || + ( dataType == typeof( Single ) ) || + ( dataType == typeof( UInt16 ) ) || + ( dataType == typeof( UInt32 ) ) || + ( dataType == typeof( UInt64 ) ) || + ( dataType == typeof( Int16 ) ) || + ( dataType == typeof( Int64 ) ) ) + { + string format = formatSettings.NumericFormat; + + if( ( ( dataType == typeof( double ) ) || + ( dataType == typeof( decimal ) ) || + ( dataType == typeof( float ) ) ) && + ( !string.IsNullOrEmpty( formatSettings.FloatingPointFormat ) ) ) + format = formatSettings.FloatingPointFormat; + + if( !string.IsNullOrEmpty( format ) ) + { + if( formatSettings.Culture == null ) + { + outputString = string.Format( CultureInfo.InvariantCulture, "{0:" + format + "}", dataValue ); + } + else + { + outputString = string.Format( formatSettings.Culture, "{0:" + format + "}", dataValue ); + } + } + } + + if( outputString == null ) + { + if( formatSettings.Culture == null ) + { + outputString = string.Format( CultureInfo.InvariantCulture, "{0}", dataValue ); + } + else + { + outputString = string.Format( formatSettings.Culture, "{0}", dataValue ); + } + } + + // For dates and numbers, as a rule, we never use the TextQualifier. However, the + // specified format can introduce whitespaces. To better support this case, we add + // the TextQualifier if needed. + if( ( checkWhitespace ) && ( formatSettings.TextQualifier != '\0' ) ) + { + bool useTextQualifier = false; + + // If the output string contains the character used to separate the fields, we + // don't bother checking for whitespace. TextQualifier will be used. + if( outputString.IndexOf( formatSettings.Separator ) < 0 ) + { + for( int i = 0; i < outputString.Length; i++ ) + { + if( char.IsWhiteSpace( outputString, i ) ) + { + useTextQualifier = true; + break; + } + } + } + else + { + useTextQualifier = true; + } + + if( useTextQualifier ) + outputString = formatSettings.TextQualifier + outputString + formatSettings.TextQualifier; + } + } + + return outputString; + } + + #endregion + + #region PRIVATE FIELDS + + private string m_indentationString; // = null; + private MemoryStream m_baseStream; // = null; + private bool m_isFirstColumn; // = false; + + #endregion + + #region ToStringMemoryStream Private Class + + // This class is used to force the ToString of the + // MemoryStream to return the content of the Stream + // instead of the name of the Type. + private class ToStringMemoryStream : MemoryStream + { + public override string ToString() + { + if( this.Length == 0 ) + { + return string.Empty; + } + else + { + try + { + return Encoding.Unicode.GetString( this.ToArray() ); + } + catch( Exception ) + { + return base.ToString(); + } + } + } + } + + #endregion + } +} + diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/FormatHelper.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/FormatHelper.cs index fc1a7df7..a8cfe398 100644 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/FormatHelper.cs +++ b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Export/FormatHelper.cs @@ -147,6 +147,85 @@ namespace Xceed.Wpf.DataGrid.Export return outputString; } + public static string FormatHtmlFieldData( Type dataType, object dataValue, HtmlFormatSettings formatSettings ) + { + string outputString = null; + + if( ( dataValue != null ) && ( !Convert.IsDBNull( dataValue ) ) && ( !( dataValue is Array ) ) ) + { + if( dataType == null ) + dataType = dataValue.GetType(); + + if( dataType == typeof( string ) ) + { + outputString = ( string )dataValue; + } + else if( dataType == typeof( DateTime ) ) + { + if( !string.IsNullOrEmpty( formatSettings.DateTimeFormat ) ) + { + if( formatSettings.Culture == null ) + { + outputString = ( ( DateTime )dataValue ).ToString( formatSettings.DateTimeFormat, CultureInfo.InvariantCulture ); + } + else + { + outputString = ( ( DateTime )dataValue ).ToString( formatSettings.DateTimeFormat, formatSettings.Culture ); + } + } + } + else if( ( dataType == typeof( double ) ) || + ( dataType == typeof( decimal ) ) || + ( dataType == typeof( float ) ) || + ( dataType == typeof( int ) ) || + ( dataType == typeof( double ) ) || + ( dataType == typeof( decimal ) ) || + ( dataType == typeof( float ) ) || + ( dataType == typeof( short ) ) || + ( dataType == typeof( Single ) ) || + ( dataType == typeof( UInt16 ) ) || + ( dataType == typeof( UInt32 ) ) || + ( dataType == typeof( UInt64 ) ) || + ( dataType == typeof( Int16 ) ) || + ( dataType == typeof( Int64 ) ) ) + { + string format = formatSettings.NumericFormat; + + if( ( ( dataType == typeof( double ) ) || + ( dataType == typeof( decimal ) ) || + ( dataType == typeof( float ) ) ) && + ( !string.IsNullOrEmpty( formatSettings.FloatingPointFormat ) ) ) + format = formatSettings.FloatingPointFormat; + + if( !string.IsNullOrEmpty( format ) ) + { + if( formatSettings.Culture == null ) + { + outputString = string.Format( CultureInfo.InvariantCulture, "{0:" + format + "}", dataValue ); + } + else + { + outputString = string.Format( formatSettings.Culture, "{0:" + format + "}", dataValue ); + } + } + } + + if( outputString == null ) + { + if( formatSettings.Culture == null ) + { + outputString = string.Format( CultureInfo.InvariantCulture, "{0}", dataValue ); + } + else + { + outputString = string.Format( formatSettings.Culture, "{0}", dataValue ); + } + } + } + + return FormatHelper.FormatPlainTextAsHtml( outputString ); + } + public static void FormatHtmlData( StringBuilder htmlDataStringBuilder ) { string htmlDataString = htmlDataStringBuilder.ToString(); @@ -201,7 +280,7 @@ namespace Xceed.Wpf.DataGrid.Export case '\r': break; - case ' ': + case '\u00A0': htmlStringBuilder.Append( " " ); break; diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/AndFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/AndFilterCriterion.cs deleted file mode 100644 index 0e15ef1c..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/AndFilterCriterion.cs +++ /dev/null @@ -1,209 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Linq.Expressions; -using System.Linq; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "@ AND @", FilterOperatorPrecedence.AndOperator, FilterTokenPriority.AndOperator )] - [DebuggerDisplay( "AND( {FirstFilterCriterion}, {SecondFilterCriterion} )" )] - public class AndFilterCriterion : FilterCriterion - { - public AndFilterCriterion() - { - } - - public AndFilterCriterion( FilterCriterion firstFilterCriterion, FilterCriterion secondFilterCriterion ) - { - this.FirstFilterCriterion = firstFilterCriterion; - this.SecondFilterCriterion = secondFilterCriterion; - } - - #region FirstFilterCriterion Property - - public FilterCriterion FirstFilterCriterion - { - get - { - return m_firstFilterCriterion; - } - - set - { - if( value == null ) - throw new ArgumentNullException( "FirstFilterCriterion" ); - - if( value != m_firstFilterCriterion ) - { - if( m_firstFilterCriterion != null ) - m_firstFilterCriterion.PropertyChanged -= new PropertyChangedEventHandler( FirstFilterCriterion_PropertyChanged ); - - m_firstFilterCriterion = value; - m_firstFilterCriterion.PropertyChanged += new PropertyChangedEventHandler( FirstFilterCriterion_PropertyChanged ); - this.RaisePropertyChanged( "FirstFilterCriterion" ); - } - } - } - - private void FirstFilterCriterion_PropertyChanged( object sender, PropertyChangedEventArgs e ) - { - this.RaisePropertyChanged( "FirstFilterCriterion" ); - } - - private FilterCriterion m_firstFilterCriterion; // = null; - - #endregion FirstFilterCriterion Property - - #region SecondFilterCriterion Property - - public FilterCriterion SecondFilterCriterion - { - get - { - return m_secondFilterCriterion; - } - - set - { - if( value == null ) - throw new ArgumentNullException( "SecondFilterCriterion" ); - - if( value != m_secondFilterCriterion ) - { - if( m_secondFilterCriterion != null ) - m_secondFilterCriterion.PropertyChanged -= new PropertyChangedEventHandler( SecondFilterCriterion_PropertyChanged ); - - m_secondFilterCriterion = value; - m_secondFilterCriterion.PropertyChanged += new PropertyChangedEventHandler( SecondFilterCriterion_PropertyChanged ); - this.RaisePropertyChanged( "SecondFilterCriterion" ); - } - } - } - - private void SecondFilterCriterion_PropertyChanged( object sender, PropertyChangedEventArgs e ) - { - this.RaisePropertyChanged( "SecondFilterCriterion" ); - } - - private FilterCriterion m_secondFilterCriterion; // = null; - - #endregion SecondFilterCriterion Property - - public override string ToExpression( CultureInfo culture ) - { - if( ( this.FirstFilterCriterion == null ) || ( this.SecondFilterCriterion == null ) ) - return ""; - - StringBuilder stringBuilder = new StringBuilder( this.FirstFilterCriterion.ToExpression( culture ) ); - stringBuilder.Append( " AND " ); - stringBuilder.Append( this.SecondFilterCriterion.ToExpression( culture ) ); - - return stringBuilder.ToString(); - } - - public override Expression ToLinqExpression( IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - Expression firstFilterLINQExpression = ( m_firstFilterCriterion == null ) ? null : m_firstFilterCriterion.ToLinqExpression( queryable, parameterExpression, propertyName ); - Expression secondFilterLINQExpression = ( m_secondFilterCriterion == null ) ? null : m_secondFilterCriterion.ToLinqExpression( queryable, parameterExpression, propertyName ); - - if( ( firstFilterLINQExpression != null ) && ( secondFilterLINQExpression != null ) ) - return Expression.And( firstFilterLINQExpression, secondFilterLINQExpression ); - - if( firstFilterLINQExpression != null ) - return firstFilterLINQExpression; - - // Will return null if both criterion or resulting LINQ expressions are null; - return secondFilterLINQExpression; - } - - public override bool IsMatch( object value ) - { - if( ( m_firstFilterCriterion == null ) || ( m_secondFilterCriterion == null ) ) - return false; - - return m_firstFilterCriterion.IsMatch( value ) && m_secondFilterCriterion.IsMatch( value ); - } - - public override bool Equals( object obj ) - { - if( !base.Equals( obj ) ) - return false; - - AndFilterCriterion criterion = ( AndFilterCriterion )obj; - - return object.Equals( this.FirstFilterCriterion, criterion.FirstFilterCriterion ) - && object.Equals( this.SecondFilterCriterion, criterion.SecondFilterCriterion ); - } - - public override int GetHashCode() - { - int hash = base.GetHashCode(); - - if( this.FirstFilterCriterion != null ) - hash ^= this.FirstFilterCriterion.GetHashCode(); - - if( this.SecondFilterCriterion != null ) - hash ^= this.SecondFilterCriterion.GetHashCode(); - - return hash; - } - -#if DEBUG - public override string ToString() - { - System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder( "AND( " ); - stringBuilder.Append( this.FirstFilterCriterion.ToString() ); - stringBuilder.Append( ", " ); - stringBuilder.Append( this.SecondFilterCriterion.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - - protected internal override void InitializeFrom( object[] parameters, Type defaultComparisonFilterCriterionType ) - { - Debug.Assert( parameters.Length == 2, "Should have been caught earlier during BuildCriterion." ); - - if( parameters.Length != 2 ) - throw new DataGridInternalException( "Missing operand for the AND operator." ); - - this.FirstFilterCriterion = FilterParser.ProduceCriterion( parameters[ 0 ], defaultComparisonFilterCriterionType ); - this.SecondFilterCriterion = FilterParser.ProduceCriterion( parameters[ 1 ], defaultComparisonFilterCriterionType ); - } - - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/ContainsFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/ContainsFilterCriterion.cs deleted file mode 100644 index dc479eea..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/ContainsFilterCriterion.cs +++ /dev/null @@ -1,99 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Linq.Expressions; -using System.Linq; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator )] - [DebuggerDisplay( "Contains( {Value} )" )] - public class ContainsFilterCriterion : RelationalFilterCriterion - { - public ContainsFilterCriterion() - : base() - { - } - - public ContainsFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - - return strValue ?? ""; - } - - public override Expression ToLinqExpression( IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - string queriedValue = this.Value as string; - - if( queriedValue == null ) - queriedValue = string.Empty; - - return queryable.CreateContainsExpression( parameterExpression, propertyName, queriedValue ); - } - - public override bool IsMatch( object value ) - { - if( value == null ) - return false; - - if( this.Value == null ) - return true; - - string searchedValue = this.Value.ToString().ToLower(); - - if( searchedValue.Length == 0 ) - return true; - - string strValue = value.ToString().ToLower(); - - return strValue.Contains( searchedValue ); - } - -#if DEBUG - public override string ToString() - { - System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder( "Contains( " ); - stringBuilder.Append( ( this.Value == null ) ? "" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/CriterionDescriptorAttribute.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/CriterionDescriptorAttribute.cs deleted file mode 100644 index e85fb828..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/CriterionDescriptorAttribute.cs +++ /dev/null @@ -1,59 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [ AttributeUsage( AttributeTargets.Class, Inherited = true, AllowMultiple = false ) ] - internal sealed class CriterionDescriptorAttribute : Attribute - { - public CriterionDescriptorAttribute( string pattern, FilterOperatorPrecedence operatorPrecedence, FilterTokenPriority parserPriority ) - { - m_pattern = pattern; - m_operatorPrecedence = operatorPrecedence; - m_parserPriority = parserPriority; - } - - public string Pattern - { - get - { - return m_pattern; - } - } - - public FilterOperatorPrecedence OperatorPrecedence - { - get - { - return m_operatorPrecedence; - } - } - - public FilterTokenPriority ParserPriority - { - get - { - return m_parserPriority; - } - } - - private readonly string m_pattern; - private readonly FilterOperatorPrecedence m_operatorPrecedence; - private readonly FilterTokenPriority m_parserPriority; - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/DifferentThanFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/DifferentThanFilterCriterion.cs deleted file mode 100644 index 02a6fafb..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/DifferentThanFilterCriterion.cs +++ /dev/null @@ -1,82 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Windows; -using System.Linq; -using System.Linq.Expressions; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "<>@", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator )] - [DebuggerDisplay( "DifferentThan( {Value} )" )] - public class DifferentThanFilterCriterion : RelationalFilterCriterion - { - public DifferentThanFilterCriterion() - : base() - { - } - - public DifferentThanFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - return ( strValue == null ) ? "" : "<>" + strValue; - } - - public override System.Linq.Expressions.Expression ToLinqExpression( IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - return queryable.CreateDifferentThanExpression( parameterExpression, propertyName, this.Value ); - } - - public override bool IsMatch( object value ) - { - return ( this.Compare( value ) != CompareResult.EqualsTo ); - } - -#if DEBUG - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder( "DifferentThan( " ); - stringBuilder.Append( ( this.Value == null ) ? "#NULL#" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/EndsWithFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/EndsWithFilterCriterion.cs deleted file mode 100644 index b7e02434..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/EndsWithFilterCriterion.cs +++ /dev/null @@ -1,103 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using System.Diagnostics; -using System.Globalization; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "*@", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator)] - [DebuggerDisplay( "EndsWith( {Value} )" )] - public class EndsWithFilterCriterion : RelationalFilterCriterion - { - public EndsWithFilterCriterion() - : base() - { - } - - public EndsWithFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - - return ( strValue == null ) ? "" : "*" + strValue; - } - - // TODO: to be tested - public override Expression ToLinqExpression( IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - string queriedValue = this.Value as string; - - if( queriedValue == null ) - queriedValue = string.Empty; - else - queriedValue = queriedValue.Remove( queriedValue.IndexOf( '*' ) ); - - return queryable.CreateEndsWithExpression( parameterExpression, propertyName, queriedValue ); - } - - public override bool IsMatch( object value ) - { - if( value == null ) - return false; - - if( this.Value == null ) - return true; - - string searchedValue = this.Value.ToString().ToLower(); - - if( searchedValue.Length == 0 ) - return true; - - string strValue = value.ToString().ToLower(); - return strValue.EndsWith( searchedValue, true, CultureInfo.CurrentCulture ); - } - -#if DEBUG - public override string ToString() - { - System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder( "EndsWith( " ); - stringBuilder.Append( ( this.Value == null ) ? "#NULL#" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/EqualToFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/EqualToFilterCriterion.cs deleted file mode 100644 index bc109faa..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/EqualToFilterCriterion.cs +++ /dev/null @@ -1,81 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Linq; -using System.Linq.Expressions; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "=@", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator )] - [DebuggerDisplay( "EqualTo( {Value} )" )] - public class EqualToFilterCriterion : RelationalFilterCriterion - { - public EqualToFilterCriterion() - : base() - { - } - - public EqualToFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - return ( strValue == null ) ? "" : "=" + strValue; - } - - public override Expression ToLinqExpression( IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - return queryable.CreateEqualExpression( parameterExpression, propertyName, this.Value ); - } - - public override bool IsMatch( object value ) - { - return ( this.Compare( value ) == CompareResult.EqualsTo ); - } - -#if DEBUG - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder( "EqualTo( " ); - stringBuilder.Append( ( this.Value == null ) ? "#NULL#" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/FilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/FilterCriterion.cs deleted file mode 100644 index 52fc32e8..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/FilterCriterion.cs +++ /dev/null @@ -1,112 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.ComponentModel; -using System.Globalization; -using System.Linq.Expressions; -using System.Linq; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [ CriterionDescriptor( "", FilterOperatorPrecedence.Default, FilterTokenPriority.Default ) ] - public abstract class FilterCriterion : INotifyPropertyChanged - { -#if DEBUG - [Obsolete( "This method exists for the general public. Consider using the overload receiving the culture." )] -#endif - public static FilterCriterion Parse( string expression, Type targetDataType ) - { - return FilterCriterion.Parse( expression, targetDataType, null ); - } - - public static FilterCriterion Parse( string expression, Type targetDataType, CultureInfo culture ) - { - if( expression == null ) - throw new ArgumentNullException( "expression" ); - - if( targetDataType == null ) - throw new ArgumentNullException( "targetDataType" ); - - return FilterParser.Parse( expression, targetDataType, culture ); - } - -#if DEBUG - [Obsolete( "This method exists for the general public. Consider using the overload receiving the culture." )] -#endif - public static bool TryParse( string expression, Type targetDataType, out FilterCriterion filterCriterion ) - { - return FilterCriterion.TryParse( expression, targetDataType, null, out filterCriterion ); - } - - public static bool TryParse( string expression, Type targetDataType, CultureInfo culture, out FilterCriterion filterCriterion ) - { - if( expression == null ) - throw new ArgumentNullException( "expression" ); - - if( targetDataType == null ) - throw new ArgumentNullException( "targetDataType" ); - - filterCriterion = FilterParser.TryParse( expression, targetDataType, culture ); - - return ( filterCriterion != null ) || ( FilterParser.LastError.Length == 0 ); - } - - public abstract bool IsMatch( object value ); - - public abstract string ToExpression( CultureInfo culture); - - public abstract Expression ToLinqExpression( IQueryable queryable, ParameterExpression parameterExpression, string propertyName ); - - public override bool Equals( object obj ) - { - FilterCriterion filterCriterion = obj as FilterCriterion; - - if( filterCriterion == null ) - return false; - - return this.GetType() == filterCriterion.GetType(); - } - - public override int GetHashCode() - { - return this.GetType().GetHashCode(); - } - -#if DEBUG - public override string ToString() - { - return "#" + this.GetType().Name + "#"; - } -#endif - - protected internal abstract void InitializeFrom( object[] parameters, Type defaultComparisonFilterCriterionType ); - - #region INotifyPropertyChanged Implementation - - public event PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged( string name ) - { - if( this.PropertyChanged != null ) - { - this.PropertyChanged( this, new PropertyChangedEventArgs( name ) ); - } - } - - #endregion - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/GreaterThanFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/GreaterThanFilterCriterion.cs deleted file mode 100644 index 7d7530e8..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/GreaterThanFilterCriterion.cs +++ /dev/null @@ -1,80 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Linq.Expressions; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( ">@", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator )] - [DebuggerDisplay( "GreaterThan( {Value} )" )] - public class GreaterThanFilterCriterion : RelationalFilterCriterion - { - public GreaterThanFilterCriterion() - : base() - { - } - - public GreaterThanFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - return ( strValue == null ) ? "" : ">" + strValue; - } - - public override System.Linq.Expressions.Expression ToLinqExpression( System.Linq.IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - return queryable.CreateGreaterThanExpression( parameterExpression, propertyName, this.Value ); - } - - public override bool IsMatch( object value ) - { - return ( this.Compare( value ) == CompareResult.GreaterThan ); - } - -#if DEBUG - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder( "GreaterThan( " ); - stringBuilder.Append( ( this.Value == null ) ? "#NULL#" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/GreaterThanOrEqualToFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/GreaterThanOrEqualToFilterCriterion.cs deleted file mode 100644 index db1b70a6..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/GreaterThanOrEqualToFilterCriterion.cs +++ /dev/null @@ -1,81 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Linq.Expressions; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( ">=@", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator )] - [DebuggerDisplay( "GreaterThanOrEqualTo( {Value} )" )] - public class GreaterThanOrEqualToFilterCriterion : RelationalFilterCriterion - { - public GreaterThanOrEqualToFilterCriterion() - : base() - { - } - - public GreaterThanOrEqualToFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - return ( strValue == null ) ? "" : ">=" + strValue; - } - - public override System.Linq.Expressions.Expression ToLinqExpression( System.Linq.IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - return queryable.CreateGreaterThanOrEqualExpression( parameterExpression, propertyName, this.Value ); - } - - public override bool IsMatch( object value ) - { - CompareResult result = this.Compare( value ); - return ( result == CompareResult.EqualsTo ) || ( result == CompareResult.GreaterThan ); - } - -#if DEBUG - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder( "GreaterThanOrEqualTo( " ); - stringBuilder.Append( ( this.Value == null ) ? "#NULL#" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/LessThanFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/LessThanFilterCriterion.cs deleted file mode 100644 index 3888f67f..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/LessThanFilterCriterion.cs +++ /dev/null @@ -1,80 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Linq.Expressions; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "<@", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator )] - [DebuggerDisplay( "LessThan( {Value} )" )] - public class LessThanFilterCriterion : RelationalFilterCriterion - { - public LessThanFilterCriterion() - : base() - { - } - - public LessThanFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - return ( strValue == null ) ? "" : "<" + strValue; - } - - public override System.Linq.Expressions.Expression ToLinqExpression( System.Linq.IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - return queryable.CreateLesserThanExpression( parameterExpression, propertyName, this.Value ); - } - - public override bool IsMatch( object value ) - { - return ( this.Compare( value ) == CompareResult.LessThan ); - } - -#if DEBUG - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder( "LessThan( " ); - stringBuilder.Append( ( this.Value == null ) ? "#NULL#" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/LessThanOrEqualToFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/LessThanOrEqualToFilterCriterion.cs deleted file mode 100644 index 62e26ddd..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/LessThanOrEqualToFilterCriterion.cs +++ /dev/null @@ -1,81 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Linq.Expressions; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "<=@", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator )] - [DebuggerDisplay( "LessThanOrEqualTo( {Value} )" )] - public class LessThanOrEqualToFilterCriterion : RelationalFilterCriterion - { - public LessThanOrEqualToFilterCriterion() - : base() - { - } - - public LessThanOrEqualToFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - return ( strValue == null ) ? "" : "<=" + strValue; - } - - public override System.Linq.Expressions.Expression ToLinqExpression( System.Linq.IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - return queryable.CreateLesserThanOrEqualExpression( parameterExpression, propertyName, this.Value ); - } - - public override bool IsMatch( object value ) - { - CompareResult result = this.Compare( value ); - return ( result == CompareResult.EqualsTo ) || ( result == CompareResult.LessThan ); - } - -#if DEBUG - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder( "LessThanOrEqualTo( " ); - stringBuilder.Append( ( this.Value == null ) ? "#NULL#" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/NotFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/NotFilterCriterion.cs deleted file mode 100644 index 74836636..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/NotFilterCriterion.cs +++ /dev/null @@ -1,157 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Windows.Markup; -using System.Linq.Expressions; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [ContentProperty( "FilterCriterion" )] - [CriterionDescriptor( "NOT @", FilterOperatorPrecedence.NotOperator, FilterTokenPriority.NotOperator )] - [DebuggerDisplay( "NOT( {FilterCriterion} )" )] - public class NotFilterCriterion : FilterCriterion - { - public NotFilterCriterion() - { - } - - public NotFilterCriterion( FilterCriterion filterCriterion ) - { - this.FilterCriterion = filterCriterion; - } - - #region FilterCriterion Property - - public FilterCriterion FilterCriterion - { - get - { - return m_filterCriterion; - } - - set - { - if( value == null ) - throw new ArgumentNullException( "FilterCriterion" ); - - if( value != m_filterCriterion ) - { - if( m_filterCriterion != null ) - m_filterCriterion.PropertyChanged -= new PropertyChangedEventHandler( FilterCriterion_PropertyChanged ); - - m_filterCriterion = value; - m_filterCriterion.PropertyChanged += new PropertyChangedEventHandler( FilterCriterion_PropertyChanged ); - this.RaisePropertyChanged( "FilterCriterion" ); - } - } - } - - private void FilterCriterion_PropertyChanged( object sender, PropertyChangedEventArgs e ) - { - this.RaisePropertyChanged( "FilterCriterion" ); - } - - private FilterCriterion m_filterCriterion; // = null; - - #endregion FilterCriterion Property - - public override string ToExpression( CultureInfo culture ) - { - if( this.FilterCriterion == null ) - return ""; - - return "NOT " + this.FilterCriterion.ToExpression( culture ); - } - - public override System.Linq.Expressions.Expression ToLinqExpression( System.Linq.IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - if( m_filterCriterion == null ) - return null; - - Expression expressionToReverse = m_filterCriterion.ToLinqExpression( queryable, parameterExpression, propertyName ); - - if( expressionToReverse == null ) - return null; - - return Expression.Not( expressionToReverse ); - } - - public override bool IsMatch( object value ) - { - if( m_filterCriterion == null ) - return false; - - return !m_filterCriterion.IsMatch( value ); - } - - protected internal override void InitializeFrom( object[] parameters, Type defaultComparisonFilterCriterionType ) - { - if( parameters.Length != 1 ) - throw new DataGridException( string.Format( FilterParser.MissingRightOperandErrorText, this.GetType().Name ) ); - - this.FilterCriterion = FilterParser.ProduceCriterion( parameters[ 0 ], defaultComparisonFilterCriterionType ); - } - - public override bool Equals( object obj ) - { - if( !base.Equals( obj ) ) - return false; - - NotFilterCriterion criterion = ( NotFilterCriterion )obj; - - return object.Equals( this.FilterCriterion, criterion.FilterCriterion ); - } - - public override int GetHashCode() - { - int hash = base.GetHashCode(); - - if( this.FilterCriterion != null ) - hash ^= this.FilterCriterion.GetHashCode(); - - return hash; - } - -#if DEBUG - public override string ToString() - { - System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder( "NOT( " ); - stringBuilder.Append( ( this.FilterCriterion == null ) ? "#NULL#" : this.FilterCriterion.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/OrFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/OrFilterCriterion.cs deleted file mode 100644 index 96544b74..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/OrFilterCriterion.cs +++ /dev/null @@ -1,211 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Text; -using System.Windows; -using System.Linq.Expressions; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "@ OR @", FilterOperatorPrecedence.OrOperator, FilterTokenPriority.OrOperator )] - [DebuggerDisplay( "OR( {FirstFilterCriterion}, {SecondFilterCriterion} )" )] - public class OrFilterCriterion : FilterCriterion - { - public OrFilterCriterion() - { - } - - public OrFilterCriterion( FilterCriterion firstFilterCriterion, FilterCriterion secondFilterCriterion ) - { - this.FirstFilterCriterion = firstFilterCriterion; - this.SecondFilterCriterion = secondFilterCriterion; - } - - #region FirstFilterCriterion Property - - public FilterCriterion FirstFilterCriterion - { - get - { - return m_firstFilterCriterion; - } - - set - { - if( value == null ) - throw new ArgumentNullException( "FirstFilterCriterion" ); - - if( value != m_firstFilterCriterion ) - { - if( m_firstFilterCriterion != null ) - m_firstFilterCriterion.PropertyChanged -= new PropertyChangedEventHandler( FirstFilterCriterion_PropertyChanged ); - - m_firstFilterCriterion = value; - m_firstFilterCriterion.PropertyChanged += new PropertyChangedEventHandler( FirstFilterCriterion_PropertyChanged ); - this.RaisePropertyChanged( "FirstFilterCriterion" ); - } - } - } - - private void FirstFilterCriterion_PropertyChanged( object sender, PropertyChangedEventArgs e ) - { - this.RaisePropertyChanged( "FirstFilterCriterion" ); - } - - private FilterCriterion m_firstFilterCriterion; // = null; - - #endregion FirstFilterCriterion Property - - #region SecondFilterCriterion Property - - public FilterCriterion SecondFilterCriterion - { - get - { - return m_secondFilterCriterion; - } - - set - { - if( value == null ) - throw new ArgumentNullException( "SecondFilterCriterion" ); - - if( value != m_secondFilterCriterion ) - { - if( m_secondFilterCriterion != null ) - m_secondFilterCriterion.PropertyChanged -= new PropertyChangedEventHandler( SecondFilterCriterion_PropertyChanged ); - - m_secondFilterCriterion = value; - m_secondFilterCriterion.PropertyChanged += new PropertyChangedEventHandler( SecondFilterCriterion_PropertyChanged ); - this.RaisePropertyChanged( "SecondFilterCriterion" ); - } - } - } - - private void SecondFilterCriterion_PropertyChanged( object sender, PropertyChangedEventArgs e ) - { - this.RaisePropertyChanged( "SecondFilterCriterion" ); - } - - private FilterCriterion m_secondFilterCriterion; // = null; - - #endregion SecondFilterCriterion Property - - public override string ToExpression( CultureInfo culture ) - { - if( ( this.FirstFilterCriterion == null ) || ( this.SecondFilterCriterion == null ) ) - return ""; - - StringBuilder builder = new StringBuilder( this.FirstFilterCriterion.ToExpression( culture ) ); - builder.Append( " OR " ); - builder.Append( this.SecondFilterCriterion.ToExpression( culture ) ); - - return builder.ToString(); - } - - public override System.Linq.Expressions.Expression ToLinqExpression( System.Linq.IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - System.Linq.Expressions.Expression firstFilterLINQExpression = - ( m_firstFilterCriterion == null ) ? null : m_firstFilterCriterion.ToLinqExpression( queryable, parameterExpression, propertyName ); - - System.Linq.Expressions.Expression secondFilterLINQExpression = - ( m_secondFilterCriterion == null ) ? null : m_secondFilterCriterion.ToLinqExpression( queryable, parameterExpression, propertyName ); - - if( ( firstFilterLINQExpression != null ) && ( secondFilterLINQExpression != null ) ) - return System.Linq.Expressions.Expression.Or( firstFilterLINQExpression, secondFilterLINQExpression ); - - if( firstFilterLINQExpression != null ) - return firstFilterLINQExpression; - - // Will return null if both criterion or resulting LINQ expressions are null; - return secondFilterLINQExpression; - } - - public override bool IsMatch( object value ) - { - if( ( m_firstFilterCriterion == null ) || ( m_secondFilterCriterion == null ) ) - return false; - - return m_firstFilterCriterion.IsMatch( value ) || m_secondFilterCriterion.IsMatch( value ); - } - - public override bool Equals( object obj ) - { - if( !base.Equals( obj ) ) - return false; - - OrFilterCriterion criterion = ( OrFilterCriterion )obj; - - return object.Equals( this.FirstFilterCriterion, criterion.FirstFilterCriterion ) - && object.Equals( this.SecondFilterCriterion, criterion.SecondFilterCriterion ); - } - - public override int GetHashCode() - { - int hash = base.GetHashCode(); - - if( this.FirstFilterCriterion != null ) - hash ^= this.FirstFilterCriterion.GetHashCode(); - - if( this.SecondFilterCriterion != null ) - hash ^= this.SecondFilterCriterion.GetHashCode(); - - return hash; - } - -#if DEBUG - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder( "OR( " ); - stringBuilder.Append( this.FirstFilterCriterion.ToString() ); - stringBuilder.Append( ", " ); - stringBuilder.Append( this.SecondFilterCriterion.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - - protected internal override void InitializeFrom( object[] parameters, Type defaultComparisonFilterCriterionType ) - { - Debug.Assert( parameters.Length == 2, "Should have been caught earlier during BuildCriterion." ); - - if( parameters.Length != 2 ) - throw new DataGridInternalException( "Missing operand for the OR operator." ); - - this.FirstFilterCriterion = FilterParser.ProduceCriterion( parameters[ 0 ], defaultComparisonFilterCriterionType ); - this.SecondFilterCriterion = FilterParser.ProduceCriterion( parameters[ 1 ], defaultComparisonFilterCriterionType ); - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/RelationalFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/RelationalFilterCriterion.cs deleted file mode 100644 index bff39a05..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/RelationalFilterCriterion.cs +++ /dev/null @@ -1,231 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Windows.Markup; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [ContentProperty( "Value" )] - public abstract class RelationalFilterCriterion : FilterCriterion - { - public RelationalFilterCriterion() - { - } - - public RelationalFilterCriterion( object value ) - { - this.Value = value; - } - - #region Value Property - - public object Value - { - get - { - return m_value; - } - - set - { - if( value != m_value ) - { - m_value = value; - m_comparableValue = value as IComparable; - this.RaisePropertyChanged( "Value" ); - } - } - } - - protected IComparable ComparableValue - { - get - { - return m_comparableValue; - } - } - - private object m_value; - private IComparable m_comparableValue; - - #endregion Value Property - - public override bool Equals( object obj ) - { - if( !base.Equals( obj ) ) - return false; - - RelationalFilterCriterion criterion = ( RelationalFilterCriterion )obj; - - return object.Equals( this.Value, criterion.Value ); - } - - public override int GetHashCode() - { - int hash = base.GetHashCode(); - - if( this.Value != null ) - hash ^= this.Value.GetHashCode(); - - return hash; - } - - // Can return null. - protected string GetValueForExpression( CultureInfo culture ) - { - string strValue = this.Value as string; - - if( ( this.Value == null ) || ( this.Value == DBNull.Value ) ) - { - strValue = "NULL"; - } - else if( strValue == null ) - { - Type dataType = this.Value.GetType(); - - if( dataType == typeof( DateTime ) ) - { - DateTime dateValue = ( DateTime )this.Value; - - // ISO 8601 format - if( ( dateValue.Hour > 0 ) - || ( dateValue.Minute > 0 ) - || ( dateValue.Second > 0 ) - || ( dateValue.Millisecond > 0 ) ) - { - strValue = ( ( DateTime )this.Value ).ToString( "yyyy-MM-ddTHH:mm:ss.FFFFFFF" ); - } - else - { - strValue = ( ( DateTime )this.Value ).ToString( "yyyy-MM-dd" ); - } - } - else - { - try - { - if( culture == null ) - { - strValue = Convert.ToString( this.Value ); - } - else - { - strValue = Convert.ToString( this.Value, culture ); - } - } - catch( OverflowException ) - { - } - catch( FormatException ) - { - } - } - } - - if( strValue != null ) - { - int index = strValue.Length - 1; - - if( strValue == "" ) - strValue = "\"\""; - - while( index >= 0 ) - { - if( strValue[ index ] == '"' ) - { - strValue = strValue.Insert( index, "\"" ); - } - - index--; - } - - if( strValue.Contains( " " ) ) - { - strValue = "\"" + strValue + "\""; - } - } - - return strValue; - } - - protected internal override void InitializeFrom( object[] parameters, Type defaultComparisonFilterCriterionType ) - { - if( parameters.Length != 1 ) - throw new DataGridException( string.Format( FilterParser.MissingRightOperandErrorText, this.GetType().Name ) ); - - Debug.Assert( !( parameters[ 0 ] is FilterCriterion), "Should have been caught earlier during BuildCriterion." ); - - if( parameters[ 0 ] is FilterCriterion ) - throw new DataGridInternalException( "Comparison with the result of a filter criterion is not allowed." ); - - this.Value = parameters[ 0 ]; - } - - /// - /// Compare the specified value (left value) with the Value property (right value). - /// For instance, this method will return LessThan if value < this.Value. - /// - internal CompareResult Compare( object value ) - { - object value2 = this.Value; - - if( ( value == null ) || ( value == DBNull.Value ) || (value as string == string.Empty) ) - { - if( ( value2 == null ) || ( value2 == DBNull.Value ) || ( ( value2 as string ) == string.Empty ) ) - { - return CompareResult.EqualsTo; - } - else - { - return CompareResult.LessThan; - } - } - else - { - if( ( value2 == null ) || ( value2 == DBNull.Value ) ) - { - return CompareResult.GreaterThan; - } - else if( m_comparableValue == null ) - { - return object.Equals( value, value2 ) ? CompareResult.EqualsTo : CompareResult.DifferentThan; - } - else - { - int i = m_comparableValue.CompareTo( value ); - - if( i < 0 ) - { - // value2 is less than value1: value is greater than. - return CompareResult.GreaterThan; - } - else if( i == 0 ) - { - return CompareResult.EqualsTo; - } - else - { - // value2 is greater than value1: value is less than. - return CompareResult.LessThan; - } - } - } - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/StartsWithFilterCriterion.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/StartsWithFilterCriterion.cs deleted file mode 100644 index 200374d0..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterCriteria/StartsWithFilterCriterion.cs +++ /dev/null @@ -1,103 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using System.Diagnostics; -using System.Globalization; - -namespace Xceed.Wpf.DataGrid.FilterCriteria -{ - [CriterionDescriptor( "@*", FilterOperatorPrecedence.RelationalOperator, FilterTokenPriority.RelationalOperator )] - [DebuggerDisplay( "StartsWith( {Value} )" )] - public class StartsWithFilterCriterion : RelationalFilterCriterion - { - public StartsWithFilterCriterion() - : base() - { - } - - public StartsWithFilterCriterion( object value ) - : base( value ) - { - } - - public override string ToExpression( CultureInfo culture ) - { - string strValue = this.GetValueForExpression( culture ); - - return ( strValue == null ) ? "" : strValue + "*"; - } - - // TODO: to be tested - public override Expression ToLinqExpression( IQueryable queryable, ParameterExpression parameterExpression, string propertyName ) - { - if( queryable == null ) - throw new ArgumentNullException( "queryable" ); - - if( parameterExpression == null ) - throw new ArgumentNullException( "parameterExpression" ); - - if( String.IsNullOrEmpty( propertyName ) ) - { - if( propertyName == null ) - throw new ArgumentNullException( "propertyName" ); - - throw new ArgumentException( "PropertyName must not be empty.", "propertyName" ); - } - - string queriedValue = this.Value as string; - - - if( queriedValue == null ) - queriedValue = string.Empty; - else - queriedValue = queriedValue.Remove( queriedValue.LastIndexOf( '*' ) ); - - return queryable.CreateStartsWithExpression( parameterExpression, propertyName, queriedValue ); - } - - public override bool IsMatch( object value ) - { - if( value == null ) - return false; - - if( this.Value == null ) - return true; - - string searchedValue = this.Value.ToString().ToLower(); - - if( searchedValue.Length == 0 ) - return true; - - string strValue = value.ToString().ToLower(); - return strValue.StartsWith( searchedValue, true, CultureInfo.CurrentCulture ); - } -#if DEBUG - public override string ToString() - { - System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder( "StartsWith( " ); - stringBuilder.Append( ( this.Value == null ) ? "#NULL#" : this.Value.ToString() ); - stringBuilder.Append( " )" ); - - return stringBuilder.ToString(); - } -#endif - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterParser.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterParser.cs deleted file mode 100644 index 919bb6e7..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterParser.cs +++ /dev/null @@ -1,809 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Globalization; -using System.Text; - -using Xceed.Wpf.DataGrid.FilterCriteria; - -namespace Xceed.Wpf.DataGrid -{ - internal static partial class FilterParser - { - static FilterParser() - { - RegisteredFilterCriterionTypes.Add( typeof( AndFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( ContainsFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( DifferentThanFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( EqualToFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( GreaterThanOrEqualToFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( GreaterThanFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( LessThanOrEqualToFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( LessThanFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( NotFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( OrFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( EndsWithFilterCriterion ) ); - RegisteredFilterCriterionTypes.Add( typeof( StartsWithFilterCriterion ) ); - - } - - public static string LastError - { - get - { - return FilterParser.LastErrorString; - } - - set - { - // Always keep the error message that triggered the error state for this session. - if( string.IsNullOrEmpty( value ) || string.IsNullOrEmpty( FilterParser.LastErrorString ) ) - FilterParser.LastErrorString = value; - } - } - - public static FilterCriterion ProduceCriterion( object parameterValue, Type defaultComparisonFilterCriterionType ) - { - if( parameterValue is FilterCriterion ) - { - return ( FilterCriterion )parameterValue; - } - else - { - if( !typeof( RelationalFilterCriterion ).IsAssignableFrom( defaultComparisonFilterCriterionType ) ) - throw new DataGridInternalException( "The default FilterCriterion type should derived from RelationalFilterCriterion." ); - - return Activator.CreateInstance( defaultComparisonFilterCriterionType, parameterValue ) as RelationalFilterCriterion; - } - } - - // If culture is null, CurrentThread.CurrentCulture will be used when necessary. - public static FilterCriterion Parse( string expression, Type dataType, CultureInfo culture ) - { - FilterCriterion filterCriterion = null; - List tokens = new List(); - - FilterParser.LastError = null; - - FilterParser.PrepareExpressionTokens( expression, tokens ); - - Type defaultCriterionType = ( dataType == typeof( string ) ) ? typeof( ContainsFilterCriterion ) : typeof( EqualToFilterCriterion ); - - FilterParser.Tokenize( tokens, dataType, defaultCriterionType ); - FilterParser.TrimTokens( tokens ); - filterCriterion = FilterParser.BuildCriterion( tokens, dataType, defaultCriterionType, culture ); - - return filterCriterion; - } - - public static FilterCriterion TryParse( string expression, Type dataType, CultureInfo culture ) - { - FilterCriterion filterCriterion = null; - FilterParser.LastError = null; - - try - { - filterCriterion = FilterParser.Parse( expression, dataType, culture ); - } - catch( Exception ex ) - { - FilterParser.LastError = ex.Message; - } - - return filterCriterion; - } - - private static void TrimTokens( List tokens ) - { - RawToken rawToken; - - for( int index = tokens.Count - 1; index >= 0; index-- ) - { - rawToken = tokens[ index ] as RawToken; - - if( rawToken != null ) - { - rawToken.Value = rawToken.Value.Trim(); - - if( rawToken.Value.Length == 0 ) - tokens.RemoveAt( index ); - } - } - } - - private static void FillPrecedenceList( List precedences ) - { - foreach( Type type in FilterParser.RegisteredFilterCriterionTypes ) - { - CriterionDescriptorAttribute attribute = ( CriterionDescriptorAttribute )type.GetCustomAttributes( typeof( CriterionDescriptorAttribute ), true )[ 0 ]; - - if( !precedences.Contains( ( int )attribute.OperatorPrecedence ) ) - precedences.Add( ( int )attribute.OperatorPrecedence ); - } - - precedences.Sort(); - } - - private static void FillParserPriorityList( List parserPriorities ) - { - foreach( Type type in FilterParser.RegisteredFilterCriterionTypes ) - { - CriterionDescriptorAttribute attribute = ( CriterionDescriptorAttribute )type.GetCustomAttributes( typeof( CriterionDescriptorAttribute ), true )[ 0 ]; - - if( !parserPriorities.Contains( ( int )attribute.ParserPriority ) ) - parserPriorities.Add( ( int )attribute.ParserPriority ); - } - - parserPriorities.Sort(); - } - - /// - /// Transforms the specified expression into one or more preliminary Tokens (RawToken - /// or AtomicStringToken). - /// - private static void PrepareExpressionTokens( string expression, List tokens ) - { - // Start index in the expression when we exclude all added tokens so far. This - // value is only updated after closing an atomic string token. - int stringStartIndex = 0; - // count the number of double quotes simplified - int quotesCounter = 0; - // Index of the first found " starting from the current position (0 for the first). - int quoteIndex = 0; - // Index of the first non " character after a found ". - int quotesEnd = 0; - // Index of the first character after the opening ". - int quotesStart = 0; - bool quoteOpened = false; - - expression = expression.Trim(); - quoteIndex = expression.IndexOf( '"' ); - - while( quoteIndex >= 0 ) - { - quotesEnd = quoteIndex + 1; - - // Find the first non " character starting from the index found. - while( quotesEnd < expression.Length ) - { - if( expression[ quotesEnd ] != '"' ) - break; - - quotesEnd++; - } - - if( ( (( quotesEnd - quoteIndex > 1 ) && ( quoteOpened ) ) ) ) - { - // Transform the " couples to a single ". - StringBuilder temp = new StringBuilder( expression.Substring( 0, quoteIndex ) ); - - for( int i = 0; i < ( quotesEnd - quoteIndex ) / 2; i++ ) - { - temp.Append( '"' ); - quotesCounter++ ; - } - temp.Append( expression.Substring( quotesEnd ) ); - - // Manually add the excess " when we're handling an odd number of " (can only - // happen when forming an AtomicString). The quotesCounter indicates where the - // last quotes have to be added (in case of (Starts/Ends)With, the quotes were misplaced). - if( ( quotesEnd - quoteIndex ) % 2 != 0 ) - { - temp.Insert( quotesEnd - quotesCounter - 1, "\"" ); - quotesCounter = 0; - } - expression = temp.ToString(); - - // Continue looking from the first character after the last " couple. - quoteIndex = quoteIndex + ( quotesEnd - quoteIndex ) / 2; - } - - else - { - if( quoteOpened ) - { - tokens.Add( new AtomicStringToken( expression.Substring( quotesStart, quoteIndex - quotesStart ) ) ); - stringStartIndex = quoteIndex + 1; - } - else - { - if( quoteIndex > stringStartIndex ) - tokens.Add( new RawToken( expression.Substring( stringStartIndex, quoteIndex - stringStartIndex ) ) ); - - quotesStart = quoteIndex + 1; - } - - quoteOpened = !quoteOpened; - quoteIndex++; - } - - quoteIndex = expression.IndexOf( '"', quoteIndex ); - } - - if( quoteOpened ) - throw new DataGridException( FilterParser.MissingClosingQuotesErrorText ); - - if( ( stringStartIndex > 0 ) && ( stringStartIndex < expression.Length ) ) - { - if( stringStartIndex < expression.Length ) - tokens.Add( new RawToken( expression.Substring( stringStartIndex ) ) ); - } - - if( tokens.Count == 0 ) - { - tokens.Add( new RawToken( expression ) ); - } - } - - private static void Tokenize( List tokens, Type dataType, Type defaultCriterionType ) - { - if( !typeof( FilterCriterion ).IsAssignableFrom( defaultCriterionType ) ) - throw new DataGridInternalException( "The default criterion type should be derived from the FilterCriterion class." ); - - List parserPriorities = new List(); - FilterParser.FillParserPriorityList( parserPriorities ); - - FilterParser.Tokenize( parserPriorities, tokens ); - - if( ( tokens.Count == 1 ) && ( tokens[ 0 ] is ValueToken ) ) - { - if( defaultCriterionType == typeof( ContainsFilterCriterion ) ) - { - // ContainsFilterCriterion has no keyword associated; it won't be handled when - // building the criterion. Initialize it with the Value already in it. - FilterCriterionToken containsToken = new FilterCriterionToken( ( FilterCriterion )Activator.CreateInstance( defaultCriterionType, ( ( ValueToken )tokens[ 0 ] ).Value ) ); - tokens.Clear(); - tokens.Add( containsToken ); - } - else - { - // Insert the default token previous to the value. - FilterCriterionToken defaultToken = new FilterCriterionToken( ( FilterCriterion )Activator.CreateInstance( defaultCriterionType ) ); - tokens.Insert( 0, defaultToken ); - } - } - } - - private static void Tokenize( List parserPriorities, List tokens ) - { - for( int index = 0; index < parserPriorities.Count; index++ ) - { - int curParserPriority = parserPriorities[ index ]; - bool tokenAdded = false; - - do - { - tokenAdded = false; - - for( int tokenIndex = 0; tokenIndex < tokens.Count; tokenIndex++ ) - { - RawToken rawToken = tokens[ tokenIndex ] as RawToken; - Token precedentToken = ( tokenIndex > 0 ) ? tokens[ tokenIndex - 1 ] : null; - if( rawToken != null ) - { - FilterCriterionToken filterToken; - int startIndex; - int length; - - - if( FilterParser.ExtractFirstCriterion( precedentToken, rawToken, curParserPriority, out filterToken, out startIndex, out length ) ) - { - tokens.RemoveAt( tokenIndex ); - - if( startIndex > 0 ) - { - tokens.Insert( tokenIndex, new RawToken( rawToken.Value.Substring( 0, startIndex ) ) ); - tokenIndex++; - } - - tokens.Insert( tokenIndex, filterToken ); - tokenIndex++; - - if( startIndex + length < rawToken.Value.Length ) - tokens.Insert( tokenIndex, new RawToken( rawToken.Value.Substring( startIndex + length ) ) ); - - tokenAdded = true; - break; - } - } - } - } - while( tokenAdded ); - } - } - - //private static bool ExtractFirstCriterion( List rawTokens, int tokenIndex, int parserPriority, out FilterCriterionToken filterToken, out int startIndex, out int length ) - private static bool ExtractFirstCriterion( Token precedentToken, RawToken rawToken, int parserPriority, out FilterCriterionToken filterToken, out int startIndex, out int length ) - { - //RawToken rawToken = rawTokens[ tokenIndex ] as RawToken; - Type foundCriterionType = null; - filterToken = null; - startIndex = int.MaxValue; - length = 0; - - foreach( Type type in FilterParser.RegisteredFilterCriterionTypes ) - { - CriterionDescriptorAttribute attribute = ( CriterionDescriptorAttribute )type.GetCustomAttributes( typeof( CriterionDescriptorAttribute ), true )[ 0 ]; - - if( ( int )attribute.ParserPriority == parserPriority ) - { - if( !string.IsNullOrEmpty( attribute.Pattern ) ) - { - string separator = attribute.Pattern.Replace( "@", "" ); - int foundIndex = -1; - - if( attribute.Pattern.StartsWith( "@" ) ) - { - // The keyword can be anywhere in the token (there can be characters - // before the token). - foundIndex = rawToken.Value.IndexOf( separator ); - } - //else if( ( rawTokens[ tokenIndex + 1 ] as AtomicStringToken ) != null ) - //{ - - //} - else - { - // The keyword must be the first non whitespace character. - if( rawToken.Value.TrimStart( null ).StartsWith( separator ) ) - { - foundIndex = rawToken.Value.IndexOf( separator ); - } - } - - if( ( foundIndex >= 0 ) && - ( ( foundIndex < startIndex ) || - ( ( foundIndex == startIndex ) && ( separator.Length > length ) ) ) ) - { - if( type == typeof( EndsWithFilterCriterion ) && ( precedentToken as AtomicStringToken ) != null ) - foundCriterionType = typeof( StartsWithFilterCriterion ); - else - foundCriterionType = type; - startIndex = foundIndex; - length = separator.Length; - } - } - else - { - if( type != typeof( ContainsFilterCriterion ) ) - throw new DataGridInternalException( "Missing pattern in attribute: " + type.Name ); - } - } - } - - if( foundCriterionType != null ) - filterToken = new FilterCriterionToken( ( FilterCriterion )Activator.CreateInstance( foundCriterionType ) ); - - return ( filterToken != null ); - } - - private static FilterCriterion BuildCriterion( List tokens, Type dataType, Type defaultCriterionType, CultureInfo culture ) - { - FilterCriterion filterCriterion = null; - ReferenceList initializedCriteria = new ReferenceList(); - List precedences = new List(); - FilterParser.FillPrecedenceList( precedences ); - - for( int index = 0; index < precedences.Count; index++ ) - { - int curOperatorPrecedence = precedences[ index ]; - - foreach( Type type in FilterParser.RegisteredFilterCriterionTypes ) - { - CriterionDescriptorAttribute attribute = ( CriterionDescriptorAttribute )type.GetCustomAttributes( typeof( CriterionDescriptorAttribute ), true )[ 0 ]; - - if( ( int )attribute.OperatorPrecedence == curOperatorPrecedence ) - { - if( !string.IsNullOrEmpty( attribute.Pattern ) ) - { - bool tokenConsumed; - - do - { - tokenConsumed = false; - - for( int i = 0; i < tokens.Count; i++ ) - { - FilterCriterionToken filterToken = tokens[ i ] as FilterCriterionToken; - - if( ( filterToken != null ) && ( filterToken.FilterCriterion.GetType() == type ) && ( !initializedCriteria.Contains( filterToken.FilterCriterion ) ) ) - { - List parameters = new List(); - - if( attribute.Pattern.StartsWith( "@" ) ) - { - if( i <= 0 ) - throw new DataGridException( string.Format( FilterParser.MissingLeftOperandErrorText, type.Name ) ); - - if( tokens[ i - 1 ] is ValueToken ) - { - FilterParser.AddValueToParameters( parameters, ( ValueToken )tokens[ i - 1 ], dataType, culture ); - } - else - { - parameters.Add( ( ( FilterCriterionToken )tokens[ i - 1 ] ).FilterCriterion ); - } - - tokens.RemoveAt( i - 1 ); - i--; - } - - if( attribute.Pattern.EndsWith( "@" ) ) - { - if( i + 1 >= tokens.Count ) - throw new DataGridException( string.Format( FilterParser.MissingRightOperandErrorText, type.Name ) ); - - if( tokens[ i + 1 ] is ValueToken ) - { - FilterParser.AddValueToParameters( parameters, ( ValueToken )tokens[ i + 1 ], dataType, culture ); - } - else - { - parameters.Add( ( ( FilterCriterionToken )tokens[ i + 1 ] ).FilterCriterion ); - } - - tokens.RemoveAt( i + 1 ); - i--; - } - - filterToken.FilterCriterion.InitializeFrom( parameters.ToArray(), defaultCriterionType ); - initializedCriteria.Add( filterToken.FilterCriterion ); - tokenConsumed = true; - break; - } - } - } - while( tokenConsumed ); - } - else - { - if( type != typeof( ContainsFilterCriterion ) ) - throw new DataGridInternalException( "Missing pattern in attribute: " + type.Name ); - } - } - } - } - - if( ( tokens.Count == 1 ) && ( tokens[ 0 ] is FilterCriterionToken ) ) - { - filterCriterion = ( ( FilterCriterionToken )tokens[ 0 ] ).FilterCriterion; - } - else - { - throw new DataGridException( FilterParser.InvalidExpressionErrorText ); - } - - return filterCriterion; - } - - private static void AddValueToParameters( List parameters, ValueToken token, Type dataType, CultureInfo culture ) - { - if( token.Value == "NULL" ) - { - parameters.Add( null ); - } - else if( dataType == typeof( string ) ) - { - parameters.Add( token.Value ); - } - else if( dataType == typeof( Guid ) ) - { - System.ComponentModel.GuidConverter converter = new System.ComponentModel.GuidConverter(); - - parameters.Add( converter.ConvertFrom( token.Value ) ); - } - else if( ( dataType == typeof( byte ) ) - || ( dataType == typeof( short ) ) - || ( dataType == typeof( bool ) ) - || ( dataType == typeof( int ) ) - || ( dataType == typeof( long ) ) - || ( dataType == typeof( float ) ) - || ( dataType == typeof( double ) ) - || ( dataType == typeof( decimal ) ) - || ( dataType == typeof( sbyte ) ) - || ( dataType == typeof( ushort ) ) - || ( dataType == typeof( uint ) ) - || ( dataType == typeof( ulong ) ) ) - { - try - { - parameters.Add( Convert.ChangeType( token.Value, dataType, culture ) ); - } - catch( OverflowException ) - { - throw new DataGridException( FilterParser.NumberOverflowErrorText ); - } - catch( FormatException ) - { - throw new DataGridException( FilterParser.InvalidNumberFormatErrorText ); - } - } - else if( dataType == typeof( char ) ) - { - if( token.Value.Length == 1 ) - { - parameters.Add( token.Value[ 0 ] ); - } - else - { - throw new DataGridException( string.Format( FilterParser.InvalidCharValueErrorText, token.Value ) ); - } - } - else if( dataType == typeof( DateTime ) ) - { - DateTime dateTime; - - try - { - if( culture == null ) - { - dateTime = DateTime.Parse( token.Value ); - } - else - { - dateTime = DateTime.Parse( token.Value, culture ); - } - } - catch( FormatException ) - { - throw new DataGridException( string.Format( FilterParser.InvalidDateTimeValueErrorText, token.Value ) ); - } - - parameters.Add( dateTime ); - } - } - - private static CriterionTypeCollection RegisteredFilterCriterionTypes = new CriterionTypeCollection(); - private static string LastErrorString = null; - internal static string MissingClosingQuotesErrorText = "Missing closing quotes."; - internal static string MissingRightOperandErrorText = "Missing right operand for filter {0}."; - internal static string MissingLeftOperandErrorText = "Missing left operand for filter {0}."; - internal static string InvalidExpressionErrorText = "The expression cannot be resolved. Are you missing a logical operator?"; - internal static string InvalidCharValueErrorText = "{0} is not a valid character value."; - internal static string InvalidDateTimeValueErrorText = "Invalid date/time value. It is recommended to use the following format: yyyy-MM-ddTHH:mm:ss.fff."; - internal static string InvalidNumberFormatErrorText = "Invalid number format."; - internal static string InvalidEnumValueErrorText = "Invalid enum value."; - internal static string NumberOverflowErrorText = "Number value is out of range."; - - #region CriterionTypeCollection Nested Type - - private class CriterionTypeCollection : Collection - { - protected override void InsertItem( int index, Type item ) - { - if( !typeof( FilterCriterion ).IsAssignableFrom( item ) ) - throw new ArgumentException( "Must be derived from FilterCriterion.", "item" ); - - if( item.GetCustomAttributes( typeof( CriterionDescriptorAttribute ), false ).Length == 0 ) - throw new ArgumentException( "Must have the CriterionDescriptor attribute.", "item" ); - - base.InsertItem( index, item ); - } - - protected override void SetItem( int index, Type item ) - { - if( !typeof( FilterCriterion ).IsAssignableFrom( item ) ) - throw new ArgumentException( "Must be derived from FilterCriterion.", "item" ); - - if( item.GetCustomAttributes( typeof( CriterionDescriptorAttribute ), false ).Length == 0 ) - throw new ArgumentException( "Must have the CriterionDescriptor attribute.", "item" ); - - base.SetItem( index, item ); - } - } - - #endregion CriterionTypeCollection Nested Type - - #region Token Nested Type - - private abstract class Token - { - } - - #endregion Token Nested Type - - #region ValueToken Nested Type - - private abstract class ValueToken : Token - { - public ValueToken() - { - } - - public ValueToken( string value ) - { - this.Value = value; - } - - public string Value - { - get; - set; - } - } - - #endregion ValueToken Nested Type - - #region RawToken Nested Type - - /// - /// A token containing still unprocessed complete or partial expression or an actual - /// value that is not between "". - /// - private class RawToken : ValueToken - { - public RawToken() - { - } - - public RawToken( string value ) - : base( value ) - { - } - } - - #endregion RawToken Nested Type - - #region AtomicStringToken Nested Type - - /// - /// A token containing a value that will not be processed by the parser because it - /// was between "". - /// - private class AtomicStringToken : ValueToken - { - public AtomicStringToken() - { - } - - public AtomicStringToken( string value ) - : base( value ) - { - } - } - - #endregion AtomicStringToken Nested Type - - #region FilterCriterionToken Nested Type - - private class FilterCriterionToken : Token - { - public FilterCriterionToken() - { - } - - public FilterCriterionToken( FilterCriterion filterCriterion ) - { - this.FilterCriterion = filterCriterion; - } - - public FilterCriterion FilterCriterion - { - get; - set; - } - } - - #endregion FilterCriterionToken Nested Type - - #region ReferenceList Nested Type - - // This list will prevent the same object of being added twice. - // To compare objects (in IndexOf, Add, Remove and Contains), it will use the - // ReferenceEquals() method. - // Naturally, this class won't behave properly with ValueType because - // of boxing. - private class ReferenceList : ICollection - { - public int IndexOf( T item ) - { - int foundIndex = -1; - - for( int i = 0; i < m_internalList.Count; i++ ) - { - if( object.ReferenceEquals( item, m_internalList[ i ] ) ) - { - foundIndex = i; - break; - } - } - - return foundIndex; - } - - #region ICollection Members - - public void Add( T item ) - { - if( this.Contains( item ) ) - throw new InvalidOperationException( "An attempt was made to add an item that is already contained in the list." ); - - m_internalList.Add( item ); - } - - public void Clear() - { - m_internalList.Clear(); - } - - public bool Contains( T item ) - { - return ( this.IndexOf( item ) > -1 ); - } - - public void CopyTo( T[] array, int arrayIndex ) - { - m_internalList.CopyTo( array, arrayIndex ); - } - - public int Count - { - get - { - return m_internalList.Count; - } - } - - public bool IsReadOnly - { - get - { - return false; - } - } - - public bool Remove( T item ) - { - int index = this.IndexOf( item ); - - if( index > -1 ) - { - m_internalList.RemoveAt( index ); - } - - return ( index > -1 ); - } - - #endregion - - #region IEnumerable Members - - public IEnumerator GetEnumerator() - { - return m_internalList.GetEnumerator(); - } - - #endregion - - #region IEnumerable Members - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return m_internalList.GetEnumerator(); - } - - #endregion - - private List m_internalList = new List(); - } - - #endregion ReferenceList Nested Type - } -} diff --git a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterParserTestWindow.cs b/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterParserTestWindow.cs deleted file mode 100644 index e4116f0e..00000000 --- a/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/FilterParserTestWindow.cs +++ /dev/null @@ -1,306 +0,0 @@ -/************************************************************************************* - - Extended WPF Toolkit - - Copyright (C) 2007-2013 Xceed Software Inc. - - This program is provided to you under the terms of the Microsoft Public - License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license - - For more features, controls, and fast professional support, - pick up the Plus Edition at http://xceed.com/wpf_toolkit - - Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids - - ***********************************************************************************/ - -#if DEBUG - -using System; -using System.Globalization; -using System.IO; -using System.Threading; -using System.Windows; -using System.Windows.Markup; -using System.Windows.Controls; -using System.Xml; - -using Xceed.Wpf.DataGrid.FilterCriteria; - -namespace Xceed.Wpf.DataGrid -{ - public class FilterParserTestWindow : Window - { - public FilterParserTestWindow() - { - string mainGridXaml = -@" - - - - - - - - - - - - - -Here, you can test various expression that will be parsed. -The result of the parsing will be shown in the second TextBox. -Don't forget to check the Output Window for errors that could have occured during the -automated tests. Untested expressions by the automated tests should be added when found. - - - - - - - - - - - - - - - - - - - - - - - - - - - Invariant - fr-FR - en-US - - - - - - - - - - - - - - - -