Browse Source

Removed original monlithic Perspex lib.

pull/4/head
Steven Kirk 12 years ago
parent
commit
4c203d0577
  1. 97
      Perspex/Application.cs
  2. 66
      Perspex/Binding.cs
  3. 39
      Perspex/BindingExtensions.cs
  4. 177
      Perspex/Classes.cs
  5. 23
      Perspex/Contract.cs
  6. 37
      Perspex/ControlExtensions.cs
  7. 62
      Perspex/Controls/Border.cs
  8. 48
      Perspex/Controls/Button.cs
  9. 12
      Perspex/Controls/CheckBox.cs
  10. 53
      Perspex/Controls/ColumnDefinition.cs
  11. 12
      Perspex/Controls/ColumnDefinitions.cs
  12. 51
      Perspex/Controls/ContentControl.cs
  13. 188
      Perspex/Controls/ContentPresenter.cs
  14. 268
      Perspex/Controls/Control.cs
  15. 39
      Perspex/Controls/ControlTemplate.cs
  16. 22
      Perspex/Controls/Controls.cs
  17. 68
      Perspex/Controls/DataTemplate.cs
  18. 20
      Perspex/Controls/DataTemplates.cs
  19. 84
      Perspex/Controls/Decorator.cs
  20. 20
      Perspex/Controls/DefinitionBase.cs
  21. 805
      Perspex/Controls/Grid.cs
  22. 121
      Perspex/Controls/GridLength.cs
  23. 43
      Perspex/Controls/HeaderedContentControl.cs
  24. 25
      Perspex/Controls/HeaderedItemsControl.cs
  25. 24
      Perspex/Controls/ITemplatedControl.cs
  26. 115
      Perspex/Controls/Image.cs
  27. 137
      Perspex/Controls/ItemsControl.cs
  28. 20
      Perspex/Controls/ItemsPanelTemplate.cs
  29. 190
      Perspex/Controls/ItemsPresenter.cs
  30. 99
      Perspex/Controls/LogicalChildren.cs
  31. 64
      Perspex/Controls/Panel.cs
  32. 53
      Perspex/Controls/RowDefinition.cs
  33. 12
      Perspex/Controls/RowDefinitions.cs
  34. 20
      Perspex/Controls/SelectingItemsControl.cs
  35. 155
      Perspex/Controls/StackPanel.cs
  36. 67
      Perspex/Controls/TabControl.cs
  37. 26
      Perspex/Controls/TabItem.cs
  38. 86
      Perspex/Controls/TabStrip.cs
  39. 94
      Perspex/Controls/TemplatedControl.cs
  40. 65
      Perspex/Controls/TextBlock.cs
  41. 133
      Perspex/Controls/TextBox.cs
  42. 126
      Perspex/Controls/TextBoxView.cs
  43. 28
      Perspex/Controls/ToggleButton.cs
  44. 107
      Perspex/Controls/TreeDataTemplate.cs
  45. 76
      Perspex/Controls/TreeView.cs
  46. 54
      Perspex/Controls/TreeViewItem.cs
  47. 71
      Perspex/Diagnostics/Debug.cs
  48. 14
      Perspex/Diagnostics/DevTools.cs
  49. 15
      Perspex/ICloseable.cs
  50. 13
      Perspex/IHeadered.cs
  51. 21
      Perspex/ILogical.cs
  52. 13
      Perspex/IObservableDescription.cs
  53. 66
      Perspex/IVisual.cs
  54. 47
      Perspex/Input/FocusManager.cs
  55. 21
      Perspex/Input/IFocusManager.cs
  56. 12
      Perspex/Input/IInputDevice.cs
  57. 37
      Perspex/Input/IInputElement.cs
  58. 21
      Perspex/Input/IInputManager.cs
  59. 33
      Perspex/Input/IKeyboardDevice.cs
  60. 13
      Perspex/Input/IMouseDevice.cs
  61. 19
      Perspex/Input/IPointerDevice.cs
  62. 128
      Perspex/Input/InputElement.cs
  63. 65
      Perspex/Input/InputManager.cs
  64. 214
      Perspex/Input/Key.cs
  65. 19
      Perspex/Input/KeyEventArgs.cs
  66. 76
      Perspex/Input/KeyboardDevice.cs
  67. 153
      Perspex/Input/MouseDevice.cs
  68. 20
      Perspex/Input/PointerEventArgs.cs
  69. 27
      Perspex/Input/Raw/RawInputEventArgs.cs
  70. 31
      Perspex/Input/Raw/RawKeyEventArgs.cs
  71. 42
      Perspex/Input/Raw/RawMouseEventArgs.cs
  72. 124
      Perspex/Interactive.cs
  73. 23
      Perspex/Layout/ILayoutManager.cs
  74. 15
      Perspex/Layout/ILayoutRoot.cs
  75. 21
      Perspex/Layout/ILayoutable.cs
  76. 59
      Perspex/Layout/LayoutHelper.cs
  77. 56
      Perspex/Layout/LayoutManager.cs
  78. 261
      Perspex/Layout/Layoutable.cs
  79. 37
      Perspex/LogicalExtensions.cs
  80. 15
      Perspex/Media/Brush.cs
  81. 301
      Perspex/Media/Brushes.cs
  82. 110
      Perspex/Media/Color.cs
  83. 716
      Perspex/Media/Colors.cs
  84. 32
      Perspex/Media/FormattedText.cs
  85. 29
      Perspex/Media/Geometry.cs
  86. 67
      Perspex/Media/IDrawingContext.cs
  87. 52
      Perspex/Media/Imaging/Bitmap.cs
  88. 17
      Perspex/Media/Imaging/IBitmap.cs
  89. 35
      Perspex/Media/Imaging/RenderTargetBitmap.cs
  90. 182
      Perspex/Media/Matrix.cs
  91. 289
      Perspex/Media/PathMarkupParser.cs
  92. 46
      Perspex/Media/Pen.cs
  93. 36
      Perspex/Media/RectangleGeometry.cs
  94. 34
      Perspex/Media/RotateTransform.cs
  95. 46
      Perspex/Media/SolidColorBrush.cs
  96. 42
      Perspex/Media/StreamGeometry.cs
  97. 41
      Perspex/Media/StreamGeometryContext.cs
  98. 16
      Perspex/Media/Stretch.cs
  99. 13
      Perspex/Media/Transform.cs
  100. 54
      Perspex/Origin.cs

97
Perspex/Application.cs

@ -1,97 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Application.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using Perspex.Controls;
using Perspex.Input;
using Perspex.Styling;
using Perspex.Threading;
using Splat;
public class Application
{
private DataTemplates dataTemplates;
private Styles styles;
public Application()
{
Current = this;
this.FocusManager = new FocusManager();
this.InputManager = new InputManager();
}
public static Application Current
{
get;
private set;
}
public DataTemplates DataTemplates
{
get
{
if (this.dataTemplates == null)
{
this.dataTemplates = new DataTemplates();
}
return this.dataTemplates;
}
set
{
this.dataTemplates = value;
}
}
public IFocusManager FocusManager
{
get;
private set;
}
public InputManager InputManager
{
get;
private set;
}
public Styles Styles
{
get
{
if (this.styles == null)
{
this.styles = new Styles();
}
return this.styles;
}
set
{
this.styles = value;
}
}
public void RegisterServices()
{
Styler styler = new Styler();
Locator.CurrentMutable.Register(() => this.FocusManager, typeof(IFocusManager));
Locator.CurrentMutable.Register(() => this.InputManager, typeof(IInputManager));
Locator.CurrentMutable.Register(() => styler, typeof(IStyler));
}
public void Run(ICloseable closable)
{
DispatcherFrame frame = new DispatcherFrame();
closable.Closed += (s, e) => frame.Continue = false;
Dispatcher.PushFrame(frame);
}
}
}

66
Perspex/Binding.cs

@ -1,66 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Perspex
{
public enum BindingMode
{
Default,
OneWay,
TwoWay,
OneTime,
OneWayToSource,
}
public struct Binding
{
public BindingMode Mode
{
get;
set;
}
public BindingPriority Priority
{
get;
set;
}
public PerspexProperty Property
{
get;
set;
}
public PerspexObject Source
{
get;
set;
}
public static Binding operator !(Binding binding)
{
return binding.WithMode(BindingMode.TwoWay);
}
public static Binding operator ~(Binding binding)
{
return binding.WithMode(BindingMode.TwoWay);
}
public Binding WithMode(BindingMode mode)
{
this.Mode = mode;
return this;
}
public Binding WithPriority(BindingPriority priority)
{
this.Priority = priority;
return this;
}
}
}

39
Perspex/BindingExtensions.cs

@ -1,39 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="BindingExtensions.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Perspex.Controls;
/// <summary>
/// Provides binding utility extension methods.
/// </summary>
public static class BindingExtensions
{
/// <summary>
/// Binds a property in a template to the same property in the templated parent.
/// </summary>
/// <typeparam name="T">The property type.</typeparam>
/// <param name="o">The control in the template.</param>
/// <param name="templatedParent">The templated parent.</param>
/// <param name="property">The property.</param>
/// <returns>
/// A disposable which can be used to terminate the binding.
/// </returns>
public static IDisposable TemplateBinding<T>(
this PerspexObject o,
ITemplatedControl templatedParent,
PerspexProperty<T> property)
{
return o.Bind(property, templatedParent.GetObservable(property), BindingPriority.TemplatedParent);
}
}
}

177
Perspex/Classes.cs

@ -1,177 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Classes.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Reactive;
using System.Reactive.Subjects;
public class Classes : ICollection<string>, INotifyCollectionChanged
{
private List<string> inner;
private Subject<NotifyCollectionChangedEventArgs> beforeChanged
= new Subject<NotifyCollectionChangedEventArgs>();
private Subject<NotifyCollectionChangedEventArgs> changed
= new Subject<NotifyCollectionChangedEventArgs>();
private Subject<NotifyCollectionChangedEventArgs> afterChanged
= new Subject<NotifyCollectionChangedEventArgs>();
public Classes()
{
this.inner = new List<string>();
}
public Classes(params string[] classes)
{
this.inner = new List<string>(classes);
}
public Classes(IEnumerable<string> classes)
{
this.inner = new List<string>(classes);
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public int Count
{
get { return this.inner.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public IObservable<NotifyCollectionChangedEventArgs> BeforeChanged
{
get { return this.beforeChanged; }
}
public IObservable<NotifyCollectionChangedEventArgs> Changed
{
get { return this.changed; }
}
public IObservable<NotifyCollectionChangedEventArgs> AfterChanged
{
get { return this.afterChanged; }
}
public void Add(string item)
{
this.Add(Enumerable.Repeat(item, 1));
}
public void Add(params string[] items)
{
this.Add((IEnumerable<string>)items);
}
public void Add(IEnumerable<string> items)
{
items = items.Except(this.inner);
NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add,
items);
this.beforeChanged.OnNext(e);
this.inner.AddRange(items);
this.RaiseChanged(e);
}
public void Clear()
{
NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Reset);
this.beforeChanged.OnNext(e);
this.inner.Clear();
this.RaiseChanged(e);
}
public bool Contains(string item)
{
return this.inner.Contains(item);
}
public void CopyTo(string[] array, int arrayIndex)
{
this.inner.CopyTo(array, arrayIndex);
}
public IEnumerator<string> GetEnumerator()
{
return this.inner.GetEnumerator();
}
public override string ToString()
{
return string.Join(" ", this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.inner.GetEnumerator();
}
public bool Remove(string item)
{
return this.Remove(Enumerable.Repeat(item, 1));
}
public bool Remove(params string[] items)
{
return this.Remove((IEnumerable<string>)items);
}
public bool Remove(IEnumerable<string> items)
{
items = items.Intersect(this.inner);
if (items.Any())
{
NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Remove,
items);
this.beforeChanged.OnNext(e);
foreach (string item in items)
{
this.inner.Remove(item);
}
this.RaiseChanged(e);
return true;
}
else
{
return false;
}
}
private void RaiseChanged(NotifyCollectionChangedEventArgs e)
{
if (this.CollectionChanged != null)
{
this.CollectionChanged(this, e);
}
this.changed.OnNext(e);
this.afterChanged.OnNext(e);
}
}
}

23
Perspex/Contract.cs

@ -1,23 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Contract.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
internal static class Contract
{
public static void Requires<TException>(bool condition) where TException : Exception, new()
{
#if DEBUG
if (!condition)
{
throw new TException();
}
#endif
}
}
}

37
Perspex/ControlExtensions.cs

@ -1,37 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ControlExtensions.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
using System.Collections.Generic;
using System.Linq;
using Perspex.Controls;
using Perspex.Styling;
public static class ControlExtensions
{
public static IEnumerable<Control> GetTemplateControls(this ITemplatedControl control)
{
return GetTemplateControls(control, (IVisual)control);
}
public static IEnumerable<Control> GetTemplateControls(ITemplatedControl templated, IVisual parent)
{
IVisual visual = parent as IVisual;
foreach (IVisual child in visual.VisualChildren.OfType<Control>().Where(x => x.TemplatedParent == templated))
{
yield return (Control)child;
foreach (IVisual grandchild in GetTemplateControls(templated, child))
{
yield return (Control)grandchild;
}
}
}
}
}

62
Perspex/Controls/Border.cs

@ -1,62 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Border.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Reactive.Linq;
using Perspex.Layout;
using Perspex.Media;
public class Border : Decorator
{
static Border()
{
AffectsRender(BackgroundProperty);
AffectsRender(BorderBrushProperty);
}
public override void Render(IDrawingContext context)
{
Brush background = this.Background;
Brush borderBrush = this.BorderBrush;
double borderThickness = this.BorderThickness;
Rect rect = new Rect(this.ActualSize).Deflate(BorderThickness / 2);
if (background != null)
{
context.FillRectange(background, rect);
}
if (borderBrush != null && borderThickness > 0)
{
context.DrawRectange(new Pen(borderBrush, borderThickness), rect);
}
}
protected override Size ArrangeOverride(Size finalSize)
{
Control content = this.Content;
if (content != null)
{
Thickness padding = this.Padding + new Thickness(this.BorderThickness);
content.Arrange(new Rect(finalSize).Deflate(padding));
}
return finalSize;
}
protected override Size MeasureOverride(Size availableSize)
{
return LayoutHelper.MeasureDecorator(
this,
this.Content,
availableSize,
this.Padding + new Thickness(this.BorderThickness));
}
}
}

48
Perspex/Controls/Button.cs

@ -1,48 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Button.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
public class Button : ContentControl
{
public static readonly RoutedEvent<RoutedEventArgs> ClickEvent =
RoutedEvent.Register<Button, RoutedEventArgs>("Click", RoutingStrategy.Bubble);
static Button()
{
FocusableProperty.OverrideDefaultValue(typeof(Button), true);
}
public Button()
{
this.PointerPressed += (s, e) =>
{
this.Classes.Add(":pressed");
e.Device.Capture(this);
};
this.PointerReleased += (s, e) =>
{
e.Device.Capture(null);
this.Classes.Remove(":pressed");
if (this.Classes.Contains(":pointerover"))
{
RoutedEventArgs click = new RoutedEventArgs(ClickEvent, this);
this.RaiseEvent(click);
}
};
}
public event EventHandler<RoutedEventArgs> Click
{
add { this.AddHandler(ClickEvent, value); }
remove { this.RemoveHandler(ClickEvent, value); }
}
}
}

12
Perspex/Controls/CheckBox.cs

@ -1,12 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="CheckBox.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class CheckBox : ToggleButton
{
}
}

53
Perspex/Controls/ColumnDefinition.cs

@ -1,53 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ColumnDefinition.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class ColumnDefinition : DefinitionBase
{
public static readonly PerspexProperty<double> MaxWidthProperty =
PerspexProperty.Register<ColumnDefinition, double>("MaxWidth", double.PositiveInfinity);
public static readonly PerspexProperty<double> MinWidthProperty =
PerspexProperty.Register<ColumnDefinition, double>("MinWidth");
public static readonly PerspexProperty<GridLength> WidthProperty =
PerspexProperty.Register<ColumnDefinition, GridLength>("Width", new GridLength(1, GridUnitType.Star));
public ColumnDefinition()
{
}
public ColumnDefinition(GridLength width)
{
this.Width = width;
}
public double ActualWidth
{
get;
internal set;
}
public double MaxWidth
{
get { return this.GetValue(MaxWidthProperty); }
set { this.SetValue(MaxWidthProperty, value); }
}
public double MinWidth
{
get { return this.GetValue(MinWidthProperty); }
set { this.SetValue(MinWidthProperty, value); }
}
public GridLength Width
{
get { return this.GetValue(WidthProperty); }
set { this.SetValue(WidthProperty, value); }
}
}
}

12
Perspex/Controls/ColumnDefinitions.cs

@ -1,12 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ColumnDefinitions.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class ColumnDefinitions : PerspexList<ColumnDefinition>
{
}
}

51
Perspex/Controls/ContentControl.cs

@ -1,51 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ContentControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
public class ContentControl : TemplatedControl, ILogical
{
public static readonly PerspexProperty<object> ContentProperty =
PerspexProperty.Register<ContentControl, object>("Content");
public ContentControl()
{
this.GetObservableWithHistory(ContentProperty).Subscribe(x =>
{
if (x.Item1 is Control)
{
((IVisual)x.Item1).VisualParent = null;
((ILogical)x.Item1).LogicalParent = null;
}
if (x.Item2 is Control)
{
((IVisual)x.Item2).VisualParent = this;
((ILogical)x.Item2).LogicalParent = this;
}
});
}
public object Content
{
get { return this.GetValue(ContentProperty); }
set { this.SetValue(ContentProperty, value); }
}
IEnumerable<ILogical> ILogical.LogicalChildren
{
get
{
ILogical logicalChild = this.Content as ILogical;
return Enumerable.Repeat(logicalChild, logicalChild != null ? 1 : 0);
}
}
}
}

188
Perspex/Controls/ContentPresenter.cs

@ -1,188 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ContentPresenter.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
using Perspex.Layout;
using Perspex.Media;
public class ContentPresenter : Control, IVisual
{
public static readonly PerspexProperty<object> ContentProperty =
ContentControl.ContentProperty.AddOwner<Control>();
public static readonly PerspexProperty<Func<object, Visual>> DataTemplateProperty =
PerspexProperty.Register<ContentPresenter, Func<object, Visual>>("DataTemplate");
private IVisual visualChild;
public ContentPresenter()
{
this.GetObservableWithHistory(ContentProperty).Subscribe(this.ContentChanged);
}
public object Content
{
get { return this.GetValue(ContentProperty); }
set { this.SetValue(ContentProperty, value); }
}
IEnumerable<IVisual> IVisual.ExistingVisualChildren
{
get { return Enumerable.Repeat(this.visualChild, this.visualChild != null ? 1 : 0); }
}
IEnumerable<IVisual> IVisual.VisualChildren
{
get
{
object content = this.Content;
if (this.visualChild == null && content != null)
{
if (content is Visual)
{
this.visualChild = (Visual)content;
}
else
{
DataTemplate dataTemplate = this.FindDataTemplate(content);
if (dataTemplate != null)
{
this.visualChild = dataTemplate.Build(content);
}
else
{
this.visualChild = new TextBlock
{
Text = content.ToString(),
};
}
}
if (this.visualChild != null)
{
this.visualChild.VisualParent = this;
((Control)this.visualChild).TemplatedParent = null;
}
}
return Enumerable.Repeat(this.visualChild, this.visualChild != null ? 1 : 0);
}
}
protected override Size ArrangeOverride(Size finalSize)
{
Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control;
if (child != null)
{
double left;
double top;
double width;
double height;
switch (child.HorizontalAlignment)
{
case HorizontalAlignment.Left:
left = 0;
width = child.DesiredSize.Value.Width;
break;
case HorizontalAlignment.Center:
left = (finalSize.Width / 2) - (child.DesiredSize.Value.Width / 2);
width = child.DesiredSize.Value.Width;
break;
case HorizontalAlignment.Right:
left = finalSize.Width - child.DesiredSize.Value.Width;
width = child.DesiredSize.Value.Width;
break;
default:
left = 0;
width = finalSize.Width;
break;
}
switch (child.VerticalAlignment)
{
case VerticalAlignment.Top:
top = 0;
height = child.DesiredSize.Value.Height;
break;
case VerticalAlignment.Center:
top = (finalSize.Height / 2) - (child.DesiredSize.Value.Height / 2);
height = child.DesiredSize.Value.Height;
break;
case VerticalAlignment.Bottom:
top = finalSize.Height - child.DesiredSize.Value.Height;
height = child.DesiredSize.Value.Height;
break;
default:
top = 0;
height = finalSize.Height;
break;
}
child.Arrange(new Rect(left, top, width, height));
}
return finalSize;
}
protected override Size MeasureOverride(Size availableSize)
{
Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control;
if (child != null)
{
child.Measure(availableSize);
return child.DesiredSize.Value;
}
return new Size();
}
private void ContentChanged(Tuple<object, object> content)
{
if (content.Item1 != null)
{
this.visualChild.VisualParent = null;
ILogical logical = content.Item1 as ILogical;
if (logical != null)
{
logical.LogicalParent = null;
}
}
if (content.Item2 != null)
{
Control control = content.Item2 as Control;
if (control == null)
{
control = this.GetDataTemplate(content.Item2).Build(content.Item2);
}
control.TemplatedParent = null;
((IVisual)control).VisualParent = this;
this.visualChild = control;
ILogical logical = content.Item2 as ILogical;
if (logical != null)
{
logical.LogicalParent = (ILogical)this.TemplatedParent;
}
}
this.InvalidateMeasure();
}
}
}

268
Perspex/Controls/Control.cs

