Browse Source

Basic implementation of scrollbar.

Horizontal only so far. VERY HACKY.
pull/4/head
Steven Kirk 11 years ago
parent
commit
f99509fc11
  1. 2
      Perspex.Base/PerspexListExtensions.cs
  2. 2
      Perspex.Controls/Perspex.Controls.csproj
  3. 56
      Perspex.Controls/Primitives/ScrollBar.cs
  4. 151
      Perspex.Controls/Primitives/Track.cs
  5. 4
      Perspex.Diagnostics/ViewModels/ControlDetails.cs
  6. 30
      Perspex.Layout/Layoutable.cs
  7. 1
      Perspex.Themes.Default/DefaultTheme.cs
  8. 1
      Perspex.Themes.Default/Perspex.Themes.Default.csproj
  9. 61
      Perspex.Themes.Default/ScrollBarStyle.cs
  10. 237
      TestApplication/Program.cs

2
Perspex.Base/PerspexListExtensions.cs

@ -56,8 +56,6 @@ namespace Perspex
collection.CollectionChanged += handler;
System.Diagnostics.Debug.WriteLine("Tracked " + collection.GetHashCode());
return Disposable.Create(() => collection.CollectionChanged -= handler);
}

2
Perspex.Controls/Perspex.Controls.csproj

@ -66,6 +66,7 @@
<Compile Include="ItemsPanelTemplate.cs" />
<Compile Include="Presenters\ItemsPresenter.cs" />
<Compile Include="Panel.cs" />
<Compile Include="Primitives\Track.cs" />
<Compile Include="Primitives\Thumb.cs" />
<Compile Include="RowDefinition.cs" />
<Compile Include="RowDefinitions.cs" />
@ -73,6 +74,7 @@
<Compile Include="Shapes\Path.cs" />
<Compile Include="Shapes\Rectangle.cs" />
<Compile Include="Shapes\Shape.cs" />
<Compile Include="Primitives\ScrollBar.cs" />
<Compile Include="StackPanel.cs" />
<Compile Include="TabControl.cs" />
<Compile Include="TabItem.cs" />

56
Perspex.Controls/Primitives/ScrollBar.cs

@ -0,0 +1,56 @@
// -----------------------------------------------------------------------
// <copyright file="ScrollBar.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls.Primitives
{
public class ScrollBar : TemplatedControl
{
public static readonly PerspexProperty<double> MinimumProperty =
PerspexProperty.Register<ScrollBar, double>("Minimum");
public static readonly PerspexProperty<double> MaximumProperty =
PerspexProperty.Register<ScrollBar, double>("Maximum", defaultValue: 100.0);
public static readonly PerspexProperty<double> ValueProperty =
PerspexProperty.Register<ScrollBar, double>("Value");
public static readonly PerspexProperty<double> ViewportSizeProperty =
PerspexProperty.Register<ScrollBar, double>("ViewportSize", defaultValue: double.NaN);
public static readonly PerspexProperty<Orientation> OrientationProperty =
PerspexProperty.Register<ScrollBar, Orientation>("Orientation");
public double Minimum
{
get { return this.GetValue(MinimumProperty); }
set { this.SetValue(MinimumProperty, value); }
}
public double Maximum
{
get { return this.GetValue(MaximumProperty); }
set { this.SetValue(MaximumProperty, value); }
}
public double Value
{
get { return this.GetValue(ValueProperty); }
set { this.SetValue(ValueProperty, value); }
}
public double ViewportSize
{
get { return this.GetValue(ViewportSizeProperty); }
set { this.SetValue(ViewportSizeProperty, value); }
}
public Orientation Orientation
{
get { return this.GetValue(OrientationProperty); }
set { this.SetValue(OrientationProperty, value); }
}
}
}

151
Perspex.Controls/Primitives/Track.cs

