/Core/Dependencies/Wwise/samples/Tools/FilePackager/FilePackager/Commands/DelegateCommand.cs

https://bitbucket.org/barakianc/nvidia-physx-and-apex-in-gge · C# · 519 lines · 384 code · 63 blank · 72 comment · 58 complexity · fa7f082b9d43562f73ec871acf02acba MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows;
  4. using System.Windows.Input;
  5. using FilePackager.ViewModels;
  6. using FilePackager.Packaging;
  7. namespace FilePackager.Commands
  8. {
  9. /// <summary>
  10. /// This class allows delegating the commanding logic to methods passed as parameters,
  11. /// and enables a View to bind commands to objects that are not part of the element tree.
  12. /// </summary>
  13. public class DelegateCommand : ICommand
  14. {
  15. public delegate void FuncExecute(object parameter);
  16. public delegate bool FuncCanExecute(object parameter);
  17. #region Constructors
  18. /// <summary>
  19. /// Constructor
  20. /// </summary>
  21. public DelegateCommand(FuncExecute executeMethod, FuncCanExecute canExecuteMethod, bool isAutomaticRequeryDisabled, string name)
  22. {
  23. if (executeMethod == null)
  24. {
  25. throw new ArgumentNullException("executeMethod");
  26. }
  27. _name = name;
  28. _executeMethod = executeMethod;
  29. _canExecuteMethod = canExecuteMethod;
  30. _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
  31. }
  32. #endregion
  33. #region Public Methods
  34. /// <summary>
  35. /// Method to determine if the command can be executed
  36. /// </summary>
  37. public bool CanExecute(object parameter)
  38. {
  39. try
  40. {
  41. if (_canExecuteMethod != null)
  42. {
  43. return _canExecuteMethod(parameter);
  44. }
  45. }
  46. catch
  47. {
  48. // Don't show anything
  49. #if DEBUG
  50. throw new InvalidOperationException("Could not execute the CanExecute");
  51. #else
  52. return false;
  53. #endif
  54. }
  55. return true;
  56. }
  57. /// <summary>
  58. /// Execution of the command
  59. /// </summary>
  60. public bool Execute(object parameter)
  61. {
  62. bool succeeded = true;
  63. try
  64. {
  65. if (_executeMethod != null)
  66. {
  67. _executeMethod(parameter);
  68. }
  69. }
  70. catch (Exception e)
  71. {
  72. MainViewModel.Instance.Application.ShowMessage(
  73. string.Format(Properties.Resources.ErrorExecutingCommand, Name, e.Message),
  74. Severity.Error);
  75. succeeded = false;
  76. }
  77. return succeeded;
  78. }
  79. /// <summary>
  80. /// Property to enable or disable CommandManager's automatic requery on this command
  81. /// </summary>
  82. public bool IsAutomaticRequeryDisabled
  83. {
  84. get
  85. {
  86. return _isAutomaticRequeryDisabled;
  87. }
  88. set
  89. {
  90. if (_isAutomaticRequeryDisabled != value)
  91. {
  92. if (value)
  93. {
  94. CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
  95. }
  96. else
  97. {
  98. CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
  99. }
  100. _isAutomaticRequeryDisabled = value;
  101. }
  102. }
  103. }
  104. public string Name
  105. {
  106. get
  107. {
  108. if (!string.IsNullOrEmpty(_name))
  109. {
  110. return _name;
  111. }
  112. // If no name was provided, use the method name
  113. return _executeMethod.Method.Name;
  114. }
  115. }
  116. /// <summary>
  117. /// Raises the CanExecuteChaged event
  118. /// </summary>
  119. public void RaiseCanExecuteChanged()
  120. {
  121. OnCanExecuteChanged();
  122. }
  123. /// <summary>
  124. /// Protected virtual method to raise CanExecuteChanged event
  125. /// </summary>
  126. protected virtual void OnCanExecuteChanged()
  127. {
  128. CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
  129. }
  130. #endregion
  131. #region ICommand Members
  132. /// <summary>
  133. /// ICommand.CanExecuteChanged implementation
  134. /// </summary>
  135. public event EventHandler CanExecuteChanged
  136. {
  137. add
  138. {
  139. if (!_isAutomaticRequeryDisabled)
  140. {
  141. CommandManager.RequerySuggested += value;
  142. }
  143. CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
  144. }
  145. remove
  146. {
  147. if (!_isAutomaticRequeryDisabled)
  148. {
  149. CommandManager.RequerySuggested -= value;
  150. }
  151. CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
  152. }
  153. }
  154. bool ICommand.CanExecute(object parameter)
  155. {
  156. return CanExecute(parameter);
  157. }
  158. void ICommand.Execute(object parameter)
  159. {
  160. Execute(parameter);
  161. }
  162. #endregion
  163. #region Data
  164. private readonly FuncExecute _executeMethod = null;
  165. private readonly FuncCanExecute _canExecuteMethod = null;
  166. private bool _isAutomaticRequeryDisabled = false;
  167. private List<WeakReference> _canExecuteChangedHandlers;
  168. private string _name;
  169. #endregion
  170. }
  171. /// <summary>
  172. /// This class allows delegating the commanding logic to methods passed as parameters,
  173. /// and enables a View to bind commands to objects that are not part of the element tree.
  174. /// </summary>
  175. /// <typeparam name="T">Type of the parameter passed to the delegates</typeparam>
  176. public class DelegateCommand<T> : ICommand
  177. {
  178. #region Constructors
  179. /// <summary>
  180. /// Constructor
  181. /// </summary>
  182. public DelegateCommand(Action<T> executeMethod)
  183. : this(executeMethod, null, false)
  184. {
  185. }
  186. /// <summary>
  187. /// Constructor
  188. /// </summary>
  189. public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
  190. : this(executeMethod, canExecuteMethod, false)
  191. {
  192. }
  193. /// <summary>
  194. /// Constructor
  195. /// </summary>
  196. public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
  197. {
  198. if (executeMethod == null)
  199. {
  200. throw new ArgumentNullException("executeMethod");
  201. }
  202. _executeMethod = executeMethod;
  203. _canExecuteMethod = canExecuteMethod;
  204. _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
  205. }
  206. #endregion
  207. #region Public Methods
  208. /// <summary>
  209. /// Method to determine if the command can be executed
  210. /// </summary>
  211. public bool CanExecute(T parameter)
  212. {
  213. if (_canExecuteMethod != null)
  214. {
  215. return _canExecuteMethod(parameter);
  216. }
  217. return true;
  218. }
  219. /// <summary>
  220. /// Execution of the command
  221. /// </summary>
  222. public void Execute(T parameter)
  223. {
  224. if (_executeMethod != null)
  225. {
  226. _executeMethod(parameter);
  227. }
  228. }
  229. /// <summary>
  230. /// Raises the CanExecuteChaged event
  231. /// </summary>
  232. public void RaiseCanExecuteChanged()
  233. {
  234. OnCanExecuteChanged();
  235. }
  236. /// <summary>
  237. /// Protected virtual method to raise CanExecuteChanged event
  238. /// </summary>
  239. protected virtual void OnCanExecuteChanged()
  240. {
  241. CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
  242. }
  243. /// <summary>
  244. /// Property to enable or disable CommandManager's automatic requery on this command
  245. /// </summary>
  246. public bool IsAutomaticRequeryDisabled
  247. {
  248. get
  249. {
  250. return _isAutomaticRequeryDisabled;
  251. }
  252. set
  253. {
  254. if (_isAutomaticRequeryDisabled != value)
  255. {
  256. if (value)
  257. {
  258. CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
  259. }
  260. else
  261. {
  262. CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
  263. }
  264. _isAutomaticRequeryDisabled = value;
  265. }
  266. }
  267. }
  268. #endregion
  269. #region ICommand Members
  270. /// <summary>
  271. /// ICommand.CanExecuteChanged implementation
  272. /// </summary>
  273. public event EventHandler CanExecuteChanged
  274. {
  275. add
  276. {
  277. if (!_isAutomaticRequeryDisabled)
  278. {
  279. CommandManager.RequerySuggested += value;
  280. }
  281. CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
  282. }
  283. remove
  284. {
  285. if (!_isAutomaticRequeryDisabled)
  286. {
  287. CommandManager.RequerySuggested -= value;
  288. }
  289. CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
  290. }
  291. }
  292. bool ICommand.CanExecute(object parameter)
  293. {
  294. // if T is of value type and the parameter is not
  295. // set yet, then return false if CanExecute delegate
  296. // exists, else return true
  297. if (parameter == null &&
  298. typeof(T).IsValueType)
  299. {
  300. return (_canExecuteMethod == null);
  301. }
  302. return CanExecute((T)parameter);
  303. }
  304. void ICommand.Execute(object parameter)
  305. {
  306. Execute((T)parameter);
  307. }
  308. #endregion
  309. #region Data
  310. private readonly Action<T> _executeMethod = null;
  311. private readonly Func<T, bool> _canExecuteMethod = null;
  312. private bool _isAutomaticRequeryDisabled = false;
  313. private List<WeakReference> _canExecuteChangedHandlers;
  314. #endregion
  315. }
  316. /// <summary>
  317. /// This class contains methods for the CommandManager that help avoid memory leaks by
  318. /// using weak references.
  319. /// </summary>
  320. internal class CommandManagerHelper
  321. {
  322. internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
  323. {
  324. if (handlers != null)
  325. {
  326. // Take a snapshot of the handlers before we call out to them since the handlers
  327. // could cause the array to me modified while we are reading it.
  328. EventHandler[] callees = new EventHandler[handlers.Count];
  329. int count = 0;
  330. for (int i = handlers.Count - 1; i >= 0; i--)
  331. {
  332. WeakReference reference = handlers[i];
  333. EventHandler handler = reference.Target as EventHandler;
  334. if (handler == null)
  335. {
  336. // Clean up old handlers that have been collected
  337. handlers.RemoveAt(i);
  338. }
  339. else
  340. {
  341. callees[count] = handler;
  342. count++;
  343. }
  344. }
  345. // Call the handlers that we snapshotted
  346. for (int i = 0; i < count; i++)
  347. {
  348. EventHandler handler = callees[i];
  349. handler(null, EventArgs.Empty);
  350. }
  351. }
  352. }
  353. internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers)
  354. {
  355. if (handlers != null)
  356. {
  357. foreach (WeakReference handlerRef in handlers)
  358. {
  359. EventHandler handler = handlerRef.Target as EventHandler;
  360. if (handler != null)
  361. {
  362. CommandManager.RequerySuggested += handler;
  363. }
  364. }
  365. }
  366. }
  367. internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers)
  368. {
  369. if (handlers != null)
  370. {
  371. foreach (WeakReference handlerRef in handlers)
  372. {
  373. EventHandler handler = handlerRef.Target as EventHandler;
  374. if (handler != null)
  375. {
  376. CommandManager.RequerySuggested -= handler;
  377. }
  378. }
  379. }
  380. }
  381. internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler)
  382. {
  383. AddWeakReferenceHandler(ref handlers, handler, -1);
  384. }
  385. internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
  386. {
  387. if (handlers == null)
  388. {
  389. handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
  390. }
  391. handlers.Add(new WeakReference(handler));
  392. }
  393. internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
  394. {
  395. if (handlers != null)
  396. {
  397. for (int i = handlers.Count - 1; i >= 0; i--)
  398. {
  399. WeakReference reference = handlers[i];
  400. EventHandler existingHandler = reference.Target as EventHandler;
  401. if ((existingHandler == null) || (existingHandler == handler))
  402. {
  403. // Clean up old handlers that have been collected
  404. // in addition to the handler that is to be removed.
  405. handlers.RemoveAt(i);
  406. }
  407. }
  408. }
  409. }
  410. internal static ICommand CreateOnceCommand(ref DelegateCommand command, Action executeMethod, Func<bool> canExecuteMethod)
  411. {
  412. return CreateOnceCommand(ref command, executeMethod, canExecuteMethod, null);
  413. }
  414. internal static ICommand CreateOnceCommand(ref DelegateCommand command, Action executeMethod, Func<bool> canExecuteMethod, string name)
  415. {
  416. if (command == null)
  417. {
  418. if (executeMethod == null)
  419. {
  420. throw new ArgumentNullException("executeMethod");
  421. }
  422. if (string.IsNullOrEmpty(name))
  423. {
  424. name = executeMethod.Method.Name;
  425. }
  426. DelegateCommand.FuncExecute execute =
  427. delegate
  428. {
  429. executeMethod();
  430. };
  431. DelegateCommand.FuncCanExecute canExecute = null;
  432. if(canExecuteMethod != null )
  433. {
  434. canExecute = delegate(object parameter)
  435. {
  436. return canExecuteMethod();
  437. };
  438. }
  439. command = new DelegateCommand(execute, canExecute,false, name);
  440. }
  441. return command;
  442. }
  443. internal static ICommand CreateOnceCommand(ref DelegateCommand command, DelegateCommand.FuncExecute execute, DelegateCommand.FuncCanExecute canExecute)
  444. {
  445. return CreateOnceCommand(ref command, execute, canExecute, null);
  446. }
  447. internal static ICommand CreateOnceCommand(ref DelegateCommand command, DelegateCommand.FuncExecute execute, DelegateCommand.FuncCanExecute canExecute, string name)
  448. {
  449. if (command == null)
  450. {
  451. command = new DelegateCommand(execute, canExecute,false, name);
  452. }
  453. return command;
  454. }
  455. }
  456. }