10 changed files with 222 additions and 2 deletions
@ -0,0 +1,12 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.LogicalTree; |
|||
|
|||
public interface IScreenSizeProvider |
|||
{ |
|||
double GetScreenWidth(); |
|||
|
|||
double GetScreenHeight(); |
|||
|
|||
event EventHandler? ScreenSizeChanged; |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.LogicalTree; |
|||
|
|||
public interface ITopLevelScreenSizeProvider |
|||
{ |
|||
IScreenSizeProvider? GetScreenSizeProvider(); |
|||
|
|||
event EventHandler? ScreenSizeProviderChanged; |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
using System; |
|||
using Avalonia.LogicalTree; |
|||
|
|||
namespace Avalonia.Styling.Activators; |
|||
|
|||
internal sealed class ScreenActivator : StyleActivatorBase |
|||
{ |
|||
private readonly ITopLevelScreenSizeProvider _provider; |
|||
private IScreenSizeProvider? _currentScreenSizeProvider; |
|||
|
|||
public ScreenActivator( |
|||
ITopLevelScreenSizeProvider provider) |
|||
{ |
|||
_provider = provider; |
|||
} |
|||
|
|||
protected override void Initialize() |
|||
{ |
|||
InitialiseScreenSizeProvider(); |
|||
PublishNext(IsMatching()); |
|||
_provider.ScreenSizeProviderChanged += ScreenSizeProviderChanged; |
|||
} |
|||
|
|||
protected override void Deinitialize() |
|||
{ |
|||
_provider.ScreenSizeProviderChanged -= ScreenSizeProviderChanged; |
|||
|
|||
if (_currentScreenSizeProvider is { }) |
|||
{ |
|||
_currentScreenSizeProvider.ScreenSizeChanged -= ScreenSizeChanged; |
|||
_currentScreenSizeProvider = null; |
|||
} |
|||
} |
|||
|
|||
private void ScreenSizeProviderChanged(object? sender, EventArgs e) |
|||
{ |
|||
if (_currentScreenSizeProvider is { }) |
|||
{ |
|||
_currentScreenSizeProvider.ScreenSizeChanged -= ScreenSizeChanged; |
|||
_currentScreenSizeProvider = null; |
|||
} |
|||
|
|||
InitialiseScreenSizeProvider(); |
|||
} |
|||
|
|||
private void InitialiseScreenSizeProvider() |
|||
{ |
|||
if (_provider.GetScreenSizeProvider() is { } screenSizeProvider) |
|||
{ |
|||
_currentScreenSizeProvider = screenSizeProvider; |
|||
|
|||
_currentScreenSizeProvider.ScreenSizeChanged += ScreenSizeChanged; |
|||
} |
|||
|
|||
PublishNext(IsMatching()); |
|||
} |
|||
|
|||
private void ScreenSizeChanged(object? sender, EventArgs e) |
|||
{ |
|||
PublishNext(IsMatching()); |
|||
} |
|||
|
|||
private bool IsMatching() => _currentScreenSizeProvider != null && ScreenSelector.Evaluate(_currentScreenSizeProvider).IsMatch; |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
using System; |
|||
using Avalonia.LogicalTree; |
|||
using Avalonia.Styling.Activators; |
|||
|
|||
namespace Avalonia.Styling; |
|||
|
|||
public class ScreenSelector : Selector |
|||
{ |
|||
private readonly Selector? _previous; |
|||
|
|||
public ScreenSelector(Selector? previous) |
|||
{ |
|||
_previous = previous; |
|||
} |
|||
public override bool InTemplate => _previous?.InTemplate ?? false; |
|||
|
|||
public override bool IsCombinator => false; |
|||
|
|||
public override Type? TargetType => _previous?.TargetType; |
|||
|
|||
protected override SelectorMatch Evaluate(IStyleable control, bool subscribe) |
|||
{ |
|||
if (!(control is ITopLevelScreenSizeProvider logical)) |
|||
{ |
|||
return SelectorMatch.NeverThisType; |
|||
} |
|||
|
|||
if (subscribe) |
|||
{ |
|||
return new SelectorMatch(new ScreenActivator(logical)); |
|||
} |
|||
|
|||
if (logical.GetScreenSizeProvider() is { } screenSizeProvider) |
|||
{ |
|||
return Evaluate(screenSizeProvider); |
|||
} |
|||
|
|||
return SelectorMatch.NeverThisInstance; |
|||
} |
|||
|
|||
internal static SelectorMatch Evaluate(IScreenSizeProvider screenSizeProvider) |
|||
{ |
|||
var match = screenSizeProvider.GetScreenWidth() > 600 && screenSizeProvider.GetScreenHeight() > 600; |
|||
|
|||
return match ? SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance; |
|||
} |
|||
|
|||
protected override Selector? MovePrevious() => _previous; |
|||
|
|||
public override string ToString() => "screen"; |
|||
} |
|||
Loading…
Reference in new issue