PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/Yaulw/Thread/DispatcherThread.cs

https://bitbucket.org/dromischer/plex-projects
C# | 507 lines | 319 code | 66 blank | 122 comment | 63 complexity | a625f9f92766faf6cc9f5b33e57121e8 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Sys = System.Threading;
  6. using System.Reflection;
  7. using Yaulw.WPF;
  8. using System.Threading;
  9. using System.Windows.Threading;
  10. using Yaulw.Other;
  11. namespace Yaulw.Thread
  12. {
  13. /// <summary>
  14. ///
  15. /// </summary>
  16. public enum DispatcherThreatType
  17. {
  18. WPF,
  19. // Winforms // ~Not implmented
  20. // Silverlight? // ~Not implemented
  21. }
  22. /// <summary>
  23. ///
  24. /// </summary>
  25. public class WindowType
  26. {
  27. public Type T;
  28. public Enum Key;
  29. public bool IsSingleton;
  30. public bool IsPerformanceLoaded;
  31. public WindowType(Type t, Enum Key, bool IsSingleton, bool IsPerformanceLoaded)
  32. {
  33. this.T = t;
  34. this.Key = Key;
  35. this.IsSingleton = IsSingleton;
  36. this.IsPerformanceLoaded = IsPerformanceLoaded;
  37. }
  38. }
  39. /// <summary>
  40. ///
  41. /// </summary>
  42. public class WindowAttributes
  43. {
  44. public IntPtr hWndOwner;
  45. public uint Height;
  46. public uint Width;
  47. public int Top;
  48. public int Left;
  49. public string Title;
  50. public WindowAttributes(IntPtr hWndOwner, uint Height, uint Width, int Top, int Left, string Title)
  51. {
  52. this.hWndOwner = hWndOwner;
  53. this.Height = Height;
  54. this.Width = Width;
  55. this.Top = Top;
  56. this.Left = Left;
  57. this.Title = Title;
  58. }
  59. public WindowAttributes(IntPtr hWndOwner, int Top, int Left)
  60. {
  61. this.hWndOwner = hWndOwner;
  62. this.Height = 0;
  63. this.Width = 0;
  64. this.Top = Top;
  65. this.Left = Left;
  66. this.Title = String.Empty;
  67. }
  68. public WindowAttributes(IntPtr hWndOwner)
  69. {
  70. this.hWndOwner = hWndOwner;
  71. this.Height = 0;
  72. this.Width = 0;
  73. this.Top = int.MinValue;
  74. this.Left = int.MinValue;
  75. this.Title = String.Empty;
  76. }
  77. }
  78. #region Window Manager Definition
  79. /// <summary>
  80. /// Abstract Base Class all Window Managers must inherit from.
  81. ///
  82. /// </summary>
  83. public abstract class WindowManager : IDisposable
  84. {
  85. #region Private Members
  86. private Dictionary<WindowType, List<object>> s_WindowsToManage = new Dictionary<WindowType, List<object>>();
  87. #endregion
  88. #region Construction
  89. /// <summary>
  90. /// Construct a Window Manager Object
  91. /// </summary>
  92. /// <param name="dispatcher">Thread Dispatcher Object</param>
  93. /// <param name="windowTypes">Window Types this WindowManager is managing</param>
  94. /// <param name="PerformanceLoad">true, to load performance enabled windows upon construction</param>
  95. public WindowManager(Dispatcher dispatcher, WindowType[] windowTypes, bool PerformanceLoad)
  96. {
  97. Dispatcher = dispatcher;
  98. WindowTypes = windowTypes;
  99. if (Dispatcher == null)
  100. throw new ArgumentException("dispatcher can't be null");
  101. if (windowTypes == null || windowTypes.Length < 1)
  102. throw new ArgumentException("windowTypes can't be null or empty");
  103. // Add All Window Types
  104. foreach (WindowType type in windowTypes)
  105. {
  106. // Add the Type to be managed
  107. AddWindowTypeToManage(type);
  108. // perform performance optimization
  109. if (PerformanceLoad && type.IsPerformanceLoaded)
  110. {
  111. object o = CreateInstance(type);
  112. AddObject(type, o);
  113. }
  114. }
  115. }
  116. #endregion
  117. #region Public Properties
  118. /// <summary>
  119. /// Returns the Dispatcher Thread responsible for this Window Manager
  120. /// </summary>
  121. public Dispatcher Dispatcher { get; private set; }
  122. /// <summary>
  123. /// Returns all the Window Types that have been set to be managed by this Window Manager
  124. /// </summary>
  125. public WindowType[] WindowTypes { get; private set; }
  126. #endregion
  127. #region Protected Common Window Object Operations
  128. /// <summary>
  129. /// Create a new Object Instance of type
  130. /// </summary>
  131. /// <param name="window">type of object to create</param>
  132. /// <returns>a new object for type, or null</returns>
  133. protected object CreateInstance(WindowType window)
  134. {
  135. object o = null;
  136. if (window != null)
  137. o = Activator.CreateInstance(window.T);
  138. return o;
  139. }
  140. /// <summary>
  141. /// Create a new Object Instance of type
  142. /// </summary>
  143. /// <param name="windowKey">type of object to create</param>
  144. /// <returns>a new object for type, or null</returns>
  145. protected object CreateInstance(Enum windowKey)
  146. {
  147. return CreateInstance(GetType(windowKey));
  148. }
  149. /// <summary>
  150. ///
  151. /// </summary>
  152. /// <param name="windowKey"></param>
  153. /// <returns></returns>
  154. protected List<object> GetObjects(Enum windowKey)
  155. {
  156. foreach (WindowType type in s_WindowsToManage.Keys)
  157. {
  158. if (type.Key.ToString() == windowKey.ToString())
  159. return s_WindowsToManage[type];
  160. }
  161. return null;
  162. }
  163. /// <summary>
  164. ///
  165. /// </summary>
  166. /// <param name="window"></param>
  167. /// <returns></returns>
  168. protected List<object> GetObjects(WindowType window)
  169. {
  170. foreach (WindowType type in s_WindowsToManage.Keys)
  171. {
  172. if (type.Key.ToString() == window.Key.ToString())
  173. return s_WindowsToManage[type];
  174. }
  175. return null;
  176. }
  177. /// <summary>
  178. ///
  179. /// </summary>
  180. /// <param name="windowKey"></param>
  181. /// <returns></returns>
  182. protected WindowType GetType(Enum windowKey)
  183. {
  184. foreach (WindowType type in s_WindowsToManage.Keys)
  185. {
  186. if (type.Key.ToString() == windowKey.ToString())
  187. return type;
  188. }
  189. return null;
  190. }
  191. /// <summary>
  192. ///
  193. /// </summary>
  194. /// <param name="window"></param>
  195. /// <param name="o"></param>
  196. /// <returns></returns>
  197. protected bool AddObject(WindowType window, object o)
  198. {
  199. if (AddWindowTypeToManage(window))
  200. {
  201. List<object> objects = GetObjects(window);
  202. if (objects.Count == 0)
  203. {
  204. objects.Add(o);
  205. return true;
  206. }
  207. else if (objects.Count > 0 && !window.IsSingleton)
  208. {
  209. objects.Add(o);
  210. return true;
  211. }
  212. }
  213. return false;
  214. }
  215. /// <summary>
  216. ///
  217. /// </summary>
  218. /// <param name="windowKey"></param>
  219. /// <param name="o"></param>
  220. /// <returns></returns>
  221. protected bool AddObject(Enum windowKey, object o)
  222. {
  223. WindowType type = GetType(windowKey);
  224. if (type != null)
  225. {
  226. List<object> objects = GetObjects(windowKey);
  227. if (objects.Count == 0)
  228. {
  229. objects.Add(o);
  230. return true;
  231. }
  232. else if (objects.Count > 0 && !type.IsSingleton)
  233. {
  234. objects.Add(o);
  235. return true;
  236. }
  237. }
  238. return false;
  239. }
  240. /// <summary>
  241. ///
  242. /// </summary>
  243. /// <param name="window"></param>
  244. /// <returns></returns>
  245. protected bool DeleteObject(WindowType window)
  246. {
  247. List<object> objects = GetObjects(window);
  248. if (objects != null && objects.Count > 0)
  249. {
  250. int nIndex = objects.Count - 1;
  251. if (objects[nIndex] is IDisposable)
  252. ((IDisposable)objects[nIndex]).Dispose();
  253. objects.RemoveAt(nIndex);
  254. return true;
  255. }
  256. return false;
  257. }
  258. /// <summary>
  259. ///
  260. /// </summary>
  261. /// <param name="windowKey"></param>
  262. /// <returns></returns>
  263. protected bool DeleteObject(Enum windowKey)
  264. {
  265. List<object> objects = GetObjects(windowKey);
  266. if (objects != null && objects.Count > 0)
  267. {
  268. int nIndex = objects.Count - 1;
  269. if (objects[nIndex] is IDisposable)
  270. ((IDisposable)objects[nIndex]).Dispose();
  271. objects.RemoveAt(nIndex);
  272. return true;
  273. }
  274. return false;
  275. }
  276. /// <summary>
  277. ///
  278. /// </summary>
  279. protected void ClearAllObjects()
  280. {
  281. // Iterate thru all objects and call dispose on them if they support it,
  282. // then clear main dictionary
  283. foreach (WindowType type in s_WindowsToManage.Keys)
  284. while (DeleteObject(type)) ;
  285. s_WindowsToManage.Clear();
  286. }
  287. /// <summary>
  288. ///
  289. /// </summary>
  290. /// <param name="window"></param>
  291. /// <returns></returns>
  292. protected bool AddWindowTypeToManage(WindowType window)
  293. {
  294. if (window != null && !IsWindowTypeManaged(window))
  295. s_WindowsToManage[window] = new List<object>();
  296. return (IsWindowTypeManaged(window));
  297. }
  298. /// <summary>
  299. ///
  300. /// </summary>
  301. /// <param name="window"></param>
  302. /// <returns></returns>
  303. protected bool IsWindowTypeManaged(WindowType window)
  304. {
  305. if (window != null)
  306. {
  307. foreach (WindowType type in s_WindowsToManage.Keys)
  308. {
  309. if (type.Key.ToString() == window.Key.ToString())
  310. return true;
  311. }
  312. }
  313. return false;
  314. }
  315. #endregion
  316. #region Abtract Methods
  317. public delegate object ShowDelegate(Enum windowKey, WindowAttributes attributes, object tag);
  318. public abstract object ShowWindow(Enum windowKey, WindowAttributes attributes, object tag);
  319. public abstract object ShowDialog(Enum windowKey, WindowAttributes attributes, object tag);
  320. public delegate bool HideCloseDelegate(Enum windowKey);
  321. public abstract bool HideWindow(Enum windowKey);
  322. public abstract bool CloseWindow(Enum windowKey);
  323. public delegate bool ActionDelegate(Enum windowKey, DelegateCollection.Bool_Param1_Window_Func action);
  324. public abstract bool RunAction(Enum windowKey, DelegateCollection.Bool_Param1_Window_Func action);
  325. public abstract void Dispose();
  326. #endregion
  327. #region Public Methods
  328. /// <summary>
  329. /// Get All Window Objects for a Window, in a readonly fashion
  330. /// </summary>
  331. /// <param name="windowKey"></param>
  332. /// <returns></returns>
  333. public object[] GetAllWindowObjectsForWindow(Enum windowKey)
  334. {
  335. List<object> objects = GetObjects(windowKey);
  336. if (objects != null)
  337. return objects.ToArray();
  338. else
  339. return null;
  340. }
  341. #endregion
  342. }
  343. #endregion
  344. #region Dispatcher Thread
  345. /// <summary>
  346. ///
  347. /// </summary>
  348. static class DispatcherThread
  349. {
  350. #region Private Static Members
  351. private static Sys.Thread s_DispatcherThread = null;
  352. private static bool s_DispatcherThreadIsInitialized = false;
  353. private static WPFWindowManager s_wpfWindowManager = null;
  354. private static DispatcherThreatType s_useWindowManagerType = DispatcherThreatType.WPF;
  355. private static WindowType[] s_windowTypes = null;
  356. private static bool s_PerformPerformanceLoad = false;
  357. #endregion
  358. #region Private Static Methods
  359. /// <summary>
  360. /// Message Loop Thread for ButtonForm
  361. /// </summary>
  362. private static void ThreadProc()
  363. {
  364. // Create WindowManager Object on this thread *Allow global access to the object*
  365. if (s_useWindowManagerType == DispatcherThreatType.WPF)
  366. s_wpfWindowManager = new WPFWindowManager(Dispatcher.CurrentDispatcher, s_windowTypes, s_PerformPerformanceLoad);
  367. s_DispatcherThreadIsInitialized = true; // always set to true to allow caller to exit out
  368. if (s_wpfWindowManager != null)
  369. {
  370. //Enter Dispatcher Message Loop
  371. System.Windows.Threading.Dispatcher.Run();
  372. }
  373. }
  374. #endregion
  375. #region Public Static Methods
  376. /// <summary>
  377. /// Retrieve the Window Manager for this Dispatcher Thread
  378. /// </summary>
  379. /// <returns>a valid window Manager or null, if none</returns>
  380. public static WindowManager GetWMForDispatcher()
  381. {
  382. if (s_DispatcherThreadIsInitialized)
  383. {
  384. if (s_useWindowManagerType == DispatcherThreatType.WPF && s_wpfWindowManager != null)
  385. return s_wpfWindowManager;
  386. }
  387. return null;
  388. }
  389. /// <summary>
  390. /// Use this function to start the Dispatcher ThreadProc(above), if needed. COM+ can shutdown the thread anytime,
  391. /// we need to make sure that the thread is alive BEFORE calling WindowManager
  392. /// </summary>
  393. public static void Start(DispatcherThreatType threatType, WindowType[] windowTypes, bool PerformPerformanceLoad, bool bWait)
  394. {
  395. if (s_DispatcherThread != null && s_DispatcherThread.IsAlive)
  396. {
  397. return;
  398. }
  399. else
  400. {
  401. s_DispatcherThreadIsInitialized = false;
  402. // Specify Thread Attributes
  403. s_useWindowManagerType = threatType;
  404. s_windowTypes = windowTypes;
  405. s_PerformPerformanceLoad = PerformPerformanceLoad;
  406. // Start a new Thread so it can become the Message Loop
  407. s_DispatcherThread = new Sys.Thread(new Sys.ThreadStart(DispatcherThread.ThreadProc));
  408. // GUI components require the thread to be STA; otherwise throws an error
  409. s_DispatcherThread.SetApartmentState(ApartmentState.STA);
  410. s_DispatcherThread.Start();
  411. // Make sure the Application Object is running
  412. // (COM will eventually just time out otherwise)
  413. if (bWait) // Syncronous call
  414. {
  415. while (!s_DispatcherThreadIsInitialized)
  416. System.Threading.Thread.Sleep(20);
  417. }
  418. }
  419. }
  420. /// <summary>
  421. /// Terminates all ButtonForm Objects and the Message Dispatcher Thread *do this only on shutdown*
  422. /// </summary>
  423. public static void Stop()
  424. {
  425. if (s_DispatcherThreadIsInitialized)
  426. {
  427. // Enforce that all WindowManagers support IDispose
  428. if (s_wpfWindowManager != null)
  429. {
  430. s_wpfWindowManager.Dispose();
  431. s_wpfWindowManager = null;
  432. }
  433. s_DispatcherThread.Abort();
  434. s_DispatcherThreadIsInitialized = false;
  435. s_DispatcherThread = null;
  436. }
  437. }
  438. #endregion
  439. }
  440. #endregion
  441. }