Full Code of akane/Gaikan for AI

master 3b9eae7d7755 cached
77 files
145.8 KB
42.4k tokens
1 requests
Download .txt
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>

[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Gaikan.svg)](https://img.shields.io/cocoapods/v/Gaikan.svg)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Build Status](https://travis-ci.org/akane/Gaikan.svg?branch=travis)](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
    }
}

Download .txt
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[![CocoaPods Compatible](https://img.shields.io/coc"
  },
  {
    "path": "Sample/AppDelegate.swift",
    "chars": 2227,
    "preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 03/09/15.\n// For the full copyright and license information, pl"
  },
  {
    "path": "Sample/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 585,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "Sample/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sample/Assets.xcassets/background.imageset/Contents.json",
    "chars": 299,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample/Assets.xcassets/logo.imageset/Contents.json",
    "chars": 370,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample/Base.lproj/LaunchScreen.storyboard",
    "chars": 1662,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "Sample/Base.lproj/Main.storyboard",
    "chars": 10291,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "Sample/CustomView.swift",
    "chars": 567,
    "preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 16/11/15.\n// For the full copyright and license information, pl"
  },
  {
    "path": "Sample/Info.plist",
    "chars": 1205,
    "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": "Sample/Theme/Gradient.swift",
    "chars": 541,
    "preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 09/05/16.\n// For the full copyright and license information, pl"
  },
  {
    "path": "Sample/Theme/SampleTheme.swift",
    "chars": 1037,
    "preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 09/05/16.\n// For the full copyright and license information, pl"
  },
  {
    "path": "Sample/Theme/UIColor.swift",
    "chars": 453,
    "preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 09/05/16.\n// For the full copyright and license information, pl"
  },
  {
    "path": "Sample/Theme/UIFont.swift",
    "chars": 555,
    "preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 09/05/16.\n// For the full copyright and license information, pl"
  },
  {
    "path": "Sample/ViewController.swift",
    "chars": 664,
    "preview": "//\n// This file is part of Gaikan\n//\n// Created by JC on 03/09/15.\n// For the full copyright and license information, pl"
  }
]

About this extraction

This page contains the full source code of the akane/Gaikan GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). 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.

Copied to clipboard!