508 lines
16 KiB
C#
508 lines
16 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public enum DispatcherThreatType
|
|
{
|
|
WPF,
|
|
// Winforms // ~Not implmented
|
|
// Silverlight? // ~Not implemented
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Abstract Base Class all Window Managers must inherit from.
|
|
///
|
|
/// </summary>
|
|
public abstract class WindowManager : IDisposable
|
|
{
|
|
#region Private Members
|
|
|
|
private Dictionary<WindowType, List<object>> s_WindowsToManage = new Dictionary<WindowType, List<object>>();
|
|
|
|
#endregion
|
|
|
|
#region Construction
|
|
|
|
/// <summary>
|
|
/// Construct a Window Manager Object
|
|
/// </summary>
|
|
/// <param name="dispatcher">Thread Dispatcher Object</param>
|
|
/// <param name="windowTypes">Window Types this WindowManager is managing</param>
|
|
/// <param name="PerformanceLoad">true, to load performance enabled windows upon construction</param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Returns the Dispatcher Thread responsible for this Window Manager
|
|
/// </summary>
|
|
public Dispatcher Dispatcher { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Returns all the Window Types that have been set to be managed by this Window Manager
|
|
/// </summary>
|
|
public WindowType[] WindowTypes { get; private set; }
|
|
|
|
#endregion
|
|
|
|
#region Protected Common Window Object Operations
|
|
|
|
/// <summary>
|
|
/// Create a new Object Instance of type
|
|
/// </summary>
|
|
/// <param name="window">type of object to create</param>
|
|
/// <returns>a new object for type, or null</returns>
|
|
protected object CreateInstance(WindowType window)
|
|
{
|
|
object o = null;
|
|
if (window != null)
|
|
o = Activator.CreateInstance(window.T);
|
|
return o;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a new Object Instance of type
|
|
/// </summary>
|
|
/// <param name="windowKey">type of object to create</param>
|
|
/// <returns>a new object for type, or null</returns>
|
|
protected object CreateInstance(Enum windowKey)
|
|
{
|
|
return CreateInstance(GetType(windowKey));
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="windowKey"></param>
|
|
/// <returns></returns>
|
|
protected List<object> GetObjects(Enum windowKey)
|
|
{
|
|
foreach (WindowType type in s_WindowsToManage.Keys)
|
|
{
|
|
if (type.Key.ToString() == windowKey.ToString())
|
|
return s_WindowsToManage[type];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="window"></param>
|
|
/// <returns></returns>
|
|
protected List<object> GetObjects(WindowType window)
|
|
{
|
|
foreach (WindowType type in s_WindowsToManage.Keys)
|
|
{
|
|
if (type.Key.ToString() == window.Key.ToString())
|
|
return s_WindowsToManage[type];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="windowKey"></param>
|
|
/// <returns></returns>
|
|
protected WindowType GetType(Enum windowKey)
|
|
{
|
|
foreach (WindowType type in s_WindowsToManage.Keys)
|
|
{
|
|
if (type.Key.ToString() == windowKey.ToString())
|
|
return type;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="window"></param>
|
|
/// <param name="o"></param>
|
|
/// <returns></returns>
|
|
protected bool AddObject(WindowType window, object o)
|
|
{
|
|
if (AddWindowTypeToManage(window))
|
|
{
|
|
List<object> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="windowKey"></param>
|
|
/// <param name="o"></param>
|
|
/// <returns></returns>
|
|
protected bool AddObject(Enum windowKey, object o)
|
|
{
|
|
WindowType type = GetType(windowKey);
|
|
if (type != null)
|
|
{
|
|
List<object> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="window"></param>
|
|
/// <returns></returns>
|
|
protected bool DeleteObject(WindowType window)
|
|
{
|
|
List<object> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="windowKey"></param>
|
|
/// <returns></returns>
|
|
protected bool DeleteObject(Enum windowKey)
|
|
{
|
|
List<object> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="window"></param>
|
|
/// <returns></returns>
|
|
protected bool AddWindowTypeToManage(WindowType window)
|
|
{
|
|
if (window != null && !IsWindowTypeManaged(window))
|
|
s_WindowsToManage[window] = new List<object>();
|
|
|
|
return (IsWindowTypeManaged(window));
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="window"></param>
|
|
/// <returns></returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Get All Window Objects for a Window, in a readonly fashion
|
|
/// </summary>
|
|
/// <param name="windowKey"></param>
|
|
/// <returns></returns>
|
|
public object[] GetAllWindowObjectsForWindow(Enum windowKey)
|
|
{
|
|
List<object> objects = GetObjects(windowKey);
|
|
if (objects != null)
|
|
return objects.ToArray();
|
|
else
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Dispatcher Thread
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Message Loop Thread for ButtonForm
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Retrieve the Window Manager for this Dispatcher Thread
|
|
/// </summary>
|
|
/// <returns>a valid window Manager or null, if none</returns>
|
|
public static WindowManager GetWMForDispatcher()
|
|
{
|
|
if (s_DispatcherThreadIsInitialized)
|
|
{
|
|
if (s_useWindowManagerType == DispatcherThreatType.WPF && s_wpfWindowManager != null)
|
|
return s_wpfWindowManager;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Terminates all ButtonForm Objects and the Message Dispatcher Thread *do this only on shutdown*
|
|
/// </summary>
|
|
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
|
|
}
|