Commit 297dc4db by Daniel Dahan

preparation for Menu component

parent 10002a2c
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_close_white.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_close_white_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_close_white_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_create_white.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_create_white_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_create_white_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_note_add_white.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_note_add_white_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_note_add_white_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_photo_camera_white.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_photo_camera_white_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_photo_camera_white_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
......@@ -29,40 +29,56 @@
*/
/**
This is an example of using the Menu component. It is designed to take any array
of buttons and provide a facility to animate them opened and closed as a group.
*/
import UIKit
import Material
class ViewController: UIViewController {
/// Menu component.
private var menu: Menu!
/// Default spacing size
let spacing: CGFloat = 16
/// Base button diameter, otherwise default to buttonSize (48 x 48)
let diameter: CGFloat = 56
override func viewDidLoad() {
super.viewDidLoad()
prepareView()
prepareMenuExample()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
}
/// Handle orientation.
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
// menuLayout.origin.x = size.width
// menuLayout.origin.y = size.height
menu.reloadLayout()
// Handle orientation change.
menu.origin = CGPointMake(view.bounds.height - diameter - spacing, view.bounds.width - diameter - spacing)
}
/// Handle the base button touch event.
internal func handleOpenMenu() {
// Only trigger open and close animations when enabled.
if menu.enabled {
let image: UIImage?
if menu.opened {
menu.close()
image = UIImage(named: "ic_add_white")
} else {
// (menuLayout.items?.first?.button as? MaterialButton)?.animate(MaterialAnimation.rotate(1))
menu.open() { (button: UIButton) in
(button as? MaterialButton)?.pulse()
}
image = UIImage(named: "ic_close_white")
}
// Add a nice rotation animation to the base button.
(menu.buttons?.first as? MaterialButton)?.animate(MaterialAnimation.rotate(1))
menu.buttons?.first?.setImage(image, forState: .Normal)
menu.buttons?.first?.setImage(image, forState: .Highlighted)
}
}
......@@ -73,38 +89,43 @@ class ViewController: UIViewController {
/// Prepares the Menu example.
private func prepareMenuExample() {
let image: UIImage? = UIImage(named: "ic_add_white")
var image: UIImage? = UIImage(named: "ic_add_white")
let btn1: FabButton = FabButton()
btn1.depth = .Depth1
/**
Remove the pulse animation, so the rotation animation
doesn't seem like too much with the pulse animation.
*/
btn1.pulseColor = nil
btn1.setImage(image, forState: .Normal)
btn1.setImage(image, forState: .Highlighted)
btn1.addTarget(self, action: "handleOpenMenu", forControlEvents: .TouchUpInside)
view.addSubview(btn1)
image = UIImage(named: "ic_create_white")
let btn2: FabButton = FabButton()
btn2.depth = .Depth1
btn2.backgroundColor = MaterialColor.blue.base
btn2.setImage(image, forState: .Normal)
btn2.setImage(image, forState: .Highlighted)
view.addSubview(btn2)
image = UIImage(named: "ic_photo_camera_white")
let btn3: FabButton = FabButton()
btn3.depth = .Depth1
btn3.backgroundColor = MaterialColor.green.base
btn3.setImage(image, forState: .Normal)
btn3.setImage(image, forState: .Highlighted)
view.addSubview(btn3)
image = UIImage(named: "ic_note_add_white")
let btn4: FabButton = FabButton()
btn4.depth = .Depth1
btn4.backgroundColor = MaterialColor.yellow.base
btn4.backgroundColor = MaterialColor.amber.base
btn4.setImage(image, forState: .Normal)
btn4.setImage(image, forState: .Highlighted)
view.addSubview(btn4)
menu = Menu(origin: CGPointMake(100, 100))
menu.direction = .Down
menu.baseSize = CGSizeMake(88, 88)
// Initialize the menu and setup the configuration options.
menu = Menu(origin: CGPointMake(view.bounds.width - diameter - spacing, view.bounds.height - diameter - spacing))
menu.direction = .Up
menu.baseSize = CGSizeMake(diameter, diameter)
menu.buttons = [btn1, btn2, btn3, btn4]
}
}
......
......@@ -57,6 +57,7 @@ Material is a growing project and will encounter changes throughout its developm
* [FlatButton](#flatbutton)
* [RaisedButton](#raisedbutton)
* [FabButton](#fabbutton)
* [Menu](#menu)
* [NavigationBarView](#navigationbarview)
* [SideNavigationViewController](#sidenavigationviewcontroller)
* [CardView](#cardview)
......@@ -75,6 +76,7 @@ Material is a growing project and will encounter changes throughout its developm
* ProgressBar (circular and horizontal)
* DatePicker
* TimePicker
* Switch Control
* More Examples
<a name="materialcolor"></a>
......@@ -159,7 +161,14 @@ A FabButton is essential to Material Design's overall look. Below showcases its
![MaterialFabButton](http://www.cosmicmind.io/MK/MaterialFabButton.gif)
[Learn More About FabButton](https://github.com/CosmicMind/Material/wiki/FabButton)
<a name="menu"></a>
## Menu
A Menu manages a group of UIButtons that may be animated open in the Up, Down, Left, and Right directions. The animations are fully customizable.
![MaterialFabButton](http://www.cosmicmind.io/MK/MaterialMenu.gif)
[Learn More About Menu](https://github.com/CosmicMind/Material/wiki/Menu)
<a name="navigationbarview"></a>
## NavigationBarView
......
......@@ -31,20 +31,32 @@
import UIKit
public class Menu {
/// A Boolean that indicates if the menu is open or not.
public private(set) var opened: Bool = false
/// The rectangular bounds that the menu animates.
public var origin: CGPoint
public var origin: CGPoint {
didSet {
reloadLayout()
}
}
/// The space between buttons.
public var spacing: CGFloat
/// A Boolean that indicates if the menu is open or not.
public private(set) var opened: Bool = false
public var spacing: CGFloat {
didSet {
reloadLayout()
}
}
/// Animation duration.
public var duration: Double = 0.07
/// Enables the animations for the Menu.
public var enabled: Bool = true
/// The direction in which the animation opens the menu.
public var direction: MaterialDirection = .Up
public var direction: MaterialDirection = .Up {
didSet {
reloadLayout()
}
}
/// An Array of UIButtons.
public var buttons: Array<UIButton>? {
......@@ -59,43 +71,85 @@ public class Menu {
/// An Optional base button size.
public var baseSize: CGSize?
/**
Initializer.
- Parameter origin: The origin position of the Menu.
- Parameter spacing: The spacing size between buttons.
*/
public init(origin: CGPoint, spacing: CGFloat = 16) {
self.origin = origin
self.spacing = spacing
}
/// Reload the button layout.
public func reloadLayout() {
opened = false
layoutButtons()
}
public func open(completion: ((UIButton) -> Void)? = nil) {
/**
Open the Menu component with animation options.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
public func open(duration duration: NSTimeInterval = 0.15, delay: NSTimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIButton) -> Void)? = nil, completion: ((UIButton) -> Void)? = nil) {
if enabled {
disable()
switch direction {
case .Up:
openUpAnimation(completion)
openUpAnimation(duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .Down:
openDownAnimation(completion)
openDownAnimation(duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .Left:
openLeftAnimation(completion)
openLeftAnimation(duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .Right:
openRightAnimation(completion)
openRightAnimation(duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
}
}
}
public func close(completion: ((UIButton) -> Void)? = nil) {
/**
Close the Menu component with animation options.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
public func close(duration duration: NSTimeInterval = 0.15, delay: NSTimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIButton) -> Void)? = nil, completion: ((UIButton) -> Void)? = nil) {
if enabled {
disable()
switch direction {
case .Up:
closeUpAnimation(completion)
closeUpAnimation(duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .Down:
closeDownAnimation(completion)
closeDownAnimation(duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .Left:
closeLeftAnimation(completion)
closeLeftAnimation(duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .Right:
closeRightAnimation(completion)
closeRightAnimation(duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
}
}
}
private func openUpAnimation(completion: ((UIButton) -> Void)? = nil) {
/**
Open the Menu component with animation options in the Up direction.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
private func openUpAnimation(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIButton) -> Void)?, completion: ((UIButton) -> Void)?) {
if let v: Array<UIButton> = buttons {
var base: UIButton?
for var i: Int = 1, l: Int = v.count; i < l; ++i {
......@@ -104,38 +158,70 @@ public class Menu {
}
let button: UIButton = v[i]
button.hidden = false
UIView.animateWithDuration(Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [unowned self] in
button.alpha = 1
button.frame.origin.y = base!.frame.origin.y - CGFloat(i) * self.buttonSize.height - CGFloat(i) * self.spacing
},
completion: { _ in
animations?(button)
}, completion: { [unowned self] _ in
completion?(button)
self.enable(button)
})
}
opened = true
}
}
public func closeUpAnimation(completion: ((UIButton) -> Void)? = nil) {
/**
Close the Menu component with animation options in the Up direction.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
public func closeUpAnimation(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIButton) -> Void)?, completion: ((UIButton) -> Void)?) {
if let v: Array<UIButton> = buttons {
for var i: Int = 1, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
UIView.animateWithDuration(Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [unowned self] in
button.alpha = 0
button.frame.origin.y = self.origin.y
},
completion: { _ in
animations?(button)
}, completion: { [unowned self] _ in
button.hidden = true
completion?(button)
self.enable(button)
})
}
opened = false
}
}
private func openDownAnimation(completion: ((UIButton) -> Void)? = nil) {
/**
Open the Menu component with animation options in the Down direction.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
private func openDownAnimation(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIButton) -> Void)?, completion: ((UIButton) -> Void)?) {
if let v: Array<UIButton> = buttons {
var base: UIButton?
for var i: Int = 1, l: Int = v.count; i < l; ++i {
......@@ -148,79 +234,141 @@ public class Menu {
let h: CGFloat = nil == baseSize ? buttonSize.height : baseSize!.height
UIView.animateWithDuration(Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [unowned self] in
button.alpha = 1
button.frame.origin.y = base!.frame.origin.y + h + CGFloat(i - 1) * self.buttonSize.height + CGFloat(i) * self.spacing
},
completion: { _ in
animations?(button)
}, completion: { [unowned self] _ in
completion?(button)
self.enable(button)
})
}
opened = true
}
}
public func closeDownAnimation(completion: ((UIButton) -> Void)? = nil) {
/**
Close the Menu component with animation options in the Down direction.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
public func closeDownAnimation(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIButton) -> Void)?, completion: ((UIButton) -> Void)?) {
if let v: Array<UIButton> = buttons {
for var i: Int = 1, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
let h: CGFloat = nil == baseSize ? buttonSize.height : baseSize!.height
UIView.animateWithDuration(Double(i) * duration,
animations: {
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [unowned self] in
button.alpha = 0
button.frame.origin.y = self.origin.y + h
},
completion: { _ in
animations?(button)
}, completion: { [unowned self] _ in
button.hidden = true
completion?(button)
self.enable(button)
})
}
opened = false
}
}
private func openLeftAnimation(completion: ((UIButton) -> Void)? = nil) {
/**
Open the Menu component with animation options in the Left direction.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
private func openLeftAnimation(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIButton) -> Void)?, completion: ((UIButton) -> Void)?) {
if let v: Array<UIButton> = buttons {
var base: UIButton?
for var i: Int = 1, l: Int = v.count; i < l; ++i {
if nil == base {
base = v[0]
}
let button: UIButton = v[i]
button.hidden = false
UIView.animateWithDuration(Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [unowned self] in
button.alpha = 1
button.frame.origin.x = base!.frame.origin.x - CGFloat(i) * self.buttonSize.width - CGFloat(i) * self.spacing
},
completion: { _ in
animations?(button)
}, completion: { [unowned self] _ in
completion?(button)
self.enable(button)
})
}
opened = true
}
}
public func closeLeftAnimation(completion: ((UIButton) -> Void)? = nil) {
/**
Close the Menu component with animation options in the Left direction.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
public func closeLeftAnimation(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIButton) -> Void)?, completion: ((UIButton) -> Void)?) {
if let v: Array<UIButton> = buttons {
for var i: Int = 1, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
UIView.animateWithDuration(Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [unowned self] in
button.alpha = 0
button.frame.origin.x = self.origin.x
},
completion: { _ in
animations?(button)
}, completion: { [unowned self] _ in
button.hidden = true
completion?(button)
self.enable(button)
})
}
opened = false
}
}
private func openRightAnimation(completion: ((UIButton) -> Void)? = nil) {
/**
Open the Menu component with animation options in the Right direction.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
private func openRightAnimation(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIButton) -> Void)?, completion: ((UIButton) -> Void)?) {
if let v: Array<UIButton> = buttons {
var base: UIButton?
for var i: Int = 1, l: Int = v.count; i < l; ++i {
......@@ -232,38 +380,59 @@ public class Menu {
let h: CGFloat = nil == baseSize ? buttonSize.height : baseSize!.height
UIView.animateWithDuration(Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [unowned self] in
button.alpha = 1
button.frame.origin.x = base!.frame.origin.x + h + CGFloat(i - 1) * self.buttonSize.width + CGFloat(i) * self.spacing
},
completion: { _ in
animations?(button)
}, completion: { [unowned self] _ in
completion?(button)
self.enable(button)
})
}
opened = true
}
}
public func closeRightAnimation(completion: ((UIButton) -> Void)? = nil) {
/**
Close the Menu component with animation options in the Right direction.
- Parameter duration: The time for each button's animation.
- Parameter delay: A delay time for each button's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each button's animation.
- Parameter completion: A completion block to execute on each button's animation.
*/
public func closeRightAnimation(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIButton) -> Void)?, completion: ((UIButton) -> Void)?) {
if let v: Array<UIButton> = buttons {
for var i: Int = 1, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
let w: CGFloat = nil == baseSize ? buttonSize.width : baseSize!.width
UIView.animateWithDuration(Double(i) * duration,
animations: {
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [unowned self] in
button.alpha = 0
button.frame.origin.x = self.origin.x + w
},
completion: { _ in
animations?(button)
}, completion: { [unowned self] _ in
button.hidden = true
completion?(button)
self.enable(button)
})
}
opened = false
}
}
/// Layout the buttons.
private func layoutButtons() {
if let v: Array<UIButton> = buttons {
let size: CGSize = nil == baseSize ? buttonSize : baseSize!
......@@ -284,4 +453,23 @@ public class Menu {
}
}
}
/// Disable the Menu if buttons exist.
private func disable() {
if let _: Array<UIButton> = buttons {
enabled = false
}
}
/**
Enable the Menu if the last button is equal to the passed in button.
- Parameter button: UIButton that is passed in to compare.
*/
private func enable(button: UIButton) {
if let v: Array<UIButton> = buttons {
if button == v.last {
enabled = true
}
}
}
}
\ No newline at end of file
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