@ -1,268 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Control.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using Perspex.Input;
using Perspex.Layout;
using Perspex.Media;
using Perspex.Styling;
using Splat;
public class Control : InputElement, ILogical, IStyleable, IStyled
{
public static readonly PerspexProperty<Brush> BackgroundProperty =
PerspexProperty.Register<Control, Brush>("Background", inherits: true);
public static readonly PerspexProperty<Brush> BorderBrushProperty =
PerspexProperty.Register<Control, Brush>("BorderBrush");
public static readonly PerspexProperty<double> BorderThicknessProperty =
PerspexProperty.Register<Control, double>("BorderThickness");
public static readonly PerspexProperty<double> FontSizeProperty =
PerspexProperty.Register<Control, double>(
"FontSize",
defaultValue: 12.0,
inherits: true);
public static readonly PerspexProperty<Brush> ForegroundProperty =
PerspexProperty.Register<Control, Brush>("Foreground", new SolidColorBrush(0xff000000), true);
public static readonly PerspexProperty<Control> ParentProperty =
PerspexProperty.Register<Control, Control>("Parent");
public static readonly PerspexProperty<ITemplatedControl> TemplatedParentProperty =
PerspexProperty.Register<Control, ITemplatedControl>("TemplatedParent", inherits: true);
private Classes classes;
private DataTemplates dataTemplates;
private string id;
private Styles styles;
static Control()
{
AffectsMeasure(IsVisibleProperty);
}
public Control()
{
this.classes = new Classes();
this.AddPseudoClass(IsPointerOverProperty, ":pointerover");
this.AddPseudoClass(IsFocusedProperty, ":focus");
}
public Brush Background
{
get { return this.GetValue(BackgroundProperty); }
set { this.SetValue(BackgroundProperty, value); }
}
public Brush BorderBrush
{
get { return this.GetValue(BorderBrushProperty); }
set { this.SetValue(BorderBrushProperty, value); }
}
public double BorderThickness
{
get { return this.GetValue(BorderThicknessProperty); }
set { this.SetValue(BorderThicknessProperty, value); }
}
public Classes Classes
{
get
{
return this.classes;
}
set
{
if (this.classes != value)
{
this.classes.Clear();
this.classes.Add(value);
}
}
}
public DataTemplates DataTemplates
{
get
{
if (this.dataTemplates == null)
{
this.dataTemplates = new DataTemplates();
}
return this.dataTemplates;
}
set
{
this.dataTemplates = value;
}
}
public double FontSize
{
get { return this.GetValue(FontSizeProperty); }
set { this.SetValue(FontSizeProperty, value); }
}
public Brush Foreground
{
get { return this.GetValue(ForegroundProperty); }
set { this.SetValue(ForegroundProperty, value); }
}
public string Id
{
get
{
return this.id;
}
set
{
if (this.id != null)
{
throw new InvalidOperationException("ID already set.");
}
if (((IVisual)this).VisualParent != null)
{
throw new InvalidOperationException("Cannot set ID : control already added to tree.");
}
this.id = value;
}
}
public Control Parent
{
get { return this.GetValue(ParentProperty); }
protected set { this.SetValue(ParentProperty, value); }
}
public Styles Styles
{
get
{
if (this.styles == null)
{
this.styles = new Styles();
}
return this.styles;
}
set
{
this.styles = value;
}
}
public ITemplatedControl TemplatedParent
{
get { return this.GetValue(TemplatedParentProperty); }
internal set { this.SetValue(TemplatedParentProperty, value); }
}
ILogical ILogical.LogicalParent
{
get { return this.Parent; }
set { this.Parent = (Control)value; }
}
IEnumerable<ILogical> ILogical.LogicalChildren
{
get { return Enumerable.Empty<ILogical>(); }
}
protected override void OnAttachedToVisualTree(ILayoutRoot root)
{
IStyler styler = Locator.Current.GetService<IStyler>();
styler.ApplyStyles(this);
}
protected void AddPseudoClass(PerspexProperty<bool> property, string className)
{
this.GetObservable(property).Subscribe(x =>
{
if (x)
{
this.classes.Add(className);
}
else
{
this.classes.Remove(className);
}
});
}
protected virtual DataTemplate FindDataTemplate(object content)
{
Control control = content as Control;
if (control != null)
{
return new DataTemplate(x => control);
}
ILogical node = this;
while (node != null)
{
control = node as Control;
if (control != null)
{
foreach (DataTemplate dt in control.DataTemplates.Reverse())
{
if (dt.Match(content))
{
return dt;
}
}
}
node = node.LogicalParent;
if (node == null && control != null)
{
node = control.TemplatedParent as ILogical;
}
}
if (Application.Current != null && Application.Current.DataTemplates != null)
{
foreach (DataTemplate dt in Application.Current.DataTemplates.Reverse())
{
if (dt.Match(content))
{
return dt;
}
}
}
return null;
}
protected DataTemplate GetDataTemplate(object content)
{
return this.FindDataTemplate(content) ?? DataTemplate.Default;
}
}
}

39
Perspex/Controls/ControlTemplate.cs

@ -1,39 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ControlTemplate.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
public class ControlTemplate
{
private Func<ITemplatedControl, Control> build;
public ControlTemplate(Func<ITemplatedControl, Control> build)
{
Contract.Requires<NullReferenceException>(build != null);
this.build = build;
}
public static ControlTemplate Create<TControl>(Func<TControl, Control> build)
where TControl : ITemplatedControl
{
Contract.Requires<NullReferenceException>(build != null);
return new ControlTemplate(c => build((TControl)c));
}
public Control Build(ITemplatedControl templatedParent)
{
Contract.Requires<NullReferenceException>(templatedParent != null);
Control root = this.build(templatedParent);
root.TemplatedParent = templatedParent;
return root;
}
}
}

22
Perspex/Controls/Controls.cs

@ -1,22 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Controls.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
using System.Collections.Generic;
namespace Perspex.Controls
{
public class Controls : PerspexList<Control>
{
public Controls()
{
}
public Controls(IEnumerable<Control> items)
: base(items)
{
}
}
}

68
Perspex/Controls/DataTemplate.cs

@ -1,68 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="DataTemplate.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Reflection;
public class DataTemplate
{
public static readonly DataTemplate Default =
new DataTemplate(typeof(object), o => new TextBlock { Text = o.ToString() });
public DataTemplate(Func<object, Control> build)
: this(o => true, build)
{
}
public DataTemplate(Type type, Func<object, Control> build)
: this(o => IsInstance(o, type), build)
{
}
public DataTemplate(Func<object, bool> match, Func<object, Control> build)
{
Contract.Requires<ArgumentNullException>(match != null);
Contract.Requires<ArgumentNullException>(build != null);
this.Match = match;
this.Build = build;
}
public static bool IsInstance(object o, Type t)
{
return t.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo());
}
public Func<object, bool> Match { get; private set; }
public Func<object, Control> Build { get; private set; }
}
public class DataTemplate<T> : DataTemplate
{
public DataTemplate(Func<T, Control> build)
: base(typeof(T), Cast(build))
{
}
public DataTemplate(Func<T, bool> match, Func<T, Control> build)
: base(CastMatch(match), Cast(build))
{
}
private static Func<object, bool> CastMatch(Func<T, bool> f)
{
return o => (o is T) ? f((T)o) : false;
}
private static Func<object, TResult> Cast<TResult>(Func<T, TResult> f)
{
return o => f((T)o);
}
}
}

20
Perspex/Controls/DataTemplates.cs

@ -1,20 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="DataTemplates.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Reactive;
using System.Reactive.Subjects;
public class DataTemplates : PerspexList<DataTemplate>
{
}
}

84
Perspex/Controls/Decorator.cs

@ -1,84 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Decorator.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using Perspex.Layout;
public class Decorator : Control, IVisual
{
public static readonly PerspexProperty<Control> ContentProperty =
PerspexProperty.Register<Decorator, Control>("Content");
public static readonly PerspexProperty<Thickness> PaddingProperty =
PerspexProperty.Register<Decorator, Thickness>("Padding");
public Decorator()
{
this.GetObservableWithHistory(ContentProperty).Subscribe(x =>
{
if (x.Item1 != null)
{
((IVisual)this).RemoveVisualChild(x.Item1);
((ILogical)this).RemoveLogicalChild(x.Item1);
}
if (x.Item2 != null)
{
((IVisual)this).AddVisualChild(x.Item2);
((ILogical)this).AddLogicalChild(x.Item2);
}
});
}
public Control Content
{
get { return this.GetValue(ContentProperty); }
set { this.SetValue(ContentProperty, value); }
}
public Thickness Padding
{
get { return this.GetValue(PaddingProperty); }
set { this.SetValue(PaddingProperty, value); }
}
IEnumerable<IVisual> IVisual.ExistingVisualChildren
{
get { return ((IVisual)this).VisualChildren; }
}
IEnumerable<IVisual> IVisual.VisualChildren
{
get
{
Control content = this.Content;
return Enumerable.Repeat(content, content != null ? 1 : 0);
}
}
protected override Size ArrangeOverride(Size finalSize)
{
Control content = this.Content;
if (content != null)
{
content.Arrange(new Rect(finalSize).Deflate(this.Padding));
}
return finalSize;
}
protected override Size MeasureOverride(Size availableSize)
{
return LayoutHelper.MeasureDecorator(this, this.Content, availableSize, this.Padding);
}
}
}

20
Perspex/Controls/DefinitionBase.cs

@ -1,20 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="DefinitionBase.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class DefinitionBase : PerspexObject
{
public static readonly PerspexProperty<string> SharedSizeGroupProperty =
PerspexProperty.Register<DefinitionBase, string>("SharedSizeGroup", inherits: true);
public string SharedSizeGroup
{
get { return this.GetValue(SharedSizeGroupProperty); }
set { this.SetValue(SharedSizeGroupProperty, value); }
}
}
}

805
Perspex/Controls/Grid.cs

@ -1,805 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Grid.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
public class Grid : Panel
{
public static readonly PerspexProperty<int> ColumnProperty =
PerspexProperty.RegisterAttached<Grid, Control, int>("Column");
public static readonly PerspexProperty<int> ColumnSpanProperty =
PerspexProperty.RegisterAttached<Grid, Control, int>("ColumnSpan", 1);
public static readonly PerspexProperty<bool> IsSharedSizeScopeProperty =
PerspexProperty.RegisterAttached<Grid, Control, bool>("IsSharedSizeScopeProperty");
public static readonly PerspexProperty<int> RowProperty =
PerspexProperty.RegisterAttached<Grid, Control, int>("Row");
public static readonly PerspexProperty<int> RowSpanProperty =
PerspexProperty.RegisterAttached<Grid, Control, int>("RowSpan", 1);
private Segment[,] rowMatrix;
private Segment[,] colMatrix;
public Grid()
{
this.ColumnDefinitions = new ColumnDefinitions();
this.RowDefinitions = new RowDefinitions();
}
public ColumnDefinitions ColumnDefinitions
{
get;
set;
}
public RowDefinitions RowDefinitions
{
get;
set;
}
public static int GetColumn(PerspexObject element)
{
return element.GetValue(ColumnProperty);
}
public static int GetColumnSpan(PerspexObject element)
{
return element.GetValue(ColumnSpanProperty);
}
public static int GetRow(PerspexObject element)
{
return element.GetValue(RowProperty);
}
public static int GetRowSpan(PerspexObject element)
{
return element.GetValue(RowSpanProperty);
}
public static void SetColumn(PerspexObject element, int value)
{
element.SetValue(ColumnProperty, value);
}
public static void SetColumnSpan(PerspexObject element, int value)
{
element.SetValue(ColumnSpanProperty, value);
}
public static void SetRow(PerspexObject element, int value)
{
element.SetValue(RowProperty, value);
}
public static void SetRowSpan(PerspexObject element, int value)
{
element.SetValue(RowSpanProperty, value);
}
protected override Size MeasureOverride(Size constraint)
{
Size totalSize = constraint;
int colCount = this.ColumnDefinitions.Count;
int rowCount = this.RowDefinitions.Count;
double totalStarsX = 0;
double totalStarsY = 0;
bool emptyRows = rowCount == 0;
bool emptyCols = colCount == 0;
bool hasChildren = this.Children.Count > 0;
if (emptyRows)
{
rowCount = 1;
}
if (emptyCols)
{
colCount = 1;
}
this.CreateMatrices(rowCount, colCount);
if (emptyRows)
{
this.rowMatrix[0, 0] = new Segment(0, 0, double.PositiveInfinity, GridUnitType.Star);
this.rowMatrix[0, 0].Stars = 1.0;
totalStarsY += 1.0;
}
else
{
for (int i = 0; i < rowCount; i++)
{
RowDefinition rowdef = this.RowDefinitions[i];
GridLength height = rowdef.Height;
rowdef.ActualHeight = double.PositiveInfinity;
this.rowMatrix[i, i] = new Segment(0, rowdef.MinHeight, rowdef.MaxHeight, height.GridUnitType);
if (height.GridUnitType == GridUnitType.Pixel)
{
this.rowMatrix[i, i].OfferedSize = Clamp(height.Value, this.rowMatrix[i, i].Min, this.rowMatrix[i, i].Max);
this.rowMatrix[i, i].DesiredSize = this.rowMatrix[i, i].OfferedSize;
rowdef.ActualHeight = this.rowMatrix[i, i].OfferedSize;
}
else if (height.GridUnitType == GridUnitType.Star)
{
this.rowMatrix[i, i].Stars = height.Value;
totalStarsY += height.Value;
}
else if (height.GridUnitType == GridUnitType.Auto)
{
this.rowMatrix[i, i].OfferedSize = Clamp(0, this.rowMatrix[i, i].Min, this.rowMatrix[i, i].Max);
this.rowMatrix[i, i].DesiredSize = this.rowMatrix[i, i].OfferedSize;
}
}
}
if (emptyCols)
{
this.colMatrix[0, 0] = new Segment(0, 0, double.PositiveInfinity, GridUnitType.Star);
this.colMatrix[0, 0].Stars = 1.0;
totalStarsX += 1.0;
}
else
{
for (int i = 0; i < colCount; i++)
{
ColumnDefinition coldef = this.ColumnDefinitions[i];
GridLength width = coldef.Width;
coldef.ActualWidth = double.PositiveInfinity;
this.colMatrix[i, i] = new Segment(0, coldef.MinWidth, coldef.MaxWidth, width.GridUnitType);
if (width.GridUnitType == GridUnitType.Pixel)
{
this.colMatrix[i, i].OfferedSize = Clamp(width.Value, this.colMatrix[i, i].Min, this.colMatrix[i, i].Max);
this.colMatrix[i, i].DesiredSize = this.colMatrix[i, i].OfferedSize;
coldef.ActualWidth = this.colMatrix[i, i].OfferedSize;
}
else if (width.GridUnitType == GridUnitType.Star)
{
this.colMatrix[i, i].Stars = width.Value;
totalStarsX += width.Value;
}
else if (width.GridUnitType == GridUnitType.Auto)
{
this.colMatrix[i, i].OfferedSize = Clamp(0, this.colMatrix[i, i].Min, this.colMatrix[i, i].Max);
this.colMatrix[i, i].DesiredSize = this.colMatrix[i, i].OfferedSize;
}
}
}
List<GridNode> sizes = new List<GridNode>();
GridNode node;
GridNode separator = new GridNode(null, 0, 0, 0);
int separatorIndex;
sizes.Add(separator);
// Pre-process the grid children so that we know what types of elements we have so
// we can apply our special measuring rules.
GridWalker gridWalker = new GridWalker(this, this.rowMatrix, this.colMatrix);
for (int i = 0; i < 6; i++)
{
// These bools tell us which grid element type we should be measuring. i.e.
// 'star/auto' means we should measure elements with a star row and auto col
bool autoAuto = i == 0;
bool starAuto = i == 1;
bool autoStar = i == 2;
bool starAutoAgain = i == 3;
bool nonStar = i == 4;
bool remainingStar = i == 5;
if (hasChildren)
{
this.ExpandStarCols(totalSize);
this.ExpandStarRows(totalSize);
}
foreach (Control child in this.Children)
{
int col, row;
int colspan, rowspan;
double childSizeX = 0;
double childSizeY = 0;
bool starCol = false;
bool starRow = false;
bool autoCol = false;
bool autoRow = false;
col = Math.Min(GetColumn(child), colCount - 1);
row = Math.Min(GetRow(child), rowCount - 1);
colspan = Math.Min(GetColumnSpan(child), colCount - col);
rowspan = Math.Min(GetRowSpan(child), rowCount - row);
for (int r = row; r < row + rowspan; r++)
{
starRow |= this.rowMatrix[r, r].Type == GridUnitType.Star;
autoRow |= this.rowMatrix[r, r].Type == GridUnitType.Auto;
}
for (int c = col; c < col + colspan; c++)
{
starCol |= this.colMatrix[c, c].Type == GridUnitType.Star;
autoCol |= this.colMatrix[c, c].Type == GridUnitType.Auto;
}
// This series of if statements checks whether or not we should measure
// the current element and also if we need to override the sizes
// passed to the Measure call.
// If the element has Auto rows and Auto columns and does not span Star
// rows/cols it should only be measured in the auto_auto phase.
// There are similar rules governing auto/star and star/auto elements.
// NOTE: star/auto elements are measured twice. The first time with
// an override for height, the second time without it.
if (autoRow && autoCol && !starRow && !starCol)
{
if (!autoAuto)
{
continue;
}
childSizeX = double.PositiveInfinity;
childSizeY = double.PositiveInfinity;
}
else if (starRow && autoCol && !starCol)
{
if (!(starAuto || starAutoAgain))
{
continue;
}
if (starAuto && gridWalker.HasAutoStar)
{
childSizeY = double.PositiveInfinity;
}
childSizeX = double.PositiveInfinity;
}
else if (autoRow && starCol && !starRow)
{
if (!autoStar)
{
continue;
}
childSizeY = double.PositiveInfinity;
}
else if ((autoRow || autoCol) && !(starRow || starCol))
{
if (!nonStar)
{
continue;
}
if (autoRow)
{
childSizeY = double.PositiveInfinity;
}
if (autoCol)
{
childSizeX = double.PositiveInfinity;
}
}
else if (!(starRow || starCol))
{
if (!nonStar)
{
continue;
}
}
else
{
if (!remainingStar)
{
continue;
}
}
for (int r = row; r < row + rowspan; r++)
{
childSizeY += this.rowMatrix[r, r].OfferedSize;
}
for (int c = col; c < col + colspan; c++)
{
childSizeX += this.colMatrix[c, c].OfferedSize;
}
child.Measure(new Size(childSizeX, childSizeY));
Size desired = child.DesiredSize.Value;
// Elements distribute their height based on two rules:
// 1) Elements with rowspan/colspan == 1 distribute their height first
// 2) Everything else distributes in a LIFO manner.
// As such, add all UIElements with rowspan/colspan == 1 after the separator in
// the list and everything else before it. Then to process, just keep popping
// elements off the end of the list.
if (!starAuto)
{
node = new GridNode(this.rowMatrix, row + rowspan - 1, row, desired.Height);
separatorIndex = sizes.IndexOf(separator);
sizes.Insert(node.Row == node.Column ? separatorIndex + 1 : separatorIndex, node);
}
node = new GridNode(this.colMatrix, col + colspan - 1, col, desired.Width);
separatorIndex = sizes.IndexOf(separator);
sizes.Insert(node.Row == node.Column ? separatorIndex + 1 : separatorIndex, node);
}
sizes.Remove(separator);
while (sizes.Count > 0)
{
node = sizes.Last();
node.Matrix[node.Row, node.Column].DesiredSize = Math.Max(node.Matrix[node.Row, node.Column].DesiredSize, node.Size);
this.AllocateDesiredSize(rowCount, colCount);
sizes.Remove(node);
}
sizes.Add(separator);
}
// Once we have measured and distributed all sizes, we have to store
// the results. Every time we want to expand the rows/cols, this will
// be used as the baseline.
this.SaveMeasureResults();
sizes.Remove(separator);
double gridSizeX = 0;
double gridSizeY = 0;
for (int c = 0; c < colCount; c++)
{
gridSizeX += this.colMatrix[c, c].DesiredSize;
}
for (int r = 0; r < rowCount; r++)
{
gridSizeY += this.rowMatrix[r, r].DesiredSize;
}
return new Size(gridSizeX, gridSizeY);
}
protected override Size ArrangeOverride(Size finalSize)
{
int colCount = this.ColumnDefinitions.Count;
int rowCount = this.RowDefinitions.Count;
int colMatrixDim = this.colMatrix.GetUpperBound(0) + 1;
int rowMatrixDim = this.rowMatrix.GetUpperBound(0) + 1;
this.RestoreMeasureResults();
double totalConsumedX = 0;
double totalConsumedY = 0;
for (int c = 0; c < colMatrixDim; c++)
{
this.colMatrix[c, c].OfferedSize = this.colMatrix[c, c].DesiredSize;
totalConsumedX += this.colMatrix[c, c].OfferedSize;
}
for (int r = 0; r < rowMatrixDim; r++)
{
this.rowMatrix[r, r].OfferedSize = this.rowMatrix[r, r].DesiredSize;
totalConsumedY += this.rowMatrix[r, r].OfferedSize;
}
if (totalConsumedX != finalSize.Width)
{
this.ExpandStarCols(finalSize);
}
if (totalConsumedY != finalSize.Height)
{
this.ExpandStarRows(finalSize);
}
for (int c = 0; c < colCount; c++)
{
this.ColumnDefinitions[c].ActualWidth = this.colMatrix[c, c].OfferedSize;
}
for (int r = 0; r < rowCount; r++)
{
this.RowDefinitions[r].ActualHeight = this.rowMatrix[r, r].OfferedSize;
}
foreach (Control child in this.Children)
{
int col = Math.Min(GetColumn(child), colMatrixDim - 1);
int row = Math.Min(GetRow(child), rowMatrixDim - 1);
int colspan = Math.Min(GetColumnSpan(child), colMatrixDim - col);
int rowspan = Math.Min(GetRowSpan(child), rowMatrixDim - row);
double childFinalX = 0;
double childFinalY = 0;
double childFinalW = 0;
double childFinalH = 0;
for (int c = 0; c < col; c++)
{
childFinalX += this.colMatrix[c, c].OfferedSize;
}
for (int c = col; c < col + colspan; c++)
{
childFinalW += this.colMatrix[c, c].OfferedSize;
}
for (int r = 0; r < row; r++)
{
childFinalY += this.rowMatrix[r, r].OfferedSize;
}
for (int r = row; r < row + rowspan; r++)
{
childFinalH += this.rowMatrix[r, r].OfferedSize;
}
child.Arrange(new Rect(childFinalX, childFinalY, childFinalW, childFinalH));
}
return finalSize;
}
private static double Clamp(double val, double min, double max)
{
if (val < min)
{
return min;
}
else if (val > max)
{
return max;
}
else
{
return val;
}
}
private void CreateMatrices(int rowCount, int colCount)
{
if (this.rowMatrix == null || this.colMatrix == null ||
this.rowMatrix.GetUpperBound(0) != rowCount - 1 ||
this.colMatrix.GetUpperBound(0) != colCount - 1)
{
this.rowMatrix = new Segment[rowCount, rowCount];
this.colMatrix = new Segment[colCount, colCount];
}
}
private void ExpandStarCols(Size availableSize)
{
int columnsCount = this.ColumnDefinitions.Count;
double width = availableSize.Width;
for (int i = 0; i < this.colMatrix.GetUpperBound(0) + 1; i++)
{
if (this.colMatrix[i, i].Type == GridUnitType.Star)
{
this.colMatrix[i, i].OfferedSize = 0;
}
else
{
width = Math.Max(availableSize.Width - this.colMatrix[i, i].OfferedSize, 0);
}
}
this.AssignSize(this.colMatrix, 0, this.colMatrix.GetUpperBound(0), ref width, GridUnitType.Star, false);
width = Math.Max(0, width);
if (columnsCount > 0)
{
for (int i = 0; i < this.colMatrix.GetUpperBound(0) + 1; i++)
{
if (this.colMatrix[i, i].Type == GridUnitType.Star)
{
this.ColumnDefinitions[i].ActualWidth = this.colMatrix[i, i].OfferedSize;
}
}
}
}
private void ExpandStarRows(Size availableSize)
{
int rowCount = this.RowDefinitions.Count;
double height = availableSize.Height;
// When expanding star rows, we need to zero out their height before
// calling AssignSize. AssignSize takes care of distributing the
// available size when there are Mins and Maxs applied.
for (int i = 0; i < this.rowMatrix.GetUpperBound(0) + 1; i++)
{
if (this.rowMatrix[i, i].Type == GridUnitType.Star)
{
this.rowMatrix[i, i].OfferedSize = 0.0;
}
else
{
height = Math.Max(availableSize.Height - this.rowMatrix[i, i].OfferedSize, 0);
}
}
this.AssignSize(this.rowMatrix, 0, this.rowMatrix.GetUpperBound(0), ref height, GridUnitType.Star, false);
if (rowCount > 0)
{
for (int i = 0; i < this.rowMatrix.GetUpperBound(0) + 1; i++)
{
if (this.rowMatrix[i, i].Type == GridUnitType.Star)
{
this.RowDefinitions[i].ActualHeight = this.rowMatrix[i, i].OfferedSize;
}
}
}
}
private void AssignSize(
Segment[,] matrix,
int start,
int end,
ref double size,
GridUnitType type,
bool desiredSize)
{
double count = 0;
bool assigned;
// Count how many segments are of the correct type. If we're measuring Star rows/cols
// we need to count the number of stars instead.
for (int i = start; i <= end; i++)
{
double segmentSize = desiredSize ? matrix[i, i].DesiredSize : matrix[i, i].OfferedSize;
if (segmentSize < matrix[i, i].Max)
{
count += type == GridUnitType.Star ? matrix[i, i].Stars : 1;
}
}
do
{
double contribution = size / count;
assigned = false;
for (int i = start; i <= end; i++)
{
double segmentSize = desiredSize ? matrix[i, i].DesiredSize : matrix[i, i].OfferedSize;
if (!(matrix[i, i].Type == type && segmentSize < matrix[i, i].Max))
{
continue;
}
double newsize = segmentSize;
newsize += contribution * (type == GridUnitType.Star ? matrix[i, i].Stars : 1);
newsize = Math.Min(newsize, matrix[i, i].Max);
assigned |= newsize > segmentSize;
size -= newsize - segmentSize;
if (desiredSize)
{
matrix[i, i].DesiredSize = newsize;
}
else
{
matrix[i, i].OfferedSize = newsize;
}
}
}
while (assigned);
}
private void AllocateDesiredSize(int rowCount, int colCount)
{
// First allocate the heights of the RowDefinitions, then allocate
// the widths of the ColumnDefinitions.
for (int i = 0; i < 2; i++)
{
Segment[,] matrix = i == 0 ? this.rowMatrix : this.colMatrix;
int count = i == 0 ? rowCount : colCount;
for (int row = count - 1; row >= 0; row--)
{
for (int col = row; col >= 0; col--)
{
bool spansStar = false;
for (int j = row; j >= col; j--)
{
spansStar |= matrix[j, j].Type == GridUnitType.Star;
}
// This is the amount of pixels which must be available between the grid rows
// at index 'col' and 'row'. i.e. if 'row' == 0 and 'col' == 2, there must
// be at least 'matrix [row][col].size' pixels of height allocated between
// all the rows in the range col -> row.
double current = matrix[row, col].DesiredSize;
// Count how many pixels have already been allocated between the grid rows
// in the range col -> row. The amount of pixels allocated to each grid row/column
// is found on the diagonal of the matrix.
double totalAllocated = 0;
for (int k = row; k >= col; k--)
{
totalAllocated += matrix[k, k].DesiredSize;
}
// If the size requirement has not been met, allocate the additional required
// size between 'pixel' rows, then 'star' rows, finally 'auto' rows, until all
// height has been assigned.
if (totalAllocated < current)
{
double additional = current - totalAllocated;
if (spansStar)
{
this.AssignSize(matrix, col, row, ref additional, GridUnitType.Star, true);
}
else
{
this.AssignSize(matrix, col, row, ref additional, GridUnitType.Pixel, true);
this.AssignSize(matrix, col, row, ref additional, GridUnitType.Auto, true);
}
}
}
}
}
for (int r = 0; r < this.rowMatrix.GetUpperBound(0) + 1; r++)
{
this.rowMatrix[r, r].OfferedSize = this.rowMatrix[r, r].DesiredSize;
}
for (int c = 0; c < this.colMatrix.GetUpperBound(0) + 1; c++)
{
this.colMatrix[c, c].OfferedSize = this.colMatrix[c, c].DesiredSize;
}
}
private void SaveMeasureResults()
{
for (int i = 0; i < this.rowMatrix.GetUpperBound(0) + 1; i++)
{
for (int j = 0; j < this.rowMatrix.GetUpperBound(0) + 1; j++)
{
this.rowMatrix[i, j].OriginalSize = this.rowMatrix[i, j].OfferedSize;
}
}
for (int i = 0; i < this.colMatrix.GetUpperBound(0); i++)
{
for (int j = 0; j < this.colMatrix.GetUpperBound(0); j++)
{
this.colMatrix[i, j].OriginalSize = this.colMatrix[i, j].OfferedSize;
}
}
}
private void RestoreMeasureResults()
{
for (int i = 0; i < this.rowMatrix.GetUpperBound(0) + 1; i++)
{
for (int j = 0; j < this.rowMatrix.GetUpperBound(0) + 1; j++)
{
this.rowMatrix[i, j].OfferedSize = this.rowMatrix[i, j].OriginalSize;
}
}
for (int i = 0; i < this.colMatrix.GetUpperBound(0) + 1; i++)
{
for (int j = 0; j < this.colMatrix.GetUpperBound(0) + 1; j++)
{
this.colMatrix[i, j].OfferedSize = this.colMatrix[i, j].OriginalSize;
}
}
}
private struct Segment
{
public double OriginalSize;
public double Max;
public double Min;
public double DesiredSize;
public double OfferedSize;
public double Stars;
public GridUnitType Type;
public Segment(double offeredSize, double min, double max, GridUnitType type)
{
this.OriginalSize = 0;
this.Min = min;
this.Max = max;
this.DesiredSize = 0;
this.OfferedSize = offeredSize;
this.Stars = 0;
this.Type = type;
}
public void Init(double offeredSize, double min, double max, GridUnitType type)
{
this.OfferedSize = offeredSize;
this.Min = min;
this.Max = max;
this.Type = type;
}
}
private struct GridNode
{
public int Row;
public int Column;
public double Size;
public Segment[,] Matrix;
public GridNode(Segment[,] matrix, int row, int col, double size)
{
this.Matrix = matrix;
this.Row = row;
this.Column = col;
this.Size = size;
}
}
private class GridWalker
{
public GridWalker(Grid grid, Segment[,] rowMatrix, Segment[,] colMatrix)
{
foreach (Control child in grid.Children)
{
bool starCol = false;
bool starRow = false;
bool autoCol = false;
bool autoRow = false;
int col = Math.Min(Grid.GetColumn(child), colMatrix.GetUpperBound(0));
int row = Math.Min(Grid.GetRow(child), rowMatrix.GetUpperBound(0));
int colspan = Math.Min(Grid.GetColumnSpan(child), colMatrix.GetUpperBound(0));
int rowspan = Math.Min(Grid.GetRowSpan(child), rowMatrix.GetUpperBound(0));
for (int r = row; r < row + rowspan; r++)
{
starRow |= rowMatrix[r, r].Type == GridUnitType.Star;
autoRow |= rowMatrix[r, r].Type == GridUnitType.Auto;
}
for (int c = col; c < col + colspan; c++)
{
starCol |= colMatrix[c, c].Type == GridUnitType.Star;
autoCol |= colMatrix[c, c].Type == GridUnitType.Auto;
}
this.HasAutoAuto |= autoRow && autoCol && !starRow && !starCol;
this.HasStarAuto |= starRow && autoCol;
this.HasAutoStar |= autoRow && starCol;
}
}
public bool HasAutoAuto { get; private set; }
public bool HasStarAuto { get; private set; }
public bool HasAutoStar { get; private set; }
}
}
}

