From 394a5be4026afcf41202d876fb29dcf4beb8ab7c Mon Sep 17 00:00:00 2001 From: Lubomir Tetak Date: Fri, 17 Dec 2021 14:52:22 +0100 Subject: [PATCH 01/12] OSX handle CMD+key up combinations in Avalonia --- native/Avalonia.Native/src/OSX/app.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/native/Avalonia.Native/src/OSX/app.mm b/native/Avalonia.Native/src/OSX/app.mm index 79175d9ff1..05b129baca 100644 --- a/native/Avalonia.Native/src/OSX/app.mm +++ b/native/Avalonia.Native/src/OSX/app.mm @@ -73,6 +73,11 @@ ComPtr _events; _isHandlingSendEvent = true; @try { [super sendEvent: event]; + if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand)) + { + [[self keyWindow] sendEvent:event]; + } + } @finally { _isHandlingSendEvent = oldHandling; } From d083acc20d9fdda5cb022d1038b5ad4d97e5e656 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Fri, 31 Dec 2021 02:26:09 -0500 Subject: [PATCH 02/12] Implement support of NthChild in DataGrid --- .../ControlCatalog/Pages/DataGridPage.xaml | 19 ++++++++- src/Avalonia.Controls.DataGrid/DataGrid.cs | 10 ----- .../DataGridColumn.cs | 2 +- .../DataGridColumnCollection.cs | 36 +++++++++-------- .../DataGridColumns.cs | 9 ++--- .../DataGridDataConnection.cs | 36 +++++++++-------- src/Avalonia.Controls.DataGrid/DataGridRow.cs | 39 +------------------ .../DataGridRows.cs | 29 ++++++++++++-- .../Primitives/DataGridCellsPresenter.cs | 39 +++++++++++++++++-- .../DataGridColumnHeadersPresenter.cs | 36 ++++++++++++++++- .../Primitives/DataGridRowsPresenter.cs | 20 +++++++++- .../Themes/Default.xaml | 12 +++++- .../Themes/Fluent.xaml | 8 ++++ src/Avalonia.Controls/ItemsControl.cs | 2 +- src/Avalonia.Controls/Panel.cs | 2 +- .../Presenters/ItemsPresenterBase.cs | 2 +- .../LogicalTree/ChildIndexChangedEventArgs.cs | 2 + 17 files changed, 199 insertions(+), 104 deletions(-) diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml b/samples/ControlCatalog/Pages/DataGridPage.xaml index f7e3cf2441..31b4039d33 100644 --- a/samples/ControlCatalog/Pages/DataGridPage.xaml +++ b/samples/ControlCatalog/Pages/DataGridPage.xaml @@ -13,9 +13,22 @@ + + + + @@ -31,7 +44,9 @@ - + diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs index 9dfb34517b..9b67c9b096 100644 --- a/src/Avalonia.Controls.DataGrid/DataGrid.cs +++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs @@ -669,8 +669,6 @@ namespace Avalonia.Controls ItemsProperty.Changed.AddClassHandler((x, e) => x.OnItemsPropertyChanged(e)); CanUserResizeColumnsProperty.Changed.AddClassHandler((x, e) => x.OnCanUserResizeColumnsChanged(e)); ColumnWidthProperty.Changed.AddClassHandler((x, e) => x.OnColumnWidthChanged(e)); - RowBackgroundProperty.Changed.AddClassHandler((x, e) => x.OnRowBackgroundChanged(e)); - AlternatingRowBackgroundProperty.Changed.AddClassHandler((x, e) => x.OnRowBackgroundChanged(e)); FrozenColumnCountProperty.Changed.AddClassHandler((x, e) => x.OnFrozenColumnCountChanged(e)); GridLinesVisibilityProperty.Changed.AddClassHandler((x, e) => x.OnGridLinesVisibilityChanged(e)); HeadersVisibilityProperty.Changed.AddClassHandler((x, e) => x.OnHeadersVisibilityChanged(e)); @@ -1144,14 +1142,6 @@ namespace Avalonia.Controls InvalidateCellsArrange(); } - private void OnRowBackgroundChanged(AvaloniaPropertyChangedEventArgs e) - { - foreach (DataGridRow row in GetAllRows()) - { - row.EnsureBackground(); - } - } - private void OnColumnWidthChanged(AvaloniaPropertyChangedEventArgs e) { var value = (DataGridLength)e.NewValue; diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs index a77b482436..4a7137dcda 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs @@ -199,7 +199,7 @@ namespace Avalonia.Controls if (change.Property == IsVisibleProperty) { OwningGrid?.OnColumnVisibleStateChanging(this); - var isVisible = (change as AvaloniaPropertyChangedEventArgs).NewValue.Value; + var isVisible = change.NewValue.GetValueOrDefault(); if (_headerCell != null) { diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumnCollection.cs b/src/Avalonia.Controls.DataGrid/DataGridColumnCollection.cs index 922b1d9c08..e7f9a9a6c4 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumnCollection.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumnCollection.cs @@ -12,7 +12,8 @@ namespace Avalonia.Controls { internal class DataGridColumnCollection : ObservableCollection { - private DataGrid _owningGrid; + private readonly Dictionary _columnsMap = new Dictionary(); + private readonly DataGrid _owningGrid; public DataGridColumnCollection(DataGrid owningGrid) { @@ -124,18 +125,8 @@ namespace Avalonia.Controls internal int VisibleColumnCount { - get - { - int visibleColumnCount = 0; - for (int columnIndex = 0; columnIndex < ItemsInternal.Count; columnIndex++) - { - if (ItemsInternal[columnIndex].IsVisible) - { - visibleColumnCount++; - } - } - return visibleColumnCount; - } + get; + private set; } internal double VisibleEdgedColumnsWidth @@ -287,20 +278,31 @@ namespace Avalonia.Controls { VisibleStarColumnCount = 0; VisibleEdgedColumnsWidth = 0; + VisibleColumnCount = 0; + _columnsMap.Clear(); + for (int columnIndex = 0; columnIndex < ItemsInternal.Count; columnIndex++) { - if (ItemsInternal[columnIndex].IsVisible) + var item = ItemsInternal[columnIndex]; + _columnsMap[columnIndex] = item.DisplayIndex; + if (item.IsVisible) { - ItemsInternal[columnIndex].EnsureWidth(); - if (ItemsInternal[columnIndex].Width.IsStar) + VisibleColumnCount++; + item.EnsureWidth(); + if (item.Width.IsStar) { VisibleStarColumnCount++; } - VisibleEdgedColumnsWidth += ItemsInternal[columnIndex].ActualWidth; + VisibleEdgedColumnsWidth += item.ActualWidth; } } } + internal int GetColumnDisplayIndex(int columnIndex) + { + return _columnsMap.TryGetValue(columnIndex, out var displayIndex) ? displayIndex : -1; + } + internal DataGridColumn GetColumnAtDisplayIndex(int displayIndex) { if (displayIndex < 0 || displayIndex >= ItemsInternal.Count || displayIndex >= DisplayIndexMap.Count) diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumns.cs b/src/Avalonia.Controls.DataGrid/DataGridColumns.cs index a4577ee952..ea8a121d29 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumns.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumns.cs @@ -444,12 +444,11 @@ namespace Avalonia.Controls // We need to explicitly collapse the cells of the invisible column because layout only goes through // visible ones - if (!updatedColumn.IsVisible) + ColumnHeaders.InvalidateChildIndex(); + foreach (var row in GetAllRows()) { - foreach (DataGridRow row in GetAllRows()) - { - row.Cells[updatedColumn.Index].IsVisible = false; - } + row.Cells[updatedColumn.Index].IsVisible = updatedColumn.IsVisible; + row.InvalidateCellsIndex(); } } diff --git a/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs b/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs index fade597ca1..a3095ad214 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs @@ -77,7 +77,7 @@ namespace Avalonia.Controls private set; } - public int Count => GetCount(true); + public int Count => TryGetCount(true, false, out var count) ? count : 0; public bool DataIsPrimitive { @@ -193,22 +193,25 @@ namespace Avalonia.Controls } } - internal bool Any() - { - return GetCount(false) > 0; - } - /// When "allowSlow" is false, method will not use Linq.Count() method and will return 0 or 1 instead. - private int GetCount(bool allowSlow) + /// If "getAny" is true, method can use Linq.Any() method to speedup. + internal bool TryGetCount(bool allowSlow, bool getAny, out int count) { - return DataSource switch + bool result; + (result, count) = DataSource switch { - ICollection collection => collection.Count, - DataGridCollectionView cv => cv.Count, - IEnumerable enumerable when allowSlow => enumerable.Cast().Count(), - IEnumerable enumerable when !allowSlow => enumerable.Cast().Any() ? 1 : 0, - _ => 0 + ICollection collection => (true, collection.Count), + DataGridCollectionView cv => (true, cv.Count), + IEnumerable enumerable when allowSlow && !getAny => (true, enumerable.Cast().Count()), + IEnumerable enumerable when getAny => (true, enumerable.Cast().Any() ? 1 : 0), + _ => (false, 0) }; + return result; + } + + internal bool Any() + { + return TryGetCount(false, true, out var count) && count > 0; } /// @@ -383,7 +386,7 @@ namespace Avalonia.Controls List propertyNames = TypeHelper.SplitPropertyPath(propertyName); for (int i = 0; i < propertyNames.Count; i++) { - propertyInfo = propertyType.GetPropertyOrIndexer(propertyNames[i], out object[] index); + propertyInfo = propertyType.GetPropertyOrIndexer(propertyNames[i], out _); if (propertyInfo == null || propertyType.GetIsReadOnly() || propertyInfo.GetIsReadOnly()) { // Either the data type is read-only, the property doesn't exist, or it does exist but is read-only @@ -391,11 +394,10 @@ namespace Avalonia.Controls } // Check if EditableAttribute is defined on the property and if it indicates uneditable - object[] attributes = propertyInfo.GetCustomAttributes(typeof(EditableAttribute), true); + var attributes = propertyInfo.GetCustomAttributes(typeof(EditableAttribute), true); if (attributes != null && attributes.Length > 0) { - EditableAttribute editableAttribute = attributes[0] as EditableAttribute; - Debug.Assert(editableAttribute != null); + var editableAttribute = (EditableAttribute)attributes[0]; if (!editableAttribute.AllowEdit) { return true; diff --git a/src/Avalonia.Controls.DataGrid/DataGridRow.cs b/src/Avalonia.Controls.DataGrid/DataGridRow.cs index 1efce7c0b8..a6faec752d 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridRow.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridRow.cs @@ -543,7 +543,6 @@ namespace Avalonia.Controls RootElement = e.NameScope.Find(DATAGRIDROW_elementRoot); if (RootElement != null) { - EnsureBackground(); UpdatePseudoClasses(); } @@ -668,43 +667,9 @@ namespace Avalonia.Controls Slot = -1; } - // Make sure the row's background is set to its correct value. It could be explicity set or inherit - // DataGrid.RowBackground or DataGrid.AlternatingRowBackground - internal void EnsureBackground() + internal void InvalidateCellsIndex() { - // Inherit the DataGrid's RowBackground properties only if this row doesn't explicity have a background set - if (RootElement != null && OwningGrid != null) - { - IBrush newBackground = null; - if (Background == null) - { - if (Index % 2 == 0 || OwningGrid.AlternatingRowBackground == null) - { - // Use OwningGrid.RowBackground if the index is even or if the OwningGrid.AlternatingRowBackground is null - if (OwningGrid.RowBackground != null) - { - newBackground = OwningGrid.RowBackground; - } - } - else - { - // Alternate row - if (OwningGrid.AlternatingRowBackground != null) - { - newBackground = OwningGrid.AlternatingRowBackground; - } - } - } - else - { - newBackground = Background; - } - - if (RootElement.Background != newBackground) - { - RootElement.Background = newBackground; - } - } + _cellsElement?.InvalidateChildIndex(); } internal void EnsureFillerVisibility() diff --git a/src/Avalonia.Controls.DataGrid/DataGridRows.cs b/src/Avalonia.Controls.DataGrid/DataGridRows.cs index 1d5c899993..52b67b8921 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridRows.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridRows.cs @@ -5,6 +5,7 @@ using Avalonia.Collections; using Avalonia.Controls.Utils; +using Avalonia.LogicalTree; using Avalonia.Media; using Avalonia.Utilities; using System; @@ -16,7 +17,7 @@ using System.Linq; namespace Avalonia.Controls { - public partial class DataGrid + public partial class DataGrid : IChildIndexProvider { internal bool AreRowBottomGridLinesRequired @@ -123,6 +124,26 @@ namespace Avalonia.Controls } } + internal EventHandler _childIndexChanged; + + event EventHandler IChildIndexProvider.ChildIndexChanged + { + add => _childIndexChanged += value; + remove => _childIndexChanged -= value; + } + + int IChildIndexProvider.GetChildIndex(ILogical child) + { + return child is DataGridRow row + ? row.Index + : throw new InvalidOperationException("Invalid DataGrid child"); + } + + bool IChildIndexProvider.TryGetTotalCount(out int count) + { + return DataConnection.TryGetCount(false, true, out count); + } + /// /// Clears the entire selection. Displayed rows are deselected explicitly to visualize /// potential transition effects @@ -811,7 +832,7 @@ namespace Avalonia.Controls if (row.Slot > slotDeleted) { CorrectRowAfterDeletion(row, wasRow); - row.EnsureBackground(); + _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(row)); } } @@ -867,7 +888,7 @@ namespace Avalonia.Controls if (row.Slot >= slotInserted) { DataGrid.CorrectRowAfterInsertion(row, rowInserted); - row.EnsureBackground(); + _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(row)); } } @@ -1485,8 +1506,8 @@ namespace Avalonia.Controls // If the row has been recycled, reapply the BackgroundBrush if (row.IsRecycled) { - row.EnsureBackground(); row.ApplyCellsState(); + _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(row)); } else if (row == EditingRow) { diff --git a/src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs b/src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs index c5fe9f0cb2..e07c933039 100644 --- a/src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs +++ b/src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs @@ -3,12 +3,13 @@ // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // All other rights reserved. +using Avalonia.LogicalTree; using Avalonia.Media; using Avalonia.Utilities; using System; +using System.Collections.Generic; +using System.Collections.Specialized; using System.Diagnostics; -using Avalonia.Controls; -using Avalonia.Controls.Utils; namespace Avalonia.Controls.Primitives { @@ -16,9 +17,10 @@ namespace Avalonia.Controls.Primitives /// Used within the template of a /// to specify the location in the control's visual tree where the cells are to be added. /// - public sealed class DataGridCellsPresenter : Panel + public sealed class DataGridCellsPresenter : Panel, IChildIndexProvider { private double _fillerLeftEdge; + private EventHandler _childIndexChanged; // The desired height needs to be cached due to column virtualization; otherwise, the cells // would grow and shrink as the DataGrid scrolls horizontally @@ -42,6 +44,25 @@ namespace Avalonia.Controls.Primitives set; } + event EventHandler IChildIndexProvider.ChildIndexChanged + { + add => _childIndexChanged += value; + remove => _childIndexChanged -= value; + } + + int IChildIndexProvider.GetChildIndex(ILogical child) + { + return child is DataGridCell cell + ? OwningGrid.ColumnsInternal.GetColumnDisplayIndex(cell.ColumnIndex) + : throw new InvalidOperationException("Invalid cell type"); + } + + bool IChildIndexProvider.TryGetTotalCount(out int count) + { + count = OwningGrid.ColumnsInternal.VisibleColumnCount; + return true; + } + /// /// Arranges the content of the . /// @@ -120,6 +141,13 @@ namespace Avalonia.Controls.Primitives } } + protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) + { + base.ChildrenChanged(sender, e); + + InvalidateChildIndex(); + } + private static void EnsureCellDisplay(DataGridCell cell, bool displayColumn) { if (cell.IsCurrent) @@ -304,6 +332,11 @@ namespace Avalonia.Controls.Primitives DesiredHeight = 0; } + internal void InvalidateChildIndex() + { + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); + } + private bool ShouldDisplayCell(DataGridColumn column, double frozenLeftEdge, double scrollingLeftEdge) { if (!column.IsVisible) diff --git a/src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs b/src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs index 4eed119240..108dc8ded7 100644 --- a/src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs +++ b/src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs @@ -3,8 +3,10 @@ // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // All other rights reserved. +using Avalonia.LogicalTree; using Avalonia.Media; using System; +using System.Collections.Specialized; using System.Diagnostics; namespace Avalonia.Controls.Primitives @@ -13,10 +15,11 @@ namespace Avalonia.Controls.Primitives /// Used within the template of a to specify the /// location in the control's visual tree where the column headers are to be added. /// - public sealed class DataGridColumnHeadersPresenter : Panel + public sealed class DataGridColumnHeadersPresenter : Panel, IChildIndexProvider { private Control _dragIndicator; private IControl _dropLocationIndicator; + private EventHandler _childIndexChanged; /// /// Tracks which column is currently being dragged. @@ -104,6 +107,25 @@ namespace Avalonia.Controls.Primitives set; } + event EventHandler IChildIndexProvider.ChildIndexChanged + { + add => _childIndexChanged += value; + remove => _childIndexChanged -= value; + } + + int IChildIndexProvider.GetChildIndex(ILogical child) + { + return child is DataGridColumnHeader header + ? OwningGrid.ColumnsInternal.GetColumnDisplayIndex(header.ColumnIndex) + : throw new InvalidOperationException("Invalid cell type"); + } + + bool IChildIndexProvider.TryGetTotalCount(out int count) + { + count = OwningGrid.ColumnsInternal.VisibleColumnCount; + return true; + } + /// /// Arranges the content of the . /// @@ -391,5 +413,17 @@ namespace Avalonia.Controls.Primitives OwningGrid.ColumnsInternal.EnsureVisibleEdgedColumnsWidth(); return new Size(OwningGrid.ColumnsInternal.VisibleEdgedColumnsWidth, height); } + + protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) + { + base.ChildrenChanged(sender, e); + + InvalidateChildIndex(); + } + + internal void InvalidateChildIndex() + { + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); + } } } diff --git a/src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs b/src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs index 308ebc69d4..0b9bd0a564 100644 --- a/src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs +++ b/src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs @@ -7,8 +7,8 @@ using System; using System.Diagnostics; using Avalonia.Input; -using Avalonia.Input.GestureRecognizers; using Avalonia.Layout; +using Avalonia.LogicalTree; using Avalonia.Media; namespace Avalonia.Controls.Primitives @@ -17,7 +17,7 @@ namespace Avalonia.Controls.Primitives /// Used within the template of a to specify the /// location in the control's visual tree where the rows are to be added. /// - public sealed class DataGridRowsPresenter : Panel + public sealed class DataGridRowsPresenter : Panel, IChildIndexProvider { public DataGridRowsPresenter() { @@ -44,6 +44,22 @@ namespace Avalonia.Controls.Primitives } } + event EventHandler IChildIndexProvider.ChildIndexChanged + { + add => OwningGrid._childIndexChanged += value; + remove => OwningGrid._childIndexChanged -= value; + } + + bool IChildIndexProvider.TryGetTotalCount(out int count) + { + return ((IChildIndexProvider)OwningGrid).TryGetTotalCount(out count); + } + + int IChildIndexProvider.GetChildIndex(ILogical child) + { + return ((IChildIndexProvider)OwningGrid).GetChildIndex(child); + } + /// /// Arranges the content of the . /// diff --git a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml index 8d4e327f3e..05c3d2dd19 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml @@ -103,8 +103,9 @@ + Background="{TemplateBinding Background}" + RowDefinitions="*,Auto,Auto" + ColumnDefinitions="Auto,*"> @@ -118,6 +119,13 @@ + + + + + + diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 0cd72dc91c..114aa9727d 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -166,7 +166,7 @@ namespace Avalonia.Controls if (Presenter is IChildIndexProvider innerProvider) { innerProvider.ChildIndexChanged += PresenterChildIndexChanged; - _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs()); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); } } diff --git a/src/Avalonia.Controls/Panel.cs b/src/Avalonia.Controls/Panel.cs index 482a7fab84..2230b4b0d2 100644 --- a/src/Avalonia.Controls/Panel.cs +++ b/src/Avalonia.Controls/Panel.cs @@ -147,7 +147,7 @@ namespace Avalonia.Controls throw new NotSupportedException(); } - _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs()); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); InvalidateMeasureOnChildrenChanged(); } diff --git a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs index f938c8d437..2821fa8cf0 100644 --- a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs +++ b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs @@ -158,7 +158,7 @@ namespace Avalonia.Controls.Presenters { ItemsChanged(e); - _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs()); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); } } diff --git a/src/Avalonia.Styling/LogicalTree/ChildIndexChangedEventArgs.cs b/src/Avalonia.Styling/LogicalTree/ChildIndexChangedEventArgs.cs index de41f5292c..afc6c1f5fc 100644 --- a/src/Avalonia.Styling/LogicalTree/ChildIndexChangedEventArgs.cs +++ b/src/Avalonia.Styling/LogicalTree/ChildIndexChangedEventArgs.cs @@ -8,6 +8,8 @@ namespace Avalonia.LogicalTree /// public class ChildIndexChangedEventArgs : EventArgs { + public static new ChildIndexChangedEventArgs Empty { get; } = new ChildIndexChangedEventArgs(); + public ChildIndexChangedEventArgs() { } From f7e8b7658fbc68e127f7dc508e386459bf763637 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Fri, 31 Dec 2021 03:43:23 -0500 Subject: [PATCH 03/12] Do not hardcode Margin and VerticalAlignment on data grid text column --- src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs | 5 +---- src/Avalonia.Controls.DataGrid/Themes/Default.xaml | 4 ++++ src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml | 5 +++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs index 863910c226..68736dee7f 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs @@ -19,8 +19,6 @@ namespace Avalonia.Controls /// public class DataGridTextColumn : DataGridBoundColumn { - private const string DATAGRID_TextColumnCellTextBlockMarginKey = "DataGridTextColumnCellTextBlockMargin"; - /// /// Initializes a new instance of the class. /// @@ -178,8 +176,7 @@ namespace Avalonia.Controls { TextBlock textBlockElement = new TextBlock { - [!Layoutable.MarginProperty] = new DynamicResourceExtension(DATAGRID_TextColumnCellTextBlockMarginKey), - VerticalAlignment = VerticalAlignment.Center + Name = "CellTextBlock" }; SyncProperties(textBlockElement); diff --git a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml index 05c3d2dd19..b066702212 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml @@ -29,6 +29,10 @@ + + + From 5019ee09853f91b695563b3ea330dcc0f04673a4 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Fri, 31 Dec 2021 03:46:59 -0500 Subject: [PATCH 04/12] Add missing support of Border properties to the DataGrid templates --- .../Themes/Default.xaml | 135 ++++++---- .../Themes/Fluent.xaml | 255 +++++++++--------- 2 files changed, 213 insertions(+), 177 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml index b066702212..0d1fe43eb6 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml @@ -12,20 +12,25 @@ - - - - - + + + + + + + @@ -44,35 +49,40 @@ - - - - - - + + + + + + + - + - + - + + @@ -106,19 +116,24 @@ @@ -192,12 +207,18 @@ + ColumnDefinitions="Auto,Auto,Auto,Auto" + RowDefinitions="Auto,*,Auto"> - + @@ -250,9 +271,11 @@ - + CornerRadius="{TemplateBinding CornerRadius}"> diff --git a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml index 6a6ab283ab..8243d9c22d 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml @@ -93,54 +93,57 @@ - + + - - - - - + + + + - + - + - - + + + @@ -185,57 +188,58 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + Fill="{TemplateBinding SeparatorBrush}" + IsVisible="{TemplateBinding AreSeparatorsVisible}" /> + + + + + - + @@ -276,35 +280,40 @@ - - - - - - - - + + + + + + + - + DataGridFrozenGrid.IsFrozen="True" /> + + - + + @@ -315,7 +324,7 @@ - + @@ -443,9 +452,12 @@ Width="12" Height="12" Margin="12,0,0,0" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" - Foreground="{TemplateBinding Foreground}" - Focusable="False" /> + CornerRadius="{TemplateBinding CornerRadius}" + Focusable="False" + Foreground="{TemplateBinding Foreground}" /> - - + CornerRadius="{TemplateBinding CornerRadius}"> + From af9f27677d0289b5c45f366f2594f393d2782eb1 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Fri, 31 Dec 2021 04:21:11 -0500 Subject: [PATCH 05/12] Fix NRE in DataGrid --- .../DataGridColumns.cs | 2 +- .../DataGridRows.cs | 28 +++---------------- .../Primitives/DataGridRowsPresenter.cs | 19 +++++++++---- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumns.cs b/src/Avalonia.Controls.DataGrid/DataGridColumns.cs index ea8a121d29..52f0ad7537 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumns.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumns.cs @@ -444,7 +444,7 @@ namespace Avalonia.Controls // We need to explicitly collapse the cells of the invisible column because layout only goes through // visible ones - ColumnHeaders.InvalidateChildIndex(); + ColumnHeaders?.InvalidateChildIndex(); foreach (var row in GetAllRows()) { row.Cells[updatedColumn.Index].IsVisible = updatedColumn.IsVisible; diff --git a/src/Avalonia.Controls.DataGrid/DataGridRows.cs b/src/Avalonia.Controls.DataGrid/DataGridRows.cs index 52b67b8921..f3afe2c42d 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridRows.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridRows.cs @@ -17,7 +17,7 @@ using System.Linq; namespace Avalonia.Controls { - public partial class DataGrid : IChildIndexProvider + public partial class DataGrid { internal bool AreRowBottomGridLinesRequired @@ -124,26 +124,6 @@ namespace Avalonia.Controls } } - internal EventHandler _childIndexChanged; - - event EventHandler IChildIndexProvider.ChildIndexChanged - { - add => _childIndexChanged += value; - remove => _childIndexChanged -= value; - } - - int IChildIndexProvider.GetChildIndex(ILogical child) - { - return child is DataGridRow row - ? row.Index - : throw new InvalidOperationException("Invalid DataGrid child"); - } - - bool IChildIndexProvider.TryGetTotalCount(out int count) - { - return DataConnection.TryGetCount(false, true, out count); - } - /// /// Clears the entire selection. Displayed rows are deselected explicitly to visualize /// potential transition effects @@ -832,7 +812,7 @@ namespace Avalonia.Controls if (row.Slot > slotDeleted) { CorrectRowAfterDeletion(row, wasRow); - _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(row)); + _rowsPresenter?.InvalidateChildIndex(row); } } @@ -888,7 +868,7 @@ namespace Avalonia.Controls if (row.Slot >= slotInserted) { DataGrid.CorrectRowAfterInsertion(row, rowInserted); - _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(row)); + _rowsPresenter?.InvalidateChildIndex(row); } } @@ -1507,7 +1487,7 @@ namespace Avalonia.Controls if (row.IsRecycled) { row.ApplyCellsState(); - _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(row)); + _rowsPresenter?.InvalidateChildIndex(row); } else if (row == EditingRow) { diff --git a/src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs b/src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs index 0b9bd0a564..5d82689eff 100644 --- a/src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs +++ b/src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs @@ -19,6 +19,8 @@ namespace Avalonia.Controls.Primitives /// public sealed class DataGridRowsPresenter : Panel, IChildIndexProvider { + private EventHandler _childIndexChanged; + public DataGridRowsPresenter() { AddHandler(Gestures.ScrollGestureEvent, OnScrollGesture); @@ -46,18 +48,25 @@ namespace Avalonia.Controls.Primitives event EventHandler IChildIndexProvider.ChildIndexChanged { - add => OwningGrid._childIndexChanged += value; - remove => OwningGrid._childIndexChanged -= value; + add => _childIndexChanged += value; + remove => _childIndexChanged -= value; + } + + int IChildIndexProvider.GetChildIndex(ILogical child) + { + return child is DataGridRow row + ? row.Index + : throw new InvalidOperationException("Invalid DataGrid child"); } bool IChildIndexProvider.TryGetTotalCount(out int count) { - return ((IChildIndexProvider)OwningGrid).TryGetTotalCount(out count); + return OwningGrid.DataConnection.TryGetCount(false, true, out count); } - int IChildIndexProvider.GetChildIndex(ILogical child) + internal void InvalidateChildIndex(DataGridRow row) { - return ((IChildIndexProvider)OwningGrid).GetChildIndex(child); + _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(row)); } /// From 64cce62e7b34f2b843d3258de640858d6bfe94f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Komosi=C5=84ski?= Date: Tue, 12 Apr 2022 23:09:46 +0200 Subject: [PATCH 06/12] Benchmark for finding resources. --- .../Styling/ResourceBenchmarks.cs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs diff --git a/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs b/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs new file mode 100644 index 0000000000..1445fcba05 --- /dev/null +++ b/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs @@ -0,0 +1,91 @@ +using System; +using Avalonia.Controls; +using Avalonia.Platform; +using Avalonia.PlatformSupport; +using Avalonia.Styling; +using Avalonia.Themes.Fluent; +using Avalonia.UnitTests; +using BenchmarkDotNet.Attributes; +using Moq; + +namespace Avalonia.Benchmarks.Styling +{ + [MemoryDiagnoser] + public class ResourceBenchmarks : IDisposable + { + private readonly Control _searchStart; + private readonly IDisposable _app; + + private static IDisposable CreateApp() + { + var services = new TestServices( + assetLoader: new AssetLoader(), + globalClock: new MockGlobalClock(), + platform: new AppBuilder().RuntimePlatform, + renderInterface: new MockPlatformRenderInterface(), + standardCursorFactory: Mock.Of(), + styler: new Styler(), + theme: () => LoadTheme(), + threadingInterface: new NullThreadingPlatform(), + fontManagerImpl: new MockFontManagerImpl(), + textShaperImpl: new MockTextShaperImpl(), + windowingPlatform: new MockWindowingPlatform()); + + return UnitTestApplication.Start(services); + } + + private static Styles LoadTheme() + { + AssetLoader.RegisterResUriParsers(); + + var hostStyle = new Style(); + + hostStyle.Resources.Add("test", null); + + return new Styles + { + hostStyle, + new FluentTheme(new Uri("avares://Avalonia.Benchmarks")) + }; + } + + public void Dispose() + { + _app.Dispose(); + } + + public ResourceBenchmarks() + { + _searchStart = new Button(); + + _app = CreateApp(); + + Decorator root = new TestRoot(true, null) + { + Renderer = new NullRenderer() + }; + + var current = root; + + for (int i = 0; i < 10; i++) + { + var child = new Decorator(); + + current.Child = child; + + current = child; + } + + current.Child = _searchStart; + } + + [Benchmark(Baseline = true)] + public void FindResource() + { + for (int i = 0; i < 100; ++i) + { + _searchStart.FindResource("test"); + } + } + } +} From 55e681a326673f680f8324fa1bb365be4305f86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Komosi=C5=84ski?= Date: Tue, 12 Apr 2022 23:15:55 +0200 Subject: [PATCH 07/12] Add more benchmark cases. --- .../Styling/ResourceBenchmarks.cs | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs b/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs index 1445fcba05..babfaef6ab 100644 --- a/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs +++ b/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs @@ -38,14 +38,17 @@ namespace Avalonia.Benchmarks.Styling { AssetLoader.RegisterResUriParsers(); - var hostStyle = new Style(); + var preHost = new Style(); + preHost.Resources.Add("preTheme", null); - hostStyle.Resources.Add("test", null); + var postHost = new Style(); + postHost.Resources.Add("postTheme", null); return new Styles { - hostStyle, - new FluentTheme(new Uri("avares://Avalonia.Benchmarks")) + preHost, + new FluentTheme(new Uri("avares://Avalonia.Benchmarks")), + postHost }; } @@ -79,12 +82,30 @@ namespace Avalonia.Benchmarks.Styling current.Child = _searchStart; } - [Benchmark(Baseline = true)] - public void FindResource() + [Benchmark] + public void FindPreResource() { for (int i = 0; i < 100; ++i) { - _searchStart.FindResource("test"); + _searchStart.FindResource("preTheme"); + } + } + + [Benchmark] + public void FindPostResource() + { + for (int i = 0; i < 100; ++i) + { + _searchStart.FindResource("postTheme"); + } + } + + [Benchmark] + public void FindNotExistingResource() + { + for (int i = 0; i < 100; ++i) + { + _searchStart.FindResource("notPresent"); } } } From a2bcd8a9c95b2fc854939b8ce1ef8f854dfc0e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Komosi=C5=84ski?= Date: Thu, 14 Apr 2022 14:39:56 +0200 Subject: [PATCH 08/12] Remove dependency on fluent theme. --- .../Styling/ResourceBenchmarks.cs | 17 ++++++----- tests/Avalonia.Benchmarks/TestStyles.cs | 29 +++++++++++++++++++ 2 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 tests/Avalonia.Benchmarks/TestStyles.cs diff --git a/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs b/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs index babfaef6ab..2a048beefa 100644 --- a/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs +++ b/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs @@ -3,7 +3,6 @@ using Avalonia.Controls; using Avalonia.Platform; using Avalonia.PlatformSupport; using Avalonia.Styling; -using Avalonia.Themes.Fluent; using Avalonia.UnitTests; using BenchmarkDotNet.Attributes; using Moq; @@ -25,7 +24,7 @@ namespace Avalonia.Benchmarks.Styling renderInterface: new MockPlatformRenderInterface(), standardCursorFactory: Mock.Of(), styler: new Styler(), - theme: () => LoadTheme(), + theme: () => CreateTheme(), threadingInterface: new NullThreadingPlatform(), fontManagerImpl: new MockFontManagerImpl(), textShaperImpl: new MockTextShaperImpl(), @@ -34,7 +33,7 @@ namespace Avalonia.Benchmarks.Styling return UnitTestApplication.Start(services); } - private static Styles LoadTheme() + private static Styles CreateTheme() { AssetLoader.RegisterResUriParsers(); @@ -43,11 +42,11 @@ namespace Avalonia.Benchmarks.Styling var postHost = new Style(); postHost.Resources.Add("postTheme", null); - + return new Styles { preHost, - new FluentTheme(new Uri("avares://Avalonia.Benchmarks")), + new TestStyles(50, 3, 5), postHost }; } @@ -81,11 +80,13 @@ namespace Avalonia.Benchmarks.Styling current.Child = _searchStart; } + + private const int LookupCount = 100; [Benchmark] public void FindPreResource() { - for (int i = 0; i < 100; ++i) + for (int i = 0; i < LookupCount; ++i) { _searchStart.FindResource("preTheme"); } @@ -94,7 +95,7 @@ namespace Avalonia.Benchmarks.Styling [Benchmark] public void FindPostResource() { - for (int i = 0; i < 100; ++i) + for (int i = 0; i < LookupCount; ++i) { _searchStart.FindResource("postTheme"); } @@ -103,7 +104,7 @@ namespace Avalonia.Benchmarks.Styling [Benchmark] public void FindNotExistingResource() { - for (int i = 0; i < 100; ++i) + for (int i = 0; i < LookupCount; ++i) { _searchStart.FindResource("notPresent"); } diff --git a/tests/Avalonia.Benchmarks/TestStyles.cs b/tests/Avalonia.Benchmarks/TestStyles.cs new file mode 100644 index 0000000000..be2ad7d072 --- /dev/null +++ b/tests/Avalonia.Benchmarks/TestStyles.cs @@ -0,0 +1,29 @@ +using Avalonia.Styling; + +namespace Avalonia.Benchmarks +{ + public class TestStyles : Styles + { + public TestStyles(int childStylesCount, int childInnerStyleCount, int childResourceCount) + { + for (int i = 0; i < childStylesCount; i++) + { + var childStyles = new Styles(); + + for (int j = 0; j < childInnerStyleCount; j++) + { + var childStyle = new Style(); + + for (int k = 0; k < childResourceCount; k++) + { + childStyle.Resources.Add($"resource.{i}.{j}.{k}", null); + } + + childStyles.Add(childStyle); + } + + Add(childStyles); + } + } + } +} From 0ec26bcdc3e9b9f841993242ca662f2ea194aa4e Mon Sep 17 00:00:00 2001 From: Max Katz Date: Thu, 14 Apr 2022 11:40:38 -0400 Subject: [PATCH 09/12] Make empty ChildIndexChangedEventArgs ctor private --- src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs b/src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs index afc6c1f5fc..497596fcc1 100644 --- a/src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs +++ b/src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs @@ -10,7 +10,7 @@ namespace Avalonia.LogicalTree { public static new ChildIndexChangedEventArgs Empty { get; } = new ChildIndexChangedEventArgs(); - public ChildIndexChangedEventArgs() + private ChildIndexChangedEventArgs() { } From e6044ea33069d994b65aa05aad7c775e7686d8d9 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 14 Apr 2022 23:49:52 +0200 Subject: [PATCH 10/12] Remove Avalonia.AndroidTestApplication. It's no longer needed. --- Avalonia.sln | 21 +--- .../Avalonia.AndroidTestApplication.csproj | 79 ------------- .../MainActivity.cs | 104 ------------------ .../Properties/AndroidManifest.xml | 4 - .../Resources/AboutResources.txt | 50 --------- .../Resources/drawable/Icon.png | Bin 4147 -> 0 bytes .../Resources/values/Strings.xml | 6 - 7 files changed, 1 insertion(+), 263 deletions(-) delete mode 100644 src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj delete mode 100644 src/Android/Avalonia.AndroidTestApplication/MainActivity.cs delete mode 100644 src/Android/Avalonia.AndroidTestApplication/Properties/AndroidManifest.xml delete mode 100644 src/Android/Avalonia.AndroidTestApplication/Resources/AboutResources.txt delete mode 100644 src/Android/Avalonia.AndroidTestApplication/Resources/drawable/Icon.png delete mode 100644 src/Android/Avalonia.AndroidTestApplication/Resources/values/Strings.xml diff --git a/Avalonia.sln b/Avalonia.sln index a216229a5b..64ed214e1f 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -55,8 +55,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{7CF9 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Android", "src\Android\Avalonia.Android\Avalonia.Android.csproj", "{7B92AF71-6287-4693-9DCB-BD5B6E927E23}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.AndroidTestApplication", "src\Android\Avalonia.AndroidTestApplication\Avalonia.AndroidTestApplication.csproj", "{FF69B927-C545-49AE-8E16-3D14D621AA12}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.iOS", "src\iOS\Avalonia.iOS\Avalonia.iOS.csproj", "{4488AD85-1495-4809-9AA4-DDFE0A48527E}" @@ -209,7 +207,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\S EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport", "src\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj", "{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport.UnitTests", "tests\Avalonia.PlatformSupport.UnitTests\Avalonia.PlatformSupport.UnitTests.csproj", "{CE910927-CE5A-456F-BC92-E4C757354A5C}" EndProject @@ -629,22 +627,6 @@ Global {7B92AF71-6287-4693-9DCB-BD5B6E927E23}.Release|Any CPU.Build.0 = Release|Any CPU {7B92AF71-6287-4693-9DCB-BD5B6E927E23}.Release|iPhone.ActiveCfg = Release|Any CPU {7B92AF71-6287-4693-9DCB-BD5B6E927E23}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.AppStore|iPhone.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|Any CPU.Build.0 = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|Any CPU.Deploy.0 = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|iPhone.ActiveCfg = Release|Any CPU - {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU @@ -1970,7 +1952,6 @@ Global {8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {08B3E6B9-1CD5-443C-9F61-6D49D1C5F162} = {9B9E3891-2366-4253-A952-D08BCEB71098} {7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F} - {FF69B927-C545-49AE-8E16-3D14D621AA12} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F} {4488AD85-1495-4809-9AA4-DDFE0A48527E} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1} {E1AA3DBF-9056-4530-9376-18119A7A3FFE} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {88060192-33D5-4932-B0F9-8BD2763E857D} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj deleted file mode 100644 index ee41b9f354..0000000000 --- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj +++ /dev/null @@ -1,79 +0,0 @@ - - - net6.0-android - 21 - Exe - enable - com.Avalonia.AndroidTestApplication - 1 - 1.0 - apk - true - portable - - - - - Resources\drawable\Icon.png - - - - - True - True - True - True - - - - - - - True - - - - True - - - - - - - - - {7b92af71-6287-4693-9dcb-bd5b6e927e23} - Avalonia.Android - - - {3e53a01a-b331-47f3-b828-4a5717e77a24} - Avalonia.Markup.Xaml - - - {b09b78d8-9b26-48b0-9149-d64a2f120f3f} - Avalonia.Base - - - {d2221c82-4a25-4583-9b43-d791e3f6820c} - Avalonia.Controls - - - {7062ae20-5dcc-4442-9645-8195bdece63e} - Avalonia.Diagnostics - - - {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} - Avalonia.Themes.Default - - - {7d2d3083-71dd-4cc9-8907-39a0d86fb322} - Avalonia.Skia - - - - - - - - - diff --git a/src/Android/Avalonia.AndroidTestApplication/MainActivity.cs b/src/Android/Avalonia.AndroidTestApplication/MainActivity.cs deleted file mode 100644 index 8f4beb2737..0000000000 --- a/src/Android/Avalonia.AndroidTestApplication/MainActivity.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using Android.App; -using Android.Content.PM; -using Avalonia.Android; -using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Input.TextInput; -using Avalonia.Markup.Xaml; -using Avalonia.Media; -using Avalonia.Styling; -using Avalonia.Themes.Default; - -namespace Avalonia.AndroidTestApplication -{ - [Activity(Label = "Main", - MainLauncher = true, - Icon = "@drawable/icon", - Theme = "@style/Theme.AppCompat.NoActionBar", - ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, - LaunchMode = LaunchMode.SingleInstance/*, - ScreenOrientation = ScreenOrientation.Landscape*/)] - public class MainActivity : AvaloniaActivity - { - protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) - { - return base.CustomizeAppBuilder(builder); - } - } - - public class App : Application - { - public override void Initialize() - { - Styles.Add(new SimpleTheme(new Uri("avares://Avalonia.AndroidTestApplication"))); - } - - public override void OnFrameworkInitializationCompleted() - { - if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime) - { - singleViewLifetime.MainView = CreateSimpleWindow(); - } - - base.OnFrameworkInitializationCompleted(); - } - - // This provides a simple UI tree for testing input handling, drawing, etc - public static ContentControl CreateSimpleWindow() - { - ContentControl window = new ContentControl() - { - Background = Brushes.Red, - Content = new StackPanel - { - Margin = new Thickness(30), - Background = Brushes.Yellow, - Children = - { - new TextBlock - { - Text = "TEXT BLOCK", - Width = 300, - Height = 40, - Background = Brushes.White, - Foreground = Brushes.Black - }, - - new Button - { - Content = "BUTTON", - Width = 150, - Height = 40, - Background = Brushes.LightGreen, - Foreground = Brushes.Black - }, - - CreateTextBox(TextInputContentType.Normal), - CreateTextBox(TextInputContentType.Password), - CreateTextBox(TextInputContentType.Email), - CreateTextBox(TextInputContentType.Url), - CreateTextBox(TextInputContentType.Digits), - CreateTextBox(TextInputContentType.Number), - } - } - }; - - return window; - } - - private static TextBox CreateTextBox(TextInputContentType contentType) - { - var textBox = new TextBox() - { - Margin = new Thickness(20, 10), - Watermark = contentType.ToString(), - BorderThickness = new Thickness(3), - FontSize = 20, - [TextInputOptions.ContentTypeProperty] = contentType - }; - - return textBox; - } - } -} diff --git a/src/Android/Avalonia.AndroidTestApplication/Properties/AndroidManifest.xml b/src/Android/Avalonia.AndroidTestApplication/Properties/AndroidManifest.xml deleted file mode 100644 index ad8134f628..0000000000 --- a/src/Android/Avalonia.AndroidTestApplication/Properties/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/Android/Avalonia.AndroidTestApplication/Resources/AboutResources.txt b/src/Android/Avalonia.AndroidTestApplication/Resources/AboutResources.txt deleted file mode 100644 index 194ae28a59..0000000000 --- a/src/Android/Avalonia.AndroidTestApplication/Resources/AboutResources.txt +++ /dev/null @@ -1,50 +0,0 @@ -Images, layout descriptions, binary blobs and string dictionaries can be included -in your application as resource files. Various Android APIs are designed to -operate on the resource IDs instead of dealing with images, strings or binary blobs -directly. - -For example, a sample Android app that contains a user interface layout (main.xml), -an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) -would keep its resources in the "Resources" directory of the application: - -Resources/ - drawable-hdpi/ - icon.png - - drawable-ldpi/ - icon.png - - drawable-mdpi/ - icon.png - - layout/ - main.xml - - values/ - strings.xml - -In order to get the build system to recognize Android resources, set the build action to -"AndroidResource". The native Android APIs do not operate directly with filenames, but -instead operate on resource IDs. When you compile an Android application that uses resources, -the build system will package the resources for distribution and generate a class called -"Resource" that contains the tokens for each one of the resources included. For example, -for the above Resources layout, this is what the Resource class would expose: - -public class Resource { - public class drawable { - public const int icon = 0x123; - } - - public class layout { - public const int main = 0x456; - } - - public class strings { - public const int first_string = 0xabc; - public const int second_string = 0xbcd; - } -} - -You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main -to reference the layout/main.xml file, or Resource.strings.first_string to reference the first -string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/src/Android/Avalonia.AndroidTestApplication/Resources/drawable/Icon.png b/src/Android/Avalonia.AndroidTestApplication/Resources/drawable/Icon.png deleted file mode 100644 index 8074c4c571b8cd19e27f4ee5545df367420686d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4147 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 diff --git a/src/Android/Avalonia.AndroidTestApplication/Resources/values/Strings.xml b/src/Android/Avalonia.AndroidTestApplication/Resources/values/Strings.xml deleted file mode 100644 index c8dca13c35..0000000000 --- a/src/Android/Avalonia.AndroidTestApplication/Resources/values/Strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - Hello World, Click Me! - Avalonia.AndroidTestApplication - \ No newline at end of file From a71ddcc8700cdd9a589b2385c0e801d55df0928c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 14 Apr 2022 23:50:16 +0200 Subject: [PATCH 11/12] Fix project files broken by #5831. --- .../ControlCatalog.Android.csproj | 44 +-------------- .../ControlCatalog.iOS.csproj | 53 +------------------ 2 files changed, 4 insertions(+), 93 deletions(-) diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj index 8d2ead054c..04c67e84e8 100644 --- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj +++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj @@ -39,49 +39,9 @@ - + - - {7b92af71-6287-4693-9dcb-bd5b6e927e23} - Avalonia.Android - - - {b09b78d8-9b26-48b0-9149-d64a2f120f3f} - Avalonia.Base - - - {d2221c82-4a25-4583-9b43-d791e3f6820c} - Avalonia.Controls - - - {7062ae20-5dcc-4442-9645-8195bdece63e} - Avalonia.Diagnostics - - - {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} - Avalonia.Themes.Default - - - {3e53a01a-b331-47f3-b828-4a5717e77a24} - Avalonia.Markup.Xaml - - - {6417e941-21bc-467b-a771-0de389353ce6} - Avalonia.Markup - - - {7d2d3083-71dd-4cc9-8907-39a0d86fb322} - Avalonia.Skia - - - {d0a739b9-3c68-4ba6-a328-41606954b6bd} - ControlCatalog - - - - - - + \ No newline at end of file diff --git a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj index d4f10b3580..513ac44f83 100644 --- a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj +++ b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj @@ -7,59 +7,10 @@ True iossimulator-x64 - + - - - - - - - - - {4488ad85-1495-4809-9aa4-ddfe0a48527e} - Avalonia.iOS - - - {3E53A01A-B331-47F3-B828-4A5717E77A24} - Avalonia.Markup.Xaml - - - {6417E941-21BC-467B-A771-0DE389353CE6} - Avalonia.Markup - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {7062AE20-5DCC-4442-9645-8195BDECE63E} - Avalonia.Diagnostics - - - {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F} - Avalonia.Themes.Default - - - {7d2d3083-71dd-4cc9-8907-39a0d86fb322} - Avalonia.Skia - - - {d0a739b9-3c68-4ba6-a328-41606954b6bd} - ControlCatalog - - - - - - - - + \ No newline at end of file From c1644eb21455bb2658ed67c52c5425139c0cb672 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Apr 2022 22:11:48 +0000 Subject: [PATCH 12/12] Bump async in /src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4. - [Release notes](https://github.com/caolan/async/releases) - [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md) - [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4) --- updated-dependencies: - dependency-name: async dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../Remote/HtmlTransport/webapp/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/package-lock.json b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/package-lock.json index 08ede477c3..403bb5a59a 100644 --- a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/package-lock.json +++ b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/package-lock.json @@ -377,9 +377,9 @@ "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, "requires": { "lodash": "^4.17.14"