PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/GammaJul.LgLcd/LcdPage.cs

#
C# | 212 lines | 89 code | 37 blank | 86 comment | 13 complexity | 037e68c684c23e0b85c936c08b4ac3ee MD5 | raw file
Possible License(s): LGPL-2.1
  1. using System;
  2. namespace GammaJul.LgLcd {
  3. /// <summary>
  4. /// Base class for every device page.
  5. /// </summary>
  6. public abstract class LcdPage : IDisposable {
  7. #region Properties
  8. private readonly LcdDevice _device;
  9. private int _desiredFramerate;
  10. private bool _invalidated;
  11. /// <summary>
  12. /// Gets the device where this page will be shown.
  13. /// </summary>
  14. public LcdDevice Device {
  15. get { return _device; }
  16. }
  17. /// <summary>
  18. /// Gets the last time this page was updated, relative to the device's creation time.
  19. /// </summary>
  20. internal TimeSpan LastFrameUpdate { get; set; }
  21. /// <summary>
  22. /// Gets or sets the priority of this page when drawing.
  23. /// The default value is <see cref="LcdPriority.Normal"/>.
  24. /// </summary>
  25. public LcdPriority Priority { get; set; }
  26. /// <summary>
  27. /// Gets or sets the mode (synchronous or asynchronous) used to update this page.
  28. /// The default value is <see cref="LcdUpdateMode.Async"/>.
  29. /// </summary>
  30. public LcdUpdateMode UpdateMode { get; set; }
  31. /// <summary>
  32. /// Gets or sets the desired frame rate, in frame per seconds, for this page.
  33. /// The default value is 30.
  34. /// </summary>
  35. public int DesiredFramerate {
  36. get { return _desiredFramerate; }
  37. set {
  38. if (value < 1 || value > 60)
  39. throw new ArgumentOutOfRangeException("value", "DesiredFrameRate must be between 1 and 60");
  40. _desiredFramerate = value;
  41. }
  42. }
  43. #endregion
  44. #region Events
  45. /// <summary>
  46. /// Occurs when the page starts updating its content.
  47. /// </summary>
  48. public event EventHandler<UpdateEventArgs> Updating;
  49. /// <summary>
  50. /// Occurs when the page has updated its content.
  51. /// </summary>
  52. public event EventHandler<UpdateEventArgs> Updated;
  53. /// <summary>
  54. /// Occurs when the page starts drawing its content.
  55. /// </summary>
  56. public event EventHandler Drawing;
  57. /// <summary>
  58. /// Occurs when the page has drawn its content, but the pixels have not yet been send to the device.
  59. /// This is your last chance to do some kind of post-processing on the pixels.
  60. /// </summary>
  61. public event EventHandler<DrawnEventArgs> Drawn;
  62. /// <summary>
  63. /// Raises the <see cref="Updating"/> event.
  64. /// </summary>
  65. /// <param name="e">Update parameters.</param>
  66. protected virtual void OnUpdating(UpdateEventArgs e) {
  67. EventHandler<UpdateEventArgs> handler = Updating;
  68. if (handler != null)
  69. handler(this, e);
  70. }
  71. /// <summary>
  72. /// Raises the <see cref="Updated"/> event.
  73. /// </summary>
  74. /// <param name="e">Update parameters.</param>
  75. protected virtual void OnUpdated(UpdateEventArgs e) {
  76. EventHandler<UpdateEventArgs> handler = Updated;
  77. if (handler != null)
  78. handler(this, e);
  79. }
  80. /// <summary>
  81. /// Raises the <see cref="Drawing"/> event.
  82. /// </summary>
  83. protected virtual void OnDrawing() {
  84. EventHandler handler = Drawing;
  85. if (handler != null)
  86. handler(this, EventArgs.Empty);
  87. }
  88. /// <summary>
  89. /// Raises the <see cref="Drawn"/> event.
  90. /// </summary>
  91. protected virtual void OnDrawn(byte[] pixels) {
  92. EventHandler<DrawnEventArgs> handler = Drawn;
  93. if (handler != null)
  94. handler(this, new DrawnEventArgs(pixels));
  95. }
  96. #endregion
  97. /// <summary>
  98. /// Sets this page as <see cref="Device"/>'s <see cref="LcdDevice.CurrentPage"/>.
  99. /// </summary>
  100. public void SetAsCurrentDevicePage() {
  101. _device.CurrentPage = this;
  102. }
  103. /// <summary>
  104. /// Call this method to force an update and draw cycle even if the page has not changed.
  105. /// </summary>
  106. public void Invalidate() {
  107. _invalidated = true;
  108. }
  109. /// <summary>
  110. /// Updates the page content.
  111. /// </summary>
  112. /// <param name="elapsedTotalTime">Time elapsed since the device creation.</param>
  113. /// <param name="elapsedTimeSinceLastFrame">Time elapsed since last frame update.</param>
  114. /// <returns><c>true</c> if the update has done something and a redraw is required.</returns>
  115. internal bool Update(TimeSpan elapsedTotalTime, TimeSpan elapsedTimeSinceLastFrame) {
  116. UpdateEventArgs updateEventArgs = new UpdateEventArgs(elapsedTotalTime, elapsedTimeSinceLastFrame);
  117. OnUpdating(updateEventArgs);
  118. bool redrawNeeded = UpdateCore(elapsedTotalTime, elapsedTimeSinceLastFrame) || _invalidated;
  119. OnUpdated(updateEventArgs);
  120. _invalidated = false;
  121. return redrawNeeded;
  122. }
  123. /// <summary>
  124. /// Derived classes override this method in order to update the page content.
  125. /// </summary>
  126. /// <param name="elapsedTotalTime">Time elapsed since the device creation.</param>
  127. /// <param name="elapsedTimeSinceLastFrame">Time elapsed since last frame update.</param>
  128. /// <returns><c>true</c> if the update has done something and a redraw is required.</returns>
  129. protected abstract bool UpdateCore(TimeSpan elapsedTotalTime, TimeSpan elapsedTimeSinceLastFrame);
  130. /// <summary>
  131. /// Draws the page content.
  132. /// </summary>
  133. /// <returns>A pixel array conforming to <see cref="Device"/>'s <see cref="LcdDevice.DeviceType"/>.</returns>
  134. internal byte[] Draw() {
  135. OnDrawing();
  136. byte[] pixels = DrawCore();
  137. OnDrawn(pixels);
  138. return pixels;
  139. }
  140. /// <summary>
  141. /// Derived classes override this method in order to draw the page content visually.
  142. /// </summary>
  143. /// <returns>Implementors must return a pixel array conforming to
  144. /// <see cref="Device"/>'s <see cref="LcdDevice.DeviceType"/>.</returns>
  145. protected abstract byte[] DrawCore();
  146. #region IDisposable
  147. /// <summary>
  148. /// Releases the resources associated with this <see cref="LcdPage"/>.
  149. /// </summary>
  150. public void Dispose() {
  151. Dispose(true);
  152. GC.SuppressFinalize(this);
  153. }
  154. /// <summary>
  155. /// Releases the resources associated with this <see cref="LcdPage"/>.
  156. /// </summary>
  157. /// <param name="disposing">Whether to also release managed resources along with unmanaged ones.</param>
  158. protected virtual void Dispose(bool disposing) {
  159. }
  160. #endregion
  161. /// <summary>
  162. /// Creates a new <see cref="LcdPage"/> on the given device.
  163. /// </summary>
  164. /// <param name="device">Device where this page will be shown.</param>
  165. protected LcdPage(LcdDevice device) {
  166. if (device == null)
  167. throw new ArgumentNullException("device");
  168. _device = device;
  169. DesiredFramerate = 30;
  170. LastFrameUpdate = TimeSpan.Zero;
  171. Priority = LcdPriority.Normal;
  172. UpdateMode = LcdUpdateMode.Async;
  173. }
  174. }
  175. }