Browse Source

Fix ScrollViewer.

Make various properties Direct properties, which gives them the correct
binding behavior.
pull/396/head
Steven Kirk 10 years ago
parent
commit
c052d389a9
  1. 27
      src/Perspex.Controls/Presenters/ScrollContentPresenter.cs
  2. 74
      src/Perspex.Controls/Primitives/RangeBase.cs
  3. 22
      src/Perspex.Controls/Primitives/Track.cs
  4. 37
      src/Perspex.Controls/ScrollViewer.cs
  5. 11
      tests/Perspex.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs

27
src/Perspex.Controls/Presenters/ScrollContentPresenter.cs

@ -21,19 +21,25 @@ namespace Perspex.Controls.Presenters
/// Defines the <see cref="Extent"/> property.
/// </summary>
public static readonly PerspexProperty<Size> ExtentProperty =
ScrollViewer.ExtentProperty.AddOwner<ScrollContentPresenter>();
ScrollViewer.ExtentProperty.AddOwner<ScrollContentPresenter>(
o => o.Extent,
(o, v) => o.Extent = v);
/// <summary>
/// Defines the <see cref="Offset"/> property.
/// </summary>
public static readonly PerspexProperty<Vector> OffsetProperty =
ScrollViewer.OffsetProperty.AddOwner<ScrollContentPresenter>();
ScrollViewer.OffsetProperty.AddOwner<ScrollContentPresenter>(
o => o.Offset,
(o, v) => o.Offset = v);
/// <summary>
/// Defines the <see cref="Viewport"/> property.
/// </summary>
public static readonly PerspexProperty<Size> ViewportProperty =
ScrollViewer.ViewportProperty.AddOwner<ScrollContentPresenter>();
ScrollViewer.ViewportProperty.AddOwner<ScrollContentPresenter>(
o => o.Viewport,
(o, v) => o.Viewport = v);
/// <summary>
/// Defines the <see cref="CanScrollHorizontally"/> property.
@ -41,8 +47,11 @@ namespace Perspex.Controls.Presenters
public static readonly PerspexProperty<bool> CanScrollHorizontallyProperty =
PerspexProperty.Register<ScrollContentPresenter, bool>("CanScrollHorizontally", true);
private Size _extent;
private Size _measuredExtent;
private Vector _offset;
private IDisposable _scrollableSubscription;
private Size _viewport;
/// <summary>
/// Initializes static members of the <see cref="ScrollContentPresenter"/> class.
@ -69,8 +78,8 @@ namespace Perspex.Controls.Presenters
/// </summary>
public Size Extent
{
get { return GetValue(ExtentProperty); }
private set { SetValue(ExtentProperty, value); }
get { return _extent; }
private set { SetAndRaise(ExtentProperty, ref _extent, value); }
}
/// <summary>
@ -78,8 +87,8 @@ namespace Perspex.Controls.Presenters
/// </summary>
public Vector Offset
{
get { return GetValue(OffsetProperty); }
set { SetValue(OffsetProperty, value); }
get { return _offset; }
set { SetAndRaise(OffsetProperty, ref _offset, value); }
}
/// <summary>
@ -87,8 +96,8 @@ namespace Perspex.Controls.Presenters
/// </summary>
public Size Viewport
{
get { return GetValue(ViewportProperty); }
private set { SetValue(ViewportProperty, value); }
get { return _viewport; }
private set { SetAndRaise(ViewportProperty, ref _viewport, value); }
}
/// <summary>

74
src/Perspex.Controls/Primitives/RangeBase.cs

