<NME> Button.swift
<BEF> //
//  Button.swift
//  TemplateKit
//
//  Created by Matias Cudich on 9/20/16.
//  Copyright © 2016 Matias Cudich. All rights reserved.
//

import Foundation

public struct ButtonProperties: Properties, EnableableProperties, ActivatableProperties {
  public var core = CoreProperties()
  public var textStyle = TextStyleProperties()

  public var text: String?
  public var backgroundImage: UIImage?
  public var image: UIImage?
  public var selected: Bool?
  public var enabled: Bool?
  public var active: Bool?

  public init() {}

  public init(_ properties: [String : Any]) {
    core = CoreProperties(properties)
    textStyle = TextStyleProperties(properties)

    text = properties.cast("text")
    selected = properties.cast("selected")
    enabled = properties.cast("enabled")
    active = properties.cast("active")
  }

  public mutating func merge(_ other: ButtonProperties) {
    core.merge(other.core)
    textStyle.merge(other.textStyle)

    merge(&text, other.text)
    merge(&selected, other.selected)
    merge(&enabled, other.enabled)
    merge(&active, other.active)
  }

  public func has(key: String, withValue value: String) -> Bool {
    switch key {
    case "selected":
      return selected == Bool.fromString(value)
    default:
      fatalError("This attribute is not yet supported")
    }
  }
}

public func ==(lhs: ButtonProperties, rhs: ButtonProperties) -> Bool {
  return lhs.textStyle == rhs.textStyle && lhs.text == rhs.text && lhs.backgroundImage == rhs.backgroundImage && lhs.image == rhs.image && lhs.selected == rhs.selected && lhs.enabled == rhs.enabled && lhs.active == rhs.active && lhs.equals(otherProperties: rhs)
}

public struct ButtonState: State {
  var active = false

  public init() {}
}

public func ==(lhs: ButtonState, rhs: ButtonState) -> Bool {
  return lhs.active == rhs.active
  public var gestures: GestureProperties?

  public var buttonStyle = [UIControlState: ButtonStyleProperties]()

  public init(_ properties: [String : Any]) {
    applyProperties(properties)

    for state in UIControlState.buttonStates {
      buttonStyle[state] = ButtonStyleProperties(properties, statePrefix: state.stringValue)
    }
  }
}

public func ==(lhs: ButtonProperties, rhs: ButtonProperties) -> Bool {
  return lhs.equals(otherViewProperties: rhs)
}

public class Button: UIButton, NativeView {
  public static var propertyTypes: [String: ValidationType] {
    return commonPropertyTypes.merged(with: [:
    ])
  }

  public var eventTarget: AnyObject?

  @objc private func handleTap() {
    updateState(stateMutation: { $0.active = false }) { [weak self] in
      guard self?.properties.enabled ?? true else {
        return
      }
      self?.performSelector(self?.properties.core.gestures.onTap, with: self)
    }
  }

  @objc private func handlePress() {
    updateState { state in
      state.active = true
    }
  }

  @objc private func handleDoubleTap() {
    updateState(stateMutation: { $0.active = false }) { [weak self] in
      guard self?.properties.enabled ?? true else {
        return
      }
      self?.performSelector(self?.properties.core.gestures.onDoubleTap)
      let stateProperties = properties.buttonStyle[state]

      setTitle(stateProperties?.title, for: state)
    }
  }
}

<MSG> Getting more stuff rendering

<DFF> @@ -66,6 +66,8 @@ public struct ButtonProperties: ViewProperties {
   public var gestures: GestureProperties?
 
   public var buttonStyle = [UIControlState: ButtonStyleProperties]()
+  public var selected: Bool?
+  public var onTouchUpInside: Selector?
 
   public init(_ properties: [String : Any]) {
     applyProperties(properties)
@@ -73,17 +75,37 @@ public struct ButtonProperties: ViewProperties {
     for state in UIControlState.buttonStates {
       buttonStyle[state] = ButtonStyleProperties(properties, statePrefix: state.stringValue)
     }
+
+    selected = properties.get("selected")
+    onTouchUpInside = properties.get("onTouchUpInside")
   }
 }
 
 public func ==(lhs: ButtonProperties, rhs: ButtonProperties) -> Bool {
-  return lhs.equals(otherViewProperties: rhs)
+  return lhs.buttonStyle == rhs.buttonStyle && lhs.equals(otherViewProperties: rhs)
 }
 
 public class Button: UIButton, NativeView {
   public static var propertyTypes: [String: ValidationType] {
-    return commonPropertyTypes.merged(with: [:
-    ])
+    return commonPropertyTypes.merged(with: buildPropertyTypes())
+  }
+
+  static func buildPropertyTypes() -> [String: ValidationType] {
+    var propertyTypes = [String: ValidationType]()
+    for state in UIControlState.buttonStates {
+      let buildKey = { (prefix: String, key: String) in
+        return prefix.isEmpty ? key : prefix + key.capitalized
+      }
+      propertyTypes[buildKey(state.stringValue, "title")] = Validation.string
+      propertyTypes[buildKey(state.stringValue, "titleColor")] = Validation.color
+      propertyTypes[buildKey(state.stringValue, "titleShadowColor")] = Validation.color
+      propertyTypes[buildKey(state.stringValue, "backgroundImage")] = Validation.string
+      propertyTypes[buildKey(state.stringValue, "image")] = Validation.string
+    }
+    propertyTypes["selected"] = Validation.boolean
+    propertyTypes["onTouchUpInside"] = Validation.selector
+    
+    return propertyTypes
   }
 
   public var eventTarget: AnyObject?
@@ -112,6 +134,14 @@ public class Button: UIButton, NativeView {
       let stateProperties = properties.buttonStyle[state]
 
       setTitle(stateProperties?.title, for: state)
+      setTitleColor(stateProperties?.titleColor, for: state)
+      setTitleShadowColor(stateProperties?.titleShadowColor, for: state)
+      setBackgroundImage(stateProperties?.backgroundImage, for: state)
+      setImage(stateProperties?.image, for: state)
+    }
+    if let onTouchUpInside = properties.onTouchUpInside {
+      addTarget(eventTarget, action: onTouchUpInside, for: .touchUpInside)
     }
+    isSelected = properties.selected ?? false
   }
 }

Getting more stuff rendering