PageRenderTime 73ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/snippets/VS2010/Nemerle.VisualStudio/ProjectBaseModifications/SettingsPage.cs

https://github.com/89sos98/nemerle
C# | 487 lines | 388 code | 72 blank | 27 comment | 83 complexity | 016e70390307b765f3b6e9cc049ed293 MD5 | raw file
  1. /***************************************************************************
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. This code is licensed under the Visual Studio SDK license terms.
  4. THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  5. ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  6. IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  7. PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  8. ***************************************************************************/
  9. using System;
  10. using System.Collections;
  11. using System.ComponentModel;
  12. using System.Drawing;
  13. using System.Globalization;
  14. using System.Runtime.InteropServices;
  15. using System.Security.Permissions;
  16. using System.Windows.Forms;
  17. using Microsoft.VisualStudio.Designer.Interfaces;
  18. using Microsoft.VisualStudio.OLE.Interop;
  19. using Microsoft.VisualStudio.Shell.Interop;
  20. namespace Microsoft.VisualStudio.Project
  21. {
  22. /// <summary>
  23. /// The base class for property pages.
  24. /// </summary>
  25. [CLSCompliant(false), ComVisible(true)]
  26. public abstract class SettingsPage :
  27. LocalizableProperties,
  28. IPropertyPage,
  29. IDisposable
  30. {
  31. #region fields
  32. private Panel panel;
  33. private bool active;
  34. private bool dirty;
  35. private IPropertyPageSite site;
  36. private ProjectNode project;
  37. private ProjectConfig[] projectConfigs;
  38. private IVSMDPropertyGrid grid;
  39. private string name;
  40. private static volatile object Mutex = new object();
  41. private bool isDisposed;
  42. #endregion
  43. #region properties
  44. [Browsable(false)]
  45. [AutomationBrowsable(false)]
  46. public string Name
  47. {
  48. get
  49. {
  50. return this.name;
  51. }
  52. set
  53. {
  54. this.name = value;
  55. }
  56. }
  57. [Browsable(false)]
  58. [AutomationBrowsable(false)]
  59. public ProjectNode ProjectMgr
  60. {
  61. get
  62. {
  63. return this.project;
  64. }
  65. }
  66. protected IVSMDPropertyGrid Grid
  67. {
  68. get { return this.grid; }
  69. }
  70. protected bool IsDirty
  71. {
  72. get
  73. {
  74. return this.dirty;
  75. }
  76. set
  77. {
  78. if (this.dirty != value)
  79. {
  80. this.dirty = value;
  81. if (this.site != null)
  82. site.OnStatusChange((uint)(this.dirty ? PropPageStatus.Dirty : PropPageStatus.Clean));
  83. }
  84. }
  85. }
  86. protected Panel ThePanel
  87. {
  88. get
  89. {
  90. return this.panel;
  91. }
  92. }
  93. #endregion
  94. #region abstract methods
  95. protected abstract void BindProperties();
  96. protected abstract int ApplyChanges();
  97. #endregion
  98. #region public methods
  99. public object GetTypedConfigProperty(string name, Type type)
  100. {
  101. string value = GetConfigProperty(name);
  102. if (string.IsNullOrEmpty(value)) return null;
  103. TypeConverter tc = TypeDescriptor.GetConverter(type);
  104. return tc.ConvertFromInvariantString(value);
  105. }
  106. public object GetTypedProperty(string name, Type type)
  107. {
  108. string value = GetProperty(name);
  109. if (string.IsNullOrEmpty(value)) return null;
  110. TypeConverter tc = TypeDescriptor.GetConverter(type);
  111. return tc.ConvertFromInvariantString(value);
  112. }
  113. public string GetProperty(string propertyName)
  114. {
  115. if (this.ProjectMgr != null)
  116. {
  117. string property;
  118. bool found = this.ProjectMgr.BuildProject.GlobalProperties.TryGetValue(propertyName, out property);
  119. if (found)
  120. {
  121. return property;
  122. }
  123. }
  124. return String.Empty;
  125. }
  126. // relative to active configuration.
  127. public string GetConfigProperty(string propertyName)
  128. {
  129. if (this.ProjectMgr != null)
  130. {
  131. string unifiedResult = null;
  132. bool cacheNeedReset = true;
  133. for (int i = 0; i < this.projectConfigs.Length; i++)
  134. {
  135. ProjectConfig config = projectConfigs[i];
  136. string property = config.GetConfigurationProperty(propertyName, cacheNeedReset);
  137. cacheNeedReset = false;
  138. if (property != null)
  139. {
  140. string text = property.Trim();
  141. if (i == 0)
  142. unifiedResult = text;
  143. else if (unifiedResult != text)
  144. return ""; // tristate value is blank then
  145. }
  146. }
  147. return unifiedResult;
  148. }
  149. return String.Empty;
  150. }
  151. /// <summary>
  152. /// Sets the value of a configuration dependent property.
  153. /// If the attribute does not exist it is created.
  154. /// If value is null it will be set to an empty string.
  155. /// </summary>
  156. /// <param name="name">property name.</param>
  157. /// <param name="value">value of property</param>
  158. public void SetConfigProperty(string name, string value)
  159. {
  160. CCITracing.TraceCall();
  161. if (value == null)
  162. {
  163. value = String.Empty;
  164. }
  165. if (this.ProjectMgr != null)
  166. {
  167. for (int i = 0, n = this.projectConfigs.Length; i < n; i++)
  168. {
  169. ProjectConfig config = projectConfigs[i];
  170. config.SetConfigurationProperty(name, value);
  171. }
  172. this.ProjectMgr.SetProjectFileDirty(true);
  173. }
  174. }
  175. #endregion
  176. #region IPropertyPage methods.
  177. public virtual void Activate(IntPtr parent, RECT[] pRect, int bModal)
  178. {
  179. if (this.panel == null)
  180. {
  181. if (pRect == null)
  182. {
  183. throw new ArgumentNullException("pRect");
  184. }
  185. this.panel = new Panel();
  186. this.panel.Size = new Size(pRect[0].right - pRect[0].left, pRect[0].bottom - pRect[0].top);
  187. this.panel.Text = SR.GetString(SR.Settings, CultureInfo.CurrentUICulture);
  188. this.panel.Visible = false;
  189. this.panel.Size = new Size(550, 300);
  190. this.panel.CreateControl();
  191. NativeMethods.SetParent(this.panel.Handle, parent);
  192. }
  193. if (this.grid == null && this.project != null && this.project.Site != null)
  194. {
  195. IVSMDPropertyBrowser pb = this.project.Site.GetService(typeof(IVSMDPropertyBrowser)) as IVSMDPropertyBrowser;
  196. this.grid = pb.CreatePropertyGrid();
  197. }
  198. if (this.grid != null)
  199. {
  200. this.active = true;
  201. Control cGrid = Control.FromHandle(new IntPtr(this.grid.Handle));
  202. cGrid.Parent = Control.FromHandle(parent);//this.panel;
  203. cGrid.Size = new Size(544, 294);
  204. cGrid.Location = new Point(3, 3);
  205. cGrid.Visible = true;
  206. this.grid.SetOption(_PROPERTYGRIDOPTION.PGOPT_TOOLBAR, false);
  207. this.grid.GridSort = _PROPERTYGRIDSORT.PGSORT_CATEGORIZED | _PROPERTYGRIDSORT.PGSORT_ALPHABETICAL;
  208. NativeMethods.SetParent(new IntPtr(this.grid.Handle), this.panel.Handle);
  209. UpdateObjects();
  210. }
  211. }
  212. public virtual int Apply()
  213. {
  214. if (IsDirty)
  215. {
  216. return this.ApplyChanges();
  217. }
  218. return VSConstants.S_OK;
  219. }
  220. public virtual void Deactivate()
  221. {
  222. if (null != this.panel)
  223. {
  224. this.panel.Dispose();
  225. this.panel = null;
  226. }
  227. this.active = false;
  228. }
  229. public virtual void GetPageInfo(PROPPAGEINFO[] arrInfo)
  230. {
  231. if (arrInfo == null)
  232. {
  233. throw new ArgumentNullException("arrInfo");
  234. }
  235. PROPPAGEINFO info = new PROPPAGEINFO();
  236. info.cb = (uint)Marshal.SizeOf(typeof(PROPPAGEINFO));
  237. info.dwHelpContext = 0;
  238. info.pszDocString = null;
  239. info.pszHelpFile = null;
  240. info.pszTitle = this.name;
  241. info.SIZE.cx = 550;
  242. info.SIZE.cy = 300;
  243. arrInfo[0] = info;
  244. }
  245. public virtual void Help(string helpDir)
  246. {
  247. }
  248. public virtual int IsPageDirty()
  249. {
  250. // Note this returns an HRESULT not a Bool.
  251. return (IsDirty ? (int)VSConstants.S_OK : (int)VSConstants.S_FALSE);
  252. }
  253. public virtual void Move(RECT[] arrRect)
  254. {
  255. if (arrRect == null)
  256. {
  257. throw new ArgumentNullException("arrRect");
  258. }
  259. RECT r = arrRect[0];
  260. this.panel.Location = new Point(r.left, r.top);
  261. this.panel.Size = new Size(r.right - r.left, r.bottom - r.top);
  262. }
  263. public virtual void SetObjects(uint count, object[] punk)
  264. {
  265. if (punk == null)
  266. {
  267. return;
  268. }
  269. if (count > 0)
  270. {
  271. if (punk[0] is ProjectConfig)
  272. {
  273. ArrayList configs = new ArrayList();
  274. for (int i = 0; i < count; i++)
  275. {
  276. ProjectConfig config = (ProjectConfig)punk[i];
  277. if (this.project == null || (this.project != (punk[0] as ProjectConfig).ProjectMgr))
  278. {
  279. this.project = config.ProjectMgr;
  280. }
  281. configs.Add(config);
  282. }
  283. this.projectConfigs = (ProjectConfig[])configs.ToArray(typeof(ProjectConfig));
  284. }
  285. else if (punk[0] is NodeProperties)
  286. {
  287. if (this.project == null || (this.project != (punk[0] as NodeProperties).Node.ProjectMgr))
  288. {
  289. this.project = (punk[0] as NodeProperties).Node.ProjectMgr;
  290. }
  291. System.Collections.Generic.Dictionary<string, ProjectConfig> configsMap = new System.Collections.Generic.Dictionary<string, ProjectConfig>();
  292. for (int i = 0; i < count; i++)
  293. {
  294. NodeProperties property = (NodeProperties)punk[i];
  295. IVsCfgProvider provider;
  296. ErrorHandler.ThrowOnFailure(property.Node.ProjectMgr.GetCfgProvider(out provider));
  297. uint[] expected = new uint[1];
  298. ErrorHandler.ThrowOnFailure(provider.GetCfgs(0, null, expected, null));
  299. if (expected[0] > 0)
  300. {
  301. ProjectConfig[] configs = new ProjectConfig[expected[0]];
  302. uint[] actual = new uint[1];
  303. ErrorHandler.ThrowOnFailure(provider.GetCfgs(expected[0], configs, actual, null));
  304. foreach (ProjectConfig config in configs)
  305. {
  306. if (!configsMap.ContainsKey(config.ConfigKey))
  307. {
  308. configsMap.Add(config.ConfigKey, config);
  309. }
  310. }
  311. }
  312. }
  313. if (configsMap.Count > 0)
  314. {
  315. if (this.projectConfigs == null)
  316. {
  317. this.projectConfigs = new ProjectConfig[configsMap.Keys.Count];
  318. }
  319. configsMap.Values.CopyTo(this.projectConfigs, 0);
  320. }
  321. }
  322. }
  323. else
  324. {
  325. this.project = null;
  326. }
  327. if (this.active && this.project != null)
  328. {
  329. UpdateObjects();
  330. }
  331. }
  332. public virtual void SetPageSite(IPropertyPageSite theSite)
  333. {
  334. this.site = theSite;
  335. }
  336. public virtual void Show(uint cmd)
  337. {
  338. this.panel.Visible = true; // TODO: pass SW_SHOW* flags through
  339. this.panel.Show();
  340. }
  341. public virtual int TranslateAccelerator(MSG[] arrMsg)
  342. {
  343. if (arrMsg == null)
  344. {
  345. throw new ArgumentNullException("arrMsg");
  346. }
  347. MSG msg = arrMsg[0];
  348. if ((msg.message < NativeMethods.WM_KEYFIRST || msg.message > NativeMethods.WM_KEYLAST) && (msg.message < NativeMethods.WM_MOUSEFIRST || msg.message > NativeMethods.WM_MOUSELAST))
  349. return 1;
  350. return (NativeMethods.IsDialogMessageA(this.panel.Handle, ref msg)) ? 0 : 1;
  351. }
  352. #endregion
  353. #region helper methods
  354. protected ProjectConfig[] GetProjectConfigurations()
  355. {
  356. return this.projectConfigs;
  357. }
  358. protected void UpdateObjects()
  359. {
  360. if (this.projectConfigs != null && this.project != null)
  361. {
  362. // Demand unmanaged permissions in order to access unmanaged memory.
  363. new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
  364. IntPtr p = Marshal.GetIUnknownForObject(this);
  365. IntPtr ppUnk = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
  366. try
  367. {
  368. Marshal.WriteIntPtr(ppUnk, p);
  369. this.BindProperties();
  370. // BUGBUG -- this is really bad casting a pointer to "int"...
  371. this.grid.SetSelectedObjects(1, ppUnk.ToInt32());
  372. this.grid.Refresh();
  373. }
  374. finally
  375. {
  376. if (ppUnk != IntPtr.Zero)
  377. {
  378. Marshal.FreeCoTaskMem(ppUnk);
  379. }
  380. if (p != IntPtr.Zero)
  381. {
  382. Marshal.Release(p);
  383. }
  384. }
  385. }
  386. }
  387. #endregion
  388. #region IDisposable Members
  389. /// <summary>
  390. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  391. /// </summary>
  392. public void Dispose()
  393. {
  394. this.Dispose(true);
  395. GC.SuppressFinalize(this);
  396. }
  397. #endregion
  398. private void Dispose(bool disposing)
  399. {
  400. if (!this.isDisposed)
  401. {
  402. lock (Mutex)
  403. {
  404. if (disposing)
  405. {
  406. this.panel.Dispose();
  407. }
  408. this.isDisposed = true;
  409. }
  410. }
  411. }
  412. }
  413. }