121
Perspex/Controls/GridLength.cs

@ -1,121 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="GridLength.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
public enum GridUnitType
{
Auto = 0,
Pixel = 1,
Star = 2,
}
public struct GridLength : IEquatable<GridLength>
{
private GridUnitType type;
private double value;
public GridLength(double value)
: this(value, GridUnitType.Pixel)
{
}
public GridLength(double value, GridUnitType type)
{
if (value < 0 || double.IsNaN(value) || double.IsInfinity(value))
{
throw new ArgumentException("Invalid value", "value");
}
if (type < GridUnitType.Auto || type > GridUnitType.Star)
{
throw new ArgumentException("Invalid value", "type");
}
this.type = type;
this.value = value;
}
public static GridLength Auto
{
get { return new GridLength(0, GridUnitType.Auto); }
}
public GridUnitType GridUnitType
{
get { return this.type; }
}
public bool IsAbsolute
{
get { return this.type == GridUnitType.Pixel; }
}
public bool IsAuto
{
get { return this.type == GridUnitType.Auto; }
}
public bool IsStar
{
get { return this.type == GridUnitType.Star; }
}
public double Value
{
get { return this.value; }
}
public static bool operator ==(GridLength a, GridLength b)
{
return (a.IsAuto && b.IsAuto) || (a.value == b.value && a.type == b.type);
}
public static bool operator !=(GridLength gl1, GridLength gl2)
{
return !(gl1 == gl2);
}
public override bool Equals(object o)
{
if (o == null)
{
return false;
}
if (!(o is GridLength))
{
return false;
}
return this == (GridLength)o;
}
public bool Equals(GridLength gridLength)
{
return this == gridLength;
}
public override int GetHashCode()
{
return this.value.GetHashCode() ^ this.type.GetHashCode();
}
public override string ToString()
{
if (this.IsAuto)
{
return "Auto";
}
string s = this.value.ToString();
return this.IsStar ? s + "*" : s;
}
}
}

43
Perspex/Controls/HeaderedContentControl.cs

@ -1,43 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ContentControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
public class HeaderedContentControl : ContentControl, ILogical, IHeadered
{
public static readonly PerspexProperty<object> HeaderProperty =
PerspexProperty.Register<ContentControl, object>("Header");
public object Header
{
get { return this.GetValue(HeaderProperty); }
set { this.SetValue(HeaderProperty, value); }
}
IEnumerable<ILogical> ILogical.LogicalChildren
{
get
{
ILogical logicalContent = this.Content as ILogical;
ILogical logicalHeader = this.Header as ILogical;
if (logicalContent != null)
{
yield return logicalContent;
}
if (logicalHeader != null)
{
yield return logicalHeader;
}
}
}
}
}

25
Perspex/Controls/HeaderedItemsControl.cs

@ -1,25 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="HeaderedItemsControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections;
using System.Linq;
using System.Reactive.Linq;
public class HeaderedItemsControl : ItemsControl
{
public static readonly PerspexProperty<object> HeaderProperty =
HeaderedContentControl.HeaderProperty.AddOwner<HeaderedItemsControl>();
public object Header
{
get { return this.GetValue(HeaderProperty); }
set { this.SetValue(HeaderProperty, value); }
}
}
}

24
Perspex/Controls/ITemplatedControl.cs

@ -1,24 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ITemplatedControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
public interface ITemplatedControl
{
IEnumerable<IVisual> VisualChildren { get; }
/// <summary>
/// Gets an observable for a <see cref="PerspexProperty"/>.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="property">The property to get the observable for.</param>
/// <returns>The observable.</returns>
IObservable<T> GetObservable<T>(PerspexProperty<T> property);
}
}

115
Perspex/Controls/Image.cs

@ -1,115 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Image.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using Perspex.Media;
using Perspex.Media.Imaging;
public class Image : Control
{
public static readonly PerspexProperty<Bitmap> SourceProperty =
PerspexProperty.Register<Image, Bitmap>("Source");
public static readonly PerspexProperty<Stretch> StretchProperty =
PerspexProperty.Register<Image, Stretch>("Stretch", Stretch.Uniform);
public Bitmap Source
{
get { return this.GetValue(SourceProperty); }
set { this.SetValue(SourceProperty, value); }
}
public Stretch Stretch
{
get { return (Stretch)this.GetValue(StretchProperty); }
set { this.SetValue(StretchProperty, value); }
}
public override void Render(IDrawingContext drawingContext)
{
Brush background = this.Background;
Bitmap source = this.Source;
if (background != null)
{
drawingContext.FillRectange(background, new Rect(this.ActualSize));
}
if (source != null)
{
Rect viewPort = new Rect(this.ActualSize);
Size sourceSize = new Size(source.PixelWidth, source.PixelHeight);
Vector scale = CalculateScaling(this.ActualSize, sourceSize, this.Stretch);
Size scaledSize = sourceSize * scale;
Rect destRect = viewPort
.Center(new Rect(scaledSize))
.Intersect(viewPort);
Rect sourceRect = new Rect(sourceSize)
.Center(new Rect(destRect.Size / scale));
drawingContext.DrawImage(source, 1, sourceRect, destRect);
}
}
private static Vector CalculateScaling(Size availableSize, Size imageSize, Stretch stretch)
{
double scaleX = 1;
double scaleY = 1;
if (stretch != Stretch.None)
{
scaleX = availableSize.Width / imageSize.Width;
scaleY = availableSize.Height / imageSize.Height;
switch (stretch)
{
case Stretch.Uniform:
scaleX = scaleY = Math.Min(scaleX, scaleY);
break;
case Stretch.UniformToFill:
scaleX = scaleY = Math.Max(scaleX, scaleY);
break;
}
}
return new Vector(scaleX, scaleY);
}
protected override Size MeasureOverride(Size availableSize)
{
double width = 0;
double height = 0;
Vector scale = new Vector();
if (this.Source != null)
{
width = this.Source.PixelWidth;
height = this.Source.PixelHeight;
if (this.Width > 0)
{
availableSize = new Size(this.Width, availableSize.Height);
}
if (this.Height > 0)
{
availableSize = new Size(availableSize.Width, this.Height);
}
scale = CalculateScaling(availableSize, new Size(width, height), this.Stretch);
}
return new Size(width * scale.X, height * scale.Y);
}
protected override Size ArrangeOverride(Size finalSize)
{
return finalSize;
}
}
}

137
Perspex/Controls/ItemsControl.cs

@ -1,137 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ItemsControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
public class ItemsControl : TemplatedControl
{
private static readonly ItemsPanelTemplate DefaultPanel =
new ItemsPanelTemplate(() => new StackPanel { Orientation = Orientation.Vertical });
public static readonly PerspexProperty<IEnumerable> ItemsProperty =
PerspexProperty.Register<ItemsControl, IEnumerable>("Items");
public static readonly PerspexProperty<ItemsPanelTemplate> ItemsPanelProperty =
PerspexProperty.Register<ItemsControl, ItemsPanelTemplate>("ItemsPanel", defaultValue: DefaultPanel);
private Dictionary<object, Control> controlsByItem = new Dictionary<object, Control>();
private Dictionary<Control, object> itemsByControl = new Dictionary<Control, object>();
public ItemsControl()
{
this.GetObservableWithHistory(ItemsProperty).Subscribe(this.ItemsChanged);
}
public IEnumerable Items
{
get { return this.GetValue(ItemsProperty); }
set { this.SetValue(ItemsProperty, value); }
}
public ItemsPanelTemplate ItemsPanel
{
get { return this.GetValue(ItemsPanelProperty); }
set { this.SetValue(ItemsPanelProperty, value); }
}
public Control GetControlForItem(object item)
{
Control result;
this.controlsByItem.TryGetValue(item, out result);
return result;
}
public object GetItemForControl(Control control)
{
object result;
this.itemsByControl.TryGetValue(control, out result);
return result;
}
public IEnumerable<Control> GetAllItemControls()
{
return this.controlsByItem.Values;
}
internal Control CreateItemControl(object item)
{
Control control = this.CreateItemControlOverride(item);
this.itemsByControl.Add(control, item);
this.controlsByItem.Add(item, control);
return control;
}
internal void RemoveItemControls(IEnumerable items)
{
foreach (object i in items)
{
Control control = this.GetControlForItem(i);
this.controlsByItem.Remove(i);
this.itemsByControl.Remove(control);
}
}
internal void ClearItemControls()
{
this.controlsByItem.Clear();
this.itemsByControl.Clear();
}
protected virtual Control CreateItemControlOverride(object item)
{
return (item as Control) ?? this.GetDataTemplate(item).Build(item);
}
private void ItemsChanged(Tuple<IEnumerable, IEnumerable> value)
{
INotifyPropertyChanged inpc = value.Item1 as INotifyPropertyChanged;
if (inpc != null)
{
inpc.PropertyChanged -= ItemsPropertyChanged;
}
if (value.Item2 == null || !value.Item2.OfType<object>().Any())
{
this.Classes.Add(":empty");
}
else
{
this.Classes.Remove(":empty");
}
inpc = value.Item2 as INotifyPropertyChanged;
if (inpc != null)
{
inpc.PropertyChanged += ItemsPropertyChanged;
}
}
private void ItemsPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Count")
{
if (((IList)sender).Count == 0)
{
this.Classes.Add(":empty");
}
else
{
this.Classes.Remove(":empty");
}
}
}
}
}

20
Perspex/Controls/ItemsPanelTemplate.cs

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Perspex.Controls
{
public class ItemsPanelTemplate
{
public ItemsPanelTemplate(Func<Panel> build)
{
Contract.Requires<ArgumentNullException>(build != null);
this.Build = build;
}
public Func<Panel> Build { get; private set; }
}
}

190
Perspex/Controls/ItemsPresenter.cs

@ -1,190 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ItemsControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Perspex.Layout;
public class ItemsPresenter : Control, IVisual
{
public static readonly PerspexProperty<IEnumerable> ItemsProperty =
ItemsControl.ItemsProperty.AddOwner<ItemsPresenter>();
public static readonly PerspexProperty<ItemsPanelTemplate> ItemsPanelProperty =
ItemsControl.ItemsPanelProperty.AddOwner<ItemsPresenter>();
private Panel panel;
public ItemsPresenter()
{
this.GetObservableWithHistory(ItemsProperty).Subscribe(this.ItemsChanged);
}
public IEnumerable Items
{
get { return this.GetValue(ItemsProperty); }
set { this.SetValue(ItemsProperty, value); }
}
public ItemsPanelTemplate ItemsPanel
{
get { return this.GetValue(ItemsPanelProperty); }
set { this.SetValue(ItemsPanelProperty, value); }
}
IEnumerable<IVisual> IVisual.ExistingVisualChildren
{
get { return Enumerable.Repeat(this.panel, this.panel != null ? 1 : 0); }
}
IEnumerable<IVisual> IVisual.VisualChildren
{
get { return Enumerable.Repeat(this.GetPanel(), 1); }
}
protected override Size MeasureOverride(Size availableSize)
{
Panel panel = this.GetPanel();
panel.Measure(availableSize);
return panel.DesiredSize.Value;
}
protected override Size ArrangeOverride(Size finalSize)
{
this.GetPanel().Arrange(new Rect(finalSize));
return finalSize;
}
private Control CreateItemControl(object item)
{
ItemsControl i = this.TemplatedParent as ItemsControl;
if (i != null)
{
return i.CreateItemControl(item);
}
else
{
return this.GetDataTemplate(item).Build(item) as Control;
}
}
private IEnumerable<Control> CreateItemControls(IEnumerable items)
{
if (items != null)
{
return items
.Cast<object>()
.Select(x => this.CreateItemControl(x))
.OfType<Control>();
}
else
{
return Enumerable.Empty<Control>();
}
}
private void ClearItemControls()
{
ItemsControl i = this.TemplatedParent as ItemsControl;
if (i != null)
{
i.ClearItemControls();
}
}
private void RemoveItemControls(IEnumerable items)
{
ItemsControl i = this.TemplatedParent as ItemsControl;
if (i != null)
{
i.RemoveItemControls(items);
}
}
private Panel GetPanel()
{
if (this.panel == null && this.ItemsPanel != null)
{
this.panel = this.ItemsPanel.Build();
((IVisual)this.panel).VisualParent = this;
this.ItemsChanged(Tuple.Create(default(IEnumerable), this.Items));
}
return this.panel;
}
private void ItemsChanged(Tuple<IEnumerable, IEnumerable> value)
{
if (value.Item1 != null)
{
INotifyCollectionChanged incc = value.Item1 as INotifyCollectionChanged;
if (incc != null)
{
incc.CollectionChanged -= this.ItemsCollectionChanged;
}
}
this.ClearItemControls();
if (this.panel != null)
{
var controls = this.CreateItemControls(value.Item2).ToList();
foreach (var control in controls)
{
control.TemplatedParent = null;
}
this.panel.Children = new Controls(controls);
INotifyCollectionChanged incc = value.Item2 as INotifyCollectionChanged;
if (incc != null)
{
incc.CollectionChanged += this.ItemsCollectionChanged;
}
}
}
private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (this.panel != null)
{
// TODO: Handle Move and Replace.
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
var controls = this.CreateItemControls(e.NewItems).ToList();
foreach (var control in controls)
{
control.TemplatedParent = null;
}
this.panel.Children.AddRange(controls);
break;
case NotifyCollectionChangedAction.Remove:
this.RemoveItemControls(e.OldItems);
break;
case NotifyCollectionChangedAction.Reset:
this.ItemsChanged(Tuple.Create(this.Items, this.Items));
break;
}
}
}
}
}

99
Perspex/Controls/LogicalChildren.cs

@ -1,99 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="LogicalChildren.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
/// <summary>
/// Manages parenting for a collection of logical child controls.
/// </summary>
/// <typeparam name="T">The type of the controls.</typeparam>
/// <remarks>
/// Unfortunately, because of ObservableCollection's handling of clear (the cleared items
/// aren't passed to the CollectionChanged event) we have to hold two lists of child controls:
/// the ones in Panel.Children and the ones here - held in case the ObservableCollection
/// gets cleared. It's either that or write a proper PerspexList which is too much work
/// for now.
/// </remarks>
internal class LogicalChildren<T> where T : class, ILogical, IVisual
{
private T parent;
private PerspexList<T> childrenCollection;
private List<T> inner = new List<T>();
public LogicalChildren(T parent, PerspexList<T> childrenCollection)
{
this.parent = parent;
this.childrenCollection = childrenCollection;
this.Add(childrenCollection);
childrenCollection.CollectionChanged += this.CollectionChanged;
}
public void Change(PerspexList<T> childrenCollection)
{
this.childrenCollection.CollectionChanged -= this.CollectionChanged;
this.Remove(this.inner.ToList());
this.childrenCollection = childrenCollection;
this.Add(childrenCollection);
childrenCollection.CollectionChanged += this.CollectionChanged;
}
private void Add(IEnumerable<T> items)
{
foreach (T item in items)
{
this.inner.Add(item);
item.LogicalParent = this.parent;
item.VisualParent = this.parent;
}
}
private void Remove(IEnumerable<T> items)
{
foreach (T item in items)
{
this.inner.Remove(item);
item.LogicalParent = null;
item.VisualParent = null;
}
}
private void Reset(IEnumerable<T> newState)
{
this.Add(newState.Except(this.inner));
this.Remove(this.inner.Except(newState));
}
private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
this.Add(e.NewItems.Cast<T>());
break;
case NotifyCollectionChangedAction.Remove:
this.Remove(e.OldItems.Cast<T>());
break;
case NotifyCollectionChangedAction.Replace:
this.Remove(e.OldItems.Cast<T>());
this.Add(e.NewItems.Cast<T>());
break;
case NotifyCollectionChangedAction.Reset:
this.Reset((IEnumerable<T>)sender);
break;
}
}
}
}

