PageRenderTime 2855ms CodeModel.GetById 29ms RepoModel.GetById 6ms app.codeStats 1ms

/Servicing/1.0/Release/Product/Python/ReplWindow/Repl/ReplWindowProvider.cs

#
C# | 227 lines | 168 code | 43 blank | 16 comment | 32 complexity | f2857930abd2f9f64bd912a9a7c0a3d3 MD5 | raw file
Possible License(s): Apache-2.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. * ***************************************************************************/
  14. using System;
  15. using System.Collections.Generic;
  16. using System.ComponentModel.Composition;
  17. using Microsoft.VisualStudio.ComponentModelHost;
  18. using Microsoft.VisualStudio.Shell;
  19. using Microsoft.VisualStudio.Shell.Interop;
  20. using Microsoft.VisualStudio.Utilities;
  21. using Microsoft.Win32;
  22. namespace Microsoft.VisualStudio.Repl {
  23. [Export(typeof(IReplWindowProvider))]
  24. [PartCreationPolicy(CreationPolicy.Shared)]
  25. internal sealed class ReplWindowProvider : IReplWindowProvider {
  26. private readonly IReplEvaluatorProvider[] _evaluators;
  27. private readonly Dictionary<int, ReplWindow> _windows = new Dictionary<int, ReplWindow>();
  28. [ImportingConstructor]
  29. public ReplWindowProvider([ImportMany]IReplEvaluatorProvider[] evaluators) {
  30. _evaluators = evaluators;
  31. }
  32. #region IReplWindowProvider Members
  33. public IReplWindow CreateReplWindow(IContentType contentType, string/*!*/ title, Guid languageServiceGuid, string replId) {
  34. int curId = 0;
  35. ReplWindow window;
  36. do {
  37. curId++;
  38. window = FindReplWindowInternal(curId);
  39. } while (window != null);
  40. foreach (var provider in _evaluators) {
  41. var evaluator = provider.GetEvaluator(replId);
  42. if (evaluator != null) {
  43. window = CreateReplWindowInternal(evaluator, contentType, curId, title, languageServiceGuid, replId);
  44. if ((null == window) || (null == window.Frame)) {
  45. throw new NotSupportedException(Resources.CanNotCreateWindow);
  46. }
  47. return window;
  48. }
  49. }
  50. throw new InvalidOperationException(String.Format("ReplId {0} was not provided by an IReplWindowProvider", replId));
  51. }
  52. public IReplWindow FindReplWindow(string replId) {
  53. foreach (var idAndWindow in _windows) {
  54. var window = idAndWindow.Value;
  55. if (window.ReplId == replId) {
  56. return window;
  57. }
  58. }
  59. return null;
  60. }
  61. public IEnumerable<IReplWindow> GetReplWindows() {
  62. return _windows.Values;
  63. }
  64. private static IReplEvaluator GetReplEvaluator(IComponentModel model, string replId) {
  65. foreach (var provider in model.GetExtensions<IReplEvaluatorProvider>()) {
  66. var evaluator = provider.GetEvaluator(replId);
  67. if (evaluator != null) {
  68. return evaluator;
  69. }
  70. }
  71. return null;
  72. }
  73. #endregion
  74. #region Registry Serialization
  75. private const string ActiveReplsKey = "ActiveRepls";
  76. private const string ContentTypeKey = "ContentType";
  77. private const string TitleKey = "Title";
  78. private const string ReplIdKey = "ReplId";
  79. private const string LanguageServiceGuidKey = "LanguageServiceGuid";
  80. private static RegistryKey GetRegistryRoot() {
  81. return VSRegistry.RegistryRoot(__VsLocalRegistryType.RegType_UserSettings, writable: true).CreateSubKey(ActiveReplsKey);
  82. }
  83. private void SaveReplInfo(int id, IReplEvaluator evaluator, IContentType contentType, string title, Guid languageServiceGuid, string replId) {
  84. using (var root = GetRegistryRoot()) {
  85. if (root != null) {
  86. using (var replInfo = root.CreateSubKey(id.ToString())) {
  87. replInfo.SetValue(ContentTypeKey, contentType.TypeName);
  88. replInfo.SetValue(TitleKey, title);
  89. replInfo.SetValue(ReplIdKey, replId.ToString());
  90. replInfo.SetValue(LanguageServiceGuidKey, languageServiceGuid.ToString());
  91. }
  92. }
  93. }
  94. }
  95. internal bool CreateFromRegistry(IComponentModel model, int id) {
  96. string contentTypeName, title, replId, languageServiceId;
  97. using (var root = GetRegistryRoot()) {
  98. if (root == null) {
  99. return false;
  100. }
  101. using (var replInfo = root.OpenSubKey(id.ToString())) {
  102. if (replInfo == null) {
  103. return false;
  104. }
  105. contentTypeName = replInfo.GetValue(ContentTypeKey) as string;
  106. if (contentTypeName == null) {
  107. return false;
  108. }
  109. title = replInfo.GetValue(TitleKey) as string;
  110. if (title == null) {
  111. return false;
  112. }
  113. replId = replInfo.GetValue(ReplIdKey) as string;
  114. if (replId == null) {
  115. return false;
  116. }
  117. languageServiceId = replInfo.GetValue(LanguageServiceGuidKey) as string;
  118. if (languageServiceId == null) {
  119. return false;
  120. }
  121. }
  122. }
  123. Guid languageServiceGuid;
  124. if (!Guid.TryParse(languageServiceId, out languageServiceGuid)) {
  125. return false;
  126. }
  127. var contentTypes = model.GetService<IContentTypeRegistryService>();
  128. var contentType = contentTypes.GetContentType(contentTypeName);
  129. if (contentType == null) {
  130. return false;
  131. }
  132. var evaluator = GetReplEvaluator(model, replId);
  133. if (evaluator == null) {
  134. return false;
  135. }
  136. CreateReplWindow(evaluator, contentType, id, title, languageServiceGuid, replId);
  137. return true;
  138. }
  139. #endregion
  140. #region Implementation Details
  141. private ReplWindow FindReplWindowInternal(int id) {
  142. ReplWindow res;
  143. if (_windows.TryGetValue(id, out res)) {
  144. return res;
  145. }
  146. return null;
  147. }
  148. public IReplWindow CreateReplWindow(IReplEvaluator/*!*/ evaluator, IContentType/*!*/ contentType, int id, string/*!*/ title, Guid languageServiceGuid, string replId) {
  149. return CreateReplWindowInternal(evaluator, contentType, id, title, languageServiceGuid, replId);
  150. }
  151. private ReplWindow CreateReplWindowInternal(IReplEvaluator evaluator, IContentType contentType, int id, string title, Guid languageServiceGuid, string replId) {
  152. var service = (IVsUIShell)ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShell));
  153. var model = (IComponentModel)ServiceProvider.GlobalProvider.GetService(typeof(SComponentModel));
  154. SaveReplInfo(id, evaluator, contentType, title, languageServiceGuid, replId);
  155. var replWindow = new ReplWindow(model, evaluator, contentType, title, languageServiceGuid, replId);
  156. Guid clsId = replWindow.ToolClsid;
  157. Guid toolType = typeof(ReplWindow).GUID;
  158. Guid empty = Guid.Empty;
  159. IVsWindowFrame frame;
  160. // we don't pass __VSCREATETOOLWIN.CTW_fMultiInstance because multi instance panes are
  161. // destroyed when closed. We are really multi instance but we don't want to be closed. This
  162. // seems to work fine.
  163. ErrorHandler.ThrowOnFailure(
  164. service.CreateToolWindow(
  165. (uint)(__VSCREATETOOLWIN.CTW_fInitNew | __VSCREATETOOLWIN.CTW_fForceCreate),
  166. (uint)id,
  167. replWindow.GetIVsWindowPane(),
  168. ref clsId,
  169. ref toolType,
  170. ref empty,
  171. null,
  172. title,
  173. null,
  174. out frame
  175. )
  176. );
  177. replWindow.Frame = frame;
  178. replWindow.OnToolBarAdded();
  179. _windows[id] = replWindow;
  180. return replWindow;
  181. }
  182. #endregion
  183. }
  184. }