Repository: akane/Gaikan
Branch: master
Commit: 3b9eae7d7755
Files: 77
Total size: 145.8 KB
Directory structure:
gitextract_7_zppekp/
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── Cartfile
├── Cartfile.private
├── Cartfile.resolved
├── Doc/
│ └── Properties.md
├── Gaikan/
│ ├── Gaikan.h
│ ├── Helpers/
│ │ ├── AssociatedObject.swift
│ │ ├── CGPoint+Helpers.swift
│ │ ├── Dictionary+Helpers.swift
│ │ ├── NSAttributedString+Style.swift
│ │ ├── NSLayoutAttribute+Helpers.swift
│ │ ├── NSLayoutRelation+Helpers.swift
│ │ ├── NSShadow+Helpers.swift
│ │ ├── Optional+Helpers.swift
│ │ ├── UIColor+Helpers.swift
│ │ ├── UIImage+Helpers.swift
│ │ └── UIView+Helpers.swift
│ ├── Info.plist
│ ├── InterfaceBuilder/
│ │ └── UIView+InterfaceBuilder.swift
│ ├── Property/
│ │ ├── Gradient.swift
│ │ ├── Property.swift
│ │ └── Value/
│ │ ├── Background.swift
│ │ ├── Border.swift
│ │ ├── Constraint.swift
│ │ ├── Corners.swift
│ │ └── Side.swift
│ ├── Style/
│ │ ├── Stylable.swift
│ │ ├── Style.swift
│ │ ├── StylePseudoState.swift
│ │ ├── StyleRule+DirectAccess.swift
│ │ ├── StyleRule.swift
│ │ └── StyleState.swift
│ ├── Theme/
│ │ └── Theme.swift
│ └── UIKit/
│ ├── Extension/
│ │ ├── UIControl.swift
│ │ ├── UILabel.swift
│ │ ├── UINavigationBar.swift
│ │ ├── UISwitch.swift
│ │ └── UIView.swift
│ ├── Layer/
│ │ ├── BackgroundLayer.swift
│ │ ├── BorderLayer.swift
│ │ └── Layer.swift
│ ├── Renderer/
│ │ ├── ConstraintRenderer.swift
│ │ └── ViewStyleRenderer.swift
│ └── VirtualView.swift
├── Gaikan.podspec
├── Gaikan.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── xcshareddata/
│ └── xcschemes/
│ └── Gaikan.xcscheme
├── Gaikan.xcworkspace/
│ └── contents.xcworkspacedata
├── GaikanTests/
│ ├── GaikanTests.swift
│ ├── Info.plist
│ ├── Style/
│ │ ├── StyleRuleSpec.swift
│ │ └── StyleSpec.swift
│ ├── Swift/
│ │ └── Extension/
│ │ └── DictionarySpec.swift
│ └── UIKit/
│ ├── Extension/
│ │ ├── UILabelSpec.swift
│ │ ├── UINavigationBarSpec.swift
│ │ └── UIViewSpec.swift
│ └── Renderer/
│ └── ConstraintRendererSpec.swift
├── LICENSE
├── Podfile
├── README.md
└── Sample/
├── AppDelegate.swift
├── Assets.xcassets/
│ ├── AppIcon.appiconset/
│ │ └── Contents.json
│ ├── Contents.json
│ ├── background.imageset/
│ │ └── Contents.json
│ └── logo.imageset/
│ └── Contents.json
├── Base.lproj/
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── CustomView.swift
├── Info.plist
├── Theme/
│ ├── Gradient.swift
│ ├── SampleTheme.swift
│ ├── UIColor.swift
│ └── UIFont.swift
└── ViewController.swift
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
Carthage/Checkouts
Carthage/Build
================================================
FILE: .travis.yml
================================================
language: objective-c
osx_image: xcode8.3
env:
- >
xcode_project=Gaikan.xcodeproj
xcode_scheme=Gaikan
xcode_sdk=iphonesimulator
xcode_platform="platform=iOS Simulator,name=iPhone 6"
before_install:
- brew update
- brew upgrade carthage
install: carthage update --platform iOS
script:
- >
set -o pipefail && xcodebuild
-project ${xcode_project}
-scheme ${xcode_scheme}
-sdk ${xcode_sdk}
-destination "${xcode_platform}" test | xcpretty -c
branches:
except:
- /^tags.+/
================================================
FILE: CHANGELOG.md
================================================
# CHANGELOG
## 0.9.1
### Added
- Added shadow property.
### Fixed
- Border not correctly set when all sides were defined by [viteinfinite](https://github.com/viteinfinite) [#PR-16](https://github.com/akane/Gaikan/pull/16)
# 0.9.0
## Added
- [Border] you can now set only one border side (top, right, bottom, left) if you want.
## Changed
## Fixed
- [UIView] Fixed rendering which was triggered every time frames changed
- [Background] Correctly render background when frames change
# 0.8.0
## Added
- Swift 3 support!
By [mcaylus](https://github.com/mcaylus)
[#PR-12](https://github.com/akane/Gaikan/pull/12)
# 0.7.0
## Added
- Added height, minHeight, maxHeight
- Added width, minWidth, maxWidth
## Changed
- Migrated to Swift 2.3
# 0.6.0
## Added
- Added Carthage support.
By [siemensikkema](https://github.com/siemensikkema)
[#PR-7](https://github.com/akane/Gaikan/pull/7)
- [Style] Added `textAttributes` on `StyleRule` which converts a style into `NSAttributedString` style attributes.
- [Style] Added `margin` attribute.
- [Style] Added `textOverflow` attribute.
## Changed
## Fixed
- [Property] Fixed `clip` attribute not setted correctly.
# 0.5.0
## Added
## Changed
- [Theme] Themes are now simple `AnyObject`. You just define (non static) attributes
on it and apply them on a `UIView` usting the new `styleClass` attribute.
- [IB] To apply a style right from InterfaceBuilder, you now define `themeClassName`
in addition to `styleName`.
- [Style] Replaced `applyStyle` with `styleInline`.
While the former was totally replacing the style, the newer appends style to `styleClass`.
## Fixed
# 0.4.0
## Added
- [Property] Added `CornerRadius`.
- [Property] Added `Clip`.
- [Property] Added `Opacity`.
- [Property] Added `Transform`.
## Changed
## Fixed
- [Background] Fixed renderer positions for `Gradient`.
================================================
FILE: Cartfile
================================================
github "facebook/KVOController"
================================================
FILE: Cartfile.private
================================================
github "Quick/Nimble"
github "Quick/Quick"
================================================
FILE: Cartfile.resolved
================================================
github "facebook/KVOController" "v1.1.0"
github "Quick/Nimble" "v4.1.0"
github "Quick/Quick" "v0.9.3"
================================================
FILE: Doc/Properties.md
================================================
# Style properties
## Background
- __**since**__: 0.3
- __**description**__: Sets a background to your view (color, gradient and or image)
- __**applies**__: `UIView`
- __**usage**__:
```swift
style.background = UIColor.redColor()
style.background = Background(UIImage(named: "bg"), UIColor.orangeGradient())
```
## Border
- __**since**__: 0.1
- __**description**__: Sets view border color and width
- __**applies**__: `UIView`
- __**usage**__:
```swift
// until 0.7
style.border = Border(width: 1, color: UIColor.blueColor())
// after 0.7 you can define one or all borders
style.border = Border(all: (width: 1, color: UIColor.blue))
style.border = Border(.left, style: (width: 1, color: UIColor.blue))
style.border = Border([.left, .right] : (width: 1, color: UIColor.blue))
```
## Clip
- __**since**__: 0.4
- __**description**__: enables/disables view overflow clipping
- __**applies**__: `UIView`
- __**default**__: false
- __**usage**__:
```swift
style.clip = true
```
## Color
- __**since**__: 0.1
- __**description**__: Sets text color
- __**applies**__: `UILabel`
- __**usage**__:
```swift
style.color = UIColor.redColor()
```
## CornerRadius
- __**since**__: 0.4
- __**description**__: Sets view corner radius
- __**applies**__: `UIView`
- __**usage**__:
```swift
style.corners = Corners(radius: 4)
```
## Font
- __**since**__: 0.1
- __**description**__: Sets text font
- __**applies**__: `UILabel`
- __**usage**__:
```swift
style.font = UIFont.systemFontOfSize(15)
```
## Height
- __**since**__: 0.7
- __**description**__: Sets a view height using AutoLayout.
- __**applies**__: `UIView`
- __**usage**__:
```swift
style.height = 42
style.height = 50 ~ UILayoutPriorityDefaultHigh
```
## Margin
- __**since**__: 0.6
- __**description**__: Sets a view internal margin/padding, i.e. `UIView.layoutMargins` or `UIButton.contentEdgeInsets`.
- __**applies**__: `UIView`, `UIButton`
- __**usage**__:
```swift
style.margin = UIEdgeInsetsMake(4, 4, 2, 2)
/// sets UIView.layoutMargins
/// or UIButton.contentEdgeInsets
```
## MaxHeight
- __**since**__: 0.7
- __**description**__: Sets a view maximum height using AutoLayout.
- __**applies**__: `UIView`
- __**usage**__:
```swift
style.maxHeight = 42
style.maxHeight = 50 ~ UILayoutPriorityDefaultHigh
```
## MaxWidth
- __**since**__: 0.7
- __**description**__: Sets a view maximum width using AutoLayout.
- __**applies**__: `UIView`
- __**see**__: maxHeight
## MinHeight
- __**since**__: 0.7
- __**description**__: Sets a view minimum height using AutoLayout.
- __**applies**__: `UIView`
- __**usage**__:
```swift
style.minHeight = 42
style.minHeight = 50 ~ UILayoutPriorityDefaultHigh
```
## MinWidth
- __**since**__: 0.7
- __**description**__: Sets a view minimum width using AutoLayout.
- __**applies**__: `UIView`
- __**see**__: minHeight
## Opacity
- __**since**__: 0.4
- __**description**__: Changes view alpha.
- __**applies**__: `UIView`
- __**range**__: 0 (tranparent) ... 100 (opaque)
- __**usage**__:
```swift
style.opacity = 80
```
## Shadow
- __**since**__: xxx
- __**description**__: Applies shadow to view.
- __**applies**__: `UIView`
- __**usage**__:
```swift
style.shadow = NSShadow(offset: CGSize(width: 0, height: 0), radius: 4, color: UIColor.red)
```
## TextAlign
## TextOverflow
## TintColor
## Transform
## Visible
- __**since**__: 0.1
- __**description**__: Sets whether or not the view is visible by changing `hidden` property.
- __**applies**__: `UIView`
- __**default**__: true
- __**usage**__:
```swift
style.visible = false
```
## Width
- __**since**__: 0.7
- __**description**__: Sets a view width using AutoLayout.
- __**applies**__: `UIView`
- __**see**__: height
================================================
FILE: Gaikan/Gaikan.h
================================================
//
// This file is part of Gaikan
//
// Created by JC on 30/08/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
#import <UIKit/UIKit.h>
//! Project version number for Gaikan.
FOUNDATION_EXPORT double GaikanVersionNumber;
//! Project version string for Gaikan.
FOUNDATION_EXPORT const unsigned char GaikanVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <Gaikan/PublicHeader.h>
================================================
FILE: Gaikan/Helpers/AssociatedObject.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 25/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
/**
Code for AssociationObject using Swift types
From https://wezzard.com/2015/10/09/associated-object-and-swift-struct
**/
internal final class AssociatedObject<T> : NSObject, NSCopying {
typealias AssociatedType = T
let value: AssociatedType
required init(_ value: AssociatedType) {
self.value = value
}
func copy(with zone: NSZone?) -> Any {
return AssociatedObject(self.value)
}
}
extension AssociatedObject where T:NSCopying {
func copyWithZone(_ zone: NSZone?) -> AnyObject {
return AssociatedObject(value.copy(with: zone) as! AssociatedType)
}
}
================================================
FILE: Gaikan/Helpers/CGPoint+Helpers.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 05/11/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
extension CGPoint {
public static func topLeft() -> CGPoint {
return CGPoint(x: 0, y: 0)
}
public static func topRight() -> CGPoint {
return CGPoint(x: 1, y: 1)
}
public static func bottomLeft() -> CGPoint {
return CGPoint(x: 0, y: 1)
}
public static func bottomRight() -> CGPoint {
return CGPoint(x: 1, y: 1)
}
public static func top() -> CGPoint {
return CGPoint(x: 0.5, y: 0)
}
public static func bottom() -> CGPoint {
return CGPoint(x: 0.5, y: 1)
}
}
================================================
FILE: Gaikan/Helpers/Dictionary+Helpers.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 24/06/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
extension Dictionary where Key : Any, Value : OptionalProtocol, Value.WrappedType : AnyObject {
typealias Wrapped = Value.WrappedType
func trimmed() -> [Key:Wrapped] {
var dict = [Key:Wrapped]()
for (key, value) in self {
if let value = value.value {
dict[key] = value
}
}
return dict
}
}
extension Dictionary {
@discardableResult
mutating func gaikan_merge(_ dictionary: Dictionary<Key, Value>) -> Dictionary<Key, Value> {
for (key, value) in dictionary {
self.updateValue(value, forKey: key)
}
return self
}
}
================================================
FILE: Gaikan/Helpers/NSAttributedString+Style.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 20/06/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
extension NSAttributedString {
public convenience init(string str: String, style: StyleRule) {
self.init(string: str, attributes: style.textAttributes)
}
}
extension NSMutableAttributedString {
public func setStyle(_ style: StyleRule, range: NSRange) {
self.setAttributes(style.textAttributes, range: range)
}
}
================================================
FILE: Gaikan/Helpers/NSLayoutAttribute+Helpers.swift
================================================
//
// NSLayoutAttribute+Helpers.swift
// Gaikan
//
// Created by pjechris on 01/09/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
extension NSLayoutAttribute {
func identifier() -> String {
switch(self) {
case .lastBaseline:
return "baseline"
case .bottom:
return "bottom"
case .bottomMargin:
return "bottomMargin"
case .centerX:
return "centerX"
case .centerXWithinMargins:
return "centerXWithinMargins"
case .centerY:
return "centerY"
case .centerYWithinMargins:
return "centerYWithinMargins"
case .firstBaseline:
return "firstBaseline"
case .height:
return "height"
case .leading:
return "leading"
case .leadingMargin:
return "leadingMargin"
case .left:
return "left"
case .leftMargin:
return "leftMargin"
case .notAnAttribute:
return "notAnAttribute"
case .right:
return "right"
case .rightMargin:
return "rightMargin"
case .top:
return "top"
case .topMargin:
return "topMargin"
case .trailing:
return "trailing"
case .trailingMargin:
return "trailingMargin"
case .width:
return "width"
}
}
}
================================================
FILE: Gaikan/Helpers/NSLayoutRelation+Helpers.swift
================================================
//
// NSLayoutRelation+Helpers.swift
// Gaikan
//
// Created by pjechris on 01/09/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
extension NSLayoutRelation {
func identifier() -> String {
switch (self) {
case .equal:
return "accurate"
case .greaterThanOrEqual:
return "min"
case .lessThanOrEqual:
return "max"
}
}
}
================================================
FILE: Gaikan/Helpers/NSShadow+Helpers.swift
================================================
//
// NSShadow+Helpers.swift
// Gaikan
//
// Created by pjechris on 07/02/17.
// Copyright © 2017 fr.akane. All rights reserved.
//
import Foundation
extension NSShadow {
public convenience init(offset: CGSize, radius: CGFloat, color: UIColor?) {
self.init()
self.shadowOffset = offset
self.shadowBlurRadius = radius
self.shadowColor = color
}
}
================================================
FILE: Gaikan/Helpers/Optional+Helpers.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 24/06/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
protocol OptionalProtocol {
associatedtype WrappedType
var value: WrappedType? { get }
}
extension Optional: OptionalProtocol {
var value: Wrapped? {
return self
}
}
================================================
FILE: Gaikan/Helpers/UIColor+Helpers.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 05/11/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
extension UIColor : BackgroundValue {
public func draw(in ctx: CGContext) {
ctx.setFillColor(self.cgColor)
ctx.fill(CGRect(origin: CGPoint.zero, size: CGSize(width: ctx.width, height: ctx.height)))
}
}
================================================
FILE: Gaikan/Helpers/UIImage+Helpers.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 15/11/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
extension UIImage : BackgroundValue {
public func draw(in ctx: CGContext) {
self.draw(in: CGRect(origin: CGPoint.zero, size: CGSize(width: ctx.width, height: ctx.height)))
}
}
================================================
FILE: Gaikan/Helpers/UIView+Helpers.swift
================================================
//
// UIView+Helpers.swift
// Gaikan
//
// Created by pjechris on 10/09/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
extension UIView {
struct Keys {
static var Dimension = "DimensionAttr"
}
var dimensions: [NSLayoutConstraint] {
get {
guard let constraints = objc_getAssociatedObject(self, &Keys.Dimension) as? [NSLayoutConstraint] else {
self.dimensions = []
return self.dimensions
}
return constraints
}
set { objc_setAssociatedObject(self, &Keys.Dimension, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
}
}
================================================
FILE: Gaikan/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
================================================
FILE: Gaikan/InterfaceBuilder/UIView+InterfaceBuilder.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 03/05/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
var ViewStyleNameAttribute = "ViewStyleNameAttribute"
var ViewThemeClassAttr = "ViewThemeClassAttr"
/**
* Dynamically retrieves a "defined styleClass" from a storyboard/xib.
*/
extension UIView {
/// theme class which contains desired styleClass instance.
/// You need to provide both `styleName` and `themeClassName` so that style can be dynamically found
@IBInspectable var themeClassName: String? {
get { return objc_getAssociatedObject(self, &ViewThemeClassAttr) as? String }
set {
guard let newValue = newValue else {
return
}
let moduleName = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
let className = newValue.contains(".") ? newValue : moduleName + "." + newValue
objc_setAssociatedObject(self, &ViewThemeClassAttr, className, .OBJC_ASSOCIATION_COPY)
self.attemptLoadingStyle()
}
}
/// styleClass attribute name into its theme class.
/// You need to provide both `styleName` and `themeClassName` so that style can be dynamically found
@IBInspectable var styleName: String? {
get { return objc_getAssociatedObject(self, &ViewStyleNameAttribute) as? String }
set {
objc_setAssociatedObject(self, &ViewStyleNameAttribute, newValue, .OBJC_ASSOCIATION_COPY)
self.attemptLoadingStyle()
}
}
fileprivate func attemptLoadingStyle() {
guard let styleName = self.styleName, let themeClassName = self.themeClassName else {
return
}
let themeClass = NSClassFromString(themeClassName) as! Theme.Type
let dynamicTheme = themeClass.init()
let dynamicMirror = Mirror(reflecting: dynamicTheme)
for (label, value) in dynamicMirror.children {
if label == styleName {
self.styleClass = value as? Style
}
}
}
}
================================================
FILE: Gaikan/Property/Gradient.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 05/11/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
public struct Gradient {
public typealias GradientItem = (color: UIColor, position: Int)
let gradientValues: [(color: UIColor, position: Int)]
let to: CGPoint
let from: CGPoint
public init(from: CGPoint, to: CGPoint, _ gradients: (color: UIColor, position: Int)...) {
self.init(from: from, to: to, gradients)
}
public init(_ gradients: (color: UIColor, position: Int)...) {
self.init(from: CGPoint.top(), to: CGPoint.bottom(), gradients)
}
fileprivate init(from: CGPoint, to: CGPoint, _ gradients: [(color: UIColor, position: Int)]) {
self.from = from
self.to = to
self.gradientValues = gradients
}
}
extension Gradient : BackgroundValue {
public func draw(in ctx: CGContext) {
let layer = CAGradientLayer()
layer.frame = CGRect(origin: CGPoint.zero, size: CGSize(width: ctx.width, height: ctx.height))
layer.endPoint = self.to
layer.startPoint = self.from
layer.colors = self.gradientValues.map { $0.color.cgColor }
layer.locations = self.gradientValues.map { NSNumber(value:($0.position/100)) }
layer.render(in: ctx)
}
}
================================================
FILE: Gaikan/Property/Property.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 30/08/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
/// Property that can be used to style a view
/// Keep this file Alphabetic ordered
public enum Property {
case background
case border
case clip
case color
case cornerRadius
case font
case height
/// view layoutMargins
case margin
case maxHeight
case maxWidth
case minHeight
case minWidth
case opacity
case shadow
case textAlign
case textOverflow
case textShadow
case tintColor
case transform
case visible
case width
}
================================================
FILE: Gaikan/Property/Value/Background.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 05/11/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
/**
Any class/struct conforming to BackgroundValue can be used to represent the `Background` property
*/
public protocol BackgroundValue {
/// Renders the object into given context
func draw(in ctx: CGContext)
}
/**
Allow to use one or more BackgroundValue objects at once as a unique background
*/
public struct Background : BackgroundValue {
internal var backgrounds: [BackgroundValue]
public init(_ backgrounds: BackgroundValue...) {
self.backgrounds = backgrounds
}
public func draw(in ctx: CGContext) {
for bg in self.backgrounds {
bg.draw(in: ctx)
}
}
}
================================================
FILE: Gaikan/Property/Value/Border.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 05/09/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
public typealias BorderStyle = (width: CGFloat, color: UIColor)
/**
Represents `Border` property
*/
public struct Border : Equatable {
var sides: [Side: BorderStyle]
public init(_ side: Side, style: BorderStyle) {
self.init(sides: [side], style: style)
}
public init(all style: BorderStyle) {
self.init(sides: [.top, .right, .bottom, .left], style: style)
}
public init(sides: [Side], style: BorderStyle) {
var allSides = [Side:BorderStyle]()
for side in sides {
allSides[side] = style
}
self.sides = allSides
}
public func stylize(_ side: Side, with style: BorderStyle) -> Border {
var newBorder = self
newBorder.sides[side] = style
return newBorder
}
}
public func ==(lhs: Border, rhs: Border) -> Bool {
for (key, lvalue) in lhs.sides {
guard let rvalue = rhs.sides[key] else {
return false
}
guard lvalue.width == rvalue.width, lvalue.color == rvalue.color else {
return false
}
}
return true
}
================================================
FILE: Gaikan/Property/Value/Constraint.swift
================================================
//
// Constraint.swift
// Gaikan
//
// Created by pjechris on 29/08/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
public struct Constraint {
public let constant: Double
public var priority = UILayoutPriorityRequired
public init(constant: Double) {
self.constant = constant
}
}
extension Constraint : ExpressibleByFloatLiteral, ExpressibleByIntegerLiteral {
public init(floatLiteral value: FloatLiteralType) {
self.init(constant: value)
}
public init(integerLiteral value: IntegerLiteralType) {
self.init(constant: Double(value))
}
}
infix operator ~
public func ~ (lhs: inout Constraint, rhs: UILayoutPriority) -> Constraint {
lhs.priority = rhs
return lhs
}
================================================
FILE: Gaikan/Property/Value/Corners.swift
================================================
//
// Corners.swift
// Gaikan
//
// Created by Brandon on 27/01/2016.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
/**
Represent the `Corners` property
*/
public struct Corners {
public let radius: CGFloat
public init(radius: CGFloat) {
self.radius = radius
}
}
================================================
FILE: Gaikan/Property/Value/Side.swift
================================================
//
// Side.swift
// Gaikan
//
// Created by pjechris on 04/12/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
public enum Side : String {
case top
case right
case bottom
case left
public static var all: Set<Side> {
return [.top, .right, .bottom, .left]
}
}
extension Side : Hashable {
public var hashValue: Int {
return self.rawValue.hashValue
}
}
//extension Side : Hashable {
// public var hashValue: Int {
// switch (self) {
// case .top(_):
// return "top".hashValue
// case .right(_):
// return "right".hashValue
// case .bottom(_):
// return "bottom".hashValue
// case .left(_):
// return "left".hashValue
// }
// }
//}
//
//public func ==<T>(lhs: Side<T>, rhs: Side<T>) -> Bool {
// return lhs.hashValue == rhs.hashValue
//}
================================================
FILE: Gaikan/Style/Stylable.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 30/08/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
var ComputedStyleAttribute = "ComputedStyleAttribute"
/**
Applies a `Style` or a `StyleRule` on an object
*/
public protocol Stylable : class {
/// `Style` class to apply. Calls `computeStyle` when changed
var styleClass: Style? { get set }
/// Style specific to the object. Has precedence over `styleClass`.
/// Works like `style` in HTML.
var styleInline: StyleRule? { get set }
/// Custom style state. If defined `computedStyle` will merge state style with "default" state style
var styleState: String? { get }
/// Re-applies computed style
func updateStyle()
static func keyPathsAffectingStyle() -> [String]
}
extension Stylable {
/// Result `StyleRule` from `styleClass` (including `styleState`) + `styleInline`.
/// When changed it calls `updateStyle` to apply it.
public internal(set) var computedStyle: StyleRule? {
get {
let value = objc_getAssociatedObject(self, &ComputedStyleAttribute) as? AssociatedObject<StyleRule>
return value != nil ? value!.value : nil
}
set {
objc_setAssociatedObject(self, &ComputedStyleAttribute, newValue.map { AssociatedObject($0) }, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
self.updateStyle()
}
}
/// Calculates style and store it into `computedStyle`
internal func computeStyle() {
guard let style = self.styleClass else {
self.computedStyle = self.styleInline
return
}
let states = StyleState.states(self)
var computedStyle = style.style
for state in states {
computedStyle = style.states[state].map { return $0.extends(computedStyle) } ?? computedStyle
}
if let styleInline = self.styleInline {
self.computedStyle = styleInline.extends(computedStyle)
}
else {
self.computedStyle = computedStyle
}
}
}
================================================
FILE: Gaikan/Style/Style.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 11/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
/**
* Defines a `StyleRule` on which you can apply supplemntary `StylePseudoState` states.
*/
public struct Style : ExpressibleByDictionaryLiteral {
internal fileprivate(set) var style: StyleRule
internal fileprivate(set) var states: [StyleState:StyleRule] = [:]
public init(dictionaryLiteral elements: (StyleRule.Key, StyleRule.Value)...) {
var attributes = Dictionary<StyleRule.Key, StyleRule.Value>()
for (attributeName, attributeValue) in elements {
attributes[attributeName] = attributeValue
}
self.init(style: StyleRule(attributes: attributes))
}
public init(_ styleBlock: (_ style: inout StyleRule) -> ()) {
self.init(style: StyleRule(styleBlock))
}
fileprivate init(style: StyleRule) {
self.style = style
}
public func state(_ state: StylePseudoState, styleRule styleBlock: (_ style: inout StyleRule) -> ()) -> Style {
return self.state(.pseudoState(state), styleRule: styleBlock)
}
internal func state(_ state: StyleState, styleRule styleBlock: (_ style: inout StyleRule) -> ()) -> Style {
var style = self
style.states[state] = StyleRule(styleBlock)
return style
}
public func state(_ state: String, styleRule styleBlock: (_ style: inout StyleRule) -> ()) -> Style {
return self.state(.custom(state), styleRule: styleBlock)
}
public func state(_ state: StylePseudoState, _ attributes: [StyleRule.Key:StyleRule.Value]) -> Style {
return self.state(.pseudoState(state), attributes: attributes)
}
public func state(_ state: String, _ attributes: [StyleRule.Key:StyleRule.Value]) -> Style {
return self.state(.custom(state), attributes: attributes)
}
internal func state(_ state: StyleState, attributes: [StyleRule.Key:StyleRule.Value]) -> Style {
var style = self
style.states[state] = StyleRule(attributes: attributes)
return style
}
internal subscript(state: StylePseudoState) -> StyleRule? {
get { return self.states[.pseudoState(state)] }
}
internal subscript(state: String) -> StyleRule? {
get { return self.states[.custom(state)] }
}
}
================================================
FILE: Gaikan/Style/StylePseudoState.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 14/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
/**
Used to define a special state of an element.
As element can be in multiple states at the same time (like disabled and on), pseudo classes are defined as a UInt enum.
The bigger the value, the higher priority it has
**/
public enum StylePseudoState : UInt {
case highlighted
case disabled
case selected
case on
}
================================================
FILE: Gaikan/Style/StyleRule+DirectAccess.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 17/06/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
public extension StyleRule {
public var background: BackgroundValue? {
get { return self[.background].map { return $0 as! BackgroundValue } }
set { self.attributes[.background] = newValue }
}
public var border: Border? {
get { return self[.border].map { return $0 as! Border } }
set { self.attributes[.border] = newValue }
}
public var clip: Bool {
get { return self[.clip].map { return $0 as! Bool } ?? false }
set { self.attributes[.clip] = newValue }
}
public var corners: Corners? {
get { return self[.cornerRadius].map { return $0 as! Corners } }
set { self.attributes[.cornerRadius] = newValue }
}
public var color: UIColor? {
get { return self[.color].map { return $0 as! UIColor } }
set { self.attributes[.color] = newValue }
}
public var font: UIFont? {
get { return self[.font].map { return $0 as! UIFont } }
set { self.attributes[.font] = newValue }
}
public var height: Constraint? {
get { return self[.height].map { $0 as! Constraint } }
set { self.attributes[.height] = newValue }
}
public var margin: UIEdgeInsets? {
get { return self[.margin].map { return $0 as! UIEdgeInsets } }
set { self.attributes[.margin] = newValue }
}
public var maxHeight: Constraint? {
get { return self[.maxHeight].map { $0 as! Constraint } }
set { self.attributes[.maxHeight] = newValue }
}
public var maxWidth: Constraint? {
get { return self[.maxWidth].map { $0 as! Constraint } }
set { self.attributes[.maxWidth] = newValue }
}
public var minHeight: Constraint? {
get { return self[.minHeight].map { $0 as! Constraint } }
set { self.attributes[.minHeight] = newValue }
}
public var minWidth: Constraint? {
get { return self[.minWidth].map { $0 as! Constraint } }
set { self.attributes[.minWidth] = newValue }
}
/// value must be between 0 and 100
/// default is 100
public var opacity: Double {
get { return self[.opacity].map { return $0 as! Double } ?? 100 }
set { self.attributes[.opacity] = newValue }
}
public var shadow: NSShadow? {
get { return self[.shadow].map { return $0 as! NSShadow } }
set { self.attributes[.shadow] = newValue }
}
public var textAlign: NSTextAlignment? {
get { return self[.textAlign].map { return $0 as! NSTextAlignment } }
set { self.attributes[.textAlign] = newValue }
}
public var textOverflow: NSLineBreakMode? {
get { return self[.textOverflow].map { return $0 as! NSLineBreakMode } }
set { self.attributes[.textOverflow] = newValue }
}
public var tintColor: UIColor? {
get { return self[.tintColor].map { return $0 as! UIColor } }
set { self.attributes[.tintColor] = newValue }
}
public var transform: CATransform3D {
get { return self[.transform].map { return $0 as! CATransform3D } ?? CATransform3DIdentity }
set { self.attributes[.transform] = newValue }
}
public var visible: Bool? {
get { return self[.visible].map { return $0 as! Bool } }
set { self.attributes[.visible] = newValue }
}
public var width: Constraint? {
get { return self[.width].map { $0 as! Constraint } }
set { self.attributes[.width] = newValue }
}
public var textShadow: NSShadow? {
get { return self[.textShadow].map { return $0 as! NSShadow } }
set { self.attributes[.textShadow] = newValue }
}
}
================================================
FILE: Gaikan/Style/StyleRule.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 30/08/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
/**
* Defines design properties with their values.
*/
public struct StyleRule : ExpressibleByDictionaryLiteral {
public typealias Key = Property
public typealias Value = Any?
var attributes : Dictionary<Key, Value>
public init(attributes: [Key:Value]) {
self.attributes = attributes
}
public init(dictionaryLiteral elements: (Key, Value)...) {
var attributes = Dictionary<Key, Value>()
for (attributeName, attributeValue) in elements {
attributes[attributeName] = attributeValue
}
self.attributes = attributes
}
public init(_ styleBlock: (_ style: inout StyleRule) -> ()) {
self.init(attributes: [:])
styleBlock(&self)
}
public func extends(_ styles: StyleRule?...) -> StyleRule {
var composedAttributes: [Key:Value] = [:]
for style in styles {
if let styleAttributes = style?.attributes {
composedAttributes.gaikan_merge(styleAttributes)
}
}
return StyleRule(attributes: composedAttributes.gaikan_merge(self.attributes))
}
subscript(keyname: Property) -> Value {
get { return self.attributes[keyname] != nil ? self.attributes[keyname]! : nil }
}
}
extension StyleRule {
public var textAttributes: [String:AnyObject] {
let attributes: [String:AnyObject?] = [
NSForegroundColorAttributeName: self.color,
NSFontAttributeName: self.font,
NSShadowAttributeName: self.textShadow
]
return attributes.trimmed()
}
}
================================================
FILE: Gaikan/Style/StyleState.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 10/12/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
enum StyleState {
case pseudoState(StylePseudoState)
case custom(String)
}
extension StyleState {
static func states<T:Stylable>(_ element: T) -> [StyleState] {
var states: [StyleState] = []
if let control = element as? UIControl {
if (control.isHighlighted) {
states.append(.pseudoState(.highlighted))
}
if (!control.isEnabled) {
states.append(.pseudoState(.disabled))
}
if (control.isSelected) {
states.append(.pseudoState(.selected))
}
if let switcher = control as? UISwitch {
if (switcher.isOn) {
states.append(.pseudoState(.on))
}
}
}
if let customState = element.styleState {
states.append(.custom(customState))
}
return states
}
}
extension StyleState : Hashable {
var hashValue: Int {
switch (self) {
case .pseudoState(let state):
return state.hashValue
case .custom(let state):
return state.hashValue
}
}
}
func ==(lhs: StyleState, rhs: StyleState) -> Bool {
switch (lhs, rhs) {
case (.pseudoState(let state1), .pseudoState(let state2)):
return state1 == state2
case (.custom(let state1), .custom(let state2)):
return state1 == state2
default:
return false
}
}
================================================
FILE: Gaikan/Theme/Theme.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 14/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
open class Theme : AnyObject {
required public init() {
}
}
================================================
FILE: Gaikan/UIKit/Extension/UIControl.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 24/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
public extension UIControl {
public override func updateStyle() {
super.updateStyle()
guard let computedStyle = self.computedStyle else {
return
}
ViewStyleRenderer.render(self, styleRule: computedStyle)
}
public override class func keyPathsAffectingStyle() -> [String] {
return ["enabled", "selected", "highlighted"]
}
}
================================================
FILE: Gaikan/UIKit/Extension/UILabel.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 26/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
public extension UILabel {
public override func updateStyle() {
super.updateStyle()
guard let computedStyle = self.computedStyle else {
return
}
ViewStyleRenderer.render(self, styleRule: computedStyle)
}
}
================================================
FILE: Gaikan/UIKit/Extension/UINavigationBar.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 26/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
public extension UINavigationBar {
fileprivate struct AssociatedKeys {
static var VirtualView = "gaikan_virtualView"
}
public override func updateStyle() {
super.updateStyle()
if let computedStyle = self.computedStyle {
ViewStyleRenderer.render(self, styleRule: computedStyle)
}
if let titleStyle = self.titleStyle.computedStyle {
ViewStyleRenderer.render(self, titleStyle: titleStyle)
}
}
public var titleStyle: VirtualView<UINavigationBar> {
guard let title = objc_getAssociatedObject(self, &AssociatedKeys.VirtualView) as? VirtualView<UINavigationBar> else {
let title = VirtualView(targetView: self)
objc_setAssociatedObject(self, &AssociatedKeys.VirtualView, title as VirtualView<UINavigationBar>?, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return title
}
return title
}
}
================================================
FILE: Gaikan/UIKit/Extension/UISwitch.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 24/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
public extension UIButton {
public override func updateStyle() {
super.updateStyle()
guard let computedStyle = self.computedStyle else {
return
}
ViewStyleRenderer.render(self, styleRule: computedStyle)
}
}
================================================
FILE: Gaikan/UIKit/Extension/UIView.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 30/08/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import KVOController
var ViewStyleStateAttribute = "ViewStyleStateAttribute"
var ViewStyleClassAttr = "ViewStyleClassAttr"
var ViewStyleInlineAttr = "ViewStyleInlineAttr"
extension UIView : Stylable {
public var styleClass: Style? {
get {
let value = objc_getAssociatedObject(self, &ViewStyleClassAttr) as? AssociatedObject<Style?>
return value.map { $0.value } ?? nil
}
set {
if (newValue == nil) {
self.unregisterStyleKeyPaths()
}
objc_setAssociatedObject(self, &ViewStyleClassAttr, AssociatedObject(newValue), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
self.addStyleLayerIfNeeded()
self.computeStyle()
if (newValue != nil) {
self.registerStyleKeyPaths()
}
}
}
public var styleInline: StyleRule? {
get {
let value = objc_getAssociatedObject(self, &ViewStyleInlineAttr) as? AssociatedObject<StyleRule>
return value.map { $0.value }
}
set {
objc_setAssociatedObject(self, &ViewStyleInlineAttr, newValue.map { AssociatedObject($0) }, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
self.addStyleLayerIfNeeded()
self.computeStyle()
}
}
public var styleState: String? {
get { return objc_getAssociatedObject(self, &ViewStyleStateAttribute) as? String }
set {
objc_setAssociatedObject(self, &ViewStyleStateAttribute, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
self.computeStyle()
}
}
public func updateStyle() {
guard let computedStyle = self.computedStyle else {
return
}
ViewStyleRenderer.render(self, styleRule: computedStyle)
}
public class func keyPathsAffectingStyle() -> [String] {
return []
}
}
internal extension UIView {
func registerStyleKeyPaths() {
let keyPaths = type(of: self).keyPathsAffectingStyle()
if keyPaths.count > 0 {
self.kvoController.observe(self, keyPaths: keyPaths, options: .new) { [weak self] _ in
self?.computeStyle()
}
}
}
func unregisterStyleKeyPaths() {
type(of: self).keyPathsAffectingStyle().map { self.kvoController.unobserve(self, keyPath: $0) }
}
}
var StyleKeyAttribute = "StyleLayer"
extension UIView {
var styleLayer: StyleLayer! {
get { return objc_getAssociatedObject(self, &StyleKeyAttribute) as? StyleLayer }
set { objc_setAssociatedObject(self, &StyleKeyAttribute, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
}
func addStyleLayerIfNeeded() {
if let _ = self.styleLayer {
return
}
let styleLayer = StyleLayer()
self.styleLayer = styleLayer
self.layer.insertSublayer(styleLayer, at: 0)
styleLayer.frame = self.layer.bounds
self.registerBounds()
}
func registerBounds() {
self.kvoController.observe(self.layer, keyPath: "bounds", options: .new) { [weak self] _ in
guard let weakSelf = self else {
return
}
weakSelf.styleLayer?.frame = weakSelf.layer.bounds
}
}
}
================================================
FILE: Gaikan/UIKit/Layer/BackgroundLayer.swift
================================================
//
// BackgroundLayer.swift
// Gaikan
//
// Created by pjechris on 01/12/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
class BackgroundLayer : CALayer {
var background: Background? {
didSet {
self.setNeedsDisplay()
}
}
override func draw(in ctx: CGContext) {
guard let background = self.background else {
return
}
UIGraphicsPushContext(ctx)
background.draw(in: ctx)
UIGraphicsPopContext()
}
}
================================================
FILE: Gaikan/UIKit/Layer/BorderLayer.swift
================================================
//
// BorderLayer.swift
// Gaikan
//
// Created by pjechris on 30/11/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
class BorderLayer : CALayer {
var border: Border? {
didSet { self.setNeedsDisplay() }
}
override func draw(in ctx: CGContext) {
guard let border = self.border else {
return
}
guard border.sides.keys.count != Side.all.count else {
drawAllSides(for: border, in: ctx)
return
}
drawSingleSides(for: border, in: ctx)
}
@inline(__always) func drawAllSides(for border: Border, in ctx: CGContext) {
UIGraphicsPushContext(ctx)
let topBorder = border.sides[.top]! // Any border here would suffice
let path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
topBorder.color.setStroke()
path.lineWidth = CGFloat(topBorder.width)
path.addClip()
path.stroke()
UIGraphicsPopContext()
}
private func drawSingleSides(for border: Border, in ctx: CGContext) {
let path = UIBezierPath()
UIGraphicsPushContext(ctx)
for (side, border) in border.sides {
switch(side) {
case .top:
self.draw(border: border,
path: path,
points: [ CGPoint(x: 0, y: 0), CGPoint(x: bounds.width, y: 0), CGPoint(x: bounds.width, y: border.width), CGPoint(x: 0, y: border.width) ])
case .right:
self.draw(border: border,
path: path,
points: [CGPoint(x: bounds.width, y: 0), CGPoint(x: bounds.width, y: bounds.height), CGPoint(x: bounds.width - border.width, y: bounds.height), CGPoint(x: bounds.width - border.width, y: 0)])
case .bottom:
self.draw(border: border,
path: path,
points: [CGPoint(x: bounds.width, y: bounds.height), CGPoint(x: 0, y: bounds.height), CGPoint(x: 0, y: bounds.height - border.width), CGPoint(x: bounds.width, y: bounds.height - border.width)])
case .left:
self.draw(border: border,
path: path,
points: [CGPoint(x: 0, y: bounds.height), CGPoint(x: 0, y: 0), CGPoint(x: Int(border.width), y: 0), CGPoint(x: border.width, y: bounds.height)])
}
}
UIGraphicsPopContext()
}
func draw(border: BorderStyle, path: UIBezierPath, points: [CGPoint]) {
guard let first = points.first else {
return
}
path.move(to: first)
for point in points {
path.addLine(to: point)
}
path.close()
border.color.setFill()
path.fill()
}
}
================================================
FILE: Gaikan/UIKit/Layer/Layer.swift
================================================
//
// Layer.swift
// Gaikan
//
// Created by pjechris on 22/11/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
import UIKit
class StyleLayer : CALayer {
let backgroundLayer = BackgroundLayer()
let borderLayer = BorderLayer()
var styleClass: StyleRule! {
didSet {
self.applyStyle()
}
}
override var frame: CGRect {
get { return super.frame }
set {
super.frame = newValue
self.applyStyle()
}
}
override init() {
super.init()
self.setupLayers()
}
override init(layer: Any) {
super.init(layer: layer)
self.setupLayers()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setupLayers()
}
private func setupLayers() {
self.contentsScale = UIScreen.main.scale
self.backgroundLayer.contentsScale = UIScreen.main.scale
self.borderLayer.contentsScale = UIScreen.main.scale
self.addSublayer(self.backgroundLayer)
self.addSublayer(self.borderLayer)
}
override func layoutSublayers() {
self.backgroundLayer.frame = self.frame
self.borderLayer.frame = self.frame
}
func applyStyle() {
guard let style = self.styleClass else {
return
}
self.backgroundLayer.background = style.background.map { Background($0) }
self.borderLayer.border = style.border
}
override var cornerRadius: CGFloat {
didSet {
self.backgroundLayer.cornerRadius = cornerRadius
self.borderLayer.cornerRadius = cornerRadius
}
}
}
================================================
FILE: Gaikan/UIKit/Renderer/ConstraintRenderer.swift
================================================
//
// ConstraintRenderer.swift
// Gaikan
//
// Created by pjechris on 30/08/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
class ConstraintRenderer {
class func render(_ view: UIView, styleRule: StyleRule) {
self.addDimension(styleRule.height, to: view, attribute: .height, relation: .equal)
self.addDimension(styleRule.maxHeight, to: view, attribute: .height, relation: .lessThanOrEqual)
self.addDimension(styleRule.minHeight, to: view, attribute: .height, relation: .greaterThanOrEqual)
self.addDimension(styleRule.width, to: view, attribute: .width, relation: .equal)
self.addDimension(styleRule.maxWidth, to: view, attribute: .width, relation: .lessThanOrEqual)
self.addDimension(styleRule.minWidth, to: view, attribute: .width, relation: .greaterThanOrEqual)
}
fileprivate class func addDimension(_ constraint: Constraint?, to view: UIView, attribute: NSLayoutAttribute, relation: NSLayoutRelation) {
let identifier = "gaikan-\(relation.identifier())\(attribute.identifier().capitalized))"
let index = view.dimensions.index { $0.identifier == identifier }
var layoutConstraint: NSLayoutConstraint
// Remove layoutConstraint if constraint nil but already active (from a previously pass)
guard let constraint = constraint else {
if let index = index {
view.dimensions[index].isActive = false
}
return
}
if let index = index {
layoutConstraint = view.dimensions[index]
}
else {
layoutConstraint = NSLayoutConstraint(item: view,
attribute: attribute,
relatedBy: relation,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 1,
constant: 0)
layoutConstraint.identifier = identifier
view.dimensions.append(layoutConstraint)
}
// Deactivate constraint if priority changing from/to required
if (layoutConstraint.priority != constraint.priority) {
if (constraint.priority == UILayoutPriorityRequired || layoutConstraint.priority == UILayoutPriorityRequired) {
layoutConstraint.isActive = false
}
}
layoutConstraint.constant = CGFloat(constraint.constant)
layoutConstraint.priority = constraint.priority
layoutConstraint.isActive = true
}
}
================================================
FILE: Gaikan/UIKit/Renderer/ViewStyleRenderer.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 30/08/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
internal class ViewStyleRenderer {
final class func render(_ stylable: UIView, styleRule: StyleRule) {
let visible = styleRule.visible ?? true
let corners = styleRule.corners ?? Corners(radius: 0)
stylable.layer.cornerRadius = corners.radius
stylable.clipsToBounds = styleRule.clip
stylable.layer.masksToBounds = styleRule.clip
stylable.layer.transform = styleRule.transform
stylable.tintColor = styleRule.tintColor
stylable.isHidden = !visible
stylable.alpha = CGFloat(styleRule.opacity / 100)
stylable.layoutMargins = styleRule.margin ?? stylable.layoutMargins
if let shadow = styleRule.shadow {
stylable.layer.shadowOpacity = 1
stylable.layer.shadowOffset = shadow.shadowOffset
stylable.layer.shadowRadius = shadow.shadowBlurRadius
stylable.layer.shadowColor = (shadow.shadowColor as? UIColor)?.cgColor
}
else {
stylable.layer.shadowOpacity = 0
}
stylable.styleLayer.styleClass = styleRule
stylable.styleLayer.cornerRadius = corners.radius
ConstraintRenderer.render(stylable, styleRule: styleRule)
}
final class func render(_ stylable: UILabel, styleRule: StyleRule) {
stylable.font = styleRule.font
stylable.textColor = styleRule.color
stylable.lineBreakMode = styleRule.textOverflow ?? .byTruncatingTail
}
final class func render(_ button: UIButton, styleRule: StyleRule) {
if let titleLabel = button.titleLabel {
self.render(titleLabel, styleRule: styleRule)
}
button.setTitleColor(styleRule.color, for: UIControlState())
button.contentEdgeInsets = styleRule.margin ?? button.contentEdgeInsets
}
final class func render(_ textField: UITextField, styleRule: StyleRule) {
textField.textAlignment = styleRule.textAlign ?? .natural
}
final class func render(_ navigationBar: UINavigationBar, titleStyle: StyleRule) {
navigationBar.titleTextAttributes = titleStyle.textAttributes
}
}
================================================
FILE: Gaikan/UIKit/VirtualView.swift
================================================
//
// VirtualView.swift
// Gaikan
//
// Created by Simone Civetta on 17/03/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
open class VirtualView<TargetView: UIView> : NSObject, Stylable {
fileprivate let targetView: TargetView
init(targetView: TargetView) {
self.targetView = targetView
}
open var styleClass: Style? {
didSet { self.computeStyle() }
}
open var styleInline: StyleRule? {
didSet { self.computeStyle() }
}
open var styleState: String? {
didSet { self.computeStyle() }
}
open func updateStyle() {
self.targetView.updateStyle()
}
open static func keyPathsAffectingStyle() -> [String] {
return []
}
}
================================================
FILE: Gaikan.podspec
================================================
Pod::Spec.new do |s|
s.name = "Gaikan"
s.version = "0.9.1"
s.source = { :git => "https://github.com/akane/Gaikan.git",
:tag => s.version.to_s }
s.summary = "Declarative view styling in Swift."
s.description = "Powerful styling capabilities using a declarative DSL in Swift. Inspired by ReactJS and CSS modules."
s.homepage = s.source[:git].to_s
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = 'pjechris', 'akane'
s.ios.deployment_target = "8.0"
s.source_files = "Gaikan/**/*.{swift}"
s.requires_arc = true
s.dependency 'KVOController', '~> 1.x'
end
================================================
FILE: Gaikan.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
420190841C80B4BB00B70169 /* UINavigationBarSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 420190831C80B4BB00B70169 /* UINavigationBarSpec.swift */; };
420190861C80B60F00B70169 /* UINavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 420190851C80B60F00B70169 /* UINavigationBar.swift */; };
42087B221C9AE4B8000606A7 /* VirtualView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42087B211C9AE4B8000606A7 /* VirtualView.swift */; };
490DA08D1D1853FD00A79778 /* Dictionary+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 490DA08C1D1853FD00A79778 /* Dictionary+Helpers.swift */; };
4912E9821BEB905A00C0DA4A /* Background.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4912E9811BEB905A00C0DA4A /* Background.swift */; };
4912E9861BEB9A9800C0DA4A /* Gradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4912E9851BEB9A9800C0DA4A /* Gradient.swift */; };
4917A4C01D17EE1A008B5CB2 /* NSAttributedString+Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4917A4BF1D17EE1A008B5CB2 /* NSAttributedString+Style.swift */; };
492C1B571BE0C9DF000515B9 /* UIControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492C1B501BE0C9DF000515B9 /* UIControl.swift */; };
492C1B591BE0C9DF000515B9 /* UISwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492C1B521BE0C9DF000515B9 /* UISwitch.swift */; };
492C1B5A1BE0C9DF000515B9 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492C1B531BE0C9DF000515B9 /* UIView.swift */; };
492C1B5B1BE0C9DF000515B9 /* ViewStyleRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492C1B561BE0C9DF000515B9 /* ViewStyleRenderer.swift */; };
492C1B601BE0CA59000515B9 /* UILabelSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492C1B5E1BE0CA59000515B9 /* UILabelSpec.swift */; };
492C1B611BE0CA59000515B9 /* UIViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492C1B5F1BE0CA59000515B9 /* UIViewSpec.swift */; };
492C1B631BE0CAD0000515B9 /* UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492C1B621BE0CAD0000515B9 /* UILabel.swift */; };
4932871A1EFA7655009D1326 /* NSShadow+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493287191EFA7655009D1326 /* NSShadow+Helpers.swift */; };
493BB1DC1DF094FC004906C4 /* BackgroundLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493BB1DB1DF094FC004906C4 /* BackgroundLayer.swift */; };
493C1B921D7479E500861CEA /* Constraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493C1B911D7479E500861CEA /* Constraint.swift */; };
495DE8FC1BA580D100DA97BF /* DictionarySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495DE8FB1BA580D100DA97BF /* DictionarySpec.swift */; };
496D38A11CD8EDCB00C8B4EC /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 496D389A1CD8EDCB00C8B4EC /* UIColor.swift */; };
496D38A21CD8EDCB00C8B4EC /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 496D389B1CD8EDCB00C8B4EC /* UIFont.swift */; };
496D38A61CD8EE2800C8B4EC /* SampleTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 496D38A51CD8EE2800C8B4EC /* SampleTheme.swift */; };
497032FB1D75E6410014E0C2 /* ConstraintRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 497032FA1D75E6410014E0C2 /* ConstraintRenderer.swift */; };
4970A8171BD4459300BCB3BA /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4970A8161BD4459300BCB3BA /* Property.swift */; };
4970A81A1BD445DB00BCB3BA /* Border.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4970A8191BD445DB00BCB3BA /* Border.swift */; };
4970A81C1BD4484F00BCB3BA /* StyleSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4970A81B1BD4484F00BCB3BA /* StyleSpec.swift */; };
497AD8981D19339A00FF5498 /* Optional+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 497AD8971D19339A00FF5498 /* Optional+Helpers.swift */; };
498E05391B98362100B4E26B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 498E05381B98362100B4E26B /* AppDelegate.swift */; };
498E053B1B98362100B4E26B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 498E053A1B98362100B4E26B /* ViewController.swift */; };
498E053E1B98362100B4E26B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 498E053C1B98362100B4E26B /* Main.storyboard */; };
498E05401B98362100B4E26B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 498E053F1B98362100B4E26B /* Assets.xcassets */; };
498E05431B98362100B4E26B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 498E05411B98362100B4E26B /* LaunchScreen.storyboard */; };
499081B31DE4EF78000F8855 /* Layer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499081B21DE4EF78000F8855 /* Layer.swift */; };
499943581D7497AB003C510E /* AssociatedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499943531D7497AB003C510E /* AssociatedObject.swift */; };
499943601D7497FA003C510E /* CGPoint+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4999435D1D7497FA003C510E /* CGPoint+Helpers.swift */; };
499943611D7497FA003C510E /* UIColor+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4999435E1D7497FA003C510E /* UIColor+Helpers.swift */; };
499943621D7497FA003C510E /* UIImage+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4999435F1D7497FA003C510E /* UIImage+Helpers.swift */; };
49A4F5581C1A3C7600D2A392 /* StylePseudoState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A4F5571C1A3C7600D2A392 /* StylePseudoState.swift */; };
49B9A23B1D14589200E4DE52 /* StyleRule+DirectAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49B9A23A1D14589200E4DE52 /* StyleRule+DirectAccess.swift */; };
49BE40B51D78565B00FE0818 /* NSLayoutAttribute+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BE40B41D78565B00FE0818 /* NSLayoutAttribute+Helpers.swift */; };
49BE40B71D78566400FE0818 /* NSLayoutRelation+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BE40B61D78566400FE0818 /* NSLayoutRelation+Helpers.swift */; };
49C25A8C1D845A6900E3735C /* ConstraintRendererSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C25A8B1D845A6900E3735C /* ConstraintRendererSpec.swift */; };
49C306551CD8FD2900CABDF4 /* Gradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C306541CD8FD2900CABDF4 /* Gradient.swift */; };
49C306581CD902EC00CABDF4 /* UIView+InterfaceBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C306571CD902EC00CABDF4 /* UIView+InterfaceBuilder.swift */; };
49C8F7E91C1A33F400FF33DC /* StyleState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C8F7E81C1A33F400FF33DC /* StyleState.swift */; };
49CF3E291D0EF48200AF89E6 /* KVOController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49CF3E281D0EF48200AF89E6 /* KVOController.framework */; };
49CF3E2D1D0EF81B00AF89E6 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49CF3E2B1D0EF81B00AF89E6 /* Nimble.framework */; };
49CF3E2E1D0EF81B00AF89E6 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49CF3E2C1D0EF81B00AF89E6 /* Quick.framework */; };
49CF3E2F1D0EF93900AF89E6 /* KVOController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49CF3E281D0EF48200AF89E6 /* KVOController.framework */; };
49CF5F991BA4866B00216E6D /* StyleRuleSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49CF5F981BA4866B00216E6D /* StyleRuleSpec.swift */; };
49D1BF831BDD4A8700348D3D /* CustomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49D1BF821BDD4A8700348D3D /* CustomView.swift */; };
49D389A51D84272800D72B2E /* UIView+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49D389A41D84272800D72B2E /* UIView+Helpers.swift */; };
49DBD9021BCAAF110069B0C2 /* Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49DBD9011BCAAF110069B0C2 /* Style.swift */; };
49E99D491DEF3A77003BF8B4 /* BorderLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E99D481DEF3A77003BF8B4 /* BorderLayer.swift */; };
49EC39681B92FC7D002938E1 /* Gaikan.h in Headers */ = {isa = PBXBuildFile; fileRef = 49EC39671B92FC7D002938E1 /* Gaikan.h */; settings = {ATTRIBUTES = (Public, ); }; };
49EC396F1B92FC7D002938E1 /* Gaikan.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49EC39641B92FC7D002938E1 /* Gaikan.framework */; };
49EC39741B92FC7D002938E1 /* GaikanTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EC39731B92FC7D002938E1 /* GaikanTests.swift */; };
49EC398B1B93085E002938E1 /* StyleRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EC398A1B93085E002938E1 /* StyleRule.swift */; };
49EC39931B9373B2002938E1 /* Stylable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EC39921B9373B2002938E1 /* Stylable.swift */; };
49F78A671DF4245300866F72 /* Side.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49F78A661DF4245300866F72 /* Side.swift */; };
49FD8A651CD16652004F2979 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49FD8A631CD16652004F2979 /* Theme.swift */; };
CAFCDA4F1C592BBC004513D3 /* Corners.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFCDA4E1C592BBC004513D3 /* Corners.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
498E05481B98362800B4E26B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 49EC395B1B92FC7D002938E1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 49EC39631B92FC7D002938E1;
remoteInfo = Gaikan;
};
49EC39701B92FC7D002938E1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 49EC395B1B92FC7D002938E1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 49EC39631B92FC7D002938E1;
remoteInfo = Gaikan;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
420190831C80B4BB00B70169 /* UINavigationBarSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UINavigationBarSpec.swift; sourceTree = "<group>"; };
420190851C80B60F00B70169 /* UINavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UINavigationBar.swift; sourceTree = "<group>"; };
42087B211C9AE4B8000606A7 /* VirtualView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VirtualView.swift; sourceTree = "<group>"; };
490DA08C1D1853FD00A79778 /* Dictionary+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dictionary+Helpers.swift"; sourceTree = "<group>"; };
4912E9811BEB905A00C0DA4A /* Background.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Background.swift; sourceTree = "<group>"; };
4912E9851BEB9A9800C0DA4A /* Gradient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Gradient.swift; sourceTree = "<group>"; };
4917A4BF1D17EE1A008B5CB2 /* NSAttributedString+Style.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Style.swift"; sourceTree = "<group>"; };
492C1B501BE0C9DF000515B9 /* UIControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIControl.swift; sourceTree = "<group>"; };
492C1B521BE0C9DF000515B9 /* UISwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UISwitch.swift; sourceTree = "<group>"; };
492C1B531BE0C9DF000515B9 /* UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = "<group>"; };
492C1B561BE0C9DF000515B9 /* ViewStyleRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewStyleRenderer.swift; sourceTree = "<group>"; };
492C1B5E1BE0CA59000515B9 /* UILabelSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UILabelSpec.swift; sourceTree = "<group>"; };
492C1B5F1BE0CA59000515B9 /* UIViewSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewSpec.swift; sourceTree = "<group>"; };
492C1B621BE0CAD0000515B9 /* UILabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UILabel.swift; sourceTree = "<group>"; };
493287191EFA7655009D1326 /* NSShadow+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSShadow+Helpers.swift"; sourceTree = "<group>"; };
493BB1DB1DF094FC004906C4 /* BackgroundLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackgroundLayer.swift; sourceTree = "<group>"; };
493C1B911D7479E500861CEA /* Constraint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constraint.swift; sourceTree = "<group>"; };
495DE8FB1BA580D100DA97BF /* DictionarySpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionarySpec.swift; sourceTree = "<group>"; };
496D389A1CD8EDCB00C8B4EC /* UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = "<group>"; };
496D389B1CD8EDCB00C8B4EC /* UIFont.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
496D38A51CD8EE2800C8B4EC /* SampleTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleTheme.swift; sourceTree = "<group>"; };
497032FA1D75E6410014E0C2 /* ConstraintRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConstraintRenderer.swift; sourceTree = "<group>"; };
4970A8161BD4459300BCB3BA /* Property.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Property.swift; sourceTree = "<group>"; };
4970A8191BD445DB00BCB3BA /* Border.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Border.swift; sourceTree = "<group>"; };
4970A81B1BD4484F00BCB3BA /* StyleSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StyleSpec.swift; sourceTree = "<group>"; };
497AD8971D19339A00FF5498 /* Optional+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Optional+Helpers.swift"; sourceTree = "<group>"; };
498E05361B98362100B4E26B /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
498E05381B98362100B4E26B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
498E053A1B98362100B4E26B /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
498E053D1B98362100B4E26B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
498E053F1B98362100B4E26B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
498E05421B98362100B4E26B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
498E05441B98362100B4E26B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
499081B21DE4EF78000F8855 /* Layer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Layer.swift; sourceTree = "<group>"; };
499943531D7497AB003C510E /* AssociatedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssociatedObject.swift; sourceTree = "<group>"; };
4999435D1D7497FA003C510E /* CGPoint+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGPoint+Helpers.swift"; sourceTree = "<group>"; };
4999435E1D7497FA003C510E /* UIColor+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Helpers.swift"; sourceTree = "<group>"; };
4999435F1D7497FA003C510E /* UIImage+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Helpers.swift"; sourceTree = "<group>"; };
49A4F5571C1A3C7600D2A392 /* StylePseudoState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StylePseudoState.swift; sourceTree = "<group>"; };
49B9A23A1D14589200E4DE52 /* StyleRule+DirectAccess.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StyleRule+DirectAccess.swift"; sourceTree = "<group>"; };
49BE40B41D78565B00FE0818 /* NSLayoutAttribute+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSLayoutAttribute+Helpers.swift"; sourceTree = "<group>"; };
49BE40B61D78566400FE0818 /* NSLayoutRelation+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSLayoutRelation+Helpers.swift"; sourceTree = "<group>"; };
49C25A8B1D845A6900E3735C /* ConstraintRendererSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConstraintRendererSpec.swift; sourceTree = "<group>"; };
49C306541CD8FD2900CABDF4 /* Gradient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Gradient.swift; sourceTree = "<group>"; };
49C306571CD902EC00CABDF4 /* UIView+InterfaceBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+InterfaceBuilder.swift"; sourceTree = "<group>"; };
49C8F7E81C1A33F400FF33DC /* StyleState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StyleState.swift; sourceTree = "<group>"; };
49CF3E281D0EF48200AF89E6 /* KVOController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = KVOController.framework; path = Carthage/Build/iOS/KVOController.framework; sourceTree = "<group>"; };
49CF3E2B1D0EF81B00AF89E6 /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = Carthage/Build/iOS/Nimble.framework; sourceTree = "<group>"; };
49CF3E2C1D0EF81B00AF89E6 /* Quick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quick.framework; path = Carthage/Build/iOS/Quick.framework; sourceTree = "<group>"; };
49CF5F981BA4866B00216E6D /* StyleRuleSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StyleRuleSpec.swift; sourceTree = "<group>"; };
49D1BF821BDD4A8700348D3D /* CustomView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomView.swift; sourceTree = "<group>"; };
49D389A41D84272800D72B2E /* UIView+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Helpers.swift"; sourceTree = "<group>"; };
49DBD9011BCAAF110069B0C2 /* Style.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Style.swift; sourceTree = "<group>"; };
49E99D481DEF3A77003BF8B4 /* BorderLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BorderLayer.swift; sourceTree = "<group>"; };
49EC39641B92FC7D002938E1 /* Gaikan.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Gaikan.framework; sourceTree = BUILT_PRODUCTS_DIR; };
49EC39671B92FC7D002938E1 /* Gaikan.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Gaikan.h; sourceTree = "<group>"; };
49EC39691B92FC7D002938E1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
49EC396E1B92FC7D002938E1 /* GaikanTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GaikanTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
49EC39731B92FC7D002938E1 /* GaikanTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GaikanTests.swift; sourceTree = "<group>"; };
49EC39751B92FC7D002938E1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
49EC398A1B93085E002938E1 /* StyleRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StyleRule.swift; sourceTree = "<group>"; };
49EC39921B9373B2002938E1 /* Stylable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stylable.swift; sourceTree = "<group>"; };
49F78A661DF4245300866F72 /* Side.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Side.swift; sourceTree = "<group>"; };
49FD8A631CD16652004F2979 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
CAFCDA4E1C592BBC004513D3 /* Corners.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Corners.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
498E05331B98362100B4E26B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
49CF3E291D0EF48200AF89E6 /* KVOController.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
49EC39601B92FC7D002938E1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
49EC396B1B92FC7D002938E1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
49CF3E2F1D0EF93900AF89E6 /* KVOController.framework in Frameworks */,
49CF3E2D1D0EF81B00AF89E6 /* Nimble.framework in Frameworks */,
49CF3E2E1D0EF81B00AF89E6 /* Quick.framework in Frameworks */,
49EC396F1B92FC7D002938E1 /* Gaikan.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
490AD3DA1BA1CD4A0078F2DB /* Style */ = {
isa = PBXGroup;
children = (
49CF5F981BA4866B00216E6D /* StyleRuleSpec.swift */,
4970A81B1BD4484F00BCB3BA /* StyleSpec.swift */,
);
path = Style;
sourceTree = "<group>";
};
4917A4BE1D17EE08008B5CB2 /* Helpers */ = {
isa = PBXGroup;
children = (
493287191EFA7655009D1326 /* NSShadow+Helpers.swift */,
499943531D7497AB003C510E /* AssociatedObject.swift */,
4999435D1D7497FA003C510E /* CGPoint+Helpers.swift */,
490DA08C1D1853FD00A79778 /* Dictionary+Helpers.swift */,
4917A4BF1D17EE1A008B5CB2 /* NSAttributedString+Style.swift */,
49BE40B41D78565B00FE0818 /* NSLayoutAttribute+Helpers.swift */,
49BE40B61D78566400FE0818 /* NSLayoutRelation+Helpers.swift */,
497AD8971D19339A00FF5498 /* Optional+Helpers.swift */,
4999435E1D7497FA003C510E /* UIColor+Helpers.swift */,
4999435F1D7497FA003C510E /* UIImage+Helpers.swift */,
49D389A41D84272800D72B2E /* UIView+Helpers.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
492C1B421BE0C81E000515B9 /* UIKit */ = {
isa = PBXGroup;
children = (
499081B11DE4EF6F000F8855 /* Layer */,
492C1B4F1BE0C9DF000515B9 /* Extension */,
492C1B551BE0C9DF000515B9 /* Renderer */,
42087B211C9AE4B8000606A7 /* VirtualView.swift */,
);
path = UIKit;
sourceTree = "<group>";
};
492C1B4F1BE0C9DF000515B9 /* Extension */ = {
isa = PBXGroup;
children = (
492C1B501BE0C9DF000515B9 /* UIControl.swift */,
492C1B621BE0CAD0000515B9 /* UILabel.swift */,
420190851C80B60F00B70169 /* UINavigationBar.swift */,
492C1B521BE0C9DF000515B9 /* UISwitch.swift */,
492C1B531BE0C9DF000515B9 /* UIView.swift */,
);
path = Extension;
sourceTree = "<group>";
};
492C1B551BE0C9DF000515B9 /* Renderer */ = {
isa = PBXGroup;
children = (
492C1B561BE0C9DF000515B9 /* ViewStyleRenderer.swift */,
497032FA1D75E6410014E0C2 /* ConstraintRenderer.swift */,
);
path = Renderer;
sourceTree = "<group>";
};
492C1B5C1BE0CA59000515B9 /* UIKit */ = {
isa = PBXGroup;
children = (
492C1B5D1BE0CA59000515B9 /* Extension */,
49C25A8A1D845A4F00E3735C /* Renderer */,
);
path = UIKit;
sourceTree = "<group>";
};
492C1B5D1BE0CA59000515B9 /* Extension */ = {
isa = PBXGroup;
children = (
492C1B5E1BE0CA59000515B9 /* UILabelSpec.swift */,
420190831C80B4BB00B70169 /* UINavigationBarSpec.swift */,
492C1B5F1BE0CA59000515B9 /* UIViewSpec.swift */,
);
path = Extension;
sourceTree = "<group>";
};
495DE8F91BA580C200DA97BF /* Swift */ = {
isa = PBXGroup;
children = (
495DE8FA1BA580C200DA97BF /* Extension */,
);
path = Swift;
sourceTree = "<group>";
};
495DE8FA1BA580C200DA97BF /* Extension */ = {
isa = PBXGroup;
children = (
495DE8FB1BA580D100DA97BF /* DictionarySpec.swift */,
);
path = Extension;
sourceTree = "<group>";
};
496D38991CD8EDCB00C8B4EC /* Theme */ = {
isa = PBXGroup;
children = (
496D389A1CD8EDCB00C8B4EC /* UIColor.swift */,
496D389B1CD8EDCB00C8B4EC /* UIFont.swift */,
496D38A51CD8EE2800C8B4EC /* SampleTheme.swift */,
49C306541CD8FD2900CABDF4 /* Gradient.swift */,
);
path = Theme;
sourceTree = "<group>";
};
4970A8151BD4455900BCB3BA /* Property */ = {
isa = PBXGroup;
children = (
4912E9851BEB9A9800C0DA4A /* Gradient.swift */,
4970A8161BD4459300BCB3BA /* Property.swift */,
4970A8181BD445DB00BCB3BA /* Value */,
);
path = Property;
sourceTree = "<group>";
};
4970A8181BD445DB00BCB3BA /* Value */ = {
isa = PBXGroup;
children = (
4970A8191BD445DB00BCB3BA /* Border.swift */,
4912E9811BEB905A00C0DA4A /* Background.swift */,
CAFCDA4E1C592BBC004513D3 /* Corners.swift */,
493C1B911D7479E500861CEA /* Constraint.swift */,
49F78A661DF4245300866F72 /* Side.swift */,
);
path = Value;
sourceTree = "<group>";
};
498E05371B98362100B4E26B /* Sample */ = {
isa = PBXGroup;
children = (
496D38991CD8EDCB00C8B4EC /* Theme */,
498E05381B98362100B4E26B /* AppDelegate.swift */,
498E053A1B98362100B4E26B /* ViewController.swift */,
498E053C1B98362100B4E26B /* Main.storyboard */,
498E053F1B98362100B4E26B /* Assets.xcassets */,
498E05411B98362100B4E26B /* LaunchScreen.storyboard */,
498E05441B98362100B4E26B /* Info.plist */,
49D1BF821BDD4A8700348D3D /* CustomView.swift */,
);
path = Sample;
sourceTree = "<group>";
};
499081B11DE4EF6F000F8855 /* Layer */ = {
isa = PBXGroup;
children = (
499081B21DE4EF78000F8855 /* Layer.swift */,
49E99D481DEF3A77003BF8B4 /* BorderLayer.swift */,
493BB1DB1DF094FC004906C4 /* BackgroundLayer.swift */,
);
path = Layer;
sourceTree = "<group>";
};
49C25A8A1D845A4F00E3735C /* Renderer */ = {
isa = PBXGroup;
children = (
49C25A8B1D845A6900E3735C /* ConstraintRendererSpec.swift */,
);
path = Renderer;
sourceTree = "<group>";
};
49C306561CD902D800CABDF4 /* InterfaceBuilder */ = {
isa = PBXGroup;
children = (
49C306571CD902EC00CABDF4 /* UIView+InterfaceBuilder.swift */,
);
path = InterfaceBuilder;
sourceTree = "<group>";
};
49EC395A1B92FC7D002938E1 = {
isa = PBXGroup;
children = (
49CF3E2B1D0EF81B00AF89E6 /* Nimble.framework */,
49CF3E2C1D0EF81B00AF89E6 /* Quick.framework */,
49CF3E281D0EF48200AF89E6 /* KVOController.framework */,
49EC39661B92FC7D002938E1 /* Gaikan */,
49EC39721B92FC7D002938E1 /* GaikanTests */,
498E05371B98362100B4E26B /* Sample */,
49EC39651B92FC7D002938E1 /* Products */,
);
sourceTree = "<group>";
};
49EC39651B92FC7D002938E1 /* Products */ = {
isa = PBXGroup;
children = (
49EC39641B92FC7D002938E1 /* Gaikan.framework */,
49EC396E1B92FC7D002938E1 /* GaikanTests.xctest */,
498E05361B98362100B4E26B /* Sample.app */,
);
name = Products;
sourceTree = "<group>";
};
49EC39661B92FC7D002938E1 /* Gaikan */ = {
isa = PBXGroup;
children = (
49EC39671B92FC7D002938E1 /* Gaikan.h */,
49EC39691B92FC7D002938E1 /* Info.plist */,
4917A4BE1D17EE08008B5CB2 /* Helpers */,
49C306561CD902D800CABDF4 /* InterfaceBuilder */,
4970A8151BD4455900BCB3BA /* Property */,
49EC397E1B92FF2F002938E1 /* Style */,
49FD8A611CD16652004F2979 /* Theme */,
492C1B421BE0C81E000515B9 /* UIKit */,
);
path = Gaikan;
sourceTree = "<group>";
};
49EC39721B92FC7D002938E1 /* GaikanTests */ = {
isa = PBXGroup;
children = (
49EC39731B92FC7D002938E1 /* GaikanTests.swift */,
49EC39751B92FC7D002938E1 /* Info.plist */,
490AD3DA1BA1CD4A0078F2DB /* Style */,
495DE8F91BA580C200DA97BF /* Swift */,
492C1B5C1BE0CA59000515B9 /* UIKit */,
);
path = GaikanTests;
sourceTree = "<group>";
};
49EC397E1B92FF2F002938E1 /* Style */ = {
isa = PBXGroup;
children = (
49EC39921B9373B2002938E1 /* Stylable.swift */,
49DBD9011BCAAF110069B0C2 /* Style.swift */,
49A4F5571C1A3C7600D2A392 /* StylePseudoState.swift */,
49EC398A1B93085E002938E1 /* StyleRule.swift */,
49C8F7E81C1A33F400FF33DC /* StyleState.swift */,
49B9A23A1D14589200E4DE52 /* StyleRule+DirectAccess.swift */,
);
path = Style;
sourceTree = "<group>";
};
49FD8A611CD16652004F2979 /* Theme */ = {
isa = PBXGroup;
children = (
49FD8A631CD16652004F2979 /* Theme.swift */,
);
path = Theme;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
49EC39611B92FC7D002938E1 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
49EC39681B92FC7D002938E1 /* Gaikan.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
498E05351B98362100B4E26B /* Sample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 498E05451B98362100B4E26B /* Build configuration list for PBXNativeTarget "Sample" */;
buildPhases = (
498E05321B98362100B4E26B /* Sources */,
498E05331B98362100B4E26B /* Frameworks */,
498E05341B98362100B4E26B /* Resources */,
49CF3E271D0EF41A00AF89E6 /* Carthage */,
);
buildRules = (
);
dependencies = (
498E05491B98362800B4E26B /* PBXTargetDependency */,
);
name = Sample;
productName = Sample;
productReference = 498E05361B98362100B4E26B /* Sample.app */;
productType = "com.apple.product-type.application";
};
49EC39631B92FC7D002938E1 /* Gaikan */ = {
isa = PBXNativeTarget;
buildConfigurationList = 49EC39781B92FC7D002938E1 /* Build configuration list for PBXNativeTarget "Gaikan" */;
buildPhases = (
49EC395F1B92FC7D002938E1 /* Sources */,
49EC39601B92FC7D002938E1 /* Frameworks */,
49EC39611B92FC7D002938E1 /* Headers */,
49EC39621B92FC7D002938E1 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Gaikan;
productName = Gaikan;
productReference = 49EC39641B92FC7D002938E1 /* Gaikan.framework */;
productType = "com.apple.product-type.framework";
};
49EC396D1B92FC7D002938E1 /* GaikanTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 49EC397B1B92FC7D002938E1 /* Build configuration list for PBXNativeTarget "GaikanTests" */;
buildPhases = (
49EC396A1B92FC7D002938E1 /* Sources */,
49EC396B1B92FC7D002938E1 /* Frameworks */,
49EC396C1B92FC7D002938E1 /* Resources */,
49CF3E2A1D0EF7E900AF89E6 /* Carthage */,
);
buildRules = (
);
dependencies = (
49EC39711B92FC7D002938E1 /* PBXTargetDependency */,
);
name = GaikanTests;
productName = GaikanTests;
productReference = 49EC396E1B92FC7D002938E1 /* GaikanTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
49EC395B1B92FC7D002938E1 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0710;
LastUpgradeCheck = 0810;
ORGANIZATIONNAME = fr.akane;
TargetAttributes = {
498E05351B98362100B4E26B = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
};
49EC39631B92FC7D002938E1 = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0810;
};
49EC396D1B92FC7D002938E1 = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0810;
};
};
};
buildConfigurationList = 49EC395E1B92FC7D002938E1 /* Build configuration list for PBXProject "Gaikan" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 49EC395A1B92FC7D002938E1;
productRefGroup = 49EC39651B92FC7D002938E1 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
49EC39631B92FC7D002938E1 /* Gaikan */,
49EC396D1B92FC7D002938E1 /* GaikanTests */,
498E05351B98362100B4E26B /* Sample */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
498E05341B98362100B4E26B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
498E05431B98362100B4E26B /* LaunchScreen.storyboard in Resources */,
498E05401B98362100B4E26B /* Assets.xcassets in Resources */,
498E053E1B98362100B4E26B /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
49EC39621B92FC7D002938E1 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
49EC396C1B92FC7D002938E1 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
49CF3E271D0EF41A00AF89E6 /* Carthage */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(SRCROOT)/Carthage/Build/iOS/KVOController.framework",
);
name = Carthage;
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/local/bin/carthage copy-frameworks";
};
49CF3E2A1D0EF7E900AF89E6 /* Carthage */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(SRCROOT)/Carthage/Build/iOS/Nimble.framework",
"$(SRCROOT)/Carthage/Build/iOS/Quick.framework",
"$(SRCROOT)/Carthage/Build/iOS/KVOController.framework",
);
name = Carthage;
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/local/bin/carthage copy-frameworks";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
498E05321B98362100B4E26B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
49D1BF831BDD4A8700348D3D /* CustomView.swift in Sources */,
496D38A61CD8EE2800C8B4EC /* SampleTheme.swift in Sources */,
496D38A21CD8EDCB00C8B4EC /* UIFont.swift in Sources */,
49C306551CD8FD2900CABDF4 /* Gradient.swift in Sources */,
498E053B1B98362100B4E26B /* ViewController.swift in Sources */,
498E05391B98362100B4E26B /* AppDelegate.swift in Sources */,
496D38A11CD8EDCB00C8B4EC /* UIColor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
49EC395F1B92FC7D002938E1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
499943601D7497FA003C510E /* CGPoint+Helpers.swift in Sources */,
4970A81A1BD445DB00BCB3BA /* Border.swift in Sources */,
4932871A1EFA7655009D1326 /* NSShadow+Helpers.swift in Sources */,
49F78A671DF4245300866F72 /* Side.swift in Sources */,
49EC398B1B93085E002938E1 /* StyleRule.swift in Sources */,
49C306581CD902EC00CABDF4 /* UIView+InterfaceBuilder.swift in Sources */,
49C8F7E91C1A33F400FF33DC /* StyleState.swift in Sources */,
49EC39931B9373B2002938E1 /* Stylable.swift in Sources */,
492C1B5B1BE0C9DF000515B9 /* ViewStyleRenderer.swift in Sources */,
49BE40B51D78565B00FE0818 /* NSLayoutAttribute+Helpers.swift in Sources */,
497032FB1D75E6410014E0C2 /* ConstraintRenderer.swift in Sources */,
493C1B921D7479E500861CEA /* Constraint.swift in Sources */,
490DA08D1D1853FD00A79778 /* Dictionary+Helpers.swift in Sources */,
492C1B631BE0CAD0000515B9 /* UILabel.swift in Sources */,
492C1B571BE0C9DF000515B9 /* UIControl.swift in Sources */,
493BB1DC1DF094FC004906C4 /* BackgroundLayer.swift in Sources */,
499081B31DE4EF78000F8855 /* Layer.swift in Sources */,
49B9A23B1D14589200E4DE52 /* StyleRule+DirectAccess.swift in Sources */,
49FD8A651CD16652004F2979 /* Theme.swift in Sources */,
49A4F5581C1A3C7600D2A392 /* StylePseudoState.swift in Sources */,
49E99D491DEF3A77003BF8B4 /* BorderLayer.swift in Sources */,
4917A4C01D17EE1A008B5CB2 /* NSAttributedString+Style.swift in Sources */,
499943581D7497AB003C510E /* AssociatedObject.swift in Sources */,
4970A8171BD4459300BCB3BA /* Property.swift in Sources */,
49BE40B71D78566400FE0818 /* NSLayoutRelation+Helpers.swift in Sources */,
4912E9821BEB905A00C0DA4A /* Background.swift in Sources */,
420190861C80B60F00B70169 /* UINavigationBar.swift in Sources */,
492C1B5A1BE0C9DF000515B9 /* UIView.swift in Sources */,
49DBD9021BCAAF110069B0C2 /* Style.swift in Sources */,
492C1B591BE0C9DF000515B9 /* UISwitch.swift in Sources */,
499943611D7497FA003C510E /* UIColor+Helpers.swift in Sources */,
497AD8981D19339A00FF5498 /* Optional+Helpers.swift in Sources */,
49D389A51D84272800D72B2E /* UIView+Helpers.swift in Sources */,
42087B221C9AE4B8000606A7 /* VirtualView.swift in Sources */,
499943621D7497FA003C510E /* UIImage+Helpers.swift in Sources */,
4912E9861BEB9A9800C0DA4A /* Gradient.swift in Sources */,
CAFCDA4F1C592BBC004513D3 /* Corners.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
49EC396A1B92FC7D002938E1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
49CF5F991BA4866B00216E6D /* StyleRuleSpec.swift in Sources */,
492C1B601BE0CA59000515B9 /* UILabelSpec.swift in Sources */,
495DE8FC1BA580D100DA97BF /* DictionarySpec.swift in Sources */,
492C1B611BE0CA59000515B9 /* UIViewSpec.swift in Sources */,
420190841C80B4BB00B70169 /* UINavigationBarSpec.swift in Sources */,
4970A81C1BD4484F00BCB3BA /* StyleSpec.swift in Sources */,
49C25A8C1D845A6900E3735C /* ConstraintRendererSpec.swift in Sources */,
49EC39741B92FC7D002938E1 /* GaikanTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
498E05491B98362800B4E26B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 49EC39631B92FC7D002938E1 /* Gaikan */;
targetProxy = 498E05481B98362800B4E26B /* PBXContainerItemProxy */;
};
49EC39711B92FC7D002938E1 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 49EC39631B92FC7D002938E1 /* Gaikan */;
targetProxy = 49EC39701B92FC7D002938E1 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
498E053C1B98362100B4E26B /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
498E053D1B98362100B4E26B /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
498E05411B98362100B4E26B /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
498E05421B98362100B4E26B /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
498E05461B98362100B4E26B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = Sample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Akane.Sample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
};
name = Debug;
};
498E05471B98362100B4E26B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = Sample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Akane.Sample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
};
name = Release;
};
49EC39761B92FC7D002938E1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
49EC39771B92FC7D002938E1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
49EC39791B92FC7D002938E1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = Gaikan/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Akane.Gaikan;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
49EC397A1B92FC7D002938E1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = Gaikan/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Akane.Gaikan;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
49EC397C1B92FC7D002938E1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = GaikanTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Akane.GaikanTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
49EC397D1B92FC7D002938E1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = GaikanTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Akane.GaikanTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
498E05451B98362100B4E26B /* Build configuration list for PBXNativeTarget "Sample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
498E05461B98362100B4E26B /* Debug */,
498E05471B98362100B4E26B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
49EC395E1B92FC7D002938E1 /* Build configuration list for PBXProject "Gaikan" */ = {
isa = XCConfigurationList;
buildConfigurations = (
49EC39761B92FC7D002938E1 /* Debug */,
49EC39771B92FC7D002938E1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
49EC39781B92FC7D002938E1 /* Build configuration list for PBXNativeTarget "Gaikan" */ = {
isa = XCConfigurationList;
buildConfigurations = (
49EC39791B92FC7D002938E1 /* Debug */,
49EC397A1B92FC7D002938E1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
49EC397B1B92FC7D002938E1 /* Build configuration list for PBXNativeTarget "GaikanTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
49EC397C1B92FC7D002938E1 /* Debug */,
49EC397D1B92FC7D002938E1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 49EC395B1B92FC7D002938E1 /* Project object */;
}
================================================
FILE: Gaikan.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Gaikan.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: Gaikan.xcodeproj/xcshareddata/xcschemes/Gaikan.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "49EC39631B92FC7D002938E1"
BuildableName = "Gaikan.framework"
BlueprintName = "Gaikan"
ReferencedContainer = "container:Gaikan.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "49EC396D1B92FC7D002938E1"
BuildableName = "GaikanTests.xctest"
BlueprintName = "GaikanTests"
ReferencedContainer = "container:Gaikan.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "49EC39631B92FC7D002938E1"
BuildableName = "Gaikan.framework"
BlueprintName = "Gaikan"
ReferencedContainer = "container:Gaikan.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "49EC39631B92FC7D002938E1"
BuildableName = "Gaikan.framework"
BlueprintName = "Gaikan"
ReferencedContainer = "container:Gaikan.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "49EC39631B92FC7D002938E1"
BuildableName = "Gaikan.framework"
BlueprintName = "Gaikan"
ReferencedContainer = "container:Gaikan.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: Gaikan.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Gaikan.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: GaikanTests/GaikanTests.swift
================================================
//
// GaikanTests.swift
// GaikanTests
//
// Created by JC on 30/08/15.
// Copyright © 2015 fr.akane. All rights reserved.
//
import XCTest
@testable import Gaikan
class GaikanTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
================================================
FILE: GaikanTests/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
================================================
FILE: GaikanTests/Style/StyleRuleSpec.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 12/09/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Quick
import Nimble
import Gaikan
class StyleRuleSpec: QuickSpec {
override func spec() {
var style: StyleRule!
describe("init") {
context("when passing block") {
beforeEach {
style = StyleRule() { (style: inout StyleRule) -> () in
style.color = UIColor.blue
}
}
it("should initialize color") {
expect(style.color) == UIColor.blue
}
}
}
describe("extends") {
beforeEach {
style = [ .color: UIColor.blue, .tintColor: nil ]
}
context("when extending properties") {
it("it should take new value") {
let newStyle: StyleRule = [ .color: UIColor.black ]
expect(newStyle.extends(style).color) == UIColor.black
}
}
context("when adding properties") {
it("should be added to style") {
let font = UIFont.systemFont(ofSize:22)
let newStyle: StyleRule = [ .font: font ]
expect(newStyle.extends(style).font) == font
}
}
context("when nullyfing a property") {
it("it should be nil") {
var newStyle: StyleRule = [ .color: nil ]
newStyle.extends(style)
expect(newStyle.color).to(beNil())
}
}
context("multiple styles") {
context("with a nil style") {
it("should merge valid ones") {
var newStyle: StyleRule = [:]
newStyle = newStyle.extends(nil, style)
expect(newStyle.color) == UIColor.blue
}
it("should add all properties") {
var newStyle: StyleRule = [:]
newStyle = newStyle.extends(style, [ .tintColor: UIColor.green ])
expect(newStyle.color) == UIColor.blue
expect(newStyle.tintColor) == UIColor.green
}
}
}
}
}
}
================================================
FILE: GaikanTests/Style/StyleSpec.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 18/10/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Quick
import Nimble
@testable import Gaikan
class StyleSpec: QuickSpec {
override func spec() {
var style: Style!
beforeEach {
style = Style() { (style: inout StyleRule) in
style.color = UIColor.blue
}
}
describe("state") {
context("when pseudo class does not exist yet") {
it("should be nil") {
expect(style[.highlighted]).to(beNil())
}
it("should add it") {
style = style.state(.highlighted) { (style: inout StyleRule) -> () in
}
expect(style[.highlighted]).toNot(beNil())
}
it("should not be merged with .Normal") {
style = style.state(.highlighted) { (style: inout StyleRule) -> () in
}
expect(style[.highlighted]?.color).to(beNil())
}
}
context("when pseudo class exist") {
beforeEach {
style = style.state(.highlighted) { (style: inout StyleRule) -> () in
style.color = .green
}
}
it("should replace it") {
style = style.state(.highlighted) { (style: inout StyleRule) -> () in
}
expect(style[.highlighted]?.color).to(beNil())
}
}
}
}
}
================================================
FILE: GaikanTests/Swift/Extension/DictionarySpec.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 12/09/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Quick
import Nimble
@testable import Gaikan
class DictionarySpec: QuickSpec {
override func spec() {
describe("merge") {
var dictionary1: [String:String?]!
context("when value is replaced") {
context("with nil") {
beforeEach {
let dictionary2: [String:String?] = [ "hello": nil ]
dictionary1 = [ "foo": "bar", "hello": "world" ]
dictionary1.gaikan_merge(dictionary2)
}
it("should exist") {
expect(dictionary1["hello"]).toNot(beNil())
}
it("should CONTAIN nil") {
expect(dictionary1["hello"]!).to(beNil())
}
}
}
context("when value is added") {
context("with nil") {
beforeEach {
let dictionary2: [String:String?] = [ "hello": nil ]
dictionary1 = [ "foo": "bar" ]
dictionary1.gaikan_merge(dictionary2)
}
it("should exist") {
expect(dictionary1["hello"]).toNot(beNil())
}
it("should CONTAIN nil") {
expect(dictionary1["hello"]!).to(beNil())
}
}
}
}
}
}
================================================
FILE: GaikanTests/UIKit/Extension/UILabelSpec.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 11/09/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Quick
import Nimble
import Gaikan
class UILabelSpec: QuickSpec {
override func spec() {
var label: UILabel!
beforeEach {
label = UILabel()
}
describe("styleInline") {
var style: StyleRule!
context("when giving style") {
it("should inherit view styles") {
style = [ .tintColor: UIColor.blue ]
label.styleInline = style
expect(label.tintColor) == UIColor.blue
}
it("should apply color") {
style = [ .color: UIColor.red ]
label.styleInline = style
expect(label.textColor) == UIColor.red
}
}
}
}
}
================================================
FILE: GaikanTests/UIKit/Extension/UINavigationBarSpec.swift
================================================
//
// This file is part of Gaikan
//
// Created by Simone Civetta on 26/02/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Quick
import Nimble
import Gaikan
class UINavigationBarSpec: QuickSpec {
override func spec() {
var navigationBar: UINavigationBar!
beforeEach {
navigationBar = UINavigationBar()
}
describe("styleInline") {
var style: StyleRule!
context("when giving style") {
it("should inherit view styles") {
style = [ .tintColor: UIColor.blue ]
navigationBar.styleInline = style
expect(navigationBar.tintColor) == UIColor.blue
}
it("should apply a title font") {
style = [ .font: UIFont.systemFont(ofSize: 42.0) ]
navigationBar.titleStyle.styleInline = style
expect(navigationBar.titleTextAttributes![NSFontAttributeName] as? UIFont) == UIFont.systemFont(ofSize: 42.0)
}
it("should apply a foreground color to the title") {
style = [ .color: UIColor.blue ]
navigationBar.titleStyle.styleInline = style
expect(navigationBar.titleTextAttributes![NSForegroundColorAttributeName] as? UIColor) == UIColor.blue
}
it("should apply a shadow to the title") {
let shadow = NSShadow()
shadow.shadowOffset = CGSize(width: 2, height: 3)
style = [ .textShadow: shadow ]
navigationBar.titleStyle.styleInline = style
expect(navigationBar.titleTextAttributes![NSShadowAttributeName] as? NSShadow) == shadow
}
}
}
}
}
================================================
FILE: GaikanTests/UIKit/Extension/UIViewSpec.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 10/09/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Quick
import Nimble
@testable import Gaikan
class UIViewSpec: QuickSpec {
override func spec() {
var view: UIView!
beforeEach {
view = UIView()
}
describe("styleInline") {
var style: StyleRule!
context("when giving style") {
it("should apply tintColor") {
style = [ .tintColor: UIColor.red ]
view.styleInline = style
expect(view.tintColor) == UIColor.red
}
it("should apply border") {
let border = Border(all: (width: 3, color: UIColor.black))
style = [ .border: border]
view.styleInline = style
expect(view.styleLayer.borderLayer.border) == border
}
it("should apply visible") {
style = [ .visible: false ]
view.styleInline = style
expect(view.isHidden) == true
}
}
}
describe("styleState") {
var style: Style!
beforeEach {
style = Style() { (styleRule:inout StyleRule) in
styleRule.tintColor = UIColor.red
}
.state("newState", [.tintColor: UIColor.blue])
}
context("when setting") {
beforeEach {
view.styleClass = style
view.styleState = "newState"
}
it("should apply state tintColor") {
expect(view.tintColor) == UIColor.blue
}
}
}
}
}
================================================
FILE: GaikanTests/UIKit/Renderer/ConstraintRendererSpec.swift
================================================
//
// ConstraintRendererSpec.swift
// Gaikan
//
// Created by pjechris on 10/09/16.
// Copyright © 2016 fr.akane. All rights reserved.
//
import Foundation
import Nimble
import Quick
@testable import Gaikan
class ConstraintRendererSpec : QuickSpec {
override func spec() {
var view: UIView!
beforeEach {
view = UIView()
}
describe("render") {
var style: StyleRule!
context("style") {
beforeEach {
style = StyleRule()
style.width = 42
ConstraintRenderer.render(view, styleRule: style)
}
it("adds constraint") {
expect(view.constraints.count) == 1
}
context("changed") {
var newStyle = StyleRule()
beforeEach {
newStyle.width = 32
ConstraintRenderer.render(view, styleRule: newStyle)
}
it("keeps constraint") {
expect(view.constraints.count) == 1
}
it("applies changed constraint") {
expect(view.constraints.first?.constant) == CGFloat(newStyle.width!.constant)
}
}
context("removed") {
beforeEach {
ConstraintRenderer.render(view, styleRule: StyleRule())
}
it("removes constraint") {
expect(view.constraints.count) == 0
}
}
}
context("removed constraint") {
beforeEach {
style = StyleRule()
style.width = 50
}
}
}
}
}
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015 akane
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Podfile
================================================
platform :ios, '9.0'
target 'Gaikan' do
use_frameworks!
pod 'KVOController'
target 'GaikanTests' do
inherit! :search_paths
pod 'Nimble'
pod 'Quick'
end
end
================================================
FILE: README.md
================================================
<h1><img src="Doc/Screen/logo.png" width="550" alt="Gaikan" /></h1>
[](https://img.shields.io/cocoapods/v/Gaikan.svg)
[](https://github.com/Carthage/Carthage)
[](https://travis-ci.org/akane/Gaikan)
Gaikan gives you powerful styling capabilities using a declarative DSL in Swift.
_Inspired by_ <a href="https://speakerdeck.com/vjeux/react-css-in-js">React: CSS in JS</a> and <a href="http://glenmaddern.com/articles/css-modules">CSS modules</a>.
To style UIView(s) just give them a ```StyleRule``` object:
```Swift
let myLabelStyle = StyleRule() { (inout style: StyleRule) -> () in
style.color = UIColor.redColor()
style.border = Border(width: 1, color: UIColor.greenColor())
style.font = UIFont(name: "Courier", size: 24)
}
self.label.styleInline = myLabelStyle
```
Check out the sample to see how to well integrate Gaikan into a project.
<img src="Doc/Screen/gaikan.png" width="400" />
## Features
* Apply a simple style using ```styleInline```....
* ... or make theming using ```styleClass``` (see below for more information).
* You can share styles using ```extends``` method to avoid repeating yourself.
* You can style depending on your control state (enabled, highlighted, ...).
* You can style `NSAttributedString`!
## Properties
Check out our page on [properties](Doc/Properties.md) to find which one to use to style your views.
Starting with 0.4, we also added `VirtualView`. This allow you to apply style effects on some non `UIView`
attributes/objects:
| NSObject | Virtual view | Description | Available since
| ------------------|---------------|------------------------|------------------
| UINavigationBar | titleStyle | Sets title navigation bar style | 0.4
## Advanced usage
### NSAttributedString
Just call `NSAttributedString(string:"Hello", style: yourStyle)` to get a styled `NSAttributedString`.
Alternatively you can use `style.textAttributes` to transform `StyleRule` into any `NSAttributedString` compatible dictionary.
### Theme
```Theme``` packages together multiple ```Style``` definitions to make a whole set.
```Swift
public class SampleTheme : Theme {
/// Non static is important if you want to reference them from InterfaceBuilder
lazy let logo = Style(...)
lazy let title = Style(...)
}
class CustomView: UIView {
typealias ThemeType = RailTheme
@IBOutlet weak var title: UILabel!
@IBOutlet weak var footnote: UILabel!
@IBOutlet weak var logo: UIImageView!
@IBOutlet weak var button: UIButton!
override func awakeFromNib() {
self.title.styleClass = SampleTheme().logo
self.logo.styleClass = SampleTheme().title
}
}
```
You can also apply themes right from InterfaceBuilder:
<img src="Doc/Screen/ib-styleclass.png" width="400" />
### Extends
You can extend your styles to reuse common features:
```Swift
func primary() -> Style {
return [
.Color: UIColor.greenColor()
]
}
func large() -> Style {
return [
.Font: UIFont.systemFontOfSize(18)
]
}
func merged() -> Style {
return Style().extends(primary(), large())
// color: green, font: 18
}
```
### States
You can define styles for states. They'll extend from the default state :
```Swift
func style() -> Style {
return Style() { (inout style: StyleRule) -> Void in
style.tintColor = UIColor.whiteColor()
}
.state(.Selected, attributes: [
.TintColor: UIColor.grayColor().colorWithAlphaComponent(0.6)
]
}
```
Don't hesitate to take a look at the sample to better understand how it works.
## Contributing
This project was first developed by [Xebia IT Architects](http://xebia.fr) in Paris, France. We will continue working and investing on it.
We encourage the community to contribute to the project by opening tickets and/or pull requests. Here a some of the subjects we are interested in:
- Add UIStackView attributes (distribution, spacing, ...).
- Support for multiple layout engines (AutoLayout, LayoutKit, Flexbox, ...)
- Allow to define 1+ borders and corner radius. Currently defining border and radius set the 4 of them (top, bottom, left, right).
- Better support for IBDesignable (if possible).
- Add debugging information (style name, inheritance, ...).
- Better integration with NSAttributedString.
- Support for traits.
- Anything you have in mind!
## License
Gaikan is released under the MIT License. Please see the LICENSE file for details.
================================================
FILE: Sample/AppDelegate.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 03/09/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
================================================
FILE: Sample/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Sample/Assets.xcassets/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Sample/Assets.xcassets/background.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "bg.jpg",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Sample/Assets.xcassets/logo.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "logo.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}
================================================
FILE: Sample/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
================================================
FILE: Sample/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="AJl-7z-nnU">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Navigation Controller-->
<scene sceneID="e1l-FZ-XFj">
<objects>
<navigationController id="AJl-7z-nnU" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" id="7Ch-Lv-eYd">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="hRn-Ka-Wgm"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="4bO-fc-QLu" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-419" y="350"/>
</scene>
<!--Welcome-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="Sample" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" customClass="CustomView" customModule="Sample" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Gaikan" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vyz-xj-UlD">
<rect key="frame" x="275" y="290.5" width="50" height="19"/>
<constraints>
<constraint firstAttribute="height" constant="42" id="cY9-bk-1QW"/>
</constraints>
<fontDescription key="fontDescription" name="Optima-Regular" family="Optima" pointSize="16"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="title"/>
<userDefinedRuntimeAttribute type="string" keyPath="themeClassName" value="SampleTheme"/>
</userDefinedRuntimeAttributes>
<variation key="default">
<mask key="constraints">
<exclude reference="cY9-bk-1QW"/>
</mask>
</variation>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Your new styling framework. For iOS." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l5F-dS-U93">
<rect key="frame" x="159.5" y="309.5" width="281.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="footnote"/>
<userDefinedRuntimeAttribute type="string" keyPath="themeClassName" value="SampleTheme"/>
</userDefinedRuntimeAttributes>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" image="logo" translatesAutoresizingMaskIntoConstraints="NO" id="QjQ-fv-UZ9">
<rect key="frame" x="223.5" y="106" width="153" height="153"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="logo"/>
<userDefinedRuntimeAttribute type="string" keyPath="themeClassName" value="SampleTheme"/>
</userDefinedRuntimeAttributes>
</imageView>
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0Vy-ih-7cJ">
<rect key="frame" x="270" y="372" width="60" height="24"/>
<constraints>
<constraint firstAttribute="height" constant="24" id="0oR-vS-xYT"/>
<constraint firstAttribute="width" constant="60" id="ksB-7X-gAf"/>
</constraints>
<state key="normal" title="Got it!"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="getIt"/>
<userDefinedRuntimeAttribute type="string" keyPath="themeClassName" value="SampleTheme"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="gotIt" destination="8bC-Xf-vdC" eventType="touchUpInside" id="3tv-K3-2WI"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="1" green="0.99997437000274658" blue="0.99999129772186279" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="0Vy-ih-7cJ" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="ISz-g8-d0Q"/>
<constraint firstItem="QjQ-fv-UZ9" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="LWw-Wi-VaU"/>
<constraint firstItem="l5F-dS-U93" firstAttribute="top" secondItem="vyz-xj-UlD" secondAttribute="bottom" id="Yz2-I4-p3k"/>
<constraint firstItem="l5F-dS-U93" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="ihS-tm-wzR"/>
<constraint firstItem="vyz-xj-UlD" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="is3-Of-qAn"/>
<constraint firstItem="QjQ-fv-UZ9" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="42" id="lpk-aG-RDK"/>
<constraint firstItem="0Vy-ih-7cJ" firstAttribute="top" secondItem="l5F-dS-U93" secondAttribute="bottom" constant="42" id="q7P-PW-7sD"/>
<constraint firstItem="vyz-xj-UlD" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="qcR-Nz-UU5"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="home"/>
<userDefinedRuntimeAttribute type="string" keyPath="themeClassName" value="SampleTheme"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="button" destination="0Vy-ih-7cJ" id="Hpf-II-fhO"/>
<outlet property="footnote" destination="l5F-dS-U93" id="rNQ-md-OhO"/>
<outlet property="logo" destination="QjQ-fv-UZ9" id="raz-7l-wub"/>
<outlet property="title" destination="vyz-xj-UlD" id="m3u-pg-cEf"/>
</connections>
</view>
<navigationItem key="navigationItem" title="Welcome" id="gba-ZH-A6k"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
<resources>
<image name="logo" width="153" height="153"/>
</resources>
</document>
================================================
FILE: Sample/CustomView.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 16/11/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Gaikan
class CustomView : UIView {
@IBOutlet weak var title: UILabel!
@IBOutlet weak var footnote: UILabel!
@IBOutlet weak var logo: UIImageView!
@IBOutlet weak var button: UIButton!
@IBAction func gotIt() {
self.button.setTitle("Great!", for: .normal)
self.button.styleClass = SampleTheme().gotIt
}
}
================================================
FILE: Sample/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
================================================
FILE: Sample/Theme/Gradient.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 09/05/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Gaikan
extension Gradient {
static func orangeGradient() -> Gradient {
return Gradient(
(color: UIColor(red: 251/255, green: 208/255, blue: 176/255, alpha: 0.5), position: 0),
(color: UIColor(red: 137/255, green: 106/255, blue: 111/255, alpha: 0.5), position: 100)
)
}
}
================================================
FILE: Sample/Theme/SampleTheme.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 09/05/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import Gaikan
class SampleTheme : Theme {
var home = Style() { (style: inout StyleRule) -> () in
style.background = Background(UIImage(named: "background")!, Gradient.orangeGradient())
}
var logo = Style() { (style: inout StyleRule) -> () in
style.tintColor = UIColor.logoColor()
style.width = 90
style.height = style.width
}
var title: Style = [
.color: UIColor.white,
.font: UIFont.titleFont()
]
var footnote = Style() { (style: inout StyleRule) -> () in
style.font = UIFont.footnoteFont()
style.color = UIColor.orangeRail()
}
var getIt: Style = [
.border: Border(all: (width: 1, color: UIColor.white)),
.color: UIColor.white
]
var gotIt: Style = [
.color: UIColor.orange
]
}
================================================
FILE: Sample/Theme/UIColor.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 09/05/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import UIKit
extension UIColor {
static func orangeRail() -> UIColor {
return UIColor(red: 251/255, green: 208/255, blue: 176/255, alpha: 1)
}
class func logoColor() -> UIColor {
return UIColor.white
}
}
================================================
FILE: Sample/Theme/UIFont.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 09/05/16.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import Foundation
import UIKit
extension UIFont {
class func bodyFont() -> UIFont? {
return UIFont(name: "Avenir", size: 12)
}
class func titleFont() -> UIFont? {
return UIFont(name: "AvenirNext-Bold", size: 38)
}
class func footnoteFont() -> UIFont? {
return UIFont(name: "AvenirNext-Italic", size: 18)
}
}
================================================
FILE: Sample/ViewController.swift
================================================
//
// This file is part of Gaikan
//
// Created by JC on 03/09/15.
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code
//
import UIKit
import Gaikan
class ViewController: UIViewController {
var customView: CustomView!
override func viewDidLoad() {
let titleStyle: StyleRule = [
.font: UIFont(name: "AvenirNext-Italic", size: 16),
.color: UIColor.purple
]
super.viewDidLoad()
self.customView = self.view as! CustomView
self.navigationController?.navigationBar.titleStyle.styleInline = titleStyle
}
}
gitextract_7_zppekp/
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── Cartfile
├── Cartfile.private
├── Cartfile.resolved
├── Doc/
│ └── Properties.md
├── Gaikan/
│ ├── Gaikan.h
│ ├── Helpers/
│ │ ├── AssociatedObject.swift
│ │ ├── CGPoint+Helpers.swift
│ │ ├── Dictionary+Helpers.swift
│ │ ├── NSAttributedString+Style.swift
│ │ ├── NSLayoutAttribute+Helpers.swift
│ │ ├── NSLayoutRelation+Helpers.swift
│ │ ├── NSShadow+Helpers.swift
│ │ ├── Optional+Helpers.swift
│ │ ├── UIColor+Helpers.swift
│ │ ├── UIImage+Helpers.swift
│ │ └── UIView+Helpers.swift
│ ├── Info.plist
│ ├── InterfaceBuilder/
│ │ └── UIView+InterfaceBuilder.swift
│ ├── Property/
│ │ ├── Gradient.swift
│ │ ├── Property.swift
│ │ └── Value/
│ │ ├── Background.swift
│ │ ├── Border.swift
│ │ ├── Constraint.swift
│ │ ├── Corners.swift
│ │ └── Side.swift
│ ├── Style/
│ │ ├── Stylable.swift
│ │ ├── Style.swift
│ │ ├── StylePseudoState.swift
│ │ ├── StyleRule+DirectAccess.swift
│ │ ├── StyleRule.swift
│ │ └── StyleState.swift
│ ├── Theme/
│ │ └── Theme.swift
│ └── UIKit/
│ ├── Extension/
│ │ ├── UIControl.swift
│ │ ├── UILabel.swift
│ │ ├── UINavigationBar.swift
│ │ ├── UISwitch.swift
│ │ └── UIView.swift
│ ├── Layer/
│ │ ├── BackgroundLayer.swift
│ │ ├── BorderLayer.swift
│ │ └── Layer.swift
│ ├── Renderer/
│ │ ├── ConstraintRenderer.swift
│ │ └── ViewStyleRenderer.swift
│ └── VirtualView.swift
├── Gaikan.podspec
├── Gaikan.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── xcshareddata/
│ └── xcschemes/
│ └── Gaikan.xcscheme
├── Gaikan.xcworkspace/
│ └── contents.xcworkspacedata
├── GaikanTests/
│ ├── GaikanTests.swift
│ ├── Info.plist
│ ├── Style/
│ │ ├── StyleRuleSpec.swift
│ │ └── StyleSpec.swift
│ ├── Swift/
│ │ └── Extension/
│ │ └── DictionarySpec.swift
│ └── UIKit/
│ ├── Extension/
│ │ ├── UILabelSpec.swift
│ │ ├── UINavigationBarSpec.swift
│ │ └── UIViewSpec.swift
│ └── Renderer/
│ └── ConstraintRendererSpec.swift
├── LICENSE
├── Podfile
├── README.md
└── Sample/
├── AppDelegate.swift
├── Assets.xcassets/
│ ├── AppIcon.appiconset/
│ │ └── Contents.json
│ ├── Contents.json
│ ├── background.imageset/
│ │ └── Contents.json
│ └── logo.imageset/
│ └── Contents.json
├── Base.lproj/
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── CustomView.swift
├── Info.plist
├── Theme/
│ ├── Gradient.swift
│ ├── SampleTheme.swift
│ ├── UIColor.swift
│ └── UIFont.swift
└── ViewController.swift
Condensed preview — 77 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (163K chars).
[
{
"path": ".gitignore",
"chars": 631,
"preview": "# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!defau"
},
{
"path": ".travis.yml",
"chars": 523,
"preview": "language: objective-c\nosx_image: xcode8.3\n\nenv:\n - >\n xcode_project=Gaikan.xcodeproj\n xcode_scheme=Gaikan\n xco"
},
{
"path": "CHANGELOG.md",
"chars": 1852,
"preview": "# CHANGELOG\n\n## 0.9.1\n\n### Added\n\n- Added shadow property.\n\n### Fixed\n\n- Border not correctly set when all sides were de"
},
{
"path": "Cartfile",
"chars": 32,
"preview": "github \"facebook/KVOController\"\n"
},
{
"path": "Cartfile.private",
"chars": 43,
"preview": "github \"Quick/Nimble\"\ngithub \"Quick/Quick\"\n"
},
{
"path": "Cartfile.resolved",
"chars": 102,
"preview": "github \"facebook/KVOController\" \"v1.1.0\"\ngithub \"Quick/Nimble\" \"v4.1.0\"\ngithub \"Quick/Quick\" \"v0.9.3\"\n"
},
{
"path": "Doc/Properties.md",
"chars": 3817,
"preview": "# Style properties\n\n## Background\n- __**since**__: 0.3\n- __**description**__: Sets a background to your view (color, gra"
},
{
"path": "Gaikan/Gaikan.h",
"chars": 543,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 30/08/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Helpers/AssociatedObject.swift",
"chars": 836,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 25/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Helpers/CGPoint+Helpers.swift",
"chars": 771,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 05/11/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Helpers/Dictionary+Helpers.swift",
"chars": 865,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 24/06/16.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Helpers/NSAttributedString+Style.swift",
"chars": 561,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 20/06/16.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Helpers/NSLayoutAttribute+Helpers.swift",
"chars": 1476,
"preview": "//\n// NSLayoutAttribute+Helpers.swift\n// Gaikan\n//\n// Created by pjechris on 01/09/16.\n// Copyright © 2016 fr.akane."
},
{
"path": "Gaikan/Helpers/NSLayoutRelation+Helpers.swift",
"chars": 435,
"preview": "//\n// NSLayoutRelation+Helpers.swift\n// Gaikan\n//\n// Created by pjechris on 01/09/16.\n// Copyright © 2016 fr.akane. "
},
{
"path": "Gaikan/Helpers/NSShadow+Helpers.swift",
"chars": 393,
"preview": "//\n// NSShadow+Helpers.swift\n// Gaikan\n//\n// Created by pjechris on 07/02/17.\n// Copyright © 2017 fr.akane. All righ"
},
{
"path": "Gaikan/Helpers/Optional+Helpers.swift",
"chars": 409,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 24/06/16.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Helpers/UIColor+Helpers.swift",
"chars": 442,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 05/11/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Helpers/UIImage+Helpers.swift",
"chars": 408,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 15/11/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Helpers/UIView+Helpers.swift",
"chars": 667,
"preview": "//\n// UIView+Helpers.swift\n// Gaikan\n//\n// Created by pjechris on 10/09/16.\n// Copyright © 2016 fr.akane. All rights"
},
{
"path": "Gaikan/Info.plist",
"chars": 806,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "Gaikan/InterfaceBuilder/UIView+InterfaceBuilder.swift",
"chars": 2149,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 03/05/16.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Property/Gradient.swift",
"chars": 1392,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 05/11/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Property/Property.swift",
"chars": 723,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 30/08/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Property/Value/Background.swift",
"chars": 846,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 05/11/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Property/Value/Border.swift",
"chars": 1317,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 05/09/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Property/Value/Constraint.swift",
"chars": 766,
"preview": "//\n// Constraint.swift\n// Gaikan\n//\n// Created by pjechris on 29/08/16.\n// Copyright © 2016 fr.akane. All rights res"
},
{
"path": "Gaikan/Property/Value/Corners.swift",
"chars": 321,
"preview": "//\n// Corners.swift\n// Gaikan\n//\n// Created by Brandon on 27/01/2016.\n// Copyright © 2016 fr.akane. All rights reser"
},
{
"path": "Gaikan/Property/Value/Side.swift",
"chars": 912,
"preview": "//\n// Side.swift\n// Gaikan\n//\n// Created by pjechris on 04/12/16.\n// Copyright © 2016 fr.akane. All rights reserved."
},
{
"path": "Gaikan/Style/Stylable.swift",
"chars": 2155,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 30/08/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Style/Style.swift",
"chars": 2437,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 11/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Style/StylePseudoState.swift",
"chars": 553,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 14/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Style/StyleRule+DirectAccess.swift",
"chars": 3857,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 17/06/16.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Style/StyleRule.swift",
"chars": 1809,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 30/08/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Style/StyleState.swift",
"chars": 1683,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 10/12/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/Theme/Theme.swift",
"chars": 285,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 14/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/UIKit/Extension/UIControl.swift",
"chars": 608,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 24/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/UIKit/Extension/UILabel.swift",
"chars": 475,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 26/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/UIKit/Extension/UINavigationBar.swift",
"chars": 1161,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 26/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/UIKit/Extension/UISwitch.swift",
"chars": 476,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 24/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/UIKit/Extension/UIView.swift",
"chars": 3490,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 30/08/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/UIKit/Layer/BackgroundLayer.swift",
"chars": 529,
"preview": "//\n// BackgroundLayer.swift\n// Gaikan\n//\n// Created by pjechris on 01/12/16.\n// Copyright © 2016 fr.akane. All right"
},
{
"path": "Gaikan/UIKit/Layer/BorderLayer.swift",
"chars": 2834,
"preview": "//\n// BorderLayer.swift\n// Gaikan\n//\n// Created by pjechris on 30/11/16.\n// Copyright © 2016 fr.akane. All rights re"
},
{
"path": "Gaikan/UIKit/Layer/Layer.swift",
"chars": 1701,
"preview": "//\n// Layer.swift\n// Gaikan\n//\n// Created by pjechris on 22/11/16.\n// Copyright © 2016 fr.akane. All rights reserved"
},
{
"path": "Gaikan/UIKit/Renderer/ConstraintRenderer.swift",
"chars": 2712,
"preview": "//\n// ConstraintRenderer.swift\n// Gaikan\n//\n// Created by pjechris on 30/08/16.\n// Copyright © 2016 fr.akane. All ri"
},
{
"path": "Gaikan/UIKit/Renderer/ViewStyleRenderer.swift",
"chars": 2343,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 30/08/15.\n// For the full copyright and license information, pl"
},
{
"path": "Gaikan/UIKit/VirtualView.swift",
"chars": 770,
"preview": "//\n// VirtualView.swift\n// Gaikan\n//\n// Created by Simone Civetta on 17/03/16.\n// Copyright © 2016 fr.akane. All rig"
},
{
"path": "Gaikan.podspec",
"chars": 777,
"preview": "Pod::Spec.new do |s|\n s.name = \"Gaikan\"\n s.version = \"0.9.1\"\n s.source "
},
{
"path": "Gaikan.xcodeproj/project.pbxproj",
"chars": 49642,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "Gaikan.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 151,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:Gaikan.xcodepro"
},
{
"path": "Gaikan.xcodeproj/xcshareddata/xcschemes/Gaikan.xcscheme",
"chars": 3628,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0810\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "Gaikan.xcworkspace/contents.xcworkspacedata",
"chars": 224,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"group:Gaikan.xcodepr"
},
{
"path": "GaikanTests/GaikanTests.swift",
"chars": 953,
"preview": "//\n// GaikanTests.swift\n// GaikanTests\n//\n// Created by JC on 30/08/15.\n// Copyright © 2015 fr.akane. All rights res"
},
{
"path": "GaikanTests/Info.plist",
"chars": 733,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "GaikanTests/Style/StyleRuleSpec.swift",
"chars": 2533,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 12/09/15.\n// For the full copyright and license information, pl"
},
{
"path": "GaikanTests/Style/StyleSpec.swift",
"chars": 1734,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 18/10/15.\n// For the full copyright and license information, pl"
},
{
"path": "GaikanTests/Swift/Extension/DictionarySpec.swift",
"chars": 1709,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 12/09/15.\n// For the full copyright and license information, pl"
},
{
"path": "GaikanTests/UIKit/Extension/UILabelSpec.swift",
"chars": 1005,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 11/09/15.\n// For the full copyright and license information, pl"
},
{
"path": "GaikanTests/UIKit/Extension/UINavigationBarSpec.swift",
"chars": 2057,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by Simone Civetta on 26/02/16.\n// For the full copyright and license inf"
},
{
"path": "GaikanTests/UIKit/Extension/UIViewSpec.swift",
"chars": 1973,
"preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 10/09/15.\n// For the full copyright and license information, pl"
},
{
"path": "GaikanTests/UIKit/Renderer/ConstraintRendererSpec.swift",
"chars": 1904,
"preview": "//\n// ConstraintRendererSpec.swift\n// Gaikan\n//\n// Created by pjechris on 10/09/16.\n// Copyright © 2016 fr.akane. Al"
},
{
"path": "LICENSE",
"chars": 1073,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015 akane\n\nPermission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "Podfile",
"chars": 181,
"preview": "platform :ios, '9.0'\n\ntarget 'Gaikan' do\n use_frameworks!\n\n pod 'KVOController'\n\n target 'GaikanTests' do\n inherit"
},
{
"path": "README.md",
"chars": 4615,
"preview": "<h1><img src=\"Doc/Screen/logo.png\" width=\"550\" alt=\"Gaikan\" /></h1>\n\n[. The extraction includes 77 files (145.8 KB), approximately 42.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.