Swiftgram/TelegramUI/AuthorizationLayout.swift
2018-01-09 13:18:08 +04:00

144 lines
5.3 KiB
Swift

import Foundation
import UIKit
import AsyncDisplayKit
import Display
struct AuthorizationLayoutItemSpacing {
let weight: CGFloat
let maxValue: CGFloat
}
struct AuthorizationLayoutItem {
let node: ASDisplayNode
let size: CGSize
let spacingBefore: AuthorizationLayoutItemSpacing
let spacingAfter: AuthorizationLayoutItemSpacing
}
final class SolvedAuthorizationLayoutItem {
let item: AuthorizationLayoutItem
var spacingBefore: CGFloat?
var spacingAfter: CGFloat?
init(item: AuthorizationLayoutItem) {
self.item = item
}
}
func layoutAuthorizationItems(bounds: CGRect, items: [AuthorizationLayoutItem], transition: ContainedViewLayoutTransition, failIfDoesNotFit: Bool) -> Bool {
var fixedHeight: CGFloat = 0.0
var totalSpacerWeight: CGFloat = 0.0
for item in items {
fixedHeight += item.size.height
totalSpacerWeight += item.spacingBefore.weight
totalSpacerWeight += item.spacingAfter.weight
}
let solvedItems = items.map(SolvedAuthorizationLayoutItem.init)
if failIfDoesNotFit && bounds.size.height - fixedHeight < 0.0 {
return false
}
var remainingSpacersHeight = max(0.0, bounds.size.height - fixedHeight)
for i in 0 ..< 3 {
if i == 0 || i == 2 {
while true {
var hasUnsolvedItems = false
for item in solvedItems {
if item.spacingBefore == nil {
hasUnsolvedItems = true
if item.item.spacingBefore.maxValue.isZero {
item.spacingBefore = 0.0
} else {
item.spacingBefore = floor(item.item.spacingBefore.weight * remainingSpacersHeight / totalSpacerWeight)
}
}
if item.spacingAfter == nil {
hasUnsolvedItems = true
if item.item.spacingAfter.maxValue.isZero {
item.spacingAfter = 0.0
} else {
item.spacingAfter = floor(item.item.spacingAfter.weight * remainingSpacersHeight / totalSpacerWeight)
}
}
}
if !hasUnsolvedItems {
break
}
}
} else {
var updated = false
for item in solvedItems {
if !item.item.spacingBefore.maxValue.isZero {
if item.spacingBefore! > item.item.spacingBefore.maxValue {
updated = true
}
}
if !item.item.spacingAfter.maxValue.isZero {
if item.spacingAfter! > item.item.spacingAfter.maxValue {
updated = true
}
}
}
if updated {
for item in solvedItems {
if !item.item.spacingBefore.maxValue.isZero {
if item.spacingBefore! > item.item.spacingBefore.maxValue {
item.spacingBefore = item.item.spacingBefore.maxValue
} else {
item.spacingBefore = nil
}
}
if !item.item.spacingAfter.maxValue.isZero {
if item.spacingAfter! > item.item.spacingAfter.maxValue {
item.spacingAfter = item.item.spacingAfter.maxValue
} else {
item.spacingAfter = nil
}
}
}
fixedHeight = 0.0
totalSpacerWeight = 0.0
for item in solvedItems {
fixedHeight += item.item.size.height
if let spacingBefore = item.spacingBefore {
fixedHeight += spacingBefore
} else if !item.item.spacingBefore.maxValue.isZero {
totalSpacerWeight += item.item.spacingBefore.weight
}
if let spacingAfter = item.spacingAfter {
fixedHeight += spacingAfter
} else if !item.item.spacingAfter.maxValue.isZero {
totalSpacerWeight += item.item.spacingAfter.weight
}
}
remainingSpacersHeight = max(0.0, bounds.size.height - fixedHeight)
}
}
}
var totalHeight: CGFloat = 0.0
for item in solvedItems {
totalHeight += item.spacingBefore! + item.spacingAfter! + item.item.size.height
}
var verticalOrigin: CGFloat = bounds.minY + floor((bounds.size.height - totalHeight) / 2.0)
for item in solvedItems {
verticalOrigin += item.spacingBefore!
transition.updateFrame(node: item.item.node, frame: CGRect(origin: CGPoint(x: floor((bounds.size.width - item.item.size.width) / 2.0), y: verticalOrigin), size: item.item.size))
verticalOrigin += item.item.size.height
verticalOrigin += item.spacingAfter!
}
return true
}