2
0

View.Drawing.Attribute.cs 6.4 KB

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