From 799b498afcfb416fa5d2535bd282c48d19d4b0d9 Mon Sep 17 00:00:00 2001 From: William David Cossey Date: Sat, 25 Aug 2018 16:29:37 +0100 Subject: [PATCH 01/10] Cleaning up Themes. Renamed ErrorBrushLight to ErrorLightBrush. ListBoxItem - Removed hardcoded Colors/Brushes, added additional sytling. Removed ListBoxItem Style Selector from AutoCompleteBox (inherrited). CalendarButton - Removed hardcoded Colors/Brushes. DropDownItem - Removed hardcoded Colors/Brushes, added additional sytling. ScrollBar - Removed hardcoded Colors/Brushes. Added ListBox to ControlCatalog. Slider bug fix (hopefully). --- samples/ControlCatalog/ControlCatalog.csproj | 9 +++ samples/ControlCatalog/MainView.xaml | 3 +- samples/ControlCatalog/Pages/ListBoxPage.xaml | 13 ++++ .../ControlCatalog/Pages/ListBoxPage.xaml.cs | 25 ++++++++ .../Pages/NumericUpDownPage.xaml | 4 +- src/Avalonia.Controls/Slider.cs | 8 +-- .../Accents/BaseLight.xaml | 60 +++++++++++++------ .../AutoCompleteBox.xaml | 6 +- .../CalendarButton.xaml | 5 +- .../DataValidationErrors.xaml | 4 +- src/Avalonia.Themes.Default/DropDownItem.xaml | 22 +++++-- src/Avalonia.Themes.Default/ListBoxItem.xaml | 23 ++++++- src/Avalonia.Themes.Default/ScrollBar.xaml | 10 ++-- 13 files changed, 145 insertions(+), 47 deletions(-) create mode 100644 samples/ControlCatalog/Pages/ListBoxPage.xaml create mode 100644 samples/ControlCatalog/Pages/ListBoxPage.xaml.cs diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj index dea9b35e24..52f91b1295 100644 --- a/samples/ControlCatalog/ControlCatalog.csproj +++ b/samples/ControlCatalog/ControlCatalog.csproj @@ -33,6 +33,15 @@ + + + + MSBuild:Compile + + + MSBuild:Compile + + \ No newline at end of file diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 87cb5e9c5c..ec3bf799b4 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -20,8 +20,9 @@ + - + diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml b/samples/ControlCatalog/Pages/ListBoxPage.xaml new file mode 100644 index 0000000000..3dd8be91c2 --- /dev/null +++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml @@ -0,0 +1,13 @@ + + + ListBox + Hosts a collection of ListBoxItem. + + + + + + diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs b/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs new file mode 100644 index 0000000000..dbe6c74800 --- /dev/null +++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace ControlCatalog.Pages +{ + public class ListBoxPage : UserControl + { + public ListBoxPage() + { + this.InitializeComponent(); + DataContext = Enumerable.Range(1, 10).Select(i => $"Item {i}" ) + .ToArray(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + } +} diff --git a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml index 305bcd177c..2bb6214b58 100644 --- a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml +++ b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml @@ -14,7 +14,7 @@ AllowSpin: - + ClipValueToMinMax: @@ -77,4 +77,4 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Controls/Slider.cs b/src/Avalonia.Controls/Slider.cs index 31113812d1..32b0a1f259 100644 --- a/src/Avalonia.Controls/Slider.cs +++ b/src/Avalonia.Controls/Slider.cs @@ -171,11 +171,7 @@ namespace Avalonia.Controls /// Value that want to snap to closest Tick. private void MoveToNextTick(double value) { - double next = SnapToTick(Math.Max(Minimum, Math.Min(Maximum, value))); - if (next != value) - { - Value = next; - } + Value = SnapToTick(Math.Max(Minimum, Math.Min(Maximum, value))); } /// @@ -194,4 +190,4 @@ namespace Avalonia.Controls return value; } } -} \ No newline at end of file +} diff --git a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml index 4c85e172ff..afac69c9b3 100644 --- a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml +++ b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml @@ -2,23 +2,49 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib"> - #FFFFFFFF - #FFAAAAAA - #FF888888 - #FF333333 - #FFFFFFFF - #FFAAAAAA - #FF888888 - #FF000000 - #FF808080 + + #CC119EDA + #99119EDA + #66119EDA + #33119EDA + + #FFFFFFFF + #FFAAAAAA + #FF888888 + #FF333333 + #FFFFFFFF + #FFAAAAAA + #FF888888 + #FFF0F0F0 + #FFD0D0D0 + #FF808080 + #FF000000 + #FF808080 + + #FF086F9E + #FFFF0000 + #10FF0000 - #FF086F9E - #CC119EDA - #99119EDA - #66119EDA - #33119EDA - Red - #10ff0000 + + + + + + + + + + + + + + + + + + + + 2 0.5 @@ -27,4 +53,4 @@ 12 16 - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/AutoCompleteBox.xaml b/src/Avalonia.Themes.Default/AutoCompleteBox.xaml index 6a9af487cb..11d8a344d9 100644 --- a/src/Avalonia.Themes.Default/AutoCompleteBox.xaml +++ b/src/Avalonia.Themes.Default/AutoCompleteBox.xaml @@ -36,8 +36,4 @@ - - - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/CalendarButton.xaml b/src/Avalonia.Themes.Default/CalendarButton.xaml index 84969c135f..b70740e0c8 100644 --- a/src/Avalonia.Themes.Default/CalendarButton.xaml +++ b/src/Avalonia.Themes.Default/CalendarButton.xaml @@ -7,6 +7,7 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/DataValidationErrors.xaml b/src/Avalonia.Themes.Default/DataValidationErrors.xaml index f7f28d90d0..be45dfd1b9 100644 --- a/src/Avalonia.Themes.Default/DataValidationErrors.xaml +++ b/src/Avalonia.Themes.Default/DataValidationErrors.xaml @@ -24,7 +24,7 @@ Background="#00FFFFFF"> @@ -35,4 +35,4 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/DropDownItem.xaml b/src/Avalonia.Themes.Default/DropDownItem.xaml index 257030d8af..f52608c0a8 100644 --- a/src/Avalonia.Themes.Default/DropDownItem.xaml +++ b/src/Avalonia.Themes.Default/DropDownItem.xaml @@ -18,10 +18,24 @@ + + + - + + + + - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/ListBoxItem.xaml b/src/Avalonia.Themes.Default/ListBoxItem.xaml index fc2600c1a9..19a6e3d4ec 100644 --- a/src/Avalonia.Themes.Default/ListBoxItem.xaml +++ b/src/Avalonia.Themes.Default/ListBoxItem.xaml @@ -1,6 +1,9 @@ + + + + + + + + - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/ScrollBar.xaml b/src/Avalonia.Themes.Default/ScrollBar.xaml index b24c863be9..ef57474eaf 100644 --- a/src/Avalonia.Themes.Default/ScrollBar.xaml +++ b/src/Avalonia.Themes.Default/ScrollBar.xaml @@ -10,7 +10,7 @@ Grid.Column="0"> + Fill="{DynamicResource ThemeForegroundLightBrush}" /> + Fill="{DynamicResource ThemeForegroundLightBrush}" /> @@ -61,7 +61,7 @@ Grid.Column="0"> + Fill="{DynamicResource ThemeForegroundLightBrush}" /> + Fill="{DynamicResource ThemeForegroundLightBrush}" /> @@ -124,4 +124,4 @@ - \ No newline at end of file + From f7e31e58c09d6c3efb281f96b8a7b70e12cbf618 Mon Sep 17 00:00:00 2001 From: William David Cossey Date: Sat, 25 Aug 2018 16:32:53 +0100 Subject: [PATCH 02/10] Removed junk. --- samples/ControlCatalog/ControlCatalog.csproj | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj index 52f91b1295..61f2443eb7 100644 --- a/samples/ControlCatalog/ControlCatalog.csproj +++ b/samples/ControlCatalog/ControlCatalog.csproj @@ -33,15 +33,6 @@ - - - - MSBuild:Compile - - - MSBuild:Compile - - - \ No newline at end of file + From e9cde299bb282db2ea99a7c6e14d9b43f83b2a35 Mon Sep 17 00:00:00 2001 From: Jeffrey Ye Date: Sat, 25 Aug 2018 15:34:52 -0700 Subject: [PATCH 03/10] #1802 add SelectedItemChanged event to TreeView --- .../SelectedItemChangedEventArgs.cs | 36 +++++++++++++++++++ src/Avalonia.Controls/TreeView.cs | 27 ++++++++++++++ .../TreeViewTests.cs | 32 +++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 src/Avalonia.Controls/SelectedItemChangedEventArgs.cs diff --git a/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs b/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs new file mode 100644 index 0000000000..6fb8a2d313 --- /dev/null +++ b/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using Avalonia; +using Avalonia.Interactivity; + +namespace Avalonia.Controls +{ + /// + /// Provides data for the event. + /// + public class SelectedItemChangedEventArgs : RoutedEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The event being raised. + /// The items added to the selection. + /// The items removed from the selection. + public SelectedItemChangedEventArgs(RoutedEvent routedEvent, object newItem, object oldItem) + : base(routedEvent) + { + NewItem = newItem; + OldItem = oldItem; + } + + /// + /// Gets the items that were added to the selection. + /// + public object NewItem { get; } + + /// + /// Gets the items that were removed from the selection. + /// + public object OldItem { get; } + } +} diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index 2e1c011685..50b45cbb9a 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -32,6 +32,14 @@ namespace Avalonia.Controls o => o.SelectedItem, (o, v) => o.SelectedItem = v); + /// + /// Defines the event. + /// + public static readonly RoutedEvent SelectedItemChangedEvent = + RoutedEvent.Register( + "SelectedItemChanged", + RoutingStrategies.Bubble); + private object _selectedItem; /// @@ -42,6 +50,15 @@ namespace Avalonia.Controls // HACK: Needed or SelectedItem property will not be found in Release build. } + /// + /// Occurs when the control's selection changes. + /// + public event EventHandler SelectedItemChanged + { + add { AddHandler(SelectedItemChangedEvent, value); } + remove { RemoveHandler(SelectedItemChangedEvent, value); } + } + /// /// Gets the for the tree view. /// @@ -75,6 +92,7 @@ namespace Avalonia.Controls MarkContainerSelected(container, false); } + var oldItem = _selectedItem; SetAndRaise(SelectedItemProperty, ref _selectedItem, value); if (_selectedItem != null) @@ -87,6 +105,15 @@ namespace Avalonia.Controls container.BringIntoView(); } } + + if (oldItem != _selectedItem) + { + var changed = new SelectedItemChangedEventArgs( + SelectedItemChangedEvent, + _selectedItem, + oldItem); + RaiseEvent(changed); + } } } diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index c49c343a45..8295409f7e 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -166,6 +166,38 @@ namespace Avalonia.Controls.UnitTests Assert.True(container.IsSelected); } + + [Fact] + public void Setting_SelectedItem_Should_Raise_SelectedItemChanged_Event() + { + var tree = CreateTestTreeData(); + var target = new TreeView + { + Template = CreateTreeViewTemplate(), + Items = tree, + }; + + var visualRoot = new TestRoot(); + visualRoot.Child = target; + + CreateNodeDataTemplate(target); + ApplyTemplates(target); + + var item = tree[0].Children[1].Children[0]; + + var called = false; + target.SelectedItemChanged += (s, e) => + { + Assert.Null(e.OldItem); + Assert.Same(item, e.NewItem); + called = true; + }; + + target.SelectedItem = item; + Assert.True(called); + } + + [Fact] public void LogicalChildren_Should_Be_Set() { From 8087f81ea57ee0b955154a61e3d59550c2a20e40 Mon Sep 17 00:00:00 2001 From: William David Cossey Date: Mon, 27 Aug 2018 02:52:04 +0100 Subject: [PATCH 04/10] Cleaned up resources for CalendarDayButton,CalendarItem,DataValidationErrors,DatePicker,Expander,Slider Typeface - Added Typeface.Default. FormattedTextImpl - Fallback to Typeface.Default for null typeface. --- src/Avalonia.Themes.Default/CalendarDayButton.xaml | 6 +++--- src/Avalonia.Themes.Default/CalendarItem.xaml | 4 ++-- src/Avalonia.Themes.Default/DataValidationErrors.xaml | 2 +- src/Avalonia.Themes.Default/DatePicker.xaml | 8 ++++---- src/Avalonia.Themes.Default/Expander.xaml | 4 ++-- src/Avalonia.Themes.Default/Slider.xaml | 3 ++- src/Avalonia.Visuals/Media/Typeface.cs | 2 ++ src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 7 ++++++- 8 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/Avalonia.Themes.Default/CalendarDayButton.xaml b/src/Avalonia.Themes.Default/CalendarDayButton.xaml index ee7afdc73b..4a971ef0cb 100644 --- a/src/Avalonia.Themes.Default/CalendarDayButton.xaml +++ b/src/Avalonia.Themes.Default/CalendarDayButton.xaml @@ -42,7 +42,7 @@ HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5" - Fill="#FF000000" + Fill="{DynamicResource ThemeForegroundBrush}" Stretch="Fill" Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z" /> @@ -103,7 +103,7 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/CalendarItem.xaml b/src/Avalonia.Themes.Default/CalendarItem.xaml index 3d3d75a39a..b52b7acf53 100644 --- a/src/Avalonia.Themes.Default/CalendarItem.xaml +++ b/src/Avalonia.Themes.Default/CalendarItem.xaml @@ -153,7 +153,7 @@ @@ -180,4 +180,4 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/DataValidationErrors.xaml b/src/Avalonia.Themes.Default/DataValidationErrors.xaml index be45dfd1b9..16c2d6adef 100644 --- a/src/Avalonia.Themes.Default/DataValidationErrors.xaml +++ b/src/Avalonia.Themes.Default/DataValidationErrors.xaml @@ -21,7 +21,7 @@ + Background="Transparent"> - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/Expander.xaml b/src/Avalonia.Themes.Default/Expander.xaml index 0bea0c9763..d12f704cc4 100644 --- a/src/Avalonia.Themes.Default/Expander.xaml +++ b/src/Avalonia.Themes.Default/Expander.xaml @@ -108,7 +108,7 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/Slider.xaml b/src/Avalonia.Themes.Default/Slider.xaml index 58fd67b2f6..95924b31a1 100644 --- a/src/Avalonia.Themes.Default/Slider.xaml +++ b/src/Avalonia.Themes.Default/Slider.xaml @@ -80,10 +80,11 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Visuals/Media/Typeface.cs b/src/Avalonia.Visuals/Media/Typeface.cs index 40e98d1565..6dde2bb591 100644 --- a/src/Avalonia.Visuals/Media/Typeface.cs +++ b/src/Avalonia.Visuals/Media/Typeface.cs @@ -7,6 +7,8 @@ namespace Avalonia.Media /// public class Typeface { + public static Typeface Default = new Typeface(FontFamily.Default); + /// /// Initializes a new instance of the class. /// diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index d835c83aa6..8ad88da7f4 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -30,6 +30,11 @@ namespace Avalonia.Skia SKTypeface skiaTypeface = TypefaceCache.Default; + if (typeface == null) + { + typeface = Typeface.Default; + } + if (typeface.FontFamily.Key != null) { var typefaces = SKTypefaceCollectionCache.GetOrAddTypefaceCollection(typeface.FontFamily); @@ -723,4 +728,4 @@ namespace Avalonia.Skia } } } -} \ No newline at end of file +} From a161f6a095eb990b48d9b7173326b6fcd7fceac4 Mon Sep 17 00:00:00 2001 From: William David Cossey Date: Tue, 28 Aug 2018 22:31:46 +0100 Subject: [PATCH 05/10] ScreenPage.cs - Bug fix. TreeViewItem - Added Depth property. BaseLight.xaml - Added InvisibleSelectionColor/Brush. DatePicker.xaml - Improvments. TreeViewItem.xaml - Reworked styling. FormattedTextImpl.cs - Reverted previous changes. --- samples/ControlCatalog/Pages/ScreenPage.cs | 8 +- src/Avalonia.Controls/TreeViewItem.cs | 40 ++++- .../Accents/BaseLight.xaml | 6 +- src/Avalonia.Themes.Default/DatePicker.xaml | 27 +-- src/Avalonia.Themes.Default/TreeViewItem.xaml | 154 ++++++++++-------- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 5 - 6 files changed, 153 insertions(+), 87 deletions(-) diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs index 34aa85b8aa..fd66185832 100644 --- a/samples/ControlCatalog/Pages/ScreenPage.cs +++ b/samples/ControlCatalog/Pages/ScreenPage.cs @@ -42,7 +42,11 @@ namespace ControlCatalog.Pages context.DrawRectangle(p, boundsRect); context.DrawRectangle(p, workingAreaRect); - FormattedText text = new FormattedText(); + FormattedText text = new FormattedText() + { + Typeface = Typeface.Default + }; + text.Text = $"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}"; context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height), text); @@ -59,4 +63,4 @@ namespace ControlCatalog.Pages context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10, w.Bounds.Width / 10, w.Bounds.Height / 10)); } } -} \ No newline at end of file +} diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs index 0886c05038..33b0e54868 100644 --- a/src/Avalonia.Controls/TreeViewItem.cs +++ b/src/Avalonia.Controls/TreeViewItem.cs @@ -6,6 +6,7 @@ using Avalonia.Controls.Generators; using Avalonia.Controls.Mixins; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; +using Avalonia.Data; using Avalonia.Input; using Avalonia.LogicalTree; @@ -21,7 +22,7 @@ namespace Avalonia.Controls /// public static readonly DirectProperty IsExpandedProperty = AvaloniaProperty.RegisterDirect( - "IsExpanded", + nameof(IsExpanded), o => o.IsExpanded, (o, v) => o.IsExpanded = v); @@ -31,11 +32,20 @@ namespace Avalonia.Controls public static readonly StyledProperty IsSelectedProperty = ListBoxItem.IsSelectedProperty.AddOwner(); + /// + /// Defines the property. + /// + public static readonly DirectProperty DepthProperty = + AvaloniaProperty.RegisterDirect( + nameof(Depth), + o => o.Depth); + private static readonly ITemplate DefaultPanel = new FuncTemplate(() => new StackPanel()); private TreeView _treeView; private bool _isExpanded; + private int _depth; /// /// Initializes static members of the class. @@ -65,6 +75,34 @@ namespace Avalonia.Controls set { SetValue(IsSelectedProperty, value); } } + /// + /// Gets or sets the depth of the item. + /// + public int Depth + { + get { return this.GetDepth(this); } + } + + private int GetDepth(TreeViewItem item) + { + TreeViewItem parent; + while ((parent = GetParent(item)) != null) + { + return GetDepth(parent) + 1; + } + return 0; + } + + private static TreeViewItem GetParent(TreeViewItem item) + { + var parent = item.InheritanceParent; + while (!(parent == null || parent is TreeViewItem || parent is TreeView)) + { + parent = item.Parent; + } + return parent as TreeViewItem; + } + /// /// Gets the for the tree view. /// diff --git a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml index afac69c9b3..5aac023708 100644 --- a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml +++ b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml @@ -25,6 +25,8 @@ #FFFF0000 #10FF0000 + #01000000 + @@ -45,7 +47,9 @@ - + + + 2 0.5 diff --git a/src/Avalonia.Themes.Default/DatePicker.xaml b/src/Avalonia.Themes.Default/DatePicker.xaml index 8e0bb5f0b0..93bafdb56f 100644 --- a/src/Avalonia.Themes.Default/DatePicker.xaml +++ b/src/Avalonia.Themes.Default/DatePicker.xaml @@ -6,7 +6,8 @@ --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:sys="clr-namespace:System;assembly=mscorlib"> + + - + - - - - - - - + + + - - \ No newline at end of file + + + + + + + + + + + + diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index 8ad88da7f4..c8d051ed74 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -30,11 +30,6 @@ namespace Avalonia.Skia SKTypeface skiaTypeface = TypefaceCache.Default; - if (typeface == null) - { - typeface = Typeface.Default; - } - if (typeface.FontFamily.Key != null) { var typefaces = SKTypefaceCollectionCache.GetOrAddTypefaceCollection(typeface.FontFamily); From d4b9ef504248585a4b34b874e8a435cf40cd6625 Mon Sep 17 00:00:00 2001 From: William David Cossey Date: Tue, 28 Aug 2018 22:32:11 +0100 Subject: [PATCH 06/10] Added missing Converter. --- .../Converters/MarginMultiplierConverter.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs diff --git a/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs b/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs new file mode 100644 index 0000000000..54bd6bcf39 --- /dev/null +++ b/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs @@ -0,0 +1,32 @@ +using System; +using System.Globalization; +using Avalonia.Data.Converters; + +namespace Avalonia.Controls.Converters +{ + public class MarginMultiplierConverter : IValueConverter + { + public double Indent { get; set; } + + public bool Left { get; set; } = false; + + public bool Top { get; set; } = false; + + public bool Right { get; set; } = false; + + public bool Bottom { get; set; } = false; + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (!(value is int depth)) + return new Thickness(0); + + return new Thickness(Left ? Indent * depth : 0, Top ? Indent * depth : 0, Right ? Indent * depth : 0, Bottom ? Indent * depth : 0); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new System.NotImplementedException(); + } + } +} From f180ec4dd7fed1cbadcc8fa4aba4875fec4530fc Mon Sep 17 00:00:00 2001 From: Jeffrey Ye Date: Wed, 29 Aug 2018 14:22:00 -0700 Subject: [PATCH 07/10] Use SelectionChangedEventArgs instead of SelectedItemChangedEventArgs --- .../SelectedItemChangedEventArgs.cs | 36 ------------------- src/Avalonia.Controls/TreeView.cs | 26 ++++++++++---- .../TreeViewTests.cs | 5 +-- 3 files changed, 23 insertions(+), 44 deletions(-) delete mode 100644 src/Avalonia.Controls/SelectedItemChangedEventArgs.cs diff --git a/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs b/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs deleted file mode 100644 index 6fb8a2d313..0000000000 --- a/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using Avalonia; -using Avalonia.Interactivity; - -namespace Avalonia.Controls -{ - /// - /// Provides data for the event. - /// - public class SelectedItemChangedEventArgs : RoutedEventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// The event being raised. - /// The items added to the selection. - /// The items removed from the selection. - public SelectedItemChangedEventArgs(RoutedEvent routedEvent, object newItem, object oldItem) - : base(routedEvent) - { - NewItem = newItem; - OldItem = oldItem; - } - - /// - /// Gets the items that were added to the selection. - /// - public object NewItem { get; } - - /// - /// Gets the items that were removed from the selection. - /// - public object OldItem { get; } - } -} diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index 50b45cbb9a..d449a7cd38 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Collections.Generic; using System.Linq; using Avalonia.Controls.Generators; using Avalonia.Controls.Primitives; @@ -35,8 +36,8 @@ namespace Avalonia.Controls /// /// Defines the event. /// - public static readonly RoutedEvent SelectedItemChangedEvent = - RoutedEvent.Register( + public static readonly RoutedEvent SelectedItemChangedEvent = + RoutedEvent.Register( "SelectedItemChanged", RoutingStrategies.Bubble); @@ -53,7 +54,7 @@ namespace Avalonia.Controls /// /// Occurs when the control's selection changes. /// - public event EventHandler SelectedItemChanged + public event EventHandler SelectedItemChanged { add { AddHandler(SelectedItemChangedEvent, value); } remove { RemoveHandler(SelectedItemChangedEvent, value); } @@ -108,10 +109,23 @@ namespace Avalonia.Controls if (oldItem != _selectedItem) { - var changed = new SelectedItemChangedEventArgs( + // Fire the SelectionChanged event + List removed = new List(); + if (oldItem != null) + { + removed.Add(oldItem); + } + + List added = new List(); + if (_selectedItem != null) + { + added.Add(_selectedItem); + } + + var changed = new SelectionChangedEventArgs( SelectedItemChangedEvent, - _selectedItem, - oldItem); + added, + removed); RaiseEvent(changed); } } diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index 8295409f7e..1a913865cb 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -188,8 +188,9 @@ namespace Avalonia.Controls.UnitTests var called = false; target.SelectedItemChanged += (s, e) => { - Assert.Null(e.OldItem); - Assert.Same(item, e.NewItem); + Assert.Empty(e.RemovedItems); + Assert.Equal(1, e.AddedItems.Count); + Assert.Same(item, e.AddedItems[0]); called = true; }; From f6dfd1688ef7ec2014503b70daa65ea84f80b838 Mon Sep 17 00:00:00 2001 From: William David Cossey Date: Thu, 30 Aug 2018 01:03:58 +0100 Subject: [PATCH 08/10] TreeViewItem updates. --- src/Avalonia.Controls/TreeViewItem.cs | 29 +--- .../LogicalTree/LogicalExtensions.cs | 15 ++ src/Avalonia.Themes.Default/TreeViewItem.xaml | 163 +++++++++--------- 3 files changed, 102 insertions(+), 105 deletions(-) diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs index 33b0e54868..c5d3313117 100644 --- a/src/Avalonia.Controls/TreeViewItem.cs +++ b/src/Avalonia.Controls/TreeViewItem.cs @@ -6,7 +6,6 @@ using Avalonia.Controls.Generators; using Avalonia.Controls.Mixins; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; -using Avalonia.Data; using Avalonia.Input; using Avalonia.LogicalTree; @@ -37,8 +36,7 @@ namespace Avalonia.Controls /// public static readonly DirectProperty DepthProperty = AvaloniaProperty.RegisterDirect( - nameof(Depth), - o => o.Depth); + nameof(Depth), o => o.Depth); private static readonly ITemplate DefaultPanel = new FuncTemplate(() => new StackPanel()); @@ -80,27 +78,8 @@ namespace Avalonia.Controls /// public int Depth { - get { return this.GetDepth(this); } - } - - private int GetDepth(TreeViewItem item) - { - TreeViewItem parent; - while ((parent = GetParent(item)) != null) - { - return GetDepth(parent) + 1; - } - return 0; - } - - private static TreeViewItem GetParent(TreeViewItem item) - { - var parent = item.InheritanceParent; - while (!(parent == null || parent is TreeViewItem || parent is TreeView)) - { - parent = item.Parent; - } - return parent as TreeViewItem; + get { return _depth; } + private set { SetAndRaise(DepthProperty, ref _depth, value); } } /// @@ -127,6 +106,8 @@ namespace Avalonia.Controls base.OnAttachedToLogicalTree(e); _treeView = this.GetLogicalAncestors().OfType().FirstOrDefault(); + Depth = this.CalculateDistanceFromLogicalParent() - 1; + if (ItemTemplate == null && _treeView?.ItemTemplate != null) { ItemTemplate = _treeView.ItemTemplate; diff --git a/src/Avalonia.Styling/LogicalTree/LogicalExtensions.cs b/src/Avalonia.Styling/LogicalTree/LogicalExtensions.cs index 276ea6c060..47550a876d 100644 --- a/src/Avalonia.Styling/LogicalTree/LogicalExtensions.cs +++ b/src/Avalonia.Styling/LogicalTree/LogicalExtensions.cs @@ -87,5 +87,20 @@ namespace Avalonia.LogicalTree { return target.GetLogicalAncestors().Any(x => x == logical); } + + public static int CalculateDistanceFromLogicalParent(this ILogical logical, int @default = -1) where T : class + { + Contract.Requires(logical != null); + + var result = 0; + + while (logical != null && logical.GetType() != typeof(T)) + { + ++result; + logical = logical.LogicalParent; + } + + return logical != null ? result : @default; + } } } diff --git a/src/Avalonia.Themes.Default/TreeViewItem.xaml b/src/Avalonia.Themes.Default/TreeViewItem.xaml index a51b6c0aca..5c5012e685 100644 --- a/src/Avalonia.Themes.Default/TreeViewItem.xaml +++ b/src/Avalonia.Themes.Default/TreeViewItem.xaml @@ -1,91 +1,92 @@ - + xmlns:converters="clr-namespace:Avalonia.Controls.Converters;assembly=Avalonia.Controls"> + - + - - - + - + - + - + - - - + - + + + + + From 22b373948a821ddb0749f2213b15fa2ec67ec34b Mon Sep 17 00:00:00 2001 From: William David Cossey Date: Thu, 30 Aug 2018 01:05:15 +0100 Subject: [PATCH 09/10] Reverted some tab indentation. --- src/Avalonia.Themes.Default/TreeViewItem.xaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Themes.Default/TreeViewItem.xaml b/src/Avalonia.Themes.Default/TreeViewItem.xaml index 5c5012e685..ada86d3535 100644 --- a/src/Avalonia.Themes.Default/TreeViewItem.xaml +++ b/src/Avalonia.Themes.Default/TreeViewItem.xaml @@ -47,10 +47,10 @@ Height="12" HorizontalAlignment="Center" VerticalAlignment="Center"> - + From 71d74fe7cdb20811e32dccf882c7cb5fcd0c4dba Mon Sep 17 00:00:00 2001 From: William David Cossey Date: Thu, 6 Sep 2018 01:11:29 +0100 Subject: [PATCH 10/10] TreeViewItem.cs - Renamed Depth to Level. TreeViewItem.cs - Moved CalculateDistanceFromLogicalParent from LogicalExtensions. TreeViewItem.xaml - Cleaned up selectors. PropertyEqualsSelector.cs - Default null to string.Empty. ContentControl.cs - Added valid & invalid pseudoclasses for ContentProperty. BaseLight.xaml - Removed unused resources. CheckBox.xaml - Hide ContentPresenter#PART_ContentPresenter when Content is null. --- src/Avalonia.Controls/ContentControl.cs | 2 + src/Avalonia.Controls/TreeViewItem.cs | 33 ++-- .../LogicalTree/LogicalExtensions.cs | 15 -- .../Styling/PropertyEqualsSelector.cs | 6 +- .../Accents/BaseLight.xaml | 102 ++++++----- src/Avalonia.Themes.Default/CheckBox.xaml | 5 +- src/Avalonia.Themes.Default/TreeViewItem.xaml | 158 +++++++++--------- 7 files changed, 160 insertions(+), 161 deletions(-) diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs index 6da6da54a5..f9241956bd 100644 --- a/src/Avalonia.Controls/ContentControl.cs +++ b/src/Avalonia.Controls/ContentControl.cs @@ -45,6 +45,8 @@ namespace Avalonia.Controls static ContentControl() { ContentControlMixin.Attach(ContentProperty, x => x.LogicalChildren); + PseudoClass(ContentProperty, x => x != null, ":valid"); + PseudoClass(ContentProperty, x => x == null, ":invalid"); } /// diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs index c5d3313117..4d229390cb 100644 --- a/src/Avalonia.Controls/TreeViewItem.cs +++ b/src/Avalonia.Controls/TreeViewItem.cs @@ -32,24 +32,24 @@ namespace Avalonia.Controls ListBoxItem.IsSelectedProperty.AddOwner(); /// - /// Defines the property. + /// Defines the property. /// - public static readonly DirectProperty DepthProperty = + public static readonly DirectProperty LevelProperty = AvaloniaProperty.RegisterDirect( - nameof(Depth), o => o.Depth); + nameof(Level), o => o.Level); private static readonly ITemplate DefaultPanel = new FuncTemplate(() => new StackPanel()); private TreeView _treeView; private bool _isExpanded; - private int _depth; + private int _level; /// /// Initializes static members of the class. /// static TreeViewItem() - { + { SelectableMixin.Attach(IsSelectedProperty); FocusableProperty.OverrideDefaultValue(true); ItemsPanelProperty.OverrideDefaultValue(DefaultPanel); @@ -74,12 +74,12 @@ namespace Avalonia.Controls } /// - /// Gets or sets the depth of the item. + /// Gets the level/indentation of the item. /// - public int Depth + public int Level { - get { return _depth; } - private set { SetAndRaise(DepthProperty, ref _depth, value); } + get { return _level; } + private set { SetAndRaise(LevelProperty, ref _level, value); } } /// @@ -106,7 +106,7 @@ namespace Avalonia.Controls base.OnAttachedToLogicalTree(e); _treeView = this.GetLogicalAncestors().OfType().FirstOrDefault(); - Depth = this.CalculateDistanceFromLogicalParent() - 1; + Level = CalculateDistanceFromLogicalParent(this) - 1; if (ItemTemplate == null && _treeView?.ItemTemplate != null) { @@ -145,5 +145,18 @@ namespace Avalonia.Controls // Don't call base.OnKeyDown - let events bubble up to containing TreeView. } + + private static int CalculateDistanceFromLogicalParent(ILogical logical, int @default = -1) where T : class + { + var result = 0; + + while (logical != null && logical.GetType() != typeof(T)) + { + ++result; + logical = logical.LogicalParent; + } + + return logical != null ? result : @default; + } } } diff --git a/src/Avalonia.Styling/LogicalTree/LogicalExtensions.cs b/src/Avalonia.Styling/LogicalTree/LogicalExtensions.cs index 47550a876d..276ea6c060 100644 --- a/src/Avalonia.Styling/LogicalTree/LogicalExtensions.cs +++ b/src/Avalonia.Styling/LogicalTree/LogicalExtensions.cs @@ -87,20 +87,5 @@ namespace Avalonia.LogicalTree { return target.GetLogicalAncestors().Any(x => x == logical); } - - public static int CalculateDistanceFromLogicalParent(this ILogical logical, int @default = -1) where T : class - { - Contract.Requires(logical != null); - - var result = 0; - - while (logical != null && logical.GetType() != typeof(T)) - { - ++result; - logical = logical.LogicalParent; - } - - return logical != null ? result : @default; - } } } diff --git a/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs b/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs index 57d5ad9271..25f12ffa57 100644 --- a/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs +++ b/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs @@ -60,7 +60,7 @@ namespace Avalonia.Styling builder.Append(_property.Name); builder.Append('='); - builder.Append(_value); + builder.Append(_value ?? string.Empty); builder.Append(']'); _selectorString = builder.ToString(); @@ -78,11 +78,11 @@ namespace Avalonia.Styling } else if (subscribe) { - return new SelectorMatch(control.GetObservable(_property).Select(v => Equals(v, _value))); + return new SelectorMatch(control.GetObservable(_property).Select(v => Equals(v ?? string.Empty, _value))); } else { - return new SelectorMatch(control.GetValue(_property).Equals(_value)); + return new SelectorMatch((control.GetValue(_property) ?? string.Empty).Equals(_value)); } } diff --git a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml index 5aac023708..46767feca0 100644 --- a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml +++ b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml @@ -1,60 +1,56 @@ diff --git a/src/Avalonia.Themes.Default/CheckBox.xaml b/src/Avalonia.Themes.Default/CheckBox.xaml index 62a05a3525..3d14dd8e51 100644 --- a/src/Avalonia.Themes.Default/CheckBox.xaml +++ b/src/Avalonia.Themes.Default/CheckBox.xaml @@ -40,6 +40,9 @@ + @@ -58,4 +61,4 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/TreeViewItem.xaml b/src/Avalonia.Themes.Default/TreeViewItem.xaml index ada86d3535..b5e0e7a005 100644 --- a/src/Avalonia.Themes.Default/TreeViewItem.xaml +++ b/src/Avalonia.Themes.Default/TreeViewItem.xaml @@ -1,92 +1,92 @@ - + - + - + - + - + - + - + - + - + - +