View.Drawing.Attribute.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #nullable enable
  2. using System.ComponentModel;
  3. namespace Terminal.Gui.ViewBase;
  4. public partial class View
  5. {
  6. #region Get
  7. /// <summary>Gets the current <see cref="System.Attribute"/> used by <see cref="AddRune(System.Text.Rune)"/>.</summary>
  8. /// <returns>The current attribute.</returns>
  9. public Attribute GetCurrentAttribute () { return Driver?.GetAttribute () ?? Attribute.Default; }
  10. /// <summary>
  11. /// Gets the <see cref="Attribute"/> associated with a specified <see cref="VisualRole"/>
  12. /// from the <see cref="Scheme"/>.
  13. /// <para>
  14. /// Raises <see cref="OnGettingAttributeForRole"/>/<see cref="GettingAttributeForRole"/>
  15. /// which can cancel the default behavior, and optionally change the attribute in the event args.
  16. /// </para>
  17. /// <para>
  18. /// If <see cref="Enabled"/> is <see langword="false"/>, <see cref="VisualRole.Disabled"/>
  19. /// will be used instead of <paramref name="role"></paramref>.
  20. /// To override this behavior use <see cref="OnGettingAttributeForRole"/>/<see cref="GettingAttributeForRole"/>
  21. /// to cancel the method, and return a different attribute.
  22. /// </para>
  23. /// <para>
  24. /// If <see cref="HighlightStates"/> is not <see cref="MouseState.None"/> and <see cref="MouseState"/> is <see cref="MouseState.In"/>
  25. /// the <see cref="VisualRole.Highlight"/> will be used instead of <paramref name="role"/>.
  26. /// To override this behavior use <see cref="OnGettingAttributeForRole"/>/<see cref="GettingAttributeForRole"/>
  27. /// to cancel the method, and return a different attribute.
  28. /// </para>
  29. /// </summary>
  30. /// <param name="role">The semantic <see cref="Drawing.VisualRole"/> describing the element being rendered.</param>
  31. /// <returns>The corresponding <see cref="Attribute"/> from the <see cref="Drawing.Scheme"/>.</returns>
  32. public Attribute GetAttributeForRole (VisualRole role)
  33. {
  34. Attribute schemeAttribute = GetScheme ()!.GetAttributeForRole (role);
  35. if (OnGettingAttributeForRole (role, ref schemeAttribute))
  36. {
  37. // The implementation may have changed the attribute
  38. return schemeAttribute;
  39. }
  40. VisualRoleEventArgs args = new (role, result: schemeAttribute);
  41. GettingAttributeForRole?.Invoke (this, args);
  42. if (args is { Handled: true, Result: { } })
  43. {
  44. // A handler may have changed the attribute
  45. return args.Result.Value;
  46. }
  47. if (role != VisualRole.Disabled && HighlightStates != MouseState.None)
  48. {
  49. // The default behavior for HighlightStates of MouseState.Over is to use the Highlight role
  50. if (((HighlightStates.HasFlag (MouseState.In) && MouseState.HasFlag (MouseState.In))
  51. || (HighlightStates.HasFlag (MouseState.Pressed) && MouseState.HasFlag (MouseState.Pressed)))
  52. && role != VisualRole.Highlight && !HasFocus)
  53. {
  54. schemeAttribute = GetAttributeForRole (VisualRole.Highlight);
  55. }
  56. }
  57. return Enabled || role == VisualRole.Disabled ? schemeAttribute : GetAttributeForRole (VisualRole.Disabled);
  58. }
  59. /// <summary>
  60. /// Called when the Attribute for a <see cref="GetAttributeForRole(VisualRole)"/> is being retrieved.
  61. /// Implementations can
  62. /// return <see langword="true"/> to stop further processing and optionally set the <see cref="Attribute"/> in the
  63. /// event args to a different value.
  64. /// </summary>
  65. /// <param name="role"></param>
  66. /// <param name="currentAttribute">The current value of the Attribute for the VisualRole. This by-ref value can be changed</param>
  67. /// <returns></returns>
  68. protected virtual bool OnGettingAttributeForRole (in VisualRole role, ref Attribute currentAttribute) { return false; }
  69. /// <summary>
  70. /// Raised when the Attribute for a <see cref="GetAttributeForRole(VisualRole)"/> is being retrieved.
  71. /// Handlers should check if <see cref="CancelEventArgs.Cancel"/>
  72. /// has been set to <see langword="true"/> and do nothing if so. If Cancel is <see langword="false"/>
  73. /// a handler can set it to <see langword="true"/> to stop further processing optionally change the
  74. /// `CurrentValue` in the event args to a different value.
  75. /// </summary>
  76. public event EventHandler<VisualRoleEventArgs>? GettingAttributeForRole;
  77. #endregion Get
  78. #region Set
  79. /// <summary>
  80. /// Selects the specified Attribute
  81. /// as the Attribute to use for subsequent calls to <see cref="AddRune(System.Text.Rune)"/> and <see cref="AddStr"/>.
  82. /// </summary>
  83. /// <param name="attribute">THe Attribute to set.</param>
  84. /// <returns>The previously set Attribute.</returns>
  85. public Attribute SetAttribute (Attribute attribute) { return Driver?.SetAttribute (attribute) ?? Attribute.Default; }
  86. /// <summary>
  87. /// Selects the Attribute associated with the specified <see cref="VisualRole"/>
  88. /// as the Attribute to use for subsequent calls to <see cref="AddRune(System.Text.Rune)"/> and <see cref="AddStr"/>.
  89. /// <para>
  90. /// Calls <see cref="GetAttributeForRole"/> to get the Attribute associated with the specified role, which will
  91. /// raise <see cref="OnGettingAttributeForRole"/>/<see cref="GettingAttributeForRole"/>.
  92. /// </para>
  93. /// </summary>
  94. /// <param name="role">The semantic <see cref="VisualRole"/> describing the element being rendered.</param>
  95. /// <returns>The previously set Attribute.</returns>
  96. public Attribute? SetAttributeForRole (VisualRole role)
  97. {
  98. Attribute schemeAttribute = GetAttributeForRole (role);
  99. Attribute currentAttribute = GetCurrentAttribute ();
  100. return SetAttribute (schemeAttribute);
  101. }
  102. #endregion Set
  103. }