64
Perspex/Controls/Panel.cs

@ -1,64 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Panel.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// Base class for controls that can contain multiple children.
/// </summary>
public class Panel : Control, ILogical, IVisual
{
private Controls children;
private LogicalChildren<Control> logicalChildren;
public Controls Children
{
get
{
if (this.children == null)
{
this.children = new Controls();
this.logicalChildren = new LogicalChildren<Control>(this, this.children);
}
return this.children;
}
set
{
this.children = value;
if (this.logicalChildren != null)
{
this.logicalChildren.Change(this.children);
}
else
{
this.logicalChildren = new LogicalChildren<Control>(this, this.children);
}
}
}
IEnumerable<ILogical> ILogical.LogicalChildren
{
get { return this.children ?? Enumerable.Empty<ILogical>(); }
}
IEnumerable<IVisual> IVisual.VisualChildren
{
get { return this.children ?? Enumerable.Empty<IVisual>(); }
}
}
}

53
Perspex/Controls/RowDefinition.cs

@ -1,53 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="RowDefinition.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class RowDefinition : DefinitionBase
{
public static readonly PerspexProperty<double> MaxHeightProperty =
PerspexProperty.Register<RowDefinition, double>("MaxHeight", double.PositiveInfinity);
public static readonly PerspexProperty<double> MinHeightProperty =
PerspexProperty.Register<RowDefinition, double>("MinHeight");
public static readonly PerspexProperty<GridLength> HeightProperty =
PerspexProperty.Register<RowDefinition, GridLength>("Height", new GridLength(1, GridUnitType.Star));
public RowDefinition()
{
}
public RowDefinition(GridLength height)
{
this.Height = height;
}
public double ActualHeight
{
get;
internal set;
}
public double MaxHeight
{
get { return this.GetValue(MaxHeightProperty); }
set { this.SetValue(MaxHeightProperty, value); }
}
public double MinHeight
{
get { return this.GetValue(MinHeightProperty); }
set { this.SetValue(MinHeightProperty, value); }
}
public GridLength Height
{
get { return this.GetValue(HeightProperty); }
set { this.SetValue(HeightProperty, value); }
}
}
}

12
Perspex/Controls/RowDefinitions.cs

@ -1,12 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="RowDefinitions.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class RowDefinitions : PerspexList<RowDefinition>
{
}
}

20
Perspex/Controls/SelectingItemsControl.cs

@ -1,20 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="SelectingItemsControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class SelectingItemsControl : ItemsControl
{
public static readonly PerspexProperty<object> SelectedItemProperty =
PerspexProperty.Register<SelectingItemsControl, object>("SelectedItem");
public object SelectedItem
{
get { return this.GetValue(SelectedItemProperty); }
set { this.SetValue(SelectedItemProperty, value); }
}
}
}

155
Perspex/Controls/StackPanel.cs

@ -1,155 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="StackPanel.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public enum Orientation
{
Vertical,
Horizontal,
}
public class StackPanel : Panel
{
public static readonly PerspexProperty<double> GapProperty =
PerspexProperty.Register<StackPanel, double>("Gap");
public static readonly PerspexProperty<Orientation> OrientationProperty =
PerspexProperty.Register<StackPanel, Orientation>("Orientation");
public double Gap
{
get { return this.GetValue(GapProperty); }
set { this.SetValue(GapProperty, value); }
}
public Orientation Orientation
{
get { return this.GetValue(OrientationProperty); }
set { this.SetValue(OrientationProperty, value); }
}
protected override Size MeasureOverride(Size availableSize)
{
double childAvailableWidth = double.PositiveInfinity;
double childAvailableHeight = double.PositiveInfinity;
if (this.Orientation == Orientation.Vertical)
{
childAvailableWidth = availableSize.Width;
if (!double.IsNaN(this.Width))
{
childAvailableWidth = this.Width;
}
childAvailableWidth = Math.Min(childAvailableWidth, this.MaxWidth);
childAvailableWidth = Math.Max(childAvailableWidth, this.MinWidth);
}
else
{
childAvailableHeight = availableSize.Height;
if (!double.IsNaN(this.Height))
{
childAvailableHeight = this.Height;
}
childAvailableHeight = Math.Min(childAvailableHeight, this.MaxHeight);
childAvailableHeight = Math.Max(childAvailableHeight, this.MinHeight);
}
double measuredWidth = 0;
double measuredHeight = 0;
double gap = this.Gap;
foreach (Control child in this.Children)
{
child.Measure(new Size(childAvailableWidth, childAvailableHeight));
Size size = child.DesiredSize.Value;
if (Orientation == Orientation.Vertical)
{
measuredHeight += size.Height + gap;
measuredWidth = Math.Max(measuredWidth, size.Width);
}
else
{
measuredWidth += size.Width + gap;
measuredHeight = Math.Max(measuredHeight, size.Height);
}
}
return new Size(measuredWidth, measuredHeight);
}
protected override Size ArrangeOverride(Size finalSize)
{
double arrangedWidth = finalSize.Width;
double arrangedHeight = finalSize.Height;
double gap = this.Gap;
if (Orientation == Orientation.Vertical)
{
arrangedHeight = 0;
}
else
{
arrangedWidth = 0;
}
foreach (Control child in this.Children.Where(x => x.DesiredSize.HasValue))
{
double childWidth = child.DesiredSize.Value.Width;
double childHeight = child.DesiredSize.Value.Height;
if (Orientation == Orientation.Vertical)
{
childWidth = finalSize.Width;
Rect childFinal = new Rect(0, arrangedHeight, childWidth, childHeight);
if (childFinal.IsEmpty)
{
child.Arrange(new Rect());
}
else
{
child.Arrange(childFinal);
}
arrangedWidth = Math.Max(arrangedWidth, childWidth);
arrangedHeight += childHeight + gap;
}
else
{
childHeight = finalSize.Height;
Rect childFinal = new Rect(arrangedWidth, 0, childWidth, childHeight);
child.Arrange(childFinal);
arrangedWidth += childWidth + gap;
arrangedHeight = Math.Max(arrangedHeight, childHeight);
}
}
if (Orientation == Orientation.Vertical)
{
arrangedHeight = Math.Max(arrangedHeight - gap, finalSize.Height);
}
else
{
arrangedWidth = Math.Max(arrangedWidth - gap, finalSize.Width);
}
return new Size(arrangedWidth, arrangedHeight);
}
}
}

67
Perspex/Controls/TabControl.cs

@ -1,67 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TabControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
public class TabControl : SelectingItemsControl, ILogical
{
public static readonly PerspexProperty<object> SelectedContentProperty =
PerspexProperty.Register<TabControl, object>("SelectedContent");
private TabStrip tabStrip;
public TabControl()
{
this.GetObservable(SelectedItemProperty).Skip(1).Subscribe(this.SelectedItemChanged);
}
IEnumerable<ILogical> ILogical.LogicalChildren
{
get { return this.Items.OfType<TabItem>(); }
}
protected override void OnTemplateApplied()
{
this.tabStrip = this.GetTemplateControls()
.OfType<TabStrip>()
.FirstOrDefault();
if (this.tabStrip != null)
{
if (this.IsSet(SelectedItemProperty))
{
this.SelectedItem = SelectedItem;
}
this.tabStrip.GetObservable(TabStrip.SelectedItemProperty).Subscribe(x =>
{
this.SelectedItem = x;
});
}
}
private void SelectedItemChanged(object item)
{
this.SelectedItem = item;
ContentControl content = item as ContentControl;
if (content != null)
{
this.SetValue(SelectedContentProperty, content.Content);
}
else
{
this.SetValue(SelectedContentProperty, item);
}
}
}
}

26
Perspex/Controls/TabItem.cs

@ -1,26 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TabItem.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class TabItem : HeaderedContentControl
{
public static readonly PerspexProperty<bool> IsSelectedProperty =
PerspexProperty.Register<TabItem, bool>("IsSelected");
public TabItem()
{
this.AddPseudoClass(IsSelectedProperty, ":selected");
AffectsRender(IsSelectedProperty);
}
public bool IsSelected
{
get { return this.GetValue(IsSelectedProperty); }
set { this.SetValue(IsSelectedProperty, value); }
}
}
}

86
Perspex/Controls/TabStrip.cs

@ -1,86 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TabStrip.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections;
using System.Linq;
using Perspex.Input;
public class TabStrip : SelectingItemsControl
{
private static readonly ItemsPanelTemplate PanelTemplate = new ItemsPanelTemplate(
() => new StackPanel());
static TabStrip()
{
ItemsPanelProperty.OverrideDefaultValue(typeof(TabStrip), PanelTemplate);
}
public TabStrip()
{
this.PointerPressed += this.OnPointerPressed;
this.GetObservable(ItemsProperty).Subscribe(this.ItemsChanged);
this.GetObservable(SelectedItemProperty).Subscribe(this.SelectedItemChanged);
}
protected override Control CreateItemControlOverride(object item)
{
TabItem result = item as TabItem;
if (result == null)
{
result = new TabItem
{
Content = this.GetDataTemplate(item).Build(item),
};
}
result.IsSelected = this.SelectedItem == item;
return result;
}
private void ItemsChanged(IEnumerable items)
{
if (items != null)
{
this.SelectedItem =
items.OfType<TabItem>().FirstOrDefault(x => x.IsSelected) ??
items.OfType<object>().FirstOrDefault();
}
else
{
this.SelectedItem = null;
}
}
private void OnPointerPressed(object sender, PointerEventArgs e)
{
IVisual source = (IVisual)e.Source;
ContentPresenter presenter = source.GetVisualAncestor<ContentPresenter>();
if (presenter != null)
{
TabItem item = presenter.TemplatedParent as TabItem;
if (item != null)
{
this.SelectedItem = item;
}
}
}
private void SelectedItemChanged(object selectedItem)
{
foreach (TabItem item in this.GetAllItemControls())
{
item.IsSelected = item == selectedItem;
}
}
}
}

94
Perspex/Controls/TemplatedControl.cs

@ -1,94 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TemplatedControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections.Generic;
using System.Linq;
using Perspex.Media;
using Splat;
public class TemplatedControl : Control, IVisual, ITemplatedControl
{
public static readonly PerspexProperty<ControlTemplate> TemplateProperty =
PerspexProperty.Register<TemplatedControl, ControlTemplate>("Template");
public ControlTemplate Template
{
get { return this.GetValue(TemplateProperty); }
set { this.SetValue(TemplateProperty, value); }
}
IEnumerable<IVisual> IVisual.ExistingVisualChildren
{
get { return Enumerable.Repeat(this.visualChild, this.visualChild != null ? 1 : 0); }
}
IEnumerable<IVisual> ITemplatedControl.VisualChildren
{
get
{
var template = this.Template;
if (this.visualChild == null && template != null)
{
this.Log().Debug(string.Format(
"Creating template for {0} (#{1:x8})",
this.GetType().Name,
this.GetHashCode()));
this.visualChild = template.Build(this);
this.visualChild.VisualParent = this;
this.OnTemplateApplied();
}
return Enumerable.Repeat(this.visualChild, this.visualChild != null ? 1 : 0);
}
}
IEnumerable<IVisual> IVisual.VisualChildren
{
get { return ((ITemplatedControl)this).VisualChildren; }
}
public sealed override void Render(IDrawingContext context)
{
}
protected override Size ArrangeOverride(Size finalSize)
{
Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control;
if (child != null)
{
child.Arrange(new Rect(finalSize));
return child.ActualSize;
}
else
{
return new Size();
}
}
protected override Size MeasureOverride(Size availableSize)
{
Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control;
if (child != null)
{
child.Measure(availableSize);
return child.DesiredSize.Value;
}
return new Size();
}
protected virtual void OnTemplateApplied()
{
}
}
}

65
Perspex/Controls/TextBlock.cs

@ -1,65 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TextBlock.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using Perspex.Media;
using Perspex.Platform;
using Splat;
public class TextBlock : Control
{
public static readonly PerspexProperty<string> TextProperty =
PerspexProperty.Register<TextBlock, string>("Text");
static TextBlock()
{
AffectsMeasure(TextProperty);
}
public string Text
{
get { return this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); }
}
private FormattedText FormattedText
{
get
{
return new FormattedText
{
FontFamilyName = "Segoe UI",
FontSize = this.FontSize,
Text = this.Text,
};
}
}
public override void Render(IDrawingContext context)
{
Brush background = this.Background;
if (background != null)
{
context.FillRectange(background, new Rect(this.ActualSize));
}
context.DrawText(this.Foreground, new Rect(this.ActualSize), this.FormattedText);
}
protected override Size MeasureOverride(Size availableSize)
{
if (!string.IsNullOrEmpty(this.Text))
{
return this.FormattedText.Measure(availableSize);
}
return new Size();
}
}
}

133
Perspex/Controls/TextBox.cs

@ -1,133 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TextBox.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Linq;
using Perspex.Input;
using Perspex.Platform;
using Perspex.Styling;
using Splat;
public class TextBox : TemplatedControl
{
public static readonly PerspexProperty<string> TextProperty =
TextBlock.TextProperty.AddOwner<TextBox>();
private int caretIndex;
private TextBoxView textBoxView;
static TextBox()
{
FocusableProperty.OverrideDefaultValue(typeof(TextBox), true);
}
public TextBox()
{
this.GotFocus += (s, e) => this.textBoxView.GotFocus();
this.LostFocus += (s, e) => this.textBoxView.LostFocus();
this.KeyDown += this.OnKeyDown;
this.PointerPressed += this.OnPointerPressed;
}
public int CaretIndex
{
get
{
return this.caretIndex;
}
set
{
value = Math.Min(Math.Max(value, 0), this.Text.Length);
if (this.caretIndex != value)
{
this.caretIndex = value;
this.textBoxView.CaretMoved();
}
}
}
public string Text
{
get { return this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); }
}
protected override void OnTemplateApplied()
{
Decorator textContainer = this.GetVisualDescendents()
.OfType<Decorator>()
.FirstOrDefault(x => x.Id == "textContainer");
if (textContainer == null)
{
throw new Exception(
"TextBox template doesn't contain a textContainer " +
"or textContainer is not a Decorator.");
}
textContainer.Content = this.textBoxView = new TextBoxView(this);
this.GetObservable(TextProperty).Subscribe(_ => this.textBoxView.InvalidateText());
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
string text = this.Text;
switch (e.Key)
{
case Key.Left:
--this.CaretIndex;
break;
case Key.Right:
++this.CaretIndex;
break;
case Key.Back:
if (this.caretIndex > 0)
{
this.Text = text.Substring(0, this.caretIndex - 1) + text.Substring(this.caretIndex);
--this.CaretIndex;
}
break;
case Key.Delete:
if (this.caretIndex < text.Length)
{
this.Text = text.Substring(0, this.caretIndex) + text.Substring(this.caretIndex + 1);
}
break;
default:
if (!string.IsNullOrEmpty(e.Text))
{
this.Text = text.Substring(0, this.caretIndex) + e.Text + text.Substring(this.caretIndex);
++this.CaretIndex;
}
break;
}
e.Handled = true;
}
private void OnPointerPressed(object sender, PointerEventArgs e)
{
IPlatformRenderInterface platform = Locator.Current.GetService<IPlatformRenderInterface>();
this.CaretIndex = platform.TextService.GetCaretIndex(
this.textBoxView.FormattedText,
e.GetPosition(this.textBoxView),
this.ActualSize);
}
}
}

126
Perspex/Controls/TextBoxView.cs

@ -1,126 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TextBoxView.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Globalization;
using Perspex.Layout;
using Perspex.Media;
using Perspex.Platform;
using Perspex.Threading;
using Splat;
internal class TextBoxView : Control
{
private TextBox parent;
private FormattedText formattedText;
private DispatcherTimer caretTimer;
private bool caretBlink;
public TextBoxView(TextBox parent)
{
this.caretTimer = new DispatcherTimer();
this.caretTimer.Interval = TimeSpan.FromMilliseconds(500);
this.caretTimer.Tick += this.CaretTimerTick;
this.parent = parent;
}
public FormattedText FormattedText
{
get
{
if (this.formattedText == null)
{
this.formattedText = this.CreateFormattedText();
}
return this.formattedText;
}
}
public new void GotFocus()
{
this.caretBlink = true;
this.caretTimer.Start();
}
public new void LostFocus()
{
this.caretTimer.Stop();
this.InvalidateVisual();
}
public void InvalidateText()
{
this.formattedText = null;
this.InvalidateMeasure();
}
internal void CaretMoved()
{
this.caretBlink = true;
this.caretTimer.Stop();
this.caretTimer.Start();
this.InvalidateVisual();
}
public override void Render(IDrawingContext context)
{
Rect rect = new Rect(this.ActualSize);
context.DrawText(Brushes.Black, rect, this.FormattedText);
if (this.parent.IsFocused)
{
IPlatformRenderInterface platform = Locator.Current.GetService<IPlatformRenderInterface>();
Point caretPos = platform.TextService.GetCaretPosition(
this.formattedText,
this.parent.CaretIndex,
this.ActualSize);
double[] lineHeights = platform.TextService.GetLineHeights(this.formattedText, this.ActualSize);
Brush caretBrush = Brushes.Black;
if (this.caretBlink)
{
context.DrawLine(
new Pen(caretBrush, 1),
caretPos,
new Point(caretPos.X, caretPos.Y + lineHeights[0]));
}
}
}
protected override Size MeasureOverride(Size constraint)
{
if (!string.IsNullOrEmpty(this.parent.Text))
{
return this.FormattedText.Measure(constraint);
}
return new Size();
}
private FormattedText CreateFormattedText()
{
return new FormattedText
{
FontFamilyName = "Segoe UI",
FontSize = this.FontSize,
Text = this.parent.Text,
};
}
private void CaretTimerTick(object sender, EventArgs e)
{
this.caretBlink = !this.caretBlink;
this.InvalidateVisual();
}
}
}

28
Perspex/Controls/ToggleButton.cs

@ -1,28 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ToggleButton.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
public class ToggleButton : Button
{
public static readonly PerspexProperty<bool> IsCheckedProperty =
PerspexProperty.Register<ToggleButton, bool>("IsChecked");
public ToggleButton()
{
this.Click += (s, e) => this.IsChecked = !this.IsChecked;
this.AddPseudoClass(IsCheckedProperty, ":checked");
}
public bool IsChecked
{
get { return this.GetValue(IsCheckedProperty); }
set { this.SetValue(IsCheckedProperty, value); }
}
}
}

107
Perspex/Controls/TreeDataTemplate.cs

@ -1,107 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TreeDataTemplate.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections;
public class TreeDataTemplate : DataTemplate
{
public TreeDataTemplate(
Func<object, Control> build,
Func<object, IEnumerable> itemsSelector)
: this(o => true, build, itemsSelector)
{
}
public TreeDataTemplate(
Type type,
Func<object, Control> build,
Func<object, IEnumerable> itemsSelector)
: this(o => IsInstance(o, type), build, itemsSelector)
{
}
public TreeDataTemplate(
Type type,
Func<object, Control> build,
Func<object, IEnumerable> itemsSelector,
Func<object, bool> isExpanded)
: this(o => IsInstance(o, type), build, itemsSelector, isExpanded)
{
}
public TreeDataTemplate(
Func<object, bool> match,
Func<object, Control> build,
Func<object, IEnumerable> itemsSelector)
: this(match, build, itemsSelector, _ => false)
{
this.ItemsSelector = itemsSelector;
}
public TreeDataTemplate(
Func<object, bool> match,
Func<object, Control> build,
Func<object, IEnumerable> itemsSelector,
Func<object, bool> isExpanded)
: base(match, build)
{
this.ItemsSelector = itemsSelector;
this.IsExpanded = isExpanded;
}
public Func<object, IEnumerable> ItemsSelector { get; private set; }
public Func<object, bool> IsExpanded { get; private set; }
}
public class TreeDataTemplate<T> : TreeDataTemplate
{
public TreeDataTemplate(
Func<T, Control> build,
Func<T, IEnumerable> itemsSelector)
: base(typeof(T), Cast(build), Cast(itemsSelector))
{
}
public TreeDataTemplate(
Func<T, Control> build,
Func<T, IEnumerable> itemsSelector,
Func<T, bool> isExpanded)
: base(typeof(T), Cast(build), Cast(itemsSelector), Cast(isExpanded))
{
}
public TreeDataTemplate(
Func<T, bool> match,
Func<T, Control> build,
Func<T, IEnumerable> itemsSelector)
: base(CastMatch(match), Cast(build), Cast(itemsSelector))
{
}
public TreeDataTemplate(
Func<T, bool> match,
Func<T, Control> build,
Func<T, IEnumerable> itemsSelector,
Func<T, bool> isExpanded)
: base(CastMatch(match), Cast(build), Cast(itemsSelector), Cast(isExpanded))
{
}
private static Func<object, bool> CastMatch(Func<T, bool> f)
{
return o => (o is T) ? f((T)o) : false;
}
private static Func<object, TResult> Cast<TResult>(Func<T, TResult> f)
{
return o => f((T)o);
}
}
}

76
Perspex/Controls/TreeView.cs

@ -1,76 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TreeView.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections;
using System.Linq;
using System.Reactive.Linq;
using Perspex.Input;
public class TreeView : SelectingItemsControl
{
public TreeView()
{
this.PointerPressed += this.OnPointerPressed;
}
protected override Control CreateItemControlOverride(object item)
{
TreeViewItem result = item as TreeViewItem;
if (result == null)
{
TreeDataTemplate template = this.GetTreeDataTemplate(item);
result = new TreeViewItem
{
Header = template.Build(item),
Items = template.ItemsSelector(item),
IsExpanded = template.IsExpanded(item),
};
}
return result;
}
private TreeDataTemplate GetTreeDataTemplate(object item)
{
DataTemplate template = this.GetDataTemplate(item);
TreeDataTemplate treeTemplate = template as TreeDataTemplate;
if (treeTemplate == null)
{
treeTemplate = new TreeDataTemplate(template.Build, x => null);
}
return treeTemplate;
}
private void OnPointerPressed(object sender, PointerEventArgs e)
{
IVisual source = (IVisual)e.Source;
ContentPresenter contentPresenter = source.GetVisualAncestor<ContentPresenter>();
if (contentPresenter != null)
{
TreeViewItem item = contentPresenter.TemplatedParent as TreeViewItem;
if (item != null)
{
foreach (var i in this.GetVisualDescendents().OfType<TreeViewItem>())
{
i.IsSelected = i == item;
}
this.SelectedItem = this.GetItemForControl(item);
}
}
}
}
}

