Browse Source

Merge branch 'master' into scenegraph

scenegraph-after-breakage
Steven Kirk 9 years ago
committed by GitHub
parent
commit
2fcafe15df
  1. 1
      Avalonia.sln.DotSettings
  2. 1
      appveyor.yml
  3. 39
      build.cake
  4. 2
      samples/interop/Direct3DInteropSample/MainWindow.cs
  5. 11
      src/Avalonia.Base/AvaloniaObject.cs
  6. 25
      src/Avalonia.Base/Collections/AvaloniaDictionary.cs
  7. 2
      src/Avalonia.Base/PriorityValue.cs
  8. 2
      src/Avalonia.Controls/Button.cs
  9. 2
      src/Avalonia.Controls/Control.cs
  10. 12
      src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
  11. 2
      src/Avalonia.Controls/ItemsControl.cs
  12. 7
      src/Avalonia.Controls/Primitives/PopupRoot.cs
  13. 7
      src/Avalonia.Controls/TextBox.cs
  14. 35
      src/Avalonia.Controls/TopLevel.cs
  15. 28
      src/Avalonia.Controls/Window.cs
  16. 34
      src/Avalonia.Controls/WindowBase.cs
  17. 4
      src/Avalonia.DesignerSupport/DesignerAssist.cs
  18. 8
      src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs
  19. 2
      src/Avalonia.Styling/Controls/NameScope.cs
  20. 2
      src/Avalonia.Visuals/Rendering/ZIndexComparer.cs
  21. 1
      src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs
  22. 1
      src/Gtk/Avalonia.Gtk3/SystemDialogs.cs
  23. 2
      src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorParser.cs
  24. 4
      src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs

1
Avalonia.sln.DotSettings

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=3E53A01A_002DB331_002D47F3_002DB828_002D4A5717E77A24_002Fd_003Aglass/@EntryIndexedValue">ExplicitlyExcluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=6417B24E_002D49C2_002D4985_002D8DB2_002D3AB9D898EC91/@EntryIndexedValue">ExplicitlyExcluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=6417B24E_002D49C2_002D4985_002D8DB2_002D3AB9D898EC91/@EntryIndexedValue">ExplicitlyExcluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=E3A1060B_002D50D0_002D44E8_002D88B6_002DF44EF2E5BD72_002Ff_003Ahtml_002Ehtm/@EntryIndexedValue">ExplicitlyExcluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=E3A1060B_002D50D0_002D44E8_002D88B6_002DF44EF2E5BD72_002Ff_003Ahtml_002Ehtm/@EntryIndexedValue">ExplicitlyExcluded</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">HINT</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">HINT</s:String>

1
appveyor.yml

@ -35,6 +35,7 @@ test: off
artifacts: artifacts:
- path: artifacts\nuget\*.nupkg - path: artifacts\nuget\*.nupkg
- path: artifacts\zip\*.zip - path: artifacts\zip\*.zip
- path: artifacts\inspectcode.xml
cache: cache:
- gtk-sharp-2.12.26.msi - gtk-sharp-2.12.26.msi
- dotnet-1.0.1.exe - dotnet-1.0.1.exe

39
build.cake

