Initial Commit
This commit is contained in:
171
ViewportRestrictions/DataHeightRestriction.cs
Normal file
171
ViewportRestrictions/DataHeightRestriction.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
public class DataHeightRestriction : ViewportRestriction, ISupportAttachToViewport
|
||||
{
|
||||
private double yEnlargeCoeff = 1.1;
|
||||
public double YEnlargeCoeff
|
||||
{
|
||||
get { return yEnlargeCoeff; }
|
||||
set
|
||||
{
|
||||
if (yEnlargeCoeff != value)
|
||||
{
|
||||
yEnlargeCoeff = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override DataRect Apply(DataRect oldDataRect, DataRect newDataRect, Viewport2D viewport)
|
||||
{
|
||||
DataRect overallBounds = DataRect.Empty;
|
||||
|
||||
foreach (var chart in viewport.ContentBoundsHosts)
|
||||
{
|
||||
var plotterElement = chart as IPlotterElement;
|
||||
var visual = viewport.Plotter.VisualBindings[plotterElement];
|
||||
var points = (ReadOnlyCollection<Point>)PointsGraphBase.GetVisiblePoints(visual);
|
||||
if (points != null)
|
||||
{
|
||||
|
||||
// searching for indices of chart's visible points which are near left and right borders of newDataRect
|
||||
double startX = newDataRect.XMin;
|
||||
double endX = newDataRect.XMax;
|
||||
|
||||
if (points[0].X > endX || points[points.Count - 1].X < startX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int startIndex = -1;
|
||||
|
||||
// we assume that points are sorted by x values ascending
|
||||
if (startX <= points[0].X)
|
||||
{
|
||||
startIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 1; i < points.Count - 1; i++)
|
||||
{
|
||||
if (points[i].X <= startX && startX < points[i + 1].X)
|
||||
{
|
||||
startIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int endIndex = points.Count;
|
||||
|
||||
if (points[points.Count - 1].X < endX)
|
||||
{
|
||||
endIndex = points.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = points.Count - 1; i >= 1; i--)
|
||||
{
|
||||
if (points[i - 1].X <= endX && endX < points[i].X)
|
||||
{
|
||||
endIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rect bounds = Rect.Empty;
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
bounds.Union(points[i]);
|
||||
}
|
||||
if (startIndex > 0)
|
||||
{
|
||||
Point pt = GetInterpolatedPoint(startX, points[startIndex], points[startIndex - 1]);
|
||||
bounds.Union(pt);
|
||||
}
|
||||
if (endIndex < points.Count - 1)
|
||||
{
|
||||
Point pt = GetInterpolatedPoint(endX, points[endIndex], points[endIndex + 1]);
|
||||
bounds.Union(pt);
|
||||
}
|
||||
|
||||
overallBounds.Union(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
if (!overallBounds.IsEmpty)
|
||||
{
|
||||
double y = overallBounds.YMin;
|
||||
double height = overallBounds.Height;
|
||||
|
||||
if (height == 0)
|
||||
{
|
||||
height = newDataRect.Height;
|
||||
y -= height / 2;
|
||||
}
|
||||
|
||||
newDataRect = new DataRect(newDataRect.XMin, y, newDataRect.Width, height);
|
||||
newDataRect = DataRectExtensions.ZoomY(newDataRect, newDataRect.GetCenter(), yEnlargeCoeff);
|
||||
}
|
||||
|
||||
return newDataRect;
|
||||
}
|
||||
|
||||
private static Point GetInterpolatedPoint(double x, Point p1, Point p2)
|
||||
{
|
||||
double xRatio = (x - p1.X) / (p2.X - p1.X);
|
||||
double y = (1 - xRatio) * p1.Y + xRatio * p2.Y;
|
||||
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
#region ISupportAttach Members
|
||||
|
||||
void ISupportAttachToViewport.Attach(Viewport2D viewport)
|
||||
{
|
||||
((INotifyCollectionChanged)viewport.ContentBoundsHosts).CollectionChanged += OnContentBoundsHostsChanged;
|
||||
|
||||
foreach (var item in viewport.ContentBoundsHosts)
|
||||
{
|
||||
PointsGraphBase chart = item as PointsGraphBase;
|
||||
if (chart != null)
|
||||
{
|
||||
chart.ProvideVisiblePoints = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnContentBoundsHostsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.NewItems != null)
|
||||
{
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
PointsGraphBase chart = item as PointsGraphBase;
|
||||
if (chart != null)
|
||||
{
|
||||
chart.ProvideVisiblePoints = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo probably set ProvideVisiblePoints to false on OldItems
|
||||
}
|
||||
|
||||
void ISupportAttachToViewport.Detach(Viewport2D viewport)
|
||||
{
|
||||
((INotifyCollectionChanged)viewport.ContentBoundsHosts).CollectionChanged -= OnContentBoundsHostsChanged;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
25
ViewportRestrictions/DateTimeHorizontalAxisRestriction.cs
Normal file
25
ViewportRestrictions/DateTimeHorizontalAxisRestriction.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
public sealed class DateTimeHorizontalAxisRestriction : ViewportRestriction
|
||||
{
|
||||
private readonly double minSeconds = new TimeSpan(DateTime.MinValue.Ticks).TotalSeconds;
|
||||
private readonly double maxSeconds = new TimeSpan(DateTime.MaxValue.Ticks).TotalSeconds;
|
||||
|
||||
public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
|
||||
{
|
||||
DataRect borderRect = DataRect.Create(minSeconds, proposedDataRect.YMin, maxSeconds, proposedDataRect.YMax);
|
||||
if (proposedDataRect.IntersectsWith(borderRect))
|
||||
{
|
||||
DataRect croppedRect = DataRect.Intersect(proposedDataRect, borderRect);
|
||||
return croppedRect;
|
||||
}
|
||||
|
||||
return previousDataRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
ViewportRestrictions/DateTimeVerticalAxisRestriction.cs
Normal file
25
ViewportRestrictions/DateTimeVerticalAxisRestriction.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
public sealed class DateTimeVerticalAxisRestriction : ViewportRestriction
|
||||
{
|
||||
private readonly double minSeconds = new TimeSpan(DateTime.MinValue.Ticks).TotalSeconds;
|
||||
private readonly double maxSeconds = new TimeSpan(DateTime.MaxValue.Ticks).TotalSeconds;
|
||||
|
||||
public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
|
||||
{
|
||||
DataRect borderRect = DataRect.Create(proposedDataRect.XMin, minSeconds, proposedDataRect.XMax, maxSeconds);
|
||||
if (proposedDataRect.IntersectsWith(borderRect))
|
||||
{
|
||||
DataRect croppedRect = DataRect.Intersect(proposedDataRect, borderRect);
|
||||
return croppedRect;
|
||||
}
|
||||
|
||||
return previousDataRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
80
ViewportRestrictions/DomainRestriction.cs
Normal file
80
ViewportRestrictions/DomainRestriction.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using Microsoft.Research.DynamicDataDisplay.Common;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a restriction which returns data rectangle, intersected with specified data domain.
|
||||
/// </summary>
|
||||
public class DomainRestriction : ViewportRestriction
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DomainRestriction"/> class.
|
||||
/// </summary>
|
||||
public DomainRestriction() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DomainRestriction"/> class with given domain property.
|
||||
/// </summary>
|
||||
/// <param name="domain">The domain.</param>
|
||||
public DomainRestriction(DataRect domain)
|
||||
{
|
||||
this.Domain = domain;
|
||||
}
|
||||
|
||||
private DataRect domain = new DataRect(-1, -1, 2, 2);
|
||||
/// <summary>
|
||||
/// Gets or sets the domain.
|
||||
/// </summary>
|
||||
/// <value>The domain.</value>
|
||||
public DataRect Domain
|
||||
{
|
||||
get { return domain; }
|
||||
set
|
||||
{
|
||||
if (domain != value)
|
||||
{
|
||||
domain = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the specified old data rect.
|
||||
/// </summary>
|
||||
/// <param name="oldDataRect">The old data rect.</param>
|
||||
/// <param name="newDataRect">The new data rect.</param>
|
||||
/// <param name="viewport">The viewport.</param>
|
||||
/// <returns></returns>
|
||||
public override DataRect Apply(DataRect oldDataRect, DataRect newDataRect, Viewport2D viewport)
|
||||
{
|
||||
DataRect res = domain;
|
||||
if (domain.IsEmpty)
|
||||
{
|
||||
res = newDataRect;
|
||||
}
|
||||
else if (newDataRect.IntersectsWith(domain))
|
||||
{
|
||||
res = newDataRect;
|
||||
if (newDataRect.Size == oldDataRect.Size)
|
||||
{
|
||||
if (res.XMin < domain.XMin) res.XMin = domain.XMin;
|
||||
if (res.YMin < domain.YMin) res.YMin = domain.YMin;
|
||||
if (res.XMax > domain.XMax) res.XMin += domain.XMax - res.XMax;
|
||||
if (res.YMax > domain.YMax) res.YMin += domain.YMax - res.YMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = DataRect.Intersect(newDataRect, domain);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
75
ViewportRestrictions/FollowWidthRestriction.cs
Normal file
75
ViewportRestrictions/FollowWidthRestriction.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a viewport restriction which modifies x coordinates of result visible rect to be adjacent to the right border of initial rect and have a fixed given width.
|
||||
/// Probably is better to add to FitToViewRestrictions collection of <see cref="Viewport"/>.
|
||||
/// </summary>
|
||||
public class FollowWidthRestriction : ViewportRestriction
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FollowWidthRestriction"/> class.
|
||||
/// </summary>
|
||||
public FollowWidthRestriction() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FollowWidthRestriction"/> class with the given width.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
public FollowWidthRestriction(double width)
|
||||
{
|
||||
Width = width;
|
||||
}
|
||||
|
||||
private double width = 1;
|
||||
/// <summary>
|
||||
/// Gets or sets the width of result visible rectangle.
|
||||
/// Default value is 1.0.
|
||||
/// </summary>
|
||||
/// <value>The width.</value>
|
||||
[DefaultValue(1.0)]
|
||||
public double Width
|
||||
{
|
||||
get { return width; }
|
||||
set
|
||||
{
|
||||
if (width != value)
|
||||
{
|
||||
width = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the restriction.
|
||||
/// </summary>
|
||||
/// <param name="previousDataRect">Previous data rectangle.</param>
|
||||
/// <param name="proposedDataRect">Proposed data rectangle.</param>
|
||||
/// <param name="viewport">The viewport, to which current restriction is being applied.</param>
|
||||
/// <returns>New changed visible rectangle.</returns>
|
||||
public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
|
||||
{
|
||||
if (proposedDataRect.IsEmpty)
|
||||
return proposedDataRect;
|
||||
|
||||
double followWidth = proposedDataRect.Width;
|
||||
if (!viewport.UnitedContentBounds.IsEmpty)
|
||||
{
|
||||
followWidth = Math.Min(width, viewport.UnitedContentBounds.Width);
|
||||
}
|
||||
if (followWidth.IsInfinite())
|
||||
followWidth = width;
|
||||
|
||||
Rect visible = new Rect(proposedDataRect.XMin + proposedDataRect.Width - followWidth, proposedDataRect.YMin, followWidth, proposedDataRect.Height);
|
||||
|
||||
return visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
ViewportRestrictions/ISupportAttachToViewport.cs
Normal file
26
ViewportRestrictions/ISupportAttachToViewport.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a restriction which is capable to attach to or detach from <see cref="Viewport"/>, to which it is applied.
|
||||
/// </summary>
|
||||
public interface ISupportAttachToViewport
|
||||
{
|
||||
/// <summary>
|
||||
/// Attaches the specified viewport to a restriction.
|
||||
/// </summary>
|
||||
/// <param name="viewport">The viewport.</param>
|
||||
void Attach(Viewport2D viewport);
|
||||
|
||||
/// <summary>
|
||||
/// Detaches the specified viewport from a restriction.
|
||||
/// </summary>
|
||||
/// <param name="viewport">The viewport.</param>
|
||||
void Detach(Viewport2D viewport);
|
||||
}
|
||||
}
|
||||
40
ViewportRestrictions/InjectionDelegateRestriction.cs
Normal file
40
ViewportRestrictions/InjectionDelegateRestriction.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
public delegate DataRect ViewportRestrictionCallback(DataRect proposedDataRect);
|
||||
|
||||
public class InjectionDelegateRestriction : ViewportRestriction
|
||||
{
|
||||
public InjectionDelegateRestriction(Viewport2D masterViewport, ViewportRestrictionCallback callback)
|
||||
{
|
||||
if (callback == null)
|
||||
throw new ArgumentNullException("callback");
|
||||
if (masterViewport == null)
|
||||
throw new ArgumentNullException("masterViewport");
|
||||
|
||||
this.callback = callback;
|
||||
this.masterViewport = masterViewport;
|
||||
masterViewport.PropertyChanged += masterViewport_PropertyChanged;
|
||||
}
|
||||
|
||||
void masterViewport_PropertyChanged(object sender, ExtendedPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Visible")
|
||||
{
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Viewport2D masterViewport;
|
||||
private ViewportRestrictionCallback callback;
|
||||
|
||||
public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
|
||||
{
|
||||
return callback(proposedDataRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
63
ViewportRestrictions/MaximalSizeRestriction.cs
Normal file
63
ViewportRestrictions/MaximalSizeRestriction.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a restriction, which limits the maximal size of <see cref="Viewport"/>'s Visible property.
|
||||
/// </summary>
|
||||
public class MaximalSizeRestriction : ViewportRestriction
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MaximalSizeRestriction"/> class.
|
||||
/// </summary>
|
||||
public MaximalSizeRestriction() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MaximalSizeRestriction"/> class with the given maximal size of Viewport's Visible.
|
||||
/// </summary>
|
||||
/// <param name="maxSize">Maximal size of Viewport's Visible.</param>
|
||||
public MaximalSizeRestriction(double maxSize)
|
||||
{
|
||||
MaxSize = maxSize;
|
||||
}
|
||||
|
||||
private double maxSize = 1000;
|
||||
/// <summary>
|
||||
/// Gets or sets the maximal size of Viewport's Visible.
|
||||
/// The default value is 1000.0.
|
||||
/// </summary>
|
||||
/// <value>The size of the max.</value>
|
||||
public double MaxSize
|
||||
{
|
||||
get { return maxSize; }
|
||||
set
|
||||
{
|
||||
if (maxSize != value)
|
||||
{
|
||||
maxSize = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the specified old data rect.
|
||||
/// </summary>
|
||||
/// <param name="oldDataRect">The old data rect.</param>
|
||||
/// <param name="newDataRect">The new data rect.</param>
|
||||
/// <param name="viewport">The viewport.</param>
|
||||
/// <returns></returns>
|
||||
public override DataRect Apply(DataRect oldDataRect, DataRect newDataRect, Viewport2D viewport)
|
||||
{
|
||||
bool decreasing = newDataRect.Width < oldDataRect.Width || newDataRect.Height < oldDataRect.Height;
|
||||
if (!decreasing && (newDataRect.Width > maxSize || newDataRect.Height > maxSize))
|
||||
return oldDataRect;
|
||||
|
||||
return newDataRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
ViewportRestrictions/MinimalSizeRestriction.cs
Normal file
48
ViewportRestrictions/MinimalSizeRestriction.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a ViewportRestriction, which the minimal size of <see cref="Viewport"/>'s Visible.
|
||||
/// </summary>
|
||||
public class MinimalSizeRestriction : ViewportRestriction
|
||||
{
|
||||
private double minSize = 1E-11;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimal size of Viewport's Visible.
|
||||
/// </summary>
|
||||
/// <value>The minimal size of Viewport's Visible.</value>
|
||||
public double MinSize
|
||||
{
|
||||
get { return minSize; }
|
||||
set
|
||||
{
|
||||
if (minSize != value)
|
||||
{
|
||||
minSize = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the restriction.
|
||||
/// </summary>
|
||||
/// <param name="previousDataRect">Previous data rectangle.</param>
|
||||
/// <param name="proposedDataRect">Proposed data rectangle.</param>
|
||||
/// <param name="viewport">The viewport, to which current restriction is being applied.</param>
|
||||
/// <returns>New changed visible rectangle.</returns>
|
||||
public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
|
||||
{
|
||||
if (proposedDataRect.Width < minSize || proposedDataRect.Height < minSize)
|
||||
return previousDataRect;
|
||||
|
||||
return proposedDataRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
ViewportRestrictions/PhysicalProportionsRestriction.cs
Normal file
79
ViewportRestrictions/PhysicalProportionsRestriction.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a restriction in which actual visible rect's proportions depends on
|
||||
/// actual output rect's proportions.
|
||||
/// </summary>
|
||||
public sealed class PhysicalProportionsRestriction : ViewportRestriction
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PhysicalProportionsRestriction"/> class.
|
||||
/// </summary>
|
||||
public PhysicalProportionsRestriction() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PhysicalProportionsRestriction"/> class with the given proportion ratio.
|
||||
/// </summary>
|
||||
/// <param name="proportionRatio">The proportion ratio.</param>
|
||||
public PhysicalProportionsRestriction(double proportionRatio)
|
||||
{
|
||||
ProportionRatio = proportionRatio;
|
||||
}
|
||||
|
||||
private double proportionRatio = 1.0;
|
||||
/// <summary>
|
||||
/// Gets or sets the proportion ratio.
|
||||
/// Default value is 1.0.
|
||||
/// </summary>
|
||||
/// <value>The proportion ratio.</value>
|
||||
public double ProportionRatio
|
||||
{
|
||||
get { return proportionRatio; }
|
||||
set
|
||||
{
|
||||
if (proportionRatio != value)
|
||||
{
|
||||
proportionRatio = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the restriction.
|
||||
/// </summary>
|
||||
/// <param name="previousDataRect">Previous data rectangle.</param>
|
||||
/// <param name="proposedDataRect">Proposed data rectangle.</param>
|
||||
/// <param name="viewport">The viewport, to which current restriction is being applied.</param>
|
||||
/// <returns>New changed visible rectangle.</returns>
|
||||
public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
|
||||
{
|
||||
Rect output = viewport.Output;
|
||||
if (output.Width == 0 || output.Height == 0)
|
||||
return proposedDataRect;
|
||||
|
||||
double screenRatio = output.Width / output.Height;
|
||||
double viewportRatio = proposedDataRect.Width / proposedDataRect.Height;
|
||||
double ratio = screenRatio / viewportRatio;
|
||||
double width = proportionRatio * proposedDataRect.Width * ratio;
|
||||
double height = proposedDataRect.Height;
|
||||
|
||||
if (width < proposedDataRect.Width)
|
||||
{
|
||||
height = proposedDataRect.Height / proportionRatio / ratio;
|
||||
width = proposedDataRect.Width;
|
||||
}
|
||||
|
||||
Point center = proposedDataRect.GetCenter();
|
||||
Rect res = RectExtensions.FromCenterSize(center, width, height);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
ViewportRestrictions/ProportionsRestriction.cs
Normal file
38
ViewportRestrictions/ProportionsRestriction.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
public sealed class ProportionsRestriction : ViewportRestriction
|
||||
{
|
||||
private double widthToHeightRatio = 1;
|
||||
public double WidthToHeightRatio
|
||||
{
|
||||
get { return widthToHeightRatio; }
|
||||
set
|
||||
{
|
||||
if (widthToHeightRatio != value)
|
||||
{
|
||||
widthToHeightRatio = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override DataRect Apply(DataRect oldDataRect, DataRect newDataRect, Viewport2D viewport)
|
||||
{
|
||||
double ratio = newDataRect.Width / newDataRect.Height;
|
||||
double coeff = Math.Sqrt(ratio);
|
||||
|
||||
double newWidth = newDataRect.Width / coeff;
|
||||
double newHeight = newDataRect.Height * coeff;
|
||||
|
||||
Point center = newDataRect.GetCenter();
|
||||
DataRect res = DataRect.FromCenterSize(center, newWidth, newHeight);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
ViewportRestrictions/RestrictionCollection.cs
Normal file
69
ViewportRestrictions/RestrictionCollection.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Microsoft.Research.DynamicDataDisplay;
|
||||
using Microsoft.Research.DynamicDataDisplay.Common;
|
||||
using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of <see cref="ViewportRestriction"/>s.
|
||||
/// <remarks>
|
||||
/// ViewportRestriction that is being added should not be null.
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
public sealed class RestrictionCollection : D3Collection<ViewportRestriction>
|
||||
{
|
||||
private readonly Viewport2D viewport;
|
||||
internal RestrictionCollection(Viewport2D viewport)
|
||||
{
|
||||
if (viewport == null)
|
||||
throw new ArgumentNullException("viewport");
|
||||
|
||||
this.viewport = viewport;
|
||||
}
|
||||
|
||||
protected override void OnItemAdding(ViewportRestriction item)
|
||||
{
|
||||
if (item == null)
|
||||
throw new ArgumentNullException("item");
|
||||
}
|
||||
|
||||
protected override void OnItemAdded(ViewportRestriction item)
|
||||
{
|
||||
item.Changed += OnItemChanged;
|
||||
ISupportAttachToViewport attachable = item as ISupportAttachToViewport;
|
||||
if (attachable != null)
|
||||
{
|
||||
attachable.Attach(viewport);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnItemChanged(object sender, EventArgs e)
|
||||
{
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
protected override void OnItemRemoving(ViewportRestriction item)
|
||||
{
|
||||
ISupportAttachToViewport attachable = item as ISupportAttachToViewport;
|
||||
if (attachable != null)
|
||||
{
|
||||
attachable.Detach(viewport);
|
||||
}
|
||||
item.Changed -= OnItemChanged;
|
||||
}
|
||||
|
||||
internal DataRect Apply(DataRect oldVisible, DataRect newVisible, Viewport2D viewport)
|
||||
{
|
||||
DataRect res = newVisible;
|
||||
foreach (var restriction in this)
|
||||
{
|
||||
res = restriction.Apply(oldVisible, res, viewport);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
ViewportRestrictions/ScaleInjectionRestriction.cs
Normal file
57
ViewportRestrictions/ScaleInjectionRestriction.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
public class ScaleInjectionRestriction : ViewportRestriction
|
||||
{
|
||||
private Viewport2D parentViewport;
|
||||
public ScaleInjectionRestriction(Viewport2D parentViewport)
|
||||
{
|
||||
if (parentViewport == null)
|
||||
throw new ArgumentNullException("parentViewport");
|
||||
|
||||
this.parentViewport = parentViewport;
|
||||
parentViewport.PropertyChanged += parentViewport_PropertyChanged;
|
||||
}
|
||||
|
||||
private void parentViewport_PropertyChanged(object sender, ExtendedPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Visible")
|
||||
{
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHorizontalTransform(double parentMin, double childMin, double parentMax, double childMax)
|
||||
{
|
||||
xScale = (childMax - childMin) / (parentMax - parentMin);
|
||||
xShift = childMin - parentMin;
|
||||
}
|
||||
|
||||
public void SetVerticalTransform(double parentMin, double childMin, double parentMax, double childMax)
|
||||
{
|
||||
yScale = (childMax - childMin) / (parentMax - parentMin);
|
||||
yShift = childMin - parentMin;
|
||||
}
|
||||
|
||||
private double xShift = 0;
|
||||
private double xScale = 1;
|
||||
private double yShift = 0;
|
||||
private double yScale = 1;
|
||||
|
||||
public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
|
||||
{
|
||||
DataRect parentVisible = parentViewport.Visible;
|
||||
|
||||
double xmin = parentVisible.XMin * xScale + xShift;
|
||||
double xmax = parentVisible.XMax * xScale + xShift;
|
||||
double ymin = parentVisible.YMin * yScale + yShift;
|
||||
double ymax = parentVisible.YMax * yScale + yShift;
|
||||
|
||||
return DataRect.Create(xmin, ymin, xmax, ymax);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
ViewportRestrictions/ViewportRestriction.cs
Normal file
41
ViewportRestrictions/ViewportRestriction.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using Microsoft.Research.DynamicDataDisplay.Common;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a base class for all restrictions that are being applied to viewport's visible rect.
|
||||
/// </summary>
|
||||
public abstract class ViewportRestriction
|
||||
{
|
||||
#region IViewportRestriction Members
|
||||
|
||||
/// <summary>
|
||||
/// Applies the restriction.
|
||||
/// </summary>
|
||||
/// <param name="previousDataRect">Previous data rectangle.</param>
|
||||
/// <param name="proposedDataRect">Proposed data rectangle.</param>
|
||||
/// <param name="viewport">The viewport, to which current restriction is being applied.</param>
|
||||
/// <returns>New changed visible rectangle.</returns>
|
||||
public abstract DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport);
|
||||
|
||||
/// <summary>
|
||||
/// Raises the changed event.
|
||||
/// </summary>
|
||||
protected void RaiseChanged()
|
||||
{
|
||||
Changed.Raise(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Occurs when restriction changes.
|
||||
/// Causes update of <see cref="Viewport"/>'s Visible property.
|
||||
/// </summary>
|
||||
public event EventHandler Changed;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user