54
Perspex/Controls/TreeViewItem.cs

@ -1,54 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="TreeViewItem.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
public class TreeViewItem : HeaderedItemsControl
{
public static readonly PerspexProperty<bool> IsExpandedProperty =
PerspexProperty.Register<TreeViewItem, bool>("IsExpanded");
public static readonly PerspexProperty<bool> IsSelectedProperty =
PerspexProperty.Register<TreeViewItem, bool>("IsSelected");
TreeView parent;
public TreeViewItem()
{
this.AddPseudoClass(IsSelectedProperty, ":selected");
AffectsRender(IsSelectedProperty);
}
public bool IsExpanded
{
get { return this.GetValue(IsExpandedProperty); }
set { this.SetValue(IsExpandedProperty, value); }
}
public bool IsSelected
{
get { return this.GetValue(IsSelectedProperty); }
set { this.SetValue(IsSelectedProperty, value); }
}
protected override Control CreateItemControlOverride(object item)
{
if (this.parent != null)
{
return this.parent.CreateItemControl(item);
}
else
{
return null;
}
}
protected override void OnVisualParentChanged(IVisual oldParent)
{
this.parent = this.GetVisualAncestor<TreeView>();
}
}
}

71
Perspex/Diagnostics/Debug.cs

@ -1,71 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Debug.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Diagnostics
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Perspex.Controls;
public static class Debug
{
public static string PrintVisualTree(IVisual visual)
{
StringBuilder result = new StringBuilder();
PrintVisualTree(visual, result, 0);
return result.ToString();
}
private static void PrintVisualTree(IVisual visual, StringBuilder builder, int indent)
{
Control control = visual as Control;
builder.Append(Indent(indent - 1));
if (indent > 0)
{
builder.Append(" +- ");
}
builder.Append(visual.GetType().Name);
if (control != null)
{
builder.Append(" ");
builder.AppendLine(control.Classes.ToString());
foreach (var value in control.GetSetValues())
{
builder.Append(Indent(indent));
builder.Append(" | ");
builder.Append(value.Item1.Name);
builder.Append(" = ");
builder.Append(value.Item2 ?? "(null)");
builder.Append(" [");
builder.Append(value.Item3);
builder.AppendLine("]");
}
}
else
{
builder.AppendLine();
}
foreach (var child in visual.VisualChildren)
{
PrintVisualTree(child, builder, indent + 1);
}
}
private static string Indent(int indent)
{
return string.Join("", Enumerable.Repeat(" ", Math.Max(indent, 0)));
}
}
}

14
Perspex/Diagnostics/DevTools.cs

@ -1,14 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="DevTools.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Diagnostics
{
using Perspex.Controls;
public class DevTools : Control
{
}
}

15
Perspex/ICloseable.cs

@ -1,15 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ICloseable.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
public interface ICloseable
{
event EventHandler Closed;
}
}

13
Perspex/IHeadered.cs

@ -1,13 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IHeadered.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
public interface IHeadered
{
object Header { get; set; }
}
}

21
Perspex/ILogical.cs

@ -1,21 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ILogical.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public interface ILogical
{
ILogical LogicalParent { get; set; }
IEnumerable<ILogical> LogicalChildren { get; }
}
}

13
Perspex/IObservableDescription.cs

@ -1,13 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IObservableDescription.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
public interface IObservableDescription
{
string Description { get; }
}
}

66
Perspex/IVisual.cs

@ -1,66 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IVisual.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using Perspex.Media;
/// <summary>
/// Represents a node in the visual scene graph.
/// </summary>
/// <remarks>
/// The <see cref="IVisual"/> interface defines the interface required for a renderer to
/// render a scene graph. You should not usually need to reference this interface unless
/// you are writing a renderer; instead use the extension methods defined in
/// <see cref="VisualExtensions"/> to traverse the scene graph. This interface is
/// implemented by <see cref="Visual"/>. It should not be necessary to implement it
/// anywhere else.
/// </remarks>
public interface IVisual
{
/// <summary>
/// Gets the bounds of the scene graph node.
/// </summary>
/// <returns></returns>
Rect Bounds { get; }
/// <summary>
/// Gets a value indicating whether this scene graph node is visible.
/// </summary>
bool IsVisible { get; }
/// <summary>
/// Gets the opacity of the scene graph node.
/// </summary>
double Opacity { get; }
/// <summary>
/// Gets the render transform of the scene graph node.
/// </summary>
Transform RenderTransform { get; }
/// <summary>
/// Gets the transform origin of the scene graph node.
/// </summary>
Origin TransformOrigin { get; }
/// <summary>
/// Gets the scene graph node's child nodes.
/// </summary>
PerspexList<IVisual> VisualChildren { get; }
/// <summary>
/// Gets the scene graph node's parent node.
/// </summary>
IVisual VisualParent { get; }
/// <summary>
/// Renders the scene graph node to a <see cref="IDrawingContext"/>.
/// </summary>
/// <param name="context">The context.</param>
void Render(IDrawingContext context);
}
}

47
Perspex/Input/FocusManager.cs

@ -1,47 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IFocusManager.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
using Perspex.Controls;
namespace Perspex.Input
{
public class FocusManager : IFocusManager
{
public IInputElement Current
{
get;
private set;
}
public void Focus(IInputElement control)
{
Interactive current = this.Current as Interactive;
Interactive next = control as Interactive;
if (current != null)
{
current.RaiseEvent(new RoutedEventArgs
{
RoutedEvent = Control.LostFocusEvent,
Source = current,
OriginalSource = current,
});
}
this.Current = control;
if (next != null)
{
next.RaiseEvent(new RoutedEventArgs
{
RoutedEvent = Control.GotFocusEvent,
Source = next,
OriginalSource = next,
});
}
}
}
}

21
Perspex/Input/IFocusManager.cs

@ -1,21 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IFocusManager.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public interface IFocusManager
{
IInputElement Current { get; }
void Focus(IInputElement focusable);
}
}

12
Perspex/Input/IInputDevice.cs

@ -1,12 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IInputDevice.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
public interface IInputDevice
{
}
}

37
Perspex/Input/IInputElement.cs

@ -1,37 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IInputElement.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
public interface IInputElement
{
event EventHandler<RoutedEventArgs> GotFocus;
event EventHandler<RoutedEventArgs> LostFocus;
event EventHandler<KeyEventArgs> KeyDown;
event EventHandler<PointerEventArgs> PointerEnter;
event EventHandler<PointerEventArgs> PointerLeave;
event EventHandler<PointerEventArgs> PointerPressed;
event EventHandler<PointerEventArgs> PointerReleased;
bool Focusable { get; }
bool IsFocused { get; }
bool IsPointerOver { get; }
void Focus();
void RaiseEvent(RoutedEventArgs e);
}
}

21
Perspex/Input/IInputManager.cs

@ -1,21 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IInputManager.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
using Perspex.Input.Raw;
using Perspex.Layout;
public interface IInputManager
{
IObservable<RawInputEventArgs> RawEventReceived { get; }
void Process(RawInputEventArgs e);
void SetPointerOver(IPointerDevice device, IVisual visual, Point p);
}
}

33
Perspex/Input/IKeyboardDevice.cs

@ -1,33 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IKeyboardDevice.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
[Flags]
public enum ModifierKeys
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
Windows = 8,
}
[Flags]
public enum KeyStates
{
None = 0,
Down = 1,
Toggled = 2,
}
public interface IKeyboardDevice : IInputDevice
{
ModifierKeys Modifiers { get; }
}
}

13
Perspex/Input/IMouseDevice.cs

@ -1,13 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IMouseDevice.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
public interface IMouseDevice : IPointerDevice
{
Point Position { get; }
}
}

19
Perspex/Input/IPointerDevice.cs

@ -1,19 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IPointerDevice.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
public interface IPointerDevice : IInputDevice
{
Interactive Captured { get; }
void Capture(Interactive visual);
Point GetPosition(IVisual relativeTo);
}
}

128
Perspex/Input/InputElement.cs

@ -1,128 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Control.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Linq;
using Perspex.Input;
using Perspex.Layout;
using Perspex.Media;
using Perspex.Styling;
using Splat;
public class InputElement : Interactive, IInputElement
{
public static readonly PerspexProperty<bool> FocusableProperty =
PerspexProperty.Register<InputElement, bool>("Focusable");
public static readonly PerspexProperty<bool> IsFocusedProperty =
PerspexProperty.Register<InputElement, bool>("IsFocused", false);
public static readonly PerspexProperty<bool> IsPointerOverProperty =
PerspexProperty.Register<InputElement, bool>("IsPointerOver");
public static readonly RoutedEvent<RoutedEventArgs> GotFocusEvent =
RoutedEvent.Register<InputElement, RoutedEventArgs>("GotFocus", RoutingStrategy.Bubble);
public static readonly RoutedEvent<RoutedEventArgs> LostFocusEvent =
RoutedEvent.Register<InputElement, RoutedEventArgs>("LostFocus", RoutingStrategy.Bubble);
public static readonly RoutedEvent<KeyEventArgs> KeyDownEvent =
RoutedEvent.Register<InputElement, KeyEventArgs>("KeyDown", RoutingStrategy.Bubble);
public static readonly RoutedEvent<KeyEventArgs> PreviewKeyDownEvent =
RoutedEvent.Register<InputElement, KeyEventArgs>("PreviewKeyDown", RoutingStrategy.Tunnel);
public static readonly RoutedEvent<PointerEventArgs> PointerEnterEvent =
RoutedEvent.Register<InputElement, PointerEventArgs>("PointerEnter", RoutingStrategy.Direct);
public static readonly RoutedEvent<PointerEventArgs> PointerLeaveEvent =
RoutedEvent.Register<InputElement, PointerEventArgs>("PointerLeave", RoutingStrategy.Direct);
public static readonly RoutedEvent<PointerEventArgs> PointerPressedEvent =
RoutedEvent.Register<InputElement, PointerEventArgs>("PointerPressed", RoutingStrategy.Bubble);
public static readonly RoutedEvent<PointerEventArgs> PointerReleasedEvent =
RoutedEvent.Register<InputElement, PointerEventArgs>("PointerReleased", RoutingStrategy.Bubble);
public InputElement()
{
this.GotFocus += (s, e) => this.IsFocused = true;
this.LostFocus += (s, e) => this.IsFocused = false;
this.PointerEnter += (s, e) => this.IsPointerOver = true;
this.PointerLeave += (s, e) => this.IsPointerOver = false;
}
public event EventHandler<RoutedEventArgs> GotFocus
{
add { this.AddHandler(GotFocusEvent, value); }
remove { this.RemoveHandler(GotFocusEvent, value); }
}
public event EventHandler<RoutedEventArgs> LostFocus
{
add { this.AddHandler(LostFocusEvent, value); }
remove { this.RemoveHandler(LostFocusEvent, value); }
}
public event EventHandler<KeyEventArgs> KeyDown
{
add { this.AddHandler(KeyDownEvent, value); }
remove { this.RemoveHandler(KeyDownEvent, value); }
}
public event EventHandler<PointerEventArgs> PointerEnter
{
add { this.AddHandler(PointerEnterEvent, value); }
remove { this.RemoveHandler(PointerEnterEvent, value); }
}
public event EventHandler<PointerEventArgs> PointerLeave
{
add { this.AddHandler(PointerLeaveEvent, value); }
remove { this.RemoveHandler(PointerLeaveEvent, value); }
}
public event EventHandler<PointerEventArgs> PointerPressed
{
add { this.AddHandler(PointerPressedEvent, value); }
remove { this.RemoveHandler(PointerPressedEvent, value); }
}
public event EventHandler<PointerEventArgs> PointerReleased
{
add { this.AddHandler(PointerReleasedEvent, value); }
remove { this.RemoveHandler(PointerReleasedEvent, value); }
}
public bool Focusable
{
get { return this.GetValue(FocusableProperty); }
set { this.SetValue(FocusableProperty, value); }
}
public bool IsFocused
{
get { return this.GetValue(IsFocusedProperty); }
private set { this.SetValue(IsFocusedProperty, value); }
}
public bool IsPointerOver
{
get { return this.GetValue(IsPointerOverProperty); }
internal set { this.SetValue(IsPointerOverProperty, value); }
}
public void Focus()
{
Locator.Current.GetService<IFocusManager>().Focus(this);
}
}
}

65
Perspex/Input/InputManager.cs

@ -1,65 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="InputManager.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
using Perspex.Controls;
using Perspex.Input.Raw;
public class InputManager : IInputManager
{
private List<Control> pointerOvers = new List<Control>();
private Subject<RawInputEventArgs> rawEventReceived = new Subject<RawInputEventArgs>();
public IObservable<RawInputEventArgs> RawEventReceived
{
get { return this.rawEventReceived; }
}
public void Process(RawInputEventArgs e)
{
this.rawEventReceived.OnNext(e);
}
public void SetPointerOver(IPointerDevice device, IVisual visual, Point p)
{
IEnumerable<IVisual> hits = visual.GetVisualsAt(p);
foreach (var control in this.pointerOvers.ToList().Except(hits).Cast<Control>())
{
PointerEventArgs e = new PointerEventArgs
{
RoutedEvent = InputElement.PointerLeaveEvent,
Device = device,
OriginalSource = control,
Source = control,
};
this.pointerOvers.Remove(control);
control.RaiseEvent(e);
}
foreach (var control in hits.Except(this.pointerOvers).Cast<Control>())
{
PointerEventArgs e = new PointerEventArgs
{
RoutedEvent = InputElement.PointerEnterEvent,
Device = device,
OriginalSource = control,
Source = control,
};
this.pointerOvers.Add(control);
control.RaiseEvent(e);
}
}
}
}

214
Perspex/Input/Key.cs

@ -1,214 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Key.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
public enum Key
{
None = 0,
Cancel = 1,
Back = 2,
Tab = 3,
LineFeed = 4,
Clear = 5,
Return = 6,
Enter = 6,
Pause = 7,
CapsLock = 8,
Capital = 8,
HangulMode = 9,
KanaMode = 9,
JunjaMode = 10,
FinalMode = 11,
KanjiMode = 12,
HanjaMode = 12,
Escape = 13,
ImeConvert = 14,
ImeNonConvert = 15,
ImeAccept = 16,
ImeModeChange = 17,
Space = 18,
PageUp = 19,
Prior = 19,
PageDown = 20,
Next = 20,
End = 21,
Home = 22,
Left = 23,
Up = 24,
Right = 25,
Down = 26,
Select = 27,
Print = 28,
Execute = 29,
Snapshot = 30,
PrintScreen = 30,
Insert = 31,
Delete = 32,
Help = 33,
D0 = 34,
D1 = 35,
D2 = 36,
D3 = 37,
D4 = 38,
D5 = 39,
D6 = 40,
D7 = 41,
D8 = 42,
D9 = 43,
A = 44,
B = 45,
C = 46,
D = 47,
E = 48,
F = 49,
G = 50,
H = 51,
I = 52,
J = 53,
K = 54,
L = 55,
M = 56,
N = 57,
O = 58,
P = 59,
Q = 60,
R = 61,
S = 62,
T = 63,
U = 64,
V = 65,
W = 66,
X = 67,
Y = 68,
Z = 69,
LWin = 70,
RWin = 71,
Apps = 72,
Sleep = 73,
NumPad0 = 74,
NumPad1 = 75,
NumPad2 = 76,
NumPad3 = 77,
NumPad4 = 78,
NumPad5 = 79,
NumPad6 = 80,
NumPad7 = 81,
NumPad8 = 82,
NumPad9 = 83,
Multiply = 84,
Add = 85,
Separator = 86,
Subtract = 87,
Decimal = 88,
Divide = 89,
F1 = 90,
F2 = 91,
F3 = 92,
F4 = 93,
F5 = 94,
F6 = 95,
F7 = 96,
F8 = 97,
F9 = 98,
F10 = 99,
F11 = 100,
F12 = 101,
F13 = 102,
F14 = 103,
F15 = 104,
F16 = 105,
F17 = 106,
F18 = 107,
F19 = 108,
F20 = 109,
F21 = 110,
F22 = 111,
F23 = 112,
F24 = 113,
NumLock = 114,
Scroll = 115,
LeftShift = 116,
RightShift = 117,
LeftCtrl = 118,
RightCtrl = 119,
LeftAlt = 120,
RightAlt = 121,
BrowserBack = 122,
BrowserForward = 123,
BrowserRefresh = 124,
BrowserStop = 125,
BrowserSearch = 126,
BrowserFavorites = 127,
BrowserHome = 128,
VolumeMute = 129,
VolumeDown = 130,
VolumeUp = 131,
MediaNextTrack = 132,
MediaPreviousTrack = 133,
MediaStop = 134,
MediaPlayPause = 135,
LaunchMail = 136,
SelectMedia = 137,
LaunchApplication1 = 138,
LaunchApplication2 = 139,
OemSemicolon = 140,
Oem1 = 140,
OemPlus = 141,
OemComma = 142,
OemMinus = 143,
OemPeriod = 144,
OemQuestion = 145,
Oem2 = 145,
OemTilde = 146,
Oem3 = 146,
AbntC1 = 147,
AbntC2 = 148,
OemOpenBrackets = 149,
Oem4 = 149,
OemPipe = 150,
Oem5 = 150,
OemCloseBrackets = 151,
Oem6 = 151,
OemQuotes = 152,
Oem7 = 152,
Oem8 = 153,
OemBackslash = 154,
Oem102 = 154,
ImeProcessed = 155,
System = 156,
OemAttn = 157,
DbeAlphanumeric = 157,
OemFinish = 158,
DbeKatakana = 158,
DbeHiragana = 159,
OemCopy = 159,
DbeSbcsChar = 160,
OemAuto = 160,
DbeDbcsChar = 161,
OemEnlw = 161,
OemBackTab = 162,
DbeRoman = 162,
DbeNoRoman = 163,
Attn = 163,
CrSel = 164,
DbeEnterWordRegisterMode = 164,
ExSel = 165,
DbeEnterImeConfigureMode = 165,
EraseEof = 166,
DbeFlushString = 166,
Play = 167,
DbeCodeInput = 167,
DbeNoCodeInput = 168,
Zoom = 168,
NoName = 169,
DbeDetermineString = 169,
DbeEnterDialogConversionMode = 170,
Pa1 = 170,
OemClear = 171,
DeadCharProcessed = 172,
}
}

19
Perspex/Input/KeyEventArgs.cs

@ -1,19 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="PointerEventArgs.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
public class KeyEventArgs : RoutedEventArgs
{
public IKeyboardDevice Device { get; set; }
public Key Key { get; set; }
public string Text { get; set; }
}
}

76
Perspex/Input/KeyboardDevice.cs

@ -1,76 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="KeyboardDevice.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
using System.Linq;
using System.Reactive.Linq;
using Perspex.Controls;
using Perspex.Input.Raw;
using Splat;
public abstract class KeyboardDevice : IKeyboardDevice
{
public KeyboardDevice()
{
this.InputManager.RawEventReceived
.OfType<RawKeyEventArgs>()
.Where(x => x.Device == this)
.Subscribe(this.ProcessRawEvent);
}
public IInputManager InputManager
{
get { return Locator.Current.GetService<IInputManager>(); }
}
public IFocusManager FocusManager
{
get { return Locator.Current.GetService<IFocusManager>(); }
}
public IInputElement FocusedElement
{
get;
protected set;
}
public abstract ModifierKeys Modifiers { get; }
private void ProcessRawEvent(RawKeyEventArgs e)
{
IInputElement element = this.FocusedElement;
if (element != null)
{
switch (e.Type)
{
case RawKeyEventType.KeyDown:
element.RaiseEvent(new KeyEventArgs
{
RoutedEvent = Control.PreviewKeyDownEvent,
Device = this,
Key = e.Key,
Text = e.Text,
Source = element,
OriginalSource = element,
});
element.RaiseEvent(new KeyEventArgs
{
RoutedEvent = Control.KeyDownEvent,
Device = this,
Key = e.Key,
Text = e.Text,
Source = element,
OriginalSource = element,
});
break;
}
}
}
}
}

153
Perspex/Input/MouseDevice.cs

@ -1,153 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="MouseDevice.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
using System.Linq;
using System.Reactive.Linq;
using Perspex.Controls;
using Perspex.Input.Raw;
using Splat;
public abstract class MouseDevice : IMouseDevice
{
public MouseDevice()
{
this.InputManager.RawEventReceived
.OfType<RawMouseEventArgs>()
.Where(x => x.Device == this)
.Subscribe(this.ProcessRawEvent);
}
public Interactive Captured
{
get;
protected set;
}
public IInputManager InputManager
{
get { return Locator.Current.GetService<IInputManager>(); }
}
public Point Position
{
get;
protected set;
}
public virtual void Capture(Interactive visual)
{
this.Captured = visual;
}
public Point GetPosition(IVisual relativeTo)
{
Point p = this.GetClientPosition();
IVisual v = relativeTo;
while (v != null)
{
p -= v.Bounds.Position;
v = v.VisualParent;
}
return p;
}
protected abstract Point GetClientPosition();
private void ProcessRawEvent(RawMouseEventArgs e)
{
this.Position = e.Position;
switch (e.Type)
{
case RawMouseEventType.Move:
this.MouseMove((IMouseDevice)e.Device, (IVisual)e.Root, e.Position);
break;
case RawMouseEventType.LeftButtonDown:
this.MouseDown((IMouseDevice)e.Device, (IVisual)e.Root, e.Position);
break;
case RawMouseEventType.LeftButtonUp:
this.MouseUp((IMouseDevice)e.Device, (IVisual)e.Root, e.Position);
break;
}
}
private void MouseMove(IMouseDevice device, IVisual visual, Point p)
{
if (this.Captured == null)
{
this.InputManager.SetPointerOver(this, visual, p);
}
else
{
Point offset = new Point();
foreach (IVisual ancestor in this.Captured.GetVisualAncestors())
{
offset += ancestor.Bounds.Position;
}
this.InputManager.SetPointerOver(this, this.Captured, p - offset);
}
}
private void MouseDown(IMouseDevice device, IVisual visual, Point p)
{
IVisual hit = visual.GetVisualAt(p);
if (hit != null)
{
Interactive interactive = this.Captured ?? (hit as Interactive) ?? hit.GetVisualAncestor<Interactive>();
IInputElement focusable =
this.Captured as IInputElement ??
hit.GetVisualAncestorsAndSelf()
.OfType<IInputElement>()
.FirstOrDefault(x => x.Focusable);
if (interactive != null)
{
interactive.RaiseEvent(new PointerEventArgs
{
Device = this,
RoutedEvent = Control.PointerPressedEvent,
OriginalSource = interactive,
Source = interactive,
});
}
if (focusable != null && focusable.Focusable)
{
focusable.Focus();
}
}
}
private void MouseUp(IMouseDevice device, IVisual visual, Point p)
{
IVisual hit = visual.GetVisualAt(p);
if (hit != null)
{
Interactive source = this.Captured ?? (hit as Interactive) ?? hit.GetVisualAncestor<Interactive>();
if (source != null)
{
source.RaiseEvent(new PointerEventArgs
{
Device = this,
RoutedEvent = Control.PointerReleasedEvent,
OriginalSource = source,
Source = source,
});
}
}
}
}
}