@ -5,7 +5,8 @@
#addin "nuget:?package=Polly&version=4.2.0" #addin "nuget:?package=Polly&version=4.2.0"
#addin "nuget:?package=NuGet.Core&version=2.12.0" #addin "nuget:?package=NuGet.Core&version=2.12.0"
#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease" #tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease"
#tool "nuget:?package=JetBrains.dotMemoryUnit&version=2.1.20150828.125449" #tool "nuget:?package=JetBrains.dotMemoryUnit&version=2.3.20160517.113140"
#tool "JetBrains.ReSharper.CommandLineTools"
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// TOOLS // TOOLS
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -104,7 +105,7 @@ Task("Restore-NuGet-Packages")
.Does(() => .Does(() =>
{ {
var maxRetryCount = 5; var maxRetryCount = 5;
var toolTimeout = 1d; var toolTimeout = 2d;
Policy Policy
.Handle<Exception>() .Handle<Exception>()
.Retry(maxRetryCount, (exception, retryCount, context) => { .Retry(maxRetryCount, (exception, retryCount, context) => {
@ -287,6 +288,7 @@ Task("Zip-Files")
Task("Create-NuGet-Packages") Task("Create-NuGet-Packages")
.IsDependentOn("Run-Unit-Tests") .IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Inspect")
.Does(() => .Does(() =>
{ {
foreach(var nuspec in packages.NuspecNuGetSettings) foreach(var nuspec in packages.NuspecNuGetSettings)
@ -363,6 +365,39 @@ Task("Publish-NuGet")
Information("Publish-NuGet Task failed, but continuing with next Task..."); Information("Publish-NuGet Task failed, but continuing with next Task...");
}); });
Task("Inspect")
.WithCriteria(parameters.IsRunningOnWindows)
.IsDependentOn("Restore-NuGet-Packages")
.Does(() =>
{
var badIssues = new []{"PossibleNullReferenceException"};
var whitelist = new []{"tests", "src\\android", "src\\ios",
"src\\windows\\avalonia.designer", "src\\avalonia.htmlrenderer\\external"};
Information("Running code inspections");
StartProcess("tools\\JetBrains.ReSharper.CommandLineTools\\tools\\inspectcode.exe",
new ProcessSettings{ Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln" });
Information("Analyzing report");
var doc = XDocument.Parse(System.IO.File.ReadAllText("artifacts\\inspectcode.xml"));
var failBuild = false;
foreach(var xml in doc.Descendants("Issue"))
{
var typeId = xml.Attribute("TypeId").Value.ToString();
if(badIssues.Contains(typeId))
{
var file = xml.Attribute("File").Value.ToString().ToLower();
if(whitelist.Any(wh => file.StartsWith(wh)))
continue;
var line = xml.Attribute("Line").Value.ToString();
Error(typeId + " - " + file + " on line " + line);
failBuild = true;
}
}
if(failBuild)
throw new Exception("Issues found");
});
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// TARGETS // TARGETS
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

2
samples/interop/Direct3DInteropSample/MainWindow.cs

@ -58,7 +58,7 @@ namespace Direct3DInteropSample
new ModeDescription((int)ClientSize.Width, (int)ClientSize.Height, new ModeDescription((int)ClientSize.Width, (int)ClientSize.Height,
new Rational(60, 1), Format.R8G8B8A8_UNorm), new Rational(60, 1), Format.R8G8B8A8_UNorm),
IsWindowed = true, IsWindowed = true,
OutputHandle = PlatformImpl.Handle.Handle, OutputHandle = PlatformImpl?.Handle.Handle ?? IntPtr.Zero,
SampleDescription = new SampleDescription(1, 0), SampleDescription = new SampleDescription(1, 0),
SwapEffect = SwapEffect.Discard, SwapEffect = SwapEffect.Discard,
Usage = Usage.RenderTargetOutput Usage = Usage.RenderTargetOutput

11
src/Avalonia.Base/AvaloniaObject.cs

@ -622,14 +622,9 @@ namespace Avalonia
/// <returns>The default value.</returns> /// <returns>The default value.</returns>
private object GetDefaultValue(AvaloniaProperty property) private object GetDefaultValue(AvaloniaProperty property)
{ {
if (property.Inherits && _inheritanceParent != null) if (property.Inherits && _inheritanceParent is AvaloniaObject aobj)
{ return aobj.GetValueInternal(property);
return (_inheritanceParent as AvaloniaObject).GetValueInternal(property); return ((IStyledPropertyAccessor) property).GetDefaultValue(GetType());
}
else
{
return ((IStyledPropertyAccessor)property).GetDefaultValue(GetType());
}
} }
/// <summary> /// <summary>

25
src/Avalonia.Base/Collections/AvaloniaDictionary.cs

@ -103,11 +103,9 @@ namespace Avalonia.Collections
_inner = new Dictionary<TKey, TValue>(); _inner = new Dictionary<TKey, TValue>();
if (PropertyChanged != null) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
{ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[]"));
PropertyChanged(this, new PropertyChangedEventArgs("Count"));
PropertyChanged(this, new PropertyChangedEventArgs($"Item[]"));
}
if (CollectionChanged != null) if (CollectionChanged != null)
{ {
@ -144,12 +142,9 @@ namespace Avalonia.Collections
if (_inner.TryGetValue(key, out value)) if (_inner.TryGetValue(key, out value))
{ {
if (PropertyChanged != null) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
{ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[{key}]"));
PropertyChanged(this, new PropertyChangedEventArgs("Count"));
PropertyChanged(this, new PropertyChangedEventArgs($"Item[{key}]"));
}
if (CollectionChanged != null) if (CollectionChanged != null)
{ {
var e = new NotifyCollectionChangedEventArgs( var e = new NotifyCollectionChangedEventArgs(
@ -199,11 +194,9 @@ namespace Avalonia.Collections
private void NotifyAdd(TKey key, TValue value) private void NotifyAdd(TKey key, TValue value)
{ {
if (PropertyChanged != null) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
{ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[{key}]"));
PropertyChanged(this, new PropertyChangedEventArgs("Count"));
PropertyChanged(this, new PropertyChangedEventArgs($"Item[{key}]"));
}
if (CollectionChanged != null) if (CollectionChanged != null)
{ {

2
src/Avalonia.Base/PriorityValue.cs

@ -285,7 +285,7 @@ namespace Avalonia
Property.Name, Property.Name,
_valueType, _valueType,
value, value,
value.GetType()); value?.GetType());
} }
} }
} }

2
src/Avalonia.Controls/Button.cs

@ -275,7 +275,7 @@ namespace Avalonia.Controls
{ {
var button = e.Sender as Button; var button = e.Sender as Button;
var isDefault = (bool)e.NewValue; var isDefault = (bool)e.NewValue;
var inputRoot = button.VisualRoot as IInputElement; var inputRoot = button?.VisualRoot as IInputElement;
if (inputRoot != null) if (inputRoot != null)
{ {

2
src/Avalonia.Controls/Control.cs

@ -645,7 +645,7 @@ namespace Avalonia.Controls
if (_focusAdorner != null) if (_focusAdorner != null)
{ {
var adornerLayer = _focusAdorner.Parent as Panel; var adornerLayer = (IPanel)_focusAdorner.Parent;
adornerLayer.Children.Remove(_focusAdorner); adornerLayer.Children.Remove(_focusAdorner);
_focusAdorner = null; _focusAdorner = null;
} }

12
src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs

@ -4,6 +4,7 @@ using Avalonia.Input;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Styling; using Avalonia.Styling;
using JetBrains.Annotations;
namespace Avalonia.Controls.Embedding namespace Avalonia.Controls.Embedding
{ {
@ -18,6 +19,7 @@ namespace Avalonia.Controls.Embedding
{ {
} }
[CanBeNull]
public new IEmbeddableWindowImpl PlatformImpl => (IEmbeddableWindowImpl) base.PlatformImpl; public new IEmbeddableWindowImpl PlatformImpl => (IEmbeddableWindowImpl) base.PlatformImpl;
public void Prepare() public void Prepare()
@ -39,8 +41,9 @@ namespace Avalonia.Controls.Embedding
protected override Size MeasureOverride(Size availableSize) protected override Size MeasureOverride(Size availableSize)
{ {
base.MeasureOverride(PlatformImpl.ClientSize); var cs = PlatformImpl?.ClientSize ?? default(Size);
return PlatformImpl.ClientSize; base.MeasureOverride(cs);
return cs;
} }
private readonly NameScope _nameScope = new NameScope(); private readonly NameScope _nameScope = new NameScope();
@ -63,9 +66,6 @@ namespace Avalonia.Controls.Embedding
public void Unregister(string name) => _nameScope.Unregister(name); public void Unregister(string name) => _nameScope.Unregister(name);
Type IStyleable.StyleKey => typeof(EmbeddableControlRoot); Type IStyleable.StyleKey => typeof(EmbeddableControlRoot);
public void Dispose() public void Dispose() => PlatformImpl?.Dispose();
{
PlatformImpl.Dispose();
}
} }
} }

2
src/Avalonia.Controls/ItemsControl.cs

@ -354,7 +354,7 @@ namespace Avalonia.Controls
} }
var collection = sender as ICollection; var collection = sender as ICollection;
PseudoClasses.Set(":empty", collection.Count == 0); PseudoClasses.Set(":empty", collection == null || collection.Count == 0);
} }
/// <summary> /// <summary>

7
src/Avalonia.Controls/Primitives/PopupRoot.cs

@ -9,6 +9,7 @@ using Avalonia.Layout;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using JetBrains.Annotations;
namespace Avalonia.Controls.Primitives namespace Avalonia.Controls.Primitives
{ {
@ -49,6 +50,7 @@ namespace Avalonia.Controls.Primitives
/// <summary> /// <summary>
/// Gets the platform-specific window implementation. /// Gets the platform-specific window implementation.
/// </summary> /// </summary>
[CanBeNull]
public new IPopupImpl PlatformImpl => (IPopupImpl)base.PlatformImpl; public new IPopupImpl PlatformImpl => (IPopupImpl)base.PlatformImpl;
/// <summary> /// <summary>
@ -65,10 +67,7 @@ namespace Avalonia.Controls.Primitives
IVisual IHostedVisualTreeRoot.Host => Parent; IVisual IHostedVisualTreeRoot.Host => Parent;
/// <inheritdoc/> /// <inheritdoc/>
public void Dispose() public void Dispose() => PlatformImpl?.Dispose();
{
this.PlatformImpl.Dispose();
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnTemplateApplied(TemplateAppliedEventArgs e) protected override void OnTemplateApplied(TemplateAppliedEventArgs e)

7
src/Avalonia.Controls/TextBox.cs

@ -720,7 +720,7 @@ namespace Avalonia.Controls
if (pos < text.Length) if (pos < text.Length)
{ {
--pos; --pos;
if (pos > 0 && Text[pos - 1] == '\r' && Text[pos] == '\n') if (pos > 0 && text[pos - 1] == '\r' && text[pos] == '\n')
{ {
--pos; --pos;
} }
@ -771,6 +771,9 @@ namespace Avalonia.Controls
private string GetSelection() private string GetSelection()
{ {
var text = Text;
if (string.IsNullOrEmpty(text))
return "";
var selectionStart = SelectionStart; var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd; var selectionEnd = SelectionEnd;
var start = Math.Min(selectionStart, selectionEnd); var start = Math.Min(selectionStart, selectionEnd);
@ -779,7 +782,7 @@ namespace Avalonia.Controls
{ {
return ""; return "";
} }
return Text.Substring(start, end - start); return text.Substring(start, end - start);
} }
private int GetLine(int caretIndex, IList<FormattedTextLine> lines) private int GetLine(int caretIndex, IList<FormattedTextLine> lines)

35
src/Avalonia.Controls/TopLevel.cs

@ -14,6 +14,7 @@ using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using JetBrains.Annotations;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -92,25 +93,25 @@ namespace Avalonia.Controls
var rendererFactory = TryGetService<IRendererFactory>(dependencyResolver); var rendererFactory = TryGetService<IRendererFactory>(dependencyResolver);
Renderer = rendererFactory?.CreateRenderer(this, renderLoop); Renderer = rendererFactory?.CreateRenderer(this, renderLoop);
PlatformImpl.SetInputRoot(this); impl.SetInputRoot(this);
PlatformImpl.Closed = HandleClosed; impl.Closed = HandleClosed;
PlatformImpl.Input = HandleInput; impl.Input = HandleInput;
PlatformImpl.Paint = HandlePaint; impl.Paint = HandlePaint;
PlatformImpl.Resized = HandleResized; impl.Resized = HandleResized;
PlatformImpl.ScalingChanged = HandleScalingChanged; impl.ScalingChanged = HandleScalingChanged;
_keyboardNavigationHandler?.SetOwner(this); _keyboardNavigationHandler?.SetOwner(this);
_accessKeyHandler?.SetOwner(this); _accessKeyHandler?.SetOwner(this);
styler?.ApplyStyles(this); styler?.ApplyStyles(this);
ClientSize = PlatformImpl.ClientSize; ClientSize = impl.ClientSize;
this.GetObservable(PointerOverElementProperty) this.GetObservable(PointerOverElementProperty)
.Select( .Select(
x => (x as InputElement)?.GetObservable(CursorProperty) ?? Observable.Empty<Cursor>()) x => (x as InputElement)?.GetObservable(CursorProperty) ?? Observable.Empty<Cursor>())
.Switch().Subscribe(cursor => PlatformImpl.SetCursor(cursor?.PlatformCursor)); .Switch().Subscribe(cursor => PlatformImpl?.SetCursor(cursor?.PlatformCursor));
if (_applicationLifecycle != null) if (_applicationLifecycle != null)
{ {
@ -135,10 +136,8 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Gets the platform-specific window implementation. /// Gets the platform-specific window implementation.
/// </summary> /// </summary>
public ITopLevelImpl PlatformImpl [CanBeNull]
{ public ITopLevelImpl PlatformImpl { get; private set; }
get;
}
/// <summary> /// <summary>
/// Gets the renderer for the window. /// Gets the renderer for the window.
@ -177,7 +176,7 @@ namespace Avalonia.Controls
Size ILayoutRoot.MaxClientSize => Size.Infinity; Size ILayoutRoot.MaxClientSize => Size.Infinity;
/// <inheritdoc/> /// <inheritdoc/>
double ILayoutRoot.LayoutScaling => PlatformImpl.Scaling; double ILayoutRoot.LayoutScaling => PlatformImpl?.Scaling ?? 1;
/// <inheritdoc/> /// <inheritdoc/>
double IRenderRoot.RenderScaling => PlatformImpl.Scaling; double IRenderRoot.RenderScaling => PlatformImpl.Scaling;
@ -192,25 +191,27 @@ namespace Avalonia.Controls
/// <inheritdoc/> /// <inheritdoc/>
protected virtual IRenderTarget CreateRenderTarget() protected virtual IRenderTarget CreateRenderTarget()
{ {
if(PlatformImpl == null)
throw new InvalidOperationException("Cann't create render target, PlatformImpl is null (might be already disposed)");
return _renderInterface.CreateRenderTarget(PlatformImpl.Surfaces); return _renderInterface.CreateRenderTarget(PlatformImpl.Surfaces);
} }
/// <inheritdoc/> /// <inheritdoc/>
void IRenderRoot.Invalidate(Rect rect) void IRenderRoot.Invalidate(Rect rect)
{ {
PlatformImpl.Invalidate(rect); PlatformImpl?.Invalidate(rect);
} }
/// <inheritdoc/> /// <inheritdoc/>
Point IRenderRoot.PointToClient(Point p) Point IRenderRoot.PointToClient(Point p)
{ {
return PlatformImpl.PointToClient(p); return PlatformImpl?.PointToClient(p) ?? default(Point);
} }
/// <inheritdoc/> /// <inheritdoc/>
Point IRenderRoot.PointToScreen(Point p) Point IRenderRoot.PointToScreen(Point p)
{ {
return PlatformImpl.PointToScreen(p); return PlatformImpl?.PointToScreen(p) ?? default(Point);
} }
/// <summary> /// <summary>
@ -227,6 +228,8 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
protected virtual void HandleClosed() protected virtual void HandleClosed()
{ {
PlatformImpl = null;
Closed?.Invoke(this, EventArgs.Empty); Closed?.Invoke(this, EventArgs.Empty);
Renderer?.Dispose(); Renderer?.Dispose();
Renderer = null; Renderer = null;

28
src/Avalonia.Controls/Window.cs

@ -12,6 +12,7 @@ using Avalonia.Platform;
using Avalonia.Styling; using Avalonia.Styling;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -87,11 +88,11 @@ namespace Avalonia.Controls
static Window() static Window()
{ {
BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White); BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White);
TitleProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetTitle((string)e.NewValue)); TitleProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetTitle((string)e.NewValue));
HasSystemDecorationsProperty.Changed.AddClassHandler<Window>( HasSystemDecorationsProperty.Changed.AddClassHandler<Window>(
(s, e) => s.PlatformImpl.SetSystemDecorations((bool) e.NewValue)); (s, e) => s.PlatformImpl?.SetSystemDecorations((bool) e.NewValue));
IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetIcon(((WindowIcon)e.NewValue).PlatformImpl)); IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
} }
/// <summary> /// <summary>
@ -109,7 +110,7 @@ namespace Avalonia.Controls
public Window(IWindowImpl impl) public Window(IWindowImpl impl)
: base(impl) : base(impl)
{ {
_maxPlatformClientSize = this.PlatformImpl.MaxClientSize; _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -129,6 +130,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Gets the platform-specific window implementation. /// Gets the platform-specific window implementation.
/// </summary> /// </summary>
[CanBeNull]
public new IWindowImpl PlatformImpl => (IWindowImpl)base.PlatformImpl; public new IWindowImpl PlatformImpl => (IWindowImpl)base.PlatformImpl;
/// <summary> /// <summary>
@ -164,8 +166,12 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public WindowState WindowState public WindowState WindowState
{ {
get { return this.PlatformImpl.WindowState; } get { return PlatformImpl?.WindowState ?? WindowState.Normal; }
set { this.PlatformImpl.WindowState = value; } set
{
if (PlatformImpl != null)
PlatformImpl.WindowState = value;
}
} }
/// <summary> /// <summary>
@ -189,7 +195,7 @@ namespace Avalonia.Controls
public void Close() public void Close()
{ {
s_windows.Remove(this); s_windows.Remove(this);
PlatformImpl.Dispose(); PlatformImpl?.Dispose();
IsVisible = false; IsVisible = false;
} }
@ -221,7 +227,7 @@ namespace Avalonia.Controls
{ {
using (BeginAutoSizing()) using (BeginAutoSizing())
{ {
PlatformImpl.Hide(); PlatformImpl?.Hide();
} }
IsVisible = false; IsVisible = false;
@ -240,7 +246,7 @@ namespace Avalonia.Controls
using (BeginAutoSizing()) using (BeginAutoSizing())
{ {
PlatformImpl.Show(); PlatformImpl?.Show();
} }
} }
@ -278,7 +284,7 @@ namespace Avalonia.Controls
var activated = affectedWindows.Where(w => w.IsActive).FirstOrDefault(); var activated = affectedWindows.Where(w => w.IsActive).FirstOrDefault();
SetIsEnabled(affectedWindows, false); SetIsEnabled(affectedWindows, false);
var modal = PlatformImpl.ShowDialog(); var modal = PlatformImpl?.ShowDialog();
var result = new TaskCompletionSource<TResult>(); var result = new TaskCompletionSource<TResult>();
Observable.FromEventPattern<EventHandler, EventArgs>( Observable.FromEventPattern<EventHandler, EventArgs>(
@ -287,7 +293,7 @@ namespace Avalonia.Controls
.Take(1) .Take(1)
.Subscribe(_ => .Subscribe(_ =>
{ {
modal.Dispose(); modal?.Dispose();
SetIsEnabled(affectedWindows, true); SetIsEnabled(affectedWindows, true);
activated?.Activate(); activated?.Activate();
result.SetResult((TResult)_dialogResult); result.SetResult((TResult)_dialogResult);

34
src/Avalonia.Controls/WindowBase.cs

@ -9,6 +9,7 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.Platform; using Avalonia.Platform;
using JetBrains.Annotations;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -43,10 +44,10 @@ namespace Avalonia.Controls
public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(impl, dependencyResolver) public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(impl, dependencyResolver)
{ {
PlatformImpl.Activated = HandleActivated; impl.Activated = HandleActivated;
PlatformImpl.Deactivated = HandleDeactivated; impl.Deactivated = HandleDeactivated;
PlatformImpl.PositionChanged = HandlePositionChanged; impl.PositionChanged = HandlePositionChanged;
this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl.Resize(x)); this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x));
} }
/// <summary> /// <summary>
@ -64,6 +65,7 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public event EventHandler<PointEventArgs> PositionChanged; public event EventHandler<PointEventArgs> PositionChanged;
[CanBeNull]
public new IWindowBaseImpl PlatformImpl => (IWindowBaseImpl) base.PlatformImpl; public new IWindowBaseImpl PlatformImpl => (IWindowBaseImpl) base.PlatformImpl;
/// <summary> /// <summary>
@ -80,8 +82,12 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public Point Position public Point Position
{ {
get { return PlatformImpl.Position; } get { return PlatformImpl?.Position ?? default(Point); }
set { PlatformImpl.Position = value; } set
{
if (PlatformImpl is IWindowBaseImpl impl)
impl.Position = value;
}
} }
/// <summary> /// <summary>
@ -98,7 +104,7 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public void Activate() public void Activate()
{ {
PlatformImpl.Activate(); PlatformImpl?.Activate();
} }
/// <summary> /// <summary>
@ -110,7 +116,7 @@ namespace Avalonia.Controls
try try
{ {
PlatformImpl.Hide(); PlatformImpl?.Hide();
IsVisible = false; IsVisible = false;
} }
finally finally
@ -131,7 +137,7 @@ namespace Avalonia.Controls
EnsureInitialized(); EnsureInitialized();
IsVisible = true; IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this); LayoutManager.Instance.ExecuteInitialLayoutPass(this);
PlatformImpl.Show(); PlatformImpl?.Show();
} }
finally finally
{ {
@ -163,10 +169,10 @@ namespace Avalonia.Controls
{ {
using (BeginAutoSizing()) using (BeginAutoSizing())
{ {
PlatformImpl.Resize(finalSize); PlatformImpl?.Resize(finalSize);
} }
return base.ArrangeOverride(PlatformImpl.ClientSize); return base.ArrangeOverride(PlatformImpl?.ClientSize ?? default(Size));
} }
/// <summary> /// <summary>
@ -174,7 +180,7 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
protected void EnsureInitialized() protected void EnsureInitialized()
{ {
if (!this.IsInitialized) if (!IsInitialized)
{ {
var init = (ISupportInitialize)this; var init = (ISupportInitialize)this;
init.BeginInit(); init.BeginInit();
@ -268,12 +274,12 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Starts moving a window with left button being held. Should be called from left mouse button press event handler /// Starts moving a window with left button being held. Should be called from left mouse button press event handler
/// </summary> /// </summary>
public void BeginMoveDrag() => PlatformImpl.BeginMoveDrag(); public void BeginMoveDrag() => PlatformImpl?.BeginMoveDrag();
/// <summary> /// <summary>
/// Starts resizing a window. This function is used if an application has window resizing controls. /// Starts resizing a window. This function is used if an application has window resizing controls.
/// Should be called from left mouse button press event handler /// Should be called from left mouse button press event handler
/// </summary> /// </summary>
public void BeginResizeDrag(WindowEdge edge) => PlatformImpl.BeginResizeDrag(edge); public void BeginResizeDrag(WindowEdge edge) => PlatformImpl?.BeginResizeDrag(edge);
} }
} }

4
src/Avalonia.DesignerSupport/DesignerAssist.cs

@ -75,7 +75,7 @@ namespace Avalonia.DesignerSupport
private static void SetScalingFactor(double factor) private static void SetScalingFactor(double factor)
{ {
PlatformManager.SetDesignerScalingFactor(factor); PlatformManager.SetDesignerScalingFactor(factor);
s_currentWindow?.PlatformImpl.Resize(s_currentWindow.ClientSize); s_currentWindow?.PlatformImpl?.Resize(s_currentWindow.ClientSize);
} }
static Window s_currentWindow; static Window s_currentWindow;
@ -149,6 +149,8 @@ namespace Avalonia.DesignerSupport
s_currentWindow = window; s_currentWindow = window;
window.Show(); window.Show();
Design.ApplyDesignerProperties(window, control); Design.ApplyDesignerProperties(window, control);
// ReSharper disable once PossibleNullReferenceException
// Always not null at this point
Api.OnWindowCreated?.Invoke(window.PlatformImpl.Handle.Handle); Api.OnWindowCreated?.Invoke(window.PlatformImpl.Handle.Handle);
Api.OnResize?.Invoke(); Api.OnResize?.Invoke();
} }

8
src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs

@ -82,7 +82,13 @@ namespace Avalonia
private void LoadAssembliesInDirectory() private void LoadAssembliesInDirectory()
{ {
foreach (var file in new FileInfo(Assembly.GetEntryAssembly().Location).Directory.EnumerateFiles("*.dll")) var location = Assembly.GetEntryAssembly().Location;
if (string.IsNullOrWhiteSpace(location))
return;
var dir = new FileInfo(location).Directory;
if (dir == null)
return;
foreach (var file in dir.EnumerateFiles("*.dll"))
{ {
try try
{ {

2
src/Avalonia.Styling/Controls/NameScope.cs

@ -50,7 +50,7 @@ namespace Avalonia.Controls
return result; return result;
} }
visual = (visual as ILogical).LogicalParent as Visual; visual = (visual as ILogical)?.LogicalParent as Visual;
} }
return null; return null;

2
src/Avalonia.Visuals/Rendering/ZIndexComparer.cs

@ -8,6 +8,6 @@ namespace Avalonia.Rendering
{ {
public static readonly ZIndexComparer Instance = new ZIndexComparer(); public static readonly ZIndexComparer Instance = new ZIndexComparer();
public int Compare(IVisual x, IVisual y) => x.ZIndex.CompareTo(y.ZIndex); public int Compare(IVisual x, IVisual y) => (x?.ZIndex ?? 0).CompareTo(y?.ZIndex ?? 0);
} }
} }

1
src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs

@ -9,6 +9,7 @@ using Avalonia.Cairo.Media.Imaging;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
// ReSharper disable PossibleNullReferenceException
namespace Avalonia.Cairo.Media namespace Avalonia.Cairo.Media
{ {

1
src/Gtk/Avalonia.Gtk3/SystemDialogs.cs

@ -28,6 +28,7 @@ namespace Avalonia.Gtk3
List<IDisposable> disposables = null; List<IDisposable> disposables = null;
Action dispose = () => Action dispose = () =>
{ {
// ReSharper disable once PossibleNullReferenceException
foreach (var d in disposables) foreach (var d in disposables)
d.Dispose(); d.Dispose();
disposables.Clear(); disposables.Clear();

2
src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorParser.cs

@ -68,7 +68,7 @@ namespace Avalonia.Markup.Xaml.Parsers
} }
else if (property != null) else if (property != null)
{ {
var type = result.TargetType; var type = result?.TargetType;
if (type == null) if (type == null)
{ {

4
src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs

@ -15,7 +15,7 @@ namespace Avalonia.Win32.Embedding
{ {
private readonly EmbeddableControlRoot _root = new EmbeddableControlRoot(); private readonly EmbeddableControlRoot _root = new EmbeddableControlRoot();
private IntPtr WindowHandle => ((WindowImpl) _root.PlatformImpl).Handle.Handle; private IntPtr WindowHandle => ((WindowImpl) _root?.PlatformImpl)?.Handle?.Handle ?? IntPtr.Zero;
public WinFormsAvaloniaControlHost() public WinFormsAvaloniaControlHost()
{ {
@ -25,6 +25,8 @@ namespace Avalonia.Win32.Embedding
if (_root.IsFocused) if (_root.IsFocused)
FocusManager.Instance.Focus(null); FocusManager.Instance.Focus(null);
_root.GotFocus += RootGotFocus; _root.GotFocus += RootGotFocus;
// ReSharper disable once PossibleNullReferenceException
// Always non-null at this point
_root.PlatformImpl.LostFocus += PlatformImpl_LostFocus; _root.PlatformImpl.LostFocus += PlatformImpl_LostFocus;
FixPosition(); FixPosition();
} }

Loading…
Cancel
Save