diff --git a/Perspex.Controls/Perspex.Controls.csproj b/Perspex.Controls/Perspex.Controls.csproj
index e0b1dee911..8c3511e128 100644
--- a/Perspex.Controls/Perspex.Controls.csproj
+++ b/Perspex.Controls/Perspex.Controls.csproj
@@ -71,7 +71,7 @@
-
+
diff --git a/Perspex.Controls/Presenters/ScrollContentPresenter.cs b/Perspex.Controls/Presenters/ScrollContentPresenter.cs
index e7e18590e4..4ec114cacc 100644
--- a/Perspex.Controls/Presenters/ScrollContentPresenter.cs
+++ b/Perspex.Controls/Presenters/ScrollContentPresenter.cs
@@ -36,8 +36,6 @@ namespace Perspex.Controls.Presenters
public ScrollContentPresenter()
{
- this.GetObservable(ContentProperty).Subscribe(this.ContentChanged);
-
this.AddHandler(
Control.RequestBringIntoViewEvent,
new EventHandler(this.BringIntoViewRequested));
@@ -145,21 +143,5 @@ namespace Perspex.Controls.Presenters
this.Offset = offset;
}
-
- private void ContentChanged(object content)
- {
- var scrollInfo = content as IScrollInfo;
-
- if (this.contentBindings != null)
- {
- this.contentBindings.Dispose();
- this.contentBindings = null;
- }
-
- if (scrollInfo != null)
- {
- this.contentBindings = this.Bind(CanScrollHorizontallyProperty, scrollInfo.CanScrollHorizontally);
- }
- }
}
}
diff --git a/Perspex.Controls/Presenters/TextPresenter.cs b/Perspex.Controls/Presenters/TextPresenter.cs
index 4c6abb5d54..da81f29dec 100644
--- a/Perspex.Controls/Presenters/TextPresenter.cs
+++ b/Perspex.Controls/Presenters/TextPresenter.cs
@@ -16,7 +16,7 @@ namespace Perspex.Controls
using Perspex.Media;
using Perspex.Threading;
- public class TextPresenter : TextBlock, IScrollInfo
+ public class TextPresenter : TextBlock
{
public static readonly PerspexProperty AcceptsReturnProperty =
TextBox.AcceptsReturnProperty.AddOwner();
@@ -97,16 +97,6 @@ namespace Perspex.Controls
get { return base.FormattedText; }
}
- IObservable IScrollInfo.CanScrollHorizontally
- {
- get { return this.canScrollHorizontally; }
- }
-
- IObservable IScrollInfo.IsHorizontalScrollBarVisible
- {
- get { return Observable.Never().StartWith(false); }
- }
-
public int GetCaretIndex(Point point)
{
var hit = this.FormattedText.HitTestPoint(point);
diff --git a/Perspex.Controls/Primitives/IScrollInfo.cs b/Perspex.Controls/Primitives/IScrollInfo.cs
deleted file mode 100644
index 7e60b18558..0000000000
--- a/Perspex.Controls/Primitives/IScrollInfo.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
-
-namespace Perspex.Controls.Primitives
-{
- using System;
-
- ///
- /// Allows the child of a to communicate with the scroll viewer.
- ///
- ///
- /// Note that this interface has a different purpose to IScrollInfo in WPF! I would give it
- /// a different name, but it does what it suggests - give information about the scrolling
- /// requirements of a control.
- ///
- public interface IScrollInfo
- {
- IObservable CanScrollHorizontally { get; }
-
- IObservable IsHorizontalScrollBarVisible { get; }
- }
-}
diff --git a/Perspex.Controls/Primitives/ScrollBar.cs b/Perspex.Controls/Primitives/ScrollBar.cs
index 5a8c0f683f..18d48b9fd9 100644
--- a/Perspex.Controls/Primitives/ScrollBar.cs
+++ b/Perspex.Controls/Primitives/ScrollBar.cs
@@ -7,6 +7,7 @@
namespace Perspex.Controls.Primitives
{
using System;
+ using System.Reactive;
using System.Reactive.Linq;
public class ScrollBar : TemplatedControl
@@ -23,6 +24,9 @@ namespace Perspex.Controls.Primitives
public static readonly PerspexProperty ViewportSizeProperty =
PerspexProperty.Register("ViewportSize", defaultValue: double.NaN);
+ public static readonly PerspexProperty VisibilityProperty =
+ PerspexProperty.Register("Visibility");
+
public static readonly PerspexProperty OrientationProperty =
PerspexProperty.Register("Orientation");
@@ -32,6 +36,17 @@ namespace Perspex.Controls.Primitives
Control.PseudoClass(OrientationProperty, x => x == Orientation.Vertical, ":vertical");
}
+ public ScrollBar()
+ {
+ var isVisible = Observable.Merge(
+ this.GetObservable(MinimumProperty).Select(_ => Unit.Default),
+ this.GetObservable(MaximumProperty).Select(_ => Unit.Default),
+ this.GetObservable(ViewportSizeProperty).Select(_ => Unit.Default),
+ this.GetObservable(VisibilityProperty).Select(_ => Unit.Default))
+ .Select(_ => this.CalculateIsVisible());
+ this.Bind(IsVisibleProperty, isVisible, BindingPriority.Style);
+ }
+
public double Minimum
{
get { return this.GetValue(MinimumProperty); }
@@ -56,6 +71,12 @@ namespace Perspex.Controls.Primitives
set { this.SetValue(ViewportSizeProperty, value); }
}
+ public ScrollBarVisibility Visibility
+ {
+ get { return this.GetValue(VisibilityProperty); }
+ set { this.SetValue(VisibilityProperty, value); }
+ }
+
public Orientation Orientation
{
get { return this.GetValue(OrientationProperty); }
@@ -66,5 +87,24 @@ namespace Perspex.Controls.Primitives
{
return base.MeasureOverride(availableSize);
}
+
+ private bool CalculateIsVisible()
+ {
+ switch (this.Visibility)
+ {
+ case ScrollBarVisibility.Visible:
+ return true;
+
+ case ScrollBarVisibility.Hidden:
+ return false;
+
+ case ScrollBarVisibility.Auto:
+ var viewportSize = this.ViewportSize;
+ return double.IsNaN(viewportSize) || viewportSize < this.Maximum - this.Minimum;
+
+ default:
+ throw new InvalidOperationException("Invalid value for ScrollBar.Visibility.");
+ }
+ }
}
}
diff --git a/Perspex.Controls/Primitives/ScrollBarVisibility.cs b/Perspex.Controls/Primitives/ScrollBarVisibility.cs
new file mode 100644
index 0000000000..8f4c275f2f
--- /dev/null
+++ b/Perspex.Controls/Primitives/ScrollBarVisibility.cs
@@ -0,0 +1,15 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Controls.Primitives
+{
+ public enum ScrollBarVisibility
+ {
+ Visible,
+ Hidden,
+ Auto,
+ }
+}
diff --git a/Perspex.Controls/ScrollViewer.cs b/Perspex.Controls/ScrollViewer.cs
index ae95d38808..9cedfc2442 100644
--- a/Perspex.Controls/ScrollViewer.cs
+++ b/Perspex.Controls/ScrollViewer.cs
@@ -23,10 +23,7 @@ namespace Perspex.Controls
PerspexProperty.Register("Viewport");
public static readonly PerspexProperty CanScrollHorizontallyProperty =
- PerspexProperty.Register("CanScrollHorizontally", false);
-
- public static readonly PerspexProperty IsHorizontalScrollBarVisibleProperty =
- PerspexProperty.Register("IsHorizontalScrollBarVisible");
+ PerspexProperty.RegisterAttached("CanScrollHorizontally", false);
public static readonly PerspexProperty HorizontalScrollBarMaximumProperty =
PerspexProperty.Register("HorizontalScrollBarMaximum");
@@ -37,8 +34,8 @@ namespace Perspex.Controls
public static readonly PerspexProperty HorizontalScrollBarViewportSizeProperty =
PerspexProperty.Register("HorizontalScrollBarViewportSize");
- public static readonly PerspexProperty IsVerticalScrollBarVisibleProperty =
- PerspexProperty.Register("IsVerticalScrollBarVisible");
+ public static readonly PerspexProperty HorizontalScrollBarVisibilityProperty =
+ PerspexProperty.RegisterAttached("HorizontalScrollBarVisibility", ScrollBarVisibility.Auto);
public static readonly PerspexProperty VerticalScrollBarMaximumProperty =
PerspexProperty.Register("VerticalScrollBarMaximum");
@@ -49,6 +46,9 @@ namespace Perspex.Controls
public static readonly PerspexProperty VerticalScrollBarViewportSizeProperty =
PerspexProperty.Register("VerticalScrollBarViewportSize");
+ public static readonly PerspexProperty VerticalScrollBarVisibilityProperty =
+ PerspexProperty.RegisterAttached("VerticalScrollBarVisibility", ScrollBarVisibility.Auto);
+
private IDisposable contentBindings;
static ScrollViewer()
@@ -64,31 +64,21 @@ namespace Perspex.Controls
this.GetObservable(ViewportProperty))
.Select(x => new { Extent = x[0], Viewport = x[1] });
- this.Bind(
- IsHorizontalScrollBarVisibleProperty,
- extentAndViewport.Select(x => x.Extent.Width > x.Viewport.Width),
- BindingPriority.Style);
-
this.Bind(
HorizontalScrollBarMaximumProperty,
- extentAndViewport.Select(x => x.Extent.Width - x.Viewport.Width));
+ extentAndViewport.Select(x => Math.Max(x.Extent.Width - x.Viewport.Width, 0)));
this.Bind(
HorizontalScrollBarViewportSizeProperty,
- extentAndViewport.Select(x => (x.Viewport.Width / x.Extent.Width) * (x.Extent.Width - x.Viewport.Width)));
-
- this.Bind(
- IsVerticalScrollBarVisibleProperty,
- extentAndViewport.Select(x => x.Extent.Height > x.Viewport.Height),
- BindingPriority.Style);
+ extentAndViewport.Select(x => Math.Max((x.Viewport.Width / x.Extent.Width) * (x.Extent.Width - x.Viewport.Width), 0)));
this.Bind(
VerticalScrollBarMaximumProperty,
- extentAndViewport.Select(x => x.Extent.Height - x.Viewport.Height));
+ extentAndViewport.Select(x => Math.Max(x.Extent.Height - x.Viewport.Height, 0)));
this.Bind(
VerticalScrollBarViewportSizeProperty,
- extentAndViewport.Select(x => (x.Viewport.Height / x.Extent.Height) * (x.Extent.Height - x.Viewport.Height)));
+ extentAndViewport.Select(x => Math.Max((x.Viewport.Height / x.Extent.Height) * (x.Extent.Height - x.Viewport.Height), 0)));
this.GetObservable(OffsetProperty).Subscribe(x =>
{
@@ -101,8 +91,6 @@ namespace Perspex.Controls
this.GetObservable(VerticalScrollBarValueProperty))
.Select(x => new Vector(x[0], x[1]))
.Subscribe(x => this.Offset = x);
-
- this.GetObservable(ContentProperty).Subscribe(this.ContentChanged);
}
public Size Extent
@@ -129,6 +117,18 @@ namespace Perspex.Controls
set { this.SetValue(CanScrollHorizontallyProperty, value); }
}
+ public ScrollBarVisibility HorizontalScrollBarVisibility
+ {
+ get { return this.GetValue(HorizontalScrollBarVisibilityProperty); }
+ set { this.SetValue(HorizontalScrollBarVisibilityProperty, value); }
+ }
+
+ public ScrollBarVisibility VerticalScrollBarVisibility
+ {
+ get { return this.GetValue(VerticalScrollBarVisibilityProperty); }
+ set { this.SetValue(VerticalScrollBarVisibilityProperty, value); }
+ }
+
protected override Size MeasureOverride(Size availableSize)
{
return base.MeasureOverride(availableSize);
@@ -156,23 +156,5 @@ namespace Perspex.Controls
return value;
}
}
-
- private void ContentChanged(object content)
- {
- var scrollInfo = content as IScrollInfo;
-
- if (this.contentBindings != null)
- {
- this.contentBindings.Dispose();
- this.contentBindings = null;
- }
-
- if (scrollInfo != null)
- {
- this.contentBindings = this.Bind(
- IsHorizontalScrollBarVisibleProperty,
- scrollInfo.IsHorizontalScrollBarVisible);
- }
- }
}
}
diff --git a/Perspex.Controls/TextBox.cs b/Perspex.Controls/TextBox.cs
index 19029cc43a..47eef390fb 100644
--- a/Perspex.Controls/TextBox.cs
+++ b/Perspex.Controls/TextBox.cs
@@ -7,6 +7,7 @@
namespace Perspex.Controls
{
using System;
+ using System.Reactive.Linq;
using Perspex.Controls.Primitives;
public class TextBox : TemplatedControl
@@ -32,6 +33,25 @@ namespace Perspex.Controls
public static readonly PerspexProperty TextWrappingProperty =
TextBlock.TextWrappingProperty.AddOwner();
+ public TextBox()
+ {
+ var canScrollHorizontally = this.GetObservable(AcceptsReturnProperty)
+ .Select(x => !x);
+
+ this.Bind(
+ ScrollViewer.CanScrollHorizontallyProperty,
+ canScrollHorizontally,
+ BindingPriority.Style);
+
+ var horizontalScrollBarVisibility = this.GetObservable(AcceptsReturnProperty)
+ .Select(x => x ? ScrollBarVisibility.Auto : ScrollBarVisibility.Hidden);
+
+ this.Bind(
+ ScrollViewer.HorizontalScrollBarVisibilityProperty,
+ horizontalScrollBarVisibility,
+ BindingPriority.Style);
+ }
+
public bool AcceptsReturn
{
get { return this.GetValue(AcceptsReturnProperty); }
diff --git a/Perspex.Themes.Default/ScrollViewerStyle.cs b/Perspex.Themes.Default/ScrollViewerStyle.cs
index a1ff62f6a7..a1d51c9024 100644
--- a/Perspex.Themes.Default/ScrollViewerStyle.cs
+++ b/Perspex.Themes.Default/ScrollViewerStyle.cs
@@ -58,20 +58,20 @@ namespace Perspex.Themes.Default
{
Id = "horizontalScrollBar",
Orientation = Orientation.Horizontal,
- [~ScrollBar.IsVisibleProperty] = control[~ScrollViewer.IsHorizontalScrollBarVisibleProperty],
[~ScrollBar.MaximumProperty] = control[~ScrollViewer.HorizontalScrollBarMaximumProperty],
[~~ScrollBar.ValueProperty] = control[~~ScrollViewer.HorizontalScrollBarValueProperty],
[~ScrollBar.ViewportSizeProperty] = control[~ScrollViewer.HorizontalScrollBarViewportSizeProperty],
+ [~ScrollBar.VisibilityProperty] = control[~ScrollViewer.HorizontalScrollBarVisibilityProperty],
[Grid.RowProperty] = 1,
},
new ScrollBar
{
Id = "verticalScrollBar",
Orientation = Orientation.Vertical,
- [~ScrollBar.IsVisibleProperty] = control[~ScrollViewer.IsVerticalScrollBarVisibleProperty],
[~ScrollBar.MaximumProperty] = control[~ScrollViewer.VerticalScrollBarMaximumProperty],
[~~ScrollBar.ValueProperty] = control[~~ScrollViewer.VerticalScrollBarValueProperty],
[~ScrollBar.ViewportSizeProperty] = control[~ScrollViewer.VerticalScrollBarViewportSizeProperty],
+ [~ScrollBar.VisibilityProperty] = control[~ScrollViewer.VerticalScrollBarVisibilityProperty],
[Grid.ColumnProperty] = 1,
},
},
diff --git a/Perspex.Themes.Default/TextBoxStyle.cs b/Perspex.Themes.Default/TextBoxStyle.cs
index 0c609a9a06..065e2c7831 100644
--- a/Perspex.Themes.Default/TextBoxStyle.cs
+++ b/Perspex.Themes.Default/TextBoxStyle.cs
@@ -49,6 +49,9 @@ namespace Perspex.Themes.Default
[~Border.BorderThicknessProperty] = control[~TextBox.BorderThicknessProperty],
Content = new ScrollViewer
{
+ [~ScrollViewer.CanScrollHorizontallyProperty] = control[~ScrollViewer.CanScrollHorizontallyProperty],
+ [~ScrollViewer.HorizontalScrollBarVisibilityProperty] = control[~ScrollViewer.HorizontalScrollBarVisibilityProperty],
+ [~ScrollViewer.VerticalScrollBarVisibilityProperty] = control[~ScrollViewer.VerticalScrollBarVisibilityProperty],
Content = new TextPresenter
{
[~TextPresenter.AcceptsReturnProperty] = control[~TextBox.AcceptsReturnProperty],