PageRenderTime 3677ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/CodeMaid/UI/ToolWindows/Spade/SpadeToolWindow.cs

https://bitbucket.org/s_cadwallader/codemaid/
C# | 330 lines | 200 code | 57 blank | 73 comment | 27 complexity | 29c0ae35bec892e43cac7fa9b8efe396 MD5 | raw file
Possible License(s): LGPL-3.0
  1. #region CodeMaid is Copyright 2007-2014 Steve Cadwallader.
  2. // CodeMaid is free software: you can redistribute it and/or modify it under the terms of the GNU
  3. // Lesser General Public License version 3 as published by the Free Software Foundation.
  4. //
  5. // CodeMaid is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
  6. // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  7. // Lesser General Public License for more details <http://www.gnu.org/licenses/>.
  8. #endregion CodeMaid is Copyright 2007-2014 Steve Cadwallader.
  9. using EnvDTE;
  10. using Microsoft.VisualStudio;
  11. using Microsoft.VisualStudio.Shell;
  12. using Microsoft.VisualStudio.Shell.Interop;
  13. using SteveCadwallader.CodeMaid.Integration;
  14. using SteveCadwallader.CodeMaid.Model;
  15. using SteveCadwallader.CodeMaid.Model.CodeItems;
  16. using SteveCadwallader.CodeMaid.Model.CodeTree;
  17. using SteveCadwallader.CodeMaid.Properties;
  18. using System;
  19. using System.ComponentModel.Design;
  20. using System.Linq;
  21. using System.Runtime.InteropServices;
  22. using System.Windows;
  23. using System.Windows.Threading;
  24. using CodeModel = SteveCadwallader.CodeMaid.Model.CodeModel;
  25. namespace SteveCadwallader.CodeMaid.UI.ToolWindows.Spade
  26. {
  27. /// <summary>
  28. /// The Spade tool window pane.
  29. /// </summary>
  30. [Guid(GuidList.GuidCodeMaidToolWindowSpadeString)]
  31. public class SpadeToolWindow : ToolWindowPane, IVsWindowFrameNotify3
  32. {
  33. #region Fields
  34. private readonly SpadeViewModel _viewModel;
  35. private CodeModelManager _codeModelManager;
  36. private Document _document;
  37. private bool _isVisible;
  38. #endregion Fields
  39. #region Constructors
  40. /// <summary>
  41. /// Initializes a new instance of the <see cref="SpadeToolWindow" /> class.
  42. /// </summary>
  43. public SpadeToolWindow()
  44. : base(null)
  45. {
  46. // Set the tool window caption.
  47. Caption = "CodeMaid Spade";
  48. // Set the tool window image from resources.
  49. BitmapResourceID = 508;
  50. BitmapIndex = 0;
  51. // Create the toolbar for the tool window.
  52. ToolBar = new CommandID(GuidList.GuidCodeMaidToolbarSpadeBaseGroup, PkgCmdIDList.ToolbarIDCodeMaidToolbarSpade);
  53. // Setup the associated classes.
  54. _viewModel = new SpadeViewModel();
  55. // Register for view model requests to be refreshed.
  56. _viewModel.RequestingRefresh += (sender, args) => Refresh();
  57. // Create and set the view.
  58. base.Content = new SpadeView { DataContext = _viewModel };
  59. // Register for changes to settings.
  60. Settings.Default.SettingsSaving += (sender, args) => Refresh();
  61. }
  62. #endregion Constructors
  63. #region Public Properties
  64. /// <summary>
  65. /// Gets or sets the layout mode.
  66. /// </summary>
  67. public TreeLayoutMode LayoutMode
  68. {
  69. get { return _viewModel.LayoutMode; }
  70. set { _viewModel.LayoutMode = value; }
  71. }
  72. /// <summary>
  73. /// Gets the selected item.
  74. /// </summary>
  75. public BaseCodeItem SelectedItem
  76. {
  77. get { return _viewModel.SelectedItem; }
  78. }
  79. #endregion Public Properties
  80. #region Public Methods
  81. /// <summary>
  82. /// A method to be called to notify the tool window about the current active document.
  83. /// </summary>
  84. /// <param name="document">The active document.</param>
  85. public void NotifyActiveDocument(Document document)
  86. {
  87. Document = document;
  88. }
  89. /// <summary>
  90. /// A method to be called to notify the tool window that has a document has been saved.
  91. /// </summary>
  92. /// <param name="document">The document.</param>
  93. public void NotifyDocumentSave(Document document)
  94. {
  95. if (Document == document)
  96. {
  97. // Refresh the document if active.
  98. Refresh();
  99. }
  100. }
  101. /// <summary>
  102. /// This method can be overriden by the derived class to execute any code that needs to run
  103. /// after the IVsWindowFrame is created. If the toolwindow has a toolbar with a combobox, it
  104. /// should make sure its command handler are set by the time they return from this method.
  105. /// This is called when someone set the Frame property.
  106. /// </summary>
  107. public override void OnToolWindowCreated()
  108. {
  109. base.OnToolWindowCreated();
  110. // Register for events to this window.
  111. ((IVsWindowFrame)Frame).SetProperty((int)__VSFPROPID.VSFPROPID_ViewHelper, this);
  112. // Package is not available at constructor time.
  113. if (Package != null)
  114. {
  115. // Get an instance of the code model manager.
  116. _codeModelManager = CodeModelManager.GetInstance(Package);
  117. _codeModelManager.CodeModelBuilt += OnCodeModelBuilt;
  118. // Pass the package over to the view model.
  119. _viewModel.Package = Package;
  120. // Attempt to initialize the Document, may have been set before Spade was created.
  121. if (Document == null)
  122. {
  123. Document = Package.ActiveDocument;
  124. }
  125. var spadeContent = Content as FrameworkElement;
  126. if (spadeContent != null)
  127. {
  128. spadeContent.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => Package.ThemeManager.ApplyTheme()));
  129. }
  130. }
  131. }
  132. /// <summary>
  133. /// Refresh the Spade tool window.
  134. /// </summary>
  135. public void Refresh()
  136. {
  137. if (Package != null)
  138. {
  139. Package.ThemeManager.ApplyTheme();
  140. }
  141. ConditionallyUpdateCodeModel(true);
  142. }
  143. #endregion Public Methods
  144. #region Private Properties
  145. /// <summary>
  146. /// Gets or sets the current document.
  147. /// </summary>
  148. private Document Document
  149. {
  150. get { return _document; }
  151. set
  152. {
  153. if (_document != value)
  154. {
  155. _document = value;
  156. ConditionallyUpdateCodeModel(false);
  157. }
  158. }
  159. }
  160. /// <summary>
  161. /// Gets or sets a flag indicating if this tool window is visible.
  162. /// </summary>
  163. private bool IsVisible
  164. {
  165. get { return _isVisible; }
  166. set
  167. {
  168. if (_isVisible != value)
  169. {
  170. _isVisible = value;
  171. ConditionallyUpdateCodeModel(false);
  172. }
  173. }
  174. }
  175. /// <summary>
  176. /// Gets or sets the package that owns the tool window.
  177. /// </summary>
  178. private new CodeMaidPackage Package { get { return base.Package as CodeMaidPackage; } }
  179. #endregion Private Properties
  180. #region Private Methods
  181. /// <summary>
  182. /// Conditionally updates the code model.
  183. /// </summary>
  184. /// <param name="isRefresh">True if refreshing a document, otherwise false.</param>
  185. private void ConditionallyUpdateCodeModel(bool isRefresh)
  186. {
  187. if (!IsVisible) return;
  188. _viewModel.Document = Document;
  189. _viewModel.IsLoading = false;
  190. _viewModel.IsRefreshing = false;
  191. if (Document == null || !isRefresh)
  192. {
  193. _viewModel.RawCodeItems = null;
  194. }
  195. if (Document != null)
  196. {
  197. if (isRefresh)
  198. {
  199. _codeModelManager.OnDocumentChanged(Document);
  200. _viewModel.IsRefreshing = true;
  201. }
  202. else
  203. {
  204. _viewModel.IsLoading = true;
  205. }
  206. var codeItems = _codeModelManager.RetrieveAllCodeItemsAsync(Document, true);
  207. if (codeItems != null)
  208. {
  209. UpdateViewModelRawCodeItems(codeItems);
  210. }
  211. }
  212. }
  213. /// <summary>
  214. /// An event handler called when the <see cref="CodeModelManager" /> raises a <see
  215. /// cref="CodeModelManager.CodeModelBuilt" /> event. If the code model was built for the
  216. /// document currently being shown by Spade, the raw code items will be processed and displayed.
  217. /// </summary>
  218. /// <param name="codeModel">The code model.</param>
  219. private void OnCodeModelBuilt(CodeModel codeModel)
  220. {
  221. if (Document == codeModel.Document)
  222. {
  223. UpdateViewModelRawCodeItems(codeModel.CodeItems);
  224. }
  225. }
  226. /// <summary>
  227. /// Update the view model's raw set of code items based on the specified code items.
  228. /// </summary>
  229. /// <param name="codeItems">The code items.</param>
  230. private void UpdateViewModelRawCodeItems(SetCodeItems codeItems)
  231. {
  232. // Create a copy of the original collection, filtering out undesired items.
  233. var filteredCodeItems = new SetCodeItems(
  234. codeItems.Where(x => !(x is CodeItemUsingStatement || x is CodeItemNamespace)));
  235. _viewModel.RawCodeItems = filteredCodeItems;
  236. _viewModel.IsLoading = false;
  237. _viewModel.IsRefreshing = false;
  238. }
  239. #endregion Private Methods
  240. #region IVsWindowFrameNotify3 Members
  241. public int OnClose(ref uint pgrfSaveOptions)
  242. {
  243. return VSConstants.S_OK;
  244. }
  245. public int OnDockableChange(int fDockable, int x, int y, int w, int h)
  246. {
  247. return VSConstants.S_OK;
  248. }
  249. public int OnMove(int x, int y, int w, int h)
  250. {
  251. return VSConstants.S_OK;
  252. }
  253. public int OnShow(int fShow)
  254. {
  255. // Track the visibility of this tool window.
  256. switch ((__FRAMESHOW)fShow)
  257. {
  258. case __FRAMESHOW.FRAMESHOW_WinShown:
  259. IsVisible = true;
  260. break;
  261. case __FRAMESHOW.FRAMESHOW_WinHidden:
  262. IsVisible = false;
  263. break;
  264. }
  265. return VSConstants.S_OK;
  266. }
  267. public int OnSize(int x, int y, int w, int h)
  268. {
  269. return VSConstants.S_OK;
  270. }
  271. #endregion IVsWindowFrameNotify3 Members
  272. }
  273. }