PageRenderTime 36ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/GitUI/GitExtensionsForm.cs

https://github.com/eisnerd/gitextensions
C# | 387 lines | 301 code | 50 blank | 36 comment | 60 complexity | b81b37452ad1e5457545699b2b88738d MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
  1. using System;
  2. using System.ComponentModel;
  3. using System.Configuration;
  4. using System.Diagnostics;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Windows.Forms;
  8. using GitUI.Properties;
  9. #if !__MonoCS__
  10. using Microsoft.WindowsAPICodePack.Taskbar;
  11. #endif
  12. using ResourceManager.Translation;
  13. using Settings = GitCommands.Settings;
  14. using System.Collections.Generic;
  15. namespace GitUI
  16. {
  17. public class GitExtensionsForm : Form, ITranslate
  18. {
  19. private static Icon ApplicationIcon = GetApplicationIcon(Settings.IconStyle, Settings.IconColor);
  20. private bool _translated;
  21. public GitExtensionsForm()
  22. {
  23. Icon = ApplicationIcon;
  24. SetFont();
  25. ShowInTaskbar = Application.OpenForms.Count <= 0 || (Application.OpenForms.Count == 1 && Application.OpenForms[0] is FormSplash);
  26. AutoScaleMode = AutoScaleMode.None;
  27. var cancelButton = new Button();
  28. cancelButton.Click += CancelButtonClick;
  29. CancelButton = cancelButton;
  30. Load += GitExtensionsFormLoad;
  31. FormClosing += GitExtensionsForm_FormClosing;
  32. }
  33. void GitExtensionsForm_FormClosing(object sender, FormClosingEventArgs e)
  34. {
  35. #if !__MonoCS__
  36. if (TaskbarManager.IsPlatformSupported)
  37. {
  38. try
  39. {
  40. TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress);
  41. }
  42. catch (InvalidOperationException) { }
  43. }
  44. #endif
  45. }
  46. #region Hotkeys
  47. /// <summary>Gets or sets a value that specifies if the hotkeys are used</summary>
  48. protected bool HotkeysEnabled { get; set; }
  49. /// <summary>Gets or sets the hotkeys</summary>
  50. protected IEnumerable<Hotkey.HotkeyCommand> Hotkeys { get; set; }
  51. /// <summary>Overridden: Checks if a hotkey wants to handle the key before letting the message propagate</summary>
  52. protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
  53. {
  54. if (HotkeysEnabled && this.Hotkeys != null)
  55. foreach (var hotkey in this.Hotkeys)
  56. {
  57. if (hotkey != null && hotkey.KeyData == keyData)
  58. {
  59. return ExecuteCommand(hotkey.CommandCode);
  60. }
  61. }
  62. return base.ProcessCmdKey(ref msg, keyData);
  63. }
  64. /// <summary>
  65. /// Override this method to handle form specific Hotkey commands
  66. /// This base method calls script-hotkeys
  67. /// </summary>
  68. /// <param name="command"></param>
  69. protected virtual bool ExecuteCommand(int command)
  70. {
  71. ExecuteScriptCommand(command, Keys.None);
  72. return true;
  73. }
  74. protected virtual bool ExecuteScriptCommand(int command, Keys keyData)
  75. {
  76. var curScripts = GitUI.Script.ScriptManager.GetScripts();
  77. foreach (GitUI.Script.ScriptInfo s in curScripts)
  78. {
  79. if (s.HotkeyCommandIdentifier == command)
  80. GitUI.Script.ScriptRunner.RunScript(s.Name, null);
  81. }
  82. return true;
  83. }
  84. #endregion
  85. private void SetFont()
  86. {
  87. Font = SystemFonts.MessageBoxFont;
  88. }
  89. #region icon
  90. protected void RotateApplicationIcon()
  91. {
  92. ApplicationIcon = GetApplicationIcon(Settings.IconStyle, Settings.IconColor);
  93. Icon = ApplicationIcon;
  94. }
  95. protected enum ColorIndex
  96. {
  97. Default,
  98. Blue,
  99. Green,
  100. LightBlue,
  101. Purple,
  102. Red,
  103. Yellow,
  104. Unknown = -1
  105. }
  106. protected static ColorIndex GetColorIndexByName(string color)
  107. {
  108. switch (color)
  109. {
  110. case "default":
  111. return ColorIndex.Default;
  112. case "blue":
  113. return ColorIndex.Blue;
  114. case "green":
  115. return ColorIndex.Green;
  116. case "lightblue":
  117. return ColorIndex.LightBlue;
  118. case "purple":
  119. return ColorIndex.Purple;
  120. case "red":
  121. return ColorIndex.Red;
  122. case "yellow":
  123. return ColorIndex.Yellow;
  124. case "random":
  125. return (ColorIndex)new Random(DateTime.Now.Millisecond).Next(7);
  126. }
  127. return ColorIndex.Unknown;
  128. }
  129. protected static Icon GetApplicationIcon(string iconStyle, string iconColor)
  130. {
  131. var colorIndex = (int)GetColorIndexByName(iconColor);
  132. if (colorIndex == (int) ColorIndex.Unknown)
  133. colorIndex = 0;
  134. Icon appIcon = null;
  135. if (iconStyle.Equals("small", StringComparison.OrdinalIgnoreCase))
  136. {
  137. Icon[] icons = {
  138. Resources.x_with_arrow,
  139. Resources.x_with_arrow_blue,
  140. Resources.x_with_arrow_green,
  141. Resources.x_with_arrow_lightblue,
  142. Resources.x_with_arrow_purple,
  143. Resources.x_with_arrow_red,
  144. Resources.x_with_arrow_yellow
  145. };
  146. Debug.Assert(icons.Length == 7);
  147. appIcon = icons[colorIndex];
  148. }
  149. else if (iconStyle.Equals("large", StringComparison.OrdinalIgnoreCase))
  150. {
  151. Icon[] icons = {
  152. Resources.git_extensions_logo_final,
  153. Resources.git_extensions_logo_final_blue,
  154. Resources.git_extensions_logo_final_green,
  155. Resources.git_extensions_logo_final_lightblue,
  156. Resources.git_extensions_logo_final_purple,
  157. Resources.git_extensions_logo_final_red,
  158. Resources.git_extensions_logo_final_yellow
  159. };
  160. Debug.Assert(icons.Length == 7);
  161. appIcon = icons[colorIndex];
  162. }
  163. else if (iconStyle.Equals("cow", StringComparison.OrdinalIgnoreCase))
  164. {
  165. Icon[] icons = {
  166. Resources.cow_head,
  167. Resources.cow_head_blue,
  168. Resources.cow_head_green,
  169. Resources.cow_head_blue,
  170. Resources.cow_head_purple,
  171. Resources.cow_head_red,
  172. Resources.cow_head_yellow
  173. };
  174. Debug.Assert(icons.Length == 7);
  175. appIcon = icons[colorIndex];
  176. }
  177. else
  178. {
  179. Icon[] icons = {
  180. Resources.git_extensions_logo_final_mixed,
  181. Resources.git_extensions_logo_final_mixed_blue,
  182. Resources.git_extensions_logo_final_mixed_green,
  183. Resources.git_extensions_logo_final_mixed_lightblue,
  184. Resources.git_extensions_logo_final_mixed_purple,
  185. Resources.git_extensions_logo_final_mixed_red,
  186. Resources.git_extensions_logo_final_mixed_yellow
  187. };
  188. Debug.Assert(icons.Length == 7);
  189. appIcon = icons[colorIndex];
  190. }
  191. Debug.Assert(appIcon != null);
  192. return appIcon;
  193. }
  194. #endregion
  195. private static bool CheckComponent(object value)
  196. {
  197. var component = value as IComponent;
  198. if (component == null)
  199. return false;
  200. var site = component.Site;
  201. return (site != null) && site.DesignMode;
  202. }
  203. protected virtual void OnRuntimeLoad(EventArgs e)
  204. {
  205. }
  206. protected override void OnLoad(EventArgs e)
  207. {
  208. base.OnLoad(e);
  209. if (!CheckComponent(this))
  210. OnRuntimeLoad(e);
  211. }
  212. private void GitExtensionsFormLoad(object sender, EventArgs e)
  213. {
  214. // find out if the value is a component and is currently in design mode
  215. var isComponentInDesignMode = CheckComponent(this);
  216. if (!_translated && !isComponentInDesignMode)
  217. throw new Exception("The control " + GetType().Name +
  218. " is not translated in the constructor. You need to call Translate() right after InitializeComponent().");
  219. }
  220. protected void Translate()
  221. {
  222. Translator.Translate(this, Settings.Translation);
  223. _translated = true;
  224. }
  225. public virtual void CancelButtonClick(object sender, EventArgs e)
  226. {
  227. Close();
  228. }
  229. private bool _windowCentred;
  230. /// <summary>
  231. /// Restores the position of a form from the user settings. Does
  232. /// nothing if there is no entry for the form in the settings, or the
  233. /// setting would be invisible on the current display configuration.
  234. /// </summary>
  235. /// <param name = "name">The name to use when looking up the position in
  236. /// the settings</param>
  237. protected void RestorePosition(String name)
  238. {
  239. if (!this.Visible ||
  240. WindowState == FormWindowState.Minimized)
  241. return;
  242. _windowCentred = (StartPosition == FormStartPosition.CenterParent);
  243. var position = LookupWindowPosition(name);
  244. if (position == null)
  245. return;
  246. StartPosition = FormStartPosition.Manual;
  247. Size = position.Rect.Size;
  248. if (Owner == null || !_windowCentred)
  249. Location = position.Rect.Location;
  250. else
  251. {
  252. // Calculate location for modal form with parent
  253. Location = new Point(Owner.Left + Owner.Width / 2 - Width / 2,
  254. Owner.Top + Owner.Height / 2 - Height / 2);
  255. }
  256. WindowState = position.State;
  257. }
  258. /// <summary>
  259. /// Save the position of a form to the user settings. Hides the window
  260. /// as a side-effect.
  261. /// </summary>
  262. /// <param name = "name">The name to use when writing the position to the
  263. /// settings</param>
  264. protected void SavePosition(String name)
  265. {
  266. try
  267. {
  268. var rectangle =
  269. WindowState == FormWindowState.Normal
  270. ? DesktopBounds
  271. : RestoreBounds;
  272. var formWindowState =
  273. WindowState == FormWindowState.Maximized
  274. ? FormWindowState.Maximized
  275. : FormWindowState.Normal;
  276. // Write to the user settings:
  277. if (Properties.Settings.Default.WindowPositions == null)
  278. Properties.Settings.Default.WindowPositions = new WindowPositionList();
  279. WindowPosition windowPosition = (WindowPosition)Properties.Settings.Default.WindowPositions[name];
  280. // Don't save location when we center modal form
  281. if (windowPosition != null && Owner != null && _windowCentred)
  282. {
  283. if (rectangle.Width <= windowPosition.Rect.Width && rectangle.Height <= windowPosition.Rect.Height)
  284. rectangle.Location = windowPosition.Rect.Location;
  285. }
  286. var position = new WindowPosition(rectangle, formWindowState);
  287. Properties.Settings.Default.WindowPositions[name] = position;
  288. Properties.Settings.Default.Save();
  289. }
  290. catch (ConfigurationException)
  291. {
  292. //TODO: howto restore a corrupted config? Properties.Settings.Default.Reset() doesn't work.
  293. }
  294. }
  295. /// <summary>
  296. /// Looks up a window in the user settings and returns its saved position.
  297. /// </summary>
  298. /// <param name = "name">The name.</param>
  299. /// <returns>
  300. /// The saved window position if it exists. Null if the entry
  301. /// doesn't exist, or would not be visible on any screen in the user's
  302. /// current display setup.
  303. /// </returns>
  304. private static WindowPosition LookupWindowPosition(String name)
  305. {
  306. try
  307. {
  308. var list = Properties.Settings.Default.WindowPositions;
  309. if (list == null)
  310. return null;
  311. var position = (WindowPosition)list[name];
  312. if (position == null || position.Rect.IsEmpty)
  313. return null;
  314. if (Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(position.Rect)))
  315. {
  316. return position;
  317. }
  318. }
  319. catch (ConfigurationException)
  320. {
  321. //TODO: howto restore a corrupted config? Properties.Settings.Default.Reset() doesn't work.
  322. }
  323. return null;
  324. }
  325. public virtual void AddTranslationItems(Translation translation)
  326. {
  327. if (!string.IsNullOrEmpty(Text))
  328. translation.AddTranslationItem(Name, "$this", "Text", Text);
  329. TranslationUtl.AddTranslationItemsFromFields(Name, this, translation);
  330. }
  331. public virtual void TranslateItems(Translation translation)
  332. {
  333. Text = translation.TranslateItem(Name, "$this", "Text", Text);
  334. TranslationUtl.TranslateItemsFromFields(Name, this, translation);
  335. }
  336. }
  337. }