ColorPickerTests.cs 28 KB

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