override func mouseDown(with event: NSEvent) {
let location = event.locationInWindow
switch ClipManager.shared.status {
case .ready:
// ....
case .select:
// 判断鼠标区域
guard let rect = self.highlightRect,
rect.contains(location)
else { return }
ClipManager.shared.status = .drag
self.lastPoint = location
default:
return
}
}
override func mouseUp(with event: NSEvent) {
switch ClipManager.shared.status {
case .start:
// ....
case .drag, .adjust:
// 保存高亮区域信息
guard let rect = self.highlightRect else { return }
self.startPoint = rect.origin
self.selectDotType = .none
self.lastRect = rect
ClipManager.shared.status = .select
default:
return
}
}
override func mouseDragged(with event: NSEvent) {
let location = event.locationInWindow
switch ClipManager.shared.status {
case .start:
// ....
case .adjust:
// 暂不实现
break
case .drag:
guard var rect = self.highlightRect,
let window = self.window
else { break }
// 和上一次检测的鼠标位置的偏移
var dx = location.x - self.lastPoint!.x
var dy = location.y - self.lastPoint!.y
// 偏移后的rect
let offsetRect = rect.offsetBy(dx: dx, dy: dy)
switch RectUtil.detectOverflow(rect: offsetRect, in: window) {
case .bothOverflow:
// 如果x和y都溢出,则抹零两轴的偏移量
dx = 0
dy = 0
case .xOverflow:
// x溢出,抹零x轴偏移量
dx = 0
case .yOverflow:
// y溢出,抹零y轴偏移量
dy = 0
default:
break
}
rect = rect.offsetBy(dx: dx, dy: dy)
// 更新highlightRect,记录鼠标位置
self.highlightRect = rect
self.lastPoint = location
self.highlight()
default:
break
}
}
其中rect溢出检测实现为:
class RectUtil: NSObject {
static func detectOverflow(rect: NSRect, in window:NSWindow) -> RectIssue {
let origin = rect.origin
let points = [origin,
origin.offsetBy(dx: rect.width, dy: 0),
origin.offsetBy(dx: 0, dy: rect.height),
origin.offsetBy(dx: rect.width, dy: rect.height)
]
var xFlag = false
var yFlag = false
for p in points {
if p.x < 0 || p.x > window.frame.width{
xFlag = true
}
if p.y < 0 || p.y > window.frame.height{
yFlag = true
}
}
if xFlag && yFlag {
return .bothOverflow
}else if xFlag {
return .xOverflow
}else if yFlag {
return .yOverflow
}else{
return .normal
}
}
// ... other functions
}
enum RectIssue {
case xOverflow
case yOverflow
case bothOverflow
case normal
}
高亮区域的调整 ➡️