Browse Source

Documentation.

pull/72/merge
Steven Kirk 11 years ago
parent
commit
1599828f9d
  1. 1
      Perspex.Animation/Animatable.cs
  2. 2
      Perspex.Application/Application.cs
  3. 24
      Perspex.Base/Collections/PerspexListExtensions.cs
  4. 12
      Perspex.Base/Diagnostics/PerspexObjectExtensions.cs
  5. 23
      Perspex.Base/Diagnostics/PerspexPropertyValue.cs
  6. 1
      Perspex.Base/PriorityValue.cs
  7. 25
      Perspex.Base/Threading/Dispatcher.cs
  8. 48
      Perspex.Base/Threading/DispatcherPriority.cs
  9. 61
      Perspex.Base/Threading/DispatcherTimer.cs
  10. 41
      Perspex.Base/Threading/MainLoop.cs
  11. 15
      Perspex.Base/Threading/PerspexScheduler.cs

1
Perspex.Animation/Animatable.cs

@ -7,7 +7,6 @@
namespace Perspex.Animation
{
using System.Linq;
using System.Reactive.Linq;
/// <summary>
/// Base class for control which can have property transitions.

2
Perspex.Application/Application.cs

@ -28,6 +28,8 @@ namespace Perspex
/// - A global set of <see cref="Styles"/>.
/// - A <see cref="FocusManager"/>.
/// - An <see cref="InputManager"/>.
/// - Loads and initializes rendering and windowing subsystems with
/// <see cref="InitializeSubsystems(int)"/> and <see cref="InitializeSubsystem(string)"/>.
/// - Registers services needed by the rest of Perspex in the <see cref="RegisterServices"/>
/// method.
/// - Tracks the lifetime of the application.

24
Perspex.Base/Collections/PerspexListExtensions.cs

@ -12,8 +12,25 @@ namespace Perspex.Collections
using System.ComponentModel;
using System.Reactive.Disposables;
/// <summary>
/// Defines extension methods for working with <see cref="PerspexList{T}"/>s.
/// </summary>
public static class PerspexListExtensions
{
/// <summary>
/// Invokes an action for each item in a collection and subsequently each item added or
/// removed from the collection.
/// </summary>
/// <typeparam name="T">The type of the collection items.</typeparam>
/// <param name="collection">The collection.</param>
/// <param name="added">
/// An action called initially for each item in the collection and subsequently for each
/// item added to the collection.
/// </param>
/// <param name="removed">
/// An action called for each item removed from the collection.
/// </param>
/// <returns>A disposable used to terminate the subscription.</returns>
public static IDisposable ForEachItem<T>(
this IPerspexReadOnlyList<T> collection,
Action<T> added,
@ -64,6 +81,13 @@ namespace Perspex.Collections
return Disposable.Create(() => collection.CollectionChanged -= handler);
}
/// <summary>
/// Listens for property changed events from all items in a collection.
/// </summary>
/// <typeparam name="T">The type of the collection items.</typeparam>
/// <param name="collection">The collection.</param>
/// <param name="callback">A callback to call for each property changed event.</param>
/// <returns>A disposable used to terminate the subscription.</returns>
public static IDisposable TrackItemPropertyChanged<T>(
this IPerspexReadOnlyList<T> collection,
Action<Tuple<object, PropertyChangedEventArgs>> callback)

12
Perspex.Base/Diagnostics/PerspexObjectExtensions.cs

@ -6,8 +6,20 @@
namespace Perspex.Diagnostics
{
/// <summary>
/// Defines diagnostic extensions on <see cref="PerspexObject"/>s.
/// </summary>
public static class PerspexObjectExtensions
{
/// <summary>
/// Gets a diagnostic for a <see cref="PerspexProperty"/> on a <see cref="PerspexObject"/>.
/// </summary>
/// <param name="o">The object.</param>
/// <param name="property">The property.</param>
/// <returns>
/// A <see cref="PerspexPropertyValue"/> that can be used to diagnose the state of the
/// property on the object.
/// </returns>
public static PerspexPropertyValue GetDiagnostic(this PerspexObject o, PerspexProperty property)
{
var set = o.GetSetValues();

23
Perspex.Base/Diagnostics/PerspexPropertyValue.cs

@ -6,8 +6,19 @@
namespace Perspex.Diagnostics
{
/// <summary>
/// Holds diagnostic-related information about the value of a <see cref="PerspexProperty"/>
/// on a <see cref="PerspexObject"/>.
/// </summary>
public class PerspexPropertyValue
{
/// <summary>
/// Initializes a new instance of the <see cref="PerspexPropertyValue"/> class.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="value">The current property value.</param>
/// <param name="priority">The priority of the current value.</param>
/// <param name="diagnostic">A diagnostic string.</param>
public PerspexPropertyValue(
PerspexProperty property,
object value,
@ -20,12 +31,24 @@ namespace Perspex.Diagnostics
this.Diagnostic = diagnostic;
}
/// <summary>
/// Gets the property.
/// </summary>
public PerspexProperty Property { get; }
/// <summary>
/// Gets the current property value.
/// </summary>
public object Value { get; }
/// <summary>
/// Gets the priority of the current value.
/// </summary>
public BindingPriority Priority { get; }
/// <summary>
/// Gets a diagnostic string.
/// </summary>
public string Diagnostic { get; }
}
}

1
Perspex.Base/PriorityValue.cs

@ -10,7 +10,6 @@ namespace Perspex
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
using System.Reflection;
using System.Text;
using Perspex.Utilities;

25
Perspex.Base/Threading/Dispatcher.cs

@ -11,26 +11,51 @@ namespace Perspex.Threading
using System.Threading.Tasks;
using Perspex.Win32.Threading;
/// <summary>
/// Provides services for managing work items on a thread.
/// </summary>
/// <remarks>
/// In Perspex, there is usually only a single <see cref="Dispatcher"/> in the application -
/// the one for the UI thread, retrieved via the <see cref="UIThread"/> property.
/// </remarks>
public class Dispatcher
{
private static Dispatcher instance = new Dispatcher();
private MainLoop mainLoop = new MainLoop();
/// <summary>
/// Initializes a new instance of the <see cref="Dispatcher"/> class.
/// </summary>
private Dispatcher()
{
}
/// <summary>
/// Gets the <see cref="Dispatcher"/> for the UI thread.
/// </summary>
public static Dispatcher UIThread
{
get { return instance; }
}
/// <summary>
/// Runs the dispatcher's main loop.
/// </summary>
/// <param name="cancellationToken">
/// A cancellation token used to exit the main loop.
/// </param>
public void MainLoop(CancellationToken cancellationToken)
{
this.mainLoop.Run(cancellationToken);
}
/// <summary>
/// Invokes a method on the dispatcher thread.
/// </summary>
/// <param name="action">The method.</param>
/// <param name="priority">The priority with which to invoke the method.</param>
/// <returns>A task that can be used to track the method's execution.</returns>
public Task InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
{
return this.mainLoop.InvokeAsync(action, priority);

48
Perspex.Base/Threading/DispatcherPriority.cs

@ -6,19 +6,65 @@
namespace Perspex.Threading
{
/// <summary>
/// Defines the priorities with which jobs can be invoked on a <see cref="Dispatcher"/>.
/// </summary>
// TODO: These are copied from WPF - many won't apply to Perspex.
public enum DispatcherPriority
{
Invalid = -1,
/// <summary>
/// The job will not be processed.
/// </summary>
Inactive = 0,
/// <summary>
/// The job will be processed when the system is idle.
/// </summary>
SystemIdle = 1,
/// <summary>
/// The job will be processed when the application sis idle.
/// </summary>
ApplicationIdle = 2,
/// <summary>
/// The job will be processed after background operations have completed.
/// </summary>
ContextIdle = 3,
/// <summary>
/// The job will be processed after other non-idle operations have completed.
/// </summary>
Background = 4,
/// <summary>
/// The job will be processed with the same priority as input.
/// </summary>
Input = 5,
/// <summary>
/// The job will be processed after layout and render but before input.
/// </summary>
Loaded = 6,
/// <summary>
/// The job will be processed with the same priority as render.
/// </summary>
Render = 7,
/// <summary>
/// The job will be processed with the same priority as data binding.
/// </summary>
DataBind = 8,
/// <summary>
/// The job will be processed with normal priority.
/// </summary>
Normal = 9,
/// <summary>
/// The job will be processed before other asynchronous operations.
/// </summary>
Send = 10,
}
}

61
Perspex.Base/Threading/DispatcherTimer.cs

@ -11,6 +11,9 @@ namespace Perspex.Threading
using Perspex.Platform;
using Splat;
/// <summary>
/// A timer that uses a <see cref="Dispatcher"/> to fire at a specified interval.
/// </summary>
public class DispatcherTimer
{
private IDisposable timer;
@ -19,24 +22,43 @@ namespace Perspex.Threading
private TimeSpan interval;
/// <summary>
/// Initializes a new instance of the <see cref="DispatcherTimer"/> class.
/// </summary>
public DispatcherTimer()
{
this.priority = DispatcherPriority.Normal;
this.Dispatcher = Dispatcher.UIThread;
}
/// <summary>
/// Initializes a new instance of the <see cref="DispatcherTimer"/> class.
/// </summary>
/// <param name="priority">The priority to use.</param>
public DispatcherTimer(DispatcherPriority priority)
{
this.priority = priority;
this.Dispatcher = Dispatcher.UIThread;
}
/// <summary>
/// Initializes a new instance of the <see cref="DispatcherTimer"/> class.
/// </summary>
/// <param name="priority">The priority to use.</param>
/// <param name="dispatcher">The dispatcher to use.</param>
public DispatcherTimer(DispatcherPriority priority, Dispatcher dispatcher)
{
this.priority = priority;
this.Dispatcher = dispatcher;
}
/// <summary>
/// Initializes a new instance of the <see cref="DispatcherTimer"/> class.
/// </summary>
/// <param name="interval">The interval at which to tick.</param>
/// <param name="priority">The priority to use.</param>
/// <param name="dispatcher">The dispatcher to use.</param>
/// <param name="callback">The event to call when the timer ticks.</param>
public DispatcherTimer(TimeSpan interval, DispatcherPriority priority, EventHandler callback, Dispatcher dispatcher)
{
this.priority = priority;
@ -45,6 +67,9 @@ namespace Perspex.Threading
this.Tick += callback;
}
/// <summary>
/// Finalizes an instance of the <see cref="DispatcherTimer"/> class.
/// </summary>
~DispatcherTimer()
{
if (this.timer != null)
@ -53,14 +78,23 @@ namespace Perspex.Threading
}
}
/// <summary>
/// Raised when the timer ticks.
/// </summary>
public event EventHandler Tick;
/// <summary>
/// Gets the dispatcher that the timer uses.
/// </summary>
public Dispatcher Dispatcher
{
get;
private set;
}
/// <summary>
/// Gets or sets the interval at which the timer ticks.
/// </summary>
public TimeSpan Interval
{
get
@ -77,6 +111,9 @@ namespace Perspex.Threading
}
}
/// <summary>
/// Gets or sets a value indicating whether the timer is running.
/// </summary>
public bool IsEnabled
{
get
@ -100,12 +137,24 @@ namespace Perspex.Threading
}
}
/// <summary>
/// Gets or sets user-defined data associated with the timer.
/// </summary>
public object Tag
{
get;
set;
}
/// <summary>
/// Starts a new timer.
/// </summary>
/// <param name="action">
/// The method to call on timer tick. If the method returns false, the timer will stop.
/// </param>
/// <param name="interval">The interval at which to tick.</param>
/// <param name="priority">The priority to use.</param>
/// <returns>An <see cref="IDisposable"/> used to cancel the timer.</returns>
public static IDisposable Run(Func<bool> action, TimeSpan interval, DispatcherPriority priority = DispatcherPriority.Normal)
{
var timer = new DispatcherTimer(priority);
@ -124,6 +173,9 @@ namespace Perspex.Threading
return Disposable.Create(() => timer.Stop());
}
/// <summary>
/// Starts the timer.
/// </summary>
public void Start()
{
if (!this.IsEnabled)
@ -133,6 +185,9 @@ namespace Perspex.Threading
}
}
/// <summary>
/// Stops the timer.
/// </summary>
public void Stop()
{
if (this.IsEnabled)
@ -143,11 +198,17 @@ namespace Perspex.Threading
}
}
/// <summary>
/// Raises the <see cref="Tick"/> event on the dispatcher thread.
/// </summary>
private void InternalTick()
{
this.Dispatcher.InvokeAsync(this.RaiseTick, this.priority);
}
/// <summary>
/// Raises the <see cref="Tick"/> event.
/// </summary>
private void RaiseTick()
{
if (this.Tick != null)

41
Perspex.Base/Threading/MainLoop.cs

@ -14,6 +14,9 @@ namespace Perspex.Win32.Threading
using Perspex.Threading;
using Splat;
/// <summary>
/// A main loop in a <see cref="Dispatcher"/>.
/// </summary>
internal class MainLoop
{
private static IPlatformThreadingInterface platform;
@ -21,11 +24,20 @@ namespace Perspex.Win32.Threading
private PriorityQueue<Job, DispatcherPriority> queue =
new PriorityQueue<Job, DispatcherPriority>(PriorityQueueType.Maximum);
/// <summary>
/// Initializes static members of the <see cref="MainLoop"/> class.
/// </summary>
static MainLoop()
{
platform = Locator.Current.GetService<IPlatformThreadingInterface>();
}
/// <summary>
/// Runs the main loop.
/// </summary>
/// <param name="cancellationToken">
/// A cancellation token used to exit the main loop.
/// </param>
public void Run(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
@ -64,6 +76,12 @@ namespace Perspex.Win32.Threading
}
}
/// <summary>
/// Invokes a method on the main loop.
/// </summary>
/// <param name="action">The method.</param>
/// <param name="priority">The priority with which to invoke the method.</param>
/// <returns>A task that can be used to track the method's execution.</returns>
public Task InvokeAsync(Action action, DispatcherPriority priority)
{
var job = new Job(action, priority);
@ -77,8 +95,16 @@ namespace Perspex.Win32.Threading
return job.TaskCompletionSource.Task;
}
/// <summary>
/// A job to run.
/// </summary>
private class Job
{
/// <summary>
/// Initializes a new instance of the <see cref="Job"/> class.
/// </summary>
/// <param name="action">The method to call.</param>
/// <param name="priority">The job priority.</param>
public Job(Action action, DispatcherPriority priority)
{
this.Action = action;
@ -86,11 +112,20 @@ namespace Perspex.Win32.Threading
this.TaskCompletionSource = new TaskCompletionSource<object>();
}
public Action Action { get; private set; }
/// <summary>
/// Gets the method to call.
/// </summary>
public Action Action { get; }
public DispatcherPriority Priority { get; private set; }
/// <summary>
/// Gets the job priority.
/// </summary>
public DispatcherPriority Priority { get; }
public TaskCompletionSource<object> TaskCompletionSource { get; set; }
/// <summary>
/// Gets the task completion source.
/// </summary>
public TaskCompletionSource<object> TaskCompletionSource { get; }
}
}
}

15
Perspex.Base/Threading/PerspexScheduler.cs

@ -8,12 +8,25 @@ namespace Perspex.Threading
{
using System;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
/// <summary>
/// A reactive scheduler that uses Perspex's <see cref="Dispatcher.UIThread"/>.
/// </summary>
public class PerspexScheduler : LocalScheduler
{
/// <summary>
/// The instance of the <see cref="PerspexScheduler"/>.
/// </summary>
public static readonly PerspexScheduler Instance = new PerspexScheduler();
/// <summary>
/// Initializes a new instance of the <see cref="PerspexScheduler"/> class.
/// </summary>
private PerspexScheduler()
{
}
/// <inheritdoc/>
public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
{
return DispatcherTimer.Run(

Loading…
Cancel
Save