diff --git a/Demo/Sources/Demos/DemosRootViewController.swift b/Demo/Sources/Demos/DemosRootViewController.swift index 03d4474aa..fb5101160 100644 --- a/Demo/Sources/Demos/DemosRootViewController.swift +++ b/Demo/Sources/Demos/DemosRootViewController.swift @@ -218,12 +218,12 @@ public final class DemosRootViewController : ListViewController section += Item( DemoItem(text: "Tappable Row"), - selectionStyle: .selectable() + selectionStyle: .tappable ) section += Item( DemoItem(text: "Tappable Row (Slow Is Selected)"), - selectionStyle: .selectable(), + selectionStyle: .tappable, onSelect: { _ in Thread.sleep(forTimeInterval: 0.5) } diff --git a/ListableUI/Sources/HeaderFooter/HeaderFooter.swift b/ListableUI/Sources/HeaderFooter/HeaderFooter.swift index d82ad777d..a99270c51 100644 --- a/ListableUI/Sources/HeaderFooter/HeaderFooter.swift +++ b/ListableUI/Sources/HeaderFooter/HeaderFooter.swift @@ -104,56 +104,3 @@ extension HeaderFooter : SignpostLoggable ) } } - - -/// -/// `HeaderFooterLayout` allows you to provide `ListLayout`-specific layout configuration for -/// individual headers and footers within a list. Eg, customize the layout for a list, a grid, etc. -/// -/// For example, if you want to specify a custom layout for list layouts, you -/// would do the following on your header: -/// ``` -/// myHeader.layouts.list = .init( -/// width: .fill -/// ) -/// ``` -/// And then, when the `HeaderFooter` is used within a `.list` style -/// list layout, the provided `HeaderFooter` layout will be used. -/// -/// If you plan on swapping the `ListLayout` type on your list, -/// you can provide multiple layouts. The correct one will be used: -/// -/// ``` -/// myHeader.layouts.list = .init( -/// width: .fill -/// ) -/// -/// myHeader.layouts.otherLayout = .init( -/// width: 300, -/// alignment: .left -/// padding: 10 -/// ) -/// ``` -public struct HeaderFooterLayouts { - - public init( - _ configure : (inout Self) -> () = { _ in } - ) { - self.storage = .init() - - configure(&self) - } - - private var storage : ContentLayoutsStorage - - public subscript(_ valueType : ValueType.Type) -> ValueType { - get { self.storage.get(valueType, default: ValueType.defaultValue) } - set { self.storage.set(valueType, new: newValue) } - } -} - - -public protocol HeaderFooterLayoutsValue { - - static var defaultValue : Self { get } -} diff --git a/ListableUI/Sources/HeaderFooter/HeaderFooterLayouts.swift b/ListableUI/Sources/HeaderFooter/HeaderFooterLayouts.swift new file mode 100644 index 000000000..f7eead975 --- /dev/null +++ b/ListableUI/Sources/HeaderFooter/HeaderFooterLayouts.swift @@ -0,0 +1,114 @@ +// +// HeaderFooterLayouts.swift +// ListableUI +// +// Created by Kyle Van Essen on 1/22/21. +// + +import Foundation + + +/// +/// `HeaderFooterLayouts` allows you to provide `ListLayout`-specific layout configuration for +/// individual headers and footers within a list. Eg, customize the layout for a header when it is in a table, a grid, etc. +/// +/// For example, if you want to specify a custom layout for table layouts, you +/// would do the following on your header: +/// +/// ``` +/// myHeader.layouts.table = .init( +/// width: .fill +/// ) +/// ``` +/// +/// And then, when the `HeaderFooter` is used within a `.table` style +/// list layout, the provided layout will be used. +/// +/// If you plan on swapping between multiple `ListLayout` types on your list, +/// you can provide multiple layouts. The correct one will be used at the correct time: +/// +/// ``` +/// myHeader.layouts.table = .init( +/// width: .fill +/// ) +/// +/// myHeader.layouts.otherLayout = .init( +/// width: 300, +/// alignment: .left +/// padding: 10 +/// ) +/// ``` +/// +/// Note +/// ---- +/// When implementing your own custom layout, you should add an extension to `HeaderFooterLayouts`, +/// to provide easier access to your layout-specific `HeaderFooterLayoutsValue` type, like so: +/// +/// ``` +/// extension HeaderFooterLayouts { +/// public var table : TableAppearance.HeaderFooter.Layout { +/// get { self[TableAppearance.HeaderFooter.Layout.self] } +/// set { self[TableAppearance.HeaderFooter.Layout.self] = newValue } +/// } +/// } +/// ``` +public struct HeaderFooterLayouts { + + /// Creates a new instance of the layouts, with an optional `configure` + /// closure, to allow you to set up styling inline. + public init( + _ configure : (inout Self) -> () = { _ in } + ) { + self.storage = .init() + + configure(&self) + } + + private var storage : ContentLayoutsStorage + + /// Allows accessing the various `HeaderFooterLayoutValue`s stored within the object. + /// This method will return the `defaultValue` for a value if none is set. + /// + /// Note + /// ---- + /// When implementing your own custom layout, you should add an extension to `HeaderFooterLayouts`, + /// to provide easier access to your layout-specific `HeaderFooterLayoutsValue` type. + /// + /// ``` + /// extension HeaderFooterLayouts { + /// public var table : TableAppearance.HeaderFooter.Layout { + /// get { self[TableAppearance.HeaderFooter.Layout.self] } + /// set { self[TableAppearance.HeaderFooter.Layout.self] = newValue } + /// } + /// } + /// ``` + public subscript(_ valueType : ValueType.Type) -> ValueType { + get { self.storage.get(valueType, default: ValueType.defaultValue) } + set { self.storage.set(valueType, new: newValue) } + } +} + + +/// +/// The `HeaderFooterLayoutsValue` protocol provides a default value for the different layouts stored +/// within `HeaderFooterLayouts`. Provide a `defaultValue` with reasonable defaults, as the +/// developer should not need to set these values at all times when using your layout. +/// +/// ``` +/// public struct Layout : Equatable, HeaderFooterLayoutsValue +/// { +/// public var width : CGFloat +/// public var minHeight : CGFloat +/// +/// ... +/// +/// public static var defaultValue : Self { +/// ... +/// } +/// } +/// ``` +public protocol HeaderFooterLayoutsValue { + + /// The default value used when accessing the value, if none is set. + static var defaultValue : Self { get } +} diff --git a/ListableUI/Sources/Item/Item.swift b/ListableUI/Sources/Item/Item.swift index 055931069..348b8e67e 100644 --- a/ListableUI/Sources/Item/Item.swift +++ b/ListableUI/Sources/Item/Item.swift @@ -181,28 +181,3 @@ extension Item : SignpostLoggable ) } } - - -public struct ItemLayouts { - - public init( - _ configure : (inout Self) -> () = { _ in } - ) { - self.storage = .init() - - configure(&self) - } - - private var storage : ContentLayoutsStorage - - public subscript(_ valueType : ValueType.Type) -> ValueType { - get { self.storage.get(valueType, default: ValueType.defaultValue) } - set { self.storage.set(valueType, new: newValue) } - } -} - - -public protocol ItemLayoutsValue { - - static var defaultValue : Self { get } -} diff --git a/ListableUI/Sources/Item/Item+Callbacks.swift b/ListableUI/Sources/Item/ItemCallbacks.swift similarity index 100% rename from ListableUI/Sources/Item/Item+Callbacks.swift rename to ListableUI/Sources/Item/ItemCallbacks.swift diff --git a/ListableUI/Sources/Item/ItemLayouts.swift b/ListableUI/Sources/Item/ItemLayouts.swift new file mode 100644 index 000000000..7681582d1 --- /dev/null +++ b/ListableUI/Sources/Item/ItemLayouts.swift @@ -0,0 +1,113 @@ +// +// ItemLayouts.swift +// ListableUI +// +// Created by Kyle Van Essen on 1/22/21. +// + +import Foundation + + +/// +/// `ItemLayouts` allows you to provide `ListLayout`-specific layout configuration for +/// individual items within a list. Eg, customize the layout for an item when it is in a table, a grid, etc. +/// +/// For example, if you want to specify a custom layout for table layouts, you +/// would do the following on your item: +/// +/// ``` +/// myItem.layouts.table = .init( +/// width: .fill +/// ) +/// ``` +/// +/// And then, when the `Item` is used within a `.table` style +/// list layout, the provided layout will be used. +/// +/// If you plan on swapping between multiple `ListLayout` types on your list, +/// you can provide multiple layouts. The correct one will be used at the correct time: +/// +/// ``` +/// myItem.layouts.table = .init( +/// width: .fill +/// ) +/// +/// myItem.layouts.otherLayout = .init( +/// width: 300, +/// alignment: .left +/// ) +/// ``` +/// +/// Note +/// ---- +/// When implementing your own custom layout, you should add an extension to `ItemLayouts`, +/// to provide easier access to your layout-specific `ItemLayoutsValue` type, like so: +/// +/// ``` +/// extension ItemLayoutsValue { +/// public var table : TableAppearance.Item.Layout { +/// get { self[TableAppearance.Item.Layout.self] } +/// set { self[TableAppearance.Item.Layout.self] = newValue } +/// } +/// } +/// ``` +public struct ItemLayouts { + + /// Creates a new instance of the layouts, with an optional `configure` + /// closure, to allow you to set up styling inline. + public init( + _ configure : (inout Self) -> () = { _ in } + ) { + self.storage = .init() + + configure(&self) + } + + private var storage : ContentLayoutsStorage + + /// Allows accessing the various `ItemLayoutsValue`s stored within the object. + /// This method will return the `defaultValue` for a value if none is set. + /// + /// Note + /// ---- + /// When implementing your own custom layout, you should add an extension to `ItemLayouts`, + /// to provide easier access to your layout-specific `ItemLayoutsValue` type. + /// + /// ``` + /// extension ItemLayoutsValue { + /// public var table : TableAppearance.Item.Layout { + /// get { self[TableAppearance.Item.Layout.self] } + /// set { self[TableAppearance.Item.Layout.self] = newValue } + /// } + /// } + /// ``` + public subscript(_ valueType : ValueType.Type) -> ValueType { + get { self.storage.get(valueType, default: ValueType.defaultValue) } + set { self.storage.set(valueType, new: newValue) } + } +} + + +/// +/// The `ItemLayoutsValue` protocol provides a default value for the different layouts stored +/// within `ItemLayouts`. Provide a `defaultValue` with reasonable defaults, as the +/// developer should not need to set these values at all times when using your layout. +/// +/// ``` +/// public struct Layout : Equatable, ItemLayoutsValue +/// { +/// public var width : CGFloat +/// public var minHeight : CGFloat +/// +/// ... +/// +/// public static var defaultValue : Self { +/// ... +/// } +/// } +/// ``` +public protocol ItemLayoutsValue { + + /// The default value used when accessing the value, if none is set. + static var defaultValue : Self { get } +} diff --git a/ListableUI/Sources/Section/Section.swift b/ListableUI/Sources/Section/Section.swift index 48084c97d..e7c6e56a3 100644 --- a/ListableUI/Sources/Section/Section.swift +++ b/ListableUI/Sources/Section/Section.swift @@ -231,28 +231,3 @@ private struct HashableSectionInfo : SectionInfo return self.value != other.value } } - - -public struct SectionLayouts { - - public init( - _ configure : (inout Self) -> () = { _ in } - ) { - self.storage = .init() - - configure(&self) - } - - private var storage : ContentLayoutsStorage - - public subscript(_ valueType : ValueType.Type) -> ValueType { - get { self.storage.get(valueType, default: ValueType.defaultValue) } - set { self.storage.set(valueType, new: newValue) } - } -} - - -public protocol SectionLayoutsValue { - - static var defaultValue : Self { get } -} diff --git a/ListableUI/Sources/Section/SectionLayouts.swift b/ListableUI/Sources/Section/SectionLayouts.swift new file mode 100644 index 000000000..ee5868047 --- /dev/null +++ b/ListableUI/Sources/Section/SectionLayouts.swift @@ -0,0 +1,113 @@ +// +// SectionLayouts.swift +// ListableUI +// +// Created by Kyle Van Essen on 1/22/21. +// + +import Foundation + + +/// +/// `SectionLayouts` allows you to provide `ListLayout`-specific layout configuration for +/// individual sections within a list. Eg, customize the layout for a section when it is in a table, a grid, etc. +/// +/// For example, if you want to specify a custom layout for table layouts, you +/// would do the following on your section: +/// +/// ``` +/// mySection.layouts.table = .init( +/// width: .fill +/// ) +/// ``` +/// +/// And then, when the `Section` is used within a `.table` style +/// list layout, the provided layout will be used. +/// +/// If you plan on swapping between multiple `ListLayout` types on your list, +/// you can provide multiple layouts. The correct one will be used at the correct time: +/// +/// ``` +/// mySection.layouts.table = .init( +/// width: .fill +/// ) +/// +/// mySection.layouts.otherLayout = .init( +/// width: 300, +/// alignment: .left +/// ) +/// ``` +/// +/// Note +/// ---- +/// When implementing your own custom layout, you should add an extension to `SectionLayouts`, +/// to provide easier access to your layout-specific `SectionLayoutsValue` type, like so: +/// +/// ``` +/// extension SectionLayouts { +/// public var table : TableAppearance.Section.Layout { +/// get { self[TableAppearance.Section.Layout.self] } +/// set { self[TableAppearance.Section.Layout.self] = newValue } +/// } +/// } +/// ``` +public struct SectionLayouts { + + /// Creates a new instance of the layouts, with an optional `configure` + /// closure, to allow you to set up styling inline. + public init( + _ configure : (inout Self) -> () = { _ in } + ) { + self.storage = .init() + + configure(&self) + } + + private var storage : ContentLayoutsStorage + + /// Allows accessing the various `SectionLayoutsValue`s stored within the object. + /// This method will return the `defaultValue` for a value if none is set. + /// + /// Note + /// ---- + /// When implementing your own custom layout, you should add an extension to `SectionLayouts`, + /// to provide easier access to your layout-specific `SectionLayoutsValue` type. + /// + /// ``` + /// extension SectionLayouts { + /// public var table : TableAppearance.Section.Layout { + /// get { self[TableAppearance.Section.Layout.self] } + /// set { self[TableAppearance.Section.Layout.self] = newValue } + /// } + /// } + /// ``` + public subscript(_ valueType : ValueType.Type) -> ValueType { + get { self.storage.get(valueType, default: ValueType.defaultValue) } + set { self.storage.set(valueType, new: newValue) } + } +} + + +/// +/// The `SectionLayoutsValue` protocol provides a default value for the different layouts stored +/// within `SectionLayouts`. Provide a `defaultValue` with reasonable defaults, as the +/// developer should not need to set these values at all times when using your layout. +/// +/// ``` +/// public struct Layout : Equatable, SectionLayoutsValue +/// { +/// public var width : CGFloat +/// public var minHeight : CGFloat +/// +/// ... +/// +/// public static var defaultValue : Self { +/// ... +/// } +/// } +/// ``` +public protocol SectionLayoutsValue { + + /// The default value used when accessing the value, if none is set. + static var defaultValue : Self { get } +}