Added public/open modifiers, moved example code

This commit is contained in:
Max Desiatov 2018-10-08 14:31:54 +01:00
parent 0baf0c32ea
commit c2d1929e37
No known key found for this signature in database
GPG Key ID: FE08EBF9CF58CBA2
4 changed files with 103 additions and 86 deletions

View File

@ -7,18 +7,61 @@
//
import UIKit
import Gluon
class ViewController: UIViewController {
final class Counter: Component<NoProps, Counter.State> {
struct State: StateType {
var counter = 0
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
func onPress() {
setState { $0.counter += 1 }
}
lazy var onPressHandler = { Unique { self.onPress() } }()
func render() -> Node {
return View.node {
[Button.node(.init(onPress: onPressHandler)) { "Press me" },
Label.node { Node("\(state.counter)") }]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
render(node: Counter.node(), container: view)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
final class ClassicViewController: UIViewController {
private let button = UIButton()
private let label = UILabel()
private var counter = 0
@objc func onPress() {
counter += 1
label.text = "\(counter)"
}
override func viewDidLoad() {
super.viewDidLoad()
label.text = "\(counter)"
button.addTarget(self, action: #selector(onPress), for: .touchUpInside)
view.addSubview(button)
view.addSubview(label)
}
}

View File

@ -7,125 +7,142 @@
import Foundation
protocol Default {
public protocol Default {
init()
}
struct Unique<T>: Equatable {
public struct Unique<T>: Equatable {
private let uuid = UUID()
private let boxed: T
init(_ boxed: T) {
public init(_ boxed: T) {
self.boxed = boxed
}
static func == (lhs: Unique<T>, rhs: Unique<T>) -> Bool {
public static func == (lhs: Unique<T>, rhs: Unique<T>) -> Bool {
return lhs.uuid == rhs.uuid
}
}
struct NoProps: Equatable, Default {
public struct NoProps: Equatable, Default {
public init() {}
}
private protocol ComponentType {
protocol ComponentType {
}
extension String: ComponentType {
}
class BaseComponent<Props: Equatable>: ComponentType {
open class BaseComponent<Props: Equatable>: ComponentType {
private(set) var props: Props
private(set) var children: [Node]
required init(props: Props, children: [Node]) {
public required init(props: Props, children: [Node]) {
self.props = props
self.children = children
}
static func node(_ props: Props, childrenFactory: () -> [Node]) -> Node {
public static func node(_ props: Props, childrenFactory: () -> [Node]) -> Node {
let children = childrenFactory()
return Node {
self.init(props: props, children: children)
}
}
static func node(_ props: Props, childFactory: () -> Node) -> Node {
public static func node(_ props: Props, childFactory: () -> Node) -> Node {
// applying `childFactory` here to avoid `@escaping` attribute
let child = childFactory()
return Node { self.init(props: props, children: [child]) }
}
static func node(_ props: Props) -> Node {
public static func node(_ props: Props) -> Node {
return Node { self.init(props: props, children: []) }
}
}
extension BaseComponent where Props: Default {
static func node(childrenFactory: () -> [Node]) -> Node {
public static func node(childrenFactory: () -> [Node]) -> Node {
return self.node(Props(), childrenFactory: childrenFactory)
}
static func node(childFactory: () -> Node) -> Node {
public static func node(childFactory: () -> Node) -> Node {
return self.node(Props(), childFactory: childFactory)
}
static func node() -> Node {
public static func node() -> Node {
return Node { self.init(props: Props(), children: []) }
}
}
struct Node {
public struct Node {
fileprivate let factory: () -> ComponentType
}
extension Node: ExpressibleByStringLiteral {
init(stringLiteral: String) {
public init(stringLiteral: String) {
factory = { stringLiteral }
}
}
extension Node {
init(_ string: String) {
public init(_ string: String) {
factory = { string }
}
}
class View: BaseComponent<NoProps> {
public final class View: BaseComponent<NoProps> {
}
class Label: BaseComponent<Label.Props> {
struct Props: Equatable, Default {
let fontColor = UIColor.black
public final class Label: BaseComponent<Label.Props> {
public struct Props: Equatable, Default {
let fontColor: UIColor
public init() {
fontColor = .black
}
public init(fontColor: UIColor) {
self.fontColor = fontColor
}
}
}
class Button: BaseComponent<Button.Props> {
struct Props: Equatable {
let backgroundColor = UIColor.white
let fontColor = UIColor.black
public final class Button: BaseComponent<Button.Props> {
public struct Props: Equatable {
let backgroundColor: UIColor
let fontColor: UIColor
let onPress: Unique<() -> ()>
public init(backgroundColor: UIColor = .white, fontColor: UIColor = .black,
onPress: Unique<() -> ()>) {
self.backgroundColor = backgroundColor
self.fontColor = fontColor
self.onPress = onPress
}
}
}
protocol CompositeComponent {
public protocol CompositeComponent {
func render() -> Node
}
protocol StateType: Default & Equatable {
public protocol StateType: Default & Equatable {
}
class StatefulComponent<Props: Equatable, State: StateType>: BaseComponent<Props> {
private(set) var state: State
open class StatefulComponent<Props: Equatable, State: StateType>:
BaseComponent<Props> {
public private(set) var state: State
required init(props: Props, children: [Node]) {
public required init(props: Props, children: [Node]) {
state = State()
super.init(props: props, children: children)
}
func setState(setter: (inout State) -> ()) {
public func setState(setter: (inout State) -> ()) {
}
}
typealias Component<P: Equatable, S: StateType> =
public typealias Component<P: Equatable, S: StateType> =
StatefulComponent<P, S> & CompositeComponent

View File

@ -8,46 +8,3 @@
import UIKit
final class Counter: Component<NoProps, Counter.State> {
struct State: StateType {
var counter = 0
}
func onPress() {
setState { $0.counter += 1 }
}
lazy var onPressHandler = { Unique { self.onPress() } }()
func render() -> Node {
return View.node {
[Button.node(.init(onPress: onPressHandler)) { "Press me" },
Label.node { Node("\(state.counter)") }]
}
}
}
final class ViewController: UIViewController {
private let button = UIButton()
private let label = UILabel()
private var counter = 0
@objc func onPress() {
counter += 1
label.text = "\(counter)"
}
override func viewDidLoad() {
super.viewDidLoad()
label.text = "\(counter)"
button.addTarget(self, action: #selector(onPress), for: .touchUpInside)
view.addSubview(button)
view.addSubview(label)
}
}
// render(node: Test.node(), container: UIView())

View File

@ -7,5 +7,5 @@
import Foundation
func render(node: Node, container: UIView) {
public func render(node: Node, container: UIView) {
}