Browse Source

Merge branch 'master' into prs/dropdownimpr

Steven Kirk 6 years ago
parent
commit
c47648d784

+ 8 - 9
.github/PULL_REQUEST_TEMPLATE.md

@@ -1,18 +1,18 @@
 ## What does the pull request do?
+<!--- Give a bit of background on the PR here, together with links to with related issues etc. -->
 
-Give a bit of background on the PR here, together with links to with related issues etc.
 
 ## What is the current behavior?
+<!--- If the PR is a fix, describe the current incorrect behavior, otherwise delete this section. -->
 
-If the PR is a fix, describe the current incorrect behavior, otherwise delete this section.
 
 ## What is the updated/expected behavior with this PR?
+<!--- Describe how to test the PR. -->
 
-Describe how to test the PR.
 
 ## How was the solution implemented (if it's not obvious)?
+<!--- Include any information that might be of use to a reviewer here. -->
 
-Include any information that might be of use to a reviewer here.
 
 ## Checklist
 
@@ -21,12 +21,11 @@ Include any information that might be of use to a reviewer here.
 - [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation
 
 ## Breaking changes
+<!--- List any breaking changes here. When the PR is merged please add an entry to https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes -->
 
-List any breaking changes here. When the PR is merged please add an entry to https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes
 
 ## Fixed issues
-
-If the pull request fixes issue(s) list them like this:
-
+<!--- If the pull request fixes issue(s) list them like this: 
 Fixes #123
-Fixes #456
+Fixes #456
+-->

+ 8 - 4
src/Avalonia.Base/AvaloniaPropertyRegistry.cs

@@ -13,8 +13,8 @@ namespace Avalonia
     /// </summary>
     public class AvaloniaPropertyRegistry
     {
-        private readonly List<AvaloniaProperty> _properties =
-            new List<AvaloniaProperty>();
+        private readonly Dictionary<int, AvaloniaProperty> _properties =
+            new Dictionary<int, AvaloniaProperty>();
         private readonly Dictionary<Type, Dictionary<int, AvaloniaProperty>> _registered =
             new Dictionary<Type, Dictionary<int, AvaloniaProperty>>();
         private readonly Dictionary<Type, Dictionary<int, AvaloniaProperty>> _attached =
@@ -33,7 +33,7 @@ namespace Avalonia
         /// <summary>
         /// Gets a list of all registered properties.
         /// </summary>
-        internal IReadOnlyList<AvaloniaProperty> Properties => _properties;
+        internal IReadOnlyCollection<AvaloniaProperty> Properties => _properties.Values;
 
         /// <summary>
         /// Gets all non-attached <see cref="AvaloniaProperty"/>s registered on a type.
@@ -220,7 +220,11 @@ namespace Avalonia
                 inner.Add(property.Id, property);
             }
 
-            _properties.Add(property);
+            if (!_properties.ContainsKey(property.Id))
+            {
+                _properties.Add(property.Id, property);
+            }
+            
             _registeredCache.Clear();
         }
 

+ 1 - 1
src/Avalonia.Base/Data/Core/BindingExpression.cs

@@ -177,7 +177,7 @@ namespace Avalonia.Data.Core
 
         protected override void Subscribed(IObserver<object> observer, bool first)
         {
-            if (!first && _value != null && _value.TryGetTarget(out var val) == true)
+            if (!first && _value != null && _value.TryGetTarget(out var val))
             {
                 observer.OnNext(val);
             }

+ 0 - 22
src/Avalonia.Base/ISupportInitialize.cs

@@ -1,22 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-namespace Avalonia
-{
-    /// <summary>
-    /// Specifies that this object supports a simple, transacted notification for batch 
-    /// initialization.
-    /// </summary>
-    public interface ISupportInitialize
-    {
-        /// <summary>
-        /// Signals the object that initialization is starting.
-        /// </summary>
-        void BeginInit();
-
-        /// <summary>
-        /// Signals the object that initialization is complete.
-        /// </summary>
-        void EndInit();
-    }
-}

+ 1 - 1
src/Avalonia.Controls/AutoCompleteBox.cs

@@ -1893,7 +1893,7 @@ namespace Avalonia.Controls
         {
             bool callTextChanged = false;
             // Update the Text dependency property
-            if ((userInitiated == null || userInitiated == true) && Text != value)
+            if ((userInitiated ?? true) && Text != value)
             {
                 _ignoreTextPropertyChange++;
                 Text = value;

+ 1 - 0
src/Avalonia.Controls/Control.cs

@@ -1,6 +1,7 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
+using System.ComponentModel;
 using Avalonia.Controls.Primitives;
 using Avalonia.Controls.Templates;
 using Avalonia.Input;

+ 1 - 0
src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs

@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel;
 using Avalonia.Controls.Platform;
 using Avalonia.Input;
 using Avalonia.Platform;

+ 1 - 0
src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs

@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel;
 using Avalonia.Styling;
 
 namespace Avalonia.Controls.Embedding.Offscreen

+ 17 - 0
src/Avalonia.Controls/Image.cs

@@ -99,5 +99,22 @@ namespace Avalonia.Controls
                 return new Size();
             }
         }
+
+        /// <inheritdoc/>
+        protected override Size ArrangeOverride(Size finalSize)
+        {
+            var source = Source;
+
+            if (source != null)
+            {
+                var sourceSize = new Size(source.PixelSize.Width, source.PixelSize.Height);
+                var result = Stretch.CalculateSize(finalSize, sourceSize);
+                return result;
+            }
+            else
+            {
+                return new Size();
+            }
+        }
     }
 }

