HStack.swift 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /// A view that arranges its subviews horizontally.
  2. public struct HStack<Content: View>: View {
  3. public var body: Content
  4. /// The amount of spacing to apply between children.
  5. private var spacing: Int
  6. /// The alignment of the stack's children in the vertical direction.
  7. private var alignment: VerticalAlignment
  8. /// Creates a horizontal stack with the given spacing and alignment.
  9. ///
  10. /// - Parameters:
  11. /// - alignment: The alignment of the stack's children in the vertical
  12. /// direction.
  13. /// - spacing: The amount of spacing to apply between children.
  14. /// - content: The content of the stack.
  15. public init(
  16. alignment: VerticalAlignment = .center,
  17. spacing: Int? = nil,
  18. @ViewBuilder _ content: () -> Content
  19. ) {
  20. body = content()
  21. self.spacing = spacing ?? VStack<EmptyView>.defaultSpacing
  22. self.alignment = alignment
  23. }
  24. public func asWidget<Backend: BaseAppBackend>(
  25. _ children: any ViewGraphNodeChildren,
  26. backend: Backend
  27. ) -> Backend.Widget {
  28. let hStack = backend.createContainer()
  29. for (index, child) in children.widgets(for: backend).enumerated() {
  30. backend.insert(child, into: hStack, at: index)
  31. }
  32. return hStack
  33. }
  34. public func computeLayout<Backend: BaseAppBackend>(
  35. _ widget: Backend.Widget,
  36. children: any ViewGraphNodeChildren,
  37. proposedSize: ProposedViewSize,
  38. environment: EnvironmentValues,
  39. backend: Backend
  40. ) -> ViewLayoutResult {
  41. if !(children is TupleViewChildren || children is EmptyViewChildren) {
  42. logger.warning(
  43. "HStack will not function correctly with non-TupleView content",
  44. metadata: ["childrenType": "\(type(of: children))"]
  45. )
  46. }
  47. var cache = (children as? TupleViewChildren)?.stackLayoutCache ?? StackLayoutCache.initial
  48. let result = LayoutSystem.computeStackLayout(
  49. container: widget,
  50. children: layoutableChildren(backend: backend, children: children),
  51. cache: &cache,
  52. proposedSize: proposedSize,
  53. environment: environment
  54. .with(\.layoutOrientation, .horizontal)
  55. .with(\.layoutAlignment, alignment.asStackAlignment)
  56. .with(\.layoutSpacing, spacing),
  57. backend: backend
  58. )
  59. (children as? TupleViewChildren)?.stackLayoutCache = cache
  60. return result
  61. }
  62. public func commit<Backend: BaseAppBackend>(
  63. _ widget: Backend.Widget,
  64. children: any ViewGraphNodeChildren,
  65. layout: ViewLayoutResult,
  66. environment: EnvironmentValues,
  67. backend: Backend
  68. ) {
  69. var cache = (children as? TupleViewChildren)?.stackLayoutCache ?? StackLayoutCache.initial
  70. LayoutSystem.commitStackLayout(
  71. container: widget,
  72. children: layoutableChildren(backend: backend, children: children),
  73. cache: &cache,
  74. layout: layout,
  75. environment: environment
  76. .with(\.layoutOrientation, .horizontal)
  77. .with(\.layoutAlignment, alignment.asStackAlignment)
  78. .with(\.layoutSpacing, spacing),
  79. backend: backend
  80. )
  81. (children as? TupleViewChildren)?.stackLayoutCache = cache
  82. }
  83. }