Add Image component (#45)

* Init Image

* Fix RenderingMode, merge Tokamak renaming

* Add image props

* Add image example

* Format comment

* Switch image to implicit member expression
This commit is contained in:
matvii 2019-02-18 20:14:08 +02:00 committed by GitHub
parent 7f0373d8c1
commit cac728b7b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 188 additions and 4 deletions

View File

@ -12,6 +12,7 @@
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
A6D5AF87221B131400DBF186 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D5AF86221B131400DBF186 /* Image.swift */; };
C449B806DFEE55B6CEE6478C /* libPods-TokamakDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B96B435A9D67621D318616E /* libPods-TokamakDemo.a */; }; C449B806DFEE55B6CEE6478C /* libPods-TokamakDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B96B435A9D67621D318616E /* libPods-TokamakDemo.a */; };
D11DB6432219C03000013FC3 /* Timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D11DB6422219C03000013FC3 /* Timer.swift */; }; D11DB6432219C03000013FC3 /* Timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D11DB6422219C03000013FC3 /* Timer.swift */; };
D1BFAF772215795900845EA0 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BFAF762215795900845EA0 /* Router.swift */; }; D1BFAF772215795900845EA0 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BFAF762215795900845EA0 /* Router.swift */; };
@ -38,6 +39,7 @@
607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; }; 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8CADEBB8BFF6F2621CA49E8F /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; }; 8CADEBB8BFF6F2621CA49E8F /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
A6D5AF86221B131400DBF186 /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
A9EEF813955DAEEFE1D52ED4 /* Pods-TokamakDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TokamakDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TokamakDemo/Pods-TokamakDemo.debug.xcconfig"; sourceTree = "<group>"; }; A9EEF813955DAEEFE1D52ED4 /* Pods-TokamakDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TokamakDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TokamakDemo/Pods-TokamakDemo.debug.xcconfig"; sourceTree = "<group>"; };
C6DA99382B6892EAB361742F /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; }; C6DA99382B6892EAB361742F /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
D11DB6422219C03000013FC3 /* Timer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timer.swift; sourceTree = "<group>"; }; D11DB6422219C03000013FC3 /* Timer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timer.swift; sourceTree = "<group>"; };
@ -159,6 +161,7 @@
D1DEEC2822009E8000C525EE /* ModalRouter.swift */, D1DEEC2822009E8000C525EE /* ModalRouter.swift */,
D1F2C3262214407B008358DC /* TableModal.swift */, D1F2C3262214407B008358DC /* TableModal.swift */,
D11DB6422219C03000013FC3 /* Timer.swift */, D11DB6422219C03000013FC3 /* Timer.swift */,
A6D5AF86221B131400DBF186 /* Image.swift */,
); );
path = Components; path = Components;
sourceTree = "<group>"; sourceTree = "<group>";
@ -274,6 +277,7 @@
D11DB6432219C03000013FC3 /* Timer.swift in Sources */, D11DB6432219C03000013FC3 /* Timer.swift in Sources */,
D1F7185322159E09004E5951 /* Controls.swift in Sources */, D1F7185322159E09004E5951 /* Controls.swift in Sources */,
D1DEEC2922009E8000C525EE /* ModalRouter.swift in Sources */, D1DEEC2922009E8000C525EE /* ModalRouter.swift in Sources */,
A6D5AF87221B131400DBF186 /* Image.swift in Sources */,
D1BFAF772215795900845EA0 /* Router.swift in Sources */, D1BFAF772215795900845EA0 /* Router.swift in Sources */,
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
D1F7185D2215A4A1004E5951 /* LayerProps.swift in Sources */, D1F7185D2215A4A1004E5951 /* LayerProps.swift in Sources */,

View File

