diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 552713f94b..537495fcad 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -2,6 +2,7 @@
<_AvaloniaUseExternalMSBuild>$(AvaloniaUseExternalMSBuild)
<_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false
+ low
+ EmbeddedResources="@(EmbeddedResources)"
+ ReportImportance="$(AvaloniaXamlReportImportance)"/>
@@ -67,6 +69,7 @@
OriginalCopyPath="$(AvaloniaXamlOriginalCopyFilePath)"
ProjectDirectory="$(MSBuildProjectDirectory)"
VerifyIl="$(AvaloniaXamlIlVerifyIl)"
+ ReportImportance="$(AvaloniaXamlReportImportance)"
/>
(AngleProperty);
+ }
+
+ public LineBoundsDemoControl()
+ {
+ var timer = new DispatcherTimer();
+ timer.Interval = TimeSpan.FromSeconds(1 / 60);
+ timer.Tick += (sender, e) => Angle += Math.PI / 360;
+ timer.Start();
+ }
+
+ public static readonly StyledProperty AngleProperty =
+ AvaloniaProperty.Register(nameof(Angle));
+
+ public double Angle
+ {
+ get => GetValue(AngleProperty);
+ set => SetValue(AngleProperty, value);
+ }
+
+ public override void Render(DrawingContext drawingContext)
+ {
+ var lineLength = Math.Sqrt((100 * 100) + (100 * 100));
+
+ var diffX = LineBoundsHelper.CalculateAdjSide(Angle, lineLength);
+ var diffY = LineBoundsHelper.CalculateOppSide(Angle, lineLength);
+
+
+ var p1 = new Point(200, 200);
+ var p2 = new Point(p1.X + diffX, p1.Y + diffY);
+
+ var pen = new Pen(Brushes.Green, 20, lineCap: PenLineCap.Square);
+ var boundPen = new Pen(Brushes.Black);
+
+ drawingContext.DrawLine(pen, p1, p2);
+
+ drawingContext.DrawRectangle(boundPen, LineBoundsHelper.CalculateBounds(p1, p2, pen));
+ }
+ }
+}
diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml
index b17520a466..c098ef411e 100644
--- a/samples/RenderDemo/MainWindow.xaml
+++ b/samples/RenderDemo/MainWindow.xaml
@@ -44,6 +44,9 @@
+
+
+
diff --git a/samples/RenderDemo/Pages/LineBoundsPage.xaml b/samples/RenderDemo/Pages/LineBoundsPage.xaml
new file mode 100644
index 0000000000..07d658630a
--- /dev/null
+++ b/samples/RenderDemo/Pages/LineBoundsPage.xaml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/samples/RenderDemo/Pages/LineBoundsPage.xaml.cs b/samples/RenderDemo/Pages/LineBoundsPage.xaml.cs
new file mode 100644
index 0000000000..28ddedd4bc
--- /dev/null
+++ b/samples/RenderDemo/Pages/LineBoundsPage.xaml.cs
@@ -0,0 +1,19 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace RenderDemo.Pages
+{
+ public class LineBoundsPage : UserControl
+ {
+ public LineBoundsPage()
+ {
+ this.InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/samples/RenderDemo/RenderDemo.csproj b/samples/RenderDemo/RenderDemo.csproj
index ce33f42143..0d7d62e177 100644
--- a/samples/RenderDemo/RenderDemo.csproj
+++ b/samples/RenderDemo/RenderDemo.csproj
@@ -3,6 +3,9 @@
Exe
netcoreapp3.1
+
+
+
diff --git a/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs b/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
index 39ee3f6bca..95e59dde2b 100644
--- a/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
+++ b/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
@@ -12,6 +12,8 @@ namespace Avalonia.Build.Tasks
{
public bool Execute()
{
+ Enum.TryParse(ReportImportance, true, out MessageImportance outputImportance);
+
OutputPath = OutputPath ?? AssemblyFile;
var outputPdb = GetPdbPath(OutputPath);
var input = AssemblyFile;
@@ -32,9 +34,12 @@ namespace Avalonia.Build.Tasks
}
}
+ var msg = $"CompileAvaloniaXamlTask -> AssemblyFile:{AssemblyFile}, ProjectDirectory:{ProjectDirectory}, OutputPath:{OutputPath}";
+ BuildEngine.LogMessage(msg, outputImportance < MessageImportance.Low ? MessageImportance.High : outputImportance);
+
var res = XamlCompilerTaskExecutor.Compile(BuildEngine, input,
File.ReadAllLines(ReferencesFilePath).Where(l => !string.IsNullOrWhiteSpace(l)).ToArray(),
- ProjectDirectory, OutputPath, VerifyIl);
+ ProjectDirectory, OutputPath, VerifyIl, outputImportance);
if (!res.Success)
return false;
if (!res.WrittenFile)
@@ -68,7 +73,9 @@ namespace Avalonia.Build.Tasks
public string OutputPath { get; set; }
public bool VerifyIl { get; set; }
-
+
+ public string ReportImportance { get; set; }
+
public IBuildEngine BuildEngine { get; set; }
public ITaskHost HostObject { get; set; }
}
diff --git a/src/Avalonia.Build.Tasks/Extensions.cs b/src/Avalonia.Build.Tasks/Extensions.cs
index 440c6d7489..46c12eaf3d 100644
--- a/src/Avalonia.Build.Tasks/Extensions.cs
+++ b/src/Avalonia.Build.Tasks/Extensions.cs
@@ -9,14 +9,19 @@ namespace Avalonia.Build.Tasks
public static void LogError(this IBuildEngine engine, BuildEngineErrorCode code, string file, string message)
{
- engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", FormatErrorCode(code), file ?? "", 0, 0, 0, 0, message,
+ engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", FormatErrorCode(code), file ?? "", 0, 0, 0, 0, message,
"", "Avalonia"));
}
-
+
public static void LogWarning(this IBuildEngine engine, BuildEngineErrorCode code, string file, string message)
{
engine.LogWarningEvent(new BuildWarningEventArgs("Avalonia", FormatErrorCode(code), file ?? "", 0, 0, 0, 0, message,
"", "Avalonia"));
}
+
+ public static void LogMessage(this IBuildEngine engine, string message, MessageImportance imp)
+ {
+ engine.LogMessageEvent(new BuildMessageEventArgs(message, "", "Avalonia", imp));
+ }
}
}
diff --git a/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs b/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs
index 98ebb3e7d1..406abe6f99 100644
--- a/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs
+++ b/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs
@@ -22,6 +22,10 @@ namespace Avalonia.Build.Tasks
[Required]
public ITaskItem[] EmbeddedResources { get; set; }
+ public string ReportImportance { get; set; }
+
+ private MessageImportance _reportImportance;
+
class Source
{
public string Path { get; set; }
@@ -29,15 +33,11 @@ namespace Avalonia.Build.Tasks
private byte[] _data;
private string _sourcePath;
- public Source(string file, string root)
+ public Source(string relativePath, string root)
{
- file = SPath.GetFullPath(file);
root = SPath.GetFullPath(root);
- var fileUri = new Uri(file, UriKind.Absolute);
- var rootUri = new Uri(root, UriKind.Absolute);
- rootUri = new Uri(rootUri.ToString().TrimEnd('/') + '/');
- Path = '/' + rootUri.MakeRelativeUri(fileUri).ToString().TrimStart('/');
- _sourcePath = file;
+ Path = "/" + relativePath.Replace('\\', '/');
+ _sourcePath = SPath.Combine(root, relativePath);
Size = (int)new FileInfo(_sourcePath).Length;
}
@@ -65,7 +65,14 @@ namespace Avalonia.Build.Tasks
}
}
- List BuildResourceSources() => Resources.Select(r => new Source(r.ItemSpec, Root)).ToList();
+ List BuildResourceSources()
+ => Resources.Select(r =>
+ {
+
+ var src = new Source(r.ItemSpec, Root);
+ BuildEngine.LogMessage($"avares -> name:{src.Path}, path: {src.SystemPath}, size:{src.Size}, ItemSpec:{r.ItemSpec}", _reportImportance);
+ return src;
+ }).ToList();
private void Pack(Stream output, List sources)
{
@@ -136,10 +143,14 @@ namespace Avalonia.Build.Tasks
sources.Add(new Source("/!AvaloniaResourceXamlInfo", ms.ToArray()));
return true;
}
-
+
public bool Execute()
{
- foreach(var r in EmbeddedResources.Where(r=>r.ItemSpec.EndsWith(".xaml")||r.ItemSpec.EndsWith(".paml")))
+ Enum.TryParse(ReportImportance, out _reportImportance);
+
+ BuildEngine.LogMessage($"GenerateAvaloniaResourcesTask -> Root: {Root}, {Resources?.Count()} resources, Output:{Output}", _reportImportance < MessageImportance.Low ? MessageImportance.High : _reportImportance);
+
+ foreach (var r in EmbeddedResources.Where(r => r.ItemSpec.EndsWith(".xaml") || r.ItemSpec.EndsWith(".paml")))
BuildEngine.LogWarning(BuildEngineErrorCode.LegacyResmScheme, r.ItemSpec,
"XAML file is packed using legacy EmbeddedResource/resm scheme, relative URIs won't work");
var resources = BuildResourceSources();
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index e348eb0fbc..3b69109e68 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -40,7 +40,7 @@ namespace Avalonia.Build.Tasks
}
public static CompileResult Compile(IBuildEngine engine, string input, string[] references, string projectDirectory,
- string output, bool verifyIl)
+ string output, bool verifyIl, MessageImportance logImportance)
{
var typeSystem = new CecilTypeSystem(references.Concat(new[] {input}), input);
var asm = typeSystem.TargetAssemblyDefinition;
@@ -121,6 +121,8 @@ namespace Avalonia.Build.Tasks
{
try
{
+ engine.LogMessage($"XAMLIL: {res.Name} -> {res.Uri}", logImportance);
+
// StreamReader is needed here to handle BOM
var xaml = new StreamReader(new MemoryStream(res.FileContents)).ReadToEnd();
var parsed = XDocumentXamlIlParser.Parse(xaml);
diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs
index 3e4f47ec8a..b38cc56a17 100644
--- a/src/Avalonia.Controls/AutoCompleteBox.cs
+++ b/src/Avalonia.Controls/AutoCompleteBox.cs
@@ -10,6 +10,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
+using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Collections;
@@ -1100,6 +1101,7 @@ namespace Avalonia.Controls
{
_textBoxSubscriptions =
_textBox.GetObservable(TextBox.TextProperty)
+ .Skip(1)
.Subscribe(_ => OnTextBoxTextChanged());
if (Text != null)
diff --git a/src/Avalonia.Controls/SelectionModel.cs b/src/Avalonia.Controls/SelectionModel.cs
index dd4934f9e5..93699583e6 100644
--- a/src/Avalonia.Controls/SelectionModel.cs
+++ b/src/Avalonia.Controls/SelectionModel.cs
@@ -20,6 +20,7 @@ namespace Avalonia.Controls
private bool _singleSelect;
private bool _autoSelect;
private int _operationCount;
+ private IndexPath _oldAnchorIndex;
private IReadOnlyList? _selectedIndicesCached;
private IReadOnlyList