PageRenderTime 37ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Core/SwatchControl.cs

https://bitbucket.org/tuldok89/openpdn
C# | 286 lines | 233 code | 44 blank | 9 comment | 26 complexity | c3348f3037270bcecf96c208072d71b0 MD5 | raw file
  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.Base;
  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.Windows.Forms;
  17. using System.Windows.Forms.VisualStyles;
  18. namespace PaintDotNet
  19. {
  20. public sealed class SwatchControl
  21. : Control
  22. {
  23. private List<ColorBgra> _colors = new List<ColorBgra>();
  24. private const int DefaultUnscaledSwatchSize = 12;
  25. private int _unscaledSwatchSize = DefaultUnscaledSwatchSize;
  26. private bool _mouseDown;
  27. private int _mouseDownIndex = -1;
  28. private bool _blinkHighlight;
  29. private const int BlinkInterval = 500;
  30. private Timer _blinkHighlightTimer;
  31. [Browsable(false)]
  32. public bool BlinkHighlight
  33. {
  34. get
  35. {
  36. return _blinkHighlight;
  37. }
  38. set
  39. {
  40. _blinkHighlight = value;
  41. _blinkHighlightTimer.Enabled = value;
  42. Invalidate();
  43. }
  44. }
  45. public event EventHandler ColorsChanged;
  46. private void OnColorsChanged()
  47. {
  48. if (ColorsChanged != null)
  49. {
  50. ColorsChanged(this, EventArgs.Empty);
  51. }
  52. }
  53. [Browsable(false)]
  54. public ColorBgra[] Colors
  55. {
  56. get
  57. {
  58. return _colors.ToArray();
  59. }
  60. set
  61. {
  62. _colors = new List<ColorBgra>(value);
  63. _mouseDown = false;
  64. Invalidate();
  65. OnColorsChanged();
  66. }
  67. }
  68. [DefaultValue(DefaultUnscaledSwatchSize)]
  69. [Browsable(true)]
  70. public int UnscaledSwatchSize
  71. {
  72. get
  73. {
  74. return _unscaledSwatchSize;
  75. }
  76. set
  77. {
  78. _unscaledSwatchSize = value;
  79. _mouseDown = false;
  80. Invalidate();
  81. }
  82. }
  83. public event EventHandler<EventArgs<Pair<int, MouseButtons>>> ColorClicked;
  84. private void OnColorClicked(int index, MouseButtons buttons)
  85. {
  86. if (ColorClicked != null)
  87. {
  88. ColorClicked(this, new EventArgs<Pair<int, MouseButtons>>(Pair.Create(index, buttons)));
  89. }
  90. }
  91. public SwatchControl()
  92. {
  93. InitializeComponent();
  94. }
  95. private void InitializeComponent()
  96. {
  97. _blinkHighlightTimer = new Timer();
  98. _blinkHighlightTimer.Tick += BlinkHighlightTimerTick;
  99. _blinkHighlightTimer.Enabled = false;
  100. _blinkHighlightTimer.Interval = BlinkInterval;
  101. DoubleBuffered = true;
  102. ResizeRedraw = true;
  103. }
  104. private void BlinkHighlightTimerTick(object sender, EventArgs e)
  105. {
  106. Invalidate();
  107. }
  108. protected override void Dispose(bool disposing)
  109. {
  110. if (disposing)
  111. {
  112. if (_blinkHighlightTimer != null)
  113. {
  114. _blinkHighlightTimer.Dispose();
  115. _blinkHighlightTimer = null;
  116. }
  117. }
  118. base.Dispose(disposing);
  119. }
  120. private int MouseXYToColorIndex(int x, int y)
  121. {
  122. if (x < 0 || y < 0 || x >= ClientSize.Width || y >= ClientSize.Height)
  123. {
  124. return -1;
  125. }
  126. int scaledSwatchSize = UI.ScaleWidth(_unscaledSwatchSize);
  127. int swatchColumns = ClientSize.Width / scaledSwatchSize;
  128. int row = y / scaledSwatchSize;
  129. int col = x / scaledSwatchSize;
  130. int index = col + (row * swatchColumns);
  131. // Make sure they aren't on the last item of a row that actually got clipped off
  132. if (col == swatchColumns)
  133. {
  134. index = -1;
  135. }
  136. return index;
  137. }
  138. protected override void OnMouseLeave(EventArgs e)
  139. {
  140. _mouseDown = false;
  141. Invalidate();
  142. base.OnMouseLeave(e);
  143. }
  144. protected override void OnMouseDown(MouseEventArgs e)
  145. {
  146. _mouseDown = true;
  147. _mouseDownIndex = MouseXYToColorIndex(e.X, e.Y);
  148. Invalidate();
  149. base.OnMouseDown(e);
  150. }
  151. protected override void OnMouseUp(MouseEventArgs e)
  152. {
  153. int colorIndex = MouseXYToColorIndex(e.X, e.Y);
  154. if (colorIndex == _mouseDownIndex &&
  155. colorIndex >= 0 &&
  156. colorIndex < _colors.Count)
  157. {
  158. OnColorClicked(colorIndex, e.Button);
  159. }
  160. _mouseDown = false;
  161. Invalidate();
  162. base.OnMouseUp(e);
  163. }
  164. protected override void OnMouseMove(MouseEventArgs e)
  165. {
  166. Invalidate();
  167. base.OnMouseMove(e);
  168. }
  169. protected override void OnPaint(PaintEventArgs e)
  170. {
  171. e.Graphics.CompositingMode = CompositingMode.SourceOver;
  172. int scaledSwatchSize = UI.ScaleWidth(_unscaledSwatchSize);
  173. int swatchColumns = ClientSize.Width / scaledSwatchSize;
  174. Point mousePt = MousePosition;
  175. mousePt = PointToClient(mousePt);
  176. int activeIndex = MouseXYToColorIndex(mousePt.X, mousePt.Y);
  177. for (int i = 0; i < _colors.Count; ++i)
  178. {
  179. ColorBgra c = _colors[i];
  180. int swatchX = i % swatchColumns;
  181. int swatchY = i / swatchColumns;
  182. var swatchRect = new Rectangle(
  183. swatchX * scaledSwatchSize,
  184. swatchY * scaledSwatchSize,
  185. scaledSwatchSize,
  186. scaledSwatchSize);
  187. PushButtonState state;
  188. if (_mouseDown)
  189. {
  190. state = i == _mouseDownIndex ? PushButtonState.Pressed : PushButtonState.Normal;
  191. }
  192. else if (i == activeIndex)
  193. {
  194. state = PushButtonState.Hot;
  195. }
  196. else
  197. {
  198. state = PushButtonState.Normal;
  199. }
  200. bool drawOutline;
  201. switch (state)
  202. {
  203. case PushButtonState.Hot:
  204. drawOutline = true;
  205. break;
  206. case PushButtonState.Pressed:
  207. drawOutline = false;
  208. break;
  209. case PushButtonState.Default:
  210. case PushButtonState.Disabled:
  211. case PushButtonState.Normal:
  212. drawOutline = false;
  213. break;
  214. default:
  215. throw new InvalidEnumArgumentException();
  216. }
  217. Utility.DrawColorRectangle(e.Graphics, swatchRect, c.ToColor(), drawOutline);
  218. }
  219. if (_blinkHighlight)
  220. {
  221. int period = (Math.Abs(Environment.TickCount) / BlinkInterval) % 2;
  222. Color color;
  223. switch (period)
  224. {
  225. case 0:
  226. color = SystemColors.Window;
  227. break;
  228. case 1:
  229. color = SystemColors.Highlight;
  230. break;
  231. default:
  232. throw new InvalidOperationException();
  233. }
  234. using (var pen = new Pen(color))
  235. {
  236. e.Graphics.DrawRectangle(pen, new Rectangle(0, 0, Width - 1, Height - 1));
  237. }
  238. }
  239. base.OnPaint(e);
  240. }
  241. }
  242. }