1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
| func insertionPoint(_ insertDirectionHints: [Int: ListViewItemOperationDirectionHint], itemCount: Int) -> ListViewInsertionPoint? {
var fixedNode: (nodeIndex: Int, index: Int, frame: CGRect)?
if let (fixedIndex, _) = self.scrollPosition {
for i in 0 ..< self.nodes.count {
let node = self.nodes[i]
if let index = node.index , index == fixedIndex {
fixedNode = (i, index, node.frame)
break
}
}
if fixedNode == nil {
return ListViewInsertionPoint(index: fixedIndex, point: CGPoint(), direction: .Down)
}
}
var fixedNodeIsStationary = false
if fixedNode == nil {
if let (fixedIndex, _) = self.stationaryOffset {
for i in 0 ..< self.nodes.count {
let node = self.nodes[i]
if let index = node.index , index == fixedIndex {
fixedNode = (i, index, node.frame)
fixedNodeIsStationary = true
break
}
}
}
}
if fixedNode == nil {
for i in 0 ..< self.nodes.count {
let node = self.nodes[i]
if let index = node.index , node.frame.maxY >= self.insets.top {
fixedNode = (i, index, node.frame)
break
}
}
}
if fixedNode == nil && self.nodes.count != 0 {
for i in (0 ..< self.nodes.count).reversed() {
let node = self.nodes[i]
if let index = node.index {
fixedNode = (i, index, node.frame)
break
}
}
}
if let fixedNode = fixedNode {
var currentUpperNode = fixedNode
for i in (0 ..< fixedNode.nodeIndex).reversed() {
let node = self.nodes[i]
if let index = node.index {
if index != currentUpperNode.index - 1 {
if currentUpperNode.frame.minY > -self.invisibleInset - CGFloat.ulpOfOne {
var directionHint: ListViewInsertionOffsetDirection?
if let hint = insertDirectionHints[currentUpperNode.index - 1] , currentUpperNode.frame.minY > self.insets.top - CGFloat.ulpOfOne {
directionHint = ListViewInsertionOffsetDirection(hint)
}
return ListViewInsertionPoint(index: currentUpperNode.index - 1, point: CGPoint(x: 0.0, y: currentUpperNode.frame.minY), direction: directionHint ?? .Up)
} else {
break
}
}
currentUpperNode = (i, index, node.frame)
}
}
if currentUpperNode.index != 0 && currentUpperNode.frame.minY > -self.invisibleInset - CGFloat.ulpOfOne {
var directionHint: ListViewInsertionOffsetDirection?
if let hint = insertDirectionHints[currentUpperNode.index - 1] {
if currentUpperNode.frame.minY >= self.insets.top - CGFloat.ulpOfOne {
directionHint = ListViewInsertionOffsetDirection(hint)
}
} else if currentUpperNode.frame.minY >= self.insets.top - CGFloat.ulpOfOne && !fixedNodeIsStationary {
directionHint = .Down
}
return ListViewInsertionPoint(index: currentUpperNode.index - 1, point: CGPoint(x: 0.0, y: currentUpperNode.frame.minY), direction: directionHint ?? .Up)
}
var currentLowerNode = fixedNode
if fixedNode.nodeIndex + 1 < self.nodes.count {
for i in (fixedNode.nodeIndex + 1) ..< self.nodes.count {
let node = self.nodes[i]
if let index = node.index {
if index != currentLowerNode.index + 1 {
if currentLowerNode.frame.maxY < self.visibleSize.height + self.invisibleInset - CGFloat.ulpOfOne {
var directionHint: ListViewInsertionOffsetDirection?
if let hint = insertDirectionHints[currentLowerNode.index + 1] , currentLowerNode.frame.maxY < self.visibleSize.height - self.insets.bottom + CGFloat.ulpOfOne {
directionHint = ListViewInsertionOffsetDirection(hint)
}
return ListViewInsertionPoint(index: currentLowerNode.index + 1, point: CGPoint(x: 0.0, y: currentLowerNode.frame.maxY), direction: directionHint ?? .Down)
} else {
break
}
}
currentLowerNode = (i, index, node.frame)
}
}
}
if currentLowerNode.index != itemCount - 1 && currentLowerNode.frame.maxY < self.visibleSize.height + self.invisibleInset - CGFloat.ulpOfOne {
var directionHint: ListViewInsertionOffsetDirection?
if let hint = insertDirectionHints[currentLowerNode.index + 1] , currentLowerNode.frame.maxY < self.visibleSize.height - self.insets.bottom + CGFloat.ulpOfOne {
directionHint = ListViewInsertionOffsetDirection(hint)
}
return ListViewInsertionPoint(index: currentLowerNode.index + 1, point: CGPoint(x: 0.0, y: currentLowerNode.frame.maxY), direction: directionHint ?? .Down)
}
} else if itemCount != 0 {
return ListViewInsertionPoint(index: 0, point: CGPoint(x: 0.0, y: self.insets.top), direction: .Down)
}
return nil
}
|