20
Perspex/Input/PointerEventArgs.cs

@ -1,20 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="PointerEventArgs.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
public class PointerEventArgs : RoutedEventArgs
{
public IPointerDevice Device { get; set; }
public Point GetPosition(IVisual relativeTo)
{
return this.Device.GetPosition(relativeTo);
}
}
}

27
Perspex/Input/Raw/RawInputEventArgs.cs

@ -1,27 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="RawInputEventArgs.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input.Raw
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Perspex.Layout;
public class RawInputEventArgs : EventArgs
{
public RawInputEventArgs(IInputDevice device)
{
Contract.Requires<ArgumentNullException>(device != null);
this.Device = device;
}
public IInputDevice Device { get; private set; }
}
}

31
Perspex/Input/Raw/RawKeyEventArgs.cs

@ -1,31 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="RawKeyEventArgs.cs" company="Tricycle">
// Copyright 2014 Tricycle. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input.Raw
{
public enum RawKeyEventType
{
KeyDown,
KeyUp
}
public class RawKeyEventArgs : RawInputEventArgs
{
public RawKeyEventArgs(KeyboardDevice device, RawKeyEventType type, Key key, string text)
: base(device)
{
this.Key = key;
this.Type = type;
this.Text = text;
}
public Key Key { get; set; }
public string Text { get; set; }
public RawKeyEventType Type { get; set; }
}
}

42
Perspex/Input/Raw/RawMouseEventArgs.cs

@ -1,42 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="RawMouseEventArgs.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input.Raw
{
using System;
using Perspex.Layout;
public enum RawMouseEventType
{
Move,
LeftButtonDown,
LeftButtonUp,
}
public class RawMouseEventArgs : RawInputEventArgs
{
public RawMouseEventArgs(
IInputDevice device,
ILayoutRoot root,
RawMouseEventType type,
Point position)
: base(device)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
this.Root = root;
this.Position = position;
this.Type = type;
}
public ILayoutRoot Root { get; private set; }
public Point Position { get; private set; }
public RawMouseEventType Type { get; private set; }
}
}

124
Perspex/Interactive.cs

@ -1,124 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Interactive.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using Perspex.Layout;
public class Interactive : Layoutable
{
private Dictionary<RoutedEvent, List<Delegate>> eventHandlers = new Dictionary<RoutedEvent, List<Delegate>>();
public void AddHandler(RoutedEvent routedEvent, Delegate handler)
{
Contract.Requires<NullReferenceException>(routedEvent != null);
Contract.Requires<NullReferenceException>(handler != null);
List<Delegate> delegates;
if (!this.eventHandlers.TryGetValue(routedEvent, out delegates))
{
delegates = new List<Delegate>();
this.eventHandlers.Add(routedEvent, delegates);
}
delegates.Add(handler);
}
public IObservable<EventPattern<T>> GetObservable<T>(RoutedEvent<T> routedEvent) where T : RoutedEventArgs
{
Contract.Requires<NullReferenceException>(routedEvent != null);
return Observable.FromEventPattern<T>(
handler => this.AddHandler(routedEvent, handler),
handler => this.RemoveHandler(routedEvent, handler));
}
public void RemoveHandler(RoutedEvent routedEvent, Delegate handler)
{
Contract.Requires<NullReferenceException>(routedEvent != null);
Contract.Requires<NullReferenceException>(handler != null);
List<Delegate> delegates;
if (this.eventHandlers.TryGetValue(routedEvent, out delegates))
{
delegates.Remove(handler);
}
}
public void RaiseEvent(RoutedEventArgs e)
{
Contract.Requires<NullReferenceException>(e != null);
if (e.RoutedEvent != null)
{
switch (e.RoutedEvent.RoutingStrategy)
{
case RoutingStrategy.Bubble:
this.BubbleEvent(e);
break;
case RoutingStrategy.Direct:
this.RaiseEventImpl(e);
break;
case RoutingStrategy.Tunnel:
this.TunnelEvent(e);
break;
}
}
}
private void BubbleEvent(RoutedEventArgs e)
{
Contract.Requires<NullReferenceException>(e != null);
foreach (var target in this.GetVisualAncestorsAndSelf().OfType<Interactive>())
{
target.RaiseEventImpl(e);
if (e.Handled)
{
break;
}
}
}
private void TunnelEvent(RoutedEventArgs e)
{
Contract.Requires<NullReferenceException>(e != null);
foreach (var target in this.GetVisualAncestorsAndSelf().OfType<Interactive>().Reverse())
{
target.RaiseEventImpl(e);
if (e.Handled)
{
break;
}
}
}
private void RaiseEventImpl(RoutedEventArgs e)
{
Contract.Requires<NullReferenceException>(e != null);
List<Delegate> delegates;
if (this.eventHandlers.TryGetValue(e.RoutedEvent, out delegates))
{
foreach (Delegate handler in delegates)
{
handler.DynamicInvoke(this, e);
}
}
}
}
}

23
Perspex/Layout/ILayoutManager.cs

@ -1,23 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ILayoutManager.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Layout
{
using System;
using System.Reactive;
using Perspex.Controls;
public interface ILayoutManager
{
IObservable<Unit> LayoutNeeded { get; }
void ExecuteLayoutPass();
void InvalidateMeasure(ILayoutable item);
void InvalidateArrange(ILayoutable item);
}
}

15
Perspex/Layout/ILayoutRoot.cs

@ -1,15 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ILayoutRoot.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Layout
{
public interface ILayoutRoot : ILayoutable
{
Size ClientSize { get; }
ILayoutManager LayoutManager { get; }
}
}

21
Perspex/Layout/ILayoutable.cs

@ -1,21 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ILayoutable.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Layout
{
public interface ILayoutable
{
Size? DesiredSize { get; }
void Arrange(Rect rect);
void Measure(Size availableSize);
void InvalidateArrange();
void InvalidateMeasure();
}
}

59
Perspex/Layout/LayoutHelper.cs

@ -1,59 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="LayoutHelper.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Layout
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Perspex.Controls;
public static class LayoutHelper
{
public static Size ApplyLayoutConstraints(Layoutable control, Size constraints)
{
double width = (control.Width > 0) ? control.Width : constraints.Width;
double height = (control.Height > 0) ? control.Height : constraints.Height;
width = Math.Min(width, control.MaxWidth);
width = Math.Max(width, control.MinWidth);
height = Math.Min(height, control.MaxHeight);
height = Math.Max(height, control.MinHeight);
return new Size(width, height);
}
public static Size MeasureDecorator(
Control decorator,
Control content,
Size availableSize,
Thickness padding)
{
double width = 0;
double height = 0;
if (content != null)
{
content.Measure(availableSize.Deflate(padding));
Size s = content.DesiredSize.Value.Inflate(padding);
width = s.Width;
height = s.Height;
}
if (decorator.Width > 0)
{
width = decorator.Width;
}
if (decorator.Height > 0)
{
height = decorator.Height;
}
return new Size(width, height);
}
}
}

56
Perspex/Layout/LayoutManager.cs

@ -1,56 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="LayoutManager.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Layout
{
using System;
using System.Collections.Generic;
using System.Reactive;
using System.Reactive.Subjects;
using Perspex.Controls;
public class LayoutManager : ILayoutManager
{
private ILayoutRoot root;
private Subject<Unit> layoutNeeded;
public LayoutManager()
{
this.layoutNeeded = new Subject<Unit>();
}
public IObservable<Unit> LayoutNeeded
{
get { return this.layoutNeeded; }
}
public void ExecuteLayoutPass()
{
if (this.root != null)
{
this.root.Measure(this.root.ClientSize);
this.root.Arrange(new Rect(this.root.ClientSize));
}
this.root = null;
}
public void InvalidateMeasure(ILayoutable item)
{
IVisual visual = item as IVisual;
this.root = visual.GetVisualAncestorOrSelf<ILayoutRoot>();
this.layoutNeeded.OnNext(Unit.Default);
}
public void InvalidateArrange(ILayoutable item)
{
IVisual visual = item as IVisual;
this.root = visual.GetVisualAncestorOrSelf<ILayoutRoot>();
this.layoutNeeded.OnNext(Unit.Default);
}
}
}

261
Perspex/Layout/Layoutable.cs

@ -1,261 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Layoutable.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Layout
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public enum HorizontalAlignment
{
Stretch,
Left,
Center,
Right,
}
public enum VerticalAlignment
{
Stretch,
Top,
Center,
Bottom,
}
public class Layoutable : Visual, ILayoutable
{
public static readonly PerspexProperty<double> WidthProperty =
PerspexProperty.Register<Layoutable, double>("Width", double.NaN);
public static readonly PerspexProperty<double> HeightProperty =
PerspexProperty.Register<Layoutable, double>("Height", double.NaN);
public static readonly PerspexProperty<double> MinWidthProperty =
PerspexProperty.Register<Layoutable, double>("MinWidth");
public static readonly PerspexProperty<double> MaxWidthProperty =
PerspexProperty.Register<Layoutable, double>("MaxWidth", double.PositiveInfinity);
public static readonly PerspexProperty<double> MinHeightProperty =
PerspexProperty.Register<Layoutable, double>("MinHeight");
public static readonly PerspexProperty<double> MaxHeightProperty =
PerspexProperty.Register<Layoutable, double>("MaxHeight", double.PositiveInfinity);
public static readonly PerspexProperty<Thickness> MarginProperty =
PerspexProperty.Register<Layoutable, Thickness>("Margin");
public static readonly PerspexProperty<HorizontalAlignment> HorizontalAlignmentProperty =
PerspexProperty.Register<Layoutable, HorizontalAlignment>("HorizontalAlignment");
public static readonly PerspexProperty<VerticalAlignment> VerticalAlignmentProperty =
PerspexProperty.Register<Layoutable, VerticalAlignment>("VerticalAlignment");
public double Width
{
get { return this.GetValue(WidthProperty); }
set { this.SetValue(WidthProperty, value); }
}
public double Height
{
get { return this.GetValue(HeightProperty); }
set { this.SetValue(HeightProperty, value); }
}
public double MinWidth
{
get { return this.GetValue(MinWidthProperty); }
set { this.SetValue(MinWidthProperty, value); }
}
public double MaxWidth
{
get { return this.GetValue(MaxWidthProperty); }
set { this.SetValue(MaxWidthProperty, value); }
}
public double MinHeight
{
get { return this.GetValue(MinHeightProperty); }
set { this.SetValue(MinHeightProperty, value); }
}
public double MaxHeight
{
get { return this.GetValue(MaxHeightProperty); }
set { this.SetValue(MaxHeightProperty, value); }
}
public Thickness Margin
{
get { return this.GetValue(MarginProperty); }
set { this.SetValue(MarginProperty, value); }
}
public HorizontalAlignment HorizontalAlignment
{
get { return this.GetValue(HorizontalAlignmentProperty); }
set { this.SetValue(HorizontalAlignmentProperty, value); }
}
public VerticalAlignment VerticalAlignment
{
get { return this.GetValue(VerticalAlignmentProperty); }
set { this.SetValue(VerticalAlignmentProperty, value); }
}
public Size ActualSize
{
get { return ((IVisual)this).Bounds.Size; }
}
public Size? DesiredSize
{
get;
set;
}
public void Measure(Size availableSize)
{
availableSize = availableSize.Deflate(this.Margin);
this.DesiredSize = this.MeasureCore(availableSize).Constrain(availableSize);
}
public void Arrange(Rect rect)
{
if (this.DesiredSize.HasValue)
{
this.ArrangeCore(rect);
}
}
public void InvalidateMeasure()
{
ILayoutRoot root = this.GetVisualAncestorOrSelf<ILayoutRoot>();
if (root != null && root.LayoutManager != null)
{
root.LayoutManager.InvalidateMeasure(this);
}
}
public void InvalidateArrange()
{
ILayoutRoot root = this.GetVisualAncestorOrSelf<ILayoutRoot>();
if (root != null)
{
root.LayoutManager.InvalidateArrange(this);
}
}
protected static void AffectsArrange(PerspexProperty property)
{
property.Changed.Subscribe(AffectsArrangeInvalidate);
}
protected static void AffectsMeasure(PerspexProperty property)
{
property.Changed.Subscribe(AffectsMeasureInvalidate);
}
protected virtual void ArrangeCore(Rect finalRect)
{
double originX = finalRect.X + this.Margin.Left;
double originY = finalRect.Y + this.Margin.Top;
double sizeX = Math.Max(0, finalRect.Width - this.Margin.Left - this.Margin.Right);
double sizeY = Math.Max(0, finalRect.Height - this.Margin.Top - this.Margin.Bottom);
if (this.HorizontalAlignment != HorizontalAlignment.Stretch)
{
sizeX = Math.Min(sizeX, this.DesiredSize.Value.Width);
}
if (this.VerticalAlignment != VerticalAlignment.Stretch)
{
sizeY = Math.Min(sizeY, this.DesiredSize.Value.Height);
}
Size taken = this.ArrangeOverride(new Size(sizeX, sizeY));
sizeX = Math.Min(taken.Width, sizeX);
sizeY = Math.Min(taken.Height, sizeY);
switch (this.HorizontalAlignment)
{
case HorizontalAlignment.Center:
originX += (finalRect.Width - sizeX) / 2;
break;
case HorizontalAlignment.Right:
originX += finalRect.Width - sizeX;
break;
}
switch (this.VerticalAlignment)
{
case VerticalAlignment.Center:
originY += (finalRect.Height - sizeY) / 2;
break;
case VerticalAlignment.Bottom:
originY += finalRect.Height - sizeY;
break;
}
((IVisual)this).Bounds = new Rect(originX, originY, sizeX, sizeY);
}
protected virtual Size ArrangeOverride(Size finalSize)
{
return finalSize;
}
protected virtual Size MeasureCore(Size availableSize)
{
if (this.IsVisible)
{
availableSize = LayoutHelper.ApplyLayoutConstraints(this, availableSize)
.Deflate(this.Margin);
var measured = this.MeasureOverride(availableSize);
return measured.Inflate(this.Margin);
}
else
{
return new Size();
}
}
protected virtual Size MeasureOverride(Size availableSize)
{
return new Size();
}
private static void AffectsArrangeInvalidate(PerspexPropertyChangedEventArgs e)
{
ILayoutable control = e.Sender as ILayoutable;
if (control != null)
{
control.InvalidateArrange();
}
}
private static void AffectsMeasureInvalidate(PerspexPropertyChangedEventArgs e)
{
ILayoutable control = e.Sender as ILayoutable;
if (control != null)
{
control.InvalidateMeasure();
}
}
}
}

37
Perspex/LogicalExtensions.cs

@ -1,37 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="LogicalExtensions.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
using System.Collections.Generic;
using System.Linq;
using Perspex.Controls;
using Perspex.Styling;
public static class LogicalExtensions
{
public static T FindControl<T>(this ILogical control, string id) where T : Control
{
return control.GetLogicalDescendents()
.OfType<T>()
.FirstOrDefault(x => x.Id == id);
}
public static IEnumerable<ILogical> GetLogicalDescendents(this ILogical control)
{
foreach (ILogical child in control.LogicalChildren)
{
yield return child;
foreach (ILogical descendent in child.GetLogicalDescendents())
{
yield return descendent;
}
}
}
}
}

15
Perspex/Media/Brush.cs

@ -1,15 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Brush.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
/// <summary>
/// Describes how an area is painted.
/// </summary>
public abstract class Brush
{
}
}

301
Perspex/Media/Brushes.cs

