Commit c316eea6 by Daniel Dahan

master: development merge

parents d8bec523 2c82f509
Pod::Spec.new do |s|
s.name = 'MK'
s.version = '1.6.0'
s.version = '1.7.0'
s.license = { :type => "AGPLv3+", :file => "LICENSE" }
s.summary = 'A Material Design Framework In Swift'
s.homepage = 'http://materialkit.io'
......
......@@ -10,7 +10,6 @@
657CD02A1B8EE0D3008C0029 /* MaterialCard.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9A94D1081B8A3F5100F586A5 /* MaterialCard.swift */; settings = {ATTRIBUTES = (Public, ); }; };
657CD02C1B8EE0D3008C0029 /* SideNavController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 65B965861B8BEEC60055B139 /* SideNavController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
657CD02D1B8EE0D3008C0029 /* MaterialButton.swift in Headers */ = {isa = PBXBuildFile; fileRef = 65B9657D1B8A7C330055B139 /* MaterialButton.swift */; settings = {ATTRIBUTES = (Public, ); }; };
657CD02E1B8EE0D3008C0029 /* (null) in Headers */ = {isa = PBXBuildFile; settings = {ATTRIBUTES = (Public, ); }; };
657CD02F1B8EE0D3008C0029 /* ImageCard.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9A94D10A1B8A485C00F586A5 /* ImageCard.swift */; settings = {ATTRIBUTES = (Public, ); }; };
65B9657E1B8A7C330055B139 /* MaterialButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65B9657D1B8A7C330055B139 /* MaterialButton.swift */; };
65B965871B8BEEC60055B139 /* SideNavController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65B965861B8BEEC60055B139 /* SideNavController.swift */; };
......@@ -35,7 +34,7 @@
963832881B8908180015F710 /* Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963832871B8908180015F710 /* Layout.swift */; };
963832891B89097D0015F710 /* Layout.swift in Headers */ = {isa = PBXBuildFile; fileRef = 963832871B8908180015F710 /* Layout.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96B57D4E1B90AF7D00DE7BBB /* MaterialTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B57D4D1B90AF7D00DE7BBB /* MaterialTheme.swift */; };
9A3A3B701B8EB582005F16BC /* ImageRevealCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A3A3B6F1B8EB582005F16BC /* ImageRevealCard.swift */; };
96C910ED1B95804B00E7CE5C /* MaterialTheme.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96B57D4D1B90AF7D00DE7BBB /* MaterialTheme.swift */; settings = {ATTRIBUTES = (Public, ); }; };
9A94D0F91B895C8C00F586A5 /* Roboto.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9AAC38531B89559900FE6B2D /* Roboto.swift */; settings = {ATTRIBUTES = (Public, ); }; };
9A94D0FA1B895EA500F586A5 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 963832631B88E5BF0015F710 /* LICENSE */; };
9A94D0FB1B895EA500F586A5 /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9AAC38591B8956E300FE6B2D /* Roboto-Regular.ttf */; };
......@@ -77,7 +76,6 @@
963832681B88E5BF0015F710 /* TextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = "<group>"; };
963832871B8908180015F710 /* Layout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Layout.swift; sourceTree = "<group>"; };
96B57D4D1B90AF7D00DE7BBB /* MaterialTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaterialTheme.swift; sourceTree = "<group>"; };
9A3A3B6F1B8EB582005F16BC /* ImageRevealCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageRevealCard.swift; sourceTree = "<group>"; };
9A94D1081B8A3F5100F586A5 /* MaterialCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaterialCard.swift; sourceTree = "<group>"; };
9A94D10A1B8A485C00F586A5 /* ImageCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCard.swift; sourceTree = "<group>"; };
9AAC384C1B89528900FE6B2D /* BasicCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicCard.swift; sourceTree = "<group>"; };
......@@ -234,7 +232,6 @@
9A94D1081B8A3F5100F586A5 /* MaterialCard.swift */,
9AAC384C1B89528900FE6B2D /* BasicCard.swift */,
9A94D10A1B8A485C00F586A5 /* ImageCard.swift */,
9A3A3B6F1B8EB582005F16BC /* ImageRevealCard.swift */,
);
name = Card;
sourceTree = "<group>";
......@@ -271,7 +268,7 @@
657CD02A1B8EE0D3008C0029 /* MaterialCard.swift in Headers */,
657CD02C1B8EE0D3008C0029 /* SideNavController.swift in Headers */,
657CD02D1B8EE0D3008C0029 /* MaterialButton.swift in Headers */,
657CD02E1B8EE0D3008C0029 /* (null) in Headers */,
96C910ED1B95804B00E7CE5C /* MaterialTheme.swift in Headers */,
657CD02F1B8EE0D3008C0029 /* ImageCard.swift in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -322,7 +319,7 @@
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0640;
ORGANIZATIONNAME = "GraphKit Inc.";
ORGANIZATIONNAME = "GraphKit, Inc.";
TargetAttributes = {
963832351B88DFD80015F710 = {
CreatedOnToolsVersion = 6.4;
......@@ -381,7 +378,6 @@
96B57D4E1B90AF7D00DE7BBB /* MaterialTheme.swift in Sources */,
9638326B1B88E5BF0015F710 /* FabButton.swift in Sources */,
9A94D1091B8A3F5100F586A5 /* MaterialCard.swift in Sources */,
9A3A3B701B8EB582005F16BC /* ImageRevealCard.swift in Sources */,
65B965871B8BEEC60055B139 /* SideNavController.swift in Sources */,
9638326C1B88E5BF0015F710 /* FlatButton.swift in Sources */,
963832711B88E5BF0015F710 /* Text.swift in Sources */,
......
......@@ -18,9 +18,10 @@ Make a call to action with a Floating Action Button.
```swift
var button: FabButton = FabButton()
button.setTitle("+", forState: .Normal)
button.titleLabel!.font = UIFont(name: "Arial", size: 32)
view.addSubview(button)
button.titleLabel!.font = Roboto.lightWithSize(16)
// layout
view.addSubview(button)
Layout.size(view, child: button, width: 60, height: 60)
```
......@@ -35,8 +36,9 @@ Use a Raised Button to capture attention.
```swift
var button: RaisedButton = RaisedButton()
button.setTitle("Raised", forState: .Normal)
view.addSubview(button)
// layout
view.addSubview(button)
Layout.size(view, child: button, width: 200, height: 60)
```
......@@ -51,8 +53,9 @@ Keep it simple and elegant with a Flat Button.
```swift
var button: RaisedButton = RaisedButton()
button.setTitle("Flat", forState: .Normal)
view.addSubview(button)
// layout
view.addSubview(button)
Layout.size(view, child: button, width: 200, height: 60)
```
......@@ -67,18 +70,18 @@ Easily make cards with fully customizable components.
```swift
var card: BasicCard = BasicCard()
// add a title
// title
card.titleLabel = UILabel()
card.titleLabel!.text = "Card Title"
// add a body of text
card.detailTextLabel = UILabel()
card.detailTextLabel!.text = "I am a very simple card. I am good at containing small bits of information. I am convenient because I require little markup to use effectively."
// details
card.detailLabel = UILabel()
card.detailLabel!.text = "I am a very simple card. I am good at containing small bits of information. I am convenient because I require little markup to use effectively."
// add a divider for buttons
// divider
card.divider = UIView()
// add a couple buttons
// buttons
var cancelButton: FlatButton = FlatButton()
cancelButton.pulseColor = MaterialTheme.blueGrey.darken3
cancelButton.setTitle("Cancel", forState: .Normal)
......@@ -89,10 +92,10 @@ okButton.pulseColor = MaterialTheme.blueGrey.darken3
okButton.setTitle("Okay", forState: .Normal)
okButton.setTitleColor(MaterialTheme.yellow.darken3, forState: .Normal)
card.buttons = [cancelButton, okButton]
card.leftButtons = [cancelButton, okButton]
// layout
view.addSubview(card)
view.addConstraints(Layout.constraint("H:|-(pad)-[child]-(pad)-|", options: nil, metrics: ["pad": 20], views: ["child": card]))
view.addConstraints(Layout.constraint("V:|-(pad)-[child]", options: nil, metrics: ["pad": 100], views: ["child": card]))
```
......@@ -108,9 +111,11 @@ Add photos with an Image Card.
```swift
var card: ImageCard = ImageCard()
card.imageView = UIImageView(image: UIImage(named: "photo.jpg"))
view.addSubview(card)
Layout.size(view, child: card, width: 300, height: 175)
// layout
view.addSubview(card)
view.addConstraints(Layout.constraint("H:|-(pad)-[child]-(pad)-|", options: nil, metrics: ["pad": 20], views: ["child": card]))
view.addConstraints(Layout.constraint("V:|-(pad)-[child]", options: nil, metrics: ["pad": 100], views: ["child": card]))
```
### Full Image Card
......@@ -125,18 +130,18 @@ Allow the Image Card to really shine by adding a title, some details, and button
var card: ImageCard = ImageCard()
card.imageView = UIImageView(image: UIImage(named: "photo.jpg"))
// add a title
// title
card.titleLabel = UILabel()
card.titleLabel!.text = "Card Title"
// add a body of text
card.detailTextLabel = UILabel()
card.detailTextLabel!.text = "I am a very simple card. I am good at containing small bits of information. I am convenient because I require little markup to use effectively."
// details
card.detailLabel = UILabel()
card.detailLabel!.text = "I am a very simple card. I am good at containing small bits of information. I am convenient because I require little markup to use effectively."
// add a divider for buttons
// divider
card.divider = UIView()
// add a couple buttons
// buttons
var cancelButton: FlatButton = FlatButton()
cancelButton.pulseColor = MaterialTheme.blueGrey.darken3
cancelButton.setTitle("Cancel", forState: .Normal)
......@@ -147,10 +152,10 @@ okButton.pulseColor = MaterialTheme.blueGrey.darken3
okButton.setTitle("Okay", forState: .Normal)
okButton.setTitleColor(MaterialTheme.yellow.darken3, forState: .Normal)
card.buttons = [cancelButton, okButton]
card.leftButtons = [cancelButton, okButton]
// layout
view.addSubview(card)
view.addConstraints(Layout.constraint("H:|-(pad)-[child]-(pad)-|", options: nil, metrics: ["pad": 20], views: ["child": card]))
view.addConstraints(Layout.constraint("V:|-(pad)-[child]", options: nil, metrics: ["pad": 100], views: ["child": card]))
```
......
......@@ -17,9 +17,8 @@
//
import UIKit
import QuartzCore
public class BasicCard : MaterialCard {
public class BasicCard : MaterialCard, Comparable, Equatable {
//
// :name: layoutConstraints
//
......@@ -31,30 +30,93 @@ public class BasicCard : MaterialCard {
internal lazy var views: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
/**
:name: verticalSpace
*/
public var verticalSpace: CGFloat = 8
/**
:name: horizontalSpace
*/
public var horizontalSpace: CGFloat = 8
/**
:name: titleLabelContainer
*/
public private(set) var titleLabelContainer: UIView?
/**
:name: shadow
*/
public var shadow: Bool = true {
didSet {
false == shadow ? removeShadow() : prepareShadow()
}
}
/**
:name: titleLabel
*/
public var titleLabel: UILabel? {
didSet {
titleLabel!.setTranslatesAutoresizingMaskIntoConstraints(false)
titleLabel!.textColor = MaterialTheme.white.color
titleLabel!.font = Roboto.regularWithSize(22.0)
addSubview(titleLabel!)
if let t = titleLabel {
// container
if nil == titleLabelContainer {
titleLabelContainer = UIView()
titleLabelContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
titleLabelContainer!.backgroundColor = MaterialTheme.clear.color
addSubview(titleLabelContainer!)
}
// text
titleLabelContainer!.addSubview(t)
t.setTranslatesAutoresizingMaskIntoConstraints(false)
t.textColor = MaterialTheme.white.color
t.backgroundColor = MaterialTheme.clear.color
t.font = Roboto.mediumWithSize(18)
t.numberOfLines = 1
prepareCard()
} else {
titleLabelContainer?.removeFromSuperview()
}
}
}
/**
:name: detailTextLabel
:name: maximumDetailLabelHeight
*/
public var maximumDetailLabelHeight: CGFloat = 144
/**
:name: detailLabelContainer
*/
public var detailTextLabel: UILabel? {
public private(set) var detailLabelContainer: UIView?
/**
:name: detailLabel
*/
public var detailLabel: UILabel? {
didSet {
detailTextLabel!.setTranslatesAutoresizingMaskIntoConstraints(false)
detailTextLabel!.textColor = MaterialTheme.white.color
detailTextLabel!.font = Roboto.lightWithSize(16.0)
detailTextLabel!.numberOfLines = 0
detailTextLabel!.lineBreakMode = .ByWordWrapping
addSubview(detailTextLabel!)
if let l = detailLabel {
// container
if nil == detailLabelContainer {
detailLabelContainer = UIView()
detailLabelContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
detailLabelContainer!.backgroundColor = MaterialTheme.clear.color
addSubview(detailLabelContainer!)
}
// text
detailLabelContainer!.addSubview(l)
l.setTranslatesAutoresizingMaskIntoConstraints(false)
l.textColor = MaterialTheme.white.color
l.backgroundColor = MaterialTheme.clear.color
l.font = Roboto.lightWithSize(16)
l.numberOfLines = 0
l.lineBreakMode = .ByWordWrapping
prepareCard()
} else {
detailLabelContainer?.removeFromSuperview()
}
}
}
......@@ -63,19 +125,57 @@ public class BasicCard : MaterialCard {
*/
public var divider: UIView? {
didSet {
divider!.setTranslatesAutoresizingMaskIntoConstraints(false)
divider!.backgroundColor = MaterialTheme.blueGrey.darken2
addSubview(divider!)
if let d = divider {
d.setTranslatesAutoresizingMaskIntoConstraints(false)
d.backgroundColor = MaterialTheme.blueGrey.color
addSubview(d)
prepareCard()
} else {
divider?.removeFromSuperview()
}
}
}
/**
:name: buttonsContainer
*/
public private(set) var buttonsContainer: UIView?
/**
:name: leftButtons
*/
public var leftButtons: Array<MaterialButton>? {
didSet {
if let b = leftButtons {
if nil == buttonsContainer {
buttonsContainer = UIView()
buttonsContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
buttonsContainer!.backgroundColor = MaterialTheme.clear.color
addSubview(buttonsContainer!)
}
prepareCard()
} else {
buttonsContainer?.removeFromSuperview()
}
}
}
/**
:name: buttons
:name: rightButtons
*/
public var buttons: Array<MaterialButton>? {
public var rightButtons: Array<MaterialButton>? {
didSet {
if let b = rightButtons {
if nil == buttonsContainer {
buttonsContainer = UIView()
buttonsContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
buttonsContainer!.backgroundColor = MaterialTheme.clear.color
addSubview(buttonsContainer!)
}
prepareCard()
} else {
buttonsContainer?.removeFromSuperview()
}
}
}
......@@ -93,6 +193,7 @@ public class BasicCard : MaterialCard {
//
internal override func prepareCard() {
super.prepareCard()
// deactivate and clear all constraints
NSLayoutConstraint.deactivateConstraints(layoutConstraints)
layoutConstraints.removeAll(keepCapacity: false)
......@@ -101,43 +202,72 @@ public class BasicCard : MaterialCard {
var verticalFormat: String = "V:|"
// title
if nil != titleLabel {
layoutConstraints += Layout.constraint("H:|-(16)-[titleLabel]-(16)-|", options: nil, metrics: nil, views: ["titleLabel": titleLabel!])
verticalFormat += "-(16)-[titleLabel(22)]"
views["titleLabel"] = titleLabel!
if nil != titleLabelContainer && nil != titleLabel {
// container
layoutConstraints += Layout.constraint("H:|[titleLabelContainer]|", options: nil, metrics: nil, views: ["titleLabelContainer": titleLabelContainer!])
verticalFormat += "[titleLabelContainer]"
views["titleLabelContainer"] = titleLabelContainer!
// text
titleLabelContainer!.addConstraints(Layout.constraint("H:|-(horizontalSpace)-[titleLabel]-(horizontalSpace)-|", options: nil, metrics: ["horizontalSpace": horizontalSpace], views: ["titleLabel": titleLabel!]))
titleLabelContainer!.addConstraints(Layout.constraint("V:|-(verticalSpace)-[titleLabel(height)]-(verticalSpace)-|", options: nil, metrics: ["verticalSpace": verticalSpace, "height": titleLabel!.font.pointSize + verticalSpace], views: ["titleLabel": titleLabel!]))
}
// details
if nil != detailTextLabel {
layoutConstraints += Layout.constraint("H:|-(16)-[detailTextLabel]-(16)-|", options: nil, metrics: nil, views: ["detailTextLabel": detailTextLabel!])
verticalFormat += "-(16)-[detailTextLabel]"
views["detailTextLabel"] = detailTextLabel!
// detail
if nil != detailLabelContainer && nil != detailLabel {
// container
layoutConstraints += Layout.constraint("H:|[detailLabelContainer]|", options: nil, metrics: nil, views: ["detailLabelContainer": detailLabelContainer!])
verticalFormat += "[detailLabelContainer]"
views["detailLabelContainer"] = detailLabelContainer!
// text
detailLabelContainer!.addConstraints(Layout.constraint("H:|-(horizontalSpace)-[detailLabel]-(horizontalSpace)-|", options: nil, metrics: ["horizontalSpace": horizontalSpace], views: ["detailLabel": detailLabel!]))
detailLabelContainer!.addConstraints(Layout.constraint("V:|-(verticalSpace)-[detailLabel(<=maximumDetailLabelHeight)]-(verticalSpace)-|", options: nil, metrics: ["verticalSpace": verticalSpace, "maximumDetailLabelHeight": maximumDetailLabelHeight], views: ["detailLabel": detailLabel!]))
}
if nil != buttons {
if nil != buttonsContainer && (nil != leftButtons || nil != rightButtons) {
// divider
if nil != divider {
layoutConstraints += Layout.constraint("H:|[divider]|", options: nil, metrics: nil, views: ["divider": divider!])
views["divider"] = divider!
verticalFormat += "-(16)-[divider(1)]"
verticalFormat += "[divider(1)]"
}
// buttons
//container
layoutConstraints += Layout.constraint("H:|[buttonsContainer]|", options: nil, metrics: nil, views: ["buttonsContainer": buttonsContainer!])
verticalFormat += "[buttonsContainer]"
views["buttonsContainer"] = buttonsContainer!
// leftButtons
if nil != leftButtons {
var horizontalFormat: String = "H:|"
var buttonViews: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
for var i: Int = 0, l: Int = buttons!.count; i < l; ++i {
let button: MaterialButton = buttons![i]
addSubview(button)
for var i: Int = 0, l: Int = leftButtons!.count; i < l; ++i {
let button: MaterialButton = leftButtons![i]
buttonsContainer!.addSubview(button)
buttonViews["button\(i)"] = button
views["button\(i)"] = button as AnyObject
horizontalFormat += "-(8)-[button\(i)]"
layoutConstraints += Layout.constraint(verticalFormat + "-(8)-[button\(i)]-(8)-|", options: nil, metrics: nil, views: views)
horizontalFormat += "-(horizontalSpace)-[button\(i)]"
Layout.expandToParentVerticallyWithPad(buttonsContainer!, child: button, top: horizontalSpace, bottom: verticalSpace)
}
buttonsContainer!.addConstraints(Layout.constraint(horizontalFormat, options: nil, metrics: ["horizontalSpace": horizontalSpace], views: buttonViews))
}
layoutConstraints += Layout.constraint(horizontalFormat, options: nil, metrics: nil, views: buttonViews)
} else {
verticalFormat += "-(16)-|"
// rightButtons
if nil != rightButtons {
var horizontalFormat: String = "H:"
var buttonViews: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
for var i: Int = 0, l: Int = rightButtons!.count; i < l; ++i {
let button: MaterialButton = rightButtons![i]
buttonsContainer!.addSubview(button)
buttonViews["button\(i)"] = button
horizontalFormat += "[button\(i)]-(horizontalSpace)-"
Layout.expandToParentVerticallyWithPad(buttonsContainer!, child: button, top: horizontalSpace, bottom: verticalSpace)
}
buttonsContainer!.addConstraints(Layout.constraint(horizontalFormat + "|", options: nil, metrics: ["horizontalSpace": horizontalSpace], views: buttonViews))
}
}
verticalFormat += "|"
// combine constraints
if 0 < layoutConstraints.count {
......@@ -146,3 +276,23 @@ public class BasicCard : MaterialCard {
}
}
}
public func ==(lhs: BasicCard, rhs: BasicCard) -> Bool {
return lhs.tag == rhs.tag
}
public func <=(lhs: BasicCard, rhs: BasicCard) -> Bool {
return lhs.tag <= rhs.tag
}
public func >=(lhs: BasicCard, rhs: BasicCard) -> Bool {
return lhs.tag >= rhs.tag
}
public func >(lhs: BasicCard, rhs: BasicCard) -> Bool {
return lhs.tag > rhs.tag
}
public func <(lhs: BasicCard, rhs: BasicCard) -> Bool {
return lhs.tag < rhs.tag
}
......@@ -89,12 +89,12 @@ public class Capture: NSObject, AVCaptureFileOutputRecordingDelegate {
public weak var delegate: CaptureDelegate?
/**
* setupSession
* prepareSession
* A helper method that prepares the session with the various available inputs and outputs.
* @param preset: String, default: AVCaptureSessionPresetHigh
* @return A boolean value, true if successful, false otherwise.
*/
public func setupSession(preset: String = AVCaptureSessionPresetHigh) -> Bool {
public func prepareSession(preset: String = AVCaptureSessionPresetHigh) -> Bool {
session.sessionPreset = preset
var error: NSError?
......
......@@ -120,18 +120,18 @@ public class Preview: UIView {
required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
prepareView()
}
public override init(frame: CGRect) {
super.init(frame: frame)
setupView()
prepareView()
}
public init() {
super.init(frame: CGRectZero)
setTranslatesAutoresizingMaskIntoConstraints(false)
setupView()
prepareView()
}
//
......@@ -160,10 +160,10 @@ public class Preview: UIView {
}
//
// :name: setupView
// :name: prepareView
// :description: Common setup for view.
//
private func setupView() {
private func prepareView() {
let captureLayer: AVCaptureVideoPreviewLayer = layer as! AVCaptureVideoPreviewLayer
captureLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
......@@ -194,7 +194,7 @@ public class Preview: UIView {
//
private func viewWithColor(color: UIColor) -> UIView {
let view: UIView = UIView(frame: Preview.boxBounds)
view.backgroundColor = .clearColor()
view.backgroundColor = MaterialTheme.clear.color
view.layer.borderColor = color.CGColor
view.layer.borderWidth = 5
view.hidden = true
......@@ -210,7 +210,7 @@ public class Preview: UIView {
view.center = point
view.hidden = false
UIView.animateWithDuration(0.15, delay: 0, options: .CurveEaseInOut, animations: { _ in
view.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1.0)
view.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1)
}) { _ in
let delayInSeconds: Double = 0.5
let popTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
......@@ -248,8 +248,8 @@ public class Preview: UIView {
exposureBox!.hidden = false
UIView.animateWithDuration(0.15, delay: 0, options: .CurveEaseInOut, animations: { _ in
self.focusBox!.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1.0)
self.exposureBox!.layer.transform = CATransform3DMakeScale(0.7, 0.7, 1.0)
self.focusBox!.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1)
self.exposureBox!.layer.transform = CATransform3DMakeScale(0.7, 0.7, 1)
}) { _ in
let delayInSeconds: Double = 0.5
let popTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
......
......@@ -26,6 +26,7 @@ public class FabButton : MaterialButton {
super.prepareView()
setTitleColor(MaterialTheme.white.color, forState: .Normal)
backgroundColor = MaterialTheme.red.darken1
contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
}
//
......
......@@ -27,7 +27,7 @@ public class FlatButton : MaterialButton {
setTitleColor(MaterialTheme.indigo.darken1, forState: .Normal)
pulseColor = MaterialTheme.indigo.darken1
backgroundColor = MaterialTheme.clear.color
contentEdgeInsets = UIEdgeInsetsMake(10, 20, 10, 20)
contentEdgeInsets = UIEdgeInsetsMake(4, 16, 4, 16)
}
//
......
......@@ -18,7 +18,7 @@
import UIKit
public class ImageCard : MaterialCard {
public class ImageCard : MaterialCard, Comparable, Equatable {
//
// :name: layoutConstraints
//
......@@ -29,72 +29,144 @@ public class ImageCard : MaterialCard {
//
internal lazy var views: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
//
// :name: detailTextContainer
//
internal var detailTextContainer: UIView?
/**
:name: verticalSpace
*/
public var verticalSpace: CGFloat = 8
//
// :name: buttonsContainer
//
internal var buttonsContainer: UIView?
/**
:name: horizontalSpace
*/
public var horizontalSpace: CGFloat = 8
/**
:name: shadow
*/
public var shadow: Bool = true {
didSet {
false == shadow ? removeShadow() : prepareShadow()
}
}
/**
:name: maximumImageViewHeight
*/
public var maximumImageViewHeight: CGFloat = 200
/**
:name: imageViewContainer
*/
public private(set) var imageViewContainer: UIView?
/**
:name: imageView
*/
public var imageView: UIImageView? {
didSet {
imageView!.setTranslatesAutoresizingMaskIntoConstraints(false)
imageView!.contentMode = .ScaleAspectFill
imageView!.userInteractionEnabled = false
imageView!.clipsToBounds = true
insertSubview(imageView!, belowSubview: backgroundColorView)
if let t = imageView {
// container
if nil == imageViewContainer {
imageViewContainer = UIView()
imageViewContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
imageViewContainer!.backgroundColor = MaterialTheme.clear.color
addSubview(imageViewContainer!)
}
// text
imageViewContainer!.addSubview(t)
t.setTranslatesAutoresizingMaskIntoConstraints(false)
t.contentMode = .ScaleAspectFill
t.userInteractionEnabled = false
t.clipsToBounds = true
if nil != titleLabel {
titleLabel!.removeFromSuperview()
imageView!.addSubview(titleLabel!)
titleLabelContainer!.backgroundColor = MaterialTheme.clear.color
titleLabel!.textColor = MaterialTheme.white.color
titleLabelContainer!.removeFromSuperview()
imageViewContainer!.addSubview(titleLabelContainer!)
}
prepareCard()
} else {
imageViewContainer?.removeFromSuperview()
}
}
}
/**
:name: titleLabelContainer
*/
public private(set) var titleLabelContainer: UIView?
/**
:name: titleLabel
*/
public var titleLabel: UILabel? {
didSet {
titleLabel!.setTranslatesAutoresizingMaskIntoConstraints(false)
titleLabel!.textColor = MaterialTheme.white.color
titleLabel!.font = Roboto.regularWithSize(22.0)
if let t = titleLabel {
// container
if nil == titleLabelContainer {
titleLabelContainer = UIView()
titleLabelContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
addSubview(titleLabelContainer!)
}
// text
titleLabelContainer!.addSubview(t)
t.setTranslatesAutoresizingMaskIntoConstraints(false)
t.backgroundColor = MaterialTheme.clear.color
t.font = Roboto.mediumWithSize(18)
t.numberOfLines = 1
if nil == imageView {
addSubview(titleLabel!)
titleLabelContainer!.backgroundColor = MaterialTheme.white.color
t.textColor = MaterialTheme.black.color
} else {
imageView!.addSubview(titleLabel!)
titleLabelContainer!.backgroundColor = MaterialTheme.clear.color
t.textColor = MaterialTheme.white.color
titleLabelContainer!.removeFromSuperview()
imageViewContainer!.addSubview(titleLabelContainer!)
}
prepareCard()
} else {
titleLabelContainer?.removeFromSuperview()
}
}
}
/**
:name: detailTextLabel
:name: maximumDetailLabelHeight
*/
public var detailTextLabel: UILabel? {
public var maximumDetailLabelHeight: CGFloat = 144
/**
:name: detailLabelContainer
*/
public private(set) var detailLabelContainer: UIView?
/**
:name: detailLabel
*/
public var detailLabel: UILabel? {
didSet {
if let l = detailLabel {
// container
if nil == detailTextContainer {
detailTextContainer = UIView()
detailTextContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
detailTextContainer!.backgroundColor = MaterialTheme.white.color
addSubview(detailTextContainer!)
if nil == detailLabelContainer {
detailLabelContainer = UIView()
detailLabelContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
detailLabelContainer!.backgroundColor = MaterialTheme.white.color
addSubview(detailLabelContainer!)
}
// text
detailTextContainer!.addSubview(detailTextLabel!)
detailTextLabel!.setTranslatesAutoresizingMaskIntoConstraints(false)
detailTextLabel!.textColor = MaterialTheme.black.color
detailTextLabel!.font = Roboto.lightWithSize(16.0)
detailTextLabel!.numberOfLines = 0
detailTextLabel!.lineBreakMode = .ByWordWrapping
detailLabelContainer!.addSubview(l)
l.setTranslatesAutoresizingMaskIntoConstraints(false)
l.textColor = MaterialTheme.black.color
l.backgroundColor = MaterialTheme.clear.color
l.font = Roboto.lightWithSize(16)
l.numberOfLines = 0
l.lineBreakMode = .ByWordWrapping
prepareCard()
} else {
detailLabelContainer?.removeFromSuperview()
}
}
}
......@@ -103,18 +175,28 @@ public class ImageCard : MaterialCard {
*/
public var divider: UIView? {
didSet {
divider!.setTranslatesAutoresizingMaskIntoConstraints(false)
divider!.backgroundColor = MaterialTheme.blueGrey.lighten4
addSubview(divider!)
if let d = divider {
d.setTranslatesAutoresizingMaskIntoConstraints(false)
d.backgroundColor = MaterialTheme.blueGrey.lighten5
addSubview(d)
prepareCard()
} else {
divider?.removeFromSuperview()
}
}
}
/**
:name: buttons
:name: buttonsContainer
*/
public private(set) var buttonsContainer: UIView?
/**
:name: leftButtons
*/
public var buttons: Array<MaterialButton>? {
public var leftButtons: Array<MaterialButton>? {
didSet {
if let b = leftButtons {
if nil == buttonsContainer {
buttonsContainer = UIView()
buttonsContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
......@@ -122,6 +204,28 @@ public class ImageCard : MaterialCard {
addSubview(buttonsContainer!)
}
prepareCard()
} else {
buttonsContainer?.removeFromSuperview()
}
}
}
/**
:name: rightButtons
*/
public var rightButtons: Array<MaterialButton>? {
didSet {
if let b = rightButtons {
if nil == buttonsContainer {
buttonsContainer = UIView()
buttonsContainer!.setTranslatesAutoresizingMaskIntoConstraints(false)
buttonsContainer!.backgroundColor = MaterialTheme.white.color
addSubview(buttonsContainer!)
}
prepareCard()
} else {
buttonsContainer?.removeFromSuperview()
}
}
}
......@@ -139,6 +243,7 @@ public class ImageCard : MaterialCard {
//
internal override func prepareCard() {
super.prepareCard()
// deactivate and clear all constraints
NSLayoutConstraint.deactivateConstraints(layoutConstraints)
layoutConstraints.removeAll(keepCapacity: false)
......@@ -146,67 +251,98 @@ public class ImageCard : MaterialCard {
// detect all components and create constraints
var verticalFormat: String = "V:|"
if nil != imageView {
layoutConstraints += Layout.constraint("H:|[imageView]|", options: nil, metrics: nil, views: ["imageView": imageView!])
verticalFormat += "[imageView(200)]"
views["imageView"] = imageView!
// image
if nil != imageViewContainer && nil != imageView {
// container
layoutConstraints += Layout.constraint("H:|[imageViewContainer]|", options: nil, metrics: nil, views: ["imageViewContainer": imageViewContainer!])
verticalFormat += "[imageViewContainer]"
views["imageViewContainer"] = imageViewContainer!
// text
imageViewContainer!.addConstraints(Layout.constraint("H:|[imageView]|", options: nil, metrics: nil, views: ["imageView": imageView!]))
imageViewContainer!.addConstraints(Layout.constraint("V:|[imageView(maximumImageViewHeight)]|", options: nil, metrics: ["maximumImageViewHeight": maximumImageViewHeight], views: ["imageView": imageView!]))
}
// title
if nil != titleLabel {
if nil != titleLabelContainer && nil != titleLabel {
if nil == imageView {
layoutConstraints += Layout.constraint("H:|-(16)-[titleLabel]-(16)-|", options: nil, metrics: nil, views: ["titleLabel": titleLabel!])
verticalFormat += "-(16)-[titleLabel(22)]"
// container
layoutConstraints += Layout.constraint("H:|[titleLabelContainer]|", options: nil, metrics: nil, views: ["titleLabelContainer": titleLabelContainer!])
verticalFormat += "[titleLabelContainer]"
views["titleLabelContainer"] = titleLabelContainer!
// text
titleLabelContainer!.addConstraints(Layout.constraint("V:|-(verticalSpace)-[titleLabel(height)]-(verticalSpace)-|", options: nil, metrics: ["verticalSpace": verticalSpace, "height": titleLabel!.font.pointSize + verticalSpace], views: ["titleLabel": titleLabel!]))
} else {
layoutConstraints += Layout.constraint("H:[titleLabel]-(16)-|", options: nil, metrics: nil, views: ["titleLabel": titleLabel!])
Layout.alignFromBottomLeft(imageView!, child: titleLabel!, bottom: 16, left: 16)
//container
Layout.alignFromBottomLeft(imageViewContainer!, child: titleLabelContainer!)
Layout.expandToParentHorizontally(imageViewContainer!, child: titleLabelContainer!)
Layout.height(titleLabelContainer!, child: titleLabel!, height: titleLabel!.font.pointSize + verticalSpace)
// text
titleLabelContainer!.addConstraints(Layout.constraint("V:|-(verticalSpace)-[titleLabel(height)]-(verticalSpace)-|", options: nil, metrics: ["verticalSpace": verticalSpace, "height": titleLabel!.font.pointSize + verticalSpace], views: ["titleLabel": titleLabel!]))
}
views["titleLabel"] = titleLabel!
// common text
titleLabelContainer!.addConstraints(Layout.constraint("H:|-(horizontalSpace)-[titleLabel]-(horizontalSpace)-|", options: nil, metrics: ["horizontalSpace": horizontalSpace], views: ["titleLabel": titleLabel!]))
}
// details
if nil != detailTextContainer && nil != detailTextLabel {
// detail
if nil != detailLabelContainer && nil != detailLabel {
// container
layoutConstraints += Layout.constraint("H:|[detailTextContainer]|", options: nil, metrics: nil, views: ["detailTextContainer": detailTextContainer!])
verticalFormat += "-(0)-[detailTextContainer]"
views["detailTextContainer"] = detailTextContainer!
layoutConstraints += Layout.constraint("H:|[detailLabelContainer]|", options: nil, metrics: nil, views: ["detailLabelContainer": detailLabelContainer!])
verticalFormat += "[detailLabelContainer]"
views["detailLabelContainer"] = detailLabelContainer!
// text
layoutConstraints += Layout.constraint("H:|-(16)-[detailTextLabel]-(16)-|", options: nil, metrics: nil, views: ["detailTextLabel": detailTextLabel!])
layoutConstraints += Layout.constraint("V:|-(16)-[detailTextLabel(<=128)]-(16)-|", options: nil, metrics: nil, views: ["detailTextLabel": detailTextLabel!])
views["detailTextLabel"] = detailTextLabel!
detailLabelContainer!.addConstraints(Layout.constraint("H:|-(horizontalSpace)-[detailLabel]-(horizontalSpace)-|", options: nil, metrics: ["horizontalSpace": horizontalSpace], views: ["detailLabel": detailLabel!]))
detailLabelContainer!.addConstraints(Layout.constraint("V:|-(verticalSpace)-[detailLabel(<=maximumDetailLabelHeight)]-(verticalSpace)-|", options: nil, metrics: ["verticalSpace": verticalSpace, "maximumDetailLabelHeight": maximumDetailLabelHeight], views: ["detailLabel": detailLabel!]))
}
if nil != buttons && nil != buttonsContainer {
if nil != buttonsContainer && (nil != leftButtons || nil != rightButtons) {
// divider
if nil != divider {
layoutConstraints += Layout.constraint("H:|[divider]|", options: nil, metrics: nil, views: ["divider": divider!])
views["divider"] = divider!
verticalFormat += "-(0)-[divider(1)]"
verticalFormat += "[divider(1)]"
}
//container
layoutConstraints += Layout.constraint("H:|[buttonsContainer]|", options: nil, metrics: nil, views: ["buttonsContainer": buttonsContainer!])
verticalFormat += "-(0)-[buttonsContainer]|"
verticalFormat += "[buttonsContainer]"
views["buttonsContainer"] = buttonsContainer!
// buttons
// leftButtons
if nil != leftButtons {
var horizontalFormat: String = "H:|"
var buttonViews: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
for var i: Int = 0, l: Int = buttons!.count; i < l; ++i {
let button: MaterialButton = buttons![i]
for var i: Int = 0, l: Int = leftButtons!.count; i < l; ++i {
let button: MaterialButton = leftButtons![i]
buttonsContainer!.addSubview(button)
buttonViews["button\(i)"] = button
views["button\(i)"] = button as AnyObject
horizontalFormat += "-(8)-[button\(i)]"
layoutConstraints += Layout.constraint("V:|-(8)-[button\(i)]-(8)-|", options: nil, metrics: nil, views: views)
horizontalFormat += "-(horizontalSpace)-[button\(i)]"
Layout.expandToParentVerticallyWithPad(buttonsContainer!, child: button, top: verticalSpace, bottom: verticalSpace)
}
buttonsContainer!.addConstraints(Layout.constraint(horizontalFormat, options: nil, metrics: ["horizontalSpace": horizontalSpace], views: buttonViews))
}
layoutConstraints += Layout.constraint(horizontalFormat, options: nil, metrics: nil, views: buttonViews)
} else {
verticalFormat += "|"
// rightButtons
if nil != rightButtons {
var horizontalFormat: String = "H:"
var buttonViews: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
for var i: Int = 0, l: Int = rightButtons!.count; i < l; ++i {
let button: MaterialButton = rightButtons![i]
buttonsContainer!.addSubview(button)
buttonViews["button\(i)"] = button
horizontalFormat += "[button\(i)]-(horizontalSpace)-"
Layout.expandToParentVerticallyWithPad(buttonsContainer!, child: button, top: verticalSpace, bottom: verticalSpace)
}
buttonsContainer!.addConstraints(Layout.constraint(horizontalFormat + "|", options: nil, metrics: ["horizontalSpace": horizontalSpace], views: buttonViews))
}
}
verticalFormat += "|"
// combine constraints
if 0 < layoutConstraints.count {
layoutConstraints += Layout.constraint(verticalFormat, options: nil, metrics: nil, views: views)
......@@ -214,3 +350,23 @@ public class ImageCard : MaterialCard {
}
}
}
public func ==(lhs: ImageCard, rhs: ImageCard) -> Bool {
return lhs.tag == rhs.tag
}
public func <=(lhs: ImageCard, rhs: ImageCard) -> Bool {
return lhs.tag <= rhs.tag
}
public func >=(lhs: ImageCard, rhs: ImageCard) -> Bool {
return lhs.tag >= rhs.tag
}
public func >(lhs: ImageCard, rhs: ImageCard) -> Bool {
return lhs.tag > rhs.tag
}
public func <(lhs: ImageCard, rhs: ImageCard) -> Bool {
return lhs.tag < rhs.tag
}
////
//// RevealCard.swift
//// MaterialKit
////
//// Created by Adam Dahan on 2015-08-26.
//// Copyright (c) 2015 GraphKit Inc. All rights reserved.
////
//
//import UIKit
//
//public class ImageRevealCard : ImageCard {
//
// private lazy var revealView: UIView = UIView()
// private lazy var tapGesture: UITapGestureRecognizer = UITapGestureRecognizer()
// private lazy var metrics: Dictionary <String, AnyObject> = Dictionary <String, AnyObject>()
// private var topLayoutConstraint: NSLayoutConstraint!
// private lazy var hideRevealViewButton: UIButton = UIButton()
//
// public required init(coder aDecoder: NSCoder) {
// super.init(coder: aDecoder)
// }
//
// public required init(frame: CGRect) {
// super.init(frame: frame)
// }
//
// internal override func initialize() {
// prepareTapGestures()
// prepareRevealView()
// prepareHideRevealViewButton()
// super.initialize()
// }
//
// public override func layoutSubviews() {
// super.layoutSubviews()
// revealView.frame = CGRectMake(0, 0, bounds.width, bounds.height)
// hideRevealViewButton.frame = CGRectMake(CGRectGetMaxX(revealView.frame) - 50, 10, 40, 40)
// }
//
// private func prepareTapGestures() {
// tapGesture.addTarget(self, action: "showRevealView")
// imageView.userInteractionEnabled = true
// addGestureRecognizer(tapGesture)
// }
//
// private func prepareRevealView() {
// revealView.backgroundColor = .whiteColor()
// revealView.hidden = true
// imageView.addSubview(revealView)
// }
//
// private func prepareHideRevealViewButton() {
// hideRevealViewButton.setImage(UIImage(named: "ic_clear"), forState: .Normal)
// hideRevealViewButton.tintColor = .whiteColor()
// hideRevealViewButton.addTarget(self, action: "hideRevealView", forControlEvents: UIControlEvents.TouchUpInside)
// revealView.addSubview(hideRevealViewButton)
// }
//
// internal func showRevealView() {
// removeTapGestures()
// revealView.hidden = false
// revealView.frame = CGRectMake(0, bounds.height, bounds.width, bounds.height)
// UIView.animateWithDuration(0.3, animations: { () -> Void in
// var frame = self.revealView.frame
// frame.origin.y -= self.bounds.height
// self.revealView.frame = frame
// })
// }
//
// internal func hideRevealView() {
// UIView.animateWithDuration(0.3, animations: { () -> Void in
// var frame = self.revealView.frame
// frame.origin.y = self.bounds.height
// self.revealView.frame = frame
// }) { (finished) -> Void in
// self.revealView.hidden = true
// self.prepareTapGestures()
// }
// }
//
// private func removeTapGestures() {
// removeGestureRecognizer(tapGesture)
// }
//}
//
//
//
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.6.0</string>
<string>1.7.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
......
......@@ -22,7 +22,7 @@ public struct Layout {
/**
:name: width
*/
public static func width(parent: UIView, child: UIView, width: CGFloat) {
public static func width(parent: UIView, child: UIView, width: CGFloat = 0) {
let metrics: Dictionary<String, AnyObject> = ["width" : width]
let views: Dictionary<String, AnyObject> = ["child" : child]
parent.addConstraints(constraint("H:[child(width)]", options: nil, metrics: metrics, views: views))
......@@ -31,7 +31,7 @@ public struct Layout {
/**
:name: height
*/
public static func height(parent: UIView, child: UIView, height: CGFloat) {
public static func height(parent: UIView, child: UIView, height: CGFloat = 0) {
let metrics: Dictionary<String, AnyObject> = ["height" : height]
let views: Dictionary<String, AnyObject> = ["child" : child]
parent.addConstraints(constraint("V:[child(height)]", options: nil, metrics: metrics, views: views))
......@@ -40,24 +40,52 @@ public struct Layout {
/**
:name: size
*/
public static func size(parent: UIView, child: UIView, width: CGFloat, height: CGFloat) {
public static func size(parent: UIView, child: UIView, width: CGFloat = 0, height: CGFloat = 0) {
Layout.width(parent, child: child, width: width)
Layout.height(parent, child: child, height: height)
}
/**
:name: expandToParentSize
:name: expandToParent
*/
public static func expandToParentSize(parent: UIView, child: UIView) {
public static func expandToParent(parent: UIView, child: UIView) {
let views: Dictionary<String, AnyObject> = ["child" : child]
parent.addConstraints(constraint("H:|[child]|", options: nil, metrics: nil, views: views))
parent.addConstraints(constraint("V:|[child]|", options: nil, metrics: nil, views: views))
}
/**
:name: expandToParentSizeWithPad
:name: expandToParentHorizontally
*/
public static func expandToParentSizeWithPad(parent: UIView, child: UIView, left: CGFloat, bottom: CGFloat, right: CGFloat, top: CGFloat) {
public static func expandToParentHorizontally(parent: UIView, child: UIView) {
expandToParentHorizontallyWithPad(parent, child: child, left: 0, right: 0)
}
/**
:name: expandToParentHorizontallyWithPad
*/
public static func expandToParentHorizontallyWithPad(parent: UIView, child: UIView, left: CGFloat = 0, right: CGFloat = 0) {
parent.addConstraints(constraint("H:|-(left)-[child]-(right)-|", options: nil, metrics: ["left": left, "right": right], views: ["child" : child]))
}
/**
:name: expandToParentVertically
*/
public static func expandToParentVertically(parent: UIView, child: UIView) {
expandToParentVerticallyWithPad(parent, child: child, top: 0, bottom: 0)
}
/**
:name: expandToParentVerticallyWithPad
*/
public static func expandToParentVerticallyWithPad(parent: UIView, child: UIView, top: CGFloat = 0, bottom: CGFloat = 0) {
parent.addConstraints(constraint("V:|-(top)-[child]-(bottom)-|", options: nil, metrics: ["bottom": bottom, "top": top], views: ["child" : child]))
}
/**
:name: expandToParentWithPad
*/
public static func expandToParentWithPad(parent: UIView, child: UIView, top: CGFloat = 0, left: CGFloat = 0, bottom: CGFloat = 0, right: CGFloat = 0) {
let views: Dictionary<String, AnyObject> = ["child" : child]
parent.addConstraints(constraint("H:|-(left)-[child]-(right)-|", options: nil, metrics: ["left": left, "right": right], views: views))
parent.addConstraints(constraint("V:|-(top)-[child]-(bottom)-|", options: nil, metrics: ["bottom": bottom, "top": top], views: views))
......@@ -66,7 +94,7 @@ public struct Layout {
/**
:name: alignFromTopLeft
*/
public static func alignFromTopLeft(parent: UIView, child: UIView, top: CGFloat, left: CGFloat) {
public static func alignFromTopLeft(parent: UIView, child: UIView, top: CGFloat = 0, left: CGFloat = 0) {
let metrics: Dictionary<String, AnyObject> = ["top" : top, "left" : left]
let views: Dictionary<String, AnyObject> = ["child" : child]
parent.addConstraints(constraint("H:|-(left)-[child]", options: nil, metrics: metrics, views: views))
......@@ -76,7 +104,7 @@ public struct Layout {
/**
:name: alignFromTopRight
*/
public static func alignFromTopRight(parent: UIView, child: UIView, top: CGFloat, right: CGFloat) {
public static func alignFromTopRight(parent: UIView, child: UIView, top: CGFloat = 0, right: CGFloat = 0) {
let metrics: Dictionary<String, AnyObject> = ["top" : top, "right" : right]
let views: Dictionary<String, AnyObject> = ["child" : child]
parent.addConstraints(constraint("H:[child]-(right)-|", options: nil, metrics: metrics, views: views))
......@@ -86,7 +114,7 @@ public struct Layout {
/**
:name: alignFromBottomLeft
*/
public static func alignFromBottomLeft(parent: UIView, child: UIView, bottom: CGFloat, left: CGFloat) {
public static func alignFromBottomLeft(parent: UIView, child: UIView, bottom: CGFloat = 0, left: CGFloat = 0) {
let metrics: Dictionary<String, AnyObject> = ["bottom" : bottom, "left" : left]
let views: Dictionary<String, AnyObject> = ["child" : child]
parent.addConstraints(constraint("H:|-(left)-[child]", options: nil, metrics: metrics, views: views))
......@@ -96,7 +124,7 @@ public struct Layout {
/**
:name: alignFromBottomRight
*/
public static func alignFromBottomRight(parent: UIView, child: UIView, bottom: CGFloat, right: CGFloat) {
public static func alignFromBottomRight(parent: UIView, child: UIView, bottom: CGFloat = 0, right: CGFloat = 0) {
let metrics: Dictionary<String, AnyObject> = ["bottom" : bottom, "right" : right]
let views: Dictionary<String, AnyObject> = ["child" : child]
parent.addConstraints(constraint("H:[child]-(right)-|", options: nil, metrics: metrics, views: views))
......
......@@ -44,7 +44,7 @@ public class MaterialButton : UIButton {
/**
:name: pulseColor
*/
public var pulseColor: UIColor? = MaterialTheme.white.color
public var pulseColor: UIColor? = MaterialTheme.blueGrey.lighten3
/**
:name: init
......@@ -100,6 +100,7 @@ public class MaterialButton : UIButton {
*/
final public override func drawRect(rect: CGRect) {
prepareContext(rect)
prepareBackgroundColorView()
prepareButton()
}
......@@ -108,7 +109,6 @@ public class MaterialButton : UIButton {
//
internal func prepareView() {
setTranslatesAutoresizingMaskIntoConstraints(false)
prepareBackgroundColorView()
}
//
......@@ -166,15 +166,13 @@ public class MaterialButton : UIButton {
//
// :name: prepareBackgroundColorView
//
// We need this view so we can use the masksToBounds
// so the pulse doesn't animate off the button
private func prepareBackgroundColorView() {
backgroundColorView.setTranslatesAutoresizingMaskIntoConstraints(false)
backgroundColorView.layer.masksToBounds = true
backgroundColorView.clipsToBounds = true
backgroundColorView.userInteractionEnabled = false
insertSubview(backgroundColorView, atIndex: 0)
Layout.expandToParentSize(self, child: backgroundColorView)
Layout.expandToParent(self, child: backgroundColorView)
}
//
......
......@@ -25,6 +25,11 @@ public class MaterialCard : UIView {
internal lazy var backgroundColorView: UIView = UIView()
//
// :name: pulseViewContainer
//
internal lazy var pulseViewContainer: UIView = UIView()
//
// :name: pulseView
//
internal var pulseView: UIView?
......@@ -44,7 +49,7 @@ public class MaterialCard : UIView {
/**
:name: pulseColor
*/
public var pulseColor: UIColor = MaterialTheme.white.color
public var pulseColor: UIColor = MaterialTheme.blueGrey.lighten3
/**
:name: init
......@@ -101,6 +106,7 @@ public class MaterialCard : UIView {
internal func prepareView() {
setTranslatesAutoresizingMaskIntoConstraints(false)
prepareBackgroundColorView()
preparePulseViewContainer()
prepareCard()
}
......@@ -114,10 +120,19 @@ public class MaterialCard : UIView {
//
internal func prepareShadow() {
layer.shadowColor = MaterialTheme.black.color.CGColor
layer.shadowOffset = CGSizeMake(0.5, 0.5)
layer.shadowOpacity = 0.5
layer.shadowRadius = 5
layer.cornerRadius = 2
layer.shadowOffset = CGSizeMake(0.05, 0.05)
layer.shadowOpacity = 0.1
layer.shadowRadius = 3
}
//
// :name: removeShadow
//
internal func removeShadow() {
layer.shadowColor = MaterialTheme.clear.color.CGColor
layer.shadowOffset = CGSizeMake(0, 0)
layer.shadowOpacity = 0
layer.shadowRadius = 0
}
//
......@@ -136,8 +151,10 @@ public class MaterialCard : UIView {
pulseView = UIView(frame: CGRectMake(0, 0, width, width))
pulseView!.layer.cornerRadius = width / 2
pulseView!.center = (touches.first as! UITouch).locationInView(self)
pulseView!.backgroundColor = pulseColor.colorWithAlphaComponent(0.5)
backgroundColorView.addSubview(pulseView!)
pulseView!.backgroundColor = pulseColor.colorWithAlphaComponent(0.3)
addSubview(pulseViewContainer)
Layout.expandToParent(self, child: pulseViewContainer)
pulseViewContainer.addSubview(pulseView!)
UIView.animateWithDuration(0.3, animations: {
self.pulseView!.transform = CGAffineTransformMakeScale(3, 3)
self.transform = CGAffineTransformMakeScale(1.05, 1.05)
......@@ -153,6 +170,7 @@ public class MaterialCard : UIView {
self.pulseView?.alpha = 0
}
) { _ in
self.pulseViewContainer.removeFromSuperview()
self.pulseView?.removeFromSuperview()
self.pulseView = nil
}
......@@ -170,7 +188,20 @@ public class MaterialCard : UIView {
backgroundColorView.clipsToBounds = true
backgroundColorView.userInteractionEnabled = false
insertSubview(backgroundColorView, atIndex: 0)
Layout.expandToParentSize(self, child: backgroundColorView)
Layout.expandToParent(self, child: backgroundColorView)
}
//
// :name: preparePulseViewContainer
//
// We need this view so we can use the masksToBounds
// so the pulse doesn't animate off the button
private func preparePulseViewContainer() {
pulseViewContainer.setTranslatesAutoresizingMaskIntoConstraints(false)
pulseViewContainer.layer.cornerRadius = 2
pulseViewContainer.layer.masksToBounds = true
pulseViewContainer.clipsToBounds = true
pulseViewContainer.userInteractionEnabled = false
}
//
......
......@@ -21,7 +21,7 @@ import UIKit
public struct MaterialTheme {
// clear
public struct clear {
public static let color: UIColor = white.color.colorWithAlphaComponent(0)
public static let color: UIColor = UIColor.clearColor()
}
// white
......
......@@ -26,7 +26,7 @@ public class RaisedButton : MaterialButton {
super.prepareView()
setTitleColor(MaterialTheme.white.color, forState: .Normal)
backgroundColor = MaterialTheme.indigo.darken1
contentEdgeInsets = UIEdgeInsetsMake(10, 20, 10, 20)
contentEdgeInsets = UIEdgeInsetsMake(4, 16, 4, 16)
}
//
......
......@@ -20,22 +20,22 @@ import UIKit
public struct Roboto {
public static func lightWithSize(size: CGFloat) -> UIFont {
if let light = UIFont(name: "Roboto-Light", size: size) {
return light
if let f = UIFont(name: "Roboto-Light", size: size) {
return f
}
return UIFont.systemFontOfSize(size)
}
public static func mediumWithSize(size: CGFloat) -> UIFont {
if let light = UIFont(name: "Roboto-Medium", size: size) {
return light
if let f = UIFont(name: "Roboto-Medium", size: size) {
return f
}
return UIFont.systemFontOfSize(size)
}
public static func regularWithSize(size: CGFloat) -> UIFont {
if let light = UIFont(name: "Roboto-Regular", size: size) {
return light
if let f = UIFont(name: "Roboto-Regular", size: size) {
return f
}
return UIFont.systemFontOfSize(size)
}
......
......@@ -25,13 +25,32 @@ public enum SideNavState {
@objc(SideNavContainer)
public class SideNavContainer : Printable {
/**
:name: state
*/
public private(set) var state: SideNavState
/**
:name: point
*/
public private(set) var point: CGPoint
/**
:name: frame
*/
public private(set) var frame: CGRect
/**
:name: description
*/
public var description: String {
let s: String = .Opened == state ? "Opened" : "Closed"
return "(state: \(s), point: \(point), frame: \(frame))"
}
/**
:name: init
*/
public init(state: SideNavState, point: CGPoint, frame: CGRect) {
self.state = state
self.point = point
......@@ -64,33 +83,57 @@ public protocol SideNavDelegate {
optional func sideNavDidOpenBottomViewContainer(nav: SideNavController, container: SideNavContainer)
optional func sideNavDidCloseBottomViewContainer(nav: SideNavController, container: SideNavContainer)
optional func sideNavDidTapBottom(nav: SideNavController, container: SideNavContainer)
// top
optional func sideNavDidBeginTopPan(nav: SideNavController, container: SideNavContainer)
optional func sideNavDidChangeTopPan(nav: SideNavController, container: SideNavContainer)
optional func sideNavDidEndTopPan(nav: SideNavController, container: SideNavContainer)
optional func sideNavDidOpenTopViewContainer(nav: SideNavController, container: SideNavContainer)
optional func sideNavDidCloseTopViewContainer(nav: SideNavController, container: SideNavContainer)
optional func sideNavDidTapTop(nav: SideNavController, container: SideNavContainer)
}
@objc(SideNavController)
public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
/**
:name: default options
*/
public struct defaultOptions {
public static var bezelWidth: CGFloat = 48
public static var bezelHeight: CGFloat = 48
public static var containerWidth: CGFloat = 240
public static var containerHeight: CGFloat = 240
public static var defaultAnimationDuration: CGFloat = 0.3
public static var threshold: CGFloat = 48
public static var panningEnabled: Bool = true
}
/**
:name: options
*/
public struct options {
public static var shadowOpacity: Float = 0
public static var shadowRadius: CGFloat = 0
public static var shadowOffset: CGSize = CGSizeZero
public static var contentViewScale: CGFloat = 1
public static var contentViewOpacity: CGFloat = 0.5
public static var backdropScale: CGFloat = 1
public static var backdropOpacity: CGFloat = 0.5
public static var hideStatusBar: Bool = true
public static var horizontalThreshold: CGFloat = 48
public static var verticalThreshold: CGFloat = 48
public static var horizontalThreshold: CGFloat = defaultOptions.threshold
public static var verticalThreshold: CGFloat = defaultOptions.threshold
public static var backdropBackgroundColor: UIColor = MaterialTheme.black.color
public static var animationDuration: CGFloat = 0.3
public static var leftBezelWidth: CGFloat = 16
public static var leftViewContainerWidth: CGFloat = 240
public static var leftPanFromBezel: Bool = true
public static var rightBezelWidth: CGFloat = 16
public static var rightViewContainerWidth: CGFloat = 240
public static var rightPanFromBezel: Bool = true
public static var bottomBezelHeight: CGFloat = 48
public static var bottomViewContainerHeight: CGFloat = 240
public static var bottomPanFromBezel: Bool = true
public static var animationDuration: CGFloat = defaultOptions.defaultAnimationDuration
public static var leftBezelWidth: CGFloat = defaultOptions.bezelWidth
public static var leftViewContainerWidth: CGFloat = defaultOptions.containerWidth
public static var leftPanFromBezel: Bool = defaultOptions.panningEnabled
public static var rightBezelWidth: CGFloat = defaultOptions.bezelWidth
public static var rightViewContainerWidth: CGFloat = defaultOptions.containerWidth
public static var rightPanFromBezel: Bool = defaultOptions.panningEnabled
public static var bottomBezelHeight: CGFloat = defaultOptions.bezelHeight
public static var bottomViewContainerHeight: CGFloat = defaultOptions.containerHeight
public static var bottomPanFromBezel: Bool = defaultOptions.panningEnabled
public static var topBezelHeight: CGFloat = defaultOptions.bezelHeight
public static var topViewContainerHeight: CGFloat = defaultOptions.containerHeight
public static var topPanFromBezel: Bool = defaultOptions.panningEnabled
}
/**
......@@ -136,6 +179,16 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
/**
:name: isTopContainerOpened
*/
public var isTopContainerOpened: Bool {
if let c = topViewContainer {
return c.frame.origin.y != topOriginY
}
return false
}
/**
:name: isUserInteractionEnabled
*/
public var isUserInteractionEnabled: Bool {
......@@ -173,6 +226,11 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
public private(set) var bottomViewContainer: UIView?
/**
:name: bottomViewContainer
*/
public private(set) var topViewContainer: UIView?
/**
:name: leftContainer
*/
public private(set) var leftContainer: SideNavContainer?
......@@ -188,6 +246,11 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
public private(set) var bottomContainer: SideNavContainer?
/**
:name: topContainer
*/
public private(set) var topContainer: SideNavContainer?
/**
:name: mainViewController
*/
public var mainViewController: UIViewController?
......@@ -208,6 +271,11 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
public var bottomViewController: UIViewController?
/**
:name: topViewController
*/
public var topViewController: UIViewController?
/**
:name: leftPanGesture
*/
public var leftPanGesture: UIPanGestureRecognizer?
......@@ -228,6 +296,11 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
public var bottomTapGesture: UITapGestureRecognizer?
/**
:name: topTapGesture
*/
public var topTapGesture: UITapGestureRecognizer?
/**
:name: rightPanGesture
*/
public var rightPanGesture: UIPanGestureRecognizer?
......@@ -237,6 +310,11 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
*/
public var bottomPanGesture: UIPanGestureRecognizer?
/**
:name: rightPanGesture
*/
public var topPanGesture: UIPanGestureRecognizer?
//
// :name: leftOriginX
//
......@@ -258,6 +336,13 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
return view.bounds.height
}
//
// :name: topOriginY
//
private var topOriginY: CGFloat {
return -options.topViewContainerHeight
}
/**
:name: init
*/
......@@ -308,6 +393,17 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
/**
:name: init
*/
public convenience init(mainViewController: UIViewController, topViewController: UIViewController) {
self.init()
self.mainViewController = mainViewController
self.topViewController = topViewController
prepareView()
prepareTopView()
}
/**
:name: init
*/
public convenience init(mainViewController: UIViewController, leftViewController: UIViewController, rightViewController: UIViewController) {
self.init()
self.mainViewController = mainViewController
......@@ -336,6 +432,23 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
/**
:name: init
*/
public convenience init(mainViewController: UIViewController, leftViewController: UIViewController, bottomViewController: UIViewController, rightViewController: UIViewController, topViewController: UIViewController) {
self.init()
self.mainViewController = mainViewController
self.leftViewController = leftViewController
self.bottomViewController = bottomViewController
self.rightViewController = rightViewController
self.topViewController = topViewController
prepareView()
prepareLeftView()
prepareBottomView()
prepareRightView()
prepareTopView()
}
/**
:name: init
*/
public convenience init(mainViewController: UIViewController, bottomViewController: UIViewController, rightViewController: UIViewController) {
self.init()
self.mainViewController = mainViewController
......@@ -346,6 +459,32 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
prepareRightView()
}
/**
:name: init
*/
public convenience init(mainViewController: UIViewController, bottomViewController: UIViewController, topViewController: UIViewController) {
self.init()
self.mainViewController = mainViewController
self.bottomViewController = bottomViewController
self.topViewController = topViewController
prepareView()
prepareBottomView()
prepareTopView()
}
/**
:name: init
*/
public convenience init(mainViewController: UIViewController, rightViewController: UIViewController, topViewController: UIViewController) {
self.init()
self.mainViewController = mainViewController
self.rightViewController = rightViewController
self.topViewController = topViewController
prepareView()
prepareRightView()
prepareTopView()
}
//
// :name: viewDidLoad
//
......@@ -359,11 +498,22 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
//
public override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if mainViewController != nil {
prepareContainedViewController(&mainViewContainer, viewController: &mainViewController)
}
if leftViewController != nil {
prepareContainedViewController(&leftViewContainer, viewController: &leftViewController)
}
if rightViewController != nil {
prepareContainedViewController(&rightViewContainer, viewController: &rightViewController)
}
if bottomViewController != nil {
prepareContainedViewController(&bottomViewContainer, viewController: &bottomViewController)
}
if topViewController != nil {
prepareContainedViewController(&topViewContainer, viewController: &topViewController)
}
}
/**
:name: toggleLeftViewContainer
......@@ -380,6 +530,20 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
/**
:name: toggleBottomViewContainer
*/
public func toggleBottomViewContainer(velocity: CGFloat = 0) {
isBottomContainerOpened ? closeBottomViewContainer(velocity: velocity) : openBottomViewContainer(velocity: velocity)
}
/**
:name: toggleTopViewContainer
*/
public func toggleTopViewContainer(velocity: CGFloat = 0) {
isTopContainerOpened ? closeTopViewContainer(velocity: velocity) : openTopViewContainer(velocity: velocity)
}
/**
:name: openLeftViewContainer
*/
public func openLeftViewContainer(velocity: CGFloat = 0) {
......@@ -391,8 +555,8 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
options: .CurveEaseInOut,
animations: { _ in
vc.frame.origin.x = 0
self.backdropViewContainer?.layer.opacity = Float(options.contentViewOpacity)
self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.contentViewScale, options.contentViewScale)
self.backdropViewContainer?.layer.opacity = Float(options.backdropOpacity)
self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.backdropScale, options.backdropScale)
}
) { _ in
self.isUserInteractionEnabled = false
......@@ -415,8 +579,8 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
options: .CurveEaseInOut,
animations: { _ in
vc.frame.origin.x = self.rightOriginX - vc.frame.size.width
self.backdropViewContainer?.layer.opacity = Float(options.contentViewOpacity)
self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.contentViewScale, options.contentViewScale)
self.backdropViewContainer?.layer.opacity = Float(options.backdropOpacity)
self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.backdropScale, options.backdropScale)
}
) { _ in
self.isUserInteractionEnabled = false
......@@ -428,7 +592,7 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
/**
:name: openRightViewContainer
:name: openBottomViewContainer
*/
public func openBottomViewContainer(velocity: CGFloat = 0) {
if let vc = bottomViewContainer {
......@@ -439,8 +603,8 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
options: .CurveEaseInOut,
animations: { _ in
vc.frame.origin.y = self.bottomOriginY - vc.frame.size.height
self.backdropViewContainer?.layer.opacity = Float(options.contentViewOpacity)
self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.contentViewScale, options.contentViewScale)
self.backdropViewContainer?.layer.opacity = Float(options.backdropOpacity)
self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.backdropScale, options.backdropScale)
}
) { _ in
self.isUserInteractionEnabled = false
......@@ -452,6 +616,30 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
/**
:name: openTopViewContainer
*/
public func openTopViewContainer(velocity: CGFloat = 0) {
if let vc = topViewContainer {
if let c = topContainer {
prepareContainerToOpen(&topViewController, viewContainer: &topViewContainer, state: c.state)
UIView.animateWithDuration(Double(0 == velocity ? options.animationDuration : fmax(0.1, fmin(1, Double(fabs(vc.frame.origin.y + topOriginY) / velocity)))),
delay: 0,
options: .CurveEaseInOut,
animations: { _ in
vc.frame.origin.y = self.topOriginY + vc.frame.size.height
self.backdropViewContainer?.layer.opacity = Float(options.backdropOpacity)
self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.backdropScale, options.backdropScale)
}
) { _ in
self.isUserInteractionEnabled = false
}
c.state = .Opened
delegate?.sideNavDidOpenTopViewContainer?(self, container: c)
}
}
}
/**
:name: closeLeftViewContainer
*/
public func closeLeftViewContainer(velocity: CGFloat = 0) {
......@@ -502,7 +690,7 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
/**
:name: closeRightViewContainer
:name: closeBottomViewContainer
*/
public func closeBottomViewContainer(velocity: CGFloat = 0) {
if let vc = bottomViewContainer {
......@@ -526,6 +714,31 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
}
/**
:name: closeBottomViewContainer
*/
public func closeTopViewContainer(velocity: CGFloat = 0) {
if let vc = topViewContainer {
if let c = topContainer {
prepareContainerToClose(&topViewController, state: c.state)
UIView.animateWithDuration(Double(0 == velocity ? options.animationDuration : fmax(0.1, fmin(1, fabs(vc.frame.origin.y - topOriginY) / velocity))),
delay: 0,
options: .CurveEaseInOut,
animations: { _ in
vc.frame.origin.y = self.topOriginY
self.backdropViewContainer?.layer.opacity = 0
self.mainViewContainer?.transform = CGAffineTransformMakeScale(1, 1)
}
) { _ in
self.removeShadow(&self.topViewContainer)
self.isUserInteractionEnabled = true
}
c.state = .Closed
delegate?.sideNavDidCloseBottomViewContainer?(self, container: c)
}
}
}
/**
:name: switchMainViewController
......@@ -576,6 +789,18 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
}
/**
:name: switchTopViewController
*/
public func switchTopViewController(viewController: UIViewController, closeTopViewContainerViewContainer: Bool) {
removeViewController(&topViewController)
topViewController = viewController
prepareContainedViewController(&topViewContainer, viewController: &topViewController)
if closeTopViewContainerViewContainer {
closeTopViewContainer()
}
}
//
// :name: gestureRecognizer
//
......@@ -589,6 +814,9 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
if gestureRecognizer == bottomPanGesture {
return gesturePanBottomViewController(gestureRecognizer, withTouchPoint: touch.locationInView(view))
}
if gestureRecognizer == topPanGesture {
return gesturePanTopViewController(gestureRecognizer, withTouchPoint: touch.locationInView(view))
}
if gestureRecognizer == leftTapGesture {
return isLeftContainerOpened && !isPointContainedWithinViewController(&leftViewContainer, point: touch.locationInView(view))
}
......@@ -598,6 +826,9 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
if gestureRecognizer == bottomTapGesture {
return isBottomContainerOpened && !isPointContainedWithinViewController(&bottomViewContainer, point: touch.locationInView(view))
}
if gestureRecognizer == topTapGesture {
return isTopContainerOpened && !isPointContainedWithinViewController(&topViewContainer, point: touch.locationInView(view))
}
return true
}
......@@ -634,6 +865,14 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
//
// :name: prepareBottomView
//
internal func prepareTopView() {
prepareContainer(&topContainer, viewContainer: &topViewContainer, originX: 0, originY: topOriginY, width: view.bounds.size.width, height: options.topViewContainerHeight)
prepareTopGestures()
}
//
// :name: addGestures
//
private func addGestures(inout pan: UIPanGestureRecognizer?, panSelector: Selector, inout tap: UITapGestureRecognizer?, tapSelector: Selector) {
......@@ -667,7 +906,7 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
// :name: handleLeftPanGesture
//
internal func handleLeftPanGesture(gesture: UIPanGestureRecognizer) {
if isRightContainerOpened { return }
if isRightContainerOpened || isBottomContainerOpened || isTopContainerOpened { return }
if let vc = leftViewContainer {
if let c = leftContainer {
if .Began == gesture.state {
......@@ -680,10 +919,10 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
} else if .Changed == gesture.state {
c.point = gesture.translationInView(gesture.view!)
let r = (vc.frame.origin.x - leftOriginX) / vc.frame.size.width
let s: CGFloat = 1 - (1 - options.contentViewScale) * r
let s: CGFloat = 1 - (1 - options.backdropScale) * r
let x: CGFloat = c.frame.origin.x + c.point.x
vc.frame.origin.x = x < leftOriginX ? leftOriginX : x > 0 ? 0 : x
backdropViewContainer?.layer.opacity = Float(r * options.contentViewOpacity)
backdropViewContainer?.layer.opacity = Float(r * options.backdropOpacity)
mainViewContainer?.transform = CGAffineTransformMakeScale(s, s)
delegate?.sideNavDidChangeLeftPan?(self, container: c)
} else {
......@@ -715,7 +954,7 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
// :name: handleRightPanGesture
//
internal func handleRightPanGesture(gesture: UIPanGestureRecognizer) {
if isLeftContainerOpened { return }
if isLeftContainerOpened || isBottomContainerOpened || isTopContainerOpened { return }
if let vc = rightViewContainer {
if let c = rightContainer {
if .Began == gesture.state {
......@@ -728,12 +967,10 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
} else if .Changed == gesture.state {
c.point = gesture.translationInView(gesture.view!)
let r = (rightOriginX - vc.frame.origin.x) / vc.frame.size.width
let s: CGFloat = 1 - (1 - options.contentViewScale) * r
let m: CGFloat = rightOriginX - vc.frame.size.width
let x: CGFloat = c.frame.origin.x + c.point.x
vc.frame.origin.x = x > rightOriginX ? rightOriginX : x < m ? m : x
backdropViewContainer?.layer.opacity = Float(r * options.contentViewOpacity)
mainViewContainer?.transform = CGAffineTransformMakeScale(s, s)
backdropViewContainer?.layer.opacity = Float(r * options.backdropOpacity)
delegate?.sideNavDidChangeRightPan?(self, container: c)
} else {
c.point = gesture.velocityInView(gesture.view)
......@@ -761,38 +998,28 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
//
// :name: handleRightPanGesture
// :name: handleBottomPanGesture
//
internal func handleBottomPanGesture(gesture: UIPanGestureRecognizer) {
if isLeftContainerOpened || isRightContainerOpened { return }
if .Began == gesture.state {
if isLeftContainerOpened || isRightContainerOpened || isTopContainerOpened { return }
if let vc = bottomViewContainer {
if let c = bottomContainer {
if .Began == gesture.state {
addShadow(&bottomViewContainer)
toggleStatusBar(hide: true)
c.state = isBottomContainerOpened ? .Opened : .Closed
c.point = gesture.locationInView(view)
c.frame = vc.frame
delegate?.sideNavDidBeginBottomPan?(self, container: c)
}
}
} else if .Changed == gesture.state {
if let vc = bottomViewContainer {
if let c = bottomContainer {
c.point = gesture.translationInView(gesture.view!)
let r = (bottomOriginY - vc.frame.origin.y) / vc.frame.size.height
let s: CGFloat = 1 - (1 - options.contentViewScale) * r
let m: CGFloat = bottomOriginY - vc.frame.size.height
let y: CGFloat = c.frame.origin.y + c.point.y
vc.frame.origin.y = y > bottomOriginY ? bottomOriginY : y < m ? m : y
backdropViewContainer?.layer.opacity = Float(r * options.contentViewOpacity)
mainViewContainer?.transform = CGAffineTransformMakeScale(s, s)
backdropViewContainer?.layer.opacity = Float(r * options.backdropOpacity)
delegate?.sideNavDidChangeBottomPan?(self, container: c)
}
}
} else {
if let vc = bottomViewContainer {
if let c = bottomContainer {
c.point = gesture.velocityInView(gesture.view)
let y: CGFloat = c.point.y <= -1000 || c.point.y >= 1000 ? c.point.y : 0
c.state = vc.frame.origin.y >= CGFloat(floor(bottomOriginY) - options.verticalThreshold) || c.point.y >= 1000 ? .Closed : .Opened
......@@ -818,6 +1045,53 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
//
// :name: handleTopPanGesture
//
internal func handleTopPanGesture(gesture: UIPanGestureRecognizer) {
if isLeftContainerOpened || isRightContainerOpened || isBottomContainerOpened { return }
if let vc = topViewContainer {
if let c = topContainer {
if .Began == gesture.state {
addShadow(&topViewContainer)
toggleStatusBar(hide: true)
c.state = isTopContainerOpened ? .Opened : .Closed
c.point = gesture.locationInView(view)
c.frame = vc.frame
delegate?.sideNavDidBeginTopPan?(self, container: c)
} else if .Changed == gesture.state {
c.point = gesture.translationInView(gesture.view!)
let r = (topOriginY - vc.frame.origin.y) / vc.frame.size.height
let m: CGFloat = topOriginY + vc.frame.size.height
let y: CGFloat = c.frame.origin.y + c.point.y // increase origin y
vc.frame.origin.y = y < topOriginY ? topOriginY : y < m ? y : m
backdropViewContainer?.layer.opacity = Float(abs(r) * options.backdropOpacity)
delegate?.sideNavDidChangeTopPan?(self, container: c)
} else {
c.point = gesture.velocityInView(gesture.view)
let y: CGFloat = c.point.y <= -1000 || c.point.y >= 1000 ? c.point.y : 0
c.state = vc.frame.origin.y >= CGFloat(floor(topOriginY) + options.verticalThreshold) || c.point.y >= 1000 ? .Opened : .Closed
if .Closed == c.state {
closeTopViewContainer(velocity: y)
} else {
openTopViewContainer(velocity: y)
}
delegate?.sideNavDidEndTopPan?(self, container: c)
}
}
}
}
//
// :name: handleRightTapGesture
//
internal func handleTopTapGesture(gesture: UIPanGestureRecognizer) {
if let c = topContainer {
delegate?.sideNavDidTapTop?(self, container: c)
closeTopViewContainer()
}
}
//
// :name: addShadow
//
private func addShadow(inout viewContainer: UIView?) {
......@@ -890,36 +1164,38 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
//
// :name: gesturePanTopViewController
//
private func gesturePanTopViewController(gesture: UIGestureRecognizer, withTouchPoint point: CGPoint) -> Bool {
return isTopContainerOpened || options.topPanFromBezel && isTopPointContainedWithinRect(point)
}
//
// :name: isLeftPointContainedWithinRect
//
private func isLeftPointContainedWithinRect(point: CGPoint) -> Bool {
var r: CGRect = CGRectZero
var t: CGRect = CGRectZero
let w: CGFloat = options.leftBezelWidth
CGRectDivide(view.bounds, &r, &t, w, .MinXEdge)
return CGRectContainsPoint(r, point)
return CGRectContainsPoint(CGRectMake(0, 0, options.leftBezelWidth, view.bounds.size.height), point)
}
//
// :name: isRightPointContainedWithinRect
//
private func isRightPointContainedWithinRect(point: CGPoint) -> Bool {
var r: CGRect = CGRectZero
var t: CGRect = CGRectZero
let w: CGFloat = rightOriginX - options.rightBezelWidth
CGRectDivide(view.bounds, &t, &r, w, .MinXEdge)
return CGRectContainsPoint(r, point)
return CGRectContainsPoint(CGRectMake(CGRectGetMaxX(view.bounds) - options.rightBezelWidth, 0, options.rightBezelWidth, view.bounds.size.height), point)
}
//
// :name: isBottomPointContainedWithinRect
//
private func isBottomPointContainedWithinRect(point: CGPoint) -> Bool {
var r: CGRect = CGRectZero
var t: CGRect = CGRectZero
let h: CGFloat = bottomOriginY - options.bottomBezelHeight
CGRectDivide(view.bounds, &t, &r, h, .MinYEdge)
return CGRectContainsPoint(r, point)
return CGRectContainsPoint(CGRectMake(0, CGRectGetMaxY(view.bounds) - options.bottomBezelHeight, view.bounds.size.width, options.bottomBezelHeight), point)
}
//
// :name: isTopPointContainedWithinRect
//
private func isTopPointContainedWithinRect(point: CGPoint) -> Bool {
return CGRectContainsPoint(CGRectMake(0, 0, view.bounds.size.width, options.topBezelHeight), point)
}
//
......@@ -937,7 +1213,7 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
//
private func prepareMainContainer() {
mainViewContainer = UIView(frame: view.bounds)
mainViewContainer!.backgroundColor = .clearColor()
mainViewContainer!.backgroundColor = MaterialTheme.clear.color
mainViewContainer!.autoresizingMask = .FlexibleHeight | .FlexibleWidth
view.addSubview(mainViewContainer!)
}
......@@ -978,6 +1254,14 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
}
//
// :name: prepareBottomGestures
//
private func prepareTopGestures() {
removeGestures(&topPanGesture, tap: &topTapGesture)
addGestures(&topPanGesture, panSelector: "handleTopPanGesture:", tap: &topTapGesture, tapSelector: "handleTopTapGesture:")
}
//
// :name: prepareContainer
//
private func prepareContainer(inout container: SideNavContainer?, inout viewContainer: UIView?, originX: CGFloat, originY: CGFloat, width: CGFloat, height: CGFloat) {
......@@ -988,7 +1272,7 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
b.origin.x = originX
b.origin.y = originY
viewContainer = UIView(frame: b)
viewContainer!.backgroundColor = .clearColor()
viewContainer!.backgroundColor = MaterialTheme.clear.color
viewContainer!.autoresizingMask = .FlexibleHeight
view.addSubview(viewContainer!)
}
......@@ -1017,7 +1301,7 @@ public class SideNavController: UIViewController, UIGestureRecognizerDelegate {
vc.view.setTranslatesAutoresizingMaskIntoConstraints(false)
addChildViewController(vc)
c.addSubview(vc.view)
Layout.expandToParentSize(c, child: vc.view)
Layout.expandToParent(c, child: vc.view)
vc.didMoveToParentViewController(self)
}
}
......
......@@ -20,10 +20,11 @@ import UIKit
@objc(TextDelegate)
public protocol TextDelegate {
optional func textStorageWillProcessEdit(text: Text!, textStorage: TextStorage!, string: String!, range: NSRange)
optional func textStorageDidProcessEdit(text: Text!, textStorage: TextStorage!, string: String!, result: NSTextCheckingResult!, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>)
optional func textStorageWillProcessEdit(text: Text, textStorage: TextStorage, string: String, range: NSRange)
optional func textStorageDidProcessEdit(text: Text, textStorage: TextStorage, string: String, result: NSTextCheckingResult, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>)
}
@objc(Text)
public class Text: NSObject {
/**
:name: searchPattern
......@@ -49,14 +50,17 @@ public class Text: NSObject {
*/
public weak var delegate: TextDelegate?
/**
:name: init
*/
override public init() {
textStorage = TextStorage()
super.init()
textStorage.searchExpression = NSRegularExpression(pattern: searchPattern, options: nil, error: nil)
textStorage.textStorageWillProcessEdit = { (textStorage: TextStorage!, string: String!, range: NSRange) -> Void in
textStorage.textStorageWillProcessEdit = { (textStorage: TextStorage, string: String, range: NSRange) -> Void in
self.delegate?.textStorageWillProcessEdit?(self, textStorage: textStorage, string: string, range: range)
}
textStorage.textStorageDidProcessEdit = { (textStorage: TextStorage!, result: NSTextCheckingResult!, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
textStorage.textStorageDidProcessEdit = { (textStorage: TextStorage, result: NSTextCheckingResult, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
self.delegate?.textStorageDidProcessEdit?(self, textStorage: textStorage, string: textStorage.string, result: result, flags: flags, stop: stop)
}
}
......
......@@ -18,8 +18,8 @@
import UIKit
internal typealias TextStorageWillProcessEdit = (TextStorage!, String!, NSRange) -> Void
internal typealias TextStorageDidProcessEdit = (TextStorage!, NSTextCheckingResult!, NSMatchingFlags, UnsafeMutablePointer<ObjCBool>) -> Void
internal typealias TextStorageWillProcessEdit = (TextStorage, String, NSRange) -> Void
internal typealias TextStorageDidProcessEdit = (TextStorage, NSTextCheckingResult, NSMatchingFlags, UnsafeMutablePointer<ObjCBool>) -> Void
public class TextStorage: NSTextStorage {
/**
......
......@@ -18,9 +18,6 @@
import UIKit
private var defaultTextColor: UIColor = UIColor(red: 33/255, green: 33/255, blue: 33/255, alpha: 1)
private var defaultPlaceholderColor: UIColor = UIColor(red: 159/255, green: 160/255, blue: 164/255, alpha: 1)
public class TextView: UITextView {
//
// :name: label
......@@ -36,7 +33,7 @@ public class TextView: UITextView {
required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
prepareView()
}
override public init(frame: CGRect, textContainer: NSTextContainer?) {
......@@ -44,7 +41,7 @@ public class TextView: UITextView {
if CGRectZero == frame {
setTranslatesAutoresizingMaskIntoConstraints(false)
}
setupView()
prepareView()
}
//
......@@ -69,7 +66,7 @@ public class TextView: UITextView {
:name: placeholderColor
:description: The placeholder color.
*/
public var placeholderColor: UIColor = defaultPlaceholderColor {
public var placeholderColor: UIColor = MaterialTheme.blueGrey.lighten1 {
didSet {
label.textColor = placeholderColor
}
......@@ -127,7 +124,7 @@ public class TextView: UITextView {
override public func layoutSubviews() {
super.layoutSubviews()
label.preferredMaxLayoutWidth = textContainer.size.width - textContainer.lineFragmentPadding * 2.0
label.preferredMaxLayoutWidth = textContainer.size.width - textContainer.lineFragmentPadding * 2
}
//
......@@ -139,18 +136,18 @@ public class TextView: UITextView {
}
//
// :name: setupView
// :name: prepareView
// :description: Sets up the common initilized values.
//
private func setupView() {
backgroundColor = .clearColor()
textColor = defaultTextColor
private func prepareView() {
backgroundColor = MaterialTheme.clear.color
textColor = MaterialTheme.black.color
label.font = font
label.textColor = defaultPlaceholderColor
label.textColor = placeholderColor
label.textAlignment = textAlignment
label.text = placeholder
label.numberOfLines = 0
label.backgroundColor = UIColor.clearColor()
label.backgroundColor = MaterialTheme.clear.color
label.setTranslatesAutoresizingMaskIntoConstraints(false)
addSubview(label)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment