View.ColorScheme.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #nullable enable
  2. using System.ComponentModel;
  3. namespace Terminal.Gui;
  4. public partial class View
  5. {
  6. // TODO: See https://github.com/gui-cs/Terminal.Gui/issues/4014
  7. // TODO: See https://github.com/gui-cs/Terminal.Gui/issues/4016
  8. // TODO: Enable ability to tell if ColorScheme was explicitly set; ColorScheme, as is, hides this.
  9. internal ColorScheme? _colorScheme;
  10. /// <summary>The color scheme for this view, if it is not defined, it returns the <see cref="SuperView"/>'s color scheme.</summary>
  11. public virtual ColorScheme? ColorScheme
  12. {
  13. // BUGBUG: This prevents the ability to know if ColorScheme was explicitly set or not.
  14. get => _colorScheme ?? SuperView?.ColorScheme;
  15. set
  16. {
  17. if (_colorScheme == value)
  18. {
  19. return;
  20. }
  21. _colorScheme = value;
  22. // BUGBUG: This should be in Border.cs somehow
  23. if (Border is { } && Border.LineStyle != LineStyle.None && Border.ColorScheme is { })
  24. {
  25. Border.ColorScheme = _colorScheme;
  26. }
  27. SetNeedsDraw ();
  28. }
  29. }
  30. /// <summary>Determines the current <see cref="ColorScheme"/> based on the <see cref="Enabled"/> value.</summary>
  31. /// <returns>
  32. /// <see cref="ColorScheme.Focus"/> if <see cref="Enabled"/> is <see langword="true"/> or
  33. /// <see cref="ColorScheme.Disabled"/> if <see cref="Enabled"/> is <see langword="false"/>. If it's
  34. /// overridden can return other values.
  35. /// </returns>
  36. public virtual Attribute GetFocusColor ()
  37. {
  38. Attribute currAttribute = ColorScheme?.Normal ?? Attribute.Default;
  39. var newAttribute = new Attribute ();
  40. CancelEventArgs<Attribute> args = new (in currAttribute, ref newAttribute);
  41. GettingFocusColor?.Invoke (this, args);
  42. if (args.Cancel)
  43. {
  44. return args.NewValue;
  45. }
  46. ColorScheme? cs = ColorScheme ?? new ();
  47. return Enabled ? GetColor (cs.Focus) : cs.Disabled;
  48. }
  49. /// <summary>
  50. /// Raised the Focus Color is being retrieved, from <see cref="GetFocusColor"/>. Cancel the event and set the new
  51. /// attribute in the event args to
  52. /// a different value to change the focus color.
  53. /// </summary>
  54. public event EventHandler<CancelEventArgs<Attribute>>? GettingFocusColor;
  55. /// <summary>Determines the current <see cref="ColorScheme"/> based on the <see cref="Enabled"/> value.</summary>
  56. /// <returns>
  57. /// <see cref="ColorScheme.Focus"/> if <see cref="Enabled"/> is <see langword="true"/> or
  58. /// <see cref="ColorScheme.Disabled"/> if <see cref="Enabled"/> is <see langword="false"/>. If it's
  59. /// overridden can return other values.
  60. /// </returns>
  61. public virtual Attribute GetHotFocusColor ()
  62. {
  63. Attribute currAttribute = ColorScheme?.Normal ?? Attribute.Default;
  64. var newAttribute = new Attribute ();
  65. CancelEventArgs<Attribute> args = new (in currAttribute, ref newAttribute);
  66. GettingHotFocusColor?.Invoke (this, args);
  67. if (args.Cancel)
  68. {
  69. return args.NewValue;
  70. }
  71. ColorScheme? cs = ColorScheme ?? new ();
  72. return Enabled ? GetColor (cs.HotFocus) : cs.Disabled;
  73. }
  74. /// <summary>
  75. /// Raised the HotFocus Color is being retrieved, from <see cref="GetHotFocusColor"/>. Cancel the event and set the new
  76. /// attribute in the event args to
  77. /// a different value to change the focus color.
  78. /// </summary>
  79. public event EventHandler<CancelEventArgs<Attribute>>? GettingHotFocusColor;
  80. /// <summary>Determines the current <see cref="ColorScheme"/> based on the <see cref="Enabled"/> value.</summary>
  81. /// <returns>
  82. /// <see cref="ColorScheme.HotNormal"/> if <see cref="Enabled"/> is <see langword="true"/> or
  83. /// <see cref="ColorScheme.Disabled"/> if <see cref="Enabled"/> is <see langword="false"/>. If it's
  84. /// overridden can return other values.
  85. /// </returns>
  86. public virtual Attribute GetHotNormalColor ()
  87. {
  88. Attribute currAttribute = ColorScheme?.Normal ?? Attribute.Default;
  89. var newAttribute = new Attribute ();
  90. CancelEventArgs<Attribute> args = new (in currAttribute, ref newAttribute);
  91. GettingHotNormalColor?.Invoke (this, args);
  92. if (args.Cancel)
  93. {
  94. return args.NewValue;
  95. }
  96. ColorScheme? cs = ColorScheme ?? new ();
  97. return Enabled ? GetColor (cs.HotNormal) : cs.Disabled;
  98. }
  99. /// <summary>
  100. /// Raised the HotNormal Color is being retrieved, from <see cref="GetHotNormalColor"/>. Cancel the event and set the
  101. /// new attribute in the event args to
  102. /// a different value to change the focus color.
  103. /// </summary>
  104. public event EventHandler<CancelEventArgs<Attribute>>? GettingHotNormalColor;
  105. /// <summary>Determines the current <see cref="ColorScheme"/> based on the <see cref="Enabled"/> value.</summary>
  106. /// <returns>
  107. /// <see cref="ColorScheme.Normal"/> if <see cref="Enabled"/> is <see langword="true"/> or
  108. /// <see cref="ColorScheme.Disabled"/> if <see cref="Enabled"/> is <see langword="false"/>. If it's
  109. /// overridden can return other values.
  110. /// </returns>
  111. public virtual Attribute GetNormalColor ()
  112. {
  113. Attribute currAttribute = ColorScheme?.Normal ?? Attribute.Default;
  114. var newAttribute = new Attribute ();
  115. CancelEventArgs<Attribute> args = new (in currAttribute, ref newAttribute);
  116. GettingNormalColor?.Invoke (this, args);
  117. if (args.Cancel)
  118. {
  119. return args.NewValue;
  120. }
  121. ColorScheme? cs = ColorScheme ?? new ();
  122. Attribute disabled = new (cs.Disabled.Foreground, cs.Disabled.Background);
  123. if (Diagnostics.HasFlag (ViewDiagnosticFlags.Hover) && _hovering)
  124. {
  125. disabled = new (disabled.Foreground.GetDarkerColor (), disabled.Background.GetDarkerColor ());
  126. }
  127. return Enabled ? GetColor (cs.Normal) : disabled;
  128. }
  129. /// <summary>
  130. /// Raised the Normal Color is being retrieved, from <see cref="GetNormalColor"/>. Cancel the event and set the new
  131. /// attribute in the event args to
  132. /// a different value to change the focus color.
  133. /// </summary>
  134. public event EventHandler<CancelEventArgs<Attribute>>? GettingNormalColor;
  135. /// <summary>
  136. /// Sets the Normal attribute if the setting process is not canceled. It triggers an event and checks for
  137. /// cancellation before proceeding.
  138. /// </summary>
  139. public void SetNormalAttribute ()
  140. {
  141. if (OnSettingNormalAttribute ())
  142. {
  143. return;
  144. }
  145. var args = new CancelEventArgs ();
  146. SettingNormalAttribute?.Invoke (this, args);
  147. if (args.Cancel)
  148. {
  149. return;
  150. }
  151. if (ColorScheme is { })
  152. {
  153. SetAttribute (GetNormalColor ());
  154. }
  155. }
  156. /// <summary>
  157. /// Called when the normal attribute for the View is to be set. This is called before the View is drawn.
  158. /// </summary>
  159. /// <returns><see langword="true"/> to stop default behavior.</returns>
  160. protected virtual bool OnSettingNormalAttribute () { return false; }
  161. /// <summary>Raised when the normal attribute for the View is to be set. This is raised before the View is drawn.</summary>
  162. /// <returns>
  163. /// Set <see cref="CancelEventArgs.Cancel"/> to <see langword="true"/> to stop default behavior.
  164. /// </returns>
  165. public event EventHandler<CancelEventArgs>? SettingNormalAttribute;
  166. private Attribute GetColor (Attribute inputAttribute)
  167. {
  168. Attribute attr = inputAttribute;
  169. if (Diagnostics.HasFlag (ViewDiagnosticFlags.Hover) && _hovering)
  170. {
  171. attr = new (attr.Foreground.GetDarkerColor (), attr.Background.GetDarkerColor ());
  172. }
  173. return attr;
  174. }
  175. }