using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sys = System.Threading; using System.Reflection; using Yaulw.WPF; using System.Threading; using System.Windows.Threading; using Yaulw.Other; namespace Yaulw.Thread { /// /// /// public enum DispatcherThreatType { WPF, // Winforms // ~Not implmented // Silverlight? // ~Not implemented } /// /// /// public class WindowType { public Type T; public Enum Key; public bool IsSingleton; public bool IsPerformanceLoaded; public WindowType(Type t, Enum Key, bool IsSingleton, bool IsPerformanceLoaded) { this.T = t; this.Key = Key; this.IsSingleton = IsSingleton; this.IsPerformanceLoaded = IsPerformanceLoaded; } } /// /// /// public class WindowAttributes { public IntPtr hWndOwner; public uint Height; public uint Width; public int Top; public int Left; public string Title; public WindowAttributes(IntPtr hWndOwner, uint Height, uint Width, int Top, int Left, string Title) { this.hWndOwner = hWndOwner; this.Height = Height; this.Width = Width; this.Top = Top; this.Left = Left; this.Title = Title; } public WindowAttributes(IntPtr hWndOwner, int Top, int Left) { this.hWndOwner = hWndOwner; this.Height = 0; this.Width = 0; this.Top = Top; this.Left = Left; this.Title = String.Empty; } public WindowAttributes(IntPtr hWndOwner) { this.hWndOwner = hWndOwner; this.Height = 0; this.Width = 0; this.Top = int.MinValue; this.Left = int.MinValue; this.Title = String.Empty; } } #region Window Manager Definition /// /// Abstract Base Class all Window Managers must inherit from. /// /// public abstract class WindowManager : IDisposable { #region Private Members private Dictionary> s_WindowsToManage = new Dictionary>(); #endregion #region Construction /// /// Construct a Window Manager Object /// /// Thread Dispatcher Object /// Window Types this WindowManager is managing /// true, to load performance enabled windows upon construction public WindowManager(Dispatcher dispatcher, WindowType[] windowTypes, bool PerformanceLoad) { Dispatcher = dispatcher; WindowTypes = windowTypes; if (Dispatcher == null) throw new ArgumentException("dispatcher can't be null"); if (windowTypes == null || windowTypes.Length < 1) throw new ArgumentException("windowTypes can't be null or empty"); // Add All Window Types foreach (WindowType type in windowTypes) { // Add the Type to be managed AddWindowTypeToManage(type); // perform performance optimization if (PerformanceLoad && type.IsPerformanceLoaded) { object o = CreateInstance(type); AddObject(type, o); } } } #endregion #region Public Properties /// /// Returns the Dispatcher Thread responsible for this Window Manager /// public Dispatcher Dispatcher { get; private set; } /// /// Returns all the Window Types that have been set to be managed by this Window Manager /// public WindowType[] WindowTypes { get; private set; } #endregion #region Protected Common Window Object Operations /// /// Create a new Object Instance of type /// /// type of object to create /// a new object for type, or null protected object CreateInstance(WindowType window) { object o = null; if (window != null) o = Activator.CreateInstance(window.T); return o; } /// /// Create a new Object Instance of type /// /// type of object to create /// a new object for type, or null protected object CreateInstance(Enum windowKey) { return CreateInstance(GetType(windowKey)); } /// /// /// /// /// protected List GetObjects(Enum windowKey) { foreach (WindowType type in s_WindowsToManage.Keys) { if (type.Key.ToString() == windowKey.ToString()) return s_WindowsToManage[type]; } return null; } /// /// /// /// /// protected List GetObjects(WindowType window) { foreach (WindowType type in s_WindowsToManage.Keys) { if (type.Key.ToString() == window.Key.ToString()) return s_WindowsToManage[type]; } return null; } /// /// /// /// /// protected WindowType GetType(Enum windowKey) { foreach (WindowType type in s_WindowsToManage.Keys) { if (type.Key.ToString() == windowKey.ToString()) return type; } return null; } /// /// /// /// /// /// protected bool AddObject(WindowType window, object o) { if (AddWindowTypeToManage(window)) { List objects = GetObjects(window); if (objects.Count == 0) { objects.Add(o); return true; } else if (objects.Count > 0 && !window.IsSingleton) { objects.Add(o); return true; } } return false; } /// /// /// /// /// /// protected bool AddObject(Enum windowKey, object o) { WindowType type = GetType(windowKey); if (type != null) { List objects = GetObjects(windowKey); if (objects.Count == 0) { objects.Add(o); return true; } else if (objects.Count > 0 && !type.IsSingleton) { objects.Add(o); return true; } } return false; } /// /// /// /// /// protected bool DeleteObject(WindowType window) { List objects = GetObjects(window); if (objects != null && objects.Count > 0) { int nIndex = objects.Count - 1; if (objects[nIndex] is IDisposable) ((IDisposable)objects[nIndex]).Dispose(); objects.RemoveAt(nIndex); return true; } return false; } /// /// /// /// /// protected bool DeleteObject(Enum windowKey) { List objects = GetObjects(windowKey); if (objects != null && objects.Count > 0) { int nIndex = objects.Count - 1; if (objects[nIndex] is IDisposable) ((IDisposable)objects[nIndex]).Dispose(); objects.RemoveAt(nIndex); return true; } return false; } /// /// /// protected void ClearAllObjects() { // Iterate thru all objects and call dispose on them if they support it, // then clear main dictionary foreach (WindowType type in s_WindowsToManage.Keys) while (DeleteObject(type)) ; s_WindowsToManage.Clear(); } /// /// /// /// /// protected bool AddWindowTypeToManage(WindowType window) { if (window != null && !IsWindowTypeManaged(window)) s_WindowsToManage[window] = new List(); return (IsWindowTypeManaged(window)); } /// /// /// /// /// protected bool IsWindowTypeManaged(WindowType window) { if (window != null) { foreach (WindowType type in s_WindowsToManage.Keys) { if (type.Key.ToString() == window.Key.ToString()) return true; } } return false; } #endregion #region Abtract Methods public delegate object ShowDelegate(Enum windowKey, WindowAttributes attributes, object tag); public abstract object ShowWindow(Enum windowKey, WindowAttributes attributes, object tag); public abstract object ShowDialog(Enum windowKey, WindowAttributes attributes, object tag); public delegate bool HideCloseDelegate(Enum windowKey); public abstract bool HideWindow(Enum windowKey); public abstract bool CloseWindow(Enum windowKey); public delegate bool ActionDelegate(Enum windowKey, DelegateCollection.Bool_Param1_Window_Func action); public abstract bool RunAction(Enum windowKey, DelegateCollection.Bool_Param1_Window_Func action); public abstract void Dispose(); #endregion #region Public Methods /// /// Get All Window Objects for a Window, in a readonly fashion /// /// /// public object[] GetAllWindowObjectsForWindow(Enum windowKey) { List objects = GetObjects(windowKey); if (objects != null) return objects.ToArray(); else return null; } #endregion } #endregion #region Dispatcher Thread /// /// /// static class DispatcherThread { #region Private Static Members private static Sys.Thread s_DispatcherThread = null; private static bool s_DispatcherThreadIsInitialized = false; private static WPFWindowManager s_wpfWindowManager = null; private static DispatcherThreatType s_useWindowManagerType = DispatcherThreatType.WPF; private static WindowType[] s_windowTypes = null; private static bool s_PerformPerformanceLoad = false; #endregion #region Private Static Methods /// /// Message Loop Thread for ButtonForm /// private static void ThreadProc() { // Create WindowManager Object on this thread *Allow global access to the object* if (s_useWindowManagerType == DispatcherThreatType.WPF) s_wpfWindowManager = new WPFWindowManager(Dispatcher.CurrentDispatcher, s_windowTypes, s_PerformPerformanceLoad); s_DispatcherThreadIsInitialized = true; // always set to true to allow caller to exit out if (s_wpfWindowManager != null) { //Enter Dispatcher Message Loop System.Windows.Threading.Dispatcher.Run(); } } #endregion #region Public Static Methods /// /// Retrieve the Window Manager for this Dispatcher Thread /// /// a valid window Manager or null, if none public static WindowManager GetWMForDispatcher() { if (s_DispatcherThreadIsInitialized) { if (s_useWindowManagerType == DispatcherThreatType.WPF && s_wpfWindowManager != null) return s_wpfWindowManager; } return null; } /// /// Use this function to start the Dispatcher ThreadProc(above), if needed. COM+ can shutdown the thread anytime, /// we need to make sure that the thread is alive BEFORE calling WindowManager /// public static void Start(DispatcherThreatType threatType, WindowType[] windowTypes, bool PerformPerformanceLoad, bool bWait) { if (s_DispatcherThread != null && s_DispatcherThread.IsAlive) { return; } else { s_DispatcherThreadIsInitialized = false; // Specify Thread Attributes s_useWindowManagerType = threatType; s_windowTypes = windowTypes; s_PerformPerformanceLoad = PerformPerformanceLoad; // Start a new Thread so it can become the Message Loop s_DispatcherThread = new Sys.Thread(new Sys.ThreadStart(DispatcherThread.ThreadProc)); // GUI components require the thread to be STA; otherwise throws an error s_DispatcherThread.SetApartmentState(ApartmentState.STA); s_DispatcherThread.Start(); // Make sure the Application Object is running // (COM will eventually just time out otherwise) if (bWait) // Syncronous call { while (!s_DispatcherThreadIsInitialized) System.Threading.Thread.Sleep(20); } } } /// /// Terminates all ButtonForm Objects and the Message Dispatcher Thread *do this only on shutdown* /// public static void Stop() { if (s_DispatcherThreadIsInitialized) { // Enforce that all WindowManagers support IDispose if (s_wpfWindowManager != null) { s_wpfWindowManager.Dispose(); s_wpfWindowManager = null; } s_DispatcherThread.Abort(); s_DispatcherThreadIsInitialized = false; s_DispatcherThread = null; } } #endregion } #endregion }