@ -1,301 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Brushes.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
/// <summary>
/// Predefined brushes.
/// </summary>
public static class Brushes
{
static Brushes()
{
AliceBlue = new SolidColorBrush(Colors.AliceBlue);
AntiqueWhite = new SolidColorBrush(Colors.AntiqueWhite);
Aqua = new SolidColorBrush(Colors.Aqua);
Aquamarine = new SolidColorBrush(Colors.Aquamarine);
Azure = new SolidColorBrush(Colors.Azure);
Beige = new SolidColorBrush(Colors.Beige);
Bisque = new SolidColorBrush(Colors.Bisque);
Black = new SolidColorBrush(Colors.Black);
BlanchedAlmond = new SolidColorBrush(Colors.BlanchedAlmond);
Blue = new SolidColorBrush(Colors.Blue);
BlueViolet = new SolidColorBrush(Colors.BlueViolet);
Brown = new SolidColorBrush(Colors.Brown);
BurlyWood = new SolidColorBrush(Colors.BurlyWood);
CadetBlue = new SolidColorBrush(Colors.CadetBlue);
Chartreuse = new SolidColorBrush(Colors.Chartreuse);
Chocolate = new SolidColorBrush(Colors.Chocolate);
Coral = new SolidColorBrush(Colors.Coral);
CornflowerBlue = new SolidColorBrush(Colors.CornflowerBlue);
Cornsilk = new SolidColorBrush(Colors.Cornsilk);
Crimson = new SolidColorBrush(Colors.Crimson);
Cyan = new SolidColorBrush(Colors.Cyan);
DarkBlue = new SolidColorBrush(Colors.DarkBlue);
DarkCyan = new SolidColorBrush(Colors.DarkCyan);
DarkGoldenrod = new SolidColorBrush(Colors.DarkGoldenrod);
DarkGray = new SolidColorBrush(Colors.DarkGray);
DarkGreen = new SolidColorBrush(Colors.DarkGreen);
DarkKhaki = new SolidColorBrush(Colors.DarkKhaki);
DarkMagenta = new SolidColorBrush(Colors.DarkMagenta);
DarkOliveGreen = new SolidColorBrush(Colors.DarkOliveGreen);
DarkOrange = new SolidColorBrush(Colors.DarkOrange);
DarkOrchid = new SolidColorBrush(Colors.DarkOrchid);
DarkRed = new SolidColorBrush(Colors.DarkRed);
DarkSalmon = new SolidColorBrush(Colors.DarkSalmon);
DarkSeaGreen = new SolidColorBrush(Colors.DarkSeaGreen);
DarkSlateBlue = new SolidColorBrush(Colors.DarkSlateBlue);
DarkSlateGray = new SolidColorBrush(Colors.DarkSlateGray);
DarkTurquoise = new SolidColorBrush(Colors.DarkTurquoise);
DarkViolet = new SolidColorBrush(Colors.DarkViolet);
DeepPink = new SolidColorBrush(Colors.DeepPink);
DeepSkyBlue = new SolidColorBrush(Colors.DeepSkyBlue);
DimGray = new SolidColorBrush(Colors.DimGray);
DodgerBlue = new SolidColorBrush(Colors.DodgerBlue);
Firebrick = new SolidColorBrush(Colors.Firebrick);
FloralWhite = new SolidColorBrush(Colors.FloralWhite);
ForestGreen = new SolidColorBrush(Colors.ForestGreen);
Fuchsia = new SolidColorBrush(Colors.Fuchsia);
Gainsboro = new SolidColorBrush(Colors.Gainsboro);
GhostWhite = new SolidColorBrush(Colors.GhostWhite);
Gold = new SolidColorBrush(Colors.Gold);
Goldenrod = new SolidColorBrush(Colors.Goldenrod);
Gray = new SolidColorBrush(Colors.Gray);
Green = new SolidColorBrush(Colors.Green);
GreenYellow = new SolidColorBrush(Colors.GreenYellow);
Honeydew = new SolidColorBrush(Colors.Honeydew);
HotPink = new SolidColorBrush(Colors.HotPink);
IndianRed = new SolidColorBrush(Colors.IndianRed);
Indigo = new SolidColorBrush(Colors.Indigo);
Ivory = new SolidColorBrush(Colors.Ivory);
Khaki = new SolidColorBrush(Colors.Khaki);
Lavender = new SolidColorBrush(Colors.Lavender);
LavenderBlush = new SolidColorBrush(Colors.LavenderBlush);
LawnGreen = new SolidColorBrush(Colors.LawnGreen);
LemonChiffon = new SolidColorBrush(Colors.LemonChiffon);
LightBlue = new SolidColorBrush(Colors.LightBlue);
LightCoral = new SolidColorBrush(Colors.LightCoral);
LightCyan = new SolidColorBrush(Colors.LightCyan);
LightGoldenrodYellow = new SolidColorBrush(Colors.LightGoldenrodYellow);
LightGray = new SolidColorBrush(Colors.LightGray);
LightGreen = new SolidColorBrush(Colors.LightGreen);
LightPink = new SolidColorBrush(Colors.LightPink);
LightSalmon = new SolidColorBrush(Colors.LightSalmon);
LightSeaGreen = new SolidColorBrush(Colors.LightSeaGreen);
LightSkyBlue = new SolidColorBrush(Colors.LightSkyBlue);
LightSlateGray = new SolidColorBrush(Colors.LightSlateGray);
LightSteelBlue = new SolidColorBrush(Colors.LightSteelBlue);
LightYellow = new SolidColorBrush(Colors.LightYellow);
Lime = new SolidColorBrush(Colors.Lime);
LimeGreen = new SolidColorBrush(Colors.LimeGreen);
Linen = new SolidColorBrush(Colors.Linen);
Magenta = new SolidColorBrush(Colors.Magenta);
Maroon = new SolidColorBrush(Colors.Maroon);
MediumAquamarine = new SolidColorBrush(Colors.MediumAquamarine);
MediumBlue = new SolidColorBrush(Colors.MediumBlue);
MediumOrchid = new SolidColorBrush(Colors.MediumOrchid);
MediumPurple = new SolidColorBrush(Colors.MediumPurple);
MediumSeaGreen = new SolidColorBrush(Colors.MediumSeaGreen);
MediumSlateBlue = new SolidColorBrush(Colors.MediumSlateBlue);
MediumSpringGreen = new SolidColorBrush(Colors.MediumSpringGreen);
MediumTurquoise = new SolidColorBrush(Colors.MediumTurquoise);
MediumVioletRed = new SolidColorBrush(Colors.MediumVioletRed);
MidnightBlue = new SolidColorBrush(Colors.MidnightBlue);
MintCream = new SolidColorBrush(Colors.MintCream);
MistyRose = new SolidColorBrush(Colors.MistyRose);
Moccasin = new SolidColorBrush(Colors.Moccasin);
NavajoWhite = new SolidColorBrush(Colors.NavajoWhite);
Navy = new SolidColorBrush(Colors.Navy);
OldLace = new SolidColorBrush(Colors.OldLace);
Olive = new SolidColorBrush(Colors.Olive);
OliveDrab = new SolidColorBrush(Colors.OliveDrab);
Orange = new SolidColorBrush(Colors.Orange);
OrangeRed = new SolidColorBrush(Colors.OrangeRed);
Orchid = new SolidColorBrush(Colors.Orchid);
PaleGoldenrod = new SolidColorBrush(Colors.PaleGoldenrod);
PaleGreen = new SolidColorBrush(Colors.PaleGreen);
PaleTurquoise = new SolidColorBrush(Colors.PaleTurquoise);
PaleVioletRed = new SolidColorBrush(Colors.PaleVioletRed);
PapayaWhip = new SolidColorBrush(Colors.PapayaWhip);
PeachPuff = new SolidColorBrush(Colors.PeachPuff);
Peru = new SolidColorBrush(Colors.Peru);
Pink = new SolidColorBrush(Colors.Pink);
Plum = new SolidColorBrush(Colors.Plum);
PowderBlue = new SolidColorBrush(Colors.PowderBlue);
Purple = new SolidColorBrush(Colors.Purple);
Red = new SolidColorBrush(Colors.Red);
RosyBrown = new SolidColorBrush(Colors.RosyBrown);
RoyalBlue = new SolidColorBrush(Colors.RoyalBlue);
SaddleBrown = new SolidColorBrush(Colors.SaddleBrown);
Salmon = new SolidColorBrush(Colors.Salmon);
SandyBrown = new SolidColorBrush(Colors.SandyBrown);
SeaGreen = new SolidColorBrush(Colors.SeaGreen);
SeaShell = new SolidColorBrush(Colors.SeaShell);
Sienna = new SolidColorBrush(Colors.Sienna);
Silver = new SolidColorBrush(Colors.Silver);
SkyBlue = new SolidColorBrush(Colors.SkyBlue);
SlateBlue = new SolidColorBrush(Colors.SlateBlue);
SlateGray = new SolidColorBrush(Colors.SlateGray);
Snow = new SolidColorBrush(Colors.Snow);
SpringGreen = new SolidColorBrush(Colors.SpringGreen);
SteelBlue = new SolidColorBrush(Colors.SteelBlue);
Tan = new SolidColorBrush(Colors.Tan);
Teal = new SolidColorBrush(Colors.Teal);
Thistle = new SolidColorBrush(Colors.Thistle);
Tomato = new SolidColorBrush(Colors.Tomato);
Transparent = new SolidColorBrush(Colors.Transparent);
Turquoise = new SolidColorBrush(Colors.Turquoise);
Violet = new SolidColorBrush(Colors.Violet);
Wheat = new SolidColorBrush(Colors.Wheat);
White = new SolidColorBrush(Colors.White);
WhiteSmoke = new SolidColorBrush(Colors.WhiteSmoke);
Yellow = new SolidColorBrush(Colors.Yellow);
YellowGreen = new SolidColorBrush(Colors.YellowGreen);
}
public static SolidColorBrush AliceBlue { get; private set; }
public static SolidColorBrush AntiqueWhite { get; private set; }
public static SolidColorBrush Aqua { get; private set; }
public static SolidColorBrush Aquamarine { get; private set; }
public static SolidColorBrush Azure { get; private set; }
public static SolidColorBrush Beige { get; private set; }
public static SolidColorBrush Bisque { get; private set; }
public static SolidColorBrush Black { get; private set; }
public static SolidColorBrush BlanchedAlmond { get; private set; }
public static SolidColorBrush Blue { get; private set; }
public static SolidColorBrush BlueViolet { get; private set; }
public static SolidColorBrush Brown { get; private set; }
public static SolidColorBrush BurlyWood { get; private set; }
public static SolidColorBrush CadetBlue { get; private set; }
public static SolidColorBrush Chartreuse { get; private set; }
public static SolidColorBrush Chocolate { get; private set; }
public static SolidColorBrush Coral { get; private set; }
public static SolidColorBrush CornflowerBlue { get; private set; }
public static SolidColorBrush Cornsilk { get; private set; }
public static SolidColorBrush Crimson { get; private set; }
public static SolidColorBrush Cyan { get; private set; }
public static SolidColorBrush DarkBlue { get; private set; }
public static SolidColorBrush DarkCyan { get; private set; }
public static SolidColorBrush DarkGoldenrod { get; private set; }
public static SolidColorBrush DarkGray { get; private set; }
public static SolidColorBrush DarkGreen { get; private set; }
public static SolidColorBrush DarkKhaki { get; private set; }
public static SolidColorBrush DarkMagenta { get; private set; }
public static SolidColorBrush DarkOliveGreen { get; private set; }
public static SolidColorBrush DarkOrange { get; private set; }
public static SolidColorBrush DarkOrchid { get; private set; }
public static SolidColorBrush DarkRed { get; private set; }
public static SolidColorBrush DarkSalmon { get; private set; }
public static SolidColorBrush DarkSeaGreen { get; private set; }
public static SolidColorBrush DarkSlateBlue { get; private set; }
public static SolidColorBrush DarkSlateGray { get; private set; }
public static SolidColorBrush DarkTurquoise { get; private set; }
public static SolidColorBrush DarkViolet { get; private set; }
public static SolidColorBrush DeepPink { get; private set; }
public static SolidColorBrush DeepSkyBlue { get; private set; }
public static SolidColorBrush DimGray { get; private set; }
public static SolidColorBrush DodgerBlue { get; private set; }
public static SolidColorBrush Firebrick { get; private set; }
public static SolidColorBrush FloralWhite { get; private set; }
public static SolidColorBrush ForestGreen { get; private set; }
public static SolidColorBrush Fuchsia { get; private set; }
public static SolidColorBrush Gainsboro { get; private set; }
public static SolidColorBrush GhostWhite { get; private set; }
public static SolidColorBrush Gold { get; private set; }
public static SolidColorBrush Goldenrod { get; private set; }
public static SolidColorBrush Gray { get; private set; }
public static SolidColorBrush Green { get; private set; }
public static SolidColorBrush GreenYellow { get; private set; }
public static SolidColorBrush Honeydew { get; private set; }
public static SolidColorBrush HotPink { get; private set; }
public static SolidColorBrush IndianRed { get; private set; }
public static SolidColorBrush Indigo { get; private set; }
public static SolidColorBrush Ivory { get; private set; }
public static SolidColorBrush Khaki { get; private set; }
public static SolidColorBrush Lavender { get; private set; }
public static SolidColorBrush LavenderBlush { get; private set; }
public static SolidColorBrush LawnGreen { get; private set; }
public static SolidColorBrush LemonChiffon { get; private set; }
public static SolidColorBrush LightBlue { get; private set; }
public static SolidColorBrush LightCoral { get; private set; }
public static SolidColorBrush LightCyan { get; private set; }
public static SolidColorBrush LightGoldenrodYellow { get; private set; }
public static SolidColorBrush LightGray { get; private set; }
public static SolidColorBrush LightGreen { get; private set; }
public static SolidColorBrush LightPink { get; private set; }
public static SolidColorBrush LightSalmon { get; private set; }
public static SolidColorBrush LightSeaGreen { get; private set; }
public static SolidColorBrush LightSkyBlue { get; private set; }
public static SolidColorBrush LightSlateGray { get; private set; }
public static SolidColorBrush LightSteelBlue { get; private set; }
public static SolidColorBrush LightYellow { get; private set; }
public static SolidColorBrush Lime { get; private set; }
public static SolidColorBrush LimeGreen { get; private set; }
public static SolidColorBrush Linen { get; private set; }
public static SolidColorBrush Magenta { get; private set; }
public static SolidColorBrush Maroon { get; private set; }
public static SolidColorBrush MediumAquamarine { get; private set; }
public static SolidColorBrush MediumBlue { get; private set; }
public static SolidColorBrush MediumOrchid { get; private set; }
public static SolidColorBrush MediumPurple { get; private set; }
public static SolidColorBrush MediumSeaGreen { get; private set; }
public static SolidColorBrush MediumSlateBlue { get; private set; }
public static SolidColorBrush MediumSpringGreen { get; private set; }
public static SolidColorBrush MediumTurquoise { get; private set; }
public static SolidColorBrush MediumVioletRed { get; private set; }
public static SolidColorBrush MidnightBlue { get; private set; }
public static SolidColorBrush MintCream { get; private set; }
public static SolidColorBrush MistyRose { get; private set; }
public static SolidColorBrush Moccasin { get; private set; }
public static SolidColorBrush NavajoWhite { get; private set; }
public static SolidColorBrush Navy { get; private set; }
public static SolidColorBrush OldLace { get; private set; }
public static SolidColorBrush Olive { get; private set; }
public static SolidColorBrush OliveDrab { get; private set; }
public static SolidColorBrush Orange { get; private set; }
public static SolidColorBrush OrangeRed { get; private set; }
public static SolidColorBrush Orchid { get; private set; }
public static SolidColorBrush PaleGoldenrod { get; private set; }
public static SolidColorBrush PaleGreen { get; private set; }
public static SolidColorBrush PaleTurquoise { get; private set; }
public static SolidColorBrush PaleVioletRed { get; private set; }
public static SolidColorBrush PapayaWhip { get; private set; }
public static SolidColorBrush PeachPuff { get; private set; }
public static SolidColorBrush Peru { get; private set; }
public static SolidColorBrush Pink { get; private set; }
public static SolidColorBrush Plum { get; private set; }
public static SolidColorBrush PowderBlue { get; private set; }
public static SolidColorBrush Purple { get; private set; }
public static SolidColorBrush Red { get; private set; }
public static SolidColorBrush RosyBrown { get; private set; }
public static SolidColorBrush RoyalBlue { get; private set; }
public static SolidColorBrush SaddleBrown { get; private set; }
public static SolidColorBrush Salmon { get; private set; }
public static SolidColorBrush SandyBrown { get; private set; }
public static SolidColorBrush SeaGreen { get; private set; }
public static SolidColorBrush SeaShell { get; private set; }
public static SolidColorBrush Sienna { get; private set; }
public static SolidColorBrush Silver { get; private set; }
public static SolidColorBrush SkyBlue { get; private set; }
public static SolidColorBrush SlateBlue { get; private set; }
public static SolidColorBrush SlateGray { get; private set; }
public static SolidColorBrush Snow { get; private set; }
public static SolidColorBrush SpringGreen { get; private set; }
public static SolidColorBrush SteelBlue { get; private set; }
public static SolidColorBrush Tan { get; private set; }
public static SolidColorBrush Teal { get; private set; }
public static SolidColorBrush Thistle { get; private set; }
public static SolidColorBrush Tomato { get; private set; }
public static SolidColorBrush Transparent { get; private set; }
public static SolidColorBrush Turquoise { get; private set; }
public static SolidColorBrush Violet { get; private set; }
public static SolidColorBrush Wheat { get; private set; }
public static SolidColorBrush White { get; private set; }
public static SolidColorBrush WhiteSmoke { get; private set; }
public static SolidColorBrush Yellow { get; private set; }
public static SolidColorBrush YellowGreen { get; private set; }
}
}

110
Perspex/Media/Color.cs

@ -1,110 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Color.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
/// <summary>
/// An ARGB color.
/// </summary>
public struct Color
{
/// <summary>
/// Gets or sets the Alpha component of the color.
/// </summary>
public byte A { get; set; }
/// <summary>
/// Gets or sets the Red component of the color.
/// </summary>
public byte R { get; set; }
/// <summary>
/// Gets or sets the Green component of the color.
/// </summary>
public byte G { get; set; }
/// <summary>
/// Gets or sets the Blue component of the color.
/// </summary>
public byte B { get; set; }
/// <summary>
/// Creates a <see cref="Color"/> from alpha, red, green and blue components.
/// </summary>
/// <param name="a">The alpha component.</param>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The color.</returns>
public static Color FromArgb(byte a, byte r, byte g, byte b)
{
return new Color
{
A = a,
R = r,
G = g,
B = b,
};
}
/// <summary>
/// Creates a <see cref="Color"/> from red, green and blue components.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The color.</returns>
public static Color FromRgb(byte r, byte g, byte b)
{
return new Color
{
A = 0xff,
R = r,
G = g,
B = b,
};
}
/// <summary>
/// Creates a <see cref="Color"/> from an integer.
/// </summary>
/// <param name="value">The integer value.</param>
/// <returns>The color.</returns>
public static Color FromUInt32(uint value)
{
return new Color
{
A = (byte)((value >> 24) & 0xff),
R = (byte)((value >> 16) & 0xff),
G = (byte)((value >> 8) & 0xff),
B = (byte)(value & 0xff),
};
}
/// <summary>
/// Returns the string representation of the color.
/// </summary>
/// <returns>
/// The string representation of the color.
/// </returns>
public override string ToString()
{
uint rgb = ((uint)this.A << 24) | ((uint)this.R << 16) | ((uint)this.G << 8) | (uint)this.B;
return string.Format("#{0:x8}", rgb);
}
/// <summary>
/// Returns the integer representation of the color.
/// </summary>
/// <returns>
/// The integer representation of the color.
/// </returns>
public uint ToUint32()
{
return ((uint)this.A << 24) | ((uint)this.R << 16) | ((uint)this.G << 8) | (uint)this.B;
}
}
}

716
Perspex/Media/Colors.cs

@ -1,716 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Colors.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
public sealed class Colors
{
public static Color AliceBlue
{
get { return Color.FromUInt32(0xfff0f8ff); }
}
public static Color AntiqueWhite
{
get { return Color.FromUInt32(0xfffaebd7); }
}
public static Color Aqua
{
get { return Color.FromUInt32(0xff00ffff); }
}
public static Color Aquamarine
{
get { return Color.FromUInt32(0xff7fffd4); }
}
public static Color Azure
{
get { return Color.FromUInt32(0xfff0ffff); }
}
public static Color Beige
{
get { return Color.FromUInt32(0xfff5f5dc); }
}
public static Color Bisque
{
get { return Color.FromUInt32(0xffffe4c4); }
}
public static Color Black
{
get { return Color.FromUInt32(0xff000000); }
}
public static Color BlanchedAlmond
{
get { return Color.FromUInt32(0xffffebcd); }
}
public static Color Blue
{
get { return Color.FromUInt32(0xff0000ff); }
}
public static Color BlueViolet
{
get { return Color.FromUInt32(0xff8a2be2); }
}
public static Color Brown
{
get { return Color.FromUInt32(0xffa52a2a); }
}
public static Color BurlyWood
{
get { return Color.FromUInt32(0xffdeb887); }
}
public static Color CadetBlue
{
get { return Color.FromUInt32(0xff5f9ea0); }
}
public static Color Chartreuse
{
get { return Color.FromUInt32(0xff7fff00); }
}
public static Color Chocolate
{
get { return Color.FromUInt32(0xffd2691e); }
}
public static Color Coral
{
get { return Color.FromUInt32(0xffff7f50); }
}
public static Color CornflowerBlue
{
get { return Color.FromUInt32(0xff6495ed); }
}
public static Color Cornsilk
{
get { return Color.FromUInt32(0xfffff8dc); }
}
public static Color Crimson
{
get { return Color.FromUInt32(0xffdc143c); }
}
public static Color Cyan
{
get { return Color.FromUInt32(0xff00ffff); }
}
public static Color DarkBlue
{
get { return Color.FromUInt32(0xff00008b); }
}
public static Color DarkCyan
{
get { return Color.FromUInt32(0xff008b8b); }
}
public static Color DarkGoldenrod
{
get { return Color.FromUInt32(0xffb8860b); }
}
public static Color DarkGray
{
get { return Color.FromUInt32(0xffa9a9a9); }
}
public static Color DarkGreen
{
get { return Color.FromUInt32(0xff006400); }
}
public static Color DarkKhaki
{
get { return Color.FromUInt32(0xffbdb76b); }
}
public static Color DarkMagenta
{
get { return Color.FromUInt32(0xff8b008b); }
}
public static Color DarkOliveGreen
{
get { return Color.FromUInt32(0xff556b2f); }
}
public static Color DarkOrange
{
get { return Color.FromUInt32(0xffff8c00); }
}
public static Color DarkOrchid
{
get { return Color.FromUInt32(0xff9932cc); }
}
public static Color DarkRed
{
get { return Color.FromUInt32(0xff8b0000); }
}
public static Color DarkSalmon
{
get { return Color.FromUInt32(0xffe9967a); }
}
public static Color DarkSeaGreen
{
get { return Color.FromUInt32(0xff8fbc8f); }
}
public static Color DarkSlateBlue
{
get { return Color.FromUInt32(0xff483d8b); }
}
public static Color DarkSlateGray
{
get { return Color.FromUInt32(0xff2f4f4f); }
}
public static Color DarkTurquoise
{
get { return Color.FromUInt32(0xff00ced1); }
}
public static Color DarkViolet
{
get { return Color.FromUInt32(0xff9400d3); }
}
public static Color DeepPink
{
get { return Color.FromUInt32(0xffff1493); }
}
public static Color DeepSkyBlue
{
get { return Color.FromUInt32(0xff00bfff); }
}
public static Color DimGray
{
get { return Color.FromUInt32(0xff696969); }
}
public static Color DodgerBlue
{
get { return Color.FromUInt32(0xff1e90ff); }
}
public static Color Firebrick
{
get { return Color.FromUInt32(0xffb22222); }
}
public static Color FloralWhite
{
get { return Color.FromUInt32(0xfffffaf0); }
}
public static Color ForestGreen
{
get { return Color.FromUInt32(0xff228b22); }
}
public static Color Fuchsia
{
get { return Color.FromUInt32(0xffff00ff); }
}
public static Color Gainsboro
{
get { return Color.FromUInt32(0xffdcdcdc); }
}
public static Color GhostWhite
{
get { return Color.FromUInt32(0xfff8f8ff); }
}
public static Color Gold
{
get { return Color.FromUInt32(0xffffd700); }
}
public static Color Goldenrod
{
get { return Color.FromUInt32(0xffdaa520); }
}
public static Color Gray
{
get { return Color.FromUInt32(0xff808080); }
}
public static Color Green
{
get { return Color.FromUInt32(0xff008000); }
}
public static Color GreenYellow
{
get { return Color.FromUInt32(0xffadff2f); }
}
public static Color Honeydew
{
get { return Color.FromUInt32(0xfff0fff0); }
}
public static Color HotPink
{
get { return Color.FromUInt32(0xffff69b4); }
}
public static Color IndianRed
{
get { return Color.FromUInt32(0xffcd5c5c); }
}
public static Color Indigo
{
get { return Color.FromUInt32(0xff4b0082); }
}
public static Color Ivory
{
get { return Color.FromUInt32(0xfffffff0); }
}
public static Color Khaki
{
get { return Color.FromUInt32(0xfff0e68c); }
}
public static Color Lavender
{
get { return Color.FromUInt32(0xffe6e6fa); }
}
public static Color LavenderBlush
{
get { return Color.FromUInt32(0xfffff0f5); }
}
public static Color LawnGreen
{
get { return Color.FromUInt32(0xff7cfc00); }
}
public static Color LemonChiffon
{
get { return Color.FromUInt32(0xfffffacd); }
}
public static Color LightBlue
{
get { return Color.FromUInt32(0xffadd8e6); }
}
public static Color LightCoral
{
get { return Color.FromUInt32(0xfff08080); }
}
public static Color LightCyan
{
get { return Color.FromUInt32(0xffe0ffff); }
}
public static Color LightGoldenrodYellow
{
get { return Color.FromUInt32(0xfffafad2); }
}
public static Color LightGray
{
get { return Color.FromUInt32(0xffd3d3d3); }
}
public static Color LightGreen
{
get { return Color.FromUInt32(0xff90ee90); }
}
public static Color LightPink
{
get { return Color.FromUInt32(0xffffb6c1); }
}
public static Color LightSalmon
{
get { return Color.FromUInt32(0xffffa07a); }
}
public static Color LightSeaGreen
{
get { return Color.FromUInt32(0xff20b2aa); }
}
public static Color LightSkyBlue
{
get { return Color.FromUInt32(0xff87cefa); }
}
public static Color LightSlateGray
{
get { return Color.FromUInt32(0xff778899); }
}
public static Color LightSteelBlue
{
get { return Color.FromUInt32(0xffb0c4de); }
}
public static Color LightYellow
{
get { return Color.FromUInt32(0xffffffe0); }
}
public static Color Lime
{
get { return Color.FromUInt32(0xff00ff00); }
}
public static Color LimeGreen
{
get { return Color.FromUInt32(0xff32cd32); }
}
public static Color Linen
{
get { return Color.FromUInt32(0xfffaf0e6); }
}
public static Color Magenta
{
get { return Color.FromUInt32(0xffff00ff); }
}
public static Color Maroon
{
get { return Color.FromUInt32(0xff800000); }
}
public static Color MediumAquamarine
{
get { return Color.FromUInt32(0xff66cdaa); }
}
public static Color MediumBlue
{
get { return Color.FromUInt32(0xff0000cd); }
}
public static Color MediumOrchid
{
get { return Color.FromUInt32(0xffba55d3); }
}
public static Color MediumPurple
{
get { return Color.FromUInt32(0xff9370db); }
}
public static Color MediumSeaGreen
{
get { return Color.FromUInt32(0xff3cb371); }
}
public static Color MediumSlateBlue
{
get { return Color.FromUInt32(0xff7b68ee); }
}
public static Color MediumSpringGreen
{
get { return Color.FromUInt32(0xff00fa9a); }
}
public static Color MediumTurquoise
{
get { return Color.FromUInt32(0xff48d1cc); }
}
public static Color MediumVioletRed
{
get { return Color.FromUInt32(0xffc71585); }
}
public static Color MidnightBlue
{
get { return Color.FromUInt32(0xff191970); }
}
public static Color MintCream
{
get { return Color.FromUInt32(0xfff5fffa); }
}
public static Color MistyRose
{
get { return Color.FromUInt32(0xffffe4e1); }
}
public static Color Moccasin
{
get { return Color.FromUInt32(0xffffe4b5); }
}
public static Color NavajoWhite
{
get { return Color.FromUInt32(0xffffdead); }
}
public static Color Navy
{
get { return Color.FromUInt32(0xff000080); }
}
public static Color OldLace
{
get { return Color.FromUInt32(0xfffdf5e6); }
}
public static Color Olive
{
get { return Color.FromUInt32(0xff808000); }
}
public static Color OliveDrab
{
get { return Color.FromUInt32(0xff6b8e23); }
}
public static Color Orange
{
get { return Color.FromUInt32(0xffffa500); }
}
public static Color OrangeRed
{
get { return Color.FromUInt32(0xffff4500); }
}
public static Color Orchid
{
get { return Color.FromUInt32(0xffda70d6); }
}
public static Color PaleGoldenrod
{
get { return Color.FromUInt32(0xffeee8aa); }
}
public static Color PaleGreen
{
get { return Color.FromUInt32(0xff98fb98); }
}
public static Color PaleTurquoise
{
get { return Color.FromUInt32(0xffafeeee); }
}
public static Color PaleVioletRed
{
get { return Color.FromUInt32(0xffdb7093); }
}
public static Color PapayaWhip
{
get { return Color.FromUInt32(0xffffefd5); }
}
public static Color PeachPuff
{
get { return Color.FromUInt32(0xffffdab9); }
}
public static Color Peru
{
get { return Color.FromUInt32(0xffcd853f); }
}
public static Color Pink
{
get { return Color.FromUInt32(0xffffc0cb); }
}
public static Color Plum
{
get { return Color.FromUInt32(0xffdda0dd); }
}
public static Color PowderBlue
{
get { return Color.FromUInt32(0xffb0e0e6); }
}
public static Color Purple
{
get { return Color.FromUInt32(0xff800080); }
}
public static Color Red
{
get { return Color.FromUInt32(0xffff0000); }
}
public static Color RosyBrown
{
get { return Color.FromUInt32(0xffbc8f8f); }
}
public static Color RoyalBlue
{
get { return Color.FromUInt32(0xff4169e1); }
}
public static Color SaddleBrown
{
get { return Color.FromUInt32(0xff8b4513); }
}
public static Color Salmon
{
get { return Color.FromUInt32(0xfffa8072); }
}
public static Color SandyBrown
{
get { return Color.FromUInt32(0xfff4a460); }
}
public static Color SeaGreen
{
get { return Color.FromUInt32(0xff2e8b57); }
}
public static Color SeaShell
{
get { return Color.FromUInt32(0xfffff5ee); }
}
public static Color Sienna
{
get { return Color.FromUInt32(0xffa0522d); }
}
public static Color Silver
{
get { return Color.FromUInt32(0xffc0c0c0); }
}
public static Color SkyBlue
{
get { return Color.FromUInt32(0xff87ceeb); }
}
public static Color SlateBlue
{
get { return Color.FromUInt32(0xff6a5acd); }
}
public static Color SlateGray
{
get { return Color.FromUInt32(0xff708090); }
}
public static Color Snow
{
get { return Color.FromUInt32(0xfffffafa); }
}
public static Color SpringGreen
{
get { return Color.FromUInt32(0xff00ff7f); }
}
public static Color SteelBlue
{
get { return Color.FromUInt32(0xff4682b4); }
}
public static Color Tan
{
get { return Color.FromUInt32(0xffd2b48c); }
}
public static Color Teal
{
get { return Color.FromUInt32(0xff008080); }
}
public static Color Thistle
{
get { return Color.FromUInt32(0xffd8bfd8); }
}
public static Color Tomato
{
get { return Color.FromUInt32(0xffff6347); }
}
public static Color Transparent
{
get { return Color.FromUInt32(0x00ffffff); }
}
public static Color Turquoise
{
get { return Color.FromUInt32(0xff40e0d0); }
}
public static Color Violet
{
get { return Color.FromUInt32(0xffee82ee); }
}
public static Color Wheat
{
get { return Color.FromUInt32(0xfff5deb3); }
}
public static Color White
{
get { return Color.FromUInt32(0xffffffff); }
}
public static Color WhiteSmoke
{
get { return Color.FromUInt32(0xfff5f5f5); }
}
public static Color Yellow
{
get { return Color.FromUInt32(0xffffff00); }
}
public static Color YellowGreen
{
get { return Color.FromUInt32(0xff9acd32); }
}
}
}