+ 1 - 1
src/Avalonia.Controls/MenuItem.cs

@@ -421,7 +421,7 @@ namespace Avalonia.Controls
         }
 
         /// <summary>
-        /// Called when the <see cref="Header"/> property changes.
+        /// Called when the <see cref="HeaderedSelectingItemsControl.Header"/> property changes.
         /// </summary>
         /// <param name="e">The property change event.</param>
         private void HeaderChanged(AvaloniaPropertyChangedEventArgs e)

+ 1 - 1
src/Avalonia.Controls/PixelPointEventArgs.cs

@@ -13,7 +13,7 @@ namespace Avalonia.Controls
         /// <summary>
         /// Initializes a new instance of the <see cref="PixelPointEventArgs"/> class.
         /// </summary>
-        /// <param name="point">The <see cref=PixelPoint"/> data.</param>
+        /// <param name="point">The <see cref="PixelPoint"/> data.</param>
         public PixelPointEventArgs(PixelPoint point)
         {
             Point = point;

+ 1 - 1
src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs

@@ -285,7 +285,7 @@ namespace Avalonia.Controls.Presenters
             {
                 scrollable.InvalidateScroll = () => UpdateFromScrollable(scrollable);
 
-                if (scrollable.IsLogicalScrollEnabled == true)
+                if (scrollable.IsLogicalScrollEnabled)
                 {
                     _logicalScrollSubscription = new CompositeDisposable(
                         this.GetObservable(CanHorizontallyScrollProperty)

+ 11 - 2
src/Avalonia.Controls/Shapes/Shape.cs

@@ -20,7 +20,10 @@ namespace Avalonia.Controls.Shapes
             AvaloniaProperty.Register<Shape, IBrush>(nameof(Stroke));
 
         public static readonly StyledProperty<AvaloniaList<double>> StrokeDashArrayProperty =
-            AvaloniaProperty.Register<Shape, AvaloniaList<double>>("StrokeDashArray");
+            AvaloniaProperty.Register<Shape, AvaloniaList<double>>(nameof(StrokeDashArray));
+            
+        public static readonly StyledProperty<double> StrokeDashOffsetProperty =
+            AvaloniaProperty.Register<Shape, double>(nameof(StrokeDashOffset));
 
         public static readonly StyledProperty<double> StrokeThicknessProperty =
             AvaloniaProperty.Register<Shape, double>(nameof(StrokeThickness));
@@ -103,6 +106,12 @@ namespace Avalonia.Controls.Shapes
             get { return GetValue(StrokeDashArrayProperty); }
             set { SetValue(StrokeDashArrayProperty, value); }
         }
+        
+        public double StrokeDashOffset
+        {
+            get { return GetValue(StrokeDashOffsetProperty); }
+            set { SetValue(StrokeDashOffsetProperty, value); }
+        }
 
         public double StrokeThickness
         {
@@ -124,7 +133,7 @@ namespace Avalonia.Controls.Shapes
 
             if (geometry != null)
             {
-                var pen = new Pen(Stroke, StrokeThickness, new DashStyle(StrokeDashArray), 
+                var pen = new Pen(Stroke, StrokeThickness, new DashStyle(StrokeDashArray, StrokeDashOffset), 
                     StrokeDashCap, StrokeStartLineCap, StrokeEndLineCap, StrokeJoin);
                 context.DrawGeometry(Fill, pen, geometry);
             }

+ 1 - 0
src/Avalonia.Controls/WindowBase.cs

@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel;
 using System.Linq;
 using System.Reactive.Disposables;
 using System.Reactive.Linq;

+ 11 - 7
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@@ -255,15 +255,19 @@ namespace Avalonia.Rendering
                         }
 
                         var (scene, updated) = UpdateRenderLayersAndConsumeSceneIfNeeded(GetContext);
+
                         using (scene)
                         {
-                            var overlay = DrawDirtyRects || DrawFps;
-                            if (DrawDirtyRects)
-                                _dirtyRectsDisplay.Tick();
-                            if (overlay)
-                                RenderOverlay(scene.Item, GetContext());
-                            if (updated || forceComposite || overlay)
-                                RenderComposite(scene.Item, GetContext());
+                            if (scene?.Item != null)
+                            {
+                                var overlay = DrawDirtyRects || DrawFps;
+                                if (DrawDirtyRects)
+                                    _dirtyRectsDisplay.Tick();
+                                if (overlay)
+                                    RenderOverlay(scene.Item, GetContext());
+                                if (updated || forceComposite || overlay)
+                                    RenderComposite(scene.Item, GetContext());
+                             }
                         }
                     }
                     finally

+ 1 - 1
src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

@@ -236,7 +236,7 @@ namespace Avalonia.Rendering.SceneGraph
         {
             foreach (var operation in DrawOperations)
             {
-                if (operation.Item.HitTest(p) == true)
+                if (operation.Item.HitTest(p))
                 {
                     return true;
                 }

+ 2 - 1
src/Avalonia.X11/X11Screens.cs

@@ -218,6 +218,7 @@ namespace Avalonia.X11
 
     class X11Screen
     {
+        private const int FullHDWidth = 1920;
         public bool Primary { get; }
         public string Name { get; set; }
         public PixelRect Bounds { get; set; }
@@ -247,6 +248,6 @@ namespace Avalonia.X11
         }
 
         public static double GuessPixelDensity(double pixelWidth, double mmWidth)
-            => Math.Max(1, Math.Round(pixelWidth / mmWidth * 25.4 / 96));
+            => pixelWidth <= FullHDWidth ? 1 : Math.Max(1, Math.Round(pixelWidth / mmWidth * 25.4 / 96));
     }
 }

+ 2 - 1
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs

@@ -8,6 +8,7 @@ using Avalonia.Platform;
 using Portable.Xaml;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.IO;
 using System.Reflection;
 using System.Runtime.Serialization;
@@ -250,7 +251,7 @@ namespace Avalonia.Markup.Xaml
                          .ToDictionary(entry =>entry.Element(arrayNs + "Key").Value,
                                 entry => entry.Element(arrayNs + "Value").Value);
                     
-                    if (xamlInfo.TryGetValue(typeName, out var rv) == true)
+                    if (xamlInfo.TryGetValue(typeName, out var rv))
                     {
                         yield return new Uri($"avares://{asm}{rv}");
                         yield break;

+ 0 - 35
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs

@@ -77,40 +77,15 @@ namespace Avalonia.Markup.Xaml.PortableXaml
             _delayedValuesHelper.ApplyAll();
         }
 
-        protected internal override void OnAfterBeginInit(object value)
-        {
-            //not called for avalonia objects
-            //as it's called inly for
-            //Portable.Xaml.ComponentModel.ISupportInitialize
-            base.OnAfterBeginInit(value);
-        }
-
-        protected internal override void OnAfterEndInit(object value)
-        {
-            //not called for avalonia objects
-            //as it's called inly for
-            //Portable.Xaml.ComponentModel.ISupportInitialize
-            base.OnAfterEndInit(value);
-        }
-
         protected internal override void OnAfterProperties(object value)
         {
             _delayedValuesHelper.EndInit(value);
 
             base.OnAfterProperties(value);
-
-            //AfterEndInit is not called as it supports only
-            //Portable.Xaml.ComponentModel.ISupportInitialize
-            //and we have Avalonia.ISupportInitialize so we need some hacks
-            HandleEndEdit(value);
         }
 
         protected internal override void OnBeforeProperties(object value)
         {
-            //OnAfterBeginInit is not called as it supports only
-            //Portable.Xaml.ComponentModel.ISupportInitialize
-            //and we have Avalonia.ISupportInitialize so we need some hacks
-            HandleBeginInit(value);
             if (value != null)
                 _delayedValuesHelper.BeginInit(value);
 
@@ -127,16 +102,6 @@ namespace Avalonia.Markup.Xaml.PortableXaml
             return base.OnSetValue(target, member, value);
         }
 
-        private void HandleBeginInit(object value)
-        {
-            (value as Avalonia.ISupportInitialize)?.BeginInit();
-        }
-
-        private void HandleEndEdit(object value)
-        {
-            (value as Avalonia.ISupportInitialize)?.EndInit();
-        }
-
         public override void WriteStartMember(XamlMember property)
         {
             foreach(var d in DesignDirectives)

+ 5 - 0
tests/Avalonia.Base.UnitTests/AvaloniaPropertyRegistryTests.cs

@@ -27,6 +27,7 @@ namespace Avalonia.Base.UnitTests
             var property = new AttachedProperty<int>("test", typeof(object), metadata, true);
             registry.Register(typeof(object), property);
             registry.RegisterAttached(typeof(AvaloniaPropertyRegistryTests), property);
+            property.AddOwner<Class4>();
 
             Assert.Equal(1, registry.Properties.Count);
         }
@@ -150,5 +151,9 @@ namespace Avalonia.Base.UnitTests
         private class AttachedOwner2 : AttachedOwner
         {
         }
+
+        private class Class4 : AvaloniaObject
+        {
+        }
     }
 }

+ 56 - 0
tests/Avalonia.Controls.UnitTests/ImageTests.cs

@@ -61,5 +61,61 @@ namespace Avalonia.Controls.UnitTests
 
             Assert.Equal(new Size(50, 50), target.DesiredSize);
         }
