# HG changeset patch # User Steven Hollidge # Date 1335175570 -3600 # Node ID a0bcd783e612d23106d759c1041ad4156c23a6c7 # Parent 81337ebf885a0025a7ec2089d1e8d21cb38086ea Latest work diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/FloatableWindow/FloatableWindow.cs --- a/SilverlightGlimpse/FloatableWindow/FloatableWindow.cs Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/FloatableWindow/FloatableWindow.cs Mon Apr 23 11:06:10 2012 +0100 @@ -25,7 +25,6 @@ [TemplatePart(Name = PART_ContentRoot, Type = typeof(FrameworkElement))] [TemplatePart(Name = PART_Overlay, Type = typeof(Panel))] [TemplatePart(Name = PART_Root, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_Resizer, Type = typeof(FrameworkElement))] [TemplateVisualState(Name = VSMSTATE_StateClosed, GroupName = VSMGROUP_Window)] [TemplateVisualState(Name = VSMSTATE_StateOpen, GroupName = VSMGROUP_Window)] public class FloatableWindow : ContentControl @@ -38,11 +37,6 @@ private const string PART_Chrome = "Chrome"; /// - /// The name of the Resizer template part. - /// - private const string PART_Resizer = "Resizer"; - - /// /// The name of the CloseButton template part. /// private const string PART_CloseButton = "CloseButton"; @@ -414,7 +408,6 @@ { this.DefaultStyleKey = typeof(FloatableWindow); this.InteractionState = WindowInteractionState.NotResponding; - this.ResizeMode = ResizeMode.CanResize; } #endregion Constructors @@ -437,10 +430,11 @@ #region Properties + private Panel _parentLayoutRoot; public Panel ParentLayoutRoot { - get; - set; + get { return _parentLayoutRoot; } + set { _parentLayoutRoot = value; } } /// @@ -572,12 +566,6 @@ private set; } - public ResizeMode ResizeMode - { - get; - set; - } - #endregion Properties #region Static Methods @@ -979,34 +967,6 @@ } /// - /// Executed when the ContentPresenter size changes. - /// - /// Content Presenter object. - /// SizeChanged event args. - private void ContentPresenter_SizeChanged(object sender, SizeChangedEventArgs e) - { - // timheuer: not sure really why this is here? - //if (this.ContentRoot != null && Application.Current != null && Application.Current.RootVisual != null && _isOpen) - //{ - // GeneralTransform gt = this.ContentRoot.TransformToVisual(Application.Current.RootVisual); - - // if (gt != null) - // { - // Point p = gt.Transform(new Point(0, 0)); - - // double x = this._windowPosition.X - p.X; - // double y = this._windowPosition.Y - p.Y; - // UpdateContentRootTransform(x, y); - // } - //} - - //RectangleGeometry rg = new RectangleGeometry(); - //rg.Rect = new Rect(0, 0, this._contentPresenter.ActualWidth, this._contentPresenter.ActualHeight); - //this._contentPresenter.Clip = rg; - //this.UpdatePosition(); - } - - /// /// Finds the X coordinate of a point that is defined by a line. /// /// Starting point of the line. @@ -1081,7 +1041,6 @@ } this._root = GetTemplateChild(PART_Root) as FrameworkElement; - this._resizer = GetTemplateChild(PART_Resizer) as FrameworkElement; if (this._root != null) { @@ -1118,19 +1077,6 @@ } //TODO: Figure out why I can't wire up the event below in SubscribeToTemplatePartEvents this._root.MouseLeftButtonDown += new MouseButtonEventHandler(this.ContentRoot_MouseLeftButtonDown); - - if (this.ResizeMode == ResizeMode.CanResize) - { - this._resizer.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(Resizer_MouseLeftButtonDown); - this._resizer.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(Resizer_MouseLeftButtonUp); - this._resizer.MouseMove += new System.Windows.Input.MouseEventHandler(Resizer_MouseMove); - this._resizer.MouseEnter += new MouseEventHandler(Resizer_MouseEnter); - this._resizer.MouseLeave += new MouseEventHandler(Resizer_MouseLeave); - } - else - { - this._resizer.Opacity = 0; - } } this.ContentRoot = GetTemplateChild(PART_ContentRoot) as FrameworkElement; @@ -1157,21 +1103,6 @@ } } - void Resizer_MouseLeave(object sender, MouseEventArgs e) - { - if (!this._isMouseCaptured) - { - this._resizer.Opacity = .25; - } - } - - void Resizer_MouseEnter(object sender, MouseEventArgs e) - { - if (!this._isMouseCaptured) - { - this._resizer.Opacity = 1; - } - } /// /// Raises the @@ -1453,10 +1384,6 @@ this._chrome.MouseMove += new MouseEventHandler(this.Chrome_MouseMove); } - if (this._contentPresenter != null) - { - this._contentPresenter.SizeChanged += new SizeChangedEventHandler(this.ContentPresenter_SizeChanged); - } } /// @@ -1494,11 +1421,6 @@ this._chrome.MouseLeftButtonUp -= new MouseButtonEventHandler(this.Chrome_MouseLeftButtonUp); this._chrome.MouseMove -= new MouseEventHandler(this.Chrome_MouseMove); } - - if (this._contentPresenter != null) - { - this._contentPresenter.SizeChanged -= new SizeChangedEventHandler(this.ContentPresenter_SizeChanged); - } } /// diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/FloatableWindow/FloatableWindow.csproj --- a/SilverlightGlimpse/FloatableWindow/FloatableWindow.csproj Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/FloatableWindow/FloatableWindow.csproj Mon Apr 23 11:06:10 2012 +0100 @@ -14,12 +14,13 @@ Properties FloatableWindow FloatableWindow - v3.0 + v5.0 false true true - true - FloatableWindowStrongNameKey.snk + false + + @@ -34,7 +35,7 @@ - 3.5 + 4.0 true @@ -72,10 +73,8 @@ - - @@ -83,15 +82,11 @@ MSBuild:MarkupCompilePass1 MSBuild:Compile Designer + MSBuild:Compile + Designer - - - - - - diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/FloatableWindow/FloatableWindowAutomationPeer.cs --- a/SilverlightGlimpse/FloatableWindow/FloatableWindowAutomationPeer.cs Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/FloatableWindow/FloatableWindowAutomationPeer.cs Mon Apr 23 11:06:10 2012 +0100 @@ -9,11 +9,6 @@ namespace System.Windows.Automation.Peers { - /// - /// Exposes types to UI - /// automation. - /// - /// Preview public class FloatableWindowAutomationPeer : FrameworkElementAutomationPeer, IWindowProvider, ITransformProvider { #region Data @@ -59,16 +54,6 @@ #endregion Properties - /// - /// Initializes a new instance of the - /// - /// class. - /// - /// - /// The to - /// associate with this - /// . - /// public FloatableWindowAutomationPeer(FloatableWindow owner) : base(owner) { diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/FloatableWindow/FloatableWindowStrongNameKey.snk Binary file SilverlightGlimpse/FloatableWindow/FloatableWindowStrongNameKey.snk has changed diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/FloatableWindow/GlobalSuppressions.cs --- a/SilverlightGlimpse/FloatableWindow/GlobalSuppressions.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -// This source is subject to the Microsoft Public License (Ms-PL). -// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. -using System.Diagnostics.CodeAnalysis; \ No newline at end of file diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/FloatableWindow/README.txt --- a/SilverlightGlimpse/FloatableWindow/README.txt Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -This is an adaptation of the ChildWindow control for Silverlight in the -Microsoft Silverlight SDK. The ChildWindow control is licensed under the -Ms-PL license, and as-such, FloatableWindow is also licensed under Ms-PL. - -This was build as a proof of concept and no warranties are provided, -implied or otherwise. The author who adapted this control is -Tim Heuer, who may be contacted at http://timheuer.com/blog/. \ No newline at end of file diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/FloatableWindow/ResizeMode.cs --- a/SilverlightGlimpse/FloatableWindow/ResizeMode.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -using System; - -namespace System.Windows -{ - public enum ResizeMode - { - NoResize = 0, - CanMinimize = 1, - CanResize = 2, - CanResizeWithGrip = 3, - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/FloatableWindow/themes/generic.xaml --- a/SilverlightGlimpse/FloatableWindow/themes/generic.xaml Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/FloatableWindow/themes/generic.xaml Mon Apr 23 11:06:10 2012 +0100 @@ -1,105 +1,64 @@ - + - - - - - - - - - - - - \ No newline at end of file diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Controllers/IResizableElement.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Controllers/IResizableElement.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -using System.Windows; -using System.Windows.Input; - -namespace SilverFlow.Controls.Controllers -{ - /// - /// This interface shall be implemented by an element to be resized. - /// - public interface IResizableElement - { - /// - /// Gets or sets the width of the element. - /// - /// The width. - double Width { get; set; } - - /// - /// Gets or sets the height of the element. - /// - /// The height. - double Height { get; set; } - - /// - /// Gets or sets minimal width of the element. - /// - /// Minimal width. - double MinWidth { get; set; } - - /// - /// Gets or sets minimal height of the element. - /// - /// Minimal height. - double MinHeight { get; set; } - - /// - /// Gets or sets maximal width of the element. - /// - /// Maximal width. - double MaxWidth { get; set; } - - /// - /// Gets or sets maximal height of the element. - /// - /// Maximal height. - double MaxHeight { get; set; } - - /// - /// Gets the actual width. - /// - /// The actual width. - double ActualWidth { get; } - - /// - /// Gets the actual height. - /// - /// The actual height. - double ActualHeight { get; } - - /// - /// Gets or sets the position of the element. - /// - /// The position. - Point Position { get; set; } - - /// - /// Gets the parent of the element. - /// - /// The parent object. - DependencyObject Parent { get; } - - /// - /// Gets or sets the cursor of the element. - /// - /// The cursor of the element. - Cursor Cursor { get; set; } - - /// - /// Snapin controller. - /// - ISnapinController SnapinController { get; } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Controllers/ISnapinController.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Controllers/ISnapinController.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -using System.Collections.Generic; -using System.Windows; - -namespace SilverFlow.Controls.Controllers -{ - public interface ISnapinController - { - /// - /// Gets or sets a value indicating whether snap in is enabled. - /// - /// true if snap in is enabled; otherwise, false. - bool SnapinEnabled { get; set; } - - /// - /// Gets or sets snap in bounds. - /// - /// Snap in bounds. - IEnumerable SnapinBounds { get; set; } - - /// - /// Gets or sets snap in distance. - /// - /// Snap in distance. - double SnapinDistance { get; set; } - - /// - /// Gets or sets a value snap in margin - distance between adjacent edges. - /// - /// Snap in margin. - double SnapinMargin { get; set; } - - /// - /// Returns new position of the specified rectangle - /// taking into account bounds the rectangle can be attracted to. - /// - /// The rectangle. - /// New position. - Point SnapRectangle(Rect rect); - - /// - /// Snaps the bottom right corner of the specified rectangle to the nearest bounds. - /// - /// The rectangle. - /// New position. - Point SnapBottomRightCorner(Rect rect); - - /// - /// Snaps the upper left corner of the specified rectangle to the nearest bounds. - /// - /// The rectangle. - /// New position. - Point SnapTopLeftCorner(Rect rect); - - /// - /// Snaps the lower left corner of the specified rectangle to the nearest bounds. - /// - /// The rectangle. - /// New position. - Point SnapBottomLeftCorner(Rect rect); - - /// - /// Snaps the upper right corner of the specified rectangle to the nearest bounds. - /// - /// The rectangle. - /// New position. - Point SnapTopRightCorner(Rect rect); - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Controllers/InertiaController.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Controllers/InertiaController.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Windows; -using System.Windows.Media.Animation; -using SilverFlow.Controls.Extensions; -using SilverFlow.Geometry; - -namespace SilverFlow.Controls.Controllers -{ - /// - /// Calculates inertial motion of a dragged element. - /// - public class InertiaController - { - private const double SCREEN_DPI = 96; - private const double INCH = 0.0254; - private const double GRAVITATIONAL_ACCELERATION = 9.81; - private const double COEFFICIENT_OF_SLIDING_FRICTION = 0.015; - private const double MIN_DELTA = 0.001; - private const double DELAY_BEFORE_MOUSE_UP_IN_MILLISECONDS = 100; - private const int MAX_LAST_POINTS_TO_COUNT = 4; - - private double pixelsPerMeter = SCREEN_DPI / INCH; - - private Queue mouseTrails = new Queue(); - - /// - /// An element starts its motion. - /// - /// The starting point of the motion. - public void StartMotion(Point point) - { - mouseTrails.Clear(); - mouseTrails.Enqueue(new Trail(point, DateTime.Now)); - } - - /// - /// Saves the last position of the moved element. - /// - /// Current position. - public void MoveToPoint(Point point) - { - while (mouseTrails.Count >= MAX_LAST_POINTS_TO_COUNT) - { - // Remove all points except the last ones - mouseTrails.Dequeue(); - } - - mouseTrails.Enqueue(new Trail(point, DateTime.Now)); - } - - /// - /// Gets inertial motion parameters: distance and duration. - /// - /// The host bounds. - /// The window bounds. - /// - /// The inertial motion parameters: distance and duration. - /// - public InertialMotion GetInertialMotionParameters(Rect hostBounds, Rect windowBounds) - { - if (mouseTrails.Count < 2) return null; - - var mouseTrailsArray = mouseTrails.ToArray(); - - Point startPosition = mouseTrailsArray[0].Position; - DateTime startTime = mouseTrailsArray[0].Timestamp; - Point endPosition = mouseTrailsArray[mouseTrails.Count - 1].Position; - DateTime endTime = mouseTrailsArray[mouseTrails.Count - 1].Timestamp; - - double timeBetweenNowAndLastMove = (DateTime.Now - endTime).TotalMilliseconds; - Vector2 vector = new Vector2(startPosition, endPosition); - - if (timeBetweenNowAndLastMove < DELAY_BEFORE_MOUSE_UP_IN_MILLISECONDS && !vector.IsZero) - { - double time = (endTime - startTime).TotalSeconds; - time = (time == 0) ? 0.001 : time; - - double distance = vector.Length / pixelsPerMeter; - - double intialVelocity = distance / time; - - double expectedDistance = ((intialVelocity * intialVelocity) / (2 * COEFFICIENT_OF_SLIDING_FRICTION * GRAVITATIONAL_ACCELERATION)); - double expectedTime = (2 * expectedDistance) / intialVelocity; - - double shiftX = Math.Round(vector.LengthX * expectedDistance / distance); - double shiftY = Math.Round(vector.LengthY * expectedDistance / distance); - - // New Inertial Motion Vector - Vector2 imVector = new Vector2(endPosition, shiftX, shiftY).Round(); - double expectedLength = imVector.Length; - - Rect bounds = hostBounds.Add(-windowBounds.Width, -windowBounds.Height); - - if (bounds.Contains(endPosition)) - { - imVector = EnsureEndPointInBounds(imVector, bounds).Round(); - } - else if (hostBounds.Contains(endPosition)) - { - imVector = EnsureEndPointInBounds(imVector, hostBounds).Round(); - } - - // Reduce expected time if the Inertial Motion Vector was truncated by the bounds - double realTime = (expectedLength == 0) ? 0 : (expectedTime * imVector.Length / expectedLength); - - var motion = new InertialMotion() - { - Seconds = realTime, - EndPosition = imVector.End, - EasingFunction = new CubicEase() - { - EasingMode = EasingMode.EaseOut - } - }; - - return motion; - } - - return null; - } - - /// - /// Ensures the end point is in bounds. - /// - /// The vector to check its ending point. - /// The bounds. - /// A vector with the ending point within specified bounds. - private Vector2 EnsureEndPointInBounds(Vector2 vector, Rect bounds) - { - if (!vector.IsZero && !bounds.Contains(vector.End)) - { - if (vector.IsVertical) - { - vector.End = vector.End.EnsureInVerticalBounds(bounds); - } - else if (vector.IsHorizontal) - { - vector.End = vector.End.EnsureInHorizontalBounds(bounds); - } - else - { - double k = (vector.LengthY) / (vector.LengthX); - Point point = vector.End; - - if (vector.End.X < bounds.Left || vector.End.X > bounds.Right) - { - point = point.EnsureInHorizontalBounds(bounds); - point.Y = (k * (point.X - vector.Start.X)) + vector.Start.Y; - } - - if (point.Y < bounds.Top || point.Y > bounds.Bottom) - { - point = point.EnsureInVerticalBounds(bounds); - point.X = ((point.Y - vector.Start.Y) / k) + vector.Start.X; - } - - vector.End = point.EnsureInBounds(bounds); - } - } - - return vector; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Controllers/InertialMotion.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Controllers/InertialMotion.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -using System.Windows; -using System.Windows.Media.Animation; - -namespace SilverFlow.Controls.Controllers -{ - /// - /// Represents a vector and duration of the inertial motion, calculated by the InertiaController. - /// - public class InertialMotion - { - /// - /// Gets or sets ending position of the displaced element. - /// - /// The ending position. - public Point EndPosition { get; set; } - - /// - /// Gets or sets duration of the inertial motion in seconds. - /// - /// Duration of the inertial motion in seconds. - public double Seconds { get; set; } - - /// - /// Gets or sets the Easing Function applied to the animation. - /// - /// The Easing Function. - public IEasingFunction EasingFunction { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public InertialMotion() - { - this.Seconds = 0; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Controllers/ResizeController.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Controllers/ResizeController.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,453 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Input; -using SilverFlow.Controls.Enums; -using SilverFlow.Controls.Extensions; - -namespace SilverFlow.Controls.Controllers -{ - /// - /// Calculates resizing element position and size. - /// - public class ResizeController - { - /// - /// Thickness of resizing area. - /// - private const double ResizingAreaDefaultValue = 6; - - /// - /// Minimal width of the resized window if MinWidth is set to 0. - /// - private const double MinResizedWidth = 20; - - /// - /// Resizing bounds, i.e. an area within which the resizing cursor can move. - /// - private Rect bounds; - - /// - /// Initial element size when resizing started. - /// - private Size initialSize; - - /// - /// Initial position of the element when resizing started. - /// - private Point initialPosition; - - /// - /// A corner or edge of the element used for resizing. - /// - private ResizeAnchor anchor; - - /// - /// An element implementing IResizableElement interface. - /// - private IResizableElement element; - - /// - /// Gets a framework element hosting resizing element. - /// - /// The host. - private FrameworkElement Host - { - get - { - return element.Parent as FrameworkElement; - } - } - - /// - /// Gets a value indicating whether the resizing can be started. - /// - /// - /// true if resizing can be started; otherwise, false. - /// - public bool CanResize - { - get - { - return anchor != ResizeAnchor.None; - } - } - - /// - /// Gets or sets the width of the resizing area. - /// - /// The width of the resizing area. Default value is 6. - public double ResizingArea { get; set; } - - /// - /// Gets a value indicating whether this instance can be resized horizontally. - /// - /// - /// true if this instance can be resized horizontally; otherwise, false. - /// - private bool CanResizeHorizontally - { - get - { - return !(element.MinWidth == element.MaxWidth && element.MinWidth != 0); - } - } - - /// - /// Gets a value indicating whether this instance can be resized vertically. - /// - /// - /// true if this instance can be resized vertically; otherwise, false. - /// - private bool CanResizeVertically - { - get - { - return !(element.MinHeight == element.MaxHeight && element.MinHeight != 0); - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The resizable element. - public ResizeController(IResizableElement resizableElement) - { - if (resizableElement == null) - throw new ArgumentNullException("resizableElement"); - - element = resizableElement; - anchor = ResizeAnchor.None; - ResizingArea = ResizingAreaDefaultValue; - } - - /// - /// Starts resizing of the element. - /// - public void StartResizing() - { - initialSize = new Size(element.ActualWidth, element.ActualHeight); - initialPosition = element.Position; - - CalculateBoundsForResizing(); - } - - /// - /// Resizes the element. - /// - /// Displacement by X-coordinate. - /// Displacement by Y-coordinate. - public void Resize(double dx, double dy) - { - switch (anchor) - { - case ResizeAnchor.BottomRight: - ResizeBottomRight(dx, dy); - break; - - case ResizeAnchor.Right: - ResizeBottomRight(dx, 0); - break; - - case ResizeAnchor.Bottom: - ResizeBottomRight(0, dy); - break; - - case ResizeAnchor.TopLeft: - ResizeTopLeft(dx, dy); - break; - - case ResizeAnchor.Top: - ResizeTopLeft(0, dy); - break; - - case ResizeAnchor.Left: - ResizeTopLeft(dx, 0); - break; - - case ResizeAnchor.BottomLeft: - ResizeBottomLeft(dx, dy); - break; - - case ResizeAnchor.TopRight: - ResizeTopRight(dx, dy); - break; - } - } - - /// - /// Determines resizing anchor and sets appropriate Cursor. - /// - /// Coordinates of the mouse pointer. - public void SetCursor(Point p) - { - if (p.Y < ResizingArea && p.X < ResizingArea) - { - anchor = ResizeAnchor.TopLeft; - element.Cursor = Cursors.SizeNWSE; - } - else if (p.Y < ResizingArea && p.X >= (element.ActualWidth - ResizingArea)) - { - anchor = ResizeAnchor.TopRight; - element.Cursor = Cursors.SizeNESW; - } - else if (p.Y < ResizingArea) - { - if (CanResizeVertically) - { - anchor = ResizeAnchor.Top; - element.Cursor = Cursors.SizeNS; - } - } - else if (p.X < ResizingArea && p.Y >= (element.ActualHeight - ResizingArea)) - { - anchor = ResizeAnchor.BottomLeft; - element.Cursor = Cursors.SizeNESW; - } - else if (p.X < ResizingArea) - { - if (CanResizeHorizontally) - { - anchor = ResizeAnchor.Left; - element.Cursor = Cursors.SizeWE; - } - } - else if (p.X >= (element.ActualWidth - ResizingArea) && p.Y >= (element.ActualHeight - ResizingArea)) - { - anchor = ResizeAnchor.BottomRight; - element.Cursor = Cursors.SizeNWSE; - } - else if (p.X >= (element.ActualWidth - ResizingArea)) - { - if (CanResizeHorizontally) - { - anchor = ResizeAnchor.Right; - element.Cursor = Cursors.SizeWE; - } - } - else if (p.Y >= (element.ActualHeight - ResizingArea)) - { - if (CanResizeVertically) - { - anchor = ResizeAnchor.Bottom; - element.Cursor = Cursors.SizeNS; - } - } - else - { - anchor = ResizeAnchor.None; - element.Cursor = null; - } - } - - /// - /// Calculates bounds for resizing. - /// - private void CalculateBoundsForResizing() - { - switch (anchor) - { - case ResizeAnchor.BottomRight: - case ResizeAnchor.Right: - case ResizeAnchor.Bottom: - bounds = GetBoundsForLowerRightCorner(); - break; - - case ResizeAnchor.TopLeft: - case ResizeAnchor.Top: - case ResizeAnchor.Left: - bounds = GetBoundsForUpperLeftCorner(); - break; - - case ResizeAnchor.BottomLeft: - bounds = GetBoundsForLowerLeftCorner(); - break; - - case ResizeAnchor.TopRight: - bounds = GetBoundsForUpperRightCorner(); - break; - } - } - - /// - /// Calculates bounds for resizing by the lower right corner. - /// - /// Bounding rectangle. - private Rect GetBoundsForLowerRightCorner() - { - double minWidth = (element.MinWidth != 0) ? element.MinWidth : MinResizedWidth; - double minHeight = element.MinHeight; - - double maxWidth = Host.ActualWidth - initialPosition.X; - - if (!element.MaxWidth.IsNotSet() && element.MaxWidth > 0) - maxWidth = Math.Min(maxWidth, element.MaxWidth); - - double maxHeight = Host.ActualHeight - initialPosition.Y; - if (!element.MaxHeight.IsNotSet() && element.MaxHeight > 0) - maxHeight = Math.Min(maxHeight, element.MaxHeight); - - Point p1 = initialPosition.Add(minWidth, minHeight); - Point p2 = initialPosition.Add(maxWidth, maxHeight); - - return new Rect(p1, p2); - } - - /// - /// Calculates bounds for resizing by the upper left corner. - /// - /// Bounding rectangle. - private Rect GetBoundsForUpperLeftCorner() - { - double minWidth = (element.MinWidth != 0) ? element.MinWidth : MinResizedWidth; - double minHeight = element.MinHeight; - - Point point = initialPosition.Add(initialSize); - double maxWidth = point.X; - double maxHeight = point.Y; - - if (!element.MaxWidth.IsNotSet() && element.MaxWidth > 0) - maxWidth = Math.Min(maxWidth, element.MaxWidth); - - if (!element.MaxHeight.IsNotSet() && element.MaxHeight > 0) - maxHeight = Math.Min(maxHeight, element.MaxHeight); - - Point p1 = point.Add(-maxWidth, -maxHeight); - Point p2 = point.Add(-minWidth, -minHeight); - - return new Rect(p1, p2); - } - - /// - /// Calculates bounds for resizing by the lower left corner. - /// - /// Bounding rectangle. - private Rect GetBoundsForLowerLeftCorner() - { - double minWidth = (element.MinWidth != 0) ? element.MinWidth : MinResizedWidth; - double minHeight = element.MinHeight; - - Point point = initialPosition.Add(initialSize.Width, 0); - double maxWidth = point.X; - - if (!element.MaxWidth.IsNotSet() && element.MaxWidth > 0) - maxWidth = Math.Min(maxWidth, element.MaxWidth); - - double maxHeight = Host.ActualHeight - initialPosition.Y; - if (!element.MaxHeight.IsNotSet() && element.MaxHeight > 0) - maxHeight = Math.Min(maxHeight, element.MaxHeight); - - Point p1 = point.Add(-maxWidth, minHeight); - Point p2 = point.Add(-minWidth, maxHeight); - - return new Rect(p1, p2); - } - - /// - /// Calculates bounds for resizing by the upper right corner. - /// - /// Bounding rectangle. - private Rect GetBoundsForUpperRightCorner() - { - double minWidth = (element.MinWidth != 0) ? element.MinWidth : MinResizedWidth; - double minHeight = element.MinHeight; - - Point point = initialPosition.Add(0, initialSize.Height); - double maxWidth = Host.ActualWidth - initialPosition.X; - - if (!element.MaxWidth.IsNotSet() && element.MaxWidth > 0) - maxWidth = Math.Min(maxWidth, element.MaxWidth); - - double maxHeight = point.Y; - if (!element.MaxHeight.IsNotSet() && element.MaxHeight > 0) - maxHeight = Math.Min(maxHeight, element.MaxHeight); - - Point p1 = point.Add(minWidth, -maxHeight); - Point p2 = point.Add(maxWidth, -minHeight); - - return new Rect(p1, p2); - } - - /// - /// Resizes the window by the bottom right corner of the window. - /// - /// Increment by X-coordinate. - /// Increment by Y-coordinate. - private void ResizeBottomRight(double dx, double dy) - { - Rect newBounds = new Rect(initialPosition, initialSize.Add(dx, dy)); - Point point = element.SnapinController.SnapBottomRightCorner(newBounds); - - // If only one coordinate was changed - restore the other after snap in - if (dx == 0) - point.X = newBounds.BottomRight().X; - - if (dy == 0) - point.Y = newBounds.BottomRight().Y; - - point = point.EnsureInBounds(bounds); - - element.Width = point.X - initialPosition.X; - element.Height = point.Y - initialPosition.Y; - } - - /// - /// Resizes the window by the top left corner of the window. - /// - /// Increment by X-coordinate. - /// Increment by Y-coordinate. - private void ResizeTopLeft(double dx, double dy) - { - Rect newBounds = new Rect(initialPosition.Add(dx, dy), initialSize); - Point point = element.SnapinController.SnapTopLeftCorner(newBounds).EnsureInBounds(bounds); - - // If only one coordinate was changed - restore the other after snap in - if (dx == 0) - point.X = newBounds.Position().X; - - if (dy == 0) - point.Y = newBounds.Position().Y; - - element.Position = point; - - Point lowerRight = initialPosition.Add(initialSize); - element.Width = lowerRight.X - point.X; - element.Height = lowerRight.Y - point.Y; - } - - /// - /// Resizes the window by the lower left corner of the window. - /// - /// Increment by X-coordinate. - /// Increment by Y-coordinate. - private void ResizeBottomLeft(double dx, double dy) - { - Rect newBounds = new Rect(initialPosition.Add(dx, 0), initialSize.Add(-dx, dy)); - - Point lowerLeft = element.SnapinController.SnapBottomLeftCorner(newBounds).EnsureInBounds(bounds); - Point topLeft = new Point(lowerLeft.X, initialPosition.Y); - - element.Position = topLeft; - - element.Width = initialSize.Width + initialPosition.X - topLeft.X; - element.Height = lowerLeft.Y - initialPosition.Y; - } - - /// - /// Resizes the window by the top right corner of the window. - /// - /// Increment by X-coordinate. - /// Increment by Y-coordinate. - private void ResizeTopRight(double dx, double dy) - { - Rect newBounds = new Rect(initialPosition.Add(0, dy), initialSize.Add(dx, -dy)); - - Point topRight = element.SnapinController.SnapTopRightCorner(newBounds).EnsureInBounds(bounds); - Point topLeft = new Point(initialPosition.X, topRight.Y); - - element.Position = topLeft; - - element.Width = topRight.X - initialPosition.X; - element.Height = initialSize.Height + initialPosition.Y - topRight.Y; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Controllers/SnapinController.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Controllers/SnapinController.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,333 +0,0 @@ -using System.Collections.Generic; -using System.Windows; -using SilverFlow.Controls.Extensions; -using SilverFlow.Geometry; - -namespace SilverFlow.Controls.Controllers -{ - /// - /// Provides helpers methods for calculating window position - /// during movement and resizing. - /// - public class SnapinController : ISnapinController - { - /// - /// Distance on which snapping works. - /// - private const double SnapinDistanceDefaultValue = 5; - - /// - /// Gets or sets a value indicating whether snap in is enabled. - /// - /// true if snap in is enabled; otherwise, false. - public bool SnapinEnabled { get; set; } - - /// - /// Gets or sets snap in bounds. - /// - /// Snap in bounds. - public IEnumerable SnapinBounds { get; set; } - - /// - /// Gets or sets snap in distance. - /// - /// Snap in distance. - public double SnapinDistance { get; set; } - - /// - /// Gets or sets a value snap in margin - distance between adjacent edges. - /// - /// Snap in margin. - public double SnapinMargin { get; set; } - - /// - /// Gets calculations accuracy. - /// - /// Accuracy. - private double Accuracy - { - get { return SnapinDistance + SnapinMargin; } - } - - /// - /// Returns new position of the specified rectangle - /// taking into account bounds the rectangle can be attracted to. - /// - /// The rectangle. - /// New position. - public Point SnapRectangle(Rect rect) - { - Point point = rect.Position(); - - if (SnapinEnabled) - { - Distance minDistance = new Distance(); - foreach (var bound in SnapinBounds) - { - Distance distance = DistanceBetweenRectangles(rect, bound); - minDistance = Distance.Min(distance, minDistance); - } - - point = point.Add(minDistance); - } - - return point; - } - - /// - /// Snaps the bottom right corner of the specified rectangle to the nearest bounds. - /// - /// The rectangle. - /// New position. - public Point SnapBottomRightCorner(Rect rect) - { - Point point = rect.BottomRight(); - - if (SnapinEnabled) - { - Distance minDistance = new Distance(); - foreach (var bound in SnapinBounds) - { - Distance distance = new Distance() - { - X = DistanceBetweenRightEdgeAndRectangle(rect, bound), - Y = DistanceBetweenBottomEdgeAndRectangle(rect, bound) - }; - - minDistance = Distance.Min(distance, minDistance); - } - - point = point.Add(minDistance); - } - - return point; - } - - /// - /// Snaps the upper left corner of the specified rectangle to the nearest bounds. - /// - /// The rectangle. - /// New position. - public Point SnapTopLeftCorner(Rect rect) - { - Point point = rect.Position(); - - if (SnapinEnabled) - { - Distance minDistance = new Distance(); - foreach (var bound in SnapinBounds) - { - Distance distance = new Distance() - { - X = DistanceBetweenLeftEdgeAndRectangle(rect, bound), - Y = DistanceBetweenTopEdgeAndRectangle(rect, bound) - }; - - minDistance = Distance.Min(distance, minDistance); - } - - point = point.Add(minDistance); - } - - return point; - } - - /// - /// Snaps the lower left corner of the specified rectangle to the nearest bounds. - /// - /// The rectangle. - /// New position. - public Point SnapBottomLeftCorner(Rect rect) - { - Point point = rect.BottomLeft(); - - if (SnapinEnabled) - { - Distance minDistance = new Distance(); - foreach (var bound in SnapinBounds) - { - Distance distance = new Distance() - { - X = DistanceBetweenLeftEdgeAndRectangle(rect, bound), - Y = DistanceBetweenBottomEdgeAndRectangle(rect, bound) - }; - - minDistance = Distance.Min(distance, minDistance); - } - - point = point.Add(minDistance); - } - - return point; - } - - /// - /// Snaps the upper right corner of the specified rectangle to the nearest bounds. - /// - /// The rectangle. - /// New position. - public Point SnapTopRightCorner(Rect rect) - { - Point point = rect.TopRight(); - - if (SnapinEnabled) - { - Distance minDistance = new Distance(); - foreach (var bound in SnapinBounds) - { - Distance distance = new Distance() - { - X = DistanceBetweenRightEdgeAndRectangle(rect, bound), - Y = DistanceBetweenTopEdgeAndRectangle(rect, bound) - }; - - minDistance = Distance.Min(distance, minDistance); - } - - point = point.Add(minDistance); - } - - return point; - } - - /// - /// Returns mininal distance between two rectangles. - /// - /// First rectangle. - /// Second rectangle. - /// Minimal distance. - private Distance DistanceBetweenRectangles(Rect first, Rect second) - { - double x1 = DistanceBetweenRightEdgeAndRectangle(first, second); - double x2 = DistanceBetweenLeftEdgeAndRectangle(first, second); - double y1 = DistanceBetweenBottomEdgeAndRectangle(first, second); - double y2 = DistanceBetweenTopEdgeAndRectangle(first, second); - - Distance distance = new Distance() - { - X = MathExtensions.AbsMin(x1, x2), - Y = MathExtensions.AbsMin(y1, y2) - }; - - return distance; - } - - /// - /// Returns distance between the right edge of the rectangle and another rectangle. - /// - /// First rectangle. - /// Second rectangle. - /// Minimal distance. - private double DistanceBetweenRightEdgeAndRectangle(Rect first, Rect second) - { - double snap; - double distance = double.NaN; - double x = first.X + first.Width - 1; - - if (first.OverlapsVertically(second, Accuracy)) - { - snap = second.X - 1 - SnapinMargin; - if (x.IsNear(snap, SnapinDistance)) - { - distance = MathExtensions.AbsMin(snap - x, distance); - } - - snap = second.X + second.Width - 1; - if (x.IsNear(snap, SnapinDistance)) - { - distance = MathExtensions.AbsMin(snap - x, distance); - } - } - - return distance; - } - - /// - /// Returns distance between the left edge of the rectangle and another rectangle. - /// - /// First rectangle. - /// Second rectangle. - /// Minimal distance. - private double DistanceBetweenLeftEdgeAndRectangle(Rect first, Rect second) - { - double snap; - double distance = double.NaN; - - if (first.OverlapsVertically(second, Accuracy)) - { - snap = second.X; - if (first.X.IsNear(snap, SnapinDistance)) - { - distance = MathExtensions.AbsMin(snap - first.X, distance); - } - - snap = second.X + second.Width + SnapinMargin; - if (first.X.IsNear(snap, SnapinDistance)) - { - distance = MathExtensions.AbsMin(snap - first.X, distance); - } - } - - return distance; - } - - /// - /// Returns distance between the bottom edge of the rectangle and another rectangle. - /// - /// First rectangle. - /// Second rectangle. - /// Minimal distance. - private double DistanceBetweenBottomEdgeAndRectangle(Rect first, Rect second) - { - double snap; - double distance = double.NaN; - double y = first.Y + first.Height - 1; - - if (first.OverlapsHorizontally(second, Accuracy)) - { - snap = second.Y - 1 - SnapinMargin; - if (y.IsNear(snap, SnapinDistance)) - { - distance = MathExtensions.AbsMin(snap - y, distance); - } - - snap = second.Y + second.Height - 1; - if (y.IsNear(snap, SnapinDistance)) - { - distance = MathExtensions.AbsMin(snap - y, distance); - } - } - - return distance; - } - - /// - /// Returns distance between the top edge of the rectangle and another rectangle. - /// - /// First rectangle. - /// Second rectangle. - /// Minimal distance. - private double DistanceBetweenTopEdgeAndRectangle(Rect first, Rect second) - { - double snap; - double distance = double.NaN; - - if (first.OverlapsHorizontally(second, Accuracy)) - { - snap = second.Y; - if (first.Y.IsNear(snap, SnapinDistance)) - { - distance = MathExtensions.AbsMin(snap - first.Y, distance); - } - - snap = second.Y + second.Height + SnapinMargin; - if (first.Y.IsNear(snap, SnapinDistance)) - { - distance = MathExtensions.AbsMin(snap - first.Y, distance); - } - } - - return distance; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Converters/BooleanToVisibilityConverter.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Converters/BooleanToVisibilityConverter.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Data; - -namespace SilverFlow.Controls.Converters -{ - public class BooleanToVisibilityConverter : IValueConverter - { - /// - /// Converts a boolean value to the display state of an element. - /// - /// The source data being passed to the target. - /// The of data expected by the target dependency property. - /// An optional parameter to be used in the converter logic. - /// The culture of the conversion. - /// - /// The value to be passed to the target dependency property. - /// - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value == null) - throw new ArgumentNullException("value"); - - return (bool)value ? Visibility.Visible : Visibility.Collapsed; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Enums/ResizeAnchor.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Enums/ResizeAnchor.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -namespace SilverFlow.Controls.Enums -{ - /// - /// Defines window's border or a corner where the user - /// clicked the mouse to start resizing. - /// - public enum ResizeAnchor - { - None = 0, - TopLeft = 1, - Top = 2, - TopRight = 3, - Right = 4, - BottomRight = 5, - Bottom = 6, - BottomLeft = 7, - Left = 9 - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Enums/WindowAction.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Enums/WindowAction.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -namespace SilverFlow.Controls.Enums -{ - /// - /// Defines mouse action. - /// - internal enum WindowAction - { - /// - /// Default - /// - None = 0, - - /// - /// Moving the window - /// - Move = 1, - - /// - /// Resizing the window - /// - Resize = 2 - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Extensions/AnimationExtensions.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Extensions/AnimationExtensions.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Media.Animation; - -namespace SilverFlow.Controls.Extensions -{ - /// - /// Useful Silverlight animation extensions - /// - public static class AnimationExtensions - { - /// - /// Animates specified property of the object. - /// - /// The target object to animate. - /// Property path, e.g. Canvas.Top. - /// Animation's starting value. - /// Animation's ending value. - /// Duration of the animation in milliseconds. - /// Easing function applied to the animation. - /// Event handler called when animation completed. - /// Returns started storyboard. - public static Storyboard AnimateDoubleProperty(this DependencyObject target, string propertyPath, double? from, double? to, double milliseconds, - IEasingFunction easingFunction = null, EventHandler completed = null) - { - Duration duration = new Duration(TimeSpan.FromMilliseconds(milliseconds)); - DoubleAnimation doubleAnimation = new DoubleAnimation() - { - From = from, - To = to, - Duration = duration, - EasingFunction = easingFunction - }; - - Storyboard storyboard = new Storyboard(); - storyboard.Duration = duration; - storyboard.Children.Add(doubleAnimation); - - Storyboard.SetTarget(doubleAnimation, target); - Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(propertyPath)); - - if (completed != null) - storyboard.Completed += completed; - - storyboard.Begin(); - - return storyboard; - } - - /// - /// Fade in the specified object. - /// - /// The target object. - /// Duration of the animation in milliseconds. - /// Event handler called when animation completed. - /// Returns started storyboard. - public static Storyboard FadeIn(this DependencyObject target, double milliseconds, EventHandler completed = null) - { - return AnimateDoubleProperty(target, "Opacity", 0, 1, milliseconds, null, completed); - } - - /// - /// Fade out the specified object. - /// - /// The target object. - /// Duration of the animation in milliseconds. - /// Event handler called when animation completed. - /// Returns started storyboard. - public static Storyboard FadeOut(this DependencyObject target, double milliseconds, EventHandler completed = null) - { - return AnimateDoubleProperty(target, "Opacity", 1, 0, milliseconds, null, completed); - } - - /// - /// Moves and resizes the object. - /// - /// The target object. - /// Ending position. - /// New width. - /// New height. - /// Duration of the animation in milliseconds. - /// Event handler called when animation completed. - public static void MoveAndResize(this DependencyObject target, Point position, double width, double height, - double milliseconds, EventHandler completed = null) - { - Duration duration = new Duration(TimeSpan.FromMilliseconds(milliseconds)); - DoubleAnimation doubleAnimation1 = new DoubleAnimation(); - DoubleAnimation doubleAnimation2 = new DoubleAnimation(); - PointAnimation pointAnimation = new PointAnimation(); - - doubleAnimation1.Duration = duration; - doubleAnimation2.Duration = duration; - pointAnimation.Duration = duration; - - Storyboard storyboard = new Storyboard(); - storyboard.Duration = duration; - - storyboard.Children.Add(doubleAnimation1); - storyboard.Children.Add(doubleAnimation2); - storyboard.Children.Add(pointAnimation); - - Storyboard.SetTarget(doubleAnimation1, target); - Storyboard.SetTarget(doubleAnimation2, target); - Storyboard.SetTarget(pointAnimation, target); - - Storyboard.SetTargetProperty(doubleAnimation1, new PropertyPath("(Width)")); - Storyboard.SetTargetProperty(doubleAnimation2, new PropertyPath("(Height)")); - Storyboard.SetTargetProperty(pointAnimation, new PropertyPath("(Position)")); - - doubleAnimation1.To = width; - if (!height.IsNotSet()) - doubleAnimation2.To = height; - - pointAnimation.To = position; - - if (completed != null) - storyboard.Completed += completed; - - storyboard.Begin(); - } - - /// - /// Animates the translate transform object, responsible for displacement of the target. - /// - /// The target object. - /// The storyboard. - /// Animation's ending value. - /// Duration of the animation in seconds. - /// Easing function applied to the animation. - public static void AnimateTranslateTransform(this DependencyObject target, Storyboard storyboard, Point to, - double seconds, IEasingFunction easingFunction = null) - { - Duration duration = new Duration(TimeSpan.FromSeconds(seconds)); - - DoubleAnimation doubleAnimationX = new DoubleAnimation() - { - To = to.X, - Duration = duration, - EasingFunction = easingFunction - }; - - DoubleAnimation doubleAnimationY = new DoubleAnimation() - { - To = to.Y, - Duration = duration, - EasingFunction = easingFunction - }; - - storyboard.Stop(); - storyboard.Children.Clear(); - storyboard.Duration = duration; - storyboard.Children.Add(doubleAnimationX); - storyboard.Children.Add(doubleAnimationY); - - Storyboard.SetTarget(doubleAnimationX, target); - Storyboard.SetTarget(doubleAnimationY, target); - Storyboard.SetTargetProperty(doubleAnimationX, (target as UIElement).GetPropertyPathForTranslateTransformX()); - Storyboard.SetTargetProperty(doubleAnimationY, (target as UIElement).GetPropertyPathForTranslateTransformY()); - - storyboard.Begin(); - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Extensions/ControlExtensions.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Extensions/ControlExtensions.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,230 +0,0 @@ -using System; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - -namespace SilverFlow.Controls.Extensions -{ - /// - /// Useful Silverlight controls extensions - /// - public static class ControlExtensions - { - /// - /// Sets the visible of the UIElement. - /// - /// The UI element. - /// Set Visible if true; otherwise - Collapsed. - public static void SetVisible(this UIElement uiElement, bool visible = true) - { - if (uiElement != null) - { - uiElement.Visibility = (visible) ? Visibility.Visible : Visibility.Collapsed; - } - } - - /// - /// Determines whether the specified UI element is visible. - /// - /// The UI element. - /// true if the specified UI element is visible; otherwise, false. - public static bool IsVisible(this UIElement uiElement) - { - return uiElement != null && uiElement.Visibility == Visibility.Visible; - } - - /// - /// Determines whether the specified element contains the point. - /// - /// This FrameworkElement. - /// The point to check. - /// Relative origin (optional). - /// true if the specified element contains the point; otherwise, false. - public static bool ContainsPoint(this FrameworkElement element, Point point, UIElement origin = null) - { - bool result = false; - - if (element != null) - { - Point elementOrigin = (origin == null) ? new Point(0, 0) : element.GetRelativePosition(origin); - Rect rect = new Rect(elementOrigin, new Size(element.ActualWidth, element.ActualHeight)); - result = rect.Contains(point); - } - - return result; - } - - /// - /// Gets position of the element relative to another specified (root) element. - /// - /// The element. - /// The root element. - /// Relative position. - /// Input parameter is null. - public static Point GetRelativePosition(this UIElement element, UIElement rootElement) - { - if (element == null) - throw new ArgumentNullException("element"); - - if (rootElement == null) - throw new ArgumentNullException("rootElement"); - - var transformFromClientToRoot = element.TransformToVisual(rootElement); - return transformFromClientToRoot.Transform(new Point(0, 0)); - } - - /// - /// Gets total horizontal value of the specified thickness. - /// - /// The thickness. - /// Horizontal thickness. - /// Input parameter is null. - public static double Horizontal(this Thickness thickness) - { - if (thickness == null) - throw new ArgumentNullException("thickness"); - - return thickness.Left + thickness.Right; - } - - /// - /// Gets total vertical value of the specified thickness. - /// - /// The thickness. - /// Vertical thickness. - /// Input parameter is null. - public static double Vertical(this Thickness thickness) - { - if (thickness == null) - throw new ArgumentNullException("thickness"); - - return thickness.Top + thickness.Bottom; - } - - /// - /// Gets the actual bounding rectangle of the FrameworkElement. - /// - /// The element. - /// Actual bounding rectangle. - public static Rect GetActualBoundingRectangle(this FrameworkElement element) - { - if (element == null) - throw new ArgumentNullException("element"); - - return new Rect(0, 0, element.ActualWidth, element.ActualHeight); - } - - /// - /// Gets a PropertyPath for the TranslateTransform.X property. - /// - /// The element. - /// A path to the property. - public static PropertyPath GetPropertyPathForTranslateTransformX(this UIElement element) - { - return element.GetPropertyPathForTranslateTransform("X"); - } - - /// - /// Gets a PropertyPath for the TranslateTransform.Y property. - /// - /// The element. - /// A path to the property. - public static PropertyPath GetPropertyPathForTranslateTransformY(this UIElement element) - { - return element.GetPropertyPathForTranslateTransform("Y"); - } - - /// - /// Gets scale factor to fit the element to the specified size. - /// - /// The element to scale. - /// Maximal width of the element. - /// Maximal height of the element. - /// Scale factor required to fit the element to the specified size. - public static double GetScaleFactorToFit(this FrameworkElement element, double maxWidth, double maxHeight) - { - if (element == null) - throw new ArgumentNullException("element"); - - double width = element.Width.IsNotSet() ? element.ActualWidth : element.Width; - double height = element.Height.IsNotSet() ? element.ActualHeight : element.Height; - - double scaleX = maxWidth / width; - double scaleY = maxHeight / height; - double minScale = Math.Min(scaleX, scaleY); - - return minScale; - } - - /// - /// Moves the element to the new container. The container can be a Panel or a Border derived class. - /// - /// The element. - /// The new container of the element. - /// New Container is null. - public static void MoveToContainer(this FrameworkElement element, FrameworkElement newContainer) - { - if (element == null) - throw new ArgumentNullException("element"); - - if (newContainer == null) - throw new ArgumentNullException("newContainer"); - - // Remove the element from the old container - element.RemoveFromContainer(); - - if (newContainer is Panel) - { - var container = newContainer as Panel; - if (!container.Children.Contains(element)) - container.Children.Add(element); - } - else if (newContainer is Border) - { - (newContainer as Border).Child = element; - } - } - - /// - /// Removes the element from its container. The container can be a Panel or a Border derived class. - /// - /// The element. - public static void RemoveFromContainer(this FrameworkElement element) - { - if (element != null && element.Parent != null) - { - // Remove the element from the old container - if (element.Parent is Panel) - { - (element.Parent as Panel).Children.Remove(element); - } - else if (element.Parent is Border) - { - (element.Parent as Border).Child = null; - } - } - } - - /// - /// Gets a PropertyPath for the TranslateTransform property. - /// - /// The element. - /// "X" or "Y" TranslateTransform property. - /// A path to the property. - private static PropertyPath GetPropertyPathForTranslateTransform(this UIElement element, string translateBy) - { - if (element == null) - throw new ArgumentNullException("element"); - - var transformGroup = element.RenderTransform as TransformGroup; - var translateTransform = transformGroup.Children.OfType().FirstOrDefault(); - int translateTransformIndex = transformGroup.Children.IndexOf(translateTransform); - - string path = string.Format("(FrameworkElement.RenderTransform).(TransformGroup.Children)[{0}].(TranslateTransform.{1})", - translateTransformIndex, translateBy); - - return new PropertyPath(path); - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Extensions/GeometryExtensions.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Extensions/GeometryExtensions.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,292 +0,0 @@ -using System; -using System.Windows; -using SilverFlow.Geometry; - -namespace SilverFlow.Controls.Extensions -{ - /// - /// Geometry extensions - /// - public static class GeometryExtensions - { - /// - /// Rounds the specified point to the nearest integer coordinates. - /// - /// The point to round coordinates. - /// New point with rounded coordinates. - public static Point Round(this Point point) - { - return new Point(Math.Round(point.X), Math.Round(point.Y)); - } - - /// - /// Ensures that coordinates are positive. - /// - /// The point. - /// Point with positive coordinates. - public static Point EnsurePositive(this Point point) - { - return new Point() - { - X = (point.X < 0) ? 0 : point.X, - Y = (point.Y < 0) ? 0 : point.Y - }; - } - - /// - /// Gets position of the specified rectangle. - /// - /// Rectangle. - /// Upper left corner of the rectangle. - public static Point Position(this Rect rect) - { - return new Point(rect.X, rect.Y); - } - - /// - /// Gets position the lower right corner of the rectangle. - /// - /// Rectangle. - /// Lower right corner of the rectangle. - public static Point BottomRight(this Rect rect) - { - return new Point(rect.Right, rect.Bottom); - } - - /// - /// Gets position the lower left corner of the rectangle. - /// - /// Rectangle. - /// Lower left corner of the rectangle. - public static Point BottomLeft(this Rect rect) - { - return new Point(rect.X, rect.Bottom); - } - - /// - /// Gets position the upper right corner of the rectangle. - /// - /// Rectangle. - /// Upper right corner of the rectangle. - public static Point TopRight(this Rect rect) - { - return new Point(rect.Right, rect.Y); - } - - /// - /// Ensures that coordinates of the point are in the specified bounds. - /// - /// The point. - /// The bounds. - /// Point within the boinds. - public static Point EnsureInBounds(this Point point, Rect bounds) - { - return new Point() - { - X = point.X.EnsureInRange(bounds.X, bounds.Right), - Y = point.Y.EnsureInRange(bounds.Y, bounds.Bottom) - }; - } - - /// - /// Ensures that the X-coordinate of the point is in the specified horizontal bounds. - /// - /// The point. - /// The bounds. - /// Point with the X-coordinate within the boinds. - public static Point EnsureInHorizontalBounds(this Point point, Rect bounds) - { - return new Point() - { - X = point.X.EnsureInRange(bounds.X, bounds.Right), - Y = point.Y - }; - } - - /// - /// Ensures that the Y-coordinate of the point is in the specified vertical bounds. - /// - /// The point. - /// The bounds. - /// Point with the Y-coordinate within the boinds. - public static Point EnsureInVerticalBounds(this Point point, Rect bounds) - { - return new Point() - { - X = point.X, - Y = point.Y.EnsureInRange(bounds.Y, bounds.Bottom) - }; - } - - /// - /// Determines whether coordinates of the point are Not a Number (NaN). - /// - /// The point. - /// - /// true if coordinates are not specified; otherwise, false. - /// - public static bool IsNotSet(this Point point) - { - return double.IsNaN(point.X) || double.IsNaN(point.Y); - } - - /// - /// Adds an offset to the specified point. - /// - /// The point. - /// Distance along X-coordinate. - /// Distance along Y-coordinate. - /// New point. - public static Point Add(this Point point, double x, double y) - { - return new Point(point.X + x, point.Y + y); - } - - /// - /// Adds an offset specified by the Size to the specified point. - /// - /// The point. - /// Distance to add. - /// New point - public static Point Add(this Point point, Size size) - { - return new Point(point.X + size.Width, point.Y + size.Height); - } - - /// - /// Determines whether dimensions are Not a Number (NaN). - /// - /// The size. - /// - /// true if dimensions are not specified; otherwise, false. - /// - public static bool IsNotSet(this Size size) - { - return double.IsNaN(size.Width) || double.IsNaN(size.Height); - } - - /// - /// Increments size to the specified values. - /// - /// The size. - /// Increment by X-coordinate. - /// Increment by Y-coordinate. - /// New size. - public static Size Add(this Size size, double x, double y) - { - double width = size.Width + x; - double height = size.Height + y; - - return new Size() - { - Width = width < 0 ? 0 : width, - Height = height < 0 ? 0 : height - }; - } - - /// - /// Increases size if the rectangle to the specified width and height. - /// - /// The rectangle. - /// Value to add to the width of the rectangle. - /// Value to add to the height of the rectangle. - /// New rectangle. - public static Rect Add(this Rect rect, double width, double height) - { - return new Rect - { - X = rect.X, - Y = rect.Y, - Width = Math.Max(0, rect.Width + width), - Height = Math.Max(0, rect.Height + height) - }; - } - - /// - /// Shifts the point to the specified distance. - /// - /// The point. - /// The distance. - /// Point shifted to the specified distance. - public static Point Add(this Point point, Distance distance) - { - return new Point() - { - X = distance.X.IsNotSet() ? point.X : point.X + distance.X, - Y = distance.Y.IsNotSet() ? point.Y : point.Y + distance.Y - }; - } - - /// - /// Tests whether the rectangle overlaps with another one vertically. - /// - /// The rectangle. - /// Test rectangle. - /// Accuracy. - /// true if overlaps vertically; otherwise, false. - public static bool OverlapsVertically(this Rect rect, Rect testRect, double accuracy = 0) - { - double y1 = rect.Y + rect.Height - 1; - double y2 = testRect.Y + testRect.Height - 1; - - if (rect.Y <= testRect.Y) - { - return y1 >= (testRect.Y - accuracy); - } - else if (rect.Y <= (y2 + accuracy)) - { - return true; - } - - return false; - } - - /// - /// Tests whether the rectangle overlaps with another one horizontally. - /// - /// The rectangle. - /// Test rectangle. - /// Accuracy. - /// true if overlaps horizontally; otherwise, false. - public static bool OverlapsHorizontally(this Rect rect, Rect testRect, double accuracy = 0) - { - double x1 = rect.X + rect.Width - 1; - double x2 = testRect.X + testRect.Width - 1; - - if (rect.X <= testRect.X) - { - return x1 >= (testRect.X - accuracy); - } - else if (rect.X <= (x2 + accuracy)) - { - return true; - } - - return false; - } - - /// - /// Tests whether the point overlaps with the rectangle vertically. - /// - /// Test point. - /// Test rectangle. - /// Accuracy. - /// true if overlaps vertically; otherwise, false. - public static bool OverlapsVertically(this Point point, Rect rect, double accuracy = 0) - { - return (point.Y >= (rect.Y - accuracy) && point.Y <= (rect.Y + rect.Height - 1 + accuracy)); - } - - /// - /// Tests whether the point overlaps with the rectangle horizontally. - /// - /// Test point. - /// Test rectangle. - /// Accuracy. - /// true if overlaps horizontally; otherwise, false. - public static bool OverlapsHorizontally(this Point point, Rect rect, double accuracy = 0) - { - return (point.X >= (rect.X - accuracy) && point.X <= (rect.X + rect.Width - 1 + accuracy)); - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Extensions/MathExtensions.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Extensions/MathExtensions.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -using System; - -namespace SilverFlow.Controls.Extensions -{ - /// - /// Math extensions - /// - public static class MathExtensions - { - /// - /// Determines whether the number is NaN. - /// - /// The number. - /// - /// true if is NaN; otherwise, false. - /// - public static bool IsNotSet(this double number) - { - return double.IsNaN(number); - } - - /// - /// Determines whether the specified number is near the test number. - /// - /// The number. - /// The test number. - /// Accuracy. - /// - /// true if the specified number is near the testing one; otherwise, false. - /// - public static bool IsNear(this double number, double testNumber, double accuracy) - { - return number >= (testNumber - accuracy) && number <= (testNumber + accuracy); - } - - /// - /// Compares two numbers without their signs and gets absolutely minimal value. - /// - /// First number. - /// Second number. - /// Absolutely minimal value. - public static double AbsMin(double num1, double num2) - { - if (num1.IsNotSet() && num2.IsNotSet()) - return double.NaN; - - if (num1.IsNotSet()) return num2; - if (num2.IsNotSet()) return num1; - - double abs1 = Math.Abs(num1); - double abs2 = Math.Abs(num2); - - if (abs1 < abs2) return num1; - if (abs2 < abs1) return num2; - - // Abs. values are equal. Return first number - return num1; - } - - /// - /// Ensures the given number is in the specified range. - /// - /// The number. - /// The lower limit. - /// The upper limit. - /// A number in the specified range. - public static double EnsureInRange(this double number, double low, double high) - { - if (number.IsNotSet()) return double.NaN; - - double result = Math.Max(number, low); - return Math.Min(result, high); - } - - /// - /// Returns a double value if it is not a NAN, or zero. - /// - /// The number. - /// Double value if it is not a NAN, or zero. - public static double ValueOrZero(this double number) - { - return double.IsNaN(number) ? 0 : number; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/ActiveWindowChangedEventArgs.cs --- a/SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/ActiveWindowChangedEventArgs.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -using System; - -namespace SilverFlow.Controls -{ - /// - /// ActiveWindowChanged event arguments class. - /// - public class ActiveWindowChangedEventArgs : EventArgs - { - public FloatingWindow Old { get; set; } - public FloatingWindow New { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public ActiveWindowChangedEventArgs() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The old active FloatingWindow. - /// The new active FloatingWindow. - public ActiveWindowChangedEventArgs(FloatingWindow oldWindow, FloatingWindow newWindow) - { - this.Old = oldWindow; - this.New = newWindow; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/BootstrapButton.cs --- a/SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/BootstrapButton.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -using System.Windows; -using System.Windows.Controls; - -namespace SilverFlow.Controls -{ - /// - /// Two-state button with an up/down arrow. - /// - [TemplateVisualState(Name = VSMSTATE_StateClose, GroupName = VSMGROUP_ButtonStates)] - [TemplateVisualState(Name = VSMSTATE_StateOpen, GroupName = VSMGROUP_ButtonStates)] - public class BootstrapButton : Button - { - // VSM groups - private const string VSMGROUP_ButtonStates = "ButtonStates"; - - // VSM states - private const string VSMSTATE_StateOpen = "Open"; - private const string VSMSTATE_StateClose = "Close"; - - #region public bool IsOpen - - /// - /// Gets or sets a value indicating whether the bootstrap button is in the "Open" state. - /// - /// true if the bootstrap button is in the "Open" state; otherwise, false. - public bool IsOpen - { - get { return (bool)GetValue(IsOpenProperty); } - set { SetValue(IsOpenProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty IsOpenProperty = - DependencyProperty.Register( - "IsOpen", - typeof(bool), - typeof(BootstrapButton), - new PropertyMetadata(false, IsOpenPropertyChanged)); - - /// - /// IsOpenProperty PropertyChangedCallback call back static function. - /// - /// BootstrapButton object whose IsOpenProperty property is changed. - /// DependencyPropertyChangedEventArgs which contains the old and new values. - private static void IsOpenPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - BootstrapButton button = (BootstrapButton)d; - VisualStateManager.GoToState( - button, - (bool)e.NewValue ? VSMSTATE_StateClose : VSMSTATE_StateOpen, - true); - } - - #endregion - - /// - /// Raises the event. - /// - protected override void OnClick() - { - // Toggle open/closed state - IsOpen = !IsOpen; - - base.OnClick(); - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/FloatingWindow.cs --- a/SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/FloatingWindow.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2210 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Animation; -using SilverFlow.Controls.Controllers; -using SilverFlow.Controls.Enums; -using SilverFlow.Controls.Extensions; -using SilverFlow.Controls.Helpers; - -namespace SilverFlow.Controls -{ - /// - /// Provides a window that can be displayed over a parent window not blocking - /// interaction with the parent window. - /// - [TemplatePart(Name = PART_Chrome, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_TitleContent, Type = typeof(ContentControl))] - [TemplatePart(Name = PART_CloseButton, Type = typeof(ButtonBase))] - [TemplatePart(Name = PART_ContentPresenter, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_ContentRoot, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_ContentBorder, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_Root, Type = typeof(FrameworkElement))] - [TemplateVisualState(Name = VSMSTATE_StateClosed, GroupName = VSMGROUP_Window)] - [TemplateVisualState(Name = VSMSTATE_StateOpen, GroupName = VSMGROUP_Window)] - [TemplateVisualState(Name = VSMSTATE_StateMinimized, GroupName = VSMGROUP_Window)] - [TemplateVisualState(Name = VSMSTATE_StateRestored, GroupName = VSMGROUP_Window)] - [TemplateVisualState(Name = VSMSTATE_StateNormal, GroupName = VSMGROUP_Button)] - [StyleTypedProperty(Property = PROPERTY_TitleStyle, StyleTargetType = typeof(ContentControl))] - [StyleTypedProperty(Property = PROPERTY_CloseButtonStyle, StyleTargetType = typeof(Button))] - [StyleTypedProperty(Property = PROPERTY_MinimizeButtonStyle, StyleTargetType = typeof(Button))] - [StyleTypedProperty(Property = PROPERTY_MaximizeButtonStyle, StyleTargetType = typeof(Button))] - [StyleTypedProperty(Property = PROPERTY_RestoreButtonStyle, StyleTargetType = typeof(Button))] - public class FloatingWindow : ContentControl, IResizableElement, IDisposable - { - #region Constants - - // Template parts - private const string PART_Chrome = "Chrome"; - private const string PART_TitleContent = "TitleContent"; - private const string PART_CloseButton = "CloseButton"; - private const string PART_MaximizeButton = "MaximizeButton"; - private const string PART_RestoreButton = "RestoreButton"; - private const string PART_MinimizeButton = "MinimizeButton"; - private const string PART_ContentPresenter = "ContentPresenter"; - private const string PART_ContentRoot = "ContentRoot"; - private const string PART_ContentBorder = "ContentBorder"; - private const string PART_Root = "Root"; - - // VSM groups - private const string VSMGROUP_Window = "WindowStates"; - private const string VSMGROUP_Button = "CommonStates"; - - // VSM states - private const string VSMSTATE_StateNormal = "Normal"; - private const string VSMSTATE_StateClosed = "Closed"; - private const string VSMSTATE_StateOpen = "Open"; - private const string VSMSTATE_StateMinimized = "Minimized"; - private const string VSMSTATE_StateRestored = "Restored"; - - // Style typed properties - private const string PROPERTY_TitleStyle = "TitleStyle"; - private const string PROPERTY_CloseButtonStyle = "CloseButtonStyle"; - private const string PROPERTY_MinimizeButtonStyle = "MinimizeButtonStyle"; - private const string PROPERTY_MaximizeButtonStyle = "MaximizeButtonStyle"; - private const string PROPERTY_RestoreButtonStyle = "RestoreButtonStyle"; - - // Thickness of resizing area - private const double ResizingAreaDefaultValue = 6; - - // Animation duration in milliseconds - private const double MaximizingDurationInMilliseconds = 20; - private const double MinimizingDurationInMilliseconds = 200; - private const double RestoringDurationInMilliseconds = 20; - - #endregion - - #region public bool ShowCloseButton - - /// - /// Gets or sets a value indicating whether to show Close button. - /// - /// true if to show Close button; otherwise, false. - public bool ShowCloseButton - { - get { return (bool)GetValue(ShowCloseButtonProperty); } - set { SetValue(ShowCloseButtonProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty ShowCloseButtonProperty = - DependencyProperty.Register( - "ShowCloseButton", - typeof(bool), - typeof(FloatingWindow), - new PropertyMetadata(true, OnShowCloseButtonPropertyChanged)); - - /// - /// ShowCloseButtonProperty PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose ShowCloseButton property is changed. - /// DependencyPropertyChangedEventArgs which contains the old and new values. - private static void OnShowCloseButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindow window = (FloatingWindow)d; - - if (window.closeButton != null) - window.closeButton.SetVisible((bool)e.NewValue); - } - - #endregion - - #region public bool ShowMaximizeButton - - /// - /// Gets or sets a value indicating whether to show Maximize button. - /// - /// true if to show Maximize button; otherwise, false. - public bool ShowMaximizeButton - { - get { return (bool)GetValue(ShowMaximizeButtonProperty); } - set { SetValue(ShowMaximizeButtonProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty ShowMaximizeButtonProperty = - DependencyProperty.Register( - "ShowMaximizeButton", - typeof(bool), - typeof(FloatingWindow), - new PropertyMetadata(true, ShowMaximizeButtonPropertyChanged)); - - /// - /// ShowMaximizeButtonProperty PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose ShowMaximizeButton property is changed. - /// DependencyPropertyChangedEventArgs which contains the old and new values. - private static void ShowMaximizeButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindow window = (FloatingWindow)d; - bool visible = window.IsModal ? false : (bool)e.NewValue; - - if (window.maximizeButton != null) - window.maximizeButton.SetVisible(visible); - } - - #endregion - - #region public bool ShowMinimizeButton - - /// - /// Gets or sets a value indicating whether to show Minimize button. - /// - /// true if to show Minimize button; otherwise, false. - public bool ShowMinimizeButton - { - get { return (bool)GetValue(ShowMinimizeButtonProperty); } - set { SetValue(ShowMinimizeButtonProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty ShowMinimizeButtonProperty = - DependencyProperty.Register( - "ShowMinimizeButton", - typeof(bool), - typeof(FloatingWindow), - new PropertyMetadata(true, ShowMinimizeButtonPropertyChanged)); - - /// - /// ShowMinimizeButtonProperty PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose ShowMinimizeButton property is changed. - /// DependencyPropertyChangedEventArgs which contains the old and new values. - private static void ShowMinimizeButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindow window = (FloatingWindow)d; - bool visible = window.IsModal ? false : (bool)e.NewValue; - - if (window.minimizeButton != null) - window.minimizeButton.SetVisible(visible); - } - - #endregion - - #region public bool ShowRestoreButton - - /// - /// Gets or sets a value indicating whether to show Restore button. - /// - /// true if to show Restore button; otherwise, false. - public bool ShowRestoreButton - { - get { return (bool)GetValue(ShowRestoreButtonProperty); } - set { SetValue(ShowRestoreButtonProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty ShowRestoreButtonProperty = - DependencyProperty.Register( - "ShowRestoreButton", - typeof(bool), - typeof(FloatingWindow), - new PropertyMetadata(true, ShowRestoreButtonPropertyChanged)); - - /// - /// ShowRestoreButtonProperty PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose ShowRestoreButton property is changed. - /// DependencyPropertyChangedEventArgs which contains the old and new values. - private static void ShowRestoreButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindow window = (FloatingWindow)d; - bool visible = window.IsModal ? false : (bool)e.NewValue; - - if (window.restoreButton != null) - window.restoreButton.SetVisible(visible); - } - - #endregion - - #region public object Title - - /// - /// Gets or sets title content that is displayed on the top of the window. - /// Can contain any UI elements - not only a text. - /// - /// - /// The title displayed at the top of the window. The default is null. - /// - public object Title - { - get { return GetValue(TitleProperty); } - set { SetValue(TitleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register( - "Title", - typeof(object), - typeof(FloatingWindow), - null); - - #endregion - - #region public object Icon - - /// - /// Gets or sets content that is displayed as an icon of the window on the iconbar. - /// - /// - /// The content displayed as an icon of the window on the iconbar. The default is null. - /// - public object Icon - { - get { return GetValue(IconProperty); } - set { SetValue(IconProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty IconProperty = - DependencyProperty.Register( - "Icon", - typeof(object), - typeof(FloatingWindow), - null); - - #endregion - - #region public string IconText - - /// - /// Gets or sets a text displayed on the icon of the minimized window. - /// - /// - /// The text displayed on the icon. - /// - public string IconText - { - get { return (string)GetValue(IconTextProperty); } - set { SetValue(IconTextProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty IconTextProperty = - DependencyProperty.Register( - "IconText", - typeof(string), - typeof(FloatingWindow), - null); - - #endregion - - #region public Brush TitleBackground - - /// - /// Gets or sets the title background. - /// - /// The title background. - public Brush TitleBackground - { - get { return (Brush)GetValue(TitleBackgroundProperty); } - set { SetValue(TitleBackgroundProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty TitleBackgroundProperty = - DependencyProperty.Register( - "TitleBackground", - typeof(Brush), - typeof(FloatingWindow), - new PropertyMetadata(new SolidColorBrush(Colors.Transparent), null)); - - #endregion - - #region public bool ResizeEnabled - - /// - /// Gets or sets a value indicating whether resizing is enabled. - /// - /// true if resizing is enabled; otherwise, false. - public bool ResizeEnabled - { - get { return (bool)GetValue(ResizeEnabledProperty); } - set { SetValue(ResizeEnabledProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty ResizeEnabledProperty = - DependencyProperty.Register( - "ResizeEnabled", - typeof(bool), - typeof(FloatingWindow), - new PropertyMetadata(true, null)); - - #endregion - - #region public double ResizingAreaThickness - - /// - /// Gets or sets the width of the resizing area. - /// - /// The width of the resizing area. - public double ResizingAreaThickness - { - get { return (double)GetValue(ResizingAreaThicknessProperty); } - set { SetValue(ResizingAreaThicknessProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty ResizingAreaThicknessProperty = - DependencyProperty.Register( - "ResizingAreaThickness", - typeof(double), - typeof(FloatingWindow), - new PropertyMetadata(ResizingAreaDefaultValue, OnResizingAreaThicknessPropertyChanged)); - - /// - /// ResizingAreaThicknessProperty PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose ResizingAreaThickness property is changed. - /// DependencyPropertyChangedEventArgs which contains the old and new values. - private static void OnResizingAreaThicknessPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindow window = (FloatingWindow)d; - window.resizeController.ResizingArea = (double)e.NewValue; - } - - #endregion - - #region public Point Position - - /// - /// Gets or sets current window position. - /// - /// Current position. - public Point Position - { - get { return (Point)GetValue(PositionProperty); } - set { SetValue(PositionProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty PositionProperty = - DependencyProperty.Register( - "Position", - typeof(Point), - typeof(FloatingWindow), - new PropertyMetadata(new Point(double.NaN, double.NaN), OnPositionPropertyChanged)); - - /// - /// PositionProperty PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose Position property is changed. - /// DependencyPropertyChangedEventArgs which contains the old and new values. - private static void OnPositionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindow window = (FloatingWindow)d; - - if (window != null) - { - if (window.FloatingWindowHost.IsLayoutUpdated) - window.MoveWindow((Point)e.NewValue); - } - } - - #endregion - - #region public bool ShowInIconbar - - /// - /// Gets or sets a value indicating whether to show minimized window in the iconbar. - /// - /// true if to show minimized window in the iconbar; otherwise, false. - public bool ShowInIconbar - { - get { return (bool)GetValue(ShowInIconbarProperty); } - set { SetValue(ShowInIconbarProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty ShowInIconbarProperty = - DependencyProperty.Register( - "ShowInIconbar", - typeof(bool), - typeof(FloatingWindow), - new PropertyMetadata(true, null)); - - #endregion - - #region public FlowDirection FlowDirection - - /// - /// Gets or sets the direction that title text flows within window's icon. - /// - /// A constant name from the FlowDirection enumeration, either LeftToRight or RightToLeft. - public FlowDirection FlowDirection - { - get { return (FlowDirection)GetValue(FlowDirectionProperty); } - set { SetValue(FlowDirectionProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty FlowDirectionProperty = - DependencyProperty.Register( - "FlowDirection", - typeof(FlowDirection), - typeof(FloatingWindow), - new PropertyMetadata(FlowDirection.LeftToRight, null)); - - #endregion - - #region public Style TitleStyle - - /// - /// Gets or sets the style that is used when rendering the Title of the window. - /// - public Style TitleStyle - { - get { return GetValue(TitleStyleProperty) as Style; } - set { SetValue(TitleStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty TitleStyleProperty = - DependencyProperty.Register( - "TitleStyle", - typeof(Style), - typeof(FloatingWindow), - new PropertyMetadata(OnTitleStylePropertyChanged)); - - /// - /// TitleStyle PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose TitleStyle property is changed. - /// The instance containing the event data. - private static void OnTitleStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindow window = (FloatingWindow)d; - if (window != null && window.titleContent != null) - { - Style style = e.NewValue as Style; - window.titleContent.Style = style; - } - } - - #endregion - - #region public Style CloseButtonStyle - - /// - /// Gets or sets the style of the Close button. - /// - public Style CloseButtonStyle - { - get { return GetValue(CloseButtonStyleProperty) as Style; } - set { SetValue(CloseButtonStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty CloseButtonStyleProperty = - DependencyProperty.Register( - "CloseButtonStyle", - typeof(Style), - typeof(FloatingWindow), - new PropertyMetadata(OnCloseButtonStylePropertyChanged)); - - /// - /// CloseButtonStyle PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose CloseButtonStyle property is changed. - /// The instance containing the event data. - private static void OnCloseButtonStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var window = (FloatingWindow)d; - if (window != null) - { - Style style = e.NewValue as Style; - window.CloseButtonStyle = style; - - if (window.closeButton != null) - window.closeButton.Style = style; - } - } - - #endregion - - #region public Style MinimizeButtonStyle - - /// - /// Gets or sets the style of the Minimize button. - /// - public Style MinimizeButtonStyle - { - get { return GetValue(MinimizeButtonStyleProperty) as Style; } - set { SetValue(MinimizeButtonStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty MinimizeButtonStyleProperty = - DependencyProperty.Register( - "MinimizeButtonStyle", - typeof(Style), - typeof(FloatingWindow), - new PropertyMetadata(OnMinimizeButtonStylePropertyChanged)); - - /// - /// CloseButtonStyle PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose MinimizeButtonStyle property is changed. - /// The instance containing the event data. - private static void OnMinimizeButtonStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var window = (FloatingWindow)d; - if (window != null) - { - Style style = e.NewValue as Style; - window.CloseButtonStyle = style; - - if (window.minimizeButton != null) - window.minimizeButton.Style = style; - } - } - - #endregion - - #region public Style MaximizeButtonStyle - - /// - /// Gets or sets the style of the Maximize button. - /// - public Style MaximizeButtonStyle - { - get { return GetValue(MaximizeButtonStyleProperty) as Style; } - set { SetValue(MaximizeButtonStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty MaximizeButtonStyleProperty = - DependencyProperty.Register( - "MaximizeButtonStyle", - typeof(Style), - typeof(FloatingWindow), - new PropertyMetadata(OnMaximizeButtonStylePropertyChanged)); - - /// - /// MaximizeButtonStyle PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose MaximizeButtonStyle property is changed. - /// The instance containing the event data. - private static void OnMaximizeButtonStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var window = (FloatingWindow)d; - if (window != null) - { - Style style = e.NewValue as Style; - window.CloseButtonStyle = style; - - if (window.maximizeButton != null) - window.maximizeButton.Style = style; - } - } - - #endregion - - #region public Style RestoreButtonStyle - - /// - /// Gets or sets the style of the Restore button. - /// - public Style RestoreButtonStyle - { - get { return GetValue(RestoreButtonStyleProperty) as Style; } - set { SetValue(RestoreButtonStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty RestoreButtonStyleProperty = - DependencyProperty.Register( - "RestoreButtonStyle", - typeof(Style), - typeof(FloatingWindow), - new PropertyMetadata(OnRestoreButtonStylePropertyChanged)); - - /// - /// RestoreButtonStyle PropertyChangedCallback call back static function. - /// - /// FloatingWindow object whose RestoreButtonStyle property is changed. - /// The instance containing the event data. - private static void OnRestoreButtonStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var window = (FloatingWindow)d; - if (window != null) - { - Style style = e.NewValue as Style; - window.CloseButtonStyle = style; - - if (window.restoreButton != null) - window.restoreButton.Style = style; - } - } - - #endregion - - #region public bool? DialogResult - - /// - /// Gets or sets a value that indicates whether the FloatingWindow was accepted or canceled. - /// - /// true if the FloatingWindow was accepted; false - if canceled. The default is null. - [TypeConverter(typeof(NullableBoolConverter))] - public bool? DialogResult { get; set; } - - #endregion - - #region Member Fields - - // Mouse click point - private Point clickPoint; - - // Window position when the mouse was clicked - private Point clickWindowPosition; - - // Window position, size and state when it was maximized or minimized - private Point previousPosition; - private Size previousSize; - private WindowState previousWindowState; - - private Thickness contentBorderThickness; - private CornerRadius contentBorderCornerRadius; - private CornerRadius chromeBorderCornerRadius; - - private Storyboard openingStoryboard; - private Storyboard closingStoryboard; - private Storyboard inertialMotionStoryboard; - - private FrameworkElement root; - private FrameworkElement contentPresenter; - private FrameworkElement contentRoot; - private FrameworkElement chrome; - private ContentControl titleContent; - private Border contentBorder; - - private ButtonBase closeButton; - private ButtonBase maximizeButton; - private ButtonBase restoreButton; - private ButtonBase minimizeButton; - - private bool isAppExit; - private bool isMouseCaptured; - - private ResizeController resizeController; - private ISnapinController snapinController; - private InertiaController inertiaController; - private ILocalStorage localStorage; - private IBitmapHelper bitmapHelper; - - // Current window state - private WindowState windowState = WindowState.Normal; - - // Specifies whether the window is moving or resizing - private WindowAction windowAction; - - // Bitmap containing thumbnail image - private ImageSource minimizedWindowThumbnail; - - #endregion Member Fields - - /// - /// Initializes a new instance of the class. - /// - public FloatingWindow() - { - DefaultStyleKey = typeof(FloatingWindow); - - resizeController = new ResizeController(this); - resizeController.ResizingArea = ResizingAreaThickness; - snapinController = new SnapinController(); - inertiaController = new InertiaController(); - localStorage = new LocalStorage(); - bitmapHelper = new BitmapHelper(); - - this.SetVisible(false); - } - - #region Events - - /// - /// Occurs when the is activated. - /// - /// Not visible cannot be the active. - public event EventHandler Activated; - - /// - /// Occurs when the is deactivated. - /// - public event EventHandler Deactivated; - - /// - /// Occurs when the is closed. - /// - public event EventHandler Closed; - - /// - /// Occurs when the is maximized. - /// - public event EventHandler Maximized; - - /// - /// Occurs when the is minimized. - /// - public event EventHandler Minimized; - - /// - /// Occurs when the is restored. - /// - public event EventHandler Restored; - - /// - /// Occurs when the is closing. - /// - public event EventHandler Closing; - - #endregion Events - - #region Properties - - /// - /// Gets or sets a reference to the FloatingWindowHost, containing the window. - /// - /// The floating window host. - public FloatingWindowHost FloatingWindowHost { get; set; } - - /// - /// Gets or sets a value indicating whether the window is always displayed in front of other windows. - /// - /// true if top most; otherwise, false. - public bool TopMost { get; set; } - - /// - /// Gets or sets a value indicating whether this window is open. - /// - /// true if this window is open; otherwise, false. - public bool IsOpen { get; private set; } - - /// - /// Gets or sets a value indicating whether this window is modal. - /// - /// true if this window is modal; otherwise, false. - public bool IsModal { get; private set; } - - /// - /// Gets the window thumbnail. - /// - /// The window thumbnail. - public ImageSource WindowThumbnail - { - get - { - return (windowState == WindowState.Minimized) ? minimizedWindowThumbnail : GetThumbnailImage(); - } - } - - /// - /// Gets the state of the window. - /// - /// Current state of the window. - public WindowState WindowState - { - get { return windowState; } - } - - /// - /// Gets or sets the minimum height constraint of a . - /// - /// he minimum height of the window. - /// The minimum height of the window, in pixels. The default is 0. - /// This value can be any value equal to or greater than 0. - /// However, is not valid. - public new double MinHeight - { - get - { - double minHeight = base.MinHeight; - - if ((base.MinHeight.IsNotSet() || base.MinHeight == 0) && - (chrome != null && contentRoot != null)) - { - // Set minimal height to the height of the chrome element of the window - minHeight = chrome.GetRelativePosition(contentRoot).Y + chrome.ActualHeight; - } - - return minHeight; - } - - set - { - base.MinHeight = value; - } - } - - /// - /// Gets a bounding rectangle of the window. - /// - /// Bounding rectangle. - public Rect BoundingRectangle - { - get { return new Rect(Position.X, Position.Y, ActualWidth, ActualHeight); } - } - - /// - /// Gets a Snapin controller. - /// - /// Snapin controller. - public ISnapinController SnapinController - { - get { return snapinController; } - } - - /// - /// Gets the host panel, containing the floating windows. - /// - /// The host panel. - public Panel HostPanel - { - get { return this.FloatingWindowHost == null ? null : this.FloatingWindowHost.HostPanel; } - } - - /// - /// Gets a value indicating whether window size is explicitly set. - /// - /// true if window size is set; otherwise, false. - private bool IsWindowSizeSet - { - get { return !Width.IsNotSet() && !Height.IsNotSet(); } - } - - /// - /// Gets a value indicating whether the window Tag property is set. - /// - /// true if the Tag set; otherwise, false. - private bool IsWindowTagSet - { - get - { - string tag = this.Tag as string; - return !string.IsNullOrWhiteSpace(tag); - } - } - - /// - /// Gets coordinates of the window placed in the center of its host. - /// - /// The centered window position. - private Point CenteredWindowPosition - { - get - { - return new Point((HostPanel.ActualWidth - Width.ValueOrZero()) / 2, (HostPanel.ActualHeight - Height.ValueOrZero()) / 2); - } - } - - #endregion Properties - - /// - /// Shows the window as a modal one. - /// - public void ShowModal() - { - IsModal = true; - Position = new Point(double.NaN, double.NaN); - ShowMaximizeButton = false; - ShowMinimizeButton = false; - - Show(); - } - - /// - /// Opens the in previously saved position or - /// in the center of the . - /// - public void Show() - { - Show(Position); - } - - /// - /// Shows the window in the specified coordinates, relative to the window's Host. - /// - /// X-coordinate. - /// Y-coordinate. - public void Show(double x, double y) - { - Show(new Point(x, y)); - } - - /// - /// Shows a at maximal size taking into account - /// specified margins and current size. - /// - /// Window margins. - public void Show(Thickness margins) - { - CheckHost(); - Action action = new Action(ShowWindow); - this.FloatingWindowHost.ShowWindow(action, margins); - } - - /// - /// Shows the window in the specified coordinates, relative to the window's Host. - /// - /// Coordinates of the upper-left corner of the window. - public void Show(Point point) - { - CheckHost(); - Action action = new Action(ShowWindow); - this.FloatingWindowHost.ShowWindow(action, point); - } - - /// - /// Shows a at maximal size taking into account - /// specified margins and current size. - /// - /// Window margins. - private void ShowWindow(Thickness margins) - { - Width = Math.Max(MinWidth, HostPanel.ActualWidth - margins.Horizontal()); - Height = Math.Max(MinHeight, HostPanel.ActualHeight - margins.Vertical()); - - ShowWindow(new Point(margins.Left, margins.Top)); - } - - /// - /// Shows the window in the specified coordinates, relative to the window's Host. - /// - /// Coordinates of the upper-left corner of the window. - /// "The FloatingWindow was not added to the host. - private void ShowWindow(Point point) - { - if (!IsOpen) - { - if (IsModal) - this.FloatingWindowHost.ShowWindowAsModal(this); - - SubscribeToEvents(); - SubscribeToTemplatePartEvents(); - SubscribeToStoryBoardEvents(); - - // Guarantee that the visual tree of an element is complete - ApplyTemplate(); - - // Brings current window to the front - SetTopmost(); - - Point position = point; - - if (point.IsNotSet()) - position = CenteredWindowPosition; - - MoveWindow(position); - this.SetVisible(true); - - if (!IsWindowSizeSet && point.IsNotSet()) - { - // If window size is not set explicitly we should wait - // when the window layout is updated and update its position - contentRoot.SizeChanged += new SizeChangedEventHandler(ContentRoot_SizeChanged); - } - - VisualStateManager.GoToState(this, VSMSTATE_StateOpen, true); - IsOpen = true; - } - else - { - MoveWindow(point); - this.SetVisible(true); - } - } - - /// - /// Handles the SizeChanged event of the ContentRoot control to update window position - /// only once when the window is opened. - /// - /// The source of the event. - /// The instance containing the event data. - private void ContentRoot_SizeChanged(object sender, SizeChangedEventArgs e) - { - contentRoot.SizeChanged -= new SizeChangedEventHandler(ContentRoot_SizeChanged); - double dx = -(e.NewSize.Width.ValueOrZero() - e.PreviousSize.Width.ValueOrZero()) / 2; - double dy = -(e.NewSize.Height.ValueOrZero() - e.PreviousSize.Height.ValueOrZero()) / 2; - Point point = Position.Add(dx, dy); - MoveWindow(point); - } - - /// - /// Restores window state, size and its position. - /// - public void RestoreWindow() - { - switch (windowState) - { - case WindowState.Minimized: - if (previousWindowState == WindowState.Maximized) - { - Width = HostPanel.ActualWidth; - Height = HostPanel.ActualHeight; - } - - SetTopmost(); - windowState = previousWindowState; - VisualStateManager.GoToState(this, VSMSTATE_StateRestored, true); - OnRestored(EventArgs.Empty); - break; - - case WindowState.Normal: - SetTopmost(); - EnsureVisible(); - break; - - case WindowState.Maximized: - SetTopmost(); - break; - } - - Focus(); - } - - /// - /// Makes the window topmost and tries to set focus on it. - /// - public void Activate() - { - SetTopmost(); - } - - /// - /// Brings current window to the front. - /// - private void SetTopmost() - { - if (this.FloatingWindowHost != null) - this.FloatingWindowHost.SetTopmostWindow(this); - } - - /// - /// Ensures the window is visible. - /// - private void EnsureVisible() - { - if (HostPanel != null && (Position.X >= HostPanel.ActualWidth || Position.Y >= HostPanel.ActualHeight)) - { - Position = CenteredWindowPosition; - } - } - - /// - /// Executed when the application is exited. - /// - /// The sender. - /// Event args. - private void Application_Exit(object sender, EventArgs e) - { - if (IsOpen) - { - isAppExit = true; - try - { - Close(); - } - finally - { - isAppExit = false; - } - } - } - - /// - /// Closes a . - /// - public void Close() - { - SaveSizeAndPosition(); - - CancelEventArgs e = new CancelEventArgs(); - OnClosing(e); - - // On ApplicationExit, Close() cannot be cancelled - if (IsOpen && (!e.Cancel || isAppExit)) - { - IsOpen = false; - - if (IsModal) - this.FloatingWindowHost.RemoveOverlay(); - - if (closingStoryboard != null) - { - VisualStateManager.GoToState(this, VSMSTATE_StateClosed, true); - } - else - { - this.Visibility = Visibility.Collapsed; - OnClosed(EventArgs.Empty); - } - - UnSubscribeFromEvents(); - UnsubscribeFromTemplatePartEvents(); - } - } - - /// - /// Restores the size and position stored in the IsolatedStorage on closing. - /// - public void RestoreSizeAndPosition() - { - if (IsWindowTagSet) - { - string positionKey = GetAppSettingsKey("Position"); - string sizeKey = GetAppSettingsKey("Size"); - - if (localStorage.Contains(positionKey)) - Position = (Point)localStorage[positionKey]; - - if (localStorage.Contains(sizeKey)) - { - Size size = (Size)localStorage[sizeKey]; - Width = size.Width == 0 ? double.NaN : size.Width; - Height = size.Height == 0 ? double.NaN : size.Height; - } - } - } - - /// - /// Executed when the Close button is clicked. - /// - /// Sender object. - /// Routed event args. - private void CloseButton_Click(object sender, RoutedEventArgs e) - { - Close(); - } - - /// - /// Executed when the Closing storyboard ends. - /// - /// Sender object. - /// Event args. - private void Closing_Completed(object sender, EventArgs e) - { - if (closingStoryboard != null) - closingStoryboard.Completed -= new EventHandler(Closing_Completed); - - this.Visibility = Visibility.Collapsed; - OnClosed(EventArgs.Empty); - } - - /// - /// Builds the visual tree for the control - /// when a new template is applied. - /// - public override void OnApplyTemplate() - { - UnsubscribeFromTemplatePartEvents(); - UnsubscribeFromStoryBoardEvents(); - - base.OnApplyTemplate(); - - root = GetTemplateChild(PART_Root) as FrameworkElement; - contentRoot = GetTemplateChild(PART_ContentRoot) as FrameworkElement; - contentBorder = GetTemplateChild(PART_ContentBorder) as Border; - chrome = GetTemplateChild(PART_Chrome) as FrameworkElement; - titleContent = GetTemplateChild(PART_TitleContent) as ContentControl; - contentPresenter = GetTemplateChild(PART_ContentPresenter) as FrameworkElement; - closeButton = GetTemplateChild(PART_CloseButton) as ButtonBase; - maximizeButton = GetTemplateChild(PART_MaximizeButton) as ButtonBase; - minimizeButton = GetTemplateChild(PART_MinimizeButton) as ButtonBase; - restoreButton = GetTemplateChild(PART_RestoreButton) as ButtonBase; - - if (root == null) - throw new NotImplementedException("Template Part PART_Root is required to display FloatingWindow."); - - if (contentRoot == null) - throw new NotImplementedException("Template Part PART_ContentRoot is required to display FloatingWindow."); - - if (contentPresenter == null) - throw new NotImplementedException("Template Part PART_ContentPresenter is required to display FloatingWindow."); - - SetStyles(); - GetStoryboards(); - SetInitialRootPosition(); - InitializeContentRootTransformGroup(); - - if (closeButton != null) - closeButton.SetVisible(ShowCloseButton); - - if (minimizeButton != null) - minimizeButton.SetVisible(ShowMinimizeButton); - - if (maximizeButton != null) - maximizeButton.SetVisible(ShowMaximizeButton); - - SubscribeToTemplatePartEvents(); - SubscribeToStoryBoardEvents(); - } - - /// - /// Sets styles that are applied for different template parts. - /// - private void SetStyles() - { - if (titleContent != null && this.TitleStyle != null) - titleContent.Style = this.TitleStyle; - - if (minimizeButton != null && this.MinimizeButtonStyle != null) - minimizeButton.Style = this.MinimizeButtonStyle; - - if (maximizeButton != null && this.MaximizeButtonStyle != null) - maximizeButton.Style = this.MaximizeButtonStyle; - - if (restoreButton != null && this.RestoreButtonStyle != null) - restoreButton.Style = this.RestoreButtonStyle; - - if (closeButton != null && this.CloseButtonStyle != null) - closeButton.Style = this.CloseButtonStyle; - } - - /// - /// Gets the storyboards defined in the style. - /// - private void GetStoryboards() - { - if (root != null) - { - var groups = VisualStateManager.GetVisualStateGroups(root) as Collection; - if (groups != null) - { - var states = (from stategroup in groups - where stategroup.Name == FloatingWindow.VSMGROUP_Window - select stategroup.States).FirstOrDefault() as Collection; - - if (states != null) - { - closingStoryboard = (from state in states - where state.Name == FloatingWindow.VSMSTATE_StateClosed - select state.Storyboard).FirstOrDefault(); - - openingStoryboard = (from state in states - where state.Name == FloatingWindow.VSMSTATE_StateOpen - select state.Storyboard).FirstOrDefault(); - } - } - - if (inertialMotionStoryboard == null) - inertialMotionStoryboard = new Storyboard(); - } - } - - /// - /// Shift the root of the window to compensate its margins. - /// - private void SetInitialRootPosition() - { - double x = Math.Round(-this.Margin.Left); - double y = Math.Round(-this.Margin.Top); - - var transformGroup = root.RenderTransform as TransformGroup; - if (transformGroup == null) - { - transformGroup = new TransformGroup(); - transformGroup.Children.Add(root.RenderTransform); - root.RenderTransform = transformGroup; - } - - var translateTransform = transformGroup.Children.OfType().FirstOrDefault(); - if (translateTransform == null) - { - transformGroup.Children.Add(new TranslateTransform() { X = x, Y = y }); - } - else - { - translateTransform.X = x; - translateTransform.Y = y; - } - } - - /// - /// Checks the TransformGroup of the content root or creates it if necesary. - /// - private void InitializeContentRootTransformGroup() - { - var transformGroup = contentRoot.RenderTransform as TransformGroup; - if (transformGroup == null) - { - transformGroup = new TransformGroup(); - transformGroup.Children.Add(contentRoot.RenderTransform); - contentRoot.RenderTransform = transformGroup; - } - - // Check that ScaleTransform exists in the TransformGroup - // ScaleTransform is used as a target in Storyboards - var scaleTransform = transformGroup.Children.OfType().FirstOrDefault(); - - if (scaleTransform == null) - transformGroup.Children.Insert(0, new ScaleTransform()); - - var translateTransform = transformGroup.Children.OfType().FirstOrDefault(); - - if (translateTransform == null) - transformGroup.Children.Add(new TranslateTransform()); - } - - /// - /// Raises the event. - /// - /// The event data. - protected virtual void OnActivated(EventArgs e) - { - EventHandler handler = Activated; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// The event data. - protected virtual void OnDeactivated(EventArgs e) - { - EventHandler handler = Deactivated; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// The event data. - protected virtual void OnClosed(EventArgs e) - { - this.FloatingWindowHost.Remove(this); - this.FloatingWindowHost.ActivateTopmostWindow(); - UnsubscribeFromStoryBoardEvents(); - - EventHandler handler = Closed; - if (handler != null) - { - handler(this, e); - } - - Dispose(); - } - - /// - /// Raises the event. - /// - /// The event data. - protected virtual void OnClosing(CancelEventArgs e) - { - EventHandler handler = Closing; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// The event data. - protected virtual void OnMaximized(EventArgs e) - { - EventHandler handler = Maximized; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// The event data. - protected virtual void OnMinimized(EventArgs e) - { - EventHandler handler = Minimized; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// The event data. - protected virtual void OnRestored(EventArgs e) - { - EventHandler handler = Restored; - if (handler != null) - { - handler(this, e); - } - } - - /// - /// This method is called every time a is displayed. - /// - protected virtual void OnOpened() - { - if (!Focus()) - { - // If the Focus() fails it means there is no focusable element in the window. - // In this case we set IsTabStop to true to have the keyboard functionality - IsTabStop = true; - Focus(); - } - } - - /// - /// Executed when the opening storyboard finishes. - /// - /// Sender object. - /// Event args. - private void Opening_Completed(object sender, EventArgs e) - { - if (openingStoryboard != null) - openingStoryboard.Completed -= new EventHandler(Opening_Completed); - - this.FloatingWindowHost.UpdateIconBar(); - IsOpen = true; - OnOpened(); - } - - /// - /// Subscribes to events when the window is opened. - /// - private void SubscribeToEvents() - { - if (Application.Current != null) - Application.Current.Exit += new EventHandler(Application_Exit); - - if (this.FloatingWindowHost != null) - { - this.FloatingWindowHost.SizeChanged += new SizeChangedEventHandler(Host_SizeChanged); - this.FloatingWindowHost.ActiveWindowChanged += new EventHandler(ActiveWindowChanged); - } - - // Attach Mouse event handler to catch already handled events to bring the window to the front - this.AddHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(FloatingWindow_MouseLeftButtonDown), true); - } - - /// - /// Handles the MouseLeftButtonDown event to bring the window to the front. - /// - /// The source of the event. - /// The instance containing the event data. - private void FloatingWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - // Gets the element with keyboard focus - Control elementWithFocus = FocusManager.GetFocusedElement() as Control; - - // Brings current window to the front - SetTopmost(); - - if (elementWithFocus != null) - { - if (IsControlInVisualTree(elementWithFocus)) - { - elementWithFocus.Focus(); - } - else - { - // Try to set focus on the window - Focus(); - } - } - - // Stop any inertial motion - StopInertialMotion(); - } - - /// - /// Determines whether the control is in the visual tree of the window. - /// - /// The control to test. - /// - /// true if the control is in the visual tree; otherwise, false. - /// - private bool IsControlInVisualTree(Control control) - { - if (control != null) - { - DependencyObject parent = control; - do - { - parent = VisualTreeHelper.GetParent(parent); - FloatingWindow window = parent as FloatingWindow; - - if (window != null && window == this) - return true; - } - while (parent != null); - } - - return false; - } - - /// - /// Unsubscribe from events when the ChildWindow is closed. - /// - private void UnSubscribeFromEvents() - { - if (Application.Current != null) - Application.Current.Exit -= new EventHandler(Application_Exit); - - if (this.FloatingWindowHost != null) - { - this.FloatingWindowHost.SizeChanged -= new SizeChangedEventHandler(Host_SizeChanged); - this.FloatingWindowHost.ActiveWindowChanged -= new EventHandler(ActiveWindowChanged); - } - - this.RemoveHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(FloatingWindow_MouseLeftButtonDown)); - } - - /// - /// Subscribes to the events on the storyboards. - /// - private void SubscribeToStoryBoardEvents() - { - if (closingStoryboard != null) - closingStoryboard.Completed += new EventHandler(Closing_Completed); - - if (openingStoryboard != null) - openingStoryboard.Completed += new EventHandler(Opening_Completed); - - if (inertialMotionStoryboard != null) - inertialMotionStoryboard.Completed += new EventHandler(InertialMotion_Completed); - } - - /// - /// Unsubscribe from events that are subscribed on the storyboards. - /// - private void UnsubscribeFromStoryBoardEvents() - { - if (closingStoryboard != null) - closingStoryboard.Completed -= new EventHandler(Closing_Completed); - - if (openingStoryboard != null) - openingStoryboard.Completed -= new EventHandler(Opening_Completed); - - if (inertialMotionStoryboard != null) - inertialMotionStoryboard.Completed -= new EventHandler(InertialMotion_Completed); - } - - /// - /// Subscribes to the events on the template parts. - /// - private void SubscribeToTemplatePartEvents() - { - if (closeButton != null) - closeButton.Click += new RoutedEventHandler(CloseButton_Click); - - if (maximizeButton != null) - maximizeButton.Click += new RoutedEventHandler(MaximizeButton_Click); - - if (restoreButton != null) - restoreButton.Click += new RoutedEventHandler(RestoreButton_Click); - - if (minimizeButton != null) - minimizeButton.Click += new RoutedEventHandler(MinimizeButton_Click); - } - - /// - /// Unsubscribe from the events that are subscribed on the template part elements. - /// - private void UnsubscribeFromTemplatePartEvents() - { - if (closeButton != null) - closeButton.Click -= new RoutedEventHandler(CloseButton_Click); - - if (maximizeButton != null) - maximizeButton.Click -= new RoutedEventHandler(MaximizeButton_Click); - - if (restoreButton != null) - restoreButton.Click -= new RoutedEventHandler(RestoreButton_Click); - - if (minimizeButton != null) - minimizeButton.Click -= new RoutedEventHandler(MinimizeButton_Click); - } - - /// - /// Handles the ActiveWindowChanged event of the Host control. - /// - /// The sender. - /// The instance containing the event data. - private void ActiveWindowChanged(object sender, ActiveWindowChangedEventArgs e) - { - if (e.Old == this) - OnDeactivated(EventArgs.Empty); - - if (e.New == this) - OnActivated(EventArgs.Empty); - } - - /// - /// Handles the Click event of the MaximizeButton control. - /// - /// The source of the event. - /// The instance containing the event data. - private void MaximizeButton_Click(object sender, RoutedEventArgs e) - { - MaximizeWindow(); - } - - /// - /// Handles the Click event of the RestoreButton control. - /// - /// The source of the event. - /// The instance containing the event data. - private void RestoreButton_Click(object sender, RoutedEventArgs e) - { - RestoreMaximizedWindow(); - } - - /// - /// Handles the Click event of the MinimizeButton control. - /// - /// The source of the event. - /// The instance containing the event data. - private void MinimizeButton_Click(object sender, RoutedEventArgs e) - { - MinimizeWindow(); - } - - /// - /// Minimizes the window. - /// - private void MinimizeWindow() - { - if (windowState != WindowState.Minimized) - { - if (minimizeButton != null) - VisualStateManager.GoToState(minimizeButton, VSMSTATE_StateNormal, true); - - if (windowState == WindowState.Normal) - { - // Store previous coordinates - previousPosition = Position; - previousSize = new Size(ActualWidth, ActualHeight); - } - - minimizedWindowThumbnail = GetThumbnailImage(); - - previousWindowState = windowState; - VisualStateManager.GoToState(this, VSMSTATE_StateMinimized, true); - OnMinimized(EventArgs.Empty); - } - - windowState = WindowState.Minimized; - OnDeactivated(EventArgs.Empty); - - this.FloatingWindowHost.ActivateTopmostWindow(); - } - - /// - /// Creates a thumbnail of the window. - /// - /// Bitmap containing thumbnail image. - private ImageSource GetThumbnailImage() - { - // If an Icon is specified - use it as a thumbnail displayed on the iconbar - // Otherwise, display the window itself - FrameworkElement icon = (Icon as FrameworkElement) ?? contentRoot; - ImageSource bitmap = bitmapHelper.RenderVisual(icon, FloatingWindowHost.IconWidth, FloatingWindowHost.IconHeight); - - return bitmap; - } - - /// - /// Maximizes the window. - /// - public void MaximizeWindow() - { - if (windowState != WindowState.Maximized) - { - if (maximizeButton != null && restoreButton != null && HostPanel != null) - { - if (this.ShowMaximizeButton) - maximizeButton.SetVisible(false); - - if (this.ShowRestoreButton) - restoreButton.SetVisible(true); - - VisualStateManager.GoToState(restoreButton, VSMSTATE_StateNormal, true); - - // Store previous coordinates - previousPosition = Position; - previousSize = new Size(ActualWidth, ActualHeight); - - // Hide the outer border - if (contentBorder != null) - { - contentBorderThickness = contentBorder.BorderThickness; - contentBorderCornerRadius = contentBorder.CornerRadius; - contentBorder.BorderThickness = new Thickness(0); - contentBorder.CornerRadius = new CornerRadius(0); - } - - Border border = chrome as Border; - if (border != null) - { - chromeBorderCornerRadius = border.CornerRadius; - border.CornerRadius = new CornerRadius(0); - } - - StartMaximizingAnimation(); - } - - previousWindowState = windowState; - windowState = WindowState.Maximized; - } - } - - /// - /// Checks if the floating window was added to the FloatingWindowHost. - /// - private void CheckHost() - { - if (this.FloatingWindowHost == null) - throw new InvalidOperationException("The FloatingWindow was not added to the FloatingWindowHost."); - } - - /// - /// Starts maximizing animation. - /// - private void StartMaximizingAnimation() - { - SaveActualSize(); - - this.MoveAndResize(new Point(0, 0), HostPanel.ActualWidth, HostPanel.ActualHeight, - MaximizingDurationInMilliseconds, Maximizing_Completed); - } - - /// - /// Saves the actual size if it was not set explicitly set. - /// E.g. the Width can be NaN, that means "Auto". - /// - private void SaveActualSize() - { - if (Width.IsNotSet()) - Width = ActualWidth; - - if (Height.IsNotSet()) - Height = ActualHeight; - } - - /// - /// Handles the Completed event of the Maximizing animation. - /// - /// The source of the event. - /// The instance containing the event data. - private void Maximizing_Completed(object sender, EventArgs e) - { - OnMaximized(EventArgs.Empty); - } - - /// - /// Restores maximized window position and size. - /// - private void RestoreMaximizedWindow() - { - if (windowState != WindowState.Normal) - { - if (maximizeButton != null && restoreButton != null && HostPanel != null) - { - if (this.ShowMaximizeButton) - maximizeButton.SetVisible(true); - - if (this.ShowRestoreButton) - restoreButton.SetVisible(false); - - VisualStateManager.GoToState(maximizeButton, VSMSTATE_StateNormal, true); - } - - // Restore the outer border - if (contentBorder != null) - { - contentBorder.BorderThickness = contentBorderThickness; - contentBorder.CornerRadius = contentBorderCornerRadius; - } - - Border border = chrome as Border; - - if (border != null) - border.CornerRadius = chromeBorderCornerRadius; - - StartRestoringAnimation(); - windowState = WindowState.Normal; - } - else - { - Show(Position); - } - } - - /// - /// Starts restoring animation. - /// - private void StartRestoringAnimation() - { - SaveActualSize(); - - this.MoveAndResize(previousPosition, previousSize.Width, previousSize.Height, - RestoringDurationInMilliseconds, Restoring_Completed); - } - - /// - /// Handles the Completed event of the Restoring animation. - /// - /// The source of the event. - /// The instance containing the event data. - private void Restoring_Completed(object sender, EventArgs e) - { - OnRestored(EventArgs.Empty); - } - - /// - /// Updates clipping region on host SizeChanged event. - /// - /// The source of the event. - /// The instance containing the event data. - private void Host_SizeChanged(object sender, SizeChangedEventArgs e) - { - if (windowState == WindowState.Maximized) - { - Width = HostPanel.ActualWidth; - Height = double.IsInfinity(MaxHeight) ? HostPanel.ActualHeight : MaxHeight; - } - } - - /// - /// Executed when mouse left button is down. - /// - /// The data for the event. - protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) - { - base.OnMouseLeftButtonDown(e); - - if (windowState == WindowState.Normal) - { - // Stop inertial motion before the mouse is captured - StopInertialMotion(); - - clickPoint = e.GetPosition(HostPanel); - clickWindowPosition = Position; - snapinController.SnapinDistance = this.FloatingWindowHost.SnapinDistance; - snapinController.SnapinMargin = this.FloatingWindowHost.SnapinMargin; - snapinController.SnapinEnabled = this.FloatingWindowHost.SnapinEnabled; - - if (ResizeEnabled && resizeController.CanResize) - { - snapinController.SnapinBounds = this.FloatingWindowHost.GetSnapinBounds(this); - resizeController.StartResizing(); - CaptureMouseCursor(); - windowAction = WindowAction.Resize; - } - else if (chrome != null) - { - // If the mouse was clicked on the chrome - start dragging the window - Point point = e.GetPosition(chrome); - - if (chrome.ContainsPoint(point)) - { - snapinController.SnapinBounds = this.FloatingWindowHost.GetSnapinBounds(this); - CaptureMouseCursor(); - windowAction = WindowAction.Move; - inertiaController.StartMotion(Position); - } - } - } - } - - /// - /// Executed when mouse left button is up. - /// - /// The data for the event. - protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) - { - base.OnMouseLeftButtonUp(e); - - if (windowAction == WindowAction.Move) - { - InertialMotion motion = inertiaController.GetInertialMotionParameters( - this.FloatingWindowHost.HostPanel.GetActualBoundingRectangle(), this.BoundingRectangle); - - if (motion != null) - { - contentRoot.AnimateTranslateTransform(inertialMotionStoryboard, motion.EndPosition, motion.Seconds, motion.EasingFunction); - } - } - - if (isMouseCaptured) - { - contentRoot.ReleaseMouseCapture(); - isMouseCaptured = false; - } - - windowAction = WindowAction.None; - } - - /// - /// Handles the Completed event of the InertialMotionStoryboard. - /// - /// The source of the event. - /// The instance containing the event data. - private void InertialMotion_Completed(object sender, EventArgs e) - { - // Save current window position reading it from the TranslateTransform object - Position = GetCurrentWindowPosition(); - } - - /// - /// Stops current inertial motion. - /// - private void StopInertialMotion() - { - if (inertialMotionStoryboard.GetCurrentState() != ClockState.Stopped) - { - inertialMotionStoryboard.Pause(); - - // The Position has rounded coordinates now, but real X and Y coordinates are fractional - Position = GetCurrentWindowPosition(); - - // Move the window to the rounded coordinates - MoveWindow(Position); - - inertialMotionStoryboard.Stop(); - inertialMotionStoryboard.Children.Clear(); - } - } - - /// - /// Gets current window position taking into account animation effects. - /// - /// Current window position. - private Point GetCurrentWindowPosition() - { - var transformGroup = contentRoot.RenderTransform as TransformGroup; - var translateTransform = transformGroup.Children.OfType().FirstOrDefault(); - var position = new Point(translateTransform.X, translateTransform.Y); - - // Round coordinates to avoid blured window - return position.Round(); - } - - /// - /// Captures the mouse cursor. - /// - private void CaptureMouseCursor() - { - contentRoot.CaptureMouse(); - isMouseCaptured = true; - } - - /// - /// Executed when mouse moves. - /// - /// The data for the event. - protected override void OnMouseMove(MouseEventArgs e) - { - base.OnMouseMove(e); - - if (windowState == WindowState.Normal && ResizeEnabled && windowAction == WindowAction.None) - { - Point mousePosition = e.GetPosition(contentRoot); - - if (IsMouseOverButtons(mousePosition, contentRoot)) - this.Cursor = Cursors.Arrow; - else - resizeController.SetCursor(mousePosition); - } - - Point p = e.GetPosition(HostPanel); - double dx = p.X - clickPoint.X; - double dy = p.Y - clickPoint.Y; - - if (windowAction == WindowAction.Resize) - resizeController.Resize(dx, dy); - - if (windowAction == WindowAction.Move) - { - Point point = clickWindowPosition.Add(dx, dy); - Rect rect = new Rect(point.X, point.Y, ActualWidth, ActualHeight); - - point = snapinController.SnapRectangle(rect); - MoveWindow(point); - - inertiaController.MoveToPoint(Position); - } - } - - /// - /// Determines whether the mouse is over buttons in the the specified mouse position. - /// - /// The mouse position. - /// Relative origin. - /// true if mouse is mouse over buttons. - private bool IsMouseOverButtons(Point position, UIElement origin) - { - return (minimizeButton.IsVisible() && minimizeButton.ContainsPoint(position, origin)) || - (maximizeButton.IsVisible() && maximizeButton.ContainsPoint(position, origin)) || - (restoreButton.IsVisible() && restoreButton.ContainsPoint(position, origin)) || - (closeButton.IsVisible() && closeButton.ContainsPoint(position, origin)); - } - - /// - /// Moves the window to the specified coordinates. - /// - /// Coordinates of the window. - private void MoveWindow(Point point) - { - if (contentRoot != null && !point.IsNotSet()) - { - // Round coordinates to avoid blured window - double x = Math.Round(Math.Max(0, point.X)); - double y = Math.Round(Math.Max(0, point.Y)); - - var transformGroup = contentRoot.RenderTransform as TransformGroup; - var translateTransform = transformGroup.Children.OfType().FirstOrDefault(); - if (translateTransform == null) - { - transformGroup.Children.Add(new TranslateTransform() { X = x, Y = y }); - } - else - { - translateTransform.X = x; - translateTransform.Y = y; - } - - Point newPosition = new Point(x, y); - - if (Position != newPosition) - Position = newPosition; - } - } - - /// - /// Saves current size and position of the window in the IsolatedStorage. - /// The key of the settings is the Tag of the window (if not null). - /// - private void SaveSizeAndPosition() - { - if (IsWindowTagSet) - { - string positionKey = GetAppSettingsKey("Position"); - string sizeKey = GetAppSettingsKey("Size"); - - Point point = windowState == WindowState.Normal ? Position : previousPosition; - localStorage[positionKey] = point; - - Size size = windowState == WindowState.Normal ? new Size(ActualWidth, ActualHeight) : previousSize; - localStorage[sizeKey] = size; - } - } - - /// - /// Gets the application settings key used to store properties in the IsolatedStorage. - /// - /// The key of the property, e.g. "Position". - /// Combined settings key or empty string. - private string GetAppSettingsKey(string key) - { - string tag = this.Tag as string; - return tag + ":" + key; - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/FloatingWindowHost.cs --- a/SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/FloatingWindowHost.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1032 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using SilverFlow.Controls.Extensions; - -namespace SilverFlow.Controls -{ - /// - /// A Content Control containing floating windows. - /// - [TemplatePart(Name = PART_Root, Type = typeof(Grid))] - [TemplatePart(Name = PART_ContentRoot, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_HostCanvas, Type = typeof(Canvas))] - [TemplatePart(Name = PART_ModalCanvas, Type = typeof(Canvas))] - [TemplatePart(Name = PART_IconBarContainer, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_Overlay, Type = typeof(Grid))] - [TemplatePart(Name = PART_IconBar, Type = typeof(IconBar))] - [TemplatePart(Name = PART_BottomBar, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_BootstrapButton, Type = typeof(BootstrapButton))] - [TemplatePart(Name = PART_BarContent, Type = typeof(ContentControl))] - [TemplateVisualState(Name = VSMSTATE_VisibleOverlay, GroupName = VSMGROUP_Overlay)] - [TemplateVisualState(Name = VSMSTATE_HiddenOverlay, GroupName = VSMGROUP_Overlay)] - [StyleTypedProperty(Property = PROPERTY_BottomBarStyle, StyleTargetType = typeof(Border))] - [StyleTypedProperty(Property = PROPERTY_BootstrapButtonStyle, StyleTargetType = typeof(BootstrapButton))] - [StyleTypedProperty(Property = PROPERTY_WindowIconStyle, StyleTargetType = typeof(WindowIcon))] - public class FloatingWindowHost : ContentControl - { - #region Constants - - // Template parts - private const string PART_Root = "PART_Root"; - private const string PART_ContentRoot = "PART_ContentRoot"; - private const string PART_HostCanvas = "PART_HostCanvas"; - private const string PART_ModalCanvas = "PART_ModalCanvas"; - private const string PART_IconBarContainer = "PART_IconBarContainer"; - private const string PART_Overlay = "PART_Overlay"; - private const string PART_IconBar = "PART_IconBar"; - private const string PART_BottomBar = "PART_BottomBar"; - private const string PART_BootstrapButton = "PART_BootstrapButton"; - private const string PART_BarContent = "PART_BarContent"; - - // VSM groups - private const string VSMGROUP_Overlay = "OverlayStates"; - - // VSM states - private const string VSMSTATE_VisibleOverlay = "VisibleOverlay"; - private const string VSMSTATE_HiddenOverlay = "HiddenOverlay"; - - // Style typed properties - private const string PROPERTY_BottomBarStyle = "BottomBarStyle"; - private const string PROPERTY_BootstrapButtonStyle = "BootstrapButtonStyle"; - private const string PROPERTY_WindowIconStyle = "WindowIconStyle"; - - // Thickness of resizing area. - private const double SnapinDistanceDefaultValue = 5.0; - - // Default icon size - private const double DefaultIconWidth = 120; - private const double DefaultIconHeight = 70; - - #endregion - - #region Member Fields - - /// - /// Current ZIndex of a child element - /// - private static int zIndex = 1; - - private Grid root; - private FrameworkElement contentRoot; - private Canvas hostCanvas; - private Canvas modalCanvas; - private FrameworkElement iconBarContainer; - private Grid overlay; - private IconBar iconBar; - private FrameworkElement bottomBar; - private BootstrapButton bootstrapButton; - private ContentControl barContent; - - private bool templateIsApplied; - - #endregion Member Fields - - #region public Style BottomBarStyle - - /// - /// Gets or sets the style of the BottomBar. - /// - public Style BottomBarStyle - { - get { return GetValue(BottomBarStyleProperty) as Style; } - set { SetValue(BottomBarStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty BottomBarStyleProperty = - DependencyProperty.Register( - "BottomBarStyle", - typeof(Style), - typeof(FloatingWindowHost), - new PropertyMetadata(BottomBarStylePropertyChanged)); - - /// - /// BottomBarStyle PropertyChangedCallback call back static function. - /// - /// FloatingWindowHost object whose BottomBarStyle property is changed. - /// The instance containing the event data. - private static void BottomBarStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindowHost host = (FloatingWindowHost)d; - if (host != null && host.bottomBar != null) - { - host.bottomBar.Style = e.NewValue as Style; - } - } - - #endregion - - #region public Style BootstrapButtonStyle - - /// - /// Gets or sets the style of the BootstrapButton. - /// - public Style BootstrapButtonStyle - { - get { return GetValue(BootstrapButtonStyleProperty) as Style; } - set { SetValue(BootstrapButtonStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty BootstrapButtonStyleProperty = - DependencyProperty.Register( - "BootstrapButtonStyle", - typeof(Style), - typeof(FloatingWindowHost), - new PropertyMetadata(BootstrapButtonStylePropertyChanged)); - - /// - /// BootstrapButtonStyle PropertyChangedCallback call back static function. - /// - /// FloatingWindowHost object whose BootstrapButtonStyle property is changed. - /// The instance containing the event data. - private static void BootstrapButtonStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindowHost host = (FloatingWindowHost)d; - if (host != null && host.bottomBar != null) - { - host.bootstrapButton.Style = e.NewValue as Style; - } - } - - #endregion - - #region public Style WindowIconStyle - - /// - /// Gets or sets the style of the WindowIcon. - /// - public Style WindowIconStyle - { - get { return GetValue(WindowIconStyleProperty) as Style; } - set { SetValue(WindowIconStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty WindowIconStyleProperty = - DependencyProperty.Register( - "WindowIconStyle", - typeof(Style), - typeof(FloatingWindowHost), - new PropertyMetadata(WindowIconStylePropertyChanged)); - - /// - /// WindowIconStyle PropertyChangedCallback call back static function. - /// - /// FloatingWindowHost object whose WindowIconStyle property is changed. - /// The instance containing the event data. - private static void WindowIconStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindowHost host = (FloatingWindowHost)d; - if (host != null && host.iconBar != null) - { - host.iconBar.WindowIconStyle = e.NewValue as Style; - } - } - - #endregion - - #region public bool SnapinEnabled - - /// - /// Gets or sets a value indicating whether snap in is enabled. - /// - /// true if snap in is enabled; otherwise, false. - public bool SnapinEnabled - { - get { return (bool)GetValue(SnapinEnabledProperty); } - set { SetValue(SnapinEnabledProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty SnapinEnabledProperty = - DependencyProperty.Register( - "SnapinEnabled", - typeof(bool), - typeof(FloatingWindowHost), - new PropertyMetadata(true, null)); - - #endregion - - #region public double SnapinDistance - - /// - /// Gets or sets a value of the snap in distance. - /// - /// Snap in distance. - public double SnapinDistance - { - get { return (double)GetValue(SnapinDistanceProperty); } - set { SetValue(SnapinDistanceProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty SnapinDistanceProperty = - DependencyProperty.Register( - "SnapinDistance", - typeof(double), - typeof(FloatingWindowHost), - new PropertyMetadata(SnapinDistanceDefaultValue, null)); - - #endregion - - #region public double SnapinMargin - - /// - /// Gets or sets a value of the snap in margin - distance between adjacent edges. - /// - /// Snap in margin. - public double SnapinMargin - { - get { return (double)GetValue(SnapinMarginProperty); } - set { SetValue(SnapinMarginProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty SnapinMarginProperty = - DependencyProperty.Register( - "SnapinMargin", - typeof(double), - typeof(FloatingWindowHost), - new PropertyMetadata(0.0, null)); - - #endregion - - #region public bool ShowMinimizedOnlyInIconbar - - /// - /// Gets or sets a value indicating whether to show only minimized windows in the iconbar. - /// - /// true if to show only minimized windows in the iconbar; otherwise, false. - public bool ShowMinimizedOnlyInIconbar - { - get { return (bool)GetValue(ShowMinimizedOnlyInIconbarProperty); } - set { SetValue(ShowMinimizedOnlyInIconbarProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty ShowMinimizedOnlyInIconbarProperty = - DependencyProperty.Register( - "ShowMinimizedOnlyInIconbar", - typeof(bool), - typeof(FloatingWindowHost), - new PropertyMetadata(false, null)); - - #endregion - - #region public Brush OverlayBrush - - /// - /// Gets or sets the overlay color. - /// - /// The overlay color. - public Brush OverlayBrush - { - get { return (Brush)GetValue(OverlayBrushProperty); } - set { SetValue(OverlayBrushProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty OverlayBrushProperty = - DependencyProperty.Register( - "OverlayBrush", - typeof(Brush), - typeof(FloatingWindowHost), - new PropertyMetadata(new SolidColorBrush(Color.FromArgb(0x90, 0x20, 0x20, 0x30)), OnOverlayBrushPropertyChanged)); - - /// - /// OverlayBrushProperty PropertyChangedCallback call back static function. - /// - /// FloatingWindowHost object whose OverlayBrush property is changed. - /// DependencyPropertyChangedEventArgs which contains the old and new values. - private static void OnOverlayBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - FloatingWindowHost host = (FloatingWindowHost)d; - - if (host != null && host.overlay != null) - host.overlay.Background = (Brush)e.NewValue; - } - - #endregion - - #region public double IconWidth - - /// - /// Gets or sets the width of the window's icon. - /// - /// The width of the window's icon. - public double IconWidth - { - get { return (double)GetValue(IconWidthProperty); } - set { SetValue(IconWidthProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty IconWidthProperty = - DependencyProperty.Register( - "IconWidth", - typeof(double), - typeof(FloatingWindowHost), - new PropertyMetadata(DefaultIconWidth, null)); - - #endregion - - #region public double IconHeight - - /// - /// Gets or sets the height of the window's icon. - /// - /// The height of the window's icon. - public double IconHeight - { - get { return (double)GetValue(IconHeightProperty); } - set { SetValue(IconHeightProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty IconHeightProperty = - DependencyProperty.Register( - "IconHeight", - typeof(double), - typeof(FloatingWindowHost), - new PropertyMetadata(DefaultIconHeight, null)); - - #endregion - - #region public object Bar - - /// - /// Gets or sets a control displayed in the BottomBar. - /// - /// The control displayed in the BottomBar. The default is null. - public object Bar - { - get { return (double)GetValue(BarProperty); } - set { SetValue(BarProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty BarProperty = - DependencyProperty.Register( - "Bar", - typeof(object), - typeof(FloatingWindowHost), - null); - - #endregion - - /// - /// Gets a collection of windows shown in the IconBar. - /// - /// Collection of windows shown in the IconBar. - public IOrderedEnumerable WindowsInIconBar - { - get - { - var windows = from window in this.FloatingWindows - where window.IsOpen && window.ShowInIconbar && - !(ShowMinimizedOnlyInIconbar && window.WindowState != WindowState.Minimized) - orderby window.IconText - select window; - - return windows; - } - } - - /// - /// Gets the host panel, containing the floating windows. - /// - /// The host panel. - public Canvas HostPanel - { - get { return hostCanvas; } - } - - /// - /// Gets the floating windows collection. - /// - /// The floating windows collection. - public IEnumerable FloatingWindows - { - get { return hostCanvas.Children.OfType(); } - } - - /// - /// Gets or sets a value indicating whether the layout of the FloatingWindowHost is updated. - /// - /// - /// true if the layout of the FloatingWindowHost is updated; otherwise, false. - /// - internal bool IsLayoutUpdated { get; private set; } - - /// - /// Gets current modal window. - /// - /// The modal window. - private FloatingWindow ModalWindow - { - get { return modalCanvas.Children.OfType().FirstOrDefault(); } - } - - /// - /// Initializes a new instance of the class. - /// - public FloatingWindowHost() - { - DefaultStyleKey = typeof(FloatingWindowHost); - } - - /// - /// Builds the visual tree for the control - /// when a new template is applied. - /// - public override void OnApplyTemplate() - { - UnsubscribeFromEvents(); - UnsubscribeFromTemplatePartEvents(); - - base.OnApplyTemplate(); - - root = GetTemplatePart(PART_Root); - contentRoot = GetTemplatePart(PART_ContentRoot); - hostCanvas = GetTemplatePart(PART_HostCanvas); - modalCanvas = GetTemplatePart(PART_ModalCanvas); - iconBarContainer = GetTemplatePart(PART_IconBarContainer); - overlay = GetTemplatePart(PART_Overlay); - iconBar = GetTemplatePart(PART_IconBar); - bottomBar = GetTemplatePart(PART_BottomBar); - bootstrapButton = GetTemplatePart(PART_BootstrapButton); - barContent = GetTemplatePart(PART_BarContent); - - iconBar.FloatingWindowHost = this; - - SetStyles(); - SubscribeToTemplatePartEvents(); - SubscribeToEvents(); - - templateIsApplied = true; - } - - #region Events - - /// - /// Occurs when the is loaded and its template is applied. - /// - public event EventHandler Rendered; - - /// - /// Occurs when the active is changed. - /// - public event EventHandler ActiveWindowChanged; - - #endregion Events - - /// - /// Adds the specified floating window to the collection of child elements of the host. - /// - /// The floating window. - /// Floating window is null. - public void Add(FloatingWindow window) - { - if (window == null) - throw new ArgumentNullException("window"); - - // Guarantee that the visual tree of the control is complete - if (!templateIsApplied) - templateIsApplied = ApplyTemplate(); - - if (!hostCanvas.Children.Contains(window)) - { - hostCanvas.Children.Add(window); - window.FloatingWindowHost = this; - } - } - - /// - /// Removes the specified floating window from the collection of child elements of the host. - /// - /// The floating window. - public void Remove(FloatingWindow window) - { - if (window != null) - { - hostCanvas.Children.Remove(window); - modalCanvas.Children.Remove(window); - iconBar.Remove(window); - } - } - - /// - /// Closes all floating windows. - /// - public void CloseAllWindows() - { - HideIconBar(); - FloatingWindows.ToList().ForEach(x => x.Close()); - } - - /// - /// Shows the IconBar. - /// - public void ShowIconBar() - { - iconBar.Show(); - } - - /// - /// Hides the IconBar. - /// - public void HideIconBar() - { - iconBar.Hide(); - } - - /// - /// Updates the IconBar if it is open. - /// - public void UpdateIconBar() - { - iconBar.Update(); - } - - /// - /// Sets the specified floating window topmost, and set Focus on it. - /// - /// FloatingWindow to set topmost. - /// FloatingWindow is null. - public void SetTopmostWindow(FloatingWindow window) - { - if (window == null) - throw new ArgumentNullException("window"); - - FloatingWindow topmostWindow = GetTopmostWindow(); - if (topmostWindow == null || window != topmostWindow) - { - SetTopmost(window); - SetFocusToActiveWindow(window); - - if (!window.TopMost && !window.IsModal) - ShowTopmostWindows(); - - ActiveWindowChangedEventArgs e = new ActiveWindowChangedEventArgs(topmostWindow, window); - OnActiveWindowChanged(e); - } - } - - /// - /// Activates the topmost window and sets focus on it. - /// - public void ActivateTopmostWindow() - { - // First, try to activate a modal window, if exists - var topmostWindow = this.ModalWindow; - - if (topmostWindow == null) - topmostWindow = GetTopmostWindow(); - - SetFocusToActiveWindow(topmostWindow); - - ActiveWindowChangedEventArgs e = new ActiveWindowChangedEventArgs(null, topmostWindow); - OnActiveWindowChanged(e); - } - - /// - /// Gets Snap In bounds as bounds of the host and all open windows except the specified one. - /// - /// The window to exclude from the list. - /// List of bounding rectangles. - internal IEnumerable GetSnapinBounds(FloatingWindow windowToExclude) - { - List bounds = new List(); - - // Add host bounds - bounds.Add(hostCanvas.GetActualBoundingRectangle()); - - if (!overlay.IsVisible()) - { - foreach (var window in FloatingWindows) - { - if (window != windowToExclude && window.IsOpen) - bounds.Add(window.BoundingRectangle); - } - } - - return bounds; - } - - /// - /// Shows the overlay, moves the window to the "modal" layer and hides the IconBar. - /// - /// The modal window. - internal void ShowWindowAsModal(FloatingWindow modalWindow) - { - HideIconBar(); - VisualStateManager.GoToState(this, VSMSTATE_VisibleOverlay, true); - - MoveWindowToModalLayer(modalWindow); - } - - /// - /// Removes the overlay under the modal window. - /// - internal void RemoveOverlay() - { - if (overlay.IsVisible()) - { - FloatingWindow topmostWindow = null; - - if (FloatingWindows.Count(x => x.IsOpen && x.IsModal) == 0) - { - // If there are no more modal windows - remove the overlay - VisualStateManager.GoToState(this, VSMSTATE_HiddenOverlay, true); - - topmostWindow = GetTopmostWindow(); - } - else - { - topmostWindow = GetTopmostModalWindow(); - - if (topmostWindow != null) - topmostWindow.MoveToContainer(modalCanvas); - } - - SetFocusToActiveWindow(topmostWindow); - } - } - - /// - /// Moves the window to the "modal" layer. - /// - /// The modal window. - private void MoveWindowToModalLayer(FloatingWindow modalWindow) - { - FloatingWindow window = this.ModalWindow; - if (window != null && window != modalWindow) - { - // If there is already a modal window - move it to the HostCanvas - window.MoveToContainer(hostCanvas); - SetTopmost(window); - } - - modalWindow.MoveToContainer(modalCanvas); - } - - /// - /// Raises the event. - /// - /// The event data. - protected virtual void OnActiveWindowChanged(ActiveWindowChangedEventArgs e) - { - EventHandler handler = ActiveWindowChanged; - - if (handler != null) - handler(this, e); - } - - /// - /// Shows a floating window when the layout is updated. - /// - /// A method that displays a window in the specified coordinates. - /// Coordinates of the upper-left corner of the window. - internal void ShowWindow(Action action, Point point) - { - if (IsLayoutUpdated) - { - action(point); - } - else - { - this.Rendered += (s, e) => { action(point); }; - } - } - - /// - /// Shows a floating window when the layout is updated. - /// - /// A method that displays a window taking into account specified margins. - /// Window margins. - internal void ShowWindow(Action action, Thickness margins) - { - if (IsLayoutUpdated) - { - action(margins); - } - else - { - this.Rendered += (s, e) => { action(margins); }; - - } - } - - /// - /// Subscribes to the events on the template parts. - /// - private void SubscribeToTemplatePartEvents() - { - bootstrapButton.Click += new RoutedEventHandler(BootstrapButton_Click); - iconBar.Opened += new EventHandler(IconBarVisibilityChanged); - iconBar.Closed += new EventHandler(IconBarVisibilityChanged); - hostCanvas.SizeChanged += new SizeChangedEventHandler(HostCanvas_SizeChanged); - modalCanvas.SizeChanged += new SizeChangedEventHandler(ModalCanvas_SizeChanged); - iconBarContainer.SizeChanged += new SizeChangedEventHandler(IconBarContainer_SizeChanged); - } - - /// - /// Unsubscribe from the events that are subscribed on the template part elements. - /// - private void UnsubscribeFromTemplatePartEvents() - { - if (bootstrapButton != null) - bootstrapButton.Click -= new RoutedEventHandler(BootstrapButton_Click); - - if (iconBar != null) - iconBar.Opened -= new EventHandler(IconBarVisibilityChanged); - - if (iconBar != null) - iconBar.Closed -= new EventHandler(IconBarVisibilityChanged); - - if (hostCanvas != null) - hostCanvas.SizeChanged -= new SizeChangedEventHandler(HostCanvas_SizeChanged); - - if (modalCanvas != null) - modalCanvas.SizeChanged -= new SizeChangedEventHandler(ModalCanvas_SizeChanged); - - if (iconBarContainer != null) - iconBarContainer.SizeChanged -= new SizeChangedEventHandler(IconBarContainer_SizeChanged); - } - - /// - /// Subscribes to the events the control shall handle. - /// - private void SubscribeToEvents() - { - this.MouseLeftButtonDown += new MouseButtonEventHandler(FloatingWindowHost_MouseLeftButtonDown); - this.LayoutUpdated += new EventHandler(FloatingWindowHost_LayoutUpdated); - } - - /// - /// Unsubscribes from the subscribed events. - /// - private void UnsubscribeFromEvents() - { - this.MouseLeftButtonDown -= new MouseButtonEventHandler(FloatingWindowHost_MouseLeftButtonDown); - this.LayoutUpdated -= new EventHandler(FloatingWindowHost_LayoutUpdated); - } - - /// - /// Handles the first LayoutUpdated event of the FloatingWindowHost control to raise the OnRendered event. - /// - /// The source of the event. - /// The instance containing the event data. - private void FloatingWindowHost_LayoutUpdated(object sender, EventArgs e) - { - if (!IsLayoutUpdated) - { - this.LayoutUpdated -= new EventHandler(FloatingWindowHost_LayoutUpdated); - IsLayoutUpdated = true; - OnRendered(EventArgs.Empty); - } - } - - /// - /// Raises the event. - /// Occures when the control template is applied and the control can be rendered. - /// - /// The instance containing the event data. - protected virtual void OnRendered(EventArgs e) - { - EventHandler handler = Rendered; - - if (handler != null) - handler(this, e); - } - - /// - /// Gets the topmost open FloatingWindow. - /// - /// The topmost open FloatingWindow. - private FloatingWindow GetTopmostWindow() - { - var topmost = (from window in FloatingWindows - where !window.TopMost && window.IsOpen && window.WindowState != WindowState.Minimized - select new - { - Window = window, - ZIndex = Canvas.GetZIndex(window) - } - ).ToList().OrderBy(x => x.ZIndex).LastOrDefault(); - - return topmost != null ? topmost.Window : null; - } - - /// - /// Gets the topmost modal FloatingWindow on the HostCanvas. - /// - /// The topmost modal FloatingWindow. - private FloatingWindow GetTopmostModalWindow() - { - var topmost = (from window in FloatingWindows - where window.IsModal && window.IsOpen - select new - { - Window = window, - ZIndex = Canvas.GetZIndex(window) - } - ).ToList().OrderBy(x => x.ZIndex).LastOrDefault(); - - return topmost != null ? topmost.Window : null; - } - - /// - /// Shows the topmost windows in front of other windows. - /// - private void ShowTopmostWindows() - { - FloatingWindows - .Where(x => x.IsOpen && x.TopMost).ToList() - .ForEach(x => SetTopmost(x)); - } - - /// - /// Sets the specified UIElement topmost. - /// - /// UIElement to set topmost. - /// UIElement is null. - private void SetTopmost(UIElement element) - { - if (element == null) - throw new ArgumentNullException("element"); - - zIndex++; - Canvas.SetZIndex(element, zIndex); - } - - /// - /// Attempts to set the focus on the FloatingWindow. - /// - /// The window. - private void SetFocusToActiveWindow(FloatingWindow window) - { - if (window != null && !window.TopMost) - window.Focus(); - } - - /// - /// Handles the MouseLeftButtonDown event of the FloatingWindowHost control. - /// Closes the IconBar on mouse left click. - /// - /// The source of the event. - /// The instance containing the event data. - private void FloatingWindowHost_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - e.Handled = false; - HideIconBar(); - } - - /// - /// Handles the Click event of the BootstrapButton. - /// - /// The source of the event. - /// The instance containing the event data. - private void BootstrapButton_Click(object sender, RoutedEventArgs e) - { - if (bootstrapButton.IsOpen) - ShowIconBar(); - else - HideIconBar(); - } - - /// - /// Handles the IconBar Visibility Changed event. - /// - /// The sender. - /// The instance containing the event data. - private void IconBarVisibilityChanged(object sender, EventArgs e) - { - bootstrapButton.IsOpen = iconBar.IsOpen; - } - - /// - /// Handles the SizeChanged event of the HostCanvas control to set its clipping region. - /// - /// The source of the event. - /// The instance containing the event data. - private void HostCanvas_SizeChanged(object sender, SizeChangedEventArgs e) - { - hostCanvas.Clip = new RectangleGeometry() - { - Rect = hostCanvas.GetActualBoundingRectangle() - }; - } - - /// - /// Handles the SizeChanged event of the ModalCanvas control to set its clipping region. - /// - /// The source of the event. - /// The instance containing the event data. - private void ModalCanvas_SizeChanged(object sender, SizeChangedEventArgs e) - { - modalCanvas.Clip = new RectangleGeometry() - { - Rect = modalCanvas.GetActualBoundingRectangle() - }; - } - - /// - /// Handles the SizeChanged event of the IconBarContainer control to set its clipping region. - /// - /// The source of the event. - /// The instance containing the event data. - private void IconBarContainer_SizeChanged(object sender, SizeChangedEventArgs e) - { - iconBarContainer.Clip = new RectangleGeometry() - { - Rect = iconBarContainer.GetActualBoundingRectangle() - }; - } - - /// - /// Sets styles that are applied for different template parts. - /// - private void SetStyles() - { - if (bottomBar != null && this.BottomBarStyle != null) - bottomBar.Style = this.BottomBarStyle; - - if (bootstrapButton != null && this.BootstrapButtonStyle != null) - bootstrapButton.Style = this.BootstrapButtonStyle; - - if (iconBar != null && this.WindowIconStyle != null) - iconBar.WindowIconStyle = this.WindowIconStyle; - } - - /// - /// Gets the FrameworkElement template part with the specified name. - /// - /// The template part type. - /// The template part name. - /// The requested element. - /// The template part not found. - private T GetTemplatePart(string partName) where T : class - { - T part = this.GetTemplateChild(partName) as T; - - if (part == null) - throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "Template Part {0} is required.", partName)); - - return part; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/IconBar.cs --- a/SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/IconBar.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,527 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Globalization; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media.Animation; -using SilverFlow.Controls.Extensions; -using SilverFlow.Controls.Helpers; - -namespace SilverFlow.Controls -{ - /// - /// IconBar containing window icons. - /// - [TemplatePart(Name = PART_LayoutRoot, Type = typeof(FrameworkElement))] - [TemplatePart(Name = PART_FixedBar, Type = typeof(Border))] - [TemplatePart(Name = PART_SlidingBar, Type = typeof(Border))] - [TemplatePart(Name = PART_Carousel, Type = typeof(StackPanel))] - [TemplateVisualState(Name = VSMSTATE_StateOpen, GroupName = VSMGROUP_States)] - [TemplateVisualState(Name = VSMSTATE_StateClosed, GroupName = VSMGROUP_States)] - [StyleTypedProperty(Property = PROPERTY_TitleStyle, StyleTargetType = typeof(Border))] - [StyleTypedProperty(Property = PROPERTY_WindowIconStyle, StyleTargetType = typeof(WindowIcon))] - public class IconBar : ContentControl, INotifyPropertyChanged - { - // Template parts - private const string PART_LayoutRoot = "PART_LayoutRoot"; - private const string PART_FixedBar = "PART_FixedBar"; - private const string PART_SlidingBar = "PART_SlidingBar"; - private const string PART_Carousel = "PART_Carousel"; - - // VSM groups - private const string VSMGROUP_States = "VisualStateGroup"; - - // VSM states - private const string VSMSTATE_StateOpen = "Open"; - private const string VSMSTATE_StateClosed = "Closed"; - - // Style typed properties - private const string PROPERTY_TitleStyle = "IconBarStyle"; - private const string PROPERTY_WindowIconStyle = "WindowIconStyle"; - - // Animation duration in milliseconds - private const double SlidingDurationInMilliseconds = 200; - - #region public Style IconBarStyle - - /// - /// Gets or sets the style of the IconBar. - /// - public Style IconBarStyle - { - get { return GetValue(IconBarStyleProperty) as Style; } - set { SetValue(IconBarStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty IconBarStyleProperty = - DependencyProperty.Register( - "IconBarStyle", - typeof(Style), - typeof(IconBar), - new PropertyMetadata(IconBarStylePropertyChanged)); - - /// - /// IconBarStyle PropertyChangedCallback call back static function. - /// - /// IconBar object whose IconBarStyle property is changed. - /// The instance containing the event data. - private static void IconBarStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - IconBar iconBar = (IconBar)d; - if (iconBar != null && iconBar.fixedBar != null) - { - iconBar.fixedBar.Style = e.NewValue as Style; - } - } - - #endregion - - #region public Style WindowIconStyle - - /// - /// Gets or sets the style of the WindowIcon. - /// - public Style WindowIconStyle - { - get { return GetValue(WindowIconStyleProperty) as Style; } - set { SetValue(WindowIconStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty WindowIconStyleProperty = - DependencyProperty.Register( - "WindowIconStyle", - typeof(Style), - typeof(IconBar), - null); - - #endregion - - private FrameworkElement layoutRoot; - private Border fixedBar; - private Border slidingBar; - private StackPanel carousel; - private Storyboard closingStoryboard; - private Storyboard openingStoryboard; - private bool isOpen; - private double slidingBarPosition; - private IVisualHelper visualHelper; - - /// - /// Gets or sets a value indicating whether the IconBar is open. - /// - /// true if the IconBar is open; otherwise, false. - public bool IsOpen - { - get { return isOpen; } - private set - { - if (value != isOpen) - { - isOpen = value; - OnPropertyChanged(new PropertyChangedEventArgs("IsOpen")); - } - } - } - - /// - /// Gets or sets the FloatingWindowHost containing the IconBar. - /// - /// FloatingWindowHost containing the IconBar. - public FloatingWindowHost FloatingWindowHost { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public IconBar() - { - DefaultStyleKey = typeof(IconBar); - visualHelper = new VisualHelper(); - } - - /// - /// Occurs when the is opened. - /// - public event EventHandler Opened; - - /// - /// Occurs when the is closed. - /// - public event EventHandler Closed; - - #region INotifyPropertyChanged implementation - /// - /// Occurs when a property changed. - /// - public event PropertyChangedEventHandler PropertyChanged; - - /// - /// Raises the event. - /// - /// The instance containing the event data. - public void OnPropertyChanged(PropertyChangedEventArgs e) - { - if (PropertyChanged != null) - PropertyChanged(this, e); - } - #endregion - - /// - /// Builds the visual tree for the control - /// when a new template is applied. - /// - public override void OnApplyTemplate() - { - UnsubscribeFromEvents(); - - base.OnApplyTemplate(); - - layoutRoot = GetTemplatePart(PART_LayoutRoot); - fixedBar = GetTemplatePart(PART_FixedBar); - slidingBar = GetTemplatePart(PART_SlidingBar); - carousel = GetTemplatePart(PART_Carousel); - - SetStyles(); - GetStoryboards(); - SubscribeToEvents(); - } - - /// - /// Shows the IconBar. - /// - public void Show() - { - if (!IsOpen) - { - FillCarousel(); - SetSlidingBarPosition(0); - VisualStateManager.GoToState(this, VSMSTATE_StateOpen, true); - } - } - - /// - /// Hides the IconBar. - /// - public void Hide() - { - if (IsOpen) - { - VisualStateManager.GoToState(this, VSMSTATE_StateClosed, true); - } - } - - /// - /// Updates the IconBar if it is open. - /// - public void Update() - { - if (IsOpen) - { - FillCarousel(); - } - } - - /// - /// Removes the specified window from the IconBar. - /// - /// The window to remove from the IconBar. - public void Remove(FloatingWindow window) - { - if (window != null) - { - var icon = (from windowIcon in carousel.Children.OfType() - where windowIcon.Window == window - select windowIcon).FirstOrDefault(); - - if (icon != null) - { - icon.Click -= new RoutedEventHandler(Icon_Click); - carousel.Children.Remove(icon); - } - } - } - - /// - /// Gets the storyboards defined in the style. - /// - private void GetStoryboards() - { - var groups = VisualStateManager.GetVisualStateGroups(layoutRoot) as Collection; - if (groups != null) - { - var states = (from stategroup in groups - where stategroup.Name == IconBar.VSMGROUP_States - select stategroup.States).FirstOrDefault() as Collection; - - if (states != null) - { - openingStoryboard = (from state in states - where state.Name == IconBar.VSMSTATE_StateOpen - select state.Storyboard).FirstOrDefault(); - - closingStoryboard = (from state in states - where state.Name == IconBar.VSMSTATE_StateClosed - select state.Storyboard).FirstOrDefault(); - } - } - } - - /// - /// Subscribes to the events after new template is applied. - /// - private void SubscribeToEvents() - { - if (closingStoryboard != null) - closingStoryboard.Completed += new EventHandler(Closing_Completed); - - if (openingStoryboard != null) - openingStoryboard.Completed += new EventHandler(Opening_Completed); - - if (fixedBar != null) - fixedBar.MouseMove += new MouseEventHandler(Bar_MouseMove); - - if (fixedBar != null) - fixedBar.SizeChanged += new SizeChangedEventHandler(FixedBar_SizeChanged); - } - - /// - /// Unsubscribe from events. - /// - private void UnsubscribeFromEvents() - { - if (closingStoryboard != null) - closingStoryboard.Completed -= new EventHandler(Closing_Completed); - - if (openingStoryboard != null) - openingStoryboard.Completed -= new EventHandler(Opening_Completed); - - if (fixedBar != null) - fixedBar.MouseMove += new MouseEventHandler(Bar_MouseMove); - - if (fixedBar != null) - fixedBar.SizeChanged -= new SizeChangedEventHandler(FixedBar_SizeChanged); - } - - /// - /// Sets styles that are applied for different template parts. - /// - private void SetStyles() - { - if (fixedBar != null && this.IconBarStyle != null) - fixedBar.Style = this.IconBarStyle; - } - - /// - /// Executed when the Closing storyboard ends. - /// - /// Sender object. - /// Event args. - private void Closing_Completed(object sender, EventArgs e) - { - IsOpen = false; - ClearCarousel(); - OnClosed(EventArgs.Empty); - } - - /// - /// Executed when the Opening storyboard finishes. - /// - /// Sender object. - /// Event args. - private void Opening_Completed(object sender, EventArgs e) - { - IsOpen = true; - OnOpened(EventArgs.Empty); - } - - /// - /// Raises the event. - /// - /// The instance containing the event data. - protected virtual void OnOpened(EventArgs e) - { - EventHandler handler = Opened; - - if (handler != null) - handler(this, e); - } - - /// - /// Raises the event. - /// - /// The instance containing the event data. - protected virtual void OnClosed(EventArgs e) - { - EventHandler handler = Closed; - - if (handler != null) - handler(this, e); - } - - /// - /// Add windows icons to the carousel. - /// - private void FillCarousel() - { - ClearCarousel(); - - Style style = this.WindowIconStyle ?? Application.Current.Resources["WindowIconStyle"] as Style; - foreach (var window in this.FloatingWindowHost.WindowsInIconBar) - { - WindowIcon icon = new WindowIcon() - { - Style = style, - Title = window.IconText, - Thumbnail = window.WindowThumbnail, - FlowDirection = window.FlowDirection, - Window = window, - IconWidth = this.FloatingWindowHost.IconWidth, - IconHeight = this.FloatingWindowHost.IconHeight - }; - - icon.Click += new RoutedEventHandler(Icon_Click); - carousel.Children.Add(icon); - } - } - - /// - /// Remove Icon Click event handlers and clear the carousel. - /// - private void ClearCarousel() - { - foreach (var icon in carousel.Children.OfType()) - { - icon.Click -= new RoutedEventHandler(Icon_Click); - } - - carousel.Children.Clear(); - } - - /// - /// Handles the Click event of the Icon control. - /// - /// The source of the event. - /// The instance containing the event data. - private void Icon_Click(object sender, RoutedEventArgs e) - { - WindowIcon icon = sender as WindowIcon; - - if (icon != null && icon.Window != null) - { - this.Hide(); - icon.Window.RestoreWindow(); - } - } - - /// - /// Handles the MouseMove event of the Bar control. It implements "Carousel" logic. - /// - /// The source of the event. - /// The instance containing the event data. - private void Bar_MouseMove(object sender, MouseEventArgs e) - { - // Get absolute mouse position - Point mousePosition = e.GetPosition(null); - - var icon = carousel.Children.OfType().FirstOrDefault(); - - // If there is at least one icon on the bar - if (icon != null) - { - double a = e.GetPosition(fixedBar).X; - double b = fixedBar.ActualWidth - fixedBar.Padding.Horizontal(); - double c = slidingBar.ActualWidth; - - // If sliding bar does not fit into the bar, shift the sliding bar - if (c > b) - { - double width = b - icon.ActualWidth; - if (width != 0) - { - a -= icon.ActualWidth / 2; - if (a < 0) a = 0; - if (a > width) a = width; - - double x = Math.Round((a / width) * (b - c)); - - if (x != slidingBarPosition) - { - Storyboard storyboard = slidingBar.AnimateDoubleProperty("(Canvas.Left)", null, x, SlidingDurationInMilliseconds); - storyboard.Completed += (s, args) => - { - // Select an icon on storyboard completion - // That is necessary because MouseOver state won't be proceeded correctly - SlidingBarStoryboardCompleted(mousePosition); - slidingBarPosition = x; - }; - } - } - } - } - } - - /// - /// Handles the Completed event of the SlidingBarStoryboard control. - /// - /// Absolute mouse position. - private void SlidingBarStoryboardCompleted(Point mousePosition) - { - // Find selected icon - var selectedIcon = (from item in visualHelper.FindElementsInCoordinates(mousePosition, carousel).OfType() - select item).FirstOrDefault(); - - // Select an icon in mouse position - foreach (var icon in carousel.Children.OfType()) - { - icon.Selected = selectedIcon != null && icon == selectedIcon; - } - } - - /// - /// Handles the SizeChanged event of the FixedBar control. - /// Sets the initial position of the sliding bar. - /// - /// The source of the event. - /// The instance containing the event data. - private void FixedBar_SizeChanged(object sender, SizeChangedEventArgs e) - { - if (slidingBarPosition != 0) - SetSlidingBarPosition(0); - } - - /// - /// Sets the sliding bar position. - /// - /// X-coordinate of the sliding bar. - private void SetSlidingBarPosition(double x) - { - slidingBarPosition = x; - Canvas.SetLeft(slidingBar, slidingBarPosition); - } - - /// - /// Gets the FrameworkElement template part with the specified name. - /// - /// The template part type. - /// The template part name. - /// The requested element. - /// The template part not found. - private T GetTemplatePart(string partName) where T : class - { - T part = this.GetTemplateChild(partName) as T; - - if (part == null) - throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "Template Part {0} is required.", partName)); - - return part; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/WindowIcon.cs --- a/SilverlightGlimpse/SilverFlow.Controls/FloatingWindow/WindowIcon.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -using System; -using System.Globalization; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using SilverFlow.Controls.Extensions; - -namespace SilverFlow.Controls -{ - /// - /// Window icon containing a thumbnail and title of the windows. - /// - [TemplatePart(Name = PART_Border, Type = typeof(Border))] - [TemplatePart(Name = PART_Title, Type = typeof(TextBlock))] - [TemplatePart(Name = PART_Thumbnail, Type = typeof(Image))] - [StyleTypedProperty(Property = PROPERTY_IconBorderStyle, StyleTargetType = typeof(Border))] - public class WindowIcon : Button - { - // Template parts - private const string PART_Border = "PART_Border"; - private const string PART_Title = "PART_Title"; - private const string PART_Thumbnail = "PART_Thumbnail"; - - // VSM states - private const string VSMSTATE_StateNormal = "Normal"; - private const string VSMSTATE_StateMouseOver = "MouseOver"; - - // Style typed properties - private const string PROPERTY_IconBorderStyle = "IconBorderStyle"; - - #region public Style IconBorderStyle - - /// - /// Gets or sets the style of the WindowIcon. - /// - public Style IconBorderStyle - { - get { return GetValue(IconBorderStyleProperty) as Style; } - set { SetValue(IconBorderStyleProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty IconBorderStyleProperty = - DependencyProperty.Register( - "IconBorderStyle", - typeof(Style), - typeof(WindowIcon), - new PropertyMetadata(IconBorderStylePropertyChanged)); - - /// - /// IconBorderStyle PropertyChangedCallback call back static function. - /// - /// WindowIcon object whose IconBorderStyle property is changed. - /// The instance containing the event data. - private static void IconBorderStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - WindowIcon windowIcon = (WindowIcon)d; - if (windowIcon != null && windowIcon.border != null) - { - windowIcon.border.Style = e.NewValue as Style; - } - } - - #endregion - - #region public double IconWidth - - /// - /// Gets or sets the width of the window's icon. - /// - /// The width of the window's icon. - public double IconWidth - { - get { return (double)GetValue(IconWidthProperty); } - set { SetValue(IconWidthProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty IconWidthProperty = - DependencyProperty.Register( - "IconWidth", - typeof(double), - typeof(WindowIcon), - null); - - #endregion - - #region public double IconHeight - - /// - /// Gets or sets the height of the window's icon. - /// - /// The height of the window's icon. - public double IconHeight - { - get { return (double)GetValue(IconHeightProperty); } - set { SetValue(IconHeightProperty, value); } - } - - /// - /// Identifies the dependency property. - /// - /// - /// The identifier for the dependency property. - /// - public static readonly DependencyProperty IconHeightProperty = - DependencyProperty.Register( - "IconHeight", - typeof(double), - typeof(WindowIcon), - null); - - #endregion - - private Border border; - private TextBlock title; - private Image thumbnail; - private bool selected; - - /// - /// Gets or sets the window title that is displayed on the icon />. - /// - /// The title displayed on the icon. - public string Title { get; set; } - - /// - /// Gets or sets the thumbnail. - /// - /// The thumbnail. - public ImageSource Thumbnail { get; set; } - - /// - /// Gets or sets the FloatingWindow associated with the icon. - /// - /// Floating window. - public FloatingWindow Window { get; set; } - - /// - /// Gets or sets a value indicating whether this is selected. - /// - /// true if selected; otherwise, false. - public bool Selected - { - get { return selected; } - set - { - if (value != selected) - { - selected = value; - VisualStateManager.GoToState( - this, - value ? VSMSTATE_StateMouseOver : VSMSTATE_StateNormal, - true); - } - } - } - - /// - /// Builds the visual tree for the control - /// when a new template is applied. - /// - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - - border = GetTemplatePart(PART_Border); - title = GetTemplatePart(PART_Title); - thumbnail = GetTemplatePart(PART_Thumbnail); - - SetStyles(); - - title.Text = Title; - title.FlowDirection = this.FlowDirection; - thumbnail.Source = Thumbnail; - } - - /// - /// Sets styles that are applied for different template parts. - /// - private void SetStyles() - { - if (border != null && this.IconBorderStyle != null) - border.Style = this.IconBorderStyle; - } - - /// - /// Gets the FrameworkElement template part with the specified name. - /// - /// The template part type. - /// The template part name. - /// The requested element. - /// The template part not found. - private T GetTemplatePart(string partName) where T : class - { - T part = this.GetTemplateChild(partName) as T; - - if (part == null) - throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "Template Part {0} is required.", partName)); - - return part; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Geometry/Distance.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Geometry/Distance.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -using SilverFlow.Controls.Extensions; - -namespace SilverFlow.Geometry -{ - /// - /// Defines displacement used for correction of window position or size. - /// - public class Distance - { - /// - /// Gets or sets displacement by X coordinate. - /// - /// Displacement by X coordinate. - public double X { get; set; } - - /// - /// Gets or sets displacement by Y coordinate. - /// - /// Displacement by Y coordinate. - public double Y { get; set; } - - /// - /// Gets a value indicating whether this instance is nonzero. - /// - /// - /// true if this instance is nonzero; otherwise, false. - /// - public bool IsNonzero - { - get - { - return !double.IsNaN(X) && !double.IsNaN(Y) && (X != 0 || Y != 0); - } - } - - /// - /// Initializes a new instance of the class. - /// - public Distance() - { - X = double.NaN; - Y = double.NaN; - } - - /// - /// Initializes a new instance of the class. - /// - /// Displacement by X coordinate. - /// Displacement by Y coordinate. - public Distance(double x, double y) - { - X = x; - Y = y; - } - - /// - /// Gets the smallest of two distances. - /// - /// First distance. - /// Second distance. - /// Smallest distance. - public static Distance Min(Distance first, Distance second) - { - Distance distance = new Distance - { - X = MathExtensions.AbsMin(first.X, second.X), - Y = MathExtensions.AbsMin(first.Y, second.Y) - }; - - return distance; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Geometry/Trail.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Geometry/Trail.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -using System; -using System.Windows; - -namespace SilverFlow.Geometry -{ - /// - /// Mouse pointer trail. - /// - public class Trail - { - /// - /// Gets or sets mouse position. - /// - /// The position. - public Point Position { get; set; } - - /// - /// Gets or sets the timestamp. - /// - /// The timestamp. - public DateTime Timestamp { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public Trail() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Point. - /// Time. - public Trail(Point point, DateTime time) - { - this.Position = point; - this.Timestamp = time; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Geometry/Vector2.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Geometry/Vector2.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -using System; -using System.Windows; -using SilverFlow.Controls.Extensions; - -namespace SilverFlow.Geometry -{ - /// - /// Defines two-dimensional vector. - /// - public class Vector2 - { - /// - /// Gets or sets the starting point of the vector. - /// - /// The starting point. - public Point Start { get; set; } - - /// - /// Gets or sets the ending point of the vector. - /// - /// The ending point. - public Point End { get; set; } - - /// - /// Gets a value indicating whether this instance is not set. - /// - /// true if this instance is not set; otherwise, false. - public bool IsNaN - { - get - { - return this.Start.IsNotSet() || this.End.IsNotSet(); - } - } - - /// - /// Gets a value indicating whether the vector is of zero length. - /// - /// true if the vector is of zero length; otherwise, false. - public bool IsZero - { - get - { - return this.IsNaN ? true : this.Start == this.End; - } - } - - /// - /// Gets a value indicating whether the vector is vertical. - /// - /// - /// true if the vector is vertical; otherwise, false. - /// - public bool IsVertical - { - get - { - return !this.IsZero && (this.Start.X == this.End.X); - } - } - - /// - /// Gets a value indicating whether the vector is horizontal. - /// - /// - /// true if the vector is horizontal; otherwise, false. - /// - public bool IsHorizontal - { - get - { - return !this.IsZero && (this.Start.Y == this.End.Y); - } - } - - /// - /// Gets the length of the vector by X-coordinate. - /// - /// The length by X-coordinate. - public double LengthX - { - get - { - return this.IsNaN ? 0 : (this.End.X - this.Start.X); - } - } - - /// - /// Gets the length of the vector by Y-coordinate. - /// - /// The length by Y-coordinate. - public double LengthY - { - get - { - return this.IsNaN ? 0 : (this.End.Y - this.Start.Y); - } - } - - /// - /// Gets the length of the vector. - /// - /// The length of the vector. - public double Length - { - get - { - if (this.IsNaN) - return 0; - - return Math.Sqrt(LengthX * LengthX + LengthY * LengthY); - } - } - - /// - /// Initializes a new instance of the class. - /// - public Vector2() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The starting point. - /// The ending point. - public Vector2(Point start, Point end) - { - this.Start = start; - this.End = end; - } - - /// - /// Initializes a new instance of the class. - /// - /// The starting point. - /// The length by X-coordinate. - /// The length by Y-coordinate. - public Vector2(Point start, double lengthX, double lengthY) - { - this.Start = start; - this.End = start.Add(lengthX, lengthY); - } - - /// - /// Rounds starting and ending points to the nearest integer coordinates. - /// - /// Vector with rounded coordinates. - public Vector2 Round() - { - this.Start = this.Start.Round(); - this.End = this.End.Round(); - return this; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Helpers/BitmapHelper.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Helpers/BitmapHelper.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using SilverFlow.Controls.Extensions; - -namespace SilverFlow.Controls.Helpers -{ - /// - /// Bitmap helper. - /// - public class BitmapHelper : IBitmapHelper - { - /// - /// Renders the visual element and returns a bitmap, containing bitmap image of the element. - /// - /// The visual element. - /// Image width. - /// Image height. - /// Bitmap image of the element. - public ImageSource RenderVisual(FrameworkElement element, double imageWidth, double imageHeight) - { - int width = element.Width.IsNotSet() ? (int)element.ActualWidth : (int)element.Width; - int height = element.Height.IsNotSet() ? (int)element.ActualHeight : (int)element.Height; - - ScaleTransform transform = null; - - // If the element is an image - do not scale it - if (!(element is Image)) - { - // Scale down the element to fit it into the window's thumbnail - double scaleX = imageWidth / width; - double scaleY = imageHeight / height; - double minScale = Math.Min(scaleX, scaleY); - - if (minScale < 1) - { - transform = new ScaleTransform - { - ScaleX = minScale, - ScaleY = minScale - }; - - width = (int)(width * minScale); - height = (int)(height * minScale); - } - } - - WriteableBitmap bitmap = new WriteableBitmap(width, height); - bitmap.Render(element, transform); - bitmap.Invalidate(); - - return bitmap; - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Helpers/IBitmapHelper.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Helpers/IBitmapHelper.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -using System.Windows; -using System.Windows.Media; - -namespace SilverFlow.Controls.Helpers -{ - /// - /// This interface defines methods used the create bitmap images. - /// - public interface IBitmapHelper - { - /// - /// Renders the visual element and returns a bitmap, containing bitmap image of the element. - /// - /// The visual element. - /// Image width. - /// Image height. - /// Bitmap image of the element. - ImageSource RenderVisual(FrameworkElement element, double imageWidth, double imageHeight); - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Helpers/ILocalStorage.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Helpers/ILocalStorage.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -namespace SilverFlow.Controls.Helpers -{ - /// - /// This interface defines isolated storage methods and properties. - /// - public interface ILocalStorage - { - /// - /// Gets or saves the value associated with the specified key. - /// - /// The value associated with the specified key. - object this[string key] { get; set; } - - /// - /// Determines if the local storage contains the specified key. - /// - /// The key for the entry to be located. - /// True if the local storage contains the specified key; otherwise, false. - bool Contains(string key); - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Helpers/IVisualHelper.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Helpers/IVisualHelper.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using System.Windows; - -namespace SilverFlow.Controls.Helpers -{ - /// - /// This interface defines methods used to traverse object relationships - /// in the visual tree. - /// - public interface IVisualHelper - { - /// - /// Retrieves a set of objects that are located within a specified point of an object's coordinate space. - /// - /// The point to use as the determination point. - /// The object to search within. - /// - /// An enumerable set of System.Windows.UIElement objects that are determined - /// to be located in the visual tree composition at the specified point and within - /// the specified subtee. - /// - IEnumerable FindElementsInCoordinates(Point intersectingPoint, UIElement subtree); - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Helpers/LocalStorage.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Helpers/LocalStorage.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -using System.IO.IsolatedStorage; - -namespace SilverFlow.Controls.Helpers -{ - /// - /// Local isolated storage. - /// - public class LocalStorage : ILocalStorage - { - /// - /// Gets or saves the value associated with the specified key. - /// - /// The value associated with the specified key. - public object this[string key] - { - get - { - return IsolatedStorageSettings.ApplicationSettings[key]; - } - set - { - IsolatedStorageSettings.ApplicationSettings[key] = value; - } - } - - /// - /// Determines if the local storage contains the specified key. - /// - /// The key for the entry to be located. - /// - /// True if the local storage contains the specified key; otherwise, false. - /// - public bool Contains(string key) - { - return IsolatedStorageSettings.ApplicationSettings.Contains(key); - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Helpers/VisualHelper.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Helpers/VisualHelper.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using System.Windows; -using System.Windows.Media; - -namespace SilverFlow.Controls.Helpers -{ - public class VisualHelper : IVisualHelper - { - /// - /// Retrieves a set of objects that are located within a specified point of an object's coordinate space. - /// - /// The point to use as the determination point. - /// The object to search within. - /// - /// An enumerable set of System.Windows.UIElement objects that are determined - /// to be located in the visual tree composition at the specified point and within - /// the specified subtee. - /// - public IEnumerable FindElementsInCoordinates(Point intersectingPoint, UIElement subtree) - { - return VisualTreeHelper.FindElementsInHostCoordinates(intersectingPoint, subtree); - } - } -} diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Properties/AssemblyInfo.cs --- a/SilverlightGlimpse/SilverFlow.Controls/Properties/AssemblyInfo.cs Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -// 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("SilverFlow.Controls")] -[assembly: AssemblyDescription("FloatingWindow Control Library for Silverlight")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Jevgenij Pankov")] -[assembly: AssemblyProduct("SilverFlow.Controls")] -[assembly: AssemblyCopyright("Copyright © 2011")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] -[assembly: CLSCompliant(true)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("00b61972-c1f0-47b6-8507-872060367303")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("2.0.2")] -[assembly: AssemblyFileVersion("2.0.2")] diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/SilverFlow.Controls.csproj --- a/SilverlightGlimpse/SilverFlow.Controls/SilverFlow.Controls.csproj Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ - - - - Debug - AnyCPU - 8.0.50727 - 2.0 - {3F3D3C8C-9724-4531-A04D-B92049F64686} - {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - SilverFlow.Controls - SilverFlow.Controls - Silverlight - v4.0 - $(TargetFrameworkVersion) - false - true - true - true - 4.0.20525.0 - - - - v3.5 - - - true - full - false - Bin\Debug - DEBUG;TRACE;SILVERLIGHT - true - true - prompt - 4 - false - BasicCorrectnessRules.ruleset - - - pdbonly - true - Bin\Release - TRACE;SILVERLIGHT - true - true - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - - - - - - - - - - - - - - MSBuild:Compile - Designer - - - - - - - - - - - - - \ No newline at end of file diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverFlow.Controls/Themes/generic.xaml --- a/SilverlightGlimpse/SilverFlow.Controls/Themes/generic.xaml Mon Apr 23 11:05:11 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,787 +0,0 @@ - - - - #FF9E9E9E - #FFd1d9e1 - White - White - #FF899199 - #FF0667D4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse.Test/App.xaml.cs --- a/SilverlightGlimpse/SilverlightGlimpse.Test/App.xaml.cs Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/SilverlightGlimpse.Test/App.xaml.cs Mon Apr 23 11:06:10 2012 +0100 @@ -1,8 +1,6 @@ using System; using System.Windows; using SilverlightGlimpse.Services; -//using Glimpse; -using System.Reflection; namespace SilverlightGlimpse.Test { @@ -19,14 +17,15 @@ private void Application_Startup(object sender, StartupEventArgs e) { + var appName = "Silverlight Glimpse"; try { RootVisual = new MainPage(); - GlimpseService.CreateInstance.Load(this, "Silverlight Glimpse"); + Glimpse.Service.Load(this, appName); } catch (Exception ex) { - GlimpseService.CreateInstance.DisplayLoadFailure(this, ex); + Glimpse.Service.DisplayLoadFailure(this, ex, appName); } } @@ -67,4 +66,4 @@ } } } -} +} \ No newline at end of file diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse.Test/MainPage.xaml.cs --- a/SilverlightGlimpse/SilverlightGlimpse.Test/MainPage.xaml.cs Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/SilverlightGlimpse.Test/MainPage.xaml.cs Mon Apr 23 11:06:10 2012 +0100 @@ -1,6 +1,14 @@ using System; -using System.Collections.Generic; +using System.Linq; +using System.Net; using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; +using System.Windows.Navigation; namespace SilverlightGlimpse.Test { @@ -9,7 +17,6 @@ public MainPage() { InitializeComponent(); - // uncomment this exception to view exception on startup //ThrowNestedException(); @@ -21,7 +28,7 @@ new Person { Id = 4 , Name = "Rich"}, new Person { Id = 5 , Name = "Clare"} }; - + listbox1.ItemsSource = list; } diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse.Test/SilverlightGlimpse.Test.csproj --- a/SilverlightGlimpse/SilverlightGlimpse.Test/SilverlightGlimpse.Test.csproj Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/SilverlightGlimpse.Test/SilverlightGlimpse.Test.csproj Mon Apr 23 11:06:10 2012 +0100 @@ -67,6 +67,7 @@ + @@ -84,10 +85,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - @@ -101,6 +98,12 @@ + + + Designer + MSBuild:Compile + + diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse/Controls/BrokenBindingsViewer.xaml.cs --- a/SilverlightGlimpse/SilverlightGlimpse/Controls/BrokenBindingsViewer.xaml.cs Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/SilverlightGlimpse/Controls/BrokenBindingsViewer.xaml.cs Mon Apr 23 11:06:10 2012 +0100 @@ -16,9 +16,8 @@ private void BrokenBindings_Loaded(object sender, RoutedEventArgs e) { - //icBrokenBindings.Items.Clear(); lbBindings.Items.Clear(); - LoadBrokenBindings(GlimpseService.CreateInstance.RootVisual); + LoadBrokenBindings(Glimpse.Service.RootVisual); } private void LoadBrokenBindings(UIElement uiElement) @@ -44,14 +43,14 @@ if (string.Compare(propertyInfo.Name, bindingExpression.ParentBinding.Path.Path) == 0) { isInherited = true; - break; // TODO: might not be correct. Was : Exit For + break; } } } if (isInherited) { - break; // TODO: might not be correct. Was : Exit For + break; } //this code handles empty bindings on the Button controls @@ -61,7 +60,7 @@ && fieldInfo.Name == "TextProperty" && string.IsNullOrEmpty(bindingExpression.ParentBinding.Path.Path)) { - break; // TODO: might not be correct. Was : Exit For + break; } var brokenBinding = new BrokenBinding( @@ -70,7 +69,6 @@ fieldInfo.Name, bindingExpression.ParentBinding.Path.Path); - //icBrokenBindings.Items.Add(brokenBinding); lbBindings.Items.Add(brokenBinding); Debug.WriteLine("Broken Binding: {0}", brokenBinding); } diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse/Controls/ExceptionsViewer.xaml --- a/SilverlightGlimpse/SilverlightGlimpse/Controls/ExceptionsViewer.xaml Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/SilverlightGlimpse/Controls/ExceptionsViewer.xaml Mon Apr 23 11:06:10 2012 +0100 @@ -37,60 +37,58 @@ Margin="3.5" DataContext="{Binding ElementName=lbExceptions, Path=SelectedItem}"> - + - - - - - - - + - - - - - - - diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse/Controls/ExceptionsViewer.xaml.cs --- a/SilverlightGlimpse/SilverlightGlimpse/Controls/ExceptionsViewer.xaml.cs Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/SilverlightGlimpse/Controls/ExceptionsViewer.xaml.cs Mon Apr 23 11:06:10 2012 +0100 @@ -14,24 +14,21 @@ private void ClearExceptions_Click(object sender, RoutedEventArgs e) { - GlimpseService.CreateInstance.HostExceptions.Clear(); + Glimpse.Service.Exceptions.Clear(); } private void ExceptionsViewer_Loaded(object sender, RoutedEventArgs e) { - DataContext = GlimpseService.CreateInstance.HostExceptions; - if (GlimpseService.CreateInstance.HostExceptions.Count > 0) + DataContext = Glimpse.Service.Exceptions; + if (Glimpse.Service.Exceptions.Count > 0) lbExceptions.SelectedIndex = 0; } private void lbExceptions_SelectionChanged(object sender, SelectionChangedEventArgs e) { - if (lbExceptions.SelectedItem == null || !(lbExceptions.SelectedItem is ExceptionWrapper)) - return; - - tbAction.Visibility = ((ExceptionWrapper)lbExceptions.SelectedItem).IsValidationException - ? Visibility.Visible - : Visibility.Collapsed; + gridExceptionDetail.Visibility = lbExceptions.SelectedItem == null + ? Visibility.Collapsed + : Visibility.Visible; } } } \ No newline at end of file diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse/Controls/FloatableWindow/FloatableWindow.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SilverlightGlimpse/SilverlightGlimpse/Controls/FloatableWindow/FloatableWindow.cs Mon Apr 23 11:06:10 2012 +0100 @@ -0,0 +1,1623 @@ +// Original code: http://floatablewindow.codeplex.com/ +// Author: Tim Heuer http://timheuer.com/blog/ + +// This source is subject to the Microsoft Public License (Ms-PL). +// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. +// All other rights reserved. + +using System.Collections; +using System.ComponentModel; +using System.Diagnostics; +using System.Windows.Automation; +using System.Windows.Automation.Peers; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; + +namespace System.Windows.Controls +{ + /// + /// Provides a window that can be displayed over a parent window and blocks + /// interaction with the parent window. + /// + /// Preview + [TemplatePart(Name = PART_Chrome, Type = typeof(FrameworkElement))] + [TemplatePart(Name = PART_CloseButton, Type = typeof(ButtonBase))] + [TemplatePart(Name = PART_ContentPresenter, Type = typeof(FrameworkElement))] + [TemplatePart(Name = PART_ContentRoot, Type = typeof(FrameworkElement))] + [TemplatePart(Name = PART_Overlay, Type = typeof(Panel))] + [TemplatePart(Name = PART_Root, Type = typeof(FrameworkElement))] + [TemplateVisualState(Name = VSMSTATE_StateClosed, GroupName = VSMGROUP_Window)] + [TemplateVisualState(Name = VSMSTATE_StateOpen, GroupName = VSMGROUP_Window)] + public class FloatableWindow : ContentControl + { + #region Static Fields and Constants + + /// + /// The name of the Chrome template part. + /// + private const string PART_Chrome = "Chrome"; + + /// + /// The name of the CloseButton template part. + /// + private const string PART_CloseButton = "CloseButton"; + + /// + /// The name of the ContentPresenter template part. + /// + private const string PART_ContentPresenter = "ContentPresenter"; + + /// + /// The name of the ContentRoot template part. + /// + private const string PART_ContentRoot = "ContentRoot"; + + /// + /// The name of the Overlay template part. + /// + private const string PART_Overlay = "Overlay"; + + /// + /// The name of the Root template part. + /// + private const string PART_Root = "Root"; + + /// + /// The name of the WindowStates VSM group. + /// + private const string VSMGROUP_Window = "WindowStates"; + + /// + /// The name of the Closing VSM state. + /// + private const string VSMSTATE_StateClosed = "Closed"; + + /// + /// The name of the Opening VSM state. + /// + private const string VSMSTATE_StateOpen = "Open"; + + #region public bool HasCloseButton + + /// + /// Gets or sets a value indicating whether the + /// has a close + /// button. + /// + /// + /// True if the child window has a close button; otherwise, false. The + /// default is true. + /// + public bool HasCloseButton + { + get { return (bool)GetValue(HasCloseButtonProperty); } + set { SetValue(HasCloseButtonProperty, value); } + } + + /// + /// Identifies the + /// + /// dependency property. + /// + /// + /// The identifier for the + /// + /// dependency property. + /// + public static readonly DependencyProperty HasCloseButtonProperty = + DependencyProperty.Register( + "HasCloseButton", + typeof(bool), + typeof(FloatableWindow), + new PropertyMetadata(true, OnHasCloseButtonPropertyChanged)); + + /// + /// HasCloseButtonProperty PropertyChangedCallback call back static function. + /// + /// FloatableWindow object whose HasCloseButton property is changed. + /// DependencyPropertyChangedEventArgs which contains the old and new values. + private static void OnHasCloseButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + FloatableWindow cw = (FloatableWindow)d; + + if (cw.CloseButton != null) + { + if ((bool)e.NewValue) + { + cw.CloseButton.Visibility = Visibility.Visible; + } + else + { + cw.CloseButton.Visibility = Visibility.Collapsed; + } + } + } + + #endregion public bool HasCloseButton + + #region public Brush OverlayBrush + + /// + /// Gets or sets the visual brush that is used to cover the parent + /// window when the child window is open. + /// + /// + /// The visual brush that is used to cover the parent window when the + /// is open. The + /// default is null. + /// + public Brush OverlayBrush + { + get { return (Brush)GetValue(OverlayBrushProperty); } + set { SetValue(OverlayBrushProperty, value); } + } + + /// + /// Identifies the + /// + /// dependency property. + /// + /// + /// The identifier for the + /// + /// dependency property. + /// + public static readonly DependencyProperty OverlayBrushProperty = + DependencyProperty.Register( + "OverlayBrush", + typeof(Brush), + typeof(FloatableWindow), + new PropertyMetadata(OnOverlayBrushPropertyChanged)); + + /// + /// OverlayBrushProperty PropertyChangedCallback call back static function. + /// + /// FloatableWindow object whose OverlayBrush property is changed. + /// DependencyPropertyChangedEventArgs which contains the old and new values. + private static void OnOverlayBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + FloatableWindow cw = (FloatableWindow)d; + + if (cw.Overlay != null) + { + cw.Overlay.Background = (Brush)e.NewValue; + } + } + + #endregion public Brush OverlayBrush + + #region public double OverlayOpacity + + /// + /// Gets or sets the opacity of the overlay brush that is used to cover + /// the parent window when the child window is open. + /// + /// + /// The opacity of the overlay brush that is used to cover the parent + /// window when the + /// is open. The default is 1.0. + /// + public double OverlayOpacity + { + get { return (double)GetValue(OverlayOpacityProperty); } + set { SetValue(OverlayOpacityProperty, value); } + } + + /// + /// Identifies the + /// + /// dependency property. + /// + /// + /// The identifier for the + /// + /// dependency property. + /// + public static readonly DependencyProperty OverlayOpacityProperty = + DependencyProperty.Register( + "OverlayOpacity", + typeof(double), + typeof(FloatableWindow), + new PropertyMetadata(OnOverlayOpacityPropertyChanged)); + + /// + /// OverlayOpacityProperty PropertyChangedCallback call back static function. + /// + /// FloatableWindow object whose OverlayOpacity property is changed. + /// DependencyPropertyChangedEventArgs which contains the old and new values. + private static void OnOverlayOpacityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + FloatableWindow cw = (FloatableWindow)d; + + if (cw.Overlay != null) + { + cw.Overlay.Opacity = (double)e.NewValue; + } + } + + #endregion public double OverlayOpacity + + #region private static Control RootVisual + + /// + /// Gets the root visual element. + /// + private static Control RootVisual + { + get + { + return Application.Current == null ? null : (Application.Current.RootVisual as Control); + } + } + + #endregion private static Control RootVisual + + #region public object Title + + /// + /// Gets or sets the title that is displayed in the frame of the + /// . + /// + /// + /// The title displayed at the top of the window. The default is null. + /// + public object Title + { + get { return GetValue(TitleProperty); } + set { SetValue(TitleProperty, value); } + } + + /// + /// Identifies the + /// + /// dependency property. + /// + /// + /// The identifier for the + /// + /// dependency property. + /// + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register( + "Title", + typeof(object), + typeof(FloatableWindow), + null); + + #endregion public object Title + + #endregion Static Fields and Constants + + #region Member Fields + /// + /// Set in the overloaded Show method. Offsets the Popup vertically from the top left corner of the browser window by this amount. + /// + private double _verticalOffset; + + /// + /// Set in the overloaded Show method. Offsets the Popup horizontally from the top left corner of the browser window by this amount. + /// + private double _horizontalOffset; + + /// + /// Private accessor for the Resizer. + /// + private FrameworkElement _resizer; + + /// + /// Private accessor for the IsModal + /// + [DefaultValue(false)] + private bool _modal; + + /// + /// Private accessor for the Chrome. + /// + private FrameworkElement _chrome; + + /// + /// Private accessor for the click point on the chrome. + /// + private Point _clickPoint; + + /// + /// Private accessor for the Closing storyboard. + /// + private Storyboard _closed; + + /// + /// Private accessor for the ContentPresenter. + /// + private FrameworkElement _contentPresenter; + + /// + /// Private accessor for the translate transform that needs to be applied on to the ContentRoot. + /// + private TranslateTransform _contentRootTransform; + + /// + /// Content area desired width. + /// + private double _desiredContentWidth; + + /// + /// Content area desired height. + /// + private double _desiredContentHeight; + + /// + /// Desired margin for the window. + /// + private Thickness _desiredMargin; + + /// + /// Private accessor for the Dialog Result property. + /// + private bool? _dialogresult; + + /// + /// Private accessor for the FloatableWindow InteractionState. + /// + private WindowInteractionState _interactionState; + + /// + /// Boolean value that specifies whether the application is exit or not. + /// + private bool _isAppExit; + + /// + /// Boolean value that specifies whether the window is in closing state or not. + /// + private bool _isClosing; + + /// + /// Boolean value that specifies whether the window is opened. + /// + private bool _isOpen; + + /// + /// Private accessor for the Opening storyboard. + /// + private Storyboard _opened; + + /// + /// Boolean value that specifies whether the mouse is captured or not. + /// + private bool _isMouseCaptured; + + /// + /// Private accessor for the Root of the window. + /// + private FrameworkElement _root; + + /// + /// Private accessor for the position of the window with respect to RootVisual. + /// + private Point _windowPosition; + + private static int z; + + #endregion Member Fields + + #region Constructors + + /// + /// Initializes a new instance of the + /// class. + /// + public FloatableWindow() + { + this.DefaultStyleKey = typeof(FloatableWindow); + this.InteractionState = WindowInteractionState.NotResponding; + } + + #endregion Constructors + + #region Events + + /// + /// Occurs when the + /// is closed. + /// + public event EventHandler Closed; + + /// + /// Occurs when the + /// is closing. + /// + public event EventHandler Closing; + + #endregion Events + + #region Properties + + private Panel _parentLayoutRoot; + public Panel ParentLayoutRoot + { + get { return _parentLayoutRoot; } + set { _parentLayoutRoot = value; } + } + + /// + /// Gets the internal accessor for the ContentRoot of the window. + /// + internal FrameworkElement ContentRoot + { + get; + private set; + } + + /// + /// Setting for the horizontal positioning offset for start position + /// + public double HorizontalOffset + { + get { return _horizontalOffset; } + set { _horizontalOffset = value; } + } + + /// + /// Setting for the vertical positioning offset for start position + /// + public double VerticalOffset + { + get { return _verticalOffset; } + set { _verticalOffset = value; } + } + + /// + /// Gets the internal accessor for the modal of the window. + /// + public bool IsModal + { + get + { + return _modal; + } + } + + /// + /// Gets or sets a value indicating whether the + /// was accepted or + /// canceled. + /// + /// + /// True if the child window was accepted; false if the child window was + /// canceled. The default is null. + /// + [TypeConverter(typeof(NullableBoolConverter))] + public bool? DialogResult + { + get + { + return this._dialogresult; + } + + set + { + if (this._dialogresult != value) + { + this._dialogresult = value; + this.Close(); + } + } + } + + /// + /// Gets the internal accessor for the PopUp of the window. + /// + internal Popup ChildWindowPopup + { + get; + private set; + } + + /// + /// Gets the internal accessor for the close button of the window. + /// + internal ButtonBase CloseButton + { + get; + private set; + } + + /// + /// Gets the InteractionState for the FloatableWindow. + /// + internal WindowInteractionState InteractionState + { + get + { + return this._interactionState; + } + private set + { + if (this._interactionState != value) + { + WindowInteractionState oldValue = this._interactionState; + this._interactionState = value; + FloatableWindowAutomationPeer peer = FloatableWindowAutomationPeer.FromElement(this) as FloatableWindowAutomationPeer; + + if (peer != null) + { + peer.RaiseInteractionStatePropertyChangedEvent(oldValue, this._interactionState); + } + } + } + } + + /// + /// Gets a value indicating whether the PopUp is open or not. + /// + private bool IsOpen + { + get + { + return (this.ChildWindowPopup != null && this.ChildWindowPopup.IsOpen) || + ((ParentLayoutRoot != null) && (ParentLayoutRoot.Children.Contains(this))); + } + } + + /// + /// Gets the internal accessor for the overlay of the window. + /// + internal Panel Overlay + { + get; + private set; + } + + #endregion Properties + + #region Static Methods + + /// + /// Inverts the input matrix. + /// + /// The matrix values that is to be inverted. + /// Returns a value indicating whether the inversion was successful or not. + private static bool InvertMatrix(ref Matrix matrix) + { + double determinant = (matrix.M11 * matrix.M22) - (matrix.M12 * matrix.M21); + + if (determinant == 0.0) + { + return false; + } + + Matrix matCopy = matrix; + matrix.M11 = matCopy.M22 / determinant; + matrix.M12 = -1 * matCopy.M12 / determinant; + matrix.M21 = -1 * matCopy.M21 / determinant; + matrix.M22 = matCopy.M11 / determinant; + matrix.OffsetX = ((matCopy.OffsetY * matCopy.M21) - (matCopy.OffsetX * matCopy.M22)) / determinant; + matrix.OffsetY = ((matCopy.OffsetX * matCopy.M12) - (matCopy.OffsetY * matCopy.M11)) / determinant; + + return true; + } + + #endregion Static Methods + + #region Methods + + /// + /// Executed when the application is exited. + /// + /// The sender. + /// Event args. + internal void Application_Exit(object sender, EventArgs e) + { + if (this.IsOpen) + { + this._isAppExit = true; + try + { + this.Close(); + } + finally + { + this._isAppExit = false; + } + } + } + + /// + /// Executed when focus is given to the window via a click. Attempts to bring current + /// window to the front in the event there are more windows. + /// + internal void BringToFront() + { + z++; + Canvas.SetZIndex(this, z); +#if DEBUG + this.Title = z.ToString(); +#endif + } + + /// + /// Changes the visual state of the FloatableWindow. + /// + private void ChangeVisualState() + { + if (this._isClosing) + { + VisualStateManager.GoToState(this, VSMSTATE_StateClosed, true); + } + else + { + VisualStateManager.GoToState(this, VSMSTATE_StateOpen, true); + BringToFront(); + } + } + + /// + /// Executed when FloatableWindow size is changed. + /// + /// Sender object. + /// Size changed event args. + private void ChildWindow_SizeChanged(object sender, SizeChangedEventArgs e) + { + if (_modal) + { + if (this.Overlay != null) + { + if (e.NewSize.Height != this.Overlay.Height) + { + this._desiredContentHeight = e.NewSize.Height; + } + + if (e.NewSize.Width != this.Overlay.Width) + { + this._desiredContentWidth = e.NewSize.Width; + } + } + + if (this.IsOpen) + { + this.UpdateOverlaySize(); + } + } + } + + /// + /// Closes a . + /// + public void Close() + { + // AutomationPeer returns "Closing" when Close() is called + // but the window is not closed completely: + this.InteractionState = WindowInteractionState.Closing; + CancelEventArgs e = new CancelEventArgs(); + this.OnClosing(e); + + // On ApplicationExit, close() cannot be cancelled + if (!e.Cancel || this._isAppExit) + { + if (RootVisual != null) + { + RootVisual.IsEnabled = true; + } + + // Close Popup + if (this.IsOpen) + { + if (this._closed != null) + { + // Popup will be closed when the storyboard ends + this._isClosing = true; + try + { + var sb = GetVisualStateStoryboard("WindowStates", "Closed"); + sb.Completed += (s, args) => + { + this.ParentLayoutRoot.Children.Remove(this); + this.OnClosed(EventArgs.Empty); + this.UnSubscribeFromEvents(); + this.UnsubscribeFromTemplatePartEvents(); + + if (Application.Current.RootVisual != null) + { + Application.Current.RootVisual.GotFocus -= new RoutedEventHandler(this.RootVisual_GotFocus); + } + }; + this.ChangeVisualState(); + } + finally + { + this._isClosing = false; + } + } + else + { + // If no closing storyboard is defined, close the Popup + this.ChildWindowPopup.IsOpen = false; + } + + if (!this._dialogresult.HasValue) + { + // If close action is not happening because of DialogResult property change action, + // Dialogresult is always false: + this._dialogresult = false; + } + + //this.OnClosed(EventArgs.Empty); + //this.UnSubscribeFromEvents(); + //this.UnsubscribeFromTemplatePartEvents(); + + //if (Application.Current.RootVisual != null) + //{ + // Application.Current.RootVisual.GotFocus -= new RoutedEventHandler(this.RootVisual_GotFocus); + //} + } + } + else + { + // If the Close is cancelled, DialogResult should always be NULL: + this._dialogresult = null; + this.InteractionState = WindowInteractionState.Running; + } + } + + /// + /// Brings the window to the front of others + /// + /// + /// + internal void ContentRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + BringToFront(); + } + + /// + /// Executed when the CloseButton is clicked. + /// + /// Sender object. + /// Routed event args. + internal void CloseButton_Click(object sender, RoutedEventArgs e) + { + this.Close(); + } + + /// + /// Executed when the Closing storyboard ends. + /// + /// Sender object. + /// Event args. + private void Closing_Completed(object sender, EventArgs e) + { + if (this.ChildWindowPopup != null) + { + this.ChildWindowPopup.IsOpen = false; + } + + // AutomationPeer returns "NotResponding" when the FloatableWindow is closed: + this.InteractionState = WindowInteractionState.NotResponding; + + if (this._closed != null) + { + this._closed.Completed -= new EventHandler(this.Closing_Completed); + } + } + + /// + /// Executed when the a key is presses when the window is open. + /// + /// Sender object. + /// Key event args. + private void ChildWindow_KeyDown(object sender, KeyEventArgs e) + { + FloatableWindow ew = sender as FloatableWindow; + Debug.Assert(ew != null, "FloatableWindow instance is null."); + + // Ctrl+Shift+F4 closes the FloatableWindow + if (e != null && !e.Handled && e.Key == Key.F4 && + ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) && + ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)) + { + ew.Close(); + e.Handled = true; + } + } + + /// + /// Executed when the window loses focus. + /// + /// Sender object. + /// Routed event args. + private void ChildWindow_LostFocus(object sender, RoutedEventArgs e) + { + // If the FloatableWindow loses focus but the popup is still open, + // it means another popup is opened. To get the focus back when the + // popup is closed, we handle GotFocus on the RootVisual + // TODO: Something else could get focus and handle the GotFocus event right. + // Try listening to routed events that were Handled (new SL 3 feature) + // Blocked by Jolt bug #29419 + if (this.IsOpen && Application.Current != null && Application.Current.RootVisual != null) + { + this.InteractionState = WindowInteractionState.BlockedByModalWindow; + Application.Current.RootVisual.GotFocus += new RoutedEventHandler(this.RootVisual_GotFocus); + } + } + + /// + /// Executed when mouse left button is down on the chrome. + /// + /// Sender object. + /// Mouse button event args. + private void Chrome_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + if (this._chrome != null) + { + e.Handled = true; + + if (this.CloseButton != null && !this.CloseButton.IsTabStop) + { + this.CloseButton.IsTabStop = true; + try + { + this.Focus(); + } + finally + { + this.CloseButton.IsTabStop = false; + } + } + else + { + this.Focus(); + } + this._chrome.CaptureMouse(); + this._isMouseCaptured = true; + this._clickPoint = e.GetPosition(sender as UIElement); +#if DEBUG + this.Title = string.Format("X:{0},Y:{1}", this._clickPoint.X.ToString(), this._clickPoint.Y.ToString()); +#endif + } + } + + /// + /// Executed when mouse left button is up on the chrome. + /// + /// Sender object. + /// Mouse button event args. + private void Chrome_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + if (this._chrome != null) + { + //e.Handled = true; + this._chrome.ReleaseMouseCapture(); + this._isMouseCaptured = false; + } + } + + /// + /// Executed when mouse moves on the chrome. + /// + /// Sender object. + /// Mouse event args. + private void Chrome_MouseMove(object sender, MouseEventArgs e) + { + #region New ChildWindow Code not working + //if (this._isMouseCaptured && this.ContentRoot != null && Application.Current != null && Application.Current.RootVisual != null) + //{ + // Point position = e.GetPosition(Application.Current.RootVisual); + + // GeneralTransform gt = this.ContentRoot.TransformToVisual(Application.Current.RootVisual); + + // if (gt != null) + // { + // Point p = gt.Transform(this._clickPoint); + // this._windowPosition = gt.Transform(new Point(0, 0)); + + // if (position.X < 0) + // { + // double Y = FindPositionY(p, position, 0); + // position = new Point(0, Y); + // } + + // if (position.X > this.Width) + // { + // double Y = FindPositionY(p, position, this.Width); + // position = new Point(this.Width, Y); + // } + + // if (position.Y < 0) + // { + // double X = FindPositionX(p, position, 0); + // position = new Point(X, 0); + // } + + // if (position.Y > this.Height) + // { + // double X = FindPositionX(p, position, this.Height); + // position = new Point(X, this.Height); + // } + + // double x = position.X - p.X; + // double y = position.Y - p.Y; + // UpdateContentRootTransform(x, y); + // } + //} + #endregion + if (this._isMouseCaptured && this.ContentRoot != null) + { + // If the child window is dragged out of the page, return + if (Application.Current != null && Application.Current.RootVisual != null && + (e.GetPosition(Application.Current.RootVisual).X < 0 || e.GetPosition(Application.Current.RootVisual).Y < 0)) + { + return; + } + + TransformGroup transformGroup = this.ContentRoot.RenderTransform as TransformGroup; + + if (transformGroup == null) + { + transformGroup = new TransformGroup(); + transformGroup.Children.Add(this.ContentRoot.RenderTransform); + } + + TranslateTransform t = new TranslateTransform(); + t.X = e.GetPosition(this.ContentRoot).X - this._clickPoint.X; + t.Y = e.GetPosition(this.ContentRoot).Y - this._clickPoint.Y; + if (transformGroup != null) + { + transformGroup.Children.Add(t); + this.ContentRoot.RenderTransform = transformGroup; + } + } + } + + /// + /// Finds the X coordinate of a point that is defined by a line. + /// + /// Starting point of the line. + /// Ending point of the line. + /// Y coordinate of the point. + /// X coordinate of the point. + private static double FindPositionX(Point p1, Point p2, double y) + { + if (y == p1.Y || p1.X == p2.X) + { + return p2.X; + } + + Debug.Assert(p1.Y != p2.Y, "Unexpected equal Y coordinates"); + + return (((y - p1.Y) * (p1.X - p2.X)) / (p1.Y - p2.Y)) + p1.X; + } + + /// + /// Finds the Y coordinate of a point that is defined by a line. + /// + /// Starting point of the line. + /// Ending point of the line. + /// X coordinate of the point. + /// Y coordinate of the point. + private static double FindPositionY(Point p1, Point p2, double x) + { + if (p1.Y == p2.Y || x == p1.X) + { + return p2.Y; + } + + Debug.Assert(p1.X != p2.X, "Unexpected equal X coordinates"); + + return (((p1.Y - p2.Y) * (x - p1.X)) / (p1.X - p2.X)) + p1.Y; + } + + /// + /// Builds the visual tree for the + /// control when a + /// new template is applied. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "No need to split the code into two parts.")] + public override void OnApplyTemplate() + { + this.UnsubscribeFromTemplatePartEvents(); + + base.OnApplyTemplate(); + + this.CloseButton = GetTemplateChild(PART_CloseButton) as ButtonBase; + + if (this.CloseButton != null) + { + if (this.HasCloseButton) + { + this.CloseButton.Visibility = Visibility.Visible; + } + else + { + this.CloseButton.Visibility = Visibility.Collapsed; + } + } + + if (this._closed != null) + { + this._closed.Completed -= new EventHandler(this.Closing_Completed); + } + + if (this._opened != null) + { + this._opened.Completed -= new EventHandler(this.Opening_Completed); + } + + this._root = GetTemplateChild(PART_Root) as FrameworkElement; + + if (this._root != null) + { + IList groups = VisualStateManager.GetVisualStateGroups(this._root); + + if (groups != null) + { + IList states = null; + + foreach (VisualStateGroup vsg in groups) + { + if (vsg.Name == FloatableWindow.VSMGROUP_Window) + { + states = vsg.States; + break; + } + } + + if (states != null) + { + foreach (VisualState state in states) + { + if (state.Name == FloatableWindow.VSMSTATE_StateClosed) + { + this._closed = state.Storyboard; + } + + if (state.Name == FloatableWindow.VSMSTATE_StateOpen) + { + this._opened = state.Storyboard; + } + } + } + } + //TODO: Figure out why I can't wire up the event below in SubscribeToTemplatePartEvents + this._root.MouseLeftButtonDown += new MouseButtonEventHandler(this.ContentRoot_MouseLeftButtonDown); + } + + this.ContentRoot = GetTemplateChild(PART_ContentRoot) as FrameworkElement; + + this._chrome = GetTemplateChild(PART_Chrome) as FrameworkElement; + + this.Overlay = GetTemplateChild(PART_Overlay) as Panel; + + this._contentPresenter = GetTemplateChild(PART_ContentPresenter) as FrameworkElement; + + this.SubscribeToTemplatePartEvents(); + this.SubscribeToStoryBoardEvents(); + this._desiredMargin = this.Margin; + this.Margin = new Thickness(0); + + // Update overlay size + if (this.IsOpen && (this.ChildWindowPopup != null)) + { + this._desiredContentHeight = this.Height; + this._desiredContentWidth = this.Width; + this.UpdateOverlaySize(); + this.UpdateRenderTransform(); + this.ChangeVisualState(); + } + } + + + /// + /// Raises the + /// event. + /// + /// The event data. + protected virtual void OnClosed(EventArgs e) + { + EventHandler handler = this.Closed; + + if (null != handler) + { + handler(this, e); + } + + this._isOpen = false; + if (!_modal) + { + this.ParentLayoutRoot.Children.Remove(this); + } + } + + /// + /// Raises the + /// event. + /// + /// The event data. + protected virtual void OnClosing(CancelEventArgs e) + { + EventHandler handler = this.Closing; + + if (null != handler) + { + handler(this, e); + } + } + + /// + /// Returns a + /// + /// for use by the Silverlight automation infrastructure. + /// + /// + /// + /// for the object. + /// + protected override AutomationPeer OnCreateAutomationPeer() + { + return new FloatableWindowAutomationPeer(this); + } + + /// + /// This method is called every time a + /// is displayed. + /// + protected virtual void OnOpened() + { + this.UpdatePosition(); + this._isOpen = true; + + if (this.Overlay != null) + { + this.Overlay.Opacity = this.OverlayOpacity; + this.Overlay.Background = this.OverlayBrush; + } + + if (!this.Focus()) + { + // If the Focus() fails it means there is no focusable element in the + // FloatableWindow. In this case we set IsTabStop to true to have the keyboard functionality + this.IsTabStop = true; + this.Focus(); + } + } + + /// + /// Executed when the opening storyboard finishes. + /// + /// Sender object. + /// Event args. + private void Opening_Completed(object sender, EventArgs e) + { + if (this._opened != null) + { + this._opened.Completed -= new EventHandler(this.Opening_Completed); + } + // AutomationPeer returns "ReadyForUserInteraction" when the FloatableWindow + // is open and all animations have been completed. + this.InteractionState = WindowInteractionState.ReadyForUserInteraction; + this.OnOpened(); + } + + /// + /// Executed when the page resizes. + /// + /// Sender object. + /// Event args. + private void Page_Resized(object sender, EventArgs e) + { + if (this.ChildWindowPopup != null) + { + this.UpdateOverlaySize(); + } + } + + /// + /// Executed when the root visual gets focus. + /// + /// Sender object. + /// Routed event args. + private void RootVisual_GotFocus(object sender, RoutedEventArgs e) + { + this.Focus(); + this.InteractionState = WindowInteractionState.ReadyForUserInteraction; + } + + public void Show() + { + ShowWindow(false); + } + + public void ShowDialog() + { + _verticalOffset = 0; + _horizontalOffset = 0; + ShowWindow(true); + } + + public void Show(double horizontalOffset, double verticalOffset) + { + _horizontalOffset = horizontalOffset; + _verticalOffset = verticalOffset; + ShowWindow(false); + } + + /// + /// Opens a and + /// returns without waiting for the + /// to close. + /// + /// + /// The child window is already in the visual tree. + /// + internal void ShowWindow(bool isModal) + { + _modal = isModal; + + // AutomationPeer returns "Running" when Show() is called + // but the FloatableWindow is not ready for user interaction: + this.InteractionState = WindowInteractionState.Running; + + this.SubscribeToEvents(); + this.SubscribeToTemplatePartEvents(); + this.SubscribeToStoryBoardEvents(); + + + // MaxHeight and MinHeight properties should not be overwritten: + this.MaxHeight = double.PositiveInfinity; + this.MaxWidth = double.PositiveInfinity; + + if (_modal) + { + if (this.ChildWindowPopup == null) + { + this.ChildWindowPopup = new Popup(); + + try + { + this.ChildWindowPopup.Child = this; + } + catch (ArgumentException) + { + // If the FloatableWindow is already in the visualtree, we cannot set it to be the child of the popup + // we are throwing a friendlier exception for this case: + this.InteractionState = WindowInteractionState.NotResponding; + throw new InvalidOperationException("Cannot call Show() on a ChildWindow that is in the visual tree. ChildWindow should be the top-most element in the .xaml file."); + } + } + + if (this.ChildWindowPopup != null && Application.Current.RootVisual != null) + { + this.ChildWindowPopup.IsOpen = true; + + this.ChildWindowPopup.HorizontalOffset = _horizontalOffset; + this.ChildWindowPopup.VerticalOffset = _verticalOffset; + + // while the FloatableWindow is open, the DialogResult is always NULL: + this._dialogresult = null; + } + } + else + { + if (ParentLayoutRoot != null) + { + this.SetValue(Canvas.TopProperty, _verticalOffset); + this.SetValue(Canvas.LeftProperty, _horizontalOffset); + this.ParentLayoutRoot.Children.Add(this); + this.BringToFront(); + } + else + { + throw new ArgumentNullException("ParentLayoutRoot", "You need to specify a root Panel element to add the window elements to."); + } + } + + // disable the underlying UI + if (RootVisual != null && _modal) + { + RootVisual.IsEnabled = false; + } + + // if the template is already loaded, display loading visuals animation + if (this.ContentRoot == null) + { + this.Loaded += (s, args) => + { + if (this.ContentRoot != null) + { + this.ChangeVisualState(); + } + }; + } + else + { + this.ChangeVisualState(); + } + } + + /// + /// Subscribes to events when the FloatableWindow is opened. + /// + private void SubscribeToEvents() + { + if (Application.Current != null && Application.Current.Host != null && Application.Current.Host.Content != null) + { + Application.Current.Exit += new EventHandler(this.Application_Exit); + Application.Current.Host.Content.Resized += new EventHandler(this.Page_Resized); + } + + this.KeyDown += new KeyEventHandler(this.ChildWindow_KeyDown); + if (_modal) + { + this.LostFocus += new RoutedEventHandler(this.ChildWindow_LostFocus); + } + this.SizeChanged += new SizeChangedEventHandler(this.ChildWindow_SizeChanged); + } + + /// + /// Subscribes to events that are on the storyboards. + /// Unsubscribing from these events happen in the event handlers individually. + /// + private void SubscribeToStoryBoardEvents() + { + if (this._closed != null) + { + this._closed.Completed += new EventHandler(this.Closing_Completed); + } + + if (this._opened != null) + { + this._opened.Completed += new EventHandler(this.Opening_Completed); + } + } + + /// + /// Subscribes to events on the template parts. + /// + private void SubscribeToTemplatePartEvents() + { + if (this.CloseButton != null) + { + this.CloseButton.Click += new RoutedEventHandler(this.CloseButton_Click); + } + + if (this._chrome != null) + { + this._chrome.MouseLeftButtonDown += new MouseButtonEventHandler(this.Chrome_MouseLeftButtonDown); + this._chrome.MouseLeftButtonUp += new MouseButtonEventHandler(this.Chrome_MouseLeftButtonUp); + this._chrome.MouseMove += new MouseEventHandler(this.Chrome_MouseMove); + } + + } + + /// + /// Unsubscribe from events when the FloatableWindow is closed. + /// + private void UnSubscribeFromEvents() + { + if (Application.Current != null && Application.Current.Host != null && Application.Current.Host.Content != null) + { + Application.Current.Exit -= new EventHandler(this.Application_Exit); + Application.Current.Host.Content.Resized -= new EventHandler(this.Page_Resized); + } + + this.KeyDown -= new KeyEventHandler(this.ChildWindow_KeyDown); + if (_modal) + { + this.LostFocus -= new RoutedEventHandler(this.ChildWindow_LostFocus); + } + this.SizeChanged -= new SizeChangedEventHandler(this.ChildWindow_SizeChanged); + } + + /// + /// Unsubscribe from the events that are subscribed on the template part elements. + /// + private void UnsubscribeFromTemplatePartEvents() + { + if (this.CloseButton != null) + { + this.CloseButton.Click -= new RoutedEventHandler(this.CloseButton_Click); + } + + if (this._chrome != null) + { + this._chrome.MouseLeftButtonDown -= new MouseButtonEventHandler(this.Chrome_MouseLeftButtonDown); + this._chrome.MouseLeftButtonUp -= new MouseButtonEventHandler(this.Chrome_MouseLeftButtonUp); + this._chrome.MouseMove -= new MouseEventHandler(this.Chrome_MouseMove); + } + } + + /// + /// Updates the size of the overlay of the window. + /// + private void UpdateOverlaySize() + { + if (_modal) + { + if (this.Overlay != null && Application.Current != null && Application.Current.Host != null && Application.Current.Host.Content != null) + { + this.Height = Application.Current.Host.Content.ActualHeight; + this.Width = Application.Current.Host.Content.ActualWidth; + this.Overlay.Height = this.Height; + this.Overlay.Width = this.Width; + + if (this.ContentRoot != null) + { + this.ContentRoot.Width = this._desiredContentWidth; + this.ContentRoot.Height = this._desiredContentHeight; + this.ContentRoot.Margin = this._desiredMargin; + } + } + } + else + { + if (this.Overlay != null) + { + this.Overlay.Visibility = Visibility.Collapsed; + } + } + } + + /// + /// Updates the position of the window in case the size of the content changes. + /// This allows FloatableWindow only scale from right and bottom. + /// + private void UpdatePosition() + { + if (this.ContentRoot != null && Application.Current != null && Application.Current.RootVisual != null) + { + GeneralTransform gt = this.ContentRoot.TransformToVisual(Application.Current.RootVisual); + + if (gt != null) + { + this._windowPosition = gt.Transform(new Point(0, 0)); + } + } + } + + /// + /// Updates the render transform applied on the overlay. + /// + private void UpdateRenderTransform() + { + if (this._root != null && this.ContentRoot != null) + { + // The Overlay part should not be affected by the render transform applied on the + // FloatableWindow. In order to achieve this, we adjust an identity matrix to represent + // the _root's transformation, invert it, apply the inverted matrix on the _root, so that + // nothing is affected by the rendertransform, and apply the original transform only on the Content + GeneralTransform gt = this._root.TransformToVisual(null); + if (gt != null) + { + Point p10 = new Point(1, 0); + Point p01 = new Point(0, 1); + Point transform10 = gt.Transform(p10); + Point transform01 = gt.Transform(p01); + + Matrix transformToRootMatrix = Matrix.Identity; + transformToRootMatrix.M11 = transform10.X; + transformToRootMatrix.M12 = transform10.Y; + transformToRootMatrix.M21 = transform01.X; + transformToRootMatrix.M22 = transform01.Y; + + MatrixTransform original = new MatrixTransform(); + original.Matrix = transformToRootMatrix; + + InvertMatrix(ref transformToRootMatrix); + MatrixTransform mt = new MatrixTransform(); + mt.Matrix = transformToRootMatrix; + + TransformGroup tg = this._root.RenderTransform as TransformGroup; + + if (tg != null) + { + tg.Children.Add(mt); + } + else + { + this._root.RenderTransform = mt; + } + + tg = this.ContentRoot.RenderTransform as TransformGroup; + + if (tg != null) + { + tg.Children.Add(original); + } + else + { + this.ContentRoot.RenderTransform = original; + } + } + } + } + + /// + /// Updates the ContentRootTranslateTransform. + /// + /// X coordinate of the transform. + /// Y coordinate of the transform. + private void UpdateContentRootTransform(double X, double Y) + { + if (this._contentRootTransform == null) + { + this._contentRootTransform = new TranslateTransform(); + this._contentRootTransform.X = X; + this._contentRootTransform.Y = Y; + + TransformGroup transformGroup = this.ContentRoot.RenderTransform as TransformGroup; + + if (transformGroup == null) + { + transformGroup = new TransformGroup(); + transformGroup.Children.Add(this.ContentRoot.RenderTransform); + } + transformGroup.Children.Add(this._contentRootTransform); + this.ContentRoot.RenderTransform = transformGroup; + } + else + { + this._contentRootTransform.X += X; + this._contentRootTransform.Y += Y; + } + } + + private void Resizer_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) + { + this._resizer.CaptureMouse(); + this._isMouseCaptured = true; + this._clickPoint = e.GetPosition(sender as UIElement); + +#if DEBUG + this.Title = string.Format("X:{0},Y:{1}", this._clickPoint.X.ToString(), this._clickPoint.Y.ToString()); +#endif + } + + private void Resizer_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) + { + this._resizer.ReleaseMouseCapture(); + this._isMouseCaptured = false; + this._resizer.Opacity = 0.25; + } + + private void Resizer_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) + { + if (this._isMouseCaptured && this.ContentRoot != null) + { + // If the child window is dragged out of the page, return + if (Application.Current != null && Application.Current.RootVisual != null && + (e.GetPosition(Application.Current.RootVisual).X < 0 || e.GetPosition(Application.Current.RootVisual).Y < 0)) + { + return; + } + +#if DEBUG + this.Title = string.Format("X:{0},Y:{1}", this._clickPoint.X.ToString(), this._clickPoint.Y.ToString()); +#endif + + Point p = e.GetPosition(this.ContentRoot); + + if ((p.X > this._clickPoint.X) && (p.Y > this._clickPoint.Y)) + { + this.Width = (double)(p.X - (12 - this._clickPoint.X)); + this.Height = (double)(p.Y - (12 - this._clickPoint.Y)); + } + } + } + + private Storyboard GetVisualStateStoryboard(string visualStateGroupName, string visualStateName) + { + foreach (VisualStateGroup g in VisualStateManager.GetVisualStateGroups((FrameworkElement)this.ContentRoot.Parent)) + { + if (g.Name != visualStateGroupName) continue; + foreach (VisualState s in g.States) + { + if (s.Name != visualStateName) continue; + return s.Storyboard; + } + } + return null; + } + + #endregion Methods + } +} \ No newline at end of file diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse/Controls/FloatableWindow/FloatableWindowAutomationPeer.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SilverlightGlimpse/SilverlightGlimpse/Controls/FloatableWindow/FloatableWindowAutomationPeer.cs Mon Apr 23 11:06:10 2012 +0100 @@ -0,0 +1,414 @@ +// (c) Copyright Microsoft Corporation. +// This source is subject to the Microsoft Public License (Ms-PL). +// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. +// All other rights reserved. + +using System.Windows.Automation.Provider; +using System.Windows.Controls; +using System.Windows.Media; + +namespace System.Windows.Automation.Peers +{ + public class FloatableWindowAutomationPeer : FrameworkElementAutomationPeer, IWindowProvider, ITransformProvider + { + #region Data + + /// + /// Specifies whether the FloatableWindow is the top most element. + /// + private bool _isTopMost; + + #endregion Data + + #region Properties + + /// + /// Gets or sets a value indicating whether the FloatableWindow is the top most element. + /// + private bool IsTopMostPrivate + { + get + { + return this._isTopMost; + } + set + { + if (this._isTopMost != value) + { + this._isTopMost = value; + this.RaisePropertyChangedEvent(WindowPatternIdentifiers.IsTopmostProperty, !this._isTopMost, this._isTopMost); + } + } + } + + /// + /// Gets the owning FloatableWindow. + /// + private FloatableWindow OwningFloatableWindow + { + get + { + return (FloatableWindow)Owner; + } + } + + #endregion Properties + + public FloatableWindowAutomationPeer(FloatableWindow owner) + : base(owner) + { + if (owner == null) + { + throw new ArgumentNullException("owner"); + } + this.RefreshIsTopMostProperty(); + } + + #region AutomationPeer overrides + + /// + /// Gets the control pattern for this + /// . + /// + /// + /// One of the enumeration values. + /// + /// + /// The object that implements the pattern interface, or null if the + /// specified pattern interface is not implemented by this peer. + /// + public override object GetPattern(PatternInterface patternInterface) + { + if (patternInterface == PatternInterface.Transform || patternInterface == PatternInterface.Window) + { + return this; + } + + return base.GetPattern(patternInterface); + } + + /// + /// Gets the + /// + /// for the element associated with this + /// . + /// Called by + /// . + /// + /// A value of the enumeration. + protected override AutomationControlType GetAutomationControlTypeCore() + { + return AutomationControlType.Window; + } + + /// + /// Gets the name of the class for the object associated with this + /// . + /// Called by + /// . + /// + /// + /// A string value that represents the type of the child window. + /// + protected override string GetClassNameCore() + { + return this.Owner.GetType().Name; + } + + /// + /// Gets the text label of the + /// that is + /// associated with this + /// . + /// Called by + /// . + /// + /// + /// The text label of the element that is associated with this + /// automation peer. + /// + protected override string GetNameCore() + { + string name = base.GetNameCore(); + if (string.IsNullOrEmpty(name)) + { + AutomationPeer labeledBy = GetLabeledByCore(); + if (labeledBy != null) + { + name = labeledBy.GetName(); + } + + if (string.IsNullOrEmpty(name) && this.OwningFloatableWindow.Title != null) + { + name = this.OwningFloatableWindow.Title.ToString(); + } + } + return name; + } + + #endregion AutomationPeer overrides + + #region IWindowProvider + + /// + /// Gets the interaction state of the window. + /// + /// + /// The interaction state of the control, as a value of the enumeration. + /// + WindowInteractionState IWindowProvider.InteractionState + { + get + { + return this.OwningFloatableWindow.InteractionState; + } + } + + /// + /// Gets a value indicating whether the window is modal. + /// + /// + /// True in all cases. + /// + bool IWindowProvider.IsModal + { + get { return true; } + } + + /// + /// Gets a value indicating whether the window is the topmost + /// element in the z-order of layout. + /// + /// + /// True if the window is topmost; otherwise, false. + /// + bool IWindowProvider.IsTopmost + { + get + { + return this.IsTopMostPrivate; + } + } + + /// + /// Gets a value indicating whether the window can be maximized. + /// + /// False in all cases. + bool IWindowProvider.Maximizable + { + get { return false; } + } + + /// + /// Gets a value indicating whether the window can be minimized. + /// + /// False in all cases. + bool IWindowProvider.Minimizable + { + get { return false; } + } + + /// + /// Gets the visual state of the window. + /// + /// + /// + /// in all cases. + /// + WindowVisualState IWindowProvider.VisualState + { + get + { + return WindowVisualState.Normal; + } + } + + /// + /// Closes the window. + /// + void IWindowProvider.Close() + { + this.OwningFloatableWindow.Close(); + } + + /// + /// Changes the visual state of the window (such as minimizing or + /// maximizing it). + /// + /// + /// The visual state of the window to change to, as a value of the + /// enumeration. + /// + void IWindowProvider.SetVisualState(WindowVisualState state) + { + } + + /// + /// Blocks the calling code for the specified time or until the + /// associated process enters an idle state, whichever completes first. + /// + /// + /// The amount of time, in milliseconds, to wait for the associated + /// process to become idle. + /// + /// + /// True if the window has entered the idle state; false if the timeout + /// occurred. + /// + bool IWindowProvider.WaitForInputIdle(int milliseconds) + { + return false; + } + + #endregion IWindowProvider + + #region ITransformProvider + + /// + /// Moves the control. + /// + /// + /// The absolute screen coordinates of the left side of the control. + /// + /// + /// The absolute screen coordinates of the top of the control. + /// + void ITransformProvider.Move(double x, double y) + { + if (x < 0) + { + x = 0; + } + + if (y < 0) + { + y = 0; + } + + if (x > this.OwningFloatableWindow.Width) + { + x = this.OwningFloatableWindow.Width; + } + + if (y > this.OwningFloatableWindow.Height) + { + y = this.OwningFloatableWindow.Height; + } + + FrameworkElement contentRoot = this.OwningFloatableWindow.ContentRoot; + + if (contentRoot != null) + { + GeneralTransform gt = contentRoot.TransformToVisual(null); + + if (gt != null) + { + Point p = gt.Transform(new Point(0, 0)); + + TransformGroup transformGroup = contentRoot.RenderTransform as TransformGroup; + + if (transformGroup == null) + { + transformGroup = new TransformGroup(); + transformGroup.Children.Add(contentRoot.RenderTransform); + } + + TranslateTransform t = new TranslateTransform(); + t.X = x - p.X; + t.Y = y - p.Y; + + if (transformGroup != null) + { + transformGroup.Children.Add(t); + contentRoot.RenderTransform = transformGroup; + } + } + } + } + + /// + /// Resizes the control. + /// + /// The new width of the window, in pixels. + /// + /// The new height of the window, in pixels. + /// + void ITransformProvider.Resize(double width, double height) + { + } + + /// + /// Rotates the control. + /// + /// + /// The number of degrees to rotate the control. A positive number + /// rotates the control clockwise. A negative number rotates the + /// control counterclockwise. + /// + void ITransformProvider.Rotate(double degrees) + { + } + + /// + /// Gets a value indicating whether the element can be moved. + /// + /// True in all cases. + bool ITransformProvider.CanMove + { + get { return true; } + } + + /// + /// Gets a value indicating whether the element can be resized. + /// + /// False in all cases. + bool ITransformProvider.CanResize + { + get { return false; } + } + + /// + /// Gets a value indicating whether the element can be rotated. + /// + /// False in all cases. + bool ITransformProvider.CanRotate + { + get { return false; } + } + + #endregion ITransformProvider + + #region Methods + + /// + /// Returns if the FloatableWindow is the top most element. + /// + /// Bool value. + private bool GetIsTopMostCore() + { + return !(this.OwningFloatableWindow.InteractionState == WindowInteractionState.BlockedByModalWindow); + } + + /// + /// Raises PropertyChangedEvent for WindowInteractionStateProperty. + /// + /// Old WindowInteractionStateProperty. + /// New WindowInteractionStateProperty. + internal void RaiseInteractionStatePropertyChangedEvent(WindowInteractionState oldValue, WindowInteractionState newValue) + { + this.RaisePropertyChangedEvent(WindowPatternIdentifiers.WindowInteractionStateProperty, oldValue, newValue); + this.RefreshIsTopMostProperty(); + } + + /// + /// Updates the IsTopMostPrivate property. + /// + private void RefreshIsTopMostProperty() + { + this.IsTopMostPrivate = this.GetIsTopMostCore(); + } + + #endregion Methods + } +} + diff -r 81337ebf885a -r a0bcd783e612 SilverlightGlimpse/SilverlightGlimpse/Controls/GlimpseViewer.xaml --- a/SilverlightGlimpse/SilverlightGlimpse/Controls/GlimpseViewer.xaml Mon Apr 23 11:05:11 2012 +0100 +++ b/SilverlightGlimpse/SilverlightGlimpse/Controls/GlimpseViewer.xaml Mon Apr 23 11:06:10 2012 +0100 @@ -2,6 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" + xmlns:local="clr-namespace:SilverlightGlimpse.Converters" xmlns:localc="clr-namespace:SilverlightGlimpse.Controls"> @@ -12,6 +13,9 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +