From 84fd1936b35030e409650d054d2f8ac2b34f91d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Manuel=20Nieto?= Date: Sat, 5 Dec 2015 12:11:52 +0100 Subject: [PATCH 01/11] Fixed link in readme This is de link to the video for Mobile Devices :) https://www.youtube.com/watch?v=NJ9-hnmUbBM --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index c57bb7ba4e..6eec66c9ae 100644 --- a/readme.md +++ b/readme.md @@ -13,7 +13,7 @@ Desktop platforms: Mobile platforms: -![](https://i.ytimg.com/vi/NJ9-hnmUbBM/hqdefault.jpg) +![](https://i.ytimg.com/vi/NJ9-hnmUbBM/hqdefault.jpg) ## NuGet From 5ac1f7c0c5dbfc511e822a61dd08e9791fb123d0 Mon Sep 17 00:00:00 2001 From: donandren Date: Sat, 5 Dec 2015 15:46:44 +0200 Subject: [PATCH 02/11] ios keyboard support --- src/iOS/Perspex.iOS/Perspex.iOS.csproj | 1 + src/iOS/Perspex.iOS/PerspexView.cs | 16 ++ .../Specific/KeyboardEventsHelper.cs | 147 ++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 src/iOS/Perspex.iOS/Specific/KeyboardEventsHelper.cs diff --git a/src/iOS/Perspex.iOS/Perspex.iOS.csproj b/src/iOS/Perspex.iOS/Perspex.iOS.csproj index 1a5866908b..0d670ac5ed 100644 --- a/src/iOS/Perspex.iOS/Perspex.iOS.csproj +++ b/src/iOS/Perspex.iOS/Perspex.iOS.csproj @@ -42,6 +42,7 @@ + diff --git a/src/iOS/Perspex.iOS/PerspexView.cs b/src/iOS/Perspex.iOS/PerspexView.cs index 1bea986c98..43d941fba3 100644 --- a/src/iOS/Perspex.iOS/PerspexView.cs +++ b/src/iOS/Perspex.iOS/PerspexView.cs @@ -14,26 +14,41 @@ using Perspex.Media; using Perspex.Platform; using Perspex.Skia.iOS; using UIKit; +using Perspex.iOS.Specific; +using ObjCRuntime; namespace Perspex.iOS { + [Adopts("UIKeyInput")] class PerspexView : SkiaView, IWindowImpl { private readonly UIWindow _window; private readonly UIViewController _controller; private IInputRoot _inputRoot; + private readonly KeyboardEventsHelper _keyboardHelper; public PerspexView(UIWindow window, UIViewController controller) : base(onFrame => PlatformThreadingInterface.Instance.Render = onFrame) { if (controller == null) throw new ArgumentNullException(nameof(controller)); _window = window; _controller = controller; + _keyboardHelper = new KeyboardEventsHelper(this); AutoresizingMask = UIViewAutoresizing.All; AutoFit(); UIApplication.Notifications.ObserveDidChangeStatusBarOrientation(delegate { AutoFit(); }); UIApplication.Notifications.ObserveDidChangeStatusBarFrame(delegate { AutoFit(); }); } + [Export("hasText")] + bool HasText => _keyboardHelper.HasText(); + + [Export("insertText:")] + void InsertText(string text) => _keyboardHelper.InsertText(text); + + [Export("deleteBackward")] + void DeleteBackward() => _keyboardHelper.DeleteBackward(); + + public override bool CanBecomeFirstResponder => _keyboardHelper.CanBecomeFirstResponder(); void AutoFit() { @@ -89,6 +104,7 @@ namespace Perspex.iOS public void Show() { + _keyboardHelper.ActivateAutoShowKeybord(); } public Size MaxClientSize => Bounds.Size.ToPerspex(); diff --git a/src/iOS/Perspex.iOS/Specific/KeyboardEventsHelper.cs b/src/iOS/Perspex.iOS/Specific/KeyboardEventsHelper.cs new file mode 100644 index 0000000000..872f9cd37d --- /dev/null +++ b/src/iOS/Perspex.iOS/Specific/KeyboardEventsHelper.cs @@ -0,0 +1,147 @@ +using ObjCRuntime; +using Perspex.Controls; +using Perspex.Input; +using Perspex.Input.Raw; +using Perspex.Platform; +using System; +using System.ComponentModel; +using System.Linq; +using UIKit; + +namespace Perspex.iOS.Specific +{ + /// + /// In order to have properly handle of keyboard event in iOS View should already made some things in the View: + /// 1. Adopt the UIKeyInput protocol - add [Adopts("UIKeyInput")] to your view class + /// 2. Implement all the methods required by UIKeyInput: + /// 2.1 Implement HasText + /// example: + /// [Export("hasText")] + /// bool HasText => _keyboardHelper.HasText() + /// 2.2 Implement InsertText + /// example: + /// [Export("insertText:")] + /// void InsertText(string text) => _keyboardHelper.InsertText(text); + /// 2.3 Implement InsertText + /// example: + /// [Export("deleteBackward")] + /// void DeleteBackward() => _keyboardHelper.DeleteBackward(); + /// 3.Let iOS know that this can become a first responder: + /// public override bool CanBecomeFirstResponder => _keyboardHelper.CanBecomeFirstResponder(); + /// or + /// public override bool CanBecomeFirstResponder { get { return true; } } + /// + /// 4. To show keyboard: + /// view.BecomeFirstResponder(); + /// 5. To hide keyboard + /// view.ResignFirstResponder(); + /// + /// View that needs keyboard events and show/hide keyboard + internal class KeyboardEventsHelper where TView : UIView, IWindowImpl + { + private TView _view; + private IInputElement _lastFocusedElement; + + public KeyboardEventsHelper(TView view) + { + _view = view; + + var uiKeyInputAttribute = view.GetType().GetCustomAttributes(typeof(AdoptsAttribute), true).OfType().Where(a => a.ProtocolType == "UIKeyInput").FirstOrDefault(); + + if (uiKeyInputAttribute == null) throw new NotSupportedException($"View class {typeof(TView).Name} should have class attribute - [Adopts(\"UIKeyInput\")] in order to access keyboard events!"); + + HandleEvents = true; + } + + /// + /// HandleEvents in order to suspend keyboard notifications or resume it + /// + public bool HandleEvents { get; set; } + + public bool HasText() => false; + + public bool CanBecomeFirstResponder() => true; + + public void DeleteBackward() + { + HandleKey(Key.Back, RawKeyEventType.KeyDown); + HandleKey(Key.Back, RawKeyEventType.KeyUp); + } + + public void InsertText(string text) + { + var rawTextEvent = new RawTextInputEventArgs(KeyboardDevice.Instance, (uint)DateTime.Now.Ticks, text); + _view.Input(rawTextEvent); + } + + private void HandleKey(Key key, RawKeyEventType type) + { + var rawKeyEvent = new RawKeyEventArgs(KeyboardDevice.Instance, (uint)DateTime.Now.Ticks, type, key, InputModifiers.None); + _view.Input(rawKeyEvent); + } + + //currently not found a way to get InputModifiers state + //private static InputModifiers GetModifierKeys(object e) + //{ + // var im = InputModifiers.None; + // //if (IsCtrlPressed) rv |= InputModifiers.Control; + // //if (IsShiftPressed) rv |= InputModifiers.Shift; + + // return im; + //} + + private bool NeedsKeyboard(IInputElement element) + { + //may be some other elements + return element is TextBox; + } + + private void TryShowHideKeyboard(IInputElement element, bool value) + { + if (value) + { + _view.BecomeFirstResponder(); + } + else + { + _view.ResignFirstResponder(); + } + } + + public void UpdateKeyboardState(IInputElement element) + { + var focusedElement = element; + bool oldValue = NeedsKeyboard(_lastFocusedElement); + bool newValue = NeedsKeyboard(focusedElement); + + if (newValue != oldValue || newValue) + { + TryShowHideKeyboard(focusedElement, newValue); + } + + _lastFocusedElement = element; + } + + public void ActivateAutoShowKeybord() + { + var kbDevice = (KeyboardDevice.Instance as INotifyPropertyChanged); + + //just in case we've called more than once the method + kbDevice.PropertyChanged -= KeyboardDevice_PropertyChanged; + kbDevice.PropertyChanged += KeyboardDevice_PropertyChanged; + } + + private void KeyboardDevice_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(KeyboardDevice.FocusedElement)) + { + UpdateKeyboardState(KeyboardDevice.Instance.FocusedElement); + } + } + + public void Dispose() + { + HandleEvents = false; + } + } +} \ No newline at end of file From fcf79c45eba904a966c9abd11ebaaf37bf74ce4d Mon Sep 17 00:00:00 2001 From: donandren Date: Sat, 5 Dec 2015 17:36:17 +0200 Subject: [PATCH 03/11] enhanced emulation of mouse scroll event from touch in iOS --- src/iOS/Perspex.iOS/PerspexView.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/iOS/Perspex.iOS/PerspexView.cs b/src/iOS/Perspex.iOS/PerspexView.cs index 43d941fba3..4adfb98790 100644 --- a/src/iOS/Perspex.iOS/PerspexView.cs +++ b/src/iOS/Perspex.iOS/PerspexView.cs @@ -168,8 +168,14 @@ namespace Perspex.iOS RawMouseEventType.Move, location, InputModifiers.LeftMouseButton)); else { - Input?.Invoke(new RawMouseWheelEventArgs(PerspexAppDelegate.MouseDevice, (uint) touch.Timestamp, - _inputRoot, location, location - _touchLastPoint, InputModifiers.LeftMouseButton)); + double x = location.X - _touchLastPoint.X; + double y = location.Y - _touchLastPoint.Y; + double correction = 0.02; + var scale = PerspexLocator.Current.GetService().RenderScalingFactor; + scale = 1; + + Input?.Invoke(new RawMouseWheelEventArgs(PerspexAppDelegate.MouseDevice, (uint)touch.Timestamp, + _inputRoot, location, new Vector(x * correction / scale, y * correction / scale), InputModifiers.LeftMouseButton)); } _touchLastPoint = location; } From fe88eae319e34e541043ded57b0b053ac7991e18 Mon Sep 17 00:00:00 2001 From: susloparov Date: Tue, 8 Dec 2015 03:10:57 +0600 Subject: [PATCH 04/11] Somehow PathTests.cs was treated as a binary file by git. Fixed that. --- tests/Perspex.RenderTests/Shapes/PathTests.cs | Bin 10128 -> 4930 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/Perspex.RenderTests/Shapes/PathTests.cs b/tests/Perspex.RenderTests/Shapes/PathTests.cs index 54cdf7e1cf79334d3f45afc531ab3223239b8aed..6a2c96feb533b42d197f3b6d71bbbcb273097e8a 100644 GIT binary patch literal 4930 zcmeHK-EW&n5P#>dSh+8@6m7s51Fb4u;v}urL}$gmYjk%N+QQiE1p`{vy`-o7?>7tB zhJssL=ZD-WJn%95o6nsYc1};pC`lg$Uxbo${T`WxKqerv6duS#B!7Z0DLIQGl0z~g zAOrCQ0;-*!l56fmoIyZVaR7oycsNK}w1nF16aKG0=A<~#zz;~bY3vWZ9%N#=>9dtSkSqhEiYxbC|D^e>DmdaEi9_+0y2BY35&&lo-8M=Z<8gvl_sio7Q3dCpL}LKWBw zeuM1xa)4S=*K6__dAdJ!ifI0!aGfn=E9Xhu@cn+peEDhfSz7cZ;X!VYXXtwR;LQYQ z@gf3m1hE7GK}GXctg_(({6sK`$sw6ofFy5841aCO8%+vaXH}GsJdh#s^mYBD233pi zAy4@otD}%dL8(r8-e7NPQ$nve=I~o`E>>9x8GR?%V^gyNPBDY;p#r^y;Cskf$o=~m zaA(orcHsL&@UK`JEINz$B3@!}5!^zhMcmt^{0c&Hzb>Oe`>uowCK)P54}mS;L9zrX z9_fS$%%;u_(N8c7$Th)x{$}YXI{B^BYnt;^3;Gk*rHb78Dl0F+kVCgfkKUUaVw5aX zCSbf|3&^^aMaoqk}luqFELj?ie~btO=-#f=U5SjF|g=Rw+-92&4FoKCj(O_qjoY< z4LTUOu4Ndu;pAY8>bBjtbxXG$qi>PpVN93y&3@G|lj^SP+Lq;5E}DwEj)rm2?*X+e z(=knbA6`xe2enS8y%)Z;&Lg(PeOmC*+TuPf_@ExSqocmG&hGDT%4nwzSol$eUt>NGQIuoD zmhajhV%8V*b^)Kq$dVl5@;2VIKfOGPDgo`rop&e>_f|-;h zz)TrDVC?%)J!xW22Q&JYf z*i%qD0oALiZ31fx+&5!j->GFf7kDV^J;3g%oNKZT&bDMt-bn*;F2Q2k@=E3F17A=1 z9pH`jiPKCIxTu#r=FuOV5A5i?5oC=@?x?rbI&mD-+N=&~lU6p$h^?)9|fW0JA zt*T6JeLR#^DWsH+TA+qW?}t7;=#JL_*7)rErU#uKLbJ!Xs9AdD0oDsWgqri@5pL@* zE2NXbutjm(Xq3ifyg5V%a%S-3EvbI?spaIU%td_n;{~U46Y#`yb*?ny=zfrApvGAA zDVDFOJYV5!9gPwuSp)W2z%@X0Yd~L&g-u<_j3M-D`sE1EA?_C9W4!$Fe4BPwF?ScV zhrm73mT{?x{yx4i20g*u$NM+5m!ab%H{8=H8`N8sn?B-bJyfah$Lh@HSi26sf($`U z)68B0O-5wK=CG7zfoZZC2gzhK=x0igah&v)p=Cx}W)()1=W2yhNhZ7Dtiwu-R9#?+ z$IA%Tx&~HeTxPni`hi>5PS@!;U046=$QfFCZWFp^j;00s8k0HdWJm_f92TsCblkkb z%pvGevT2-L4R;+bR(0JqeW{%-+ZgM?8`{tlGZpQ73jd&Avf^oDtbrz9BD(F@8Dq^&Vw=yimH|CZVd`%ARVEOM+ z!d1gn*7>AS4Php2Qm&w;tKf~ftOAGv`en^^q{1tIe(pXXDqTDseQ^r-r zUGufd9A3ctZNpRb?Og)*UfQgWwmPDzRlm;1xb@}vRc(@=i66f&Z_3Ux#}}r zWt-Ki{6oxYRm&{aW;>{VZwGY^H7IwK?L@aBJb&WpQv>HQ+O F>fZ{lwf_JB From eef1704fda2e15a6baca6cdc0846e807466bcde2 Mon Sep 17 00:00:00 2001 From: susloparov Date: Tue, 8 Dec 2015 03:13:26 +0600 Subject: [PATCH 05/11] Added DashLineCap, StartLineCap, EndLineCap to the Shape. Fixed properties assignment order in Pen constructor. --- src/Perspex.Controls/Shapes/Shape.cs | 9 ++++++++- src/Perspex.SceneGraph/Media/Pen.cs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Perspex.Controls/Shapes/Shape.cs b/src/Perspex.Controls/Shapes/Shape.cs index 58dc24a738..fcd1fc20fe 100644 --- a/src/Perspex.Controls/Shapes/Shape.cs +++ b/src/Perspex.Controls/Shapes/Shape.cs @@ -90,13 +90,20 @@ namespace Perspex.Controls.Shapes set { SetValue(StrokeThicknessProperty, value); } } + public PenLineCap DashCap { get; set; } = PenLineCap.Flat; + + public PenLineCap StartLineCap { get; set; } = PenLineCap.Flat; + + public PenLineCap EndLineCap { get; set; } = PenLineCap.Flat; + public override void Render(DrawingContext context) { var geometry = RenderedGeometry; if (geometry != null) { - var pen = new Pen(Stroke, StrokeThickness, new DashStyle(StrokeDashArray)); + var pen = new Pen(Stroke, StrokeThickness, new DashStyle(StrokeDashArray), + DashCap, StartLineCap, EndLineCap); context.DrawGeometry(Fill, pen, geometry); } } diff --git a/src/Perspex.SceneGraph/Media/Pen.cs b/src/Perspex.SceneGraph/Media/Pen.cs index cc14ae29d6..489860a87a 100644 --- a/src/Perspex.SceneGraph/Media/Pen.cs +++ b/src/Perspex.SceneGraph/Media/Pen.cs @@ -31,12 +31,12 @@ namespace Perspex.Media { Brush = brush; Thickness = thickness; + DashCap = dashCap; StartLineCap = startLineCap; EndLineCap = endLineCap; LineJoin = lineJoin; MiterLimit = miterLimit; DashStyle = dashStyle; - DashCap = dashCap; } /// From 42bddea9f2c90af3e59fc081523bcafe7f5bd896 Mon Sep 17 00:00:00 2001 From: susloparov Date: Tue, 8 Dec 2015 03:14:02 +0600 Subject: [PATCH 06/11] Direct2D render test for the Path using DashLineCap, StartLineCap, EndLineCap. --- tests/Perspex.RenderTests/Shapes/PathTests.cs | 31 ++++++++++++++++++ .../Path/Path_With_PenLineCap.expected.png | Bin 0 -> 1155 bytes 2 files changed, 31 insertions(+) create mode 100644 tests/TestFiles/Direct2D1/Shapes/Path/Path_With_PenLineCap.expected.png diff --git a/tests/Perspex.RenderTests/Shapes/PathTests.cs b/tests/Perspex.RenderTests/Shapes/PathTests.cs index 6a2c96feb5..bc70aa1088 100644 --- a/tests/Perspex.RenderTests/Shapes/PathTests.cs +++ b/tests/Perspex.RenderTests/Shapes/PathTests.cs @@ -15,6 +15,8 @@ namespace Perspex.Skia.RenderTests namespace Perspex.Direct2D1.RenderTests.Shapes #endif { + using Perspex.Collections; + public class PathTests : TestBase { public PathTests() @@ -126,6 +128,35 @@ namespace Perspex.Direct2D1.RenderTests.Shapes } }; + RenderToFile(target); + CompareImages(); + } + +#if PERSPEX_SKIA + [Fact(Skip = "FIXME")] +#else + [Fact] +#endif + public void Path_With_PenLineCap() + { + Decorator target = new Decorator + { + Width = 200, + Height = 200, + Child = new Path + { + Stroke = Brushes.Black, + StrokeThickness = 10, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + DashCap = PenLineCap.Triangle, + StrokeDashArray = new PerspexList(3, 1), + StartLineCap = PenLineCap.Round, + EndLineCap = PenLineCap.Square, + Data = StreamGeometry.Parse("M 20,20 L 180,180"), + } + }; + RenderToFile(target); CompareImages(); } diff --git a/tests/TestFiles/Direct2D1/Shapes/Path/Path_With_PenLineCap.expected.png b/tests/TestFiles/Direct2D1/Shapes/Path/Path_With_PenLineCap.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..d33068d62c9deb097896fc29422ed4f765f2daf4 GIT binary patch literal 1155 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZkrl|*^>lFzsfc@fcVS*?s6^XCKHq>2FBQJ-H3}`=2Odm_kdbq4YOq#d;WQ6u zeaIKUa*%^XsIi&l+Wq2LCU3L$Z#AF0F(MRJMfd&p*>N!&ha? z=hHWI+IFi6Mg7dn5j#{X%$a+|edo*RUv9b_T5M$-7r*uXu{ina_n)rr;(DF)=Fuln zo8nTXGk#qr>YTY9EKCy}6ofcjm>NA41UOlg8XZ&w5P}EqdDw6?nSFElbXa1`MpL22 z3+JYJusC_Ip2*R%Elf#}W9?E8mP7U59##C^zpB6JzU`fRpNihhKKxd>bhT%4r8rp;nX#c1#@*LIshHz5UoAYAzM@Ef!yYdbzy~$*_#d4`KxR(>wfeM zX!mA?G+|ENvq?L$l@`v82*=qvRM@vPM5M&m=>;`3Jffudm8s7>Gy@t zTlY)jdoM6-^85Ez?%4bE`Ns47+b>+cp1gVT)2vb^$7sz7vph1gRY7E?DTqw>Rxq6i z^q@nQ(!yT<<7t9RI$O+MowWnGdW#~?Sc5pRT6yJuTOQpvolE}x<-`?vw^$$D+;b;H z{^>R2`t&;a)#?Av{jvP^_n}zTs^uro`%PPYm6IiRDaih{Q$gg?s~~c&E+_)EqnUvb zX!dG<^K5XGtuX(s(_}L7LL0V}gcNLVdY^O~W+eKn?C*1wj#d`rc$?D+47M#&oen_X z1H&$=>&Zptk2!I2(X~^e`I~2~OlPdG*fF=Na*vaDe(zbLT=k75sCt8kUw?Q-*FOns zY3uzpTi5N|x9>et^0&{sNXV%+9xCf)*MGQEWAyFnL$MvFr%gW6AF*YNP^U%4+kGBK v7!T_R6&^6Xt}Mvz6C&}5fuVv&UHw1P$(b*Hr Date: Tue, 8 Dec 2015 03:14:11 +0600 Subject: [PATCH 07/11] Fixes #313 --- .../Perspex.Direct2D1/PrimitiveExtensions.cs | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs b/src/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs index fac270dd7c..65d3ce2dad 100644 --- a/src/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs +++ b/src/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs @@ -71,26 +71,23 @@ namespace Perspex.Direct2D1 /// The Direct2D brush. public static StrokeStyle ToDirect2DStrokeStyle(this Perspex.Media.Pen pen, SharpDX.Direct2D1.RenderTarget target) { - if (pen.DashStyle != null) + var properties = new StrokeStyleProperties { - if (pen.DashStyle.Dashes != null && pen.DashStyle.Dashes.Count > 0) - { - var properties = new StrokeStyleProperties - { - DashStyle = DashStyle.Custom, - DashOffset = (float)pen.DashStyle.Offset, - MiterLimit = (float)pen.MiterLimit, - LineJoin = pen.LineJoin.ToDirect2D(), - StartCap = pen.StartLineCap.ToDirect2D(), - EndCap = pen.EndLineCap.ToDirect2D(), - DashCap = pen.DashCap.ToDirect2D() - }; - - return new StrokeStyle(target.Factory, properties, pen.DashStyle?.Dashes.Select(x => (float)x).ToArray()); - } + DashStyle = DashStyle.Solid, + MiterLimit = (float)pen.MiterLimit, + LineJoin = pen.LineJoin.ToDirect2D(), + StartCap = pen.StartLineCap.ToDirect2D(), + EndCap = pen.EndLineCap.ToDirect2D(), + DashCap = pen.DashCap.ToDirect2D() + }; + var dashes = new float[0]; + if (pen.DashStyle?.Dashes != null && pen.DashStyle.Dashes.Count > 0) + { + properties.DashStyle = DashStyle.Custom; + properties.DashOffset = (float)pen.DashStyle.Offset; + dashes = pen.DashStyle?.Dashes.Select(x => (float)x).ToArray(); } - - return null; + return new StrokeStyle(target.Factory, properties, dashes); } /// From 40c01b73fbb001021a5f97671199ac45a55e47e3 Mon Sep 17 00:00:00 2001 From: susloparov Date: Tue, 8 Dec 2015 23:43:13 +0600 Subject: [PATCH 08/11] Renamed stroke Shape properties according to WPF naming --- src/Perspex.Controls/Shapes/Shape.cs | 8 ++++---- tests/Perspex.RenderTests/Shapes/PathTests.cs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Perspex.Controls/Shapes/Shape.cs b/src/Perspex.Controls/Shapes/Shape.cs index fcd1fc20fe..6e7934b0e7 100644 --- a/src/Perspex.Controls/Shapes/Shape.cs +++ b/src/Perspex.Controls/Shapes/Shape.cs @@ -90,11 +90,11 @@ namespace Perspex.Controls.Shapes set { SetValue(StrokeThicknessProperty, value); } } - public PenLineCap DashCap { get; set; } = PenLineCap.Flat; + public PenLineCap StrokeDashCap { get; set; } = PenLineCap.Flat; - public PenLineCap StartLineCap { get; set; } = PenLineCap.Flat; + public PenLineCap StrokeStartLineCap { get; set; } = PenLineCap.Flat; - public PenLineCap EndLineCap { get; set; } = PenLineCap.Flat; + public PenLineCap StrokeEndLineCap { get; set; } = PenLineCap.Flat; public override void Render(DrawingContext context) { @@ -103,7 +103,7 @@ namespace Perspex.Controls.Shapes if (geometry != null) { var pen = new Pen(Stroke, StrokeThickness, new DashStyle(StrokeDashArray), - DashCap, StartLineCap, EndLineCap); + StrokeDashCap, StrokeStartLineCap, StrokeEndLineCap); context.DrawGeometry(Fill, pen, geometry); } } diff --git a/tests/Perspex.RenderTests/Shapes/PathTests.cs b/tests/Perspex.RenderTests/Shapes/PathTests.cs index bc70aa1088..9736f86d1c 100644 --- a/tests/Perspex.RenderTests/Shapes/PathTests.cs +++ b/tests/Perspex.RenderTests/Shapes/PathTests.cs @@ -149,10 +149,10 @@ namespace Perspex.Direct2D1.RenderTests.Shapes StrokeThickness = 10, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, - DashCap = PenLineCap.Triangle, + StrokeDashCap = PenLineCap.Triangle, StrokeDashArray = new PerspexList(3, 1), - StartLineCap = PenLineCap.Round, - EndLineCap = PenLineCap.Square, + StrokeStartLineCap = PenLineCap.Round, + StrokeEndLineCap = PenLineCap.Square, Data = StreamGeometry.Parse("M 20,20 L 180,180"), } }; From ef7dc640c5dc3363f9a146becb310865166dff37 Mon Sep 17 00:00:00 2001 From: susloparov Date: Wed, 9 Dec 2015 00:36:55 +0600 Subject: [PATCH 09/11] Skipped Path_With_PenLineCap render test for Cairo --- tests/Perspex.RenderTests/Shapes/PathTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Perspex.RenderTests/Shapes/PathTests.cs b/tests/Perspex.RenderTests/Shapes/PathTests.cs index 9736f86d1c..68b5956234 100644 --- a/tests/Perspex.RenderTests/Shapes/PathTests.cs +++ b/tests/Perspex.RenderTests/Shapes/PathTests.cs @@ -132,7 +132,9 @@ namespace Perspex.Direct2D1.RenderTests.Shapes CompareImages(); } -#if PERSPEX_SKIA +#if PERSPEX_CAIRO + [Fact(Skip = "Path with StrokeDashCap, StrokeStartLineCap, StrokeEndLineCap rendering is not implemented in Cairo yet")] +#elif PERSPEX_SKIA [Fact(Skip = "FIXME")] #else [Fact] From 626aa9cd19008366e223babe9d63e59664c07923 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 9 Dec 2015 20:09:26 +0100 Subject: [PATCH 10/11] Fix SelectingItemsControl.SelectedItems bug. Make sure unbound SelectedItems cleared when DataContext is cleared. --- src/Perspex.Controls/Control.cs | 5 ++++ .../SelectingItemsControlTests_Multiple.cs | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs index 861192202b..25cabadb0a 100644 --- a/src/Perspex.Controls/Control.cs +++ b/src/Perspex.Controls/Control.cs @@ -419,6 +419,11 @@ namespace Perspex.Controls if (control != null) { control.IsDataContextChanging = notifying; + + if (!notifying) + { + control.OnDataContextFinishedChanging(); + } } } } diff --git a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs index d651216ca3..3d19e353ad 100644 --- a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs +++ b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs @@ -427,6 +427,34 @@ namespace Perspex.Controls.UnitTests.Primitives // Clear DataContext and ensure that SelectedItems is still set in the VM. target.DataContext = null; Assert.Equal(new[] { "bar" }, vm.SelectedItems); + + // Ensure target's SelectedItems is now clear. + Assert.Empty(target.SelectedItems); + } + + [Fact] + public void Unbound_SelectedItems_Should_Be_Cleared_When_DataContext_Cleared() + { + var data = new + { + Items = new[] { "foo", "bar", "baz" }, + }; + + var target = new TestSelector + { + DataContext = data, + Template = Template(), + }; + + var itemsBinding = new Binding { Path = "Items" }; + itemsBinding.Bind(target, TestSelector.ItemsProperty); + + Assert.Same(data.Items, target.Items); + + target.SelectedItems.Add("bar"); + target.DataContext = null; + + Assert.Empty(target.SelectedItems); } private FuncControlTemplate Template() From 195fb6df3b57a0f43b5ca08452590adc538ae19d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 9 Dec 2015 20:15:20 +0100 Subject: [PATCH 11/11] Renamed OnDataContextFinishedChanging To OnDataContextChanged and added DataContextChanged event. --- src/Perspex.Controls/Control.cs | 14 ++++++++++++-- .../Primitives/SelectingItemsControl.cs | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs index 25cabadb0a..ad959d7f8e 100644 --- a/src/Perspex.Controls/Control.cs +++ b/src/Perspex.Controls/Control.cs @@ -93,6 +93,15 @@ namespace Perspex.Controls _nameScope = this as INameScope; } + /// + /// Occurs when the property changes. + /// + /// + /// This event will be raised when the property has changed and + /// all subscribers to that change have been notified. + /// + public event EventHandler DataContextChanged; + /// /// Gets or sets the control's classes. /// @@ -394,8 +403,9 @@ namespace Perspex.Controls /// Called when the is changed and all subscribers to that change /// have been notified. /// - protected virtual void OnDataContextFinishedChanging() + protected virtual void OnDataContextChanged() { + DataContextChanged?.Invoke(this, EventArgs.Empty); } /// @@ -422,7 +432,7 @@ namespace Perspex.Controls if (!notifying) { - control.OnDataContextFinishedChanging(); + control.OnDataContextChanged(); } } } diff --git a/src/Perspex.Controls/Primitives/SelectingItemsControl.cs b/src/Perspex.Controls/Primitives/SelectingItemsControl.cs index 42886a0f41..b60af28fda 100644 --- a/src/Perspex.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Perspex.Controls/Primitives/SelectingItemsControl.cs @@ -287,7 +287,7 @@ namespace Perspex.Controls.Primitives } /// - protected override void OnDataContextFinishedChanging() + protected override void OnDataContextChanged() { if (_clearSelectedItemsAfterDataContextChanged == SelectedItems) {