Browse Source

Make PlatformImpl nullable and always check for null value

pull/995/head
Nikita Tsukanov 9 years ago
parent
commit
e883107ca3
  1. 2
      samples/interop/Direct3DInteropSample/MainWindow.cs
  2. 12
      src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
  3. 7
      src/Avalonia.Controls/Primitives/PopupRoot.cs
  4. 33
      src/Avalonia.Controls/TopLevel.cs
  5. 28
      src/Avalonia.Controls/Window.cs
  6. 34
      src/Avalonia.Controls/WindowBase.cs
  7. 4
      src/Avalonia.DesignerSupport/DesignerAssist.cs
  8. 4
      src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs

2
samples/interop/Direct3DInteropSample/MainWindow.cs

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

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

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

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

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

33
src/Avalonia.Controls/TopLevel.cs

@ -14,6 +14,7 @@ using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.VisualTree;
using JetBrains.Annotations;
namespace Avalonia.Controls
{
@ -92,13 +93,13 @@ namespace Avalonia.Controls
var rendererFactory = TryGetService<IRendererFactory>(dependencyResolver);
Renderer = rendererFactory?.CreateRenderer(this, renderLoop);
PlatformImpl.SetInputRoot(this);
impl.SetInputRoot(this);
PlatformImpl.Closed = HandleClosed;
PlatformImpl.Input = HandleInput;
PlatformImpl.Paint = HandlePaint;
PlatformImpl.Resized = HandleResized;
PlatformImpl.ScalingChanged = HandleScalingChanged;
impl.Closed = HandleClosed;
impl.Input = HandleInput;
impl.Paint = HandlePaint;
impl.Resized = HandleResized;
impl.ScalingChanged = HandleScalingChanged;
_keyboardNavigationHandler?.SetOwner(this);
@ -110,7 +111,7 @@ namespace Avalonia.Controls
this.GetObservable(PointerOverElementProperty)
.Select(
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)
{
@ -135,10 +136,8 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the platform-specific window implementation.
/// </summary>
public ITopLevelImpl PlatformImpl
{
get;
}
[CanBeNull]
public ITopLevelImpl PlatformImpl { get; private set; }
/// <summary>
/// Gets the renderer for the window.
@ -177,7 +176,7 @@ namespace Avalonia.Controls
Size ILayoutRoot.MaxClientSize => Size.Infinity;
/// <inheritdoc/>
double ILayoutRoot.LayoutScaling => PlatformImpl.Scaling;
double ILayoutRoot.LayoutScaling => PlatformImpl?.Scaling ?? 1;
IStyleHost IStyleHost.StylingParent
{
@ -189,25 +188,27 @@ namespace Avalonia.Controls
/// <inheritdoc/>
protected virtual IRenderTarget CreateRenderTarget()
{
if(PlatformImpl == null)
throw new InvalidOperationException("PlatformImpl isn't available");
return _renderInterface.CreateRenderTarget(PlatformImpl.Surfaces);
}
/// <inheritdoc/>
void IRenderRoot.Invalidate(Rect rect)
{
PlatformImpl.Invalidate(rect);
PlatformImpl?.Invalidate(rect);
}
/// <inheritdoc/>
Point IRenderRoot.PointToClient(Point p)
{
return PlatformImpl.PointToClient(p);
return PlatformImpl?.PointToClient(p) ?? default(Point);
}
/// <inheritdoc/>
Point IRenderRoot.PointToScreen(Point p)
{
return PlatformImpl.PointToScreen(p);
return PlatformImpl?.PointToScreen(p) ?? default(Point);
}
/// <summary>
@ -224,6 +225,8 @@ namespace Avalonia.Controls
/// </summary>
protected virtual void HandleClosed()
{
PlatformImpl = null;
Closed?.Invoke(this, EventArgs.Empty);
Renderer?.Dispose();
Renderer = null;

28
src/Avalonia.Controls/Window.cs

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

34
src/Avalonia.Controls/WindowBase.cs

@ -9,6 +9,7 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Platform;
using JetBrains.Annotations;
namespace Avalonia.Controls
{
@ -43,10 +44,10 @@ namespace Avalonia.Controls
public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(impl, dependencyResolver)
{
PlatformImpl.Activated = HandleActivated;
PlatformImpl.Deactivated = HandleDeactivated;
PlatformImpl.PositionChanged = HandlePositionChanged;
this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl.Resize(x));
impl.Activated = HandleActivated;
impl.Deactivated = HandleDeactivated;
impl.PositionChanged = HandlePositionChanged;
this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x));
}
/// <summary>
@ -64,6 +65,7 @@ namespace Avalonia.Controls
/// </summary>
public event EventHandler<PointEventArgs> PositionChanged;
[CanBeNull]
public new IWindowBaseImpl PlatformImpl => (IWindowBaseImpl) base.PlatformImpl;
/// <summary>
@ -80,8 +82,12 @@ namespace Avalonia.Controls
/// </summary>
public Point Position
{
get { return PlatformImpl.Position; }
set { PlatformImpl.Position = value; }
get { return PlatformImpl?.Position ?? default(Point); }
set
{
if (PlatformImpl is IWindowBaseImpl impl)
impl.Position = value;
}
}
/// <summary>
@ -98,7 +104,7 @@ namespace Avalonia.Controls
/// </summary>
public void Activate()
{
PlatformImpl.Activate();
PlatformImpl?.Activate();
}
/// <summary>
@ -110,7 +116,7 @@ namespace Avalonia.Controls
try
{
PlatformImpl.Hide();
PlatformImpl?.Hide();
IsVisible = false;
}
finally
@ -131,7 +137,7 @@ namespace Avalonia.Controls
EnsureInitialized();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
PlatformImpl.Show();
PlatformImpl?.Show();
}
finally
{
@ -163,10 +169,10 @@ namespace Avalonia.Controls
{
using (BeginAutoSizing())
{
PlatformImpl.Resize(finalSize);
PlatformImpl?.Resize(finalSize);
}
return base.ArrangeOverride(PlatformImpl.ClientSize);
return base.ArrangeOverride(PlatformImpl?.ClientSize ?? default(Size));
}
/// <summary>
@ -174,7 +180,7 @@ namespace Avalonia.Controls
/// </summary>
protected void EnsureInitialized()
{
if (!this.IsInitialized)
if (!IsInitialized)
{
var init = (ISupportInitialize)this;
init.BeginInit();
@ -268,12 +274,12 @@ namespace Avalonia.Controls
/// <summary>
/// Starts moving a window with left button being held. Should be called from left mouse button press event handler
/// </summary>
public void BeginMoveDrag() => PlatformImpl.BeginMoveDrag();
public void BeginMoveDrag() => PlatformImpl?.BeginMoveDrag();
/// <summary>
/// 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
/// </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)
{
PlatformManager.SetDesignerScalingFactor(factor);
s_currentWindow?.PlatformImpl.Resize(s_currentWindow.ClientSize);
s_currentWindow?.PlatformImpl?.Resize(s_currentWindow.ClientSize);
}
static Window s_currentWindow;
@ -149,6 +149,8 @@ namespace Avalonia.DesignerSupport
s_currentWindow = window;
window.Show();
Design.ApplyDesignerProperties(window, control);
// ReSharper disable once PossibleNullReferenceException
// Always not null at this point
Api.OnWindowCreated?.Invoke(window.PlatformImpl.Handle.Handle);
Api.OnResize?.Invoke();
}

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

@ -15,7 +15,7 @@ namespace Avalonia.Win32.Embedding
{
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()
{
@ -25,6 +25,8 @@ namespace Avalonia.Win32.Embedding
if (_root.IsFocused)
FocusManager.Instance.Focus(null);
_root.GotFocus += RootGotFocus;
// ReSharper disable once PossibleNullReferenceException
// Always non-null at this point
_root.PlatformImpl.LostFocus += PlatformImpl_LostFocus;
FixPosition();
}

Loading…
Cancel
Save