@ -15,34 +15,38 @@ namespace Perspex.Controls.Primitives
/// Defines the <see cref="Minimum"/> property.
/// </summary>
public static readonly PerspexProperty<double> MinimumProperty =
PerspexProperty.Register<RangeBase, double>(
PerspexProperty.RegisterDirect<RangeBase, double>(
nameof(Minimum),
validate: ValidateMinimum);
o => o.Minimum,
(o, v) => o.Minimum = v);
/// <summary>
/// Defines the <see cref="Maximum"/> property.
/// </summary>
public static readonly PerspexProperty<double> MaximumProperty =
PerspexProperty.Register<RangeBase, double>(
PerspexProperty.RegisterDirect<RangeBase, double>(
nameof(Maximum),
defaultValue: 100.0,
validate: ValidateMaximum);
o => o.Maximum,
(o, v) => o.Maximum = v);
/// <summary>
/// Defines the <see cref="Value"/> property.
/// </summary>
public static readonly PerspexProperty<double> ValueProperty =
PerspexProperty.Register<RangeBase, double>(
PerspexProperty.RegisterDirect<RangeBase, double>(
nameof(Value),
validate: ValidateValue);
o => o.Value,
(o, v) => o.Value = v);
private double _minimum;
private double _maximum = 100.0;
private double _value;
/// <summary>
/// Initializes a new instance of the <see cref="RangeBase"/> class.
/// </summary>
public RangeBase()
{
AffectsValidation(MinimumProperty, MaximumProperty, ValueProperty);
AffectsValidation(MaximumProperty, ValueProperty);
}
/// <summary>
@ -50,8 +54,18 @@ namespace Perspex.Controls.Primitives
/// </summary>
public double Minimum
{
get { return GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
get
{
return _minimum;
}
set
{
value = ValidateMinimum(value);
SetAndRaise(MinimumProperty, ref _minimum, value);
Maximum = ValidateMaximum(Maximum);
Value = ValidateValue(Value);
}
}
/// <summary>
@ -59,8 +73,17 @@ namespace Perspex.Controls.Primitives
/// </summary>
public double Maximum
{
get { return GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
get
{
return _maximum;
}
set
{
value = ValidateMaximum(value);
SetAndRaise(MaximumProperty, ref _maximum, value);
Value = ValidateValue(Value);
}
}
/// <summary>
@ -68,8 +91,16 @@ namespace Perspex.Controls.Primitives
/// </summary>
public double Value
{
get { return GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
get
{
return _value;
}
set
{
value = ValidateValue(value);
SetAndRaise(ValueProperty, ref _value, value);
}
}
/// <summary>
@ -88,10 +119,9 @@ namespace Perspex.Controls.Primitives
/// <summary>
/// Validates the <see cref="Minimum"/> property.
/// </summary>
/// <param name="sender">The RangeBase control.</param>
/// <param name="value">The value.</param>
/// <returns>The coerced value.</returns>
private static double ValidateMinimum(RangeBase sender, double value)
private double ValidateMinimum(double value)
{
ValidateDouble(value, "Minimum");
return value;
@ -100,25 +130,23 @@ namespace Perspex.Controls.Primitives
/// <summary>
/// Validates/coerces the <see cref="Maximum"/> property.
/// </summary>
/// <param name="sender">The RangeBase control.</param>
/// <param name="value">The value.</param>
/// <returns>The coerced value.</returns>
private static double ValidateMaximum(RangeBase sender, double value)
private double ValidateMaximum(double value)
{
ValidateDouble(value, "Maximum");
return Math.Max(value, sender.Minimum);
return Math.Max(value, Minimum);
}
/// <summary>
/// Validates/coerces the <see cref="Value"/> property.
/// </summary>
/// <param name="sender">The RangeBase control.</param>
/// <param name="value">The value.</param>
/// <returns>The coerced value.</returns>
private static double ValidateValue(RangeBase sender, double value)
private double ValidateValue(double value)
{
ValidateDouble(value, "Value");
return MathUtilities.Clamp(value, sender.Minimum, sender.Maximum);
return MathUtilities.Clamp(value, Minimum, Maximum);
}
}
}

22
src/Perspex.Controls/Primitives/Track.cs

@ -11,13 +11,13 @@ namespace Perspex.Controls.Primitives
public class Track : Control
{
public static readonly PerspexProperty<double> MinimumProperty =
RangeBase.MinimumProperty.AddOwner<Track>();
RangeBase.MinimumProperty.AddOwner<Track>(o => o.Minimum, (o,v) => o.Minimum = v);
public static readonly PerspexProperty<double> MaximumProperty =
RangeBase.MaximumProperty.AddOwner<Track>();
RangeBase.MaximumProperty.AddOwner<Track>(o => o.Maximum, (o, v) => o.Maximum = v);
public static readonly PerspexProperty<double> ValueProperty =
RangeBase.ValueProperty.AddOwner<Track>();
RangeBase.ValueProperty.AddOwner<Track>(o => o.Value, (o, v) => o.Value = v);
public static readonly PerspexProperty<double> ViewportSizeProperty =
ScrollBar.ViewportSizeProperty.AddOwner<Track>();
@ -28,6 +28,10 @@ namespace Perspex.Controls.Primitives
public static readonly PerspexProperty<Thumb> ThumbProperty =
PerspexProperty.Register<Track, Thumb>("Thumb");
private double _minimum;
private double _maximum = 100.0;
private double _value;
static Track()
{
AffectsArrange(MinimumProperty);
@ -57,20 +61,20 @@ namespace Perspex.Controls.Primitives
public double Minimum
{
get { return GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
get { return _minimum; }
set { SetAndRaise(MinimumProperty, ref _minimum, value); }
}
public double Maximum
{
get { return GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
get { return _maximum; }
set { SetAndRaise(MaximumProperty, ref _maximum, value); }
}
public double Value
{
get { return GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
get { return _value; }
set { SetAndRaise(ValueProperty, ref _value, value); }
}
public double ViewportSize

37
src/Perspex.Controls/ScrollViewer.cs

@ -26,19 +26,26 @@ namespace Perspex.Controls
/// Defines the <see cref="Extent"/> property.
/// </summary>
public static readonly PerspexProperty<Size> ExtentProperty =
PerspexProperty.Register<ScrollViewer, Size>(nameof(Extent));
PerspexProperty.RegisterDirect<ScrollViewer, Size>(nameof(Extent),
o => o.Extent,
(o, v) => o.Extent = v);
/// <summary>
/// Defines the <see cref="Offset"/> property.
/// </summary>
public static readonly PerspexProperty<Vector> OffsetProperty =
PerspexProperty.Register<ScrollViewer, Vector>(nameof(Offset), validate: ValidateOffset);
PerspexProperty.RegisterDirect<ScrollViewer, Vector>(
nameof(Offset),
o => o.Offset,
(o, v) => o.Offset = v);
/// <summary>
/// Defines the <see cref="Viewport"/> property.
/// </summary>
public static readonly PerspexProperty<Size> ViewportProperty =
PerspexProperty.Register<ScrollViewer, Size>(nameof(Viewport));
PerspexProperty.RegisterDirect<ScrollViewer, Size>(nameof(Viewport),
o => o.Viewport,
(o, v) => o.Viewport = v);
/// <summary>
/// Defines the HorizontalScrollBarMaximum property.
@ -120,6 +127,10 @@ namespace Perspex.Controls
nameof(VerticalScrollBarVisibility),
ScrollBarVisibility.Auto);
private Size _extent;
private Vector _offset;
private Size _viewport;
/// <summary>
/// Initializes static members of the <see cref="ScrollViewer"/> class.
/// </summary>
@ -173,8 +184,8 @@ namespace Perspex.Controls
/// </summary>
public Size Extent
{
get { return GetValue(ExtentProperty); }
private set { SetValue(ExtentProperty, value); }
get { return _extent; }
private set { SetAndRaise(ExtentProperty, ref _extent, value); }
}
/// <summary>
@ -182,8 +193,16 @@ namespace Perspex.Controls
/// </summary>
public Vector Offset
{
get { return GetValue(OffsetProperty); }
set { SetValue(OffsetProperty, value); }
get
{
return _offset;
}
set
{
value = ValidateOffset(this, value);
SetAndRaise(OffsetProperty, ref _offset, value);
}
}
/// <summary>
@ -191,8 +210,8 @@ namespace Perspex.Controls
/// </summary>
public Size Viewport
{
get { return GetValue(ViewportProperty); }
private set { SetValue(ViewportProperty, value); }
get { return _viewport; }
private set { SetAndRaise(ViewportProperty, ref _viewport, value); }
}
/// <summary>

11
tests/Perspex.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs

@ -218,17 +218,6 @@ namespace Perspex.Controls.UnitTests.Presenters
Assert.False(target.IsArrangeValid);
}
[Fact]
public void Offset_Should_Be_Coerced_To_Viewport()
{
var target = new ScrollContentPresenter();
target.SetValue(ScrollContentPresenter.ExtentProperty, new Size(20, 20));
target.SetValue(ScrollContentPresenter.ViewportProperty, new Size(10, 10));
target.Offset = new Vector(12, 12);
Assert.Equal(new Vector(10, 10), target.Offset);
}
[Fact]
public void BringDescendentIntoView_Should_Update_Offset()
{

Loading…
Cancel
Save