@ -0,0 +1,24 @@
//
// Image.swift
// TokamakDemo
//
// Created by Matvii Hodovaniuk on 2/18/19.
// Copyright © 2019 Tokamak. All rights reserved.
//
import Tokamak
struct ImageExample: LeafComponent {
typealias Props = Null
static func render(props: Null, hooks: Hooks) -> AnyNode {
return StackView.node(.init(
alignment: .center,
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
), [
Image.node(.init(name: "tokamak")),
])
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "tokamak.jpg",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@ -17,6 +17,7 @@ enum AppRoute: String, CaseIterable {
case datePicker = "Date Picker" case datePicker = "Date Picker"
case layerProps = "Layer Props" case layerProps = "Layer Props"
case timer case timer
case image
} }
extension AppRoute: CustomStringConvertible { extension AppRoute: CustomStringConvertible {
@ -56,6 +57,8 @@ struct Router: NavigationRouter {
result = LayerProps.node() result = LayerProps.node()
case .timer: case .timer:
result = TimerCounter.node() result = TimerCounter.node()
case .image:
result = ImageExample.node()
} }
return NavigationItem.node( return NavigationItem.node(

View File

@ -0,0 +1,68 @@
//
// Image.swift
// Tokamak
//
// Created by Matvii Hodovaniuk on 2/17/19.
//
import Foundation
public struct Image: HostComponent {
public typealias Children = [AnyNode]
public struct Props: Equatable, StyleProps {
public enum RenderingMode {
case automatic
case alwaysOriginal
case alwaysTemplate
}
public enum Source: Equatable {
case name(String)
case data(Data)
}
// when changed initializes new image with `UIImage(named:)`
// or `UIImage(data:)`
public let source: Source
// when changed creates new image with `withRenderingMode`
public let renderingMode: RenderingMode
// when changed initializes new image with given scale
public let scale: Double
// mirrors `flipsForRightToLeftLayoutDirection`
public let flipsForRTL: Bool
public let style: Style?
public init(
flipsForRTL: Bool = false,
name: String,
renderingMode: RenderingMode = .automatic,
scale: Double = 1.0,
_ style: Style? = nil
) {
source = .name(name)
self.renderingMode = renderingMode
self.scale = scale
self.flipsForRTL = flipsForRTL
self.style = style
}
public init(
data: Data,
flipsForRTL: Bool = false,
renderingMode: RenderingMode = .automatic,
scale: Double = 1.0,
_ style: Style? = nil
) {
source = .data(data)
self.renderingMode = renderingMode
self.scale = scale
self.flipsForRTL = flipsForRTL
self.style = style
}
}
}

View File

@ -0,0 +1,51 @@
//
// Image.swift
// TokamakUIKit
//
// Created by Matvii Hodovaniuk on 2/17/19.
//
import Tokamak
import UIKit
final class TokamakImage: UIImageView, Default {
public static var defaultValue: TokamakImage {
return TokamakImage()
}
}
extension UIImage.RenderingMode {
public init(_ rawValue: Image.Props.RenderingMode) {
switch rawValue {
case .automatic:
self = .automatic
case .alwaysOriginal:
self = .alwaysOriginal
case .alwaysTemplate:
self = .alwaysTemplate
}
}
}
extension Image: UIViewComponent {
static func update(
view box: ViewBox<TokamakImage>,
_ props: Image.Props,
_ children: [AnyNode]
) {
var image: UIImage?
switch props.source {
case let .name(name):
image = UIImage(named: name)
case let .data(data):
image = UIImage(data: data, scale: CGFloat(props.scale))
}
if props.flipsForRTL {
image = image?.imageFlippedForRightToLeftLayoutDirection()
}
box.view.image = image?.withRenderingMode(.init(props.renderingMode))
}
}

View File

@ -21,6 +21,8 @@
/* End PBXAggregateTarget section */ /* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
D1B4F8DB221AFB0E00C53C42 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B4F8D9221AFB0800C53C42 /* Image.swift */; };
D1B4F8DD221AFB2B00C53C42 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B4F8DC221AFB2B00C53C42 /* Image.swift */; };
OBJ_153 /* AnyEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_66 /* AnyEquatable.swift */; }; OBJ_153 /* AnyEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_66 /* AnyEquatable.swift */; };
OBJ_154 /* AnyNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_67 /* AnyNode.swift */; }; OBJ_154 /* AnyNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_67 /* AnyNode.swift */; };
OBJ_155 /* Components.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_68 /* Components.swift */; }; OBJ_155 /* Components.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_68 /* Components.swift */; };
@ -180,6 +182,8 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
D1B4F8D9221AFB0800C53C42 /* Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
D1B4F8DC221AFB2B00C53C42 /* Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
OBJ_10 /* ContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerViewController.swift; sourceTree = "<group>"; }; OBJ_10 /* ContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerViewController.swift; sourceTree = "<group>"; };
OBJ_100 /* FirstBaseline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstBaseline.swift; sourceTree = "<group>"; }; OBJ_100 /* FirstBaseline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstBaseline.swift; sourceTree = "<group>"; };
OBJ_101 /* Height.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Height.swift; sourceTree = "<group>"; }; OBJ_101 /* Height.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Height.swift; sourceTree = "<group>"; };
@ -406,6 +410,7 @@
OBJ_17 /* Host */ = { OBJ_17 /* Host */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D1B4F8D9221AFB0800C53C42 /* Image.swift */,
OBJ_18 /* Button.swift */, OBJ_18 /* Button.swift */,
OBJ_19 /* DatePicker.swift */, OBJ_19 /* DatePicker.swift */,
OBJ_20 /* Label.swift */, OBJ_20 /* Label.swift */,
@ -460,7 +465,7 @@
path = Constraint; path = Constraint;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
OBJ_5 /* */ = { OBJ_5 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
OBJ_6 /* Package.swift */, OBJ_6 /* Package.swift */,
@ -472,7 +477,6 @@
OBJ_142 /* tokamakui.org */, OBJ_142 /* tokamakui.org */,
OBJ_143 /* Products */, OBJ_143 /* Products */,
); );
name = "";
sourceTree = "<group>"; sourceTree = "<group>";
}; };
OBJ_55 /* Protocols */ = { OBJ_55 /* Protocols */ = {
@ -502,8 +506,8 @@
OBJ_66 /* AnyEquatable.swift */, OBJ_66 /* AnyEquatable.swift */,
OBJ_67 /* AnyNode.swift */, OBJ_67 /* AnyNode.swift */,
OBJ_68 /* Components.swift */, OBJ_68 /* Components.swift */,
OBJ_69 /* Components */,
OBJ_117 /* Default.swift */, OBJ_117 /* Default.swift */,
OBJ_69 /* Components */,
OBJ_118 /* Hooks */, OBJ_118 /* Hooks */,
OBJ_123 /* MountedComponents */, OBJ_123 /* MountedComponents */,
OBJ_128 /* Null.swift */, OBJ_128 /* Null.swift */,
@ -539,6 +543,7 @@
OBJ_70 /* Host */ = { OBJ_70 /* Host */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D1B4F8DC221AFB2B00C53C42 /* Image.swift */,
OBJ_71 /* Alert.swift */, OBJ_71 /* Alert.swift */,
OBJ_72 /* Animated.swift */, OBJ_72 /* Animated.swift */,
OBJ_73 /* Button.swift */, OBJ_73 /* Button.swift */,
@ -733,7 +738,7 @@
knownRegions = ( knownRegions = (
en, en,
); );
mainGroup = OBJ_5 /* */; mainGroup = OBJ_5;
productRefGroup = OBJ_143 /* Products */; productRefGroup = OBJ_143 /* Products */;
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
@ -778,6 +783,7 @@
OBJ_175 /* Color.swift in Sources */, OBJ_175 /* Color.swift in Sources */,
OBJ_176 /* Bottom.swift in Sources */, OBJ_176 /* Bottom.swift in Sources */,
OBJ_177 /* Center.swift in Sources */, OBJ_177 /* Center.swift in Sources */,
D1B4F8DD221AFB2B00C53C42 /* Image.swift in Sources */,
OBJ_178 /* CenterX.swift in Sources */, OBJ_178 /* CenterX.swift in Sources */,
OBJ_179 /* CenterY.swift in Sources */, OBJ_179 /* CenterY.swift in Sources */,
OBJ_180 /* Constraint.swift in Sources */, OBJ_180 /* Constraint.swift in Sources */,
@ -873,6 +879,7 @@
OBJ_276 /* CenterX.swift in Sources */, OBJ_276 /* CenterX.swift in Sources */,
OBJ_277 /* CenterY.swift in Sources */, OBJ_277 /* CenterY.swift in Sources */,
OBJ_278 /* Constrainable.swift in Sources */, OBJ_278 /* Constrainable.swift in Sources */,
D1B4F8DB221AFB0E00C53C42 /* Image.swift in Sources */,
OBJ_279 /* Constraint.swift in Sources */, OBJ_279 /* Constraint.swift in Sources */,
OBJ_280 /* FirstBaseline.swift in Sources */, OBJ_280 /* FirstBaseline.swift in Sources */,
OBJ_281 /* Height.swift in Sources */, OBJ_281 /* Height.swift in Sources */,