@ -0,0 +1,151 @@
// -----------------------------------------------------------------------
// <copyright file="Thumb.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls.Primitives
{
using System;
using Perspex.Input;
using Perspex.Interactivity;
public class Track : Control
{
public static readonly PerspexProperty<double> MinimumProperty =
ScrollBar.MinimumProperty.AddOwner<Track>();
public static readonly PerspexProperty<double> MaximumProperty =
ScrollBar.MaximumProperty.AddOwner<Track>();
public static readonly PerspexProperty<double> ValueProperty =
ScrollBar.ValueProperty.AddOwner<Track>();
public static readonly PerspexProperty<double> ViewportSizeProperty =
ScrollBar.ViewportSizeProperty.AddOwner<Track>();
public static readonly PerspexProperty<Orientation> OrientationProperty =
ScrollBar.OrientationProperty.AddOwner<Track>();
public static readonly PerspexProperty<Thumb> ThumbProperty =
PerspexProperty.Register<Track, Thumb>("Thumb");
public Track()
{
this.GetObservableWithHistory(ThumbProperty).Subscribe(val =>
{
if (val.Item1 != null)
{
val.Item1.DragDelta -= ThumbDragged;
}
this.ClearVisualChildren();
if (val.Item2 != null)
{
val.Item2.DragDelta += ThumbDragged;
this.AddVisualChild(val.Item2);
}
});
AffectsArrange(MinimumProperty);
AffectsArrange(MaximumProperty);
AffectsArrange(ValueProperty);
}
public double Minimum
{
get { return this.GetValue(MinimumProperty); }
set { this.SetValue(MinimumProperty, value); }
}
public double Maximum
{
get { return this.GetValue(MaximumProperty); }
set { this.SetValue(MaximumProperty, value); }
}
public double Value
{
get { return this.GetValue(ValueProperty); }
set { this.SetValue(ValueProperty, value); }
}
public double ViewportSize
{
get { return this.GetValue(ViewportSizeProperty); }
set { this.SetValue(ViewportSizeProperty, value); }
}
public Orientation Orientation
{
get { return this.GetValue(OrientationProperty); }
set { this.SetValue(OrientationProperty, value); }
}
public Thumb Thumb
{
get { return this.GetValue(ThumbProperty); }
set { this.SetValue(ThumbProperty, value); }
}
protected override Size MeasureOverride(Size availableSize)
{
var thumb = this.Thumb;
if (thumb != null)
{
thumb.Measure(availableSize);
if (this.Orientation == Orientation.Horizontal)
{
return new Size(0, thumb.DesiredSize.Value.Height);
}
else
{
return new Size(thumb.DesiredSize.Value.Width, 0);
}
}
return base.MeasureOverride(availableSize);
}
protected override Size ArrangeOverride(Size finalSize)
{
var thumb = this.Thumb;
if (thumb != null)
{
var range = this.Maximum - this.Minimum;
var thumbsize = this.ViewportSize / range;
if (this.Orientation == Orientation.Horizontal)
{
var width = finalSize.Width * thumbsize;
var x = finalSize.Width * (this.Value / range);
thumb.Arrange(new Rect(x, 0, width, finalSize.Height));
}
else
{
}
}
return finalSize;
}
private void ThumbDragged(object sender, VectorEventArgs e)
{
var range = this.Maximum - this.Minimum;
if (this.Orientation == Orientation.Horizontal)
{
var value = this.Value + e.Vector.X * (range / this.ActualSize.Width);
value = Math.Max(value, this.Minimum);
value = Math.Min(value, this.Maximum - this.ViewportSize);
this.Value = value;
}
}
}
}

4
Perspex.Diagnostics/ViewModels/ControlDetails.cs

@ -18,7 +18,9 @@ namespace Perspex.Diagnostics.ViewModels
if (po != null)
{
this.Properties = po.GetAllValues().Select(x => new PropertyDetails(x));
this.Properties = po.GetAllValues()
.Select(x => new PropertyDetails(x))
.OrderBy(x => x.Name);
}
}

30
Perspex.Layout/Layoutable.cs

@ -28,6 +28,9 @@ namespace Perspex.Layout
public class Layoutable : Visual, ILayoutable, IEnableLogger
{
public static readonly PerspexProperty<Size> ActualSizeProperty =
PerspexProperty.Register<Layoutable, Size>("ActualSize");
public static readonly PerspexProperty<double> WidthProperty =
PerspexProperty.Register<Layoutable, double>("Width", double.NaN);
@ -111,7 +114,7 @@ namespace Perspex.Layout
public Size ActualSize
{
get { return ((IVisual)this).Bounds.Size; }
get { return this.GetValue(ActualSizeProperty); }
}
public Size? DesiredSize
@ -218,7 +221,9 @@ namespace Perspex.Layout
break;
}
this.SetVisualBounds(new Rect(originX, originY, sizeX, sizeY));
var bounds = new Rect(originX, originY, sizeX, sizeY);
this.SetVisualBounds(bounds);
this.SetValue(ActualSizeProperty, bounds.Size);
}
protected virtual Size ArrangeOverride(Size finalSize)
@ -237,9 +242,28 @@ namespace Perspex.Layout
{
availableSize = LayoutHelper.ApplyLayoutConstraints(this, availableSize)
.Deflate(this.Margin);
var measured = this.MeasureOverride(availableSize);
var width = measured.Width;
var height = measured.Height;
if (!double.IsNaN(this.Width))
{
width = this.Width;
}
width = Math.Min(width, this.MaxWidth);
width = Math.Max(width, this.MinWidth);
if (!double.IsNaN(this.Height))
{
height = this.Height;
}
height = Math.Min(height, this.MaxHeight);
height = Math.Max(height, this.MinHeight);
return measured.Inflate(this.Margin);
return new Size(width, height).Inflate(this.Margin);
}
else
{

1
Perspex.Themes.Default/DefaultTheme.cs

@ -17,6 +17,7 @@ namespace Perspex.Themes.Default
this.Add(new ContentControlStyle());
this.Add(new GridSplitterStyle());
this.Add(new ItemsControlStyle());
this.Add(new ScrollBarStyle());
this.Add(new TabControlStyle());
this.Add(new TabItemStyle());
this.Add(new TabStripStyle());

1
Perspex.Themes.Default/Perspex.Themes.Default.csproj

@ -66,6 +66,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="ScrollBarStyle.cs" />
<Compile Include="GridSplitterStyle.cs" />
<Compile Include="ButtonStyle.cs" />
<Compile Include="CheckBoxStyle.cs" />

61
Perspex.Themes.Default/ScrollBarStyle.cs

@ -0,0 +1,61 @@
// -----------------------------------------------------------------------
// <copyright file="ScrollBarStyle.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 ScrollBarStyle : Styles
{
public ScrollBarStyle()
{
this.AddRange(new[]
{
new Style(x => x.OfType<ScrollBar>())
{
Setters = new[]
{
new Setter(ScrollBar.TemplateProperty, ControlTemplate.Create<ScrollBar>(this.Template)),
new Setter(ScrollBar.HeightProperty, 20.0),
},
},
});
}
private Control Template(ScrollBar control)
{
return new Border
{
Background = Brushes.Silver,
Content = new Track
{
[~Track.MinimumProperty] = control[~ScrollBar.MinimumProperty],
[~Track.MaximumProperty] = control[~ScrollBar.MaximumProperty],
[~Track.ValueProperty] = control[~ScrollBar.ValueProperty],
[~Track.ViewportSizeProperty] = control[~ScrollBar.ViewportSizeProperty],
[~Track.OrientationProperty] = control[~ScrollBar.OrientationProperty],
Thumb = new Thumb
{
Template = ControlTemplate.Create<Thumb>(this.ThumbTemplate),
},
},
};
}
private Control ThumbTemplate(Thumb control)
{
return new Border
{
Background = Brushes.Gray,
};
}
}
}

