/Controller/Commands/CommandsCommon/DeleteFromPSMDiagramCommand.cs

# · C# · 239 lines · 149 code · 22 blank · 68 comment · 24 complexity · 27d8245d75184134c94769ce40ce020f MD5 · raw file

  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using XCase.Controller.Dialogs;
  5. using XCase.Model;
  6. namespace XCase.Controller.Commands
  7. {
  8. /// <summary>
  9. /// Removes one or more elements from a diagram, presence of the elements in other diagrams is
  10. /// not affected.
  11. /// </summary>
  12. public class DeleteFromPSMDiagramCommand : DiagramCommandBase
  13. {
  14. /// <summary>
  15. /// Elements that should be deleted
  16. /// </summary>
  17. [MandatoryArgument]
  18. public IList<Element> DeletedElements { get; set; }
  19. /// <summary>
  20. /// If set to true, <see cref="DeletedElements"/> are deleted immediately with
  21. /// their dependent elements and no dialog window is shown.
  22. /// </summary>
  23. public bool ForceDelete { get; set;}
  24. private Dictionary<Element, ViewHelper> DeletedElementsViewHelpers { get; set; }
  25. private bool safeOrdering = false;
  26. /// <summary>
  27. /// If set to true (default), command will check whether the PSM diagram is left in
  28. /// a consistent state after execution (i.e. all association have both parent
  29. /// and child present..). If the command leaves the PSM diagram in an inconsistent
  30. /// state and CheckOrdering is set to true, the command cannot be undone.
  31. /// </summary>
  32. public bool CheckOrdering { get; set; }
  33. private IEnumerable<Element> _deletionOrder;
  34. /// <summary>
  35. /// Creates new instance of <see cref="DeleteFromPSMDiagramCommand" />.
  36. /// </summary>
  37. /// <param name="Controller">command controller</param>
  38. public DeleteFromPSMDiagramCommand(DiagramController Controller)
  39. : base(Controller)
  40. {
  41. DeletedElementsViewHelpers = new Dictionary<Element, ViewHelper>();
  42. Description = CommandDescription.REMOVE_FROM_DIAGRAM;
  43. CheckOrdering = true;
  44. }
  45. private bool IsInDiagram(Element element)
  46. {
  47. return Diagram.IsElementPresent(element);
  48. }
  49. public override bool CanExecute()
  50. {
  51. foreach (Element element in DeletedElements)
  52. {
  53. if (!IsInDiagram(element))
  54. {
  55. ErrorDescription = String.Format(CommandError.CMDERR_DELETE_NONEXISTING, element);
  56. return false;
  57. }
  58. }
  59. return true;
  60. }
  61. /// <summary>
  62. /// Tells the command which elements to delete. The method uses
  63. /// interactive dialogs to specify the initial set of delted elements and
  64. /// to ask whether to delete unused elements from the model.
  65. /// </summary>
  66. /// <param name="deletedElements">set of deleted elements</param>
  67. /// <returns><code>true</code> when user pressed OK, <code>false</code> when user pressed Cancel in the</returns>
  68. public bool InitializeCommand(params Element[] deletedElements)
  69. {
  70. return InitializeCommand(null, (IEnumerable<Element>)deletedElements);
  71. }
  72. /// <summary>
  73. /// Tells the command which elements to delete. The method uses
  74. /// interactive dialogs to specify the initial set of delted elements and
  75. /// to ask whether to delete unused elements from the model.
  76. /// </summary>
  77. /// <param name="deletedElements">set of deleted elements</param>
  78. /// <param name="selectionCallback">function that is called, when selected elements are specified in the dialog. Can be set to null.</param>
  79. /// <returns><code>true</code> when user pressed OK, <code>false</code> when user pressed Cancel in the</returns>
  80. public bool InitializeCommand(Action<IEnumerable<Element>> selectionCallback, params Element[] deletedElements)
  81. {
  82. return InitializeCommand(selectionCallback, (IEnumerable<Element>)deletedElements);
  83. }
  84. /// <summary>
  85. /// Tells the command which elements to delete. The method uses
  86. /// interactive dialogs to specify the initial set of delted elements and
  87. /// to ask whether to delete unused elements from the model.
  88. /// </summary>
  89. /// <param name="deletedElements">set of deleted elements</param>
  90. /// <param name="selectionCallback">function that is called, when selected elements are specified in the dialog. Can be set to null.</param>
  91. /// <returns><code>true</code> when user pressed OK, <code>false</code> when user pressed Cancel in the</returns>
  92. public bool InitializeCommand(Action<IEnumerable<Element>> selectionCallback, IEnumerable<Element> deletedElements)
  93. {
  94. List<Element> _deleted = new List<Element>(deletedElements);
  95. ElementDependencies dependencies = ElementDependencies.FindPSMDependencies(deletedElements);
  96. DeleteDependentElementsDialog dialog = new DeleteDependentElementsDialog(dependencies);
  97. if (dependencies.Count > 0 && selectionCallback != null)
  98. {
  99. IEnumerable<Element> res = dependencies.Keys;
  100. foreach (var elements in dependencies.Values)
  101. {
  102. res = res.Union(elements);
  103. }
  104. selectionCallback(res);
  105. }
  106. if (dependencies.Count == 0 || ForceDelete || dialog.ShowDialog() == true)
  107. {
  108. if (dependencies.Count == 0 || ForceDelete) dialog.Close();
  109. // add all selected dependent elements, remove those that were not selected
  110. foreach (KeyValuePair<Element, bool> _flag in dependencies.Flags)
  111. {
  112. if (!ForceDelete && _flag.Value == false)
  113. {
  114. _deleted.Remove(_flag.Key);
  115. }
  116. }
  117. foreach (KeyValuePair<Element, bool> _flag in dependencies.Flags)
  118. {
  119. if (_flag.Value || ForceDelete)
  120. {
  121. foreach (Element element in dependencies[_flag.Key])
  122. {
  123. if (!_deleted.Contains(element))
  124. _deleted.Add(element);
  125. }
  126. }
  127. }
  128. DeletedElements = _deleted;
  129. return true;
  130. }
  131. else
  132. {
  133. return false;
  134. }
  135. }
  136. internal override void CommandOperation()
  137. {
  138. IList<Element> _deleted;
  139. // try to order elements
  140. if (PSMTree.ReturnElementsInPSMOrder(DeletedElements, out _deleted, true))
  141. {
  142. safeOrdering = true;
  143. _deletionOrder = _deleted.Reverse();
  144. }
  145. else
  146. {
  147. // this will forbid undo
  148. safeOrdering = false;
  149. _deletionOrder = DeletedElements;
  150. }
  151. foreach (Element element in _deletionOrder)
  152. {
  153. if (DeletedElements.Contains(element))
  154. {
  155. DeletedElementsViewHelpers[element] = Diagram.DiagramElements[element];
  156. element.RemoveMeFromModel();
  157. Diagram.RemoveModelElement(element);
  158. }
  159. //AssociatedElements.Add(element);
  160. }
  161. }
  162. internal override OperationResult UndoOperation()
  163. {
  164. /*
  165. * forbid undo in those cases where elements couldn't be ordered
  166. * in an ordering that would allow to put them back in the diagram
  167. * safely
  168. */
  169. if (CheckOrdering && !safeOrdering)
  170. return OperationResult.Failed;
  171. foreach (Element element in DeletedElements)
  172. {
  173. if (IsInDiagram(element))
  174. {
  175. ErrorDescription = CommandError.CMDERR_REMOVED_ELEMENT_BEING_USED;
  176. return OperationResult.Failed;
  177. }
  178. }
  179. foreach (Element element in _deletionOrder.Reverse())
  180. {
  181. if (DeletedElements.Contains(element))
  182. {
  183. element.PutMeBackToModel();
  184. Diagram.AddModelElement(element, DeletedElementsViewHelpers[element]);
  185. }
  186. }
  187. return OperationResult.OK;
  188. }
  189. }
  190. #region DeleteFromPSMDiagramCommandFactory
  191. /// <summary>
  192. /// Factory that creates instances of <see cref="DeleteFromPSMDiagramCommand"/>.
  193. /// Derived from <see cref="DiagramCommandFactory{ConcreateCommandFactory}"/>
  194. /// therefore all its product commands recieve reference
  195. /// to <see cref="DiagramController"/> during their initialization.
  196. /// </summary>
  197. public class DeleteFromPSMDiagramCommandFactory : DiagramCommandFactory<DeleteFromPSMDiagramCommandFactory>
  198. {
  199. /// <summary>
  200. /// Direct constructor is hidden to avoid user making standalone instances.
  201. /// Static <see cref="CommandFactoryBase{ConcreteCommandFactory}.Factory"/> accessor
  202. /// should be used to get the singleton instance of the factory.
  203. /// </summary>
  204. private DeleteFromPSMDiagramCommandFactory()
  205. {
  206. }
  207. /// <summary>
  208. /// Creates new instance of DeleteFromPSMDiagramCommand
  209. /// <param name="diagramController">Associated diagram controller</param>
  210. /// </summary>
  211. public override IStackedCommand Create(DiagramController diagramController)
  212. {
  213. return new DeleteFromPSMDiagramCommand(diagramController);
  214. }
  215. }
  216. #endregion
  217. }