PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/GitUI/GitExtensionsForm.cs

https://github.com/qgppl/gitextensions
C# | 358 lines | 276 code | 40 blank | 42 comment | 55 complexity | 25e81a4e683f35144abba746946cd1c6 MD5 | raw file
Possible License(s): GPL-3.0
  1. using System;
  2. using System.Collections.Generic;
  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. using ResourceManager;
  10. using Settings = GitCommands.AppSettings;
  11. #if !__MonoCS__
  12. using Microsoft.WindowsAPICodePack.Taskbar;
  13. #endif
  14. namespace GitUI
  15. {
  16. /// <summary>Base class for a Git Extensions <see cref="Form"/>.
  17. /// <remarks>
  18. /// Includes support for font, hotkey, icon, translation, and position restore.
  19. /// </remarks></summary>
  20. public class GitExtensionsForm : GitExtensionsFormBase
  21. {
  22. internal static Icon ApplicationIcon = GetApplicationIcon(Settings.IconStyle, Settings.IconColor);
  23. /// <summary>indicates whether the <see cref="Form"/>'s position will be restored</summary>
  24. readonly bool _enablePositionRestore;
  25. /// <summary>Creates a new <see cref="GitExtensionsForm"/> without position restore.</summary>
  26. public GitExtensionsForm()
  27. : this(false)
  28. {
  29. }
  30. /// <summary>Creates a new <see cref="GitExtensionsForm"/> indicating position restore.</summary>
  31. /// <param name="enablePositionRestore">Indicates whether the <see cref="Form"/>'s position
  32. /// will be restored upon being re-opened.</param>
  33. public GitExtensionsForm(bool enablePositionRestore)
  34. : base()
  35. {
  36. _enablePositionRestore = enablePositionRestore;
  37. Icon = ApplicationIcon;
  38. FormClosing += GitExtensionsForm_FormClosing;
  39. var cancelButton = new Button();
  40. cancelButton.Click += CancelButtonClick;
  41. CancelButton = cancelButton;
  42. }
  43. public virtual void CancelButtonClick(object sender, EventArgs e)
  44. {
  45. Close();
  46. }
  47. void GitExtensionsForm_FormClosing(object sender, FormClosingEventArgs e)
  48. {
  49. if (_enablePositionRestore)
  50. SavePosition(GetType().Name);
  51. #if !__MonoCS__
  52. if (GitCommands.Utils.EnvUtils.RunningOnWindows() && TaskbarManager.IsPlatformSupported)
  53. {
  54. try
  55. {
  56. TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress);
  57. }
  58. catch (InvalidOperationException) { }
  59. }
  60. #endif
  61. }
  62. #region icon
  63. protected void RotateApplicationIcon()
  64. {
  65. ApplicationIcon = GetApplicationIcon(Settings.IconStyle, Settings.IconColor);
  66. Icon = ApplicationIcon;
  67. }
  68. /// <summary>Specifies a Git Extensions' color index.</summary>
  69. protected enum ColorIndex
  70. {
  71. Default,
  72. Blue,
  73. Green,
  74. LightBlue,
  75. Purple,
  76. Red,
  77. Yellow,
  78. Unknown = -1
  79. }
  80. protected static ColorIndex GetColorIndexByName(string color)
  81. {
  82. switch (color)
  83. {
  84. case "default":
  85. return ColorIndex.Default;
  86. case "blue":
  87. return ColorIndex.Blue;
  88. case "green":
  89. return ColorIndex.Green;
  90. case "lightblue":
  91. return ColorIndex.LightBlue;
  92. case "purple":
  93. return ColorIndex.Purple;
  94. case "red":
  95. return ColorIndex.Red;
  96. case "yellow":
  97. return ColorIndex.Yellow;
  98. case "random":
  99. return (ColorIndex)new Random(DateTime.Now.Millisecond).Next(7);
  100. }
  101. return ColorIndex.Unknown;
  102. }
  103. public static Icon GetApplicationIcon(string iconStyle, string iconColor)
  104. {
  105. var colorIndex = (int)GetColorIndexByName(iconColor);
  106. if (colorIndex == (int) ColorIndex.Unknown)
  107. colorIndex = 0;
  108. Icon appIcon;
  109. if (iconStyle.Equals("small", StringComparison.OrdinalIgnoreCase))
  110. {
  111. Icon[] icons = {
  112. Resources.x_with_arrow,
  113. Resources.x_with_arrow_blue,
  114. Resources.x_with_arrow_green,
  115. Resources.x_with_arrow_lightblue,
  116. Resources.x_with_arrow_purple,
  117. Resources.x_with_arrow_red,
  118. Resources.x_with_arrow_yellow
  119. };
  120. Debug.Assert(icons.Length == 7);
  121. appIcon = icons[colorIndex];
  122. }
  123. else if (iconStyle.Equals("large", StringComparison.OrdinalIgnoreCase))
  124. {
  125. Icon[] icons = {
  126. Resources.git_extensions_logo_final,
  127. Resources.git_extensions_logo_final_blue,
  128. Resources.git_extensions_logo_final_green,
  129. Resources.git_extensions_logo_final_lightblue,
  130. Resources.git_extensions_logo_final_purple,
  131. Resources.git_extensions_logo_final_red,
  132. Resources.git_extensions_logo_final_yellow
  133. };
  134. Debug.Assert(icons.Length == 7);
  135. appIcon = icons[colorIndex];
  136. }
  137. else if (iconStyle.Equals("cow", StringComparison.OrdinalIgnoreCase))
  138. {
  139. Icon[] icons = {
  140. Resources.cow_head,
  141. Resources.cow_head_blue,
  142. Resources.cow_head_green,
  143. Resources.cow_head_blue,
  144. Resources.cow_head_purple,
  145. Resources.cow_head_red,
  146. Resources.cow_head_yellow
  147. };
  148. Debug.Assert(icons.Length == 7);
  149. appIcon = icons[colorIndex];
  150. }
  151. else
  152. {
  153. Icon[] icons = {
  154. Resources.git_extensions_logo_final_mixed,
  155. Resources.git_extensions_logo_final_mixed_blue,
  156. Resources.git_extensions_logo_final_mixed_green,
  157. Resources.git_extensions_logo_final_mixed_lightblue,
  158. Resources.git_extensions_logo_final_mixed_purple,
  159. Resources.git_extensions_logo_final_mixed_red,
  160. Resources.git_extensions_logo_final_mixed_yellow
  161. };
  162. Debug.Assert(icons.Length == 7);
  163. appIcon = icons[colorIndex];
  164. }
  165. Debug.Assert(appIcon != null);
  166. return appIcon;
  167. }
  168. #endregion icon
  169. /// <summary>Sets <see cref="AutoScaleMode"/>,
  170. /// restores position, raises the <see cref="Form.Load"/> event,
  171. /// and .
  172. /// </summary>
  173. protected override void OnLoad(EventArgs e)
  174. {
  175. base.OnLoad(e);
  176. if (_enablePositionRestore)
  177. RestorePosition(GetType().Name);
  178. if (!CheckComponent(this))
  179. OnRuntimeLoad(e);
  180. }
  181. /// <summary>Invoked at runtime during the <see cref="OnLoad"/> method.</summary>
  182. protected virtual void OnRuntimeLoad(EventArgs e)
  183. {
  184. }
  185. private bool _windowCentred;
  186. /// <summary>
  187. /// Restores the position of a form from the user settings. Does
  188. /// nothing if there is no entry for the form in the settings, or the
  189. /// setting would be invisible on the current display configuration.
  190. /// </summary>
  191. /// <param name = "name">The name to use when looking up the position in
  192. /// the settings</param>
  193. private void RestorePosition(String name)
  194. {
  195. if (!Visible ||
  196. WindowState == FormWindowState.Minimized)
  197. return;
  198. _windowCentred = (StartPosition == FormStartPosition.CenterParent);
  199. var position = LookupWindowPosition(name);
  200. if (position == null)
  201. return;
  202. StartPosition = FormStartPosition.Manual;
  203. if (FormBorderStyle == FormBorderStyle.Sizable ||
  204. FormBorderStyle == FormBorderStyle.SizableToolWindow)
  205. Size = position.Rect.Size;
  206. if (Owner == null || !_windowCentred)
  207. {
  208. Point location = position.Rect.Location;
  209. Rectangle? rect = FindWindowScreen(location);
  210. if (rect != null)
  211. location.Y = rect.Value.Y;
  212. DesktopLocation = location;
  213. }
  214. else
  215. {
  216. // Calculate location for modal form with parent
  217. Location = new Point(Owner.Left + Owner.Width / 2 - Width / 2,
  218. Math.Max(0, Owner.Top + Owner.Height / 2 - Height / 2));
  219. }
  220. if(WindowState != position.State)
  221. WindowState = position.State;
  222. }
  223. static Rectangle? FindWindowScreen(Point location)
  224. {
  225. SortedDictionary<float, Rectangle> distance = new SortedDictionary<float, Rectangle>();
  226. foreach (var rect in (from screen in Screen.AllScreens
  227. select screen.WorkingArea))
  228. {
  229. if (rect.Contains(location) && !distance.ContainsKey(0.0f))
  230. return null; // title in screen
  231. int midPointX = (rect.X + rect.Width / 2);
  232. int midPointY = (rect.Y + rect.Height / 2);
  233. float d = (float)Math.Sqrt((location.X - midPointX) * (location.X - midPointX) +
  234. (location.Y - midPointY) * (location.Y - midPointY));
  235. distance.Add(d, rect);
  236. }
  237. if (distance.Count > 0)
  238. {
  239. return distance.First().Value;
  240. }
  241. else
  242. {
  243. return null;
  244. }
  245. }
  246. private static WindowPositionList _windowPositionList;
  247. /// <summary>
  248. /// Save the position of a form to the user settings. Hides the window
  249. /// as a side-effect.
  250. /// </summary>
  251. /// <param name = "name">The name to use when writing the position to the
  252. /// settings</param>
  253. private void SavePosition(String name)
  254. {
  255. try
  256. {
  257. var rectangle =
  258. WindowState == FormWindowState.Normal
  259. ? DesktopBounds
  260. : RestoreBounds;
  261. var formWindowState =
  262. WindowState == FormWindowState.Maximized
  263. ? FormWindowState.Maximized
  264. : FormWindowState.Normal;
  265. // Write to the user settings:
  266. if (_windowPositionList == null)
  267. _windowPositionList = WindowPositionList.Load();
  268. WindowPosition windowPosition = _windowPositionList.Get(name);
  269. // Don't save location when we center modal form
  270. if (windowPosition != null && Owner != null && _windowCentred)
  271. {
  272. if (rectangle.Width <= windowPosition.Rect.Width && rectangle.Height <= windowPosition.Rect.Height)
  273. rectangle.Location = windowPosition.Rect.Location;
  274. }
  275. var position = new WindowPosition(rectangle, formWindowState, name);
  276. _windowPositionList.AddOrUpdate(position);
  277. _windowPositionList.Save();
  278. }
  279. catch (Exception)
  280. {
  281. //TODO: howto restore a corrupted config?
  282. }
  283. }
  284. /// <summary>
  285. /// Looks up a window in the user settings and returns its saved position.
  286. /// </summary>
  287. /// <param name = "name">The name.</param>
  288. /// <returns>
  289. /// The saved window position if it exists. Null if the entry
  290. /// doesn't exist, or would not be visible on any screen in the user's
  291. /// current display setup.
  292. /// </returns>
  293. private static WindowPosition LookupWindowPosition(String name)
  294. {
  295. try
  296. {
  297. if (_windowPositionList == null)
  298. _windowPositionList = WindowPositionList.Load();
  299. if (_windowPositionList == null)
  300. {
  301. return null;
  302. }
  303. var position = _windowPositionList.Get(name);
  304. if (position == null || position.Rect.IsEmpty)
  305. return null;
  306. if (Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(position.Rect)))
  307. {
  308. return position;
  309. }
  310. }
  311. catch (Exception)
  312. {
  313. //TODO: howto restore a corrupted config?
  314. }
  315. return null;
  316. }
  317. }
  318. }