// Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; using Avalonia.Platform; namespace Avalonia.Rendering { /// /// Defines a default render loop that uses a standard timer. /// /// /// This class may be overridden by platform implementations to use a specialized timer /// implementation. /// public class DefaultRenderLoop : IRenderLoop { private IRuntimePlatform _runtime; private int _subscriberCount; private EventHandler _tick; private IDisposable _subscription; /// /// Initializes a new instance of the class. /// /// /// The number of frames per second at which the loop should run. /// public DefaultRenderLoop(int framesPerSecond) { FramesPerSecond = framesPerSecond; } /// /// Gets the number of frames per second at which the loop runs. /// public int FramesPerSecond { get; } /// public event EventHandler Tick { add { if (_subscriberCount++ == 0) { Start(); } _tick += value; } remove { if (--_subscriberCount == 0) { Stop(); } _tick -= value; } } /// /// Starts the timer. /// protected void Start() { _subscription = StartCore(InternalTick); } /// /// Provides the implementation of starting the timer. /// /// The method to call on each tick. /// /// This can be overridden by platform implementations to use a specialized timer /// implementation. /// protected virtual IDisposable StartCore(Action tick) { if (_runtime == null) { _runtime = AvaloniaLocator.Current.GetService(); } return _runtime.StartSystemTimer(TimeSpan.FromSeconds(1.0 / FramesPerSecond), tick); } /// /// Stops the timer. /// protected void Stop() { _subscription.Dispose(); _subscription = null; } private void InternalTick() { _tick(this, EventArgs.Empty); } } }