Browse Source
Currently works so far as to scroll an image in the Images tab of the test app. Hiding the scrollbars is currently disabled as it requires a layout pass to be triggered during a layout pass. Need to work out a way around that...pull/4/head
10 changed files with 282 additions and 5 deletions
@ -0,0 +1,78 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="ScrollContentPresenter.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Controls.Presenters |
|||
{ |
|||
using System.Linq; |
|||
using Perspex.Layout; |
|||
|
|||
public class ScrollContentPresenter : ContentPresenter |
|||
{ |
|||
public static PerspexProperty<Size> ExtentProperty = |
|||
ScrollViewer.ExtentProperty.AddOwner<ScrollContentPresenter>(); |
|||
|
|||
public static PerspexProperty<Vector> OffsetProperty = |
|||
ScrollViewer.OffsetProperty.AddOwner<ScrollContentPresenter>(); |
|||
|
|||
public static PerspexProperty<Size> ViewportProperty = |
|||
ScrollViewer.ViewportProperty.AddOwner<ScrollContentPresenter>(); |
|||
|
|||
public ScrollContentPresenter() |
|||
{ |
|||
AffectsRender(OffsetProperty); |
|||
} |
|||
|
|||
public Size Extent |
|||
{ |
|||
get { return this.GetValue(ExtentProperty); } |
|||
private set { this.SetValue(ExtentProperty, value); } |
|||
} |
|||
|
|||
public Vector Offset |
|||
{ |
|||
get { return this.GetValue(OffsetProperty); } |
|||
set { this.SetValue(OffsetProperty, value); } |
|||
} |
|||
|
|||
public Size Viewport |
|||
{ |
|||
get { return this.GetValue(ViewportProperty); } |
|||
private set { this.SetValue(ViewportProperty, value); } |
|||
} |
|||
|
|||
protected override Size MeasureOverride(Size availableSize) |
|||
{ |
|||
var content = this.Content as ILayoutable; |
|||
|
|||
if (content != null) |
|||
{ |
|||
content.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); |
|||
var size = content.DesiredSize.Value; |
|||
this.Extent = size; |
|||
return size.Constrain(availableSize); |
|||
} |
|||
else |
|||
{ |
|||
return this.Extent = new Size(); |
|||
} |
|||
} |
|||
|
|||
protected override Size ArrangeOverride(Size finalSize) |
|||
{ |
|||
var child = this.GetVisualChildren().SingleOrDefault() as ILayoutable; |
|||
|
|||
this.Viewport = finalSize; |
|||
|
|||
if (child != null) |
|||
{ |
|||
child.Arrange(new Rect((Point)(-this.Offset), child.DesiredSize.Value)); |
|||
return finalSize; |
|||
} |
|||
|
|||
return new Size(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="DefinitionBase.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
using System.Reactive.Linq; |
|||
using Perspex.Controls.Presenters; |
|||
using Perspex.Controls.Primitives; |
|||
|
|||
namespace Perspex.Controls |
|||
{ |
|||
public class ScrollViewer : ContentControl |
|||
{ |
|||
public static PerspexProperty<Size> ExtentProperty = |
|||
PerspexProperty.Register<ScrollViewer, Size>("Extent"); |
|||
|
|||
public static PerspexProperty<Vector> OffsetProperty = |
|||
PerspexProperty.Register<ScrollViewer, Vector>("Offset"); |
|||
|
|||
public static PerspexProperty<Size> ViewportProperty = |
|||
PerspexProperty.Register<ScrollViewer, Size>("Viewport"); |
|||
|
|||
private ScrollContentPresenter presenter; |
|||
|
|||
private ScrollBar horizontalScrollBar; |
|||
|
|||
private ScrollBar verticalScrollBar; |
|||
|
|||
public Size Extent |
|||
{ |
|||
get { return this.GetValue(ExtentProperty); } |
|||
private set { this.SetValue(ExtentProperty, value); } |
|||
} |
|||
|
|||
public Vector Offset |
|||
{ |
|||
get { return this.GetValue(OffsetProperty); } |
|||
set { this.SetValue(OffsetProperty, value); } |
|||
} |
|||
|
|||
public Size Viewport |
|||
{ |
|||
get { return this.GetValue(ViewportProperty); } |
|||
private set { this.SetValue(ViewportProperty, value); } |
|||
} |
|||
|
|||
protected override void OnTemplateApplied() |
|||
{ |
|||
this.presenter = this.GetTemplateChild<ScrollContentPresenter>("presenter"); |
|||
this.horizontalScrollBar = this.GetTemplateChild<ScrollBar>("horizontalScrollBar"); |
|||
this.verticalScrollBar = this.GetTemplateChild<ScrollBar>("verticalScrollBar"); |
|||
|
|||
this[!ExtentProperty] = this.presenter[!ExtentProperty]; |
|||
this[!ViewportProperty] = this.presenter[!ViewportProperty]; |
|||
this.presenter[!OffsetProperty] = this[!OffsetProperty]; |
|||
|
|||
var extentAndViewport = Observable.CombineLatest( |
|||
this.GetObservable(ExtentProperty).StartWith(this.Extent), |
|||
this.GetObservable(ViewportProperty).StartWith(this.Viewport)) |
|||
.Select(x => new { Extent = x[0], Viewport = x[1] }); |
|||
|
|||
//this.horizontalScrollBar.Bind(
|
|||
// IsVisibleProperty,
|
|||
// extentAndViewport.Select(x => x.Extent.Width > x.Viewport.Width));
|
|||
|
|||
this.horizontalScrollBar.Bind( |
|||
ScrollBar.MaximumProperty, |
|||
extentAndViewport.Select(x => x.Extent.Width)); |
|||
|
|||
this.horizontalScrollBar.Bind( |
|||
ScrollBar.ViewportSizeProperty, |
|||
extentAndViewport.Select(x => x.Viewport.Width)); |
|||
|
|||
//this.verticalScrollBar.Bind(
|
|||
// IsVisibleProperty,
|
|||
// extentAndViewport.Select(x => x.Extent.Height > x.Viewport.Height));
|
|||
|
|||
this.verticalScrollBar.Bind( |
|||
ScrollBar.MaximumProperty, |
|||
extentAndViewport.Select(x => x.Extent.Height)); |
|||
|
|||
this.verticalScrollBar.Bind( |
|||
ScrollBar.ViewportSizeProperty, |
|||
extentAndViewport.Select(x => x.Viewport.Height)); |
|||
|
|||
var offset = Observable.CombineLatest( |
|||
this.horizontalScrollBar.GetObservable(ScrollBar.ValueProperty), |
|||
this.verticalScrollBar.GetObservable(ScrollBar.ValueProperty)) |
|||
.Select(x => new Vector(x[0], x[1])); |
|||
|
|||
this.Bind(OffsetProperty, offset); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="ScrollViewerStyle.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Themes.Default |
|||
{ |
|||
using System.Linq; |
|||
using Perspex.Controls; |
|||
using Perspex.Controls.Presenters; |
|||
using Perspex.Controls.Primitives; |
|||
using Perspex.Media; |
|||
using Perspex.Styling; |
|||
|
|||
public class ScrollViewerStyle : Styles |
|||
{ |
|||
public ScrollViewerStyle() |
|||
{ |
|||
this.AddRange(new[] |
|||
{ |
|||
new Style(x => x.OfType<ScrollViewer>()) |
|||
{ |
|||
Setters = new[] |
|||
{ |
|||
new Setter(ScrollViewer.TemplateProperty, ControlTemplate.Create<ScrollViewer>(this.Template)), |
|||
}, |
|||
}, |
|||
}); |
|||
} |
|||
|
|||
private Control Template(ScrollViewer control) |
|||
{ |
|||
return new Grid |
|||
{ |
|||
ColumnDefinitions = new ColumnDefinitions |
|||
{ |
|||
new ColumnDefinition(1, GridUnitType.Star), |
|||
new ColumnDefinition(GridLength.Auto), |
|||
}, |
|||
RowDefinitions = new RowDefinitions |
|||
{ |
|||
new RowDefinition(1, GridUnitType.Star), |
|||
new RowDefinition(GridLength.Auto), |
|||
}, |
|||
Children = new Controls |
|||
{ |
|||
new ScrollContentPresenter |
|||
{ |
|||
Id = "presenter", |
|||
[~ContentPresenter.ContentProperty] = control[~ScrollViewer.ContentProperty], |
|||
}, |
|||
new ScrollBar |
|||
{ |
|||
Id = "horizontalScrollBar", |
|||
Orientation = Orientation.Horizontal, |
|||
[Grid.RowProperty] = 1, |
|||
}, |
|||
new ScrollBar |
|||
{ |
|||
Id = "verticalScrollBar", |
|||
Orientation = Orientation.Vertical, |
|||
[Grid.ColumnProperty] = 1, |
|||
}, |
|||
}, |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue