diff --git a/packages.cake b/packages.cake index 84a04b7238..7ffc805ec8 100644 --- a/packages.cake +++ b/packages.cake @@ -120,6 +120,7 @@ public class Packages var SharpDXDirect3D9Version = packageVersions["SharpDX.Direct3D9"].FirstOrDefault().Item1; var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1; var SystemMemoryVersion = packageVersions["System.Memory"].FirstOrDefault().Item1; + var SystemComponentModelAnnotationsVersion = packageVersions["System.ComponentModel.Annotations"].FirstOrDefault().Item1; context.Information("Package: Serilog, version: {0}", SerilogVersion); context.Information("Package: System.Reactive, version: {0}", SystemReactiveVersion); @@ -238,6 +239,7 @@ public class Packages new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion }, new NuSpecDependency() { Id = "Avalonia.Remote.Protocol", Version = parameters.Version }, new NuSpecDependency() { Id = "System.Memory", Version = SystemMemoryVersion }, + new NuSpecDependency() { Id = "System.ComponentModel.Annotations", Version = SystemComponentModelAnnotationsVersion }, //.NET Core new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp2.0", Version = "4.3.0" }, new NuSpecDependency() { Id = "Microsoft.Extensions.DependencyModel", TargetFramework = "netcoreapp2.0", Version = "1.1.0" }, diff --git a/readme.md b/readme.md index 2b26cbdd1a..4fe76a2faf 100644 --- a/readme.md +++ b/readme.md @@ -18,7 +18,7 @@ Avalonia is a WPF-inspired cross-platform XAML-based UI framework providing a fl ## Getting Started -Avalonia [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio) contains project and control templates that will help you get started. After installing it, open "New Project" dialog in Visual Studio, choose "Avalonia" in "Visual C#" section, select "Avalonia .NET Core Application" and press OK (screenshot). Now you can write code and markup that will work on multiple platforms! +Avalonia [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio) contains project and control templates that will help you get started. After installing it, open "New Project" dialog in Visual Studio, choose "Avalonia" in "Visual C#" section, select "Avalonia .NET Core Application" and press OK (screenshot). Now you can write code and markup that will work on multiple platforms! Avalonia is delivered via NuGet package manager. You can find the packages here: ([stable(ish)](https://www.nuget.org/packages/Avalonia/), [nightly](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed)) @@ -52,7 +52,7 @@ Please read the [contribution guidelines](http://avaloniaui.net/contributing/con ### Contributors This project exists thanks to all the people who contribute. [[Contribute](http://avaloniaui.net/contributing/contributing)]. - + ### Backers diff --git a/samples/ControlCatalog/DecoratedWindow.xaml.cs b/samples/ControlCatalog/DecoratedWindow.xaml.cs index d28281e476..749f83c1ab 100644 --- a/samples/ControlCatalog/DecoratedWindow.xaml.cs +++ b/samples/ControlCatalog/DecoratedWindow.xaml.cs @@ -20,7 +20,7 @@ namespace ControlCatalog ctl.Cursor = new Cursor(cursor); ctl.PointerPressed += delegate { - PlatformImpl.BeginResizeDrag(edge); + PlatformImpl?.BeginResizeDrag(edge); }; } @@ -29,7 +29,7 @@ namespace ControlCatalog AvaloniaXamlLoader.Load(this); this.FindControl("TitleBar").PointerPressed += delegate { - PlatformImpl.BeginMoveDrag(); + PlatformImpl?.BeginMoveDrag(); }; SetupSide("Left", StandardCursorType.LeftSide, WindowEdge.West); SetupSide("Right", StandardCursorType.RightSide, WindowEdge.East); diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs index 351cbf5520..96fb9be8ac 100644 --- a/src/Avalonia.Controls/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox.cs @@ -2150,7 +2150,7 @@ namespace Avalonia.Controls } // Update the view - if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace) + if ((e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace) && e.OldItems != null) { for (int index = 0; index < e.OldItems.Count; index++) { diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs index 59281c5ad0..029e4dadc8 100644 --- a/src/Avalonia.Controls/Calendar/Calendar.cs +++ b/src/Avalonia.Controls/Calendar/Calendar.cs @@ -769,7 +769,7 @@ namespace Avalonia.Controls } private static void UpdateDisplayDate(Calendar c, DateTime addedDate, DateTime removedDate) { - Debug.Assert(c != null, "c should not be null!"); + Contract.Requires(c != null); // If DisplayDate < DisplayDateStart, DisplayDate = DisplayDateStart if (DateTime.Compare(addedDate, c.DisplayDateRangeStart) < 0) @@ -1016,8 +1016,6 @@ namespace Avalonia.Controls internal CalendarDayButton FindDayButtonFromDay(DateTime day) { - CalendarDayButton b; - DateTime? d; CalendarItem monthControl = MonthControl; // REMOVE_RTM: should be updated if we support MultiCalendar @@ -1028,14 +1026,16 @@ namespace Avalonia.Controls { for (int childIndex = ColumnsPerMonth; childIndex < count; childIndex++) { - b = monthControl.MonthView.Children[childIndex] as CalendarDayButton; - d = b.DataContext as DateTime?; - - if (d.HasValue) + if (monthControl.MonthView.Children[childIndex] is CalendarDayButton b) { - if (DateTimeHelper.CompareDays(d.Value, day) == 0) + var d = b.DataContext as DateTime?; + + if (d.HasValue) { - return b; + if (DateTimeHelper.CompareDays(d.Value, day) == 0) + { + return b; + } } } } @@ -1044,20 +1044,6 @@ namespace Avalonia.Controls return null; } - private void Calendar_SizeChanged(object sender, EventArgs e) - { - Debug.Assert(sender is Calendar, "The sender should be a Calendar!"); - - var size = Bounds.Size; - RectangleGeometry rg = new RectangleGeometry(); - rg.Rect = new Rect(0, 0, size.Width, size.Height); - - if (Root != null) - { - Root.Clip = rg; - } - } - private void OnSelectedMonthChanged(DateTime? selectedMonth) { if (selectedMonth.HasValue) @@ -1090,7 +1076,6 @@ namespace Avalonia.Controls internal void ResetStates() { - CalendarDayButton d; CalendarItem monthControl = MonthControl; int count = RowsPerMonth * ColumnsPerMonth; if (monthControl != null) @@ -1099,7 +1084,7 @@ namespace Avalonia.Controls { for (int childIndex = ColumnsPerMonth; childIndex < count; childIndex++) { - d = monthControl.MonthView.Children[childIndex] as CalendarDayButton; + var d = (CalendarDayButton)monthControl.MonthView.Children[childIndex]; d.IgnoreMouseOverState(); } } @@ -1190,8 +1175,6 @@ namespace Avalonia.Controls if (HoverEnd != null && HoverStart != null) { int startIndex, endIndex, i; - CalendarDayButton b; - DateTime? d; CalendarItem monthControl = MonthControl; // This assumes a contiguous set of dates: @@ -1201,18 +1184,20 @@ namespace Avalonia.Controls for (i = startIndex; i <= endIndex; i++) { - b = monthControl.MonthView.Children[i] as CalendarDayButton; - b.IsSelected = true; - d = b.DataContext as DateTime?; - - if (d.HasValue && DateTimeHelper.CompareDays(HoverEnd.Value, d.Value) == 0) + if (monthControl.MonthView.Children[i] is CalendarDayButton b) { - if (FocusButton != null) + b.IsSelected = true; + var d = b.DataContext as DateTime?; + + if (d.HasValue && DateTimeHelper.CompareDays(HoverEnd.Value, d.Value) == 0) { - FocusButton.IsCurrent = false; + if (FocusButton != null) + { + FocusButton.IsCurrent = false; + } + b.IsCurrent = HasFocusInternal; + FocusButton = b; } - b.IsCurrent = HasFocusInternal; - FocusButton = b; } } } @@ -1228,8 +1213,6 @@ namespace Avalonia.Controls if (HoverEnd != null && HoverStart != null) { CalendarItem monthControl = MonthControl; - CalendarDayButton b; - DateTime? d; if (HoverEndIndex != null && HoverStartIndex != null) { @@ -1240,15 +1223,17 @@ namespace Avalonia.Controls { for (i = startIndex; i <= endIndex; i++) { - b = monthControl.MonthView.Children[i] as CalendarDayButton; - d = b.DataContext as DateTime?; - - if (d.HasValue) + if (monthControl.MonthView.Children[i] is CalendarDayButton b) { - if (!SelectedDates.Contains(d.Value)) + var d = b.DataContext as DateTime?; + + if (d.HasValue) { - b.IsSelected = false; - } + if (!SelectedDates.Contains(d.Value)) + { + b.IsSelected = false; + } + } } } } @@ -1257,7 +1242,7 @@ namespace Avalonia.Controls // It is SingleRange for (i = startIndex; i <= endIndex; i++) { - (monthControl.MonthView.Children[i] as CalendarDayButton).IsSelected = false; + ((CalendarDayButton)monthControl.MonthView.Children[i]).IsSelected = false; } } } @@ -1628,16 +1613,15 @@ namespace Avalonia.Controls e.Handled = true; } } - internal void Calendar_KeyDown(object sender, KeyEventArgs e) - { - Calendar c = sender as Calendar; - Debug.Assert(c != null, "c should not be null!"); - if (!e.Handled && c.IsEnabled) + internal void Calendar_KeyDown(KeyEventArgs e) + { + if (!e.Handled && IsEnabled) { e.Handled = ProcessCalendarKey(e); } } + internal bool ProcessCalendarKey(KeyEventArgs e) { if (DisplayMode == CalendarMode.Month) @@ -1976,7 +1960,7 @@ namespace Avalonia.Controls } } } - private void Calendar_KeyUp(object sender, KeyEventArgs e) + private void Calendar_KeyUp(KeyEventArgs e) { if (!e.Handled && (e.Key == Key.LeftShift || e.Key == Key.RightShift)) { @@ -2083,6 +2067,9 @@ namespace Avalonia.Controls DisplayDateProperty.Changed.AddClassHandler(x => x.OnDisplayDateChanged); DisplayDateStartProperty.Changed.AddClassHandler(x => x.OnDisplayDateStartChanged); DisplayDateEndProperty.Changed.AddClassHandler(x => x.OnDisplayDateEndChanged); + KeyDownEvent.AddClassHandler(x => x.Calendar_KeyDown); + KeyUpEvent.AddClassHandler(x => x.Calendar_KeyUp); + } /// @@ -2122,10 +2109,6 @@ namespace Avalonia.Controls month.Owner = this; } } - - LayoutUpdated += Calendar_SizeChanged; - KeyDown += Calendar_KeyDown; - KeyUp += Calendar_KeyUp; } } diff --git a/src/Avalonia.Controls/Calendar/CalendarDateRange.cs b/src/Avalonia.Controls/Calendar/CalendarDateRange.cs index 273cda8c5b..718cc7142b 100644 --- a/src/Avalonia.Controls/Calendar/CalendarDateRange.cs +++ b/src/Avalonia.Controls/Calendar/CalendarDateRange.cs @@ -66,7 +66,7 @@ namespace Avalonia.Controls /// Inherited code: Requires comment 2. internal bool ContainsAny(CalendarDateRange range) { - Debug.Assert(range != null, "range should not be null!"); + Contract.Requires(range != null); int start = DateTime.Compare(Start, range.Start); diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs index 3432fa549d..b0cbd0be53 100644 --- a/src/Avalonia.Controls/Calendar/CalendarItem.cs +++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs @@ -517,7 +517,7 @@ namespace Avalonia.Controls.Primitives for (int childIndex = Calendar.ColumnsPerMonth; childIndex < count; childIndex++) { CalendarDayButton childButton = MonthView.Children[childIndex] as CalendarDayButton; - Debug.Assert(childButton != null, "childButton should not be null!"); + Contract.Requires(childButton != null); childButton.Index = childIndex; SetButtonState(childButton, dateToAdd); @@ -554,7 +554,7 @@ namespace Avalonia.Controls.Primitives for (int i = childIndex; i < count; i++) { childButton = MonthView.Children[i] as CalendarDayButton; - Debug.Assert(childButton != null, "childButton should not be null!"); + Contract.Requires(childButton != null); // button needs a content to occupy the necessary space // for the content presenter childButton.Content = i.ToString(DateTimeHelper.GetCurrentDateFormat()); @@ -650,7 +650,7 @@ namespace Avalonia.Controls.Primitives foreach (object child in YearView.Children) { CalendarButton childButton = child as CalendarButton; - Debug.Assert(childButton != null, "childButton should not be null!"); + Contract.Requires(childButton != null); // There should be no time component. Time is 12:00 AM DateTime day = new DateTime(_currentMonth.Year, count + 1, 1); childButton.DataContext = day; @@ -746,7 +746,7 @@ namespace Avalonia.Controls.Primitives foreach (object child in YearView.Children) { CalendarButton childButton = child as CalendarButton; - Debug.Assert(childButton != null, "childButton should not be null!"); + Contract.Requires(childButton != null); year = decade + count; if (year <= DateTime.MaxValue.Year && year >= DateTime.MinValue.Year) @@ -826,7 +826,7 @@ namespace Avalonia.Controls.Primitives { Owner.Focus(); } - Button b = sender as Button; + Button b = (Button)sender; DateTime d; if (b.IsEnabled) @@ -863,7 +863,7 @@ namespace Avalonia.Controls.Primitives Owner.Focus(); } - Button b = sender as Button; + Button b = (Button)sender; if (b.IsEnabled) { Owner.OnPreviousClick(); @@ -878,7 +878,7 @@ namespace Avalonia.Controls.Primitives { Owner.Focus(); } - Button b = sender as Button; + Button b = (Button)sender; if (b.IsEnabled) { @@ -891,8 +891,7 @@ namespace Avalonia.Controls.Primitives { if (Owner != null) { - CalendarDayButton b = sender as CalendarDayButton; - if (_isMouseLeftButtonDown && b != null && b.IsEnabled && !b.IsBlackout) + if (_isMouseLeftButtonDown && sender is CalendarDayButton b && b.IsEnabled && !b.IsBlackout) { // Update the states of all buttons to be selected starting // from HoverStart to b @@ -918,7 +917,7 @@ namespace Avalonia.Controls.Primitives Debug.Assert(b.DataContext != null, "The DataContext should not be null!"); Owner.UnHighlightDays(); Owner.HoverEndIndex = b.Index; - Owner.HoverEnd = (DateTime)b.DataContext; + Owner.HoverEnd = (DateTime?)b.DataContext; // Update the States of the buttons Owner.HighlightDays(); return; @@ -931,7 +930,7 @@ namespace Avalonia.Controls.Primitives { if (_isMouseLeftButtonDown) { - CalendarDayButton b = sender as CalendarDayButton; + CalendarDayButton b = (CalendarDayButton)sender; // The button is in Pressed state. Change the state to normal. if (e.Device.Captured == b) e.Device.Capture(null); @@ -973,7 +972,7 @@ namespace Avalonia.Controls.Primitives if (b.IsEnabled && !b.IsBlackout) { DateTime selectedDate = (DateTime)b.DataContext; - Debug.Assert(selectedDate != null, "selectedDate should not be null!"); + Contract.Requires(selectedDate != null); _isMouseLeftButtonDown = true; // null check is added for unit tests if (e != null) @@ -1149,7 +1148,7 @@ namespace Avalonia.Controls.Primitives if (_isControlPressed && Owner.SelectionMode == CalendarSelectionMode.MultipleRange) { CalendarDayButton b = sender as CalendarDayButton; - Debug.Assert(b != null, "The sender should be a non-null CalendarDayButton!"); + Contract.Requires(b != null); if (b.IsSelected) { @@ -1169,7 +1168,7 @@ namespace Avalonia.Controls.Primitives private void Month_CalendarButtonMouseDown(object sender, PointerPressedEventArgs e) { CalendarButton b = sender as CalendarButton; - Debug.Assert(b != null, "The sender should be a non-null CalendarDayButton!"); + Contract.Requires(b != null); _isMouseLeftButtonDownYearView = true; @@ -1208,7 +1207,7 @@ namespace Avalonia.Controls.Primitives if (_isMouseLeftButtonDownYearView) { CalendarButton b = sender as CalendarButton; - Debug.Assert(b != null, "The sender should be a non-null CalendarDayButton!"); + Contract.Requires(b != null); UpdateYearViewSelection(b); } } @@ -1217,7 +1216,7 @@ namespace Avalonia.Controls.Primitives { if (_isMouseLeftButtonDownYearView) { - CalendarButton b = sender as CalendarButton; + CalendarButton b = (CalendarButton)sender; // The button is in Pressed state. Change the state to normal. if (e.Device.Captured == b) e.Device.Capture(null); diff --git a/src/Avalonia.Controls/Calendar/DatePicker.cs b/src/Avalonia.Controls/Calendar/DatePicker.cs index 418ef50b2c..08608ad359 100644 --- a/src/Avalonia.Controls/Calendar/DatePicker.cs +++ b/src/Avalonia.Controls/Calendar/DatePicker.cs @@ -842,7 +842,7 @@ namespace Avalonia.Controls private void Calendar_KeyDown(object sender, KeyEventArgs e) { Calendar c = sender as Calendar; - Debug.Assert(c != null, "The Calendar should not be null!"); + Contract.Requires(c != null); if (!e.Handled && (e.Key == Key.Enter || e.Key == Key.Space || e.Key == Key.Escape) && c.DisplayMode == CalendarMode.Month) { diff --git a/src/Avalonia.Controls/Design.cs b/src/Avalonia.Controls/Design.cs index ce52891749..894240a09f 100644 --- a/src/Avalonia.Controls/Design.cs +++ b/src/Avalonia.Controls/Design.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; +using Avalonia.Styling; namespace Avalonia.Controls { @@ -45,23 +46,18 @@ namespace Avalonia.Controls { return control.GetValue(DataContextProperty); } - - static readonly ConditionalWeakTable Substitutes = new ConditionalWeakTable(); - + public static readonly AttachedProperty PreviewWithProperty = AvaloniaProperty - .RegisterAttached("PreviewWith", typeof (Design)); + .RegisterAttached("PreviewWith", typeof (Design)); - public static void SetPreviewWith(object target, Control control) + public static void SetPreviewWith(Style target, Control control) { - Substitutes.Remove(target); - Substitutes.Add(target, control); + target.SetValue(PreviewWithProperty, control); } - public static Control GetPreviewWith(object target) + public static Control GetPreviewWith(Style target) { - Control rv; - Substitutes.TryGetValue(target, out rv); - return rv; + return target.GetValue(PreviewWithProperty); } public static void ApplyDesignModeProperties(Control target, Control source) diff --git a/src/Avalonia.Controls/DropDownItem.cs b/src/Avalonia.Controls/DropDownItem.cs index 3fd80c4562..fb465e93ec 100644 --- a/src/Avalonia.Controls/DropDownItem.cs +++ b/src/Avalonia.Controls/DropDownItem.cs @@ -22,14 +22,13 @@ namespace Avalonia.Controls static DropDownItem() { FocusableProperty.OverrideDefaultValue(true); - IsFocusedProperty.Changed.Subscribe(x => - { - var sender = x.Sender as IControl; + } - if (sender != null) - { - ((IPseudoClasses)sender.Classes).Set(":selected", (bool)x.NewValue); - } + public DropDownItem() + { + this.GetObservable(DropDownItem.IsFocusedProperty).Subscribe(focused => + { + PseudoClasses.Set(":selected", focused); }); } diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs index cd2da692ba..4db16c71a5 100644 --- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs +++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs @@ -57,7 +57,7 @@ namespace Avalonia.Controls.Embedding.Offscreen Type IStyleable.StyleKey => typeof(EmbeddableControlRoot); public void Dispose() { - PlatformImpl.Dispose(); + PlatformImpl?.Dispose(); } } } diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs index e136efe2a9..52e09aba45 100644 --- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs +++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs @@ -62,7 +62,7 @@ namespace Avalonia.Platform RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects); var tl = root.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); - tl.PlatformImpl.Input(rawEvent); + tl.PlatformImpl?.Input(rawEvent); var effect = GetPreferredEffect(rawEvent.Effects & _allowedEffects, modifiers); UpdateCursor(root, effect); diff --git a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs index c6ef5a14e9..e438843078 100644 --- a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs +++ b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs @@ -106,7 +106,6 @@ namespace Avalonia.Controls.Presenters /// protected override void ItemsChanged(NotifyCollectionChangedEventArgs e) { - // TODO: Handle items changing. switch (e.Action) { case NotifyCollectionChangedAction.Remove: @@ -115,9 +114,35 @@ namespace Avalonia.Controls.Presenters var generator = ItemContainerGenerator; var containers = generator.RemoveRange(e.OldStartingIndex, e.OldItems.Count); Panel.Children.RemoveAll(containers.Select(x => x.ContainerControl)); + + MoveToPage(-1, SelectedIndex); } break; + case NotifyCollectionChangedAction.Reset: + { + var generator = ItemContainerGenerator; + var containers = generator.Containers.ToList(); + generator.Clear(); + Panel.Children.RemoveAll(containers.Select(x => x.ContainerControl)); + + var newIndex = SelectedIndex; + + if(SelectedIndex < 0) + { + if(Items != null && Items.Count() > 0) + { + newIndex = 0; + } + else + { + newIndex = -1; + } + } + + MoveToPage(-1, newIndex); + } + break; } } diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 874d2a3229..2ea9319194 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -68,6 +68,10 @@ namespace Avalonia.Controls public static readonly StyledProperty UseFloatingWatermarkProperty = AvaloniaProperty.Register(nameof(UseFloatingWatermark)); + public static readonly DirectProperty NewLineProperty = + AvaloniaProperty.RegisterDirect(nameof(NewLine), + textbox => textbox.NewLine, (textbox, newline) => textbox.NewLine = newline); + struct UndoRedoState : IEquatable { public string Text { get; } @@ -90,6 +94,7 @@ namespace Avalonia.Controls private UndoRedoHelper _undoRedoHelper; private bool _isUndoingRedoing; private bool _ignoreTextChanges; + private string _newLine = Environment.NewLine; private static readonly string[] invalidCharacters = new String[1] { "\u007f" }; static TextBox() @@ -241,6 +246,15 @@ namespace Avalonia.Controls set { SetValue(TextWrappingProperty, value); } } + /// + /// Gets or sets which characters are inserted when Enter is pressed. Default: + /// + public string NewLine + { + get { return _newLine; } + set { SetAndRaise(NewLineProperty, ref _newLine, value); } + } + protected override void OnTemplateApplied(TemplateAppliedEventArgs e) { _presenter = e.NameScope.Get("PART_TextPresenter"); @@ -498,7 +512,7 @@ namespace Avalonia.Controls case Key.Enter: if (AcceptsReturn) { - HandleTextInput("\r\n"); + HandleTextInput(NewLine); handled = true; } diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index c4a09ac043..3cbfdbd657 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -145,11 +145,9 @@ namespace Avalonia.Controls : base(impl) { impl.Closing = HandleClosing; + impl.WindowStateChanged = HandleWindowStateChanged; _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size); Screens = new Screens(PlatformImpl?.Screen); - - if (PlatformImpl != null) - PlatformImpl.WindowStateChanged = s => WindowState = s; } /// @@ -318,6 +316,20 @@ namespace Avalonia.Controls return args.Cancel; } + protected virtual void HandleWindowStateChanged(WindowState state) + { + WindowState = state; + + if (state == WindowState.Minimized) + { + Renderer.Stop(); + } + else + { + Renderer.Start(); + } + } + /// /// Hides the window but does not close it. /// diff --git a/src/Avalonia.DesignerSupport/DesignWindowLoader.cs b/src/Avalonia.DesignerSupport/DesignWindowLoader.cs index d1958ac9bf..6dca479d38 100644 --- a/src/Avalonia.DesignerSupport/DesignWindowLoader.cs +++ b/src/Avalonia.DesignerSupport/DesignWindowLoader.cs @@ -36,8 +36,7 @@ namespace Avalonia.DesignerSupport var styles = loaded as Styles; if (styles != null) { - var substitute = Design.GetPreviewWith(styles) ?? - styles.Select(Design.GetPreviewWith).FirstOrDefault(s => s != null); + var substitute = styles.OfType