PageRenderTime 63ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 1ms

/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CodeFormattingPanel.cs

https://github.com/Shanto/monodevelop
C# | 426 lines | 343 code | 54 blank | 29 comment | 56 complexity | 7ec176a656497def8c1316a66df44155 MD5 | raw file
  1. //
  2. // CodeFormattingPanelWidget.cs
  3. //
  4. // Author:
  5. // Lluis Sanchez Gual <lluis@novell.com>
  6. //
  7. // Copyright (c) 2009 Novell, Inc (http://www.novell.com)
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. using System;
  27. using System.Collections;
  28. using System.Collections.Generic;
  29. using Mono.Addins;
  30. using MonoDevelop.Ide.Gui.Dialogs;
  31. using MonoDevelop.Ide.Extensions;
  32. using MonoDevelop.Projects;
  33. using MonoDevelop.Core;
  34. using MonoDevelop.Projects.Policies;
  35. using MonoDevelop.Components;
  36. using System.Linq;
  37. namespace MonoDevelop.Ide.Projects.OptionPanels
  38. {
  39. class CodeFormattingPanel: OptionsPanel
  40. {
  41. PolicyContainer policyContainer;
  42. Dictionary<string,MimeTypePanelData> typeSections = new Dictionary<string, MimeTypePanelData> ();
  43. List<string> globalMimeTypes;
  44. HashSet<string> mimeTypesWithPolicies = new HashSet<string> ();
  45. bool internalPolicyUpdate;
  46. CodeFormattingPanelWidget widget;
  47. public override void Initialize (MonoDevelop.Ide.Gui.Dialogs.OptionsDialog dialog, object dataObject)
  48. {
  49. base.Initialize (dialog, dataObject);
  50. foreach (MimeTypeOptionsPanelNode node in AddinManager.GetExtensionNodes ("/MonoDevelop/ProjectModel/Gui/MimeTypePolicyPanels"))
  51. mimeTypesWithPolicies.Add (node.MimeType);
  52. var provider = dataObject as IPolicyProvider;
  53. if (provider == null)
  54. provider = PolicyService.GetUserDefaultPolicySet ();
  55. policyContainer = provider.Policies;
  56. if (!(dataObject is SolutionItem) && !(dataObject is Solution)) {
  57. globalMimeTypes = new List<string> ();
  58. string userTypes = PropertyService.Get<string> ("MonoDevelop.Projects.GlobalPolicyMimeTypes", "");
  59. globalMimeTypes.AddRange (userTypes.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
  60. }
  61. foreach (string mt in GetItemMimeTypes ())
  62. AddPanel (mt);
  63. policyContainer.PolicyChanged += HandlePolicyContainerPolicyChanged;
  64. }
  65. public override void Dispose ()
  66. {
  67. base.Dispose ();
  68. policyContainer.PolicyChanged -= HandlePolicyContainerPolicyChanged;
  69. }
  70. void HandlePolicyContainerPolicyChanged (object sender, PolicyChangedEventArgs e)
  71. {
  72. if (internalPolicyUpdate)
  73. return;
  74. // The policy container has changed externally. The panel data has to be reloaded
  75. foreach (MimeTypePanelData pd in typeSections.Values) {
  76. bool useParentPolicy = false;
  77. bool modified = false;
  78. foreach (IMimeTypePolicyOptionsPanel panel in pd.Panels) {
  79. // Reload the panel if it is handling the modified policy
  80. if (panel.HandlesPolicyType (e.PolicyType, e.Scope)) {
  81. panel.LoadSetPolicy (policyContainer);
  82. modified = true;
  83. }
  84. if (!panel.HasCustomPolicy)
  85. useParentPolicy = true;
  86. }
  87. if (modified)
  88. pd.SetUseParentPolicy (useParentPolicy, e.PolicyType, e.Scope);
  89. if (pd.SectionLoaded) {
  90. pd.SectionPanel.FillPolicies ();
  91. pd.SectionPanel.UpdateSelectedNamedPolicy ();
  92. }
  93. }
  94. if (widget != null)
  95. widget.Refresh ();
  96. }
  97. MimeTypePanelData AddPanel (string mt)
  98. {
  99. var chain = new List<string> (DesktopService.GetMimeTypeInheritanceChain (mt).Where (x => mimeTypesWithPolicies.Contains (x)));
  100. if (chain.Count == 0)
  101. return null;
  102. MimeTypePanelData data = new MimeTypePanelData ();
  103. OptionsDialogSection sec = new MimetypeOptionsDialogSection (mt);
  104. sec.Fill = true;
  105. data.Section = sec;
  106. data.MimeType = mt;
  107. data.TypeDescription = DesktopService.GetMimeTypeDescription (mt);
  108. if (string.IsNullOrEmpty (data.TypeDescription))
  109. data.TypeDescription = mt;
  110. data.DataObject = DataObject;
  111. data.PolicyContainer = policyContainer;
  112. sec.Label = data.TypeDescription;
  113. LoadPolicyTypeData (data, mt, chain);
  114. typeSections [mt] = data;
  115. ParentDialog.AddChildSection (this, sec, data);
  116. return data;
  117. }
  118. void RemovePanel (string mt)
  119. {
  120. MimeTypePanelData data = typeSections [mt];
  121. typeSections.Remove (mt);
  122. ParentDialog.RemoveSection (data.Section);
  123. }
  124. internal MimeTypePanelData AddGlobalMimeType (string mt)
  125. {
  126. if (!globalMimeTypes.Contains (mt)) {
  127. globalMimeTypes.Add (mt);
  128. return AddPanel (mt);
  129. }
  130. return null;
  131. }
  132. internal void RemoveGlobalMimeType (string mt)
  133. {
  134. if (globalMimeTypes.Remove (mt))
  135. RemovePanel (mt);
  136. }
  137. public IEnumerable<MimeTypePanelData> GetMimeTypeData ()
  138. {
  139. return typeSections.Values;
  140. }
  141. public PolicyContainer PolicyContainer {
  142. get { return policyContainer; }
  143. }
  144. void LoadPolicyTypeData (MimeTypePanelData data, string mimeType, List<string> types)
  145. {
  146. List<IMimeTypePolicyOptionsPanel> panels = new List<IMimeTypePolicyOptionsPanel> ();
  147. bool useParentPolicy = false;
  148. foreach (MimeTypeOptionsPanelNode node in AddinManager.GetExtensionNodes ("/MonoDevelop/ProjectModel/Gui/MimeTypePolicyPanels")) {
  149. if (!types.Contains (node.MimeType))
  150. continue;
  151. IMimeTypePolicyOptionsPanel panel = (IMimeTypePolicyOptionsPanel) node.CreateInstance (typeof(IMimeTypePolicyOptionsPanel));
  152. panel.Initialize (ParentDialog, DataObject);
  153. panel.InitializePolicy (policyContainer, mimeType, mimeType == node.MimeType);
  154. panel.Label = GettextCatalog.GetString (node.Label);
  155. if (!panel.IsVisible ())
  156. continue;
  157. if (!panel.HasCustomPolicy)
  158. useParentPolicy = true;
  159. panels.Add (panel);
  160. }
  161. data.Panels = panels;
  162. if (!policyContainer.IsRoot || ParentDialog is DefaultPolicyOptionsDialog)
  163. data.UseParentPolicy = useParentPolicy;
  164. }
  165. public override Gtk.Widget CreatePanelWidget ()
  166. {
  167. return widget = new CodeFormattingPanelWidget (this, ParentDialog);
  168. }
  169. public override void ApplyChanges ()
  170. {
  171. if (globalMimeTypes != null) {
  172. string types = string.Join (";", globalMimeTypes.ToArray ());
  173. PropertyService.Set ("MonoDevelop.Projects.GlobalPolicyMimeTypes", types);
  174. }
  175. try {
  176. internalPolicyUpdate = true;
  177. // If a section is already loaded, changes will be committed in the panel
  178. foreach (MimeTypePanelData pd in typeSections.Values) {
  179. if (!pd.SectionLoaded)
  180. pd.ApplyChanges ();
  181. }
  182. } finally {
  183. internalPolicyUpdate = false;
  184. }
  185. }
  186. public IEnumerable<string> GetItemMimeTypes ()
  187. {
  188. HashSet<string> types = new HashSet<string> ();
  189. if (DataObject is Solution)
  190. GetItemMimeTypes (types, ((Solution)DataObject).RootFolder);
  191. else if (DataObject is SolutionItem)
  192. GetItemMimeTypes (types, (SolutionItem)DataObject);
  193. else {
  194. types.Add ("application/xml");
  195. foreach (MimeTypeOptionsPanelNode node in AddinManager.GetExtensionNodes ("/MonoDevelop/ProjectModel/Gui/MimeTypePolicyPanels")) {
  196. types.Add (node.MimeType);
  197. globalMimeTypes.Remove (node.MimeType);
  198. }
  199. types.UnionWith (globalMimeTypes);
  200. }
  201. return types;
  202. }
  203. public bool IsUserMimeType (string type)
  204. {
  205. return globalMimeTypes != null && globalMimeTypes.Contains (type);
  206. }
  207. void GetItemMimeTypes (HashSet<string> types, SolutionItem item)
  208. {
  209. if (item is SolutionFolder) {
  210. foreach (SolutionItem it in ((SolutionFolder)item).Items)
  211. GetItemMimeTypes (types, it);
  212. }
  213. else if (item is Project) {
  214. foreach (ProjectFile pf in ((Project)item).Files) {
  215. string mt = DesktopService.GetMimeTypeForUri (pf.FilePath);
  216. foreach (string mth in DesktopService.GetMimeTypeInheritanceChain (mt))
  217. types.Add (mth);
  218. }
  219. }
  220. }
  221. }
  222. class MimetypeOptionsDialogSection : OptionsDialogSection
  223. {
  224. public MimetypeOptionsDialogSection (string mimetype): base (typeof(MimeTypePolicyOptionsSection))
  225. {
  226. this.MimeType = mimetype;
  227. }
  228. //this is used by the options dialog to look up the icon as needed, at required scales
  229. public string MimeType { get; private set; }
  230. }
  231. [System.ComponentModel.ToolboxItem(true)]
  232. partial class CodeFormattingPanelWidget : Gtk.Bin
  233. {
  234. CodeFormattingPanel panel;
  235. Gtk.ListStore store;
  236. OptionsDialog dialog;
  237. public CodeFormattingPanelWidget (CodeFormattingPanel panel, OptionsDialog dialog)
  238. {
  239. this.Build();
  240. this.panel = panel;
  241. this.dialog = dialog;
  242. store = new Gtk.ListStore (typeof(MimeTypePanelData), typeof(Gdk.Pixbuf), typeof(string));
  243. tree.Model = store;
  244. boxButtons.Visible = panel.DataObject is PolicySet;
  245. Gtk.CellRendererText crt = new Gtk.CellRendererText ();
  246. Gtk.CellRendererPixbuf crp = new Gtk.CellRendererPixbuf ();
  247. Gtk.TreeViewColumn col = new Gtk.TreeViewColumn ();
  248. col.Title = GettextCatalog.GetString ("File Type");
  249. col.PackStart (crp, false);
  250. col.PackStart (crt, true);
  251. col.AddAttribute (crp, "pixbuf", 1);
  252. col.AddAttribute (crt, "text", 2);
  253. tree.AppendColumn (col);
  254. store.SetSortColumnId (2, Gtk.SortType.Ascending);
  255. CellRendererComboBox comboCell = new CellRendererComboBox ();
  256. comboCell.Changed += OnPolicySelectionChanged;
  257. Gtk.TreeViewColumn polCol = tree.AppendColumn (GettextCatalog.GetString ("Policy"), comboCell, new Gtk.TreeCellDataFunc (OnSetPolicyData));
  258. tree.Selection.Changed += delegate {
  259. Gtk.TreeIter it;
  260. tree.Selection.GetSelected (out it);
  261. Gtk.TreeViewColumn ccol;
  262. Gtk.TreePath path;
  263. tree.GetCursor (out path, out ccol);
  264. if (ccol == polCol)
  265. tree.SetCursor (path, ccol, true);
  266. };
  267. Fill ();
  268. UpdateButtons ();
  269. tree.Selection.Changed += delegate {
  270. UpdateButtons ();
  271. };
  272. }
  273. static readonly string parentPolicyText = GettextCatalog.GetString ("(Inherited Policy)");
  274. static readonly string customPolicyText = GettextCatalog.GetString ("(Custom)");
  275. void OnSetPolicyData (Gtk.TreeViewColumn treeColumn, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
  276. {
  277. MimeTypePanelData mt = (MimeTypePanelData) store.GetValue (iter, 0);
  278. string selection;
  279. if (mt.UseParentPolicy)
  280. selection = parentPolicyText;
  281. else {
  282. PolicySet matchingSet = mt.GetMatchingSet (null);
  283. if (matchingSet != null)
  284. selection = matchingSet.Name;
  285. else
  286. selection = customPolicyText;
  287. }
  288. CellRendererComboBox comboCell = (CellRendererComboBox) cell;
  289. comboCell.Values = GetComboOptions (mt);
  290. comboCell.Text = selection;
  291. }
  292. string[] GetComboOptions (MimeTypePanelData mt)
  293. {
  294. List<string> values = new List<string> ();
  295. if (!this.panel.PolicyContainer.IsRoot)
  296. values.Add (parentPolicyText);
  297. foreach (PolicySet set in mt.GetSupportedPolicySets ())
  298. values.Add (set.Name);
  299. values.Add (customPolicyText);
  300. return values.ToArray ();
  301. }
  302. void OnPolicySelectionChanged (object s, ComboSelectionChangedArgs args)
  303. {
  304. Gtk.TreeIter iter;
  305. if (store.GetIter (out iter, new Gtk.TreePath (args.Path))) {
  306. MimeTypePanelData mt = (MimeTypePanelData) store.GetValue (iter, 0);
  307. if (args.Active != -1) {
  308. string sel = args.ActiveText;
  309. if (sel == parentPolicyText)
  310. mt.UseParentPolicy = true;
  311. else if (sel != customPolicyText) {
  312. PolicySet pset = PolicyService.GetPolicySet (sel);
  313. mt.AssignPolicies (pset);
  314. }
  315. }
  316. }
  317. }
  318. void Fill ()
  319. {
  320. foreach (MimeTypePanelData mt in panel.GetMimeTypeData ()) {
  321. store.AppendValues (mt, DesktopService.GetPixbufForType (mt.MimeType, Gtk.IconSize.Menu), mt.TypeDescription);
  322. }
  323. }
  324. public void Refresh ()
  325. {
  326. tree.QueueDraw ();
  327. }
  328. protected void OnButtonEditClicked (object sender, System.EventArgs e)
  329. {
  330. Gtk.TreeIter iter;
  331. if (tree.Selection.GetSelected (out iter)) {
  332. MimeTypePanelData mt = (MimeTypePanelData) store.GetValue (iter, 0);
  333. dialog.ShowPage (mt.Section);
  334. }
  335. }
  336. protected virtual void OnButtonAddClicked (object sender, System.EventArgs e)
  337. {
  338. AddMimeTypeDialog dlg = new AddMimeTypeDialog (panel.GetItemMimeTypes ());
  339. try {
  340. if (MessageService.RunCustomDialog (dlg, this.Toplevel as Gtk.Window) == (int) Gtk.ResponseType.Ok) {
  341. MimeTypePanelData mt = panel.AddGlobalMimeType (dlg.MimeType);
  342. store.AppendValues (mt, DesktopService.GetPixbufForType (mt.MimeType, Gtk.IconSize.Menu), mt.TypeDescription);
  343. }
  344. } finally {
  345. dlg.Destroy ();
  346. }
  347. }
  348. protected virtual void OnButtonRemoveClicked (object sender, System.EventArgs e)
  349. {
  350. Gtk.TreeIter iter;
  351. if (tree.Selection.GetSelected (out iter)) {
  352. MimeTypePanelData mt = (MimeTypePanelData) store.GetValue (iter, 0);
  353. if (MessageService.Confirm (GettextCatalog.GetString ("Are you sure you want to remove the formatting policy for the type '{0}'?", mt.TypeDescription), AlertButton.Delete)) {
  354. panel.RemoveGlobalMimeType (mt.MimeType);
  355. store.Remove (ref iter);
  356. }
  357. }
  358. }
  359. void UpdateButtons ()
  360. {
  361. Gtk.TreeIter iter;
  362. if (tree.Selection.GetSelected (out iter)) {
  363. MimeTypePanelData mt = (MimeTypePanelData) store.GetValue (iter, 0);
  364. if (panel.IsUserMimeType (mt.MimeType)) {
  365. buttonRemove.Sensitive = buttonEdit.Sensitive = true;
  366. return;
  367. }
  368. }
  369. buttonRemove.Sensitive = buttonEdit.Sensitive = false;
  370. }
  371. }
  372. }