PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Menus/FileMenu.cs

https://bitbucket.org/tcz001/openpdn
C# | 515 lines | 395 code | 68 blank | 52 comment | 23 complexity | 07cb542358c52a7a518ce8920dda01db MD5 | raw file
Possible License(s): Unlicense
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
  4. // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
  5. // See src/Resources/Files/License.txt for full licensing and attribution //
  6. // details. //
  7. // . //
  8. /////////////////////////////////////////////////////////////////////////////////
  9. using PaintDotNet.Actions;
  10. using PaintDotNet.SystemLayer;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.ComponentModel;
  14. using System.Drawing;
  15. using System.Drawing.Drawing2D;
  16. using System.Drawing.Imaging;
  17. using System.IO;
  18. using System.Reflection;
  19. using System.Runtime.InteropServices;
  20. using System.Text;
  21. using System.Threading;
  22. using System.Windows.Forms;
  23. namespace PaintDotNet.Menus
  24. {
  25. internal sealed class FileMenu
  26. : PdnMenuItem
  27. {
  28. private PdnMenuItem menuFileNew;
  29. private PdnMenuItem menuFileOpen;
  30. private PdnMenuItem menuFileOpenRecent;
  31. private PdnMenuItem menuFileOpenRecentSentinel;
  32. private PdnMenuItem menuFileAcquire;
  33. private PdnMenuItem menuFileAcquireFromScannerOrCamera;
  34. private PdnMenuItem menuFileClose;
  35. private ToolStripSeparator menuFileSeparator1;
  36. private PdnMenuItem menuFileSave;
  37. private PdnMenuItem menuFileSaveAs;
  38. private ToolStripSeparator menuFileSeparator2;
  39. private PdnMenuItem menuFilePrint;
  40. private ToolStripSeparator menuFileSeparator3;
  41. private PdnMenuItem menuFileViewPluginLoadErrors;
  42. private ToolStripSeparator menuFileSeparator4;
  43. private PdnMenuItem menuFileExit;
  44. private bool OnCtrlF4Typed(Keys keys)
  45. {
  46. this.menuFileClose.PerformClick();
  47. return true;
  48. }
  49. public FileMenu()
  50. {
  51. PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.F4, OnCtrlF4Typed);
  52. InitializeComponent();
  53. }
  54. private void InitializeComponent()
  55. {
  56. this.menuFileNew = new PdnMenuItem();
  57. this.menuFileOpen = new PdnMenuItem();
  58. this.menuFileOpenRecent = new PdnMenuItem();
  59. this.menuFileOpenRecentSentinel = new PdnMenuItem();
  60. this.menuFileAcquire = new PdnMenuItem();
  61. this.menuFileAcquireFromScannerOrCamera = new PdnMenuItem();
  62. this.menuFileClose = new PdnMenuItem();
  63. this.menuFileSeparator1 = new ToolStripSeparator();
  64. this.menuFileSave = new PdnMenuItem();
  65. this.menuFileSaveAs = new PdnMenuItem();
  66. this.menuFileSeparator2 = new ToolStripSeparator();
  67. this.menuFilePrint = new PdnMenuItem();
  68. this.menuFileSeparator3 = new ToolStripSeparator();
  69. this.menuFileViewPluginLoadErrors = new PdnMenuItem();
  70. this.menuFileSeparator4 = new ToolStripSeparator();
  71. this.menuFileExit = new PdnMenuItem();
  72. //
  73. // FileMenu
  74. //
  75. this.DropDownItems.AddRange(GetMenuItemsToAdd(true));
  76. this.Name = "Menu.File";
  77. this.Text = PdnResources.GetString("Menu.File.Text");
  78. //
  79. // menuFileNew
  80. //
  81. this.menuFileNew.Name = "New";
  82. this.menuFileNew.ShortcutKeys = Keys.Control | Keys.N;
  83. this.menuFileNew.Click += new System.EventHandler(this.MenuFileNew_Click);
  84. //
  85. // menuFileOpen
  86. //
  87. this.menuFileOpen.Name = "Open";
  88. this.menuFileOpen.ShortcutKeys = Keys.Control | Keys.O;
  89. this.menuFileOpen.Click += new System.EventHandler(this.MenuFileOpen_Click);
  90. //
  91. // menuFileOpenRecent
  92. //
  93. this.menuFileOpenRecent.Name = "OpenRecent";
  94. this.menuFileOpenRecent.DropDownItems.AddRange(
  95. new ToolStripItem[]
  96. {
  97. this.menuFileOpenRecentSentinel
  98. });
  99. this.menuFileOpenRecent.DropDownOpening += new System.EventHandler(this.MenuFileOpenRecent_DropDownOpening);
  100. //
  101. // menuFileOpenRecentSentinel
  102. //
  103. this.menuFileOpenRecentSentinel.Text = "sentinel";
  104. //
  105. // menuFileAcquire
  106. //
  107. this.menuFileAcquire.Name = "Acquire";
  108. this.menuFileAcquire.DropDownItems.AddRange(
  109. new ToolStripItem[]
  110. {
  111. this.menuFileAcquireFromScannerOrCamera
  112. });
  113. this.menuFileAcquire.DropDownOpening += new System.EventHandler(this.MenuFileAcquire_DropDownOpening);
  114. //
  115. // menuFileAcquireFromScannerOrCamera
  116. //
  117. this.menuFileAcquireFromScannerOrCamera.Name = "FromScannerOrCamera";
  118. this.menuFileAcquireFromScannerOrCamera.Click += new System.EventHandler(this.MenuFileAcquireFromScannerOrCamera_Click);
  119. //
  120. // menuFileClose
  121. //
  122. this.menuFileClose.Name = "Close";
  123. this.menuFileClose.Click += new EventHandler(MenuFileClose_Click);
  124. this.menuFileClose.ShortcutKeys = Keys.Control | Keys.W;
  125. //
  126. // menuFileSave
  127. //
  128. this.menuFileSave.Name = "Save";
  129. this.menuFileSave.ShortcutKeys = Keys.Control | Keys.S;
  130. this.menuFileSave.Click += new System.EventHandler(this.MenuFileSave_Click);
  131. //
  132. // menuFileSaveAs
  133. //
  134. this.menuFileSaveAs.Name = "SaveAs";
  135. this.menuFileSaveAs.ShortcutKeys = Keys.Control | Keys.Shift | Keys.S;
  136. this.menuFileSaveAs.Click += new System.EventHandler(this.MenuFileSaveAs_Click);
  137. //
  138. // menuFilePrint
  139. //
  140. this.menuFilePrint.Name = "Print";
  141. this.menuFilePrint.ShortcutKeys = Keys.Control | Keys.P;
  142. this.menuFilePrint.Click += new System.EventHandler(this.MenuFilePrint_Click);
  143. //
  144. // menuFileViewPluginLoadErrors
  145. //
  146. this.menuFileViewPluginLoadErrors.Name = "ViewPluginLoadErrors";
  147. this.menuFileViewPluginLoadErrors.Click += new EventHandler(MenuFileViewPluginLoadErrors_Click);
  148. //
  149. // menuFileExit
  150. //
  151. this.menuFileExit.Name = "Exit";
  152. this.menuFileExit.Click += new System.EventHandler(this.MenuFileExit_Click);
  153. }
  154. private ToolStripItem[] GetMenuItemsToAdd(bool includeLoadErrors)
  155. {
  156. List<ToolStripItem> items = new List<ToolStripItem>();
  157. items.Add(this.menuFileNew);
  158. items.Add(this.menuFileOpen);
  159. items.Add(this.menuFileOpenRecent);
  160. items.Add(this.menuFileAcquire);
  161. items.Add(this.menuFileClose);
  162. items.Add(this.menuFileSeparator1);
  163. items.Add(this.menuFileSave);
  164. items.Add(this.menuFileSaveAs);
  165. items.Add(this.menuFileSeparator2);
  166. items.Add(this.menuFilePrint);
  167. items.Add(this.menuFileSeparator3);
  168. if (includeLoadErrors)
  169. {
  170. items.Add(this.menuFileViewPluginLoadErrors);
  171. items.Add(this.menuFileSeparator4);
  172. }
  173. items.Add(this.menuFileExit);
  174. return items.ToArray();
  175. }
  176. private List<Triple<Assembly, Type, Exception>> RemoveDuplicates(IList<Triple<Assembly, Type, Exception>> allErrors)
  177. {
  178. // Exception has reference identity, but we want to collate based on the message contents
  179. Set<Triple<Assembly, Type, string>> internedList = new Set<Triple<Assembly, Type, string>>();
  180. List<Triple<Assembly, Type, Exception>> noDupesList = new List<Triple<Assembly, Type, Exception>>();
  181. for (int i = 0; i < allErrors.Count; ++i)
  182. {
  183. Triple<Assembly, Type, string> interned = Triple.Create(
  184. allErrors[i].First, allErrors[i].Second, string.Intern(allErrors[i].Third.ToString()));
  185. if (!internedList.Contains(interned))
  186. {
  187. internedList.Add(interned);
  188. noDupesList.Add(allErrors[i]);
  189. }
  190. }
  191. return noDupesList;
  192. }
  193. private void MenuFileViewPluginLoadErrors_Click(object sender, EventArgs e)
  194. {
  195. IList<Triple<Assembly, Type, Exception>> allErrors = AppWorkspace.GetEffectLoadErrors();
  196. IList<Triple<Assembly, Type, Exception>> errors = RemoveDuplicates(allErrors);
  197. using (Form errorsDialog = new Form())
  198. {
  199. errorsDialog.Icon = Utility.ImageToIcon(PdnResources.GetImageResource("Icons.MenuFileViewPluginLoadErrorsIcon.png").Reference);
  200. errorsDialog.Text = PdnResources.GetString("Effects.PluginLoadErrorsDialog.Text");
  201. Label messageLabel = new Label();
  202. messageLabel.Name = "messageLabel";
  203. messageLabel.Text = PdnResources.GetString("Effects.PluginLoadErrorsDialog.Message.Text");
  204. TextBox errorsBox = new TextBox();
  205. errorsBox.Font = new Font(FontFamily.GenericMonospace, errorsBox.Font.Size);
  206. errorsBox.ReadOnly = true;
  207. errorsBox.Multiline = true;
  208. errorsBox.ScrollBars = ScrollBars.Vertical;
  209. StringBuilder allErrorsText = new StringBuilder();
  210. string headerTextFormat = PdnResources.GetString("EffectErrorMessage.HeaderFormat");
  211. for (int i = 0; i < errors.Count; ++i)
  212. {
  213. Assembly assembly = errors[i].First;
  214. Type type = errors[i].Second;
  215. Exception exception = errors[i].Third;
  216. string headerText = string.Format(headerTextFormat, i + 1, errors.Count);
  217. string errorText = AppWorkspace.GetLocalizedEffectErrorMessage(assembly, type, exception);
  218. allErrorsText.Append(headerText);
  219. allErrorsText.Append(Environment.NewLine);
  220. allErrorsText.Append(errorText);
  221. if (i != errors.Count - 1)
  222. {
  223. allErrorsText.Append(Environment.NewLine);
  224. }
  225. }
  226. errorsBox.Text = allErrorsText.ToString();
  227. errorsDialog.Layout +=
  228. delegate(object sender2, LayoutEventArgs e2)
  229. {
  230. int hMargin = UI.ScaleWidth(8);
  231. int vMargin = UI.ScaleHeight(8);
  232. int insetWidth = errorsDialog.ClientSize.Width - (hMargin * 2);
  233. messageLabel.Location = new Point(hMargin, vMargin);
  234. messageLabel.Width = insetWidth;
  235. messageLabel.Size = messageLabel.GetPreferredSize(new Size(messageLabel.Width, 1));
  236. errorsBox.Location = new Point(hMargin, messageLabel.Bottom + vMargin);
  237. errorsBox.Width = insetWidth;
  238. errorsBox.Height = errorsDialog.ClientSize.Height - vMargin - errorsBox.Top;
  239. };
  240. errorsDialog.StartPosition = FormStartPosition.CenterParent;
  241. errorsDialog.ShowInTaskbar = false;
  242. errorsDialog.MinimizeBox = false;
  243. errorsDialog.Width *= 2;
  244. errorsDialog.Size = UI.ScaleSize(errorsDialog.Size);
  245. errorsDialog.Controls.Add(messageLabel);
  246. errorsDialog.Controls.Add(errorsBox);
  247. errorsDialog.ShowDialog(AppWorkspace);
  248. }
  249. }
  250. protected override void OnDropDownOpening(EventArgs e)
  251. {
  252. this.DropDownItems.Clear();
  253. IList<Triple<Assembly, Type, Exception>> pluginLoadErrors = AppWorkspace.GetEffectLoadErrors();
  254. this.DropDownItems.AddRange(GetMenuItemsToAdd(pluginLoadErrors.Count > 0));
  255. this.menuFileNew.Enabled = true;
  256. this.menuFileOpen.Enabled = true;
  257. this.menuFileOpenRecent.Enabled = true;
  258. this.menuFileOpenRecentSentinel.Enabled = true;
  259. this.menuFileAcquire.Enabled = true;
  260. this.menuFileAcquireFromScannerOrCamera.Enabled = true;
  261. this.menuFileExit.Enabled = true;
  262. if (AppWorkspace.ActiveDocumentWorkspace != null)
  263. {
  264. this.menuFileSave.Enabled = true;
  265. this.menuFileSaveAs.Enabled = true;
  266. this.menuFileClose.Enabled = true;
  267. this.menuFilePrint.Enabled = true;
  268. }
  269. else
  270. {
  271. this.menuFileSave.Enabled = false;
  272. this.menuFileSaveAs.Enabled = false;
  273. this.menuFileClose.Enabled = false;
  274. this.menuFilePrint.Enabled = false;
  275. }
  276. base.OnDropDownOpening(e);
  277. }
  278. private void MenuFileOpen_Click(object sender, System.EventArgs e)
  279. {
  280. AppWorkspace.PerformAction(new OpenFileAction());
  281. }
  282. private void DoExit()
  283. {
  284. Startup.CloseApplication();
  285. }
  286. private void MenuFileExit_Click(object sender, System.EventArgs e)
  287. {
  288. DoExit();
  289. }
  290. private void MenuFileClose_Click(object sender, EventArgs e)
  291. {
  292. if (this.AppWorkspace.DocumentWorkspaces.Length > 0)
  293. {
  294. this.AppWorkspace.PerformAction(new CloseWorkspaceAction());
  295. }
  296. else
  297. {
  298. DoExit();
  299. }
  300. }
  301. private void MenuFileSaveAs_Click(object sender, System.EventArgs e)
  302. {
  303. if (AppWorkspace.ActiveDocumentWorkspace != null)
  304. {
  305. AppWorkspace.ActiveDocumentWorkspace.DoSaveAs();
  306. }
  307. }
  308. private void MenuFileSave_Click(object sender, System.EventArgs e)
  309. {
  310. if (AppWorkspace.ActiveDocumentWorkspace != null)
  311. {
  312. AppWorkspace.ActiveDocumentWorkspace.DoSave();
  313. }
  314. }
  315. private void MenuFileAcquire_DropDownOpening(object sender, System.EventArgs e)
  316. {
  317. // We only disable the scanner menu item if we know for sure a scanner is not available
  318. // If WIA isn't available we leave the menu item enabled. That way we can give an
  319. // informative error message when the user clicks on it and say "scanning requires XP SP1"
  320. // Otherwise the user is confused and will make scathing posts on our forum.
  321. bool scannerEnabled = true;
  322. if (ScanningAndPrinting.IsComponentAvailable)
  323. {
  324. if (!ScanningAndPrinting.CanScan)
  325. {
  326. scannerEnabled = false;
  327. }
  328. }
  329. menuFileAcquireFromScannerOrCamera.Enabled = scannerEnabled;
  330. }
  331. private void MenuFilePrint_Click(object sender, System.EventArgs e)
  332. {
  333. if (this.AppWorkspace.ActiveDocumentWorkspace != null)
  334. {
  335. this.AppWorkspace.ActiveDocumentWorkspace.PerformAction(new PrintAction());
  336. }
  337. }
  338. private void MenuFileOpenInNewWindow_Click(object sender, System.EventArgs e)
  339. {
  340. string fileName;
  341. string startingDir = Path.GetDirectoryName(AppWorkspace.ActiveDocumentWorkspace.FilePath);
  342. DialogResult result = DocumentWorkspace.ChooseFile(AppWorkspace, out fileName, startingDir);
  343. if (result == DialogResult.OK)
  344. {
  345. Startup.StartNewInstance(AppWorkspace, fileName);
  346. }
  347. }
  348. private void MenuFileNewWindow_Click(object sender, System.EventArgs e)
  349. {
  350. Startup.StartNewInstance(AppWorkspace, null);
  351. }
  352. private void MenuFileOpenRecent_DropDownOpening(object sender, System.EventArgs e)
  353. {
  354. AppWorkspace.MostRecentFiles.LoadMruList();
  355. MostRecentFile[] filesReverse = AppWorkspace.MostRecentFiles.GetFileList();
  356. MostRecentFile[] files = new MostRecentFile[filesReverse.Length];
  357. int i;
  358. for (i = 0; i < filesReverse.Length; ++i)
  359. {
  360. files[files.Length - i - 1] = filesReverse[i];
  361. }
  362. foreach (ToolStripItem mi in menuFileOpenRecent.DropDownItems)
  363. {
  364. mi.Click -= new EventHandler(MenuFileOpenRecentFile_Click);
  365. }
  366. menuFileOpenRecent.DropDownItems.Clear();
  367. i = 0;
  368. foreach (MostRecentFile mrf in files)
  369. {
  370. string menuName;
  371. if (i < 9)
  372. {
  373. menuName = "&";
  374. }
  375. else
  376. {
  377. menuName = "";
  378. }
  379. menuName += (1 + i).ToString() + " " + Path.GetFileName(mrf.FileName);
  380. ToolStripMenuItem mi = new ToolStripMenuItem(menuName);
  381. mi.Click += new EventHandler(MenuFileOpenRecentFile_Click);
  382. mi.ImageScaling = ToolStripItemImageScaling.None;
  383. mi.Image = (Image)mrf.Thumb.Clone();
  384. menuFileOpenRecent.DropDownItems.Add(mi);
  385. ++i;
  386. }
  387. if (menuFileOpenRecent.DropDownItems.Count == 0)
  388. {
  389. ToolStripMenuItem none = new ToolStripMenuItem(PdnResources.GetString("Menu.File.OpenRecent.None"));
  390. none.Enabled = false;
  391. menuFileOpenRecent.DropDownItems.Add(none);
  392. }
  393. else
  394. {
  395. ToolStripSeparator separator = new ToolStripSeparator();
  396. menuFileOpenRecent.DropDownItems.Add(separator);
  397. ToolStripMenuItem clearList = new ToolStripMenuItem();
  398. clearList.Text = PdnResources.GetString("Menu.File.OpenRecent.ClearThisList");
  399. menuFileOpenRecent.DropDownItems.Add(clearList);
  400. Image deleteIcon = PdnResources.GetImageResource("Icons.MenuEditEraseSelectionIcon.png").Reference;
  401. clearList.ImageTransparentColor = Utility.TransparentKey;
  402. clearList.ImageAlign = ContentAlignment.MiddleCenter;
  403. clearList.ImageScaling = ToolStripItemImageScaling.None;
  404. int iconSize = AppWorkspace.MostRecentFiles.IconSize;
  405. Bitmap bitmap = new Bitmap(iconSize + 2, iconSize + 2);
  406. using (Graphics g = Graphics.FromImage(bitmap))
  407. {
  408. g.Clear(clearList.ImageTransparentColor);
  409. Point offset = new Point((bitmap.Width - deleteIcon.Width) / 2,
  410. (bitmap.Height - deleteIcon.Height) / 2);
  411. g.CompositingMode = CompositingMode.SourceCopy;
  412. g.DrawImage(deleteIcon, offset.X, offset.Y, deleteIcon.Width, deleteIcon.Height);
  413. }
  414. clearList.Image = bitmap;
  415. clearList.Click += new EventHandler(ClearList_Click);
  416. }
  417. }
  418. private void MenuFileOpenRecentFile_Click(object sender, System.EventArgs e)
  419. {
  420. try
  421. {
  422. ToolStripMenuItem mi = (ToolStripMenuItem)sender;
  423. int spaceIndex = mi.Text.IndexOf(" ");
  424. string indexString = mi.Text.Substring(1, spaceIndex - 1);
  425. int index = int.Parse(indexString) - 1;
  426. MostRecentFile[] recentFiles = AppWorkspace.MostRecentFiles.GetFileList();
  427. string fileName = recentFiles[recentFiles.Length - index - 1].FileName;
  428. AppWorkspace.OpenFileInNewWorkspace(fileName);
  429. }
  430. catch (Exception)
  431. {
  432. }
  433. }
  434. private void MenuFileNew_Click(object sender, System.EventArgs e)
  435. {
  436. AppWorkspace.PerformAction(new NewImageAction());
  437. }
  438. private void MenuFileAcquireFromScannerOrCamera_Click(object sender, System.EventArgs e)
  439. {
  440. AppWorkspace.PerformAction(new AcquireFromScannerOrCameraAction());
  441. }
  442. private void ClearList_Click(object sender, EventArgs e)
  443. {
  444. AppWorkspace.PerformAction(new ClearMruListAction());
  445. }
  446. }
  447. }