-
Notifications
You must be signed in to change notification settings - Fork 895
/
Copy pathSPopoverViewController.swift
157 lines (123 loc) · 5.05 KB
/
SPopoverViewController.swift
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//
// SPopoverViewController.swift
// Telegram-Mac
//
// Created by keepcoder on 09/11/2016.
// Copyright © 2016 Telegram. All rights reserved.
//
import Cocoa
import SwiftSignalKit
public struct SPopoverAdditionItemView {
let context: Any?
let view: NSView
let updateIsSelected:((Bool)->Void)?
public init(context: Any?, view: NSView, updateIsSelected:((Bool)->Void)? = nil) {
self.context = context
self.view = view
self.updateIsSelected = updateIsSelected
}
}
public struct SPopoverItem : Equatable {
public let title:String
let image:CGImage?
let textColor: NSColor
let height: CGFloat
public let handler:()->Void
let isSeparator: Bool
let drawSeparatorBorder: Bool
let additionView: SPopoverAdditionItemView?
public init(_ title:String, _ handler:@escaping ()->Void, _ image:CGImage? = nil, _ textColor: NSColor = presentation.colors.text, height: CGFloat = 40.0, isSeparator: Bool = false, drawSeparatorBorder: Bool = true, additionView: SPopoverAdditionItemView? = nil) {
self.title = title
self.image = image
self.textColor = textColor
self.handler = handler
self.height = height
self.isSeparator = false
self.additionView = additionView
self.drawSeparatorBorder = drawSeparatorBorder
}
public init(_ drawSeparatorBorder: Bool = true) {
self.title = ""
self.image = nil
self.textColor = presentation.colors.text
self.handler = {}
self.height = 10
self.isSeparator = true
self.drawSeparatorBorder = drawSeparatorBorder
self.additionView = nil
}
public static func ==(lhs: SPopoverItem, rhs: SPopoverItem) -> Bool {
return lhs.title == rhs.title && lhs.textColor == rhs.textColor
}
}
public class SPopoverViewController: GenericViewController<TableView> {
private let items:[TableRowItem]
private let disposable = MetaDisposable()
public override func viewDidLoad() {
super.viewDidLoad()
genericView.insert(items: items)
genericView.needUpdateVisibleAfterScroll = true
genericView.reloadData()
readyOnce()
}
public init(items:[SPopoverItem], visibility:Int = 4, handlerDelay: Double = 0.15, headerItems: [TableRowItem] = []) {
weak var controller:SPopoverViewController?
let alignAsImage = !items.filter({$0.image != nil}).isEmpty
let items = items.map { item -> TableRowItem in
if item.isSeparator {
return SPopoverSeparatorItem(item.drawSeparatorBorder)
} else {
return SPopoverRowItem(NSZeroSize, height: item.height, image: item.image, alignAsImage: alignAsImage, title: item.title, textColor: item.textColor, additionView: item.additionView, clickHandler: {
Queue.mainQueue().justDispatch {
controller?.popover?.hide()
if handlerDelay == 0 {
item.handler()
} else {
_ = (Signal<Void, NoError>.single(Void()) |> delay(handlerDelay, queue: Queue.mainQueue())).start(next: {
item.handler()
})
}
}
})
}
}
let width: CGFloat = items.isEmpty ? 200 : items.compactMap({ $0 as? SPopoverRowItem }).max(by: {$0.itemWidth < $1.itemWidth})!.itemWidth
for item in headerItems {
_ = item.makeSize(width + 48 + 18)
}
self.items = headerItems + (headerItems.isEmpty ? [] : [SPopoverSeparatorItem(false)]) + items
var height: CGFloat = 0
for (i, item) in self.items.enumerated() {
if i < visibility {
height += item.height
} else {
height += item.height / 2
break
}
}
// let height = min(visibility * 40 + 20, items.count * 40)
super.init(frame: NSMakeRect(0, 0, width + 45 + 18, CGFloat(height)))
bar = .init(height: 0)
controller = self
}
deinit {
disposable.dispose()
}
public override func becomeFirstResponder() -> Bool? {
return nil
}
public override func viewWillAppear(_ animated: Bool) {
}
}
//public func presntContextMenu(for event: NSEvent, items: [SPopoverItem]) -> Void {
//
//
// let controller = SPopoverViewController(items: items, visibility: Int.max, handlerDelay: 0)
//
// let window = Window(contentRect: NSMakeRect(event.locationInWindow.x, event.locationInWindow.y, controller.frame.width, controller.frame.height), styleMask: [], backing: .buffered, defer: true)
// window.contentView = controller.view
// window.backgroundColor = .clear
// event.window?.addChildWindow(window, ordered: .above)
// window.makeKeyAndOrderFront(nil)
//
//}