LinearGradient.swift 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /// A linear gradient.
  2. public struct LinearGradient: ElementaryView {
  3. /// The gradient represented as an array of color stops, each having a parametric location value.
  4. public let gradient: Gradient
  5. /// The normalized point where the gradient begins, defined in the view's coordinate space.
  6. ///
  7. /// Use values like `.top`, `.leading`, or custom `UnitPoint(x:y:)` offsets.
  8. public let startPoint: UnitPoint
  9. /// The normalized point where the gradient ends, defined in the views coordinate space.
  10. ///
  11. /// The color interpolation moves linearly from the start point to this point.
  12. public let endPoint: UnitPoint
  13. private static let idealSize = ViewSize(10, 10)
  14. /// Creates a linear gradient from a base gradient.
  15. public init(
  16. gradient: Gradient,
  17. startPoint: UnitPoint,
  18. endPoint: UnitPoint
  19. ) {
  20. self.gradient = gradient
  21. self.startPoint = startPoint
  22. self.endPoint = endPoint
  23. }
  24. func asWidget<Backend: BaseAppBackend>(
  25. backend: Backend
  26. ) -> Backend.Widget {
  27. func castBackend_inner<NewBackend: BaseAppBackend & BackendFeatures.LinearGradients>(_ backend: NewBackend) -> NewBackend.Widget {
  28. return backend.createLinearGradientWidget()
  29. }
  30. guard let castedBackend = backend as? any (BaseAppBackend & BackendFeatures.LinearGradients) else {
  31. fatalError("Backend does not implement BackendFeatures.LinearGradients")
  32. }
  33. return castBackend_inner(castedBackend) as! Backend.Widget
  34. }
  35. public func computeLayout<Backend: BaseAppBackend>(
  36. _ widget: Backend.Widget,
  37. proposedSize: ProposedViewSize,
  38. environment: EnvironmentValues,
  39. backend: Backend
  40. ) -> ViewLayoutResult {
  41. ViewLayoutResult.leafView(
  42. size: proposedSize.replacingUnspecifiedDimensions(by: Self.idealSize)
  43. )
  44. }
  45. func commit<Backend: BaseAppBackend>(
  46. _ widget: Backend.Widget,
  47. layout: ViewLayoutResult,
  48. environment: EnvironmentValues,
  49. backend: Backend
  50. ) {
  51. func castBackend_inner<NewBackend: BaseAppBackend & BackendFeatures.LinearGradients>(_ backend: NewBackend) {
  52. let widget = widget as! NewBackend.Widget
  53. backend.setSize(of: widget, to: layout.size.vector)
  54. backend.updateLinearGradientWidget(
  55. widget,
  56. gradient: self,
  57. withSize: layout.size.vector,
  58. in: environment
  59. )
  60. }
  61. guard let castedBackend = backend as? any (BaseAppBackend & BackendFeatures.LinearGradients) else {
  62. fatalError("Backend does not implement BackendFeatures.LinearGradients")
  63. }
  64. castBackend_inner(castedBackend)
  65. }
  66. }
  67. extension LinearGradient {
  68. /// Creates a linear gradient from a collection of colors.
  69. public init(
  70. stops: [Gradient.Stop],
  71. startPoint: UnitPoint,
  72. endPoint: UnitPoint
  73. ) {
  74. self.init(
  75. gradient: Gradient(stops: stops),
  76. startPoint: startPoint,
  77. endPoint: endPoint
  78. )
  79. }
  80. /// Creates a linear gradient from a collection of color stops.
  81. public init(
  82. colors: [Color],
  83. startPoint: UnitPoint,
  84. endPoint: UnitPoint
  85. ) {
  86. self.init(
  87. gradient: Gradient(colors: colors),
  88. startPoint: startPoint,
  89. endPoint: endPoint
  90. )
  91. }
  92. }