32
Perspex/Media/FormattedText.cs

@ -1,32 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="FormattedText.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using Perspex.Platform;
using Splat;
public class FormattedText
{
public string FontFamilyName { get; set; }
public double FontSize { get; set; }
public string Text { get; set; }
public double[] GetLineHeights(Size constraint)
{
IPlatformRenderInterface factory = Locator.Current.GetService<IPlatformRenderInterface>();
return factory.TextService.GetLineHeights(this, constraint);
}
public Size Measure(Size constraint)
{
IPlatformRenderInterface factory = Locator.Current.GetService<IPlatformRenderInterface>();
return factory.TextService.Measure(this, constraint);
}
}
}

29
Perspex/Media/Geometry.cs

@ -1,29 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Geometry.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using Perspex.Platform;
public abstract class Geometry
{
public abstract Rect Bounds
{
get;
}
public IGeometryImpl PlatformImpl
{
get;
protected set;
}
public Rect GetRenderBounds(double strokeThickness)
{
return this.PlatformImpl.GetRenderBounds(strokeThickness);
}
}
}

67
Perspex/Media/IDrawingContext.cs

@ -1,67 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IDrawingContext.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using System;
using Perspex.Media.Imaging;
/// <summary>
/// Defines the interface through which drawing occurs.
/// </summary>
public interface IDrawingContext : IDisposable
{
Matrix CurrentTransform { get; }
void DrawImage(Bitmap source, double opacity, Rect sourceRect, Rect destRect);
/// <summary>
/// Draws a line.
/// </summary>
/// <param name="pen">The stroke pen.</param>
/// <param name="p1">The first point of the line.</param>
/// <param name="p1">The second point of the line.</param>
void DrawLine(Pen pen, Point p1, Point p2);
/// <summary>
/// Draws a geometry.
/// </summary>
/// <param name="brush">The fill brush.</param>
/// <param name="pen">The stroke pen.</param>
/// <param name="geometry">The geometry.</param>
void DrawGeometry(Brush brush, Pen pen, Geometry geometry);
/// <summary>
/// Draws the outline of a rectangle.
/// </summary>
/// <param name="pen">The pen.</param>
/// <param name="rect">The rectangle bounds.</param>
void DrawRectange(Pen pen, Rect rect);
/// <summary>
/// Draws text.
/// </summary>
/// <param name="foreground">The foreground brush.</param>
/// <param name="rect">The bounding rectangle.</param>
/// <param name="text">The text.</param>
void DrawText(Brush foreground, Rect rect, FormattedText text);
/// <summary>
/// Draws a filled rectangle.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="rect">The rectangle bounds.</param>
void FillRectange(Brush brush, Rect rect);
/// <summary>
/// Pushes a matrix transformation.
/// </summary>
/// <param name="matrix">The matrix</param>
/// <returns>A disposable used to undo the transformation.</returns>
IDisposable PushTransform(Matrix matrix);
}
}

52
Perspex/Media/Imaging/Bitmap.cs

@ -1,52 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Bitmap.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media.Imaging
{
using Perspex.Platform;
using Splat;
public class Bitmap : IBitmap
{
public Bitmap(string fileName)
{
IPlatformRenderInterface factory = Locator.Current.GetService<IPlatformRenderInterface>();
this.PlatformImpl = factory.LoadBitmap(fileName);
}
public Bitmap(int width, int height)
{
IPlatformRenderInterface factory = Locator.Current.GetService<IPlatformRenderInterface>();
this.PlatformImpl = factory.CreateBitmap(width, height);
}
protected Bitmap(IBitmapImpl impl)
{
this.PlatformImpl = impl;
}
public int PixelWidth
{
get { return this.PlatformImpl.PixelWidth; }
}
public int PixelHeight
{
get { return this.PlatformImpl.PixelHeight; }
}
public IBitmapImpl PlatformImpl
{
get;
private set;
}
public void Save(string fileName)
{
this.PlatformImpl.Save(fileName);
}
}
}

17
Perspex/Media/Imaging/IBitmap.cs

@ -1,17 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IBitmap.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media.Imaging
{
public interface IBitmap
{
int PixelHeight { get; }
int PixelWidth { get; }
void Save(string fileName);
}
}

35
Perspex/Media/Imaging/RenderTargetBitmap.cs

@ -1,35 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="RenderTargetBitmap.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media.Imaging
{
using Perspex.Platform;
using Splat;
public class RenderTargetBitmap : Bitmap
{
public RenderTargetBitmap(int width, int height)
: base(CreateImpl(width, height))
{
}
public new IRenderTargetBitmapImpl PlatformImpl
{
get { return (IRenderTargetBitmapImpl)base.PlatformImpl; }
}
public void Render(IVisual visual)
{
this.PlatformImpl.Render(visual);
}
private static IBitmapImpl CreateImpl(int width, int height)
{
IPlatformRenderInterface factory = Locator.Current.GetService<IPlatformRenderInterface>();
return factory.CreateRenderTargetBitmap(width, height);
}
}
}

182
Perspex/Media/Matrix.cs

@ -1,182 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Matrix.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using System;
public struct Matrix
{
private double m11;
private double m12;
private double m21;
private double m22;
private double offsetX;
private double offsetY;
public Matrix(
double m11,
double m12,
double m21,
double m22,
double offsetX,
double offsetY)
{
this.m11 = m11;
this.m12 = m12;
this.m21 = m21;
this.m22 = m22;
this.offsetX = offsetX;
this.offsetY = offsetY;
}
public static Matrix Identity
{
get { return new Matrix(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); }
}
public double Determinant
{
get { return (this.m11 * this.m22) - (this.m12 * this.m21); }
}
public bool HasInverse
{
get { return this.Determinant != 0; }
}
public bool IsIdentity
{
get { return this.Equals(Matrix.Identity); }
}
public double M11
{
get { return this.m11; }
}
public double M12
{
get { return this.m12; }
}
public double M21
{
get { return this.m21; }
}
public double M22
{
get { return this.m22; }
}
public double OffsetX
{
get { return this.offsetX; }
}
public double OffsetY
{
get { return this.offsetY; }
}
public static Matrix operator *(Matrix left, Matrix right)
{
return new Matrix(
(left.M11 * right.M11) + (left.M12 * right.M21),
(left.M11 * right.M12) + (left.M12 * right.M22),
(left.M21 * right.M11) + (left.M22 * right.M21),
(left.M21 * right.M12) + (left.M22 * right.M22),
(left.offsetX * right.M11) + (left.offsetY * right.M21) + right.offsetX,
(left.offsetX * right.M12) + (left.offsetY * right.M22) + right.offsetY);
}
public static bool Equals(Matrix matrix1, Matrix matrix2)
{
return matrix1.Equals(matrix2);
}
public static Matrix Rotation(double angle)
{
double cos = Math.Cos(angle);
double sin = Math.Sin(angle);
return new Matrix(cos, sin, -sin, cos, 0, 0);
}
public static Matrix Translation(Vector v)
{
return Translation(v.X, v.Y);
}
public static Matrix Translation(double x, double y)
{
return new Matrix(1.0, 0.0, 0.0, 1.0, x, y);
}
public static double ToRadians(double angle)
{
return angle * 0.0174532925;
}
public static Matrix operator -(Matrix matrix)
{
return matrix.Invert();
}
public static bool operator ==(Matrix matrix1, Matrix matrix2)
{
return matrix1.Equals(matrix2);
}
public static bool operator !=(Matrix matrix1, Matrix matrix2)
{
return !matrix1.Equals(matrix2);
}
public bool Equals(Matrix value)
{
return this.m11 == value.M11 &&
this.m12 == value.M12 &&
this.m21 == value.M21 &&
this.m22 == value.M22 &&
this.offsetX == value.OffsetX &&
this.offsetY == value.OffsetY;
}
public override bool Equals(object o)
{
if (!(o is Matrix))
{
return false;
}
return this.Equals((Matrix)o);
}
public override int GetHashCode()
{
throw new NotImplementedException();
}
public Matrix Invert()
{
if (!this.HasInverse)
{
throw new InvalidOperationException("Transform is not invertible.");
}
double d = this.Determinant;
return new Matrix(
this.m22 / d,
-this.m12 / d,
-this.m21 / d,
this.m11 / d,
((this.m21 * this.offsetY) - (this.m22 * this.offsetX)) / d,
((this.m12 * this.offsetX) - (this.m11 * this.offsetY)) / d);
}
}
}

289
Perspex/Media/PathMarkupParser.cs

@ -1,289 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="PathMarkupParser.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
public class PathMarkupParser
{
private static readonly Dictionary<char, Command> Commands = new Dictionary<char, Command>
{
{ 'F', Command.FillRule },
{ 'f', Command.FillRule },
{ 'M', Command.Move },
{ 'm', Command.MoveRelative },
{ 'L', Command.Line },
{ 'l', Command.LineRelative },
{ 'H', Command.HorizontalLine },
{ 'h', Command.HorizontalLineRelative },
{ 'V', Command.VerticalLine },
{ 'v', Command.VerticalLineRelative },
{ 'C', Command.CubicBezierCurve },
{ 'c', Command.CubicBezierCurveRelative },
{ 'Z', Command.Close },
{ 'z', Command.Close },
};
private StreamGeometry geometry;
private StreamGeometryContext context;
public PathMarkupParser(StreamGeometry geometry, StreamGeometryContext context)
{
this.geometry = geometry;
this.context = context;
}
private enum Command
{
None,
FillRule,
Move,
MoveRelative,
Line,
LineRelative,
HorizontalLine,
HorizontalLineRelative,
VerticalLine,
VerticalLineRelative,
CubicBezierCurve,
CubicBezierCurveRelative,
Close,
Eof,
}
public void Parse(string s)
{
bool openFigure = false;
using (StringReader reader = new StringReader(s))
{
Command lastCommand = Command.None;
Command command;
Point point = new Point();
while ((command = ReadCommand(reader, lastCommand)) != Command.Eof)
{
switch (command)
{
case Command.FillRule:
// TODO: Implement.
reader.Read();
break;
case Command.Move:
case Command.MoveRelative:
if (openFigure)
{
this.context.EndFigure(false);
}
point = ReadPoint(reader);
this.context.BeginFigure(point, true);
openFigure = true;
break;
case Command.Line:
point = ReadPoint(reader);
this.context.LineTo(point);
break;
case Command.LineRelative:
point = ReadRelativePoint(reader, point);
this.context.LineTo(point);
break;
////case Command.HorizontalLine:
//// point.X = ReadDouble(reader);
//// this.context.LineTo(point, true, false);
//// break;
////case Command.HorizontalLineRelative:
//// point.X += ReadDouble(reader);
//// this.context.LineTo(point, true, false);
//// break;
////case Command.VerticalLine:
//// point.Y = ReadDouble(reader);
//// this.context.LineTo(point, true, false);
//// break;
////case Command.VerticalLineRelative:
//// point.Y += ReadDouble(reader);
//// this.context.LineTo(point, true, false);
//// break;
////case Command.CubicBezierCurve:
////{
//// Point point1 = ReadPoint(reader);
//// Point point2 = ReadPoint(reader);
//// point = ReadPoint(reader);
//// this.context.BezierTo(point1, point2, point, true, false);
//// break;
////}
case Command.Close:
this.context.EndFigure(true);
openFigure = false;
break;
default:
throw new NotSupportedException("Unsupported command");
}
lastCommand = command;
}
if (openFigure)
{
this.context.EndFigure(false);
}
}
}
private static Command ReadCommand(StringReader reader, Command lastCommand)
{
ReadWhitespace(reader);
int i = reader.Peek();
if (i == -1)
{
return Command.Eof;
}
else
{
char c = (char)i;
Command command = Command.None;
if (!Commands.TryGetValue(c, out command))
{
if ((char.IsDigit(c) || c == '.' || c == '+' || c == '-') &&
(lastCommand != Command.None))
{
return lastCommand;
}
else
{
throw new InvalidDataException("Unexpected path command '" + c + "'.");
}
}
reader.Read();
return command;
}
}
private static double ReadDouble(TextReader reader)
{
// TODO: Handle Infinity, NaN and scientific notation.
StringBuilder b = new StringBuilder();
bool readSign = false;
bool readPoint = false;
bool readExponent = false;
int i;
while ((i = reader.Peek()) != -1)
{
char c = char.ToUpperInvariant((char)i);
if (((c == '+' || c == '-') && !readSign) ||
(c == '.' && !readPoint) ||
(c == 'E' && !readExponent) ||
char.IsDigit(c))
{
b.Append(c);
reader.Read();
readSign = c == '+' || c == '-';
readPoint = c == '.';
if (c == 'E')
{
readSign = false;
readExponent = c == 'E';
}
}
else
{
break;
}
}
return double.Parse(b.ToString());
}
private static Point ReadPoint(StringReader reader)
{
ReadWhitespace(reader);
double x = ReadDouble(reader);
ReadSeparator(reader);
double y = ReadDouble(reader);
return new Point(x, y);
}
private static Point ReadRelativePoint(StringReader reader, Point lastPoint)
{
ReadWhitespace(reader);
double x = ReadDouble(reader);
ReadSeparator(reader);
double y = ReadDouble(reader);
return new Point(lastPoint.X + x, lastPoint.Y + y);
}
private static void ReadSeparator(StringReader reader)
{
int i;
bool readComma = false;
while ((i = reader.Peek()) != -1)
{
char c = (char)i;
if (char.IsWhiteSpace(c))
{
reader.Read();
}
else if (c == ',')
{
if (readComma)
{
throw new InvalidDataException("Unexpected ','.");
}
readComma = true;
reader.Read();
}
else
{
break;
}
}
}
private static void ReadWhitespace(StringReader reader)
{
int i;
while ((i = reader.Peek()) != -1)
{
char c = (char)i;
if (char.IsWhiteSpace(c))
{
reader.Read();
}
else
{
break;
}
}
}
}
}

46
Perspex/Media/Pen.cs

@ -1,46 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Pen.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
/// <summary>
/// Describes how a stroke is drawn.
/// </summary>
public class Pen
{
/// <summary>
/// Initializes a new instance of the <see cref="Pen"/> class.
/// </summary>
/// <param name="brush">The brush used to draw.</param>
/// <param name="thickness">The stroke thickness.</param>
public Pen(Brush brush, double thickness)
{
this.Brush = brush;
this.Thickness = thickness;
}
/// <summary>
/// Initializes a new instance of the <see cref="Pen"/> class.
/// </summary>
/// <param name="color">The stroke color.</param>
/// <param name="thickness">The stroke thickness.</param>
public Pen(uint color, double thickness)
{
this.Brush = new SolidColorBrush(color);
this.Thickness = thickness;
}
/// <summary>
/// Gets the brush used to draw the stroke.
/// </summary>
public Brush Brush { get; private set; }
/// <summary>
/// Gets the stroke thickness.
/// </summary>
public double Thickness { get; private set; }
}
}

36
Perspex/Media/RectangleGeometry.cs

@ -1,36 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="RectangleGeometry.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using Perspex.Platform;
using Splat;
public class RectangleGeometry : Geometry
{
public RectangleGeometry(Rect rect)
{
IPlatformRenderInterface factory = Locator.Current.GetService<IPlatformRenderInterface>();
IStreamGeometryImpl impl = factory.CreateStreamGeometry();
using (IStreamGeometryContextImpl context = impl.Open())
{
context.BeginFigure(rect.TopLeft, true);
context.LineTo(rect.TopRight);
context.LineTo(rect.BottomRight);
context.LineTo(rect.BottomLeft);
context.EndFigure(true);
}
this.PlatformImpl = impl;
}
public override Rect Bounds
{
get { return this.PlatformImpl.Bounds; }
}
}
}

34
Perspex/Media/RotateTransform.cs

@ -1,34 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="RotateTransform.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
public class RotateTransform : Transform
{
public static readonly PerspexProperty<double> AngleProperty =
PerspexProperty.Register<RotateTransform, double>("Angle");
public RotateTransform()
{
}
public RotateTransform(double angle)
{
this.Angle = angle;
}
public double Angle
{
get { return this.GetValue(AngleProperty); }
set { this.SetValue(AngleProperty, value); }
}
public override Matrix Value
{
get { return Matrix.Rotation(Matrix.ToRadians(this.Angle)); }
}
}
}

46
Perspex/Media/SolidColorBrush.cs

@ -1,46 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="SolidColorBrush.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
/// <summary>
/// Fills an area with a solid color.
/// </summary>
public class SolidColorBrush : Brush
{
/// <summary>
/// Initializes a new instance of the <see cref="SolidColorBrush"/> class.
/// </summary>
/// <param name="color">The color to use.</param>
public SolidColorBrush(Color color)
{
this.Color = color;
}
/// <summary>
/// Initializes a new instance of the <see cref="SolidColorBrush"/> class.
/// </summary>
/// <param name="color">The color to use.</param>
public SolidColorBrush(uint color)
: this(Color.FromUInt32(color))
{
}
/// <summary>
/// Gets the color of the brush.
/// </summary>
public Color Color
{
get;
private set;
}
public override string ToString()
{
return this.Color.ToString();
}
}
}

42
Perspex/Media/StreamGeometry.cs

@ -1,42 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="StreamGeometry.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using Perspex.Platform;
using Splat;
public class StreamGeometry : Geometry
{
public StreamGeometry()
{
IPlatformRenderInterface factory = Locator.Current.GetService<IPlatformRenderInterface>();
this.PlatformImpl = factory.CreateStreamGeometry();
}
public override Rect Bounds
{
get { return this.PlatformImpl.Bounds; }
}
public static StreamGeometry Parse(string s)
{
StreamGeometry result = new StreamGeometry();
using (StreamGeometryContext ctx = result.Open())
{
PathMarkupParser parser = new PathMarkupParser(result, ctx);
parser.Parse(s);
return result;
}
}
public StreamGeometryContext Open()
{
return new StreamGeometryContext(((IStreamGeometryImpl)this.PlatformImpl).Open());
}
}
}

41
Perspex/Media/StreamGeometryContext.cs

@ -1,41 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="StreamGeometryContext.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using System;
using Perspex.Platform;
public class StreamGeometryContext : IDisposable
{
private IStreamGeometryContextImpl impl;
public StreamGeometryContext(IStreamGeometryContextImpl impl)
{
this.impl = impl;
}
public void BeginFigure(Point startPoint, bool isFilled)
{
this.impl.BeginFigure(startPoint, isFilled);
}
public void LineTo(Point point)
{
this.impl.LineTo(point);
}
public void EndFigure(bool isClosed)
{
this.impl.EndFigure(isClosed);
}
public void Dispose()
{
this.impl.Dispose();
}
}
}

16
Perspex/Media/Stretch.cs

@ -1,16 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Stretch.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
public enum Stretch
{
None,
Fill,
Uniform,
UniformToFill,
}
}

13
Perspex/Media/Transform.cs

@ -1,13 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Transform.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
public abstract class Transform : PerspexObject
{
public abstract Matrix Value { get; }
}
}

54
Perspex/Origin.cs

@ -1,54 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Origin.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
using System.Globalization;
public enum OriginUnit
{
Percent,
Pixels,
}
public struct Origin
{
public static readonly Origin Default = new Origin(0.5, 0.5, OriginUnit.Percent);
private Point point;
private OriginUnit unit;
public Origin(double x, double y, OriginUnit unit)
: this(new Point(x, y), unit)
{
}
public Origin(Point point, OriginUnit unit)
{
this.point = point;
this.unit = unit;
}
public Point Point
{
get { return this.point; }
}
public OriginUnit Unit
{
get { return this.unit; }
}
public Point ToPixels(Size size)
{
return this.unit == OriginUnit.Pixels ?
point :
new Point(point.X * size.Width, point.Y * size.Height);
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save