237
TestApplication/Program.cs

@ -1,5 +1,6 @@
using Perspex;
using Perspex.Controls;
using Perspex.Controls.Primitives;
using Perspex.Diagnostics;
using Perspex.Layout;
using Perspex.Media;
@ -112,101 +113,10 @@ namespace TestApplication
{
Items = new[]
{
new TabItem
{
Header = "Buttons",
Content = new StackPanel
{
Orientation = Orientation.Vertical,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
MinWidth = 120,
Children = new Controls
{
new Button
{
Content = "Button",
},
new Button
{
Content = "Button",
Background = new SolidColorBrush(0xcc119eda),
},
new CheckBox
{
Content = "Checkbox",
},
}
},
},
new TabItem
{
Header = "Text",
Content = new StackPanel
{
Orientation = Orientation.Vertical,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
Width = 120,
Children = new Controls
{
new TextBlock
{
Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt.",
},
new TextBlock
{
Text = "Italic text.",
FontStyle = FontStyle.Italic,
},
new TextBox
{
Text = "Text Box",
},
}
},
},
new TabItem
{
Header = "Images",
Content = new StackPanel
{
Orientation = Orientation.Vertical,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
Width = 120,
Children = new Controls
{
new Image
{
Source = new Bitmap("github_icon.png"),
Width = 200,
},
}
},
},
new TabItem
{
Header = "Lists",
Content = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
Children = new Controls
{
new TreeView
{
Id = "treeView",
Items = treeData,
},
}
},
},
ButtonsTab(),
TextTab(),
ListsTab(),
SlidersTab(),
}
},
new TextBlock
@ -223,5 +133,142 @@ namespace TestApplication
window.Show();
Application.Current.Run(window);
}
private static TabItem ButtonsTab()
{
return new TabItem
{
Header = "Buttons",
Content = new StackPanel
{
Orientation = Orientation.Vertical,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
MinWidth = 120,
Children = new Controls
{
new Button
{
Content = "Button",
},
new Button
{
Content = "Button",
Background = new SolidColorBrush(0xcc119eda),
},
new CheckBox
{
Content = "Checkbox",
},
}
},
};
}
private static TabItem TextTab()
{
return new TabItem
{
Header = "Text",
Content = new StackPanel
{
Orientation = Orientation.Vertical,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
Width = 120,
Children = new Controls
{
new TextBlock
{
Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt.",
},
new TextBlock
{
Text = "Italic text.",
FontStyle = FontStyle.Italic,
},
new TextBox
{
Text = "Text Box",
},
}
},
};
}
private static TabItem ImagesTab()
{
return new TabItem
{
Header = "Images",
Content = new StackPanel
{
Orientation = Orientation.Vertical,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
Width = 120,
Children = new Controls
{
new Image
{
Source = new Bitmap("github_icon.png"),
Width = 200,
},
}
},
};
}
private static TabItem ListsTab()
{
return new TabItem
{
Header = "Lists",
Content = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
Children = new Controls
{
new TreeView
{
Id = "treeView",
Items = treeData,
},
}
},
};
}
private static TabItem SlidersTab()
{
return new TabItem
{
Header = "Sliders",
Content = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Gap = 8,
Children = new Controls
{
new ScrollBar
{
Orientation = Orientation.Horizontal,
ViewportSize = 25,
Value = 25,
Width = 300,
},
},
}
};
}
}
}

Loading…
Cancel
Save