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