+
+        [Fact]
+        public void Arrange_Should_Return_Correct_Size_For_No_Stretch()
+        {
+            var bitmap = Mock.Of<IBitmap>(x => x.PixelSize == new PixelSize(50, 100));
+            var target = new Image();
+            target.Stretch = Stretch.None;
+            target.Source = bitmap;
+
+            target.Measure(new Size(50, 50));
+            target.Arrange(new Rect(0, 0, 100, 400));
+
+            Assert.Equal(new Size(50, 100), target.Bounds.Size);
+        }
+
+        [Fact]
+        public void Arrange_Should_Return_Correct_Size_For_Fill_Stretch()
+        {
+            var bitmap = Mock.Of<IBitmap>(x => x.PixelSize == new PixelSize(50, 100));
+            var target = new Image();
+            target.Stretch = Stretch.Fill;
+            target.Source = bitmap;
+
+            target.Measure(new Size(50, 50));
+            target.Arrange(new Rect(0, 0, 25, 100));
+
+            Assert.Equal(new Size(25, 100), target.Bounds.Size);
+        }
+
+        [Fact]
+        public void Arrange_Should_Return_Correct_Size_For_Uniform_Stretch()
+        {
+            var bitmap = Mock.Of<IBitmap>(x => x.PixelSize == new PixelSize(50, 100));
+            var target = new Image();
+            target.Stretch = Stretch.Uniform;
+            target.Source = bitmap;
+
+            target.Measure(new Size(50, 50));
+            target.Arrange(new Rect(0, 0, 25, 100));
+
+            Assert.Equal(new Size(25, 50), target.Bounds.Size);
+        }
+
+        [Fact]
+        public void Arrange_Should_Return_Correct_Size_For_UniformToFill_Stretch()
+        {
+            var bitmap = Mock.Of<IBitmap>(x => x.PixelSize == new PixelSize(50, 100));
+            var target = new Image();
+            target.Stretch = Stretch.UniformToFill;
+            target.Source = bitmap;
+
+            target.Measure(new Size(50, 50));
+            target.Arrange(new Rect(0, 0, 25, 100));
+
+            Assert.Equal(new Size(25, 100), target.Bounds.Size);
+        }
     }
 }

+ 1 - 0
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

@@ -4,6 +4,7 @@
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Collections.Specialized;
+using System.ComponentModel;
 using System.Linq;
 using Avalonia.Collections;
 using Avalonia.Controls.Presenters;

+ 2 - 1
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/InitializationOrderTracker.cs

@@ -4,6 +4,7 @@
 using Avalonia.Controls;
 using Avalonia.LogicalTree;
 using System.Collections.Generic;
+using System.ComponentModel;
 
 namespace Avalonia.Markup.Xaml.UnitTests.Xaml
 {
@@ -39,4 +40,4 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
             Order.Add($"EndInit {InitState}");
         }
     }
-}
+}

+ 1 - 0
tests/Avalonia.Styling.UnitTests/StyledElementTests.cs

@@ -10,6 +10,7 @@ using Avalonia.UnitTests;
 using Xunit;
 using Avalonia.LogicalTree;
 using Avalonia.Controls;
+using System.ComponentModel;
 
 namespace Avalonia.Styling.UnitTests
 {