PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/AutomationMLMapping Tool/trunk/Avalon Version2.0/AvalonDock/AvalonDock/Controls/FocusElementManager.cs

http://AutomationMLMapper.codeplex.com
C# | 241 lines | 173 code | 37 blank | 31 comment | 50 complexity | 420bd207c01e81f729f23e86c1bbd835 MD5 | raw file
  1. //Copyright (c) 2007-2012, Adolfo Marinucci
  2. //All rights reserved.
  3. //Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
  4. //following conditions are met:
  5. //* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  6. //* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
  7. //disclaimer in the documentation and/or other materials provided with the distribution.
  8. //* Neither the name of Adolfo Marinucci nor the names of its contributors may be used to endorse or promote products
  9. //derived from this software without specific prior written permission.
  10. //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  11. //INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  12. //IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  13. //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  14. //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  15. //STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  16. //EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Linq;
  20. using System.Text;
  21. using System.Windows.Input;
  22. using System.Windows.Interop;
  23. using System.Windows;
  24. using System.Diagnostics;
  25. using AvalonDock.Layout;
  26. using System.Windows.Media;
  27. namespace AvalonDock.Controls
  28. {
  29. internal static class FocusElementManager
  30. {
  31. #region Focus Management
  32. static List<DockingManager> _managers = new List<DockingManager>();
  33. internal static void SetupFocusManagement(DockingManager manager)
  34. {
  35. if (_managers.Count == 0)
  36. {
  37. InputManager.Current.EnterMenuMode += new EventHandler(InputManager_EnterMenuMode);
  38. InputManager.Current.LeaveMenuMode += new EventHandler(InputManager_LeaveMenuMode);
  39. _windowHandler = new WindowHookHandler();
  40. _windowHandler.FocusChanged += new EventHandler<FocusChangeEventArgs>(_windowHandler_FocusChanged);
  41. _windowHandler.Activate += new EventHandler(_windowHandler_Activate);
  42. _windowHandler.Attach();
  43. Application.Current.Exit += new ExitEventHandler(Current_Exit);
  44. }
  45. manager.PreviewGotKeyboardFocus += new KeyboardFocusChangedEventHandler(manager_PreviewGotKeyboardFocus);
  46. _managers.Add(manager);
  47. }
  48. internal static void FinalizeFocusManagement(DockingManager manager)
  49. {
  50. manager.PreviewGotKeyboardFocus -= new KeyboardFocusChangedEventHandler(manager_PreviewGotKeyboardFocus);
  51. _managers.Remove(manager);
  52. if (_managers.Count == 0)
  53. {
  54. InputManager.Current.EnterMenuMode -= new EventHandler(InputManager_EnterMenuMode);
  55. InputManager.Current.LeaveMenuMode -= new EventHandler(InputManager_LeaveMenuMode);
  56. if (_windowHandler != null)
  57. {
  58. _windowHandler.FocusChanged -= new EventHandler<FocusChangeEventArgs>(_windowHandler_FocusChanged);
  59. _windowHandler.Activate -= new EventHandler(_windowHandler_Activate);
  60. _windowHandler.Detach();
  61. _windowHandler = null;
  62. }
  63. }
  64. }
  65. static void _windowHandler_Activate(object sender, EventArgs e)
  66. {
  67. if (Keyboard.FocusedElement == null && _lastFocusedElement != null && _lastFocusedElement.IsAlive)
  68. {
  69. var elementToSetFocus = _lastFocusedElement.Target as ILayoutElement;
  70. if (elementToSetFocus != null)
  71. {
  72. //SetFocusOnLastElement(elementToSetFocus);
  73. _lastFocusedElement = null;
  74. }
  75. }
  76. }
  77. private static void Current_Exit(object sender, ExitEventArgs e)
  78. {
  79. Application.Current.Exit -= new ExitEventHandler(Current_Exit);
  80. if (_windowHandler != null)
  81. {
  82. _windowHandler.FocusChanged -= new EventHandler<FocusChangeEventArgs>(_windowHandler_FocusChanged);
  83. _windowHandler.Detach();
  84. _windowHandler = null;
  85. }
  86. }
  87. static void manager_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
  88. {
  89. var focusedElement = e.NewFocus as Visual;
  90. if (focusedElement != null && !(focusedElement is LayoutAnchorableTabItem || focusedElement is LayoutDocumentTabItem))
  91. {
  92. var parentAnchorable = focusedElement.FindVisualAncestor<LayoutAnchorableControl>();
  93. if (parentAnchorable != null)
  94. {
  95. _modelFocusedElement[parentAnchorable.Model] = e.NewFocus;
  96. }
  97. else
  98. {
  99. var parentDocument = focusedElement.FindVisualAncestor<LayoutDocumentControl>();
  100. if (parentDocument != null)
  101. {
  102. _modelFocusedElement[parentDocument.Model] = e.NewFocus;
  103. }
  104. }
  105. }
  106. }
  107. static WeakDictionary<ILayoutElement, IInputElement> _modelFocusedElement = new WeakDictionary<ILayoutElement, IInputElement>();
  108. static WeakDictionary<ILayoutElement, IntPtr> _modelFocusedWindowHandle = new WeakDictionary<ILayoutElement, IntPtr>();
  109. /// <summary>
  110. /// Get the input element that was focused before user left the layout element
  111. /// </summary>
  112. /// <param name="model">Element to look for</param>
  113. /// <returns>Input element </returns>
  114. internal static IInputElement GetLastFocusedElement(ILayoutElement model)
  115. {
  116. IInputElement objectWithFocus;
  117. if (_modelFocusedElement.GetValue(model, out objectWithFocus))
  118. return objectWithFocus;
  119. return null;
  120. }
  121. /// <summary>
  122. /// Get the last window handle focused before user left the element passed as argument
  123. /// </summary>
  124. /// <param name="model"></param>
  125. /// <returns></returns>
  126. internal static IntPtr GetLastWindowHandle(ILayoutElement model)
  127. {
  128. IntPtr handleWithFocus;
  129. if (_modelFocusedWindowHandle.GetValue(model, out handleWithFocus))
  130. return handleWithFocus;
  131. return IntPtr.Zero;
  132. }
  133. static WeakReference _lastFocusedElement;
  134. /// <summary>
  135. /// Given a layout element tries to set the focus of the keyword where it was before user moved to another element
  136. /// </summary>
  137. /// <param name="model"></param>
  138. internal static void SetFocusOnLastElement(ILayoutElement model)
  139. {
  140. bool focused = false;
  141. IInputElement objectToFocus;
  142. if (_modelFocusedElement.GetValue(model, out objectToFocus))
  143. focused = objectToFocus == Keyboard.Focus(objectToFocus);
  144. IntPtr handleToFocus;
  145. if (_modelFocusedWindowHandle.GetValue(model, out handleToFocus))
  146. focused = IntPtr.Zero != Win32Helper.SetFocus(handleToFocus);
  147. if (focused)
  148. _lastFocusedElement = new WeakReference(model);
  149. }
  150. static WindowHookHandler _windowHandler = null;
  151. static void _windowHandler_FocusChanged(object sender, FocusChangeEventArgs e)
  152. {
  153. foreach (var manager in _managers)
  154. {
  155. var hostContainingFocusedHandle = manager.FindLogicalChildren<HwndHost>().FirstOrDefault(hw => Win32Helper.IsChild(hw.Handle, e.GotFocusWinHandle));
  156. if (hostContainingFocusedHandle != null)
  157. {
  158. var parentAnchorable = hostContainingFocusedHandle.FindVisualAncestor<LayoutAnchorableControl>();
  159. if (parentAnchorable != null)
  160. {
  161. _modelFocusedWindowHandle[parentAnchorable.Model] = e.GotFocusWinHandle;
  162. if (parentAnchorable.Model != null)
  163. parentAnchorable.Model.IsActive = true;
  164. }
  165. else
  166. {
  167. var parentDocument = hostContainingFocusedHandle.FindVisualAncestor<LayoutDocumentControl>();
  168. if (parentDocument != null)
  169. {
  170. _modelFocusedWindowHandle[parentDocument.Model] = e.GotFocusWinHandle;
  171. if (parentDocument.Model != null)
  172. parentDocument.Model.IsActive = true;
  173. }
  174. }
  175. }
  176. }
  177. }
  178. static WeakReference _lastFocusedElementBeforeEnterMenuMode = null;
  179. static void InputManager_EnterMenuMode(object sender, EventArgs e)
  180. {
  181. if (Keyboard.FocusedElement == null)
  182. return;
  183. var lastfocusDepObj = Keyboard.FocusedElement as DependencyObject;
  184. if (lastfocusDepObj.FindLogicalAncestor<DockingManager>() == null)
  185. {
  186. _lastFocusedElementBeforeEnterMenuMode = null;
  187. return;
  188. }
  189. _lastFocusedElementBeforeEnterMenuMode = new WeakReference(Keyboard.FocusedElement);
  190. }
  191. static void InputManager_LeaveMenuMode(object sender, EventArgs e)
  192. {
  193. if (_lastFocusedElementBeforeEnterMenuMode != null &&
  194. _lastFocusedElementBeforeEnterMenuMode.IsAlive)
  195. {
  196. var lastFocusedInputElement = _lastFocusedElementBeforeEnterMenuMode.Target as IInputElement;
  197. if (lastFocusedInputElement != null)
  198. if (lastFocusedInputElement != Keyboard.Focus(lastFocusedInputElement))
  199. Debug.WriteLine("Unable to activate the element");
  200. }
  201. }
  202. #endregion
  203. }
  204. }