ColorPickerTests.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. using UnitTests;
  2. namespace UnitTests.ViewsTests;
  3. public class ColorPickerTests
  4. {
  5. [Fact]
  6. [SetupFakeApplication]
  7. public void ColorPicker_ChangeValueOnUI_UpdatesAllUIElements ()
  8. {
  9. ColorPicker cp = GetColorPicker (ColorModel.RGB, true);
  10. var otherView = new View { CanFocus = true };
  11. Application.Running?.Add (otherView); // thi sets focus to otherView
  12. Assert.True (otherView.HasFocus);
  13. cp.SetFocus ();
  14. Assert.False (otherView.HasFocus);
  15. cp.Draw ();
  16. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  17. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  18. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  19. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  20. TextField rTextField = GetTextField (cp, ColorPickerPart.Bar1);
  21. TextField gTextField = GetTextField (cp, ColorPickerPart.Bar2);
  22. TextField bTextField = GetTextField (cp, ColorPickerPart.Bar3);
  23. Assert.Equal ("R:", r.Text);
  24. Assert.Equal (2, r.TrianglePosition);
  25. Assert.Equal ("0", rTextField.Text);
  26. Assert.Equal ("G:", g.Text);
  27. Assert.Equal (2, g.TrianglePosition);
  28. Assert.Equal ("0", gTextField.Text);
  29. Assert.Equal ("B:", b.Text);
  30. Assert.Equal (2, b.TrianglePosition);
  31. Assert.Equal ("0", bTextField.Text);
  32. Assert.Equal ("#000000", hex.Text);
  33. // Change value using text field
  34. TextField rBarTextField = cp.SubViews.OfType<TextField> ().First (tf => tf.Text == "0");
  35. rBarTextField.SetFocus ();
  36. rBarTextField.Text = "128";
  37. otherView.SetFocus ();
  38. Assert.True (otherView.HasFocus);
  39. cp.Draw ();
  40. Assert.Equal ("R:", r.Text);
  41. Assert.Equal (9, r.TrianglePosition);
  42. Assert.Equal ("128", rTextField.Text);
  43. Assert.Equal ("G:", g.Text);
  44. Assert.Equal (2, g.TrianglePosition);
  45. Assert.Equal ("0", gTextField.Text);
  46. Assert.Equal ("B:", b.Text);
  47. Assert.Equal (2, b.TrianglePosition);
  48. Assert.Equal ("0", bTextField.Text);
  49. Assert.Equal ("#800000", hex.Text);
  50. }
  51. [Fact]
  52. [SetupFakeApplication]
  53. public void ColorPicker_ClickingAtEndOfBar_SetsMaxValue ()
  54. {
  55. ColorPicker cp = GetColorPicker (ColorModel.RGB, false);
  56. cp.Draw ();
  57. // Click at the end of the Red bar
  58. cp.Focused.RaiseMouseEvent (
  59. new ()
  60. {
  61. Flags = MouseFlags.Button1Pressed,
  62. Position = new (19, 0) // Assuming 0-based indexing
  63. });
  64. cp.Draw ();
  65. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  66. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  67. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  68. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  69. Assert.Equal ("R:", r.Text);
  70. Assert.Equal (19, r.TrianglePosition);
  71. Assert.Equal ("G:", g.Text);
  72. Assert.Equal (2, g.TrianglePosition);
  73. Assert.Equal ("B:", b.Text);
  74. Assert.Equal (2, b.TrianglePosition);
  75. Assert.Equal ("#FF0000", hex.Text);
  76. }
  77. [Fact]
  78. [SetupFakeApplication]
  79. public void ColorPicker_ClickingBeyondBar_ChangesToMaxValue ()
  80. {
  81. ColorPicker cp = GetColorPicker (ColorModel.RGB, false);
  82. cp.Draw ();
  83. // Click beyond the bar
  84. cp.Focused.RaiseMouseEvent (
  85. new ()
  86. {
  87. Flags = MouseFlags.Button1Pressed,
  88. Position = new (21, 0) // Beyond the bar
  89. });
  90. cp.Draw ();
  91. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  92. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  93. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  94. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  95. Assert.Equal ("R:", r.Text);
  96. Assert.Equal (19, r.TrianglePosition);
  97. Assert.Equal ("G:", g.Text);
  98. Assert.Equal (2, g.TrianglePosition);
  99. Assert.Equal ("B:", b.Text);
  100. Assert.Equal (2, b.TrianglePosition);
  101. Assert.Equal ("#FF0000", hex.Text);
  102. }
  103. [Fact]
  104. [SetupFakeApplication]
  105. public void ColorPicker_ClickingDifferentBars_ChangesFocus ()
  106. {
  107. ColorPicker cp = GetColorPicker (ColorModel.RGB, false);
  108. cp.Draw ();
  109. // Click on Green bar
  110. Application.RaiseMouseEvent (
  111. new ()
  112. {
  113. Flags = MouseFlags.Button1Pressed,
  114. ScreenPosition = new (0, 1)
  115. });
  116. //cp.SubViews.OfType<GBar> ()
  117. // .Single ()
  118. // .OnMouseEvent (
  119. // new ()
  120. // {
  121. // Flags = MouseFlags.Button1Pressed,
  122. // Position = new (0, 1)
  123. // });
  124. cp.Draw ();
  125. Assert.IsAssignableFrom<GBar> (cp.Focused);
  126. // Click on Blue bar
  127. Application.RaiseMouseEvent (
  128. new ()
  129. {
  130. Flags = MouseFlags.Button1Pressed,
  131. ScreenPosition = new (0, 2)
  132. });
  133. //cp.SubViews.OfType<BBar> ()
  134. // .Single ()
  135. // .OnMouseEvent (
  136. // new ()
  137. // {
  138. // Flags = MouseFlags.Button1Pressed,
  139. // Position = new (0, 2)
  140. // });
  141. cp.Draw ();
  142. Assert.IsAssignableFrom<BBar> (cp.Focused);
  143. }
  144. [Fact]
  145. [SetupFakeApplication]
  146. public void ColorPicker_Construct_DefaultValue ()
  147. {
  148. ColorPicker cp = GetColorPicker (ColorModel.HSV, false);
  149. // Should be only a single text field (Hex) because ShowTextFields is false
  150. Assert.Single (cp.SubViews.OfType<TextField> ());
  151. cp.Draw ();
  152. // All bars should be at 0 with the triangle at 0 (+2 because of "H:", "S:" etc)
  153. ColorBar h = GetColorBar (cp, ColorPickerPart.Bar1);
  154. Assert.Equal ("H:", h.Text);
  155. Assert.Equal (2, h.TrianglePosition);
  156. Assert.IsType<HueBar> (h);
  157. ColorBar s = GetColorBar (cp, ColorPickerPart.Bar2);
  158. Assert.Equal ("S:", s.Text);
  159. Assert.Equal (2, s.TrianglePosition);
  160. Assert.IsType<SaturationBar> (s);
  161. ColorBar v = GetColorBar (cp, ColorPickerPart.Bar3);
  162. Assert.Equal ("V:", v.Text);
  163. Assert.Equal (2, v.TrianglePosition);
  164. Assert.IsType<ValueBar> (v);
  165. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  166. Assert.Equal ("#000000", hex.Text);
  167. }
  168. [Fact]
  169. [SetupFakeApplication]
  170. public void ColorPicker_DisposesOldViews_OnModelChange ()
  171. {
  172. ColorPicker cp = GetColorPicker (ColorModel.HSL, true);
  173. ColorBar b1 = GetColorBar (cp, ColorPickerPart.Bar1);
  174. ColorBar b2 = GetColorBar (cp, ColorPickerPart.Bar2);
  175. ColorBar b3 = GetColorBar (cp, ColorPickerPart.Bar3);
  176. TextField tf1 = GetTextField (cp, ColorPickerPart.Bar1);
  177. TextField tf2 = GetTextField (cp, ColorPickerPart.Bar2);
  178. TextField tf3 = GetTextField (cp, ColorPickerPart.Bar3);
  179. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  180. #if DEBUG_IDISPOSABLE
  181. Assert.All (new View [] { b1, b2, b3, tf1, tf2, tf3, hex }, b => Assert.False (b.WasDisposed));
  182. #endif
  183. cp.Style.ColorModel = ColorModel.RGB;
  184. cp.ApplyStyleChanges ();
  185. ColorBar b1After = GetColorBar (cp, ColorPickerPart.Bar1);
  186. ColorBar b2After = GetColorBar (cp, ColorPickerPart.Bar2);
  187. ColorBar b3After = GetColorBar (cp, ColorPickerPart.Bar3);
  188. TextField tf1After = GetTextField (cp, ColorPickerPart.Bar1);
  189. TextField tf2After = GetTextField (cp, ColorPickerPart.Bar2);
  190. TextField tf3After = GetTextField (cp, ColorPickerPart.Bar3);
  191. TextField hexAfter = GetTextField (cp, ColorPickerPart.Hex);
  192. // Old bars should be disposed
  193. #if DEBUG_IDISPOSABLE
  194. Assert.All (new View [] { b1, b2, b3, tf1, tf2, tf3, hex }, b => Assert.True (b.WasDisposed));
  195. #endif
  196. Assert.NotSame (hex, hexAfter);
  197. Assert.NotSame (b1, b1After);
  198. Assert.NotSame (b2, b2After);
  199. Assert.NotSame (b3, b3After);
  200. Assert.NotSame (tf1, tf1After);
  201. Assert.NotSame (tf2, tf2After);
  202. Assert.NotSame (tf3, tf3After);
  203. }
  204. [Fact]
  205. [SetupFakeApplication]
  206. public void ColorPicker_EnterHexFor_ColorName ()
  207. {
  208. ColorPicker cp = GetColorPicker (ColorModel.RGB, true, true);
  209. cp.Draw ();
  210. TextField name = GetTextField (cp, ColorPickerPart.ColorName);
  211. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  212. hex.SetFocus ();
  213. Assert.True (hex.HasFocus);
  214. Assert.Same (hex, cp.Focused);
  215. hex.Text = "";
  216. name.Text = "";
  217. Assert.Empty (hex.Text);
  218. Assert.Empty (name.Text);
  219. Application.RaiseKeyDownEvent ('#');
  220. Assert.Empty (name.Text);
  221. //7FFFD4
  222. Assert.Equal ("#", hex.Text);
  223. Application.RaiseKeyDownEvent ('7');
  224. Application.RaiseKeyDownEvent ('F');
  225. Application.RaiseKeyDownEvent ('F');
  226. Application.RaiseKeyDownEvent ('F');
  227. Application.RaiseKeyDownEvent ('D');
  228. Assert.Empty (name.Text);
  229. Application.RaiseKeyDownEvent ('4');
  230. Assert.True (hex.HasFocus);
  231. // Tab out of the hex field - should wrap to first focusable subview
  232. Application.RaiseKeyDownEvent (Key.Tab);
  233. Assert.False (hex.HasFocus);
  234. Assert.NotSame (hex, cp.Focused);
  235. // Color name should be recognised as a known string and populated
  236. Assert.Equal ("#7FFFD4", hex.Text);
  237. Assert.Equal ("Aquamarine", name.Text);
  238. }
  239. /// <summary>
  240. /// In this version we use the Enter button to accept the typed text instead
  241. /// of tabbing to the next view.
  242. /// </summary>
  243. [Fact]
  244. [SetupFakeApplication]
  245. public void ColorPicker_EnterHexFor_ColorName_AcceptVariation ()
  246. {
  247. ColorPicker cp = GetColorPicker (ColorModel.RGB, true, true);
  248. cp.Draw ();
  249. TextField name = GetTextField (cp, ColorPickerPart.ColorName);
  250. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  251. hex.SetFocus ();
  252. Assert.True (hex.HasFocus);
  253. Assert.Same (hex, cp.Focused);
  254. hex.Text = "";
  255. name.Text = "";
  256. Assert.Empty (hex.Text);
  257. Assert.Empty (name.Text);
  258. Application.RaiseKeyDownEvent ('#');
  259. Assert.Empty (name.Text);
  260. //7FFFD4
  261. Assert.Equal ("#", hex.Text);
  262. Application.RaiseKeyDownEvent ('7');
  263. Application.RaiseKeyDownEvent ('F');
  264. Application.RaiseKeyDownEvent ('F');
  265. Application.RaiseKeyDownEvent ('F');
  266. Application.RaiseKeyDownEvent ('D');
  267. Assert.Empty (name.Text);
  268. Application.RaiseKeyDownEvent ('4');
  269. Assert.True (hex.HasFocus);
  270. // Should stay in the hex field (because accept not tab)
  271. Application.RaiseKeyDownEvent (Key.Enter);
  272. Assert.True (hex.HasFocus);
  273. Assert.Same (hex, cp.Focused);
  274. // But still, Color name should be recognised as a known string and populated
  275. Assert.Equal ("#7FFFD4", hex.Text);
  276. Assert.Equal ("Aquamarine", name.Text);
  277. }
  278. [Fact]
  279. [SetupFakeApplication]
  280. public void ColorPicker_InvalidHexInput_DoesNotChangeColor ()
  281. {
  282. ColorPicker cp = GetColorPicker (ColorModel.RGB, true);
  283. cp.Draw ();
  284. // Enter invalid hex value
  285. TextField hexField = cp.SubViews.OfType<TextField> ().First (tf => tf.Text == "#000000");
  286. hexField.SetFocus ();
  287. hexField.Text = "#ZZZZZZ";
  288. Assert.True (hexField.HasFocus);
  289. Assert.Equal ("#ZZZZZZ", hexField.Text);
  290. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  291. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  292. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  293. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  294. Assert.Equal ("#ZZZZZZ", hex.Text);
  295. // Advance away from hexField to cause validation
  296. cp.AdvanceFocus (NavigationDirection.Forward, null);
  297. cp.Draw ();
  298. Assert.Equal ("R:", r.Text);
  299. Assert.Equal (2, r.TrianglePosition);
  300. Assert.Equal ("G:", g.Text);
  301. Assert.Equal (2, g.TrianglePosition);
  302. Assert.Equal ("B:", b.Text);
  303. Assert.Equal (2, b.TrianglePosition);
  304. Assert.Equal ("#000000", hex.Text);
  305. }
  306. [Fact]
  307. [SetupFakeApplication]
  308. public void ColorPicker_RGB_KeyboardNavigation ()
  309. {
  310. ColorPicker cp = GetColorPicker (ColorModel.RGB, false);
  311. cp.Draw ();
  312. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  313. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  314. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  315. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  316. Assert.Equal ("R:", r.Text);
  317. Assert.Equal (2, r.TrianglePosition);
  318. Assert.IsType<RBar> (r);
  319. Assert.Equal ("G:", g.Text);
  320. Assert.Equal (2, g.TrianglePosition);
  321. Assert.IsType<GBar> (g);
  322. Assert.Equal ("B:", b.Text);
  323. Assert.Equal (2, b.TrianglePosition);
  324. Assert.IsType<BBar> (b);
  325. Assert.Equal ("#000000", hex.Text);
  326. Assert.IsAssignableFrom<IColorBar> (cp.Focused);
  327. cp.Draw ();
  328. Application.RaiseKeyDownEvent (Key.CursorRight);
  329. cp.Draw ();
  330. Assert.Equal (3, r.TrianglePosition);
  331. Assert.Equal ("#0F0000", hex.Text);
  332. Application.RaiseKeyDownEvent (Key.CursorRight);
  333. cp.Draw ();
  334. Assert.Equal (4, r.TrianglePosition);
  335. Assert.Equal ("#1E0000", hex.Text);
  336. // Use cursor to move the triangle all the way to the right
  337. for (var i = 0; i < 1000; i++)
  338. {
  339. Application.RaiseKeyDownEvent (Key.CursorRight);
  340. }
  341. cp.Draw ();
  342. // 20 width and TrianglePosition is 0 indexed
  343. // Meaning we are asserting that triangle is at end
  344. Assert.Equal (19, r.TrianglePosition);
  345. Assert.Equal ("#FF0000", hex.Text);
  346. }
  347. [Fact]
  348. [SetupFakeApplication]
  349. public void ColorPicker_RGB_MouseNavigation ()
  350. {
  351. ColorPicker cp = GetColorPicker (ColorModel.RGB, false);
  352. cp.Draw ();
  353. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  354. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  355. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  356. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  357. Assert.Equal ("R:", r.Text);
  358. Assert.Equal (2, r.TrianglePosition);
  359. Assert.IsType<RBar> (r);
  360. Assert.Equal ("G:", g.Text);
  361. Assert.Equal (2, g.TrianglePosition);
  362. Assert.IsType<GBar> (g);
  363. Assert.Equal ("B:", b.Text);
  364. Assert.Equal (2, b.TrianglePosition);
  365. Assert.IsType<BBar> (b);
  366. Assert.Equal ("#000000", hex.Text);
  367. Assert.IsAssignableFrom<IColorBar> (cp.Focused);
  368. cp.Focused.RaiseMouseEvent (
  369. new ()
  370. {
  371. Flags = MouseFlags.Button1Pressed,
  372. Position = new (3, 0)
  373. });
  374. cp.Draw ();
  375. Assert.Equal (3, r.TrianglePosition);
  376. Assert.Equal ("#0F0000", hex.Text);
  377. cp.Focused.RaiseMouseEvent (
  378. new ()
  379. {
  380. Flags = MouseFlags.Button1Pressed,
  381. Position = new (4, 0)
  382. });
  383. cp.Draw ();
  384. Assert.Equal (4, r.TrianglePosition);
  385. Assert.Equal ("#1E0000", hex.Text);
  386. }
  387. [Theory]
  388. [SetupFakeApplication]
  389. [MemberData (nameof (ColorPickerTestData))]
  390. public void ColorPicker_RGB_NoText (
  391. Color c,
  392. string expectedR,
  393. int expectedRTriangle,
  394. string expectedG,
  395. int expectedGTriangle,
  396. string expectedB,
  397. int expectedBTriangle,
  398. string expectedHex
  399. )
  400. {
  401. ColorPicker cp = GetColorPicker (ColorModel.RGB, false);
  402. cp.SelectedColor = c;
  403. cp.Draw ();
  404. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  405. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  406. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  407. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  408. Assert.Equal (expectedR, r.Text);
  409. Assert.Equal (expectedRTriangle, r.TrianglePosition);
  410. Assert.Equal (expectedG, g.Text);
  411. Assert.Equal (expectedGTriangle, g.TrianglePosition);
  412. Assert.Equal (expectedB, b.Text);
  413. Assert.Equal (expectedBTriangle, b.TrianglePosition);
  414. Assert.Equal (expectedHex, hex.Text);
  415. }
  416. [Theory]
  417. [SetupFakeApplication]
  418. [MemberData (nameof (ColorPickerTestData_WithTextFields))]
  419. public void ColorPicker_RGB_NoText_WithTextFields (
  420. Color c,
  421. string expectedR,
  422. int expectedRTriangle,
  423. int expectedRValue,
  424. string expectedG,
  425. int expectedGTriangle,
  426. int expectedGValue,
  427. string expectedB,
  428. int expectedBTriangle,
  429. int expectedBValue,
  430. string expectedHex
  431. )
  432. {
  433. ColorPicker cp = GetColorPicker (ColorModel.RGB, true);
  434. cp.SelectedColor = c;
  435. cp.Draw ();
  436. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  437. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  438. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  439. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  440. TextField rTextField = GetTextField (cp, ColorPickerPart.Bar1);
  441. TextField gTextField = GetTextField (cp, ColorPickerPart.Bar2);
  442. TextField bTextField = GetTextField (cp, ColorPickerPart.Bar3);
  443. Assert.Equal (expectedR, r.Text);
  444. Assert.Equal (expectedRTriangle, r.TrianglePosition);
  445. Assert.Equal (expectedRValue.ToString (), rTextField.Text);
  446. Assert.Equal (expectedG, g.Text);
  447. Assert.Equal (expectedGTriangle, g.TrianglePosition);
  448. Assert.Equal (expectedGValue.ToString (), gTextField.Text);
  449. Assert.Equal (expectedB, b.Text);
  450. Assert.Equal (expectedBTriangle, b.TrianglePosition);
  451. Assert.Equal (expectedBValue.ToString (), bTextField.Text);
  452. Assert.Equal (expectedHex, hex.Text);
  453. }
  454. [Fact]
  455. [SetupFakeApplication]
  456. public void ColorPicker_SwitchingColorModels_ResetsBars ()
  457. {
  458. ColorPicker cp = GetColorPicker (ColorModel.RGB, false);
  459. cp.BeginInit ();
  460. cp.EndInit ();
  461. cp.SelectedColor = new (255, 0);
  462. cp.Draw ();
  463. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  464. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  465. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  466. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  467. Assert.Equal ("R:", r.Text);
  468. Assert.Equal (19, r.TrianglePosition);
  469. Assert.Equal ("G:", g.Text);
  470. Assert.Equal (2, g.TrianglePosition);
  471. Assert.Equal ("B:", b.Text);
  472. Assert.Equal (2, b.TrianglePosition);
  473. Assert.Equal ("#FF0000", hex.Text);
  474. // Switch to HSV
  475. cp.Style.ColorModel = ColorModel.HSV;
  476. cp.ApplyStyleChanges ();
  477. cp.Draw ();
  478. ColorBar h = GetColorBar (cp, ColorPickerPart.Bar1);
  479. ColorBar s = GetColorBar (cp, ColorPickerPart.Bar2);
  480. ColorBar v = GetColorBar (cp, ColorPickerPart.Bar3);
  481. Assert.Equal ("H:", h.Text);
  482. Assert.Equal (2, h.TrianglePosition);
  483. Assert.Equal ("S:", s.Text);
  484. Assert.Equal (19, s.TrianglePosition);
  485. Assert.Equal ("V:", v.Text);
  486. Assert.Equal (19, v.TrianglePosition);
  487. Assert.Equal ("#FF0000", hex.Text);
  488. }
  489. [Fact]
  490. [SetupFakeApplication]
  491. public void ColorPicker_SyncBetweenTextFieldAndBars ()
  492. {
  493. ColorPicker cp = GetColorPicker (ColorModel.RGB, true);
  494. cp.Draw ();
  495. // Change value using the bar
  496. RBar rBar = cp.SubViews.OfType<RBar> ().First ();
  497. rBar.Value = 128;
  498. cp.Draw ();
  499. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  500. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  501. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  502. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  503. TextField rTextField = GetTextField (cp, ColorPickerPart.Bar1);
  504. TextField gTextField = GetTextField (cp, ColorPickerPart.Bar2);
  505. TextField bTextField = GetTextField (cp, ColorPickerPart.Bar3);
  506. Assert.Equal ("R:", r.Text);
  507. Assert.Equal (9, r.TrianglePosition);
  508. Assert.Equal ("128", rTextField.Text);
  509. Assert.Equal ("G:", g.Text);
  510. Assert.Equal (2, g.TrianglePosition);
  511. Assert.Equal ("0", gTextField.Text);
  512. Assert.Equal ("B:", b.Text);
  513. Assert.Equal (2, b.TrianglePosition);
  514. Assert.Equal ("0", bTextField.Text);
  515. Assert.Equal ("#800000", hex.Text);
  516. }
  517. [Fact]
  518. [SetupFakeApplication]
  519. public void ColorPicker_TabCompleteColorName ()
  520. {
  521. ColorPicker cp = GetColorPicker (ColorModel.RGB, true, true);
  522. cp.Draw ();
  523. ColorBar r = GetColorBar (cp, ColorPickerPart.Bar1);
  524. ColorBar g = GetColorBar (cp, ColorPickerPart.Bar2);
  525. ColorBar b = GetColorBar (cp, ColorPickerPart.Bar3);
  526. TextField name = GetTextField (cp, ColorPickerPart.ColorName);
  527. TextField hex = GetTextField (cp, ColorPickerPart.Hex);
  528. name.SetFocus ();
  529. Assert.True (name.HasFocus);
  530. Assert.Same (name, cp.Focused);
  531. name.Text = "";
  532. Assert.Empty (name.Text);
  533. Application.RaiseKeyDownEvent (Key.A);
  534. Application.RaiseKeyDownEvent (Key.Q);
  535. Assert.Equal ("aq", name.Text);
  536. // Auto complete the color name
  537. Application.RaiseKeyDownEvent (Key.Tab);
  538. // Match cyan alternative name
  539. Assert.Equal ("Aqua", name.Text);
  540. Assert.True (name.HasFocus);
  541. Application.RaiseKeyDownEvent (Key.Tab);
  542. // Resolves to cyan color
  543. Assert.Equal ("Aqua", name.Text);
  544. // Tab out of the text field
  545. Application.RaiseKeyDownEvent (Key.Tab);
  546. Assert.False (name.HasFocus);
  547. Assert.NotSame (name, cp.Focused);
  548. Assert.Equal ("#00FFFF", hex.Text);
  549. }
  550. public static IEnumerable<object []> ColorPickerTestData ()
  551. {
  552. yield return new object []
  553. {
  554. new Color (255, 0),
  555. "R:", 19, "G:", 2, "B:", 2, "#FF0000"
  556. };
  557. yield return new object []
  558. {
  559. new Color (0, 255),
  560. "R:", 2, "G:", 19, "B:", 2, "#00FF00"
  561. };
  562. yield return new object []
  563. {
  564. new Color (0, 0, 255),
  565. "R:", 2, "G:", 2, "B:", 19, "#0000FF"
  566. };
  567. yield return new object []
  568. {
  569. new Color (125, 125, 125),
  570. "R:", 11, "G:", 11, "B:", 11, "#7D7D7D"
  571. };
  572. }
  573. public static IEnumerable<object []> ColorPickerTestData_WithTextFields ()
  574. {
  575. yield return new object []
  576. {
  577. new Color (255, 0),
  578. "R:", 15, 255, "G:", 2, 0, "B:", 2, 0, "#FF0000"
  579. };
  580. yield return new object []
  581. {
  582. new Color (0, 255),
  583. "R:", 2, 0, "G:", 15, 255, "B:", 2, 0, "#00FF00"
  584. };
  585. yield return new object []
  586. {
  587. new Color (0, 0, 255),
  588. "R:", 2, 0, "G:", 2, 0, "B:", 15, 255, "#0000FF"
  589. };
  590. yield return new object []
  591. {
  592. new Color (125, 125, 125),
  593. "R:", 9, 125, "G:", 9, 125, "B:", 9, 125, "#7D7D7D"
  594. };
  595. }
  596. private ColorBar GetColorBar (ColorPicker cp, ColorPickerPart toGet)
  597. {
  598. if (toGet <= ColorPickerPart.Bar3)
  599. {
  600. return cp.SubViews.OfType<ColorBar> ().ElementAt ((int)toGet);
  601. }
  602. throw new NotSupportedException ("ColorPickerPart must be a bar");
  603. }
  604. private ColorPicker GetColorPicker (ColorModel colorModel, bool showTextFields, bool showName = false)
  605. {
  606. var cp = new ColorPicker { Width = 20, SelectedColor = new (0, 0) };
  607. cp.Style.ColorModel = colorModel;
  608. cp.Style.ShowTextFields = showTextFields;
  609. cp.Style.ShowColorName = showName;
  610. cp.ApplyStyleChanges ();
  611. Application.Running = new () { Width = 20, Height = 5 };
  612. Application.Running.Add (cp);
  613. Application.Running.LayoutSubViews ();
  614. Application.Running.SetFocus ();
  615. return cp;
  616. }
  617. private TextField GetTextField (ColorPicker cp, ColorPickerPart toGet)
  618. {
  619. bool hasBarValueTextFields = cp.Style.ShowTextFields;
  620. bool hasColorNameTextField = cp.Style.ShowColorName;
  621. switch (toGet)
  622. {
  623. case ColorPickerPart.Bar1:
  624. case ColorPickerPart.Bar2:
  625. case ColorPickerPart.Bar3:
  626. if (!hasBarValueTextFields)
  627. {
  628. throw new NotSupportedException ("Corresponding Style option is not enabled");
  629. }
  630. return cp.SubViews.OfType<TextField> ().ElementAt ((int)toGet);
  631. case ColorPickerPart.ColorName:
  632. if (!hasColorNameTextField)
  633. {
  634. throw new NotSupportedException ("Corresponding Style option is not enabled");
  635. }
  636. return cp.SubViews.OfType<TextField> ().ElementAt (hasBarValueTextFields ? (int)toGet : (int)toGet - 3);
  637. case ColorPickerPart.Hex:
  638. int offset = hasBarValueTextFields ? 0 : 3;
  639. offset += hasColorNameTextField ? 0 : 1;
  640. return cp.SubViews.OfType<TextField> ().ElementAt ((int)toGet - offset);
  641. default:
  642. throw new ArgumentOutOfRangeException (nameof (toGet), toGet, null);
  643. }
  644. }
  645. private enum ColorPickerPart
  646. {
  647. Bar1 = 0,
  648. Bar2 = 1,
  649. Bar3 = 2,
  650. ColorName = 3,
  651. Hex = 4
  652. }
  653. }