1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-01 18:39:52 +03:00
vimr/SwiftNeoVim/NeoVimView+Mouse.swift

177 lines
5.7 KiB
Swift

/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
extension NeoVimView {
override public func mouseDown(with event: NSEvent) {
self.mouse(event: event, vimName: "LeftMouse")
}
override public func mouseUp(with event: NSEvent) {
self.mouse(event: event, vimName: "LeftRelease")
}
override public func mouseDragged(with event: NSEvent) {
self.mouse(event: event, vimName: "LeftDrag")
}
override public func scrollWheel(with event: NSEvent) {
let (deltaX, deltaY) = (event.scrollingDeltaX, event.scrollingDeltaY)
if deltaX == 0 && deltaY == 0 {
return
}
let cellPosition = self.cellPositionFor(event: event)
let isTrackpad = event.hasPreciseScrollingDeltas
if isTrackpad == false {
let (vimInputX, vimInputY) = self.vimScrollInputFor(deltaX: deltaX, deltaY: deltaY,
modifierFlags: event.modifierFlags,
cellPosition: cellPosition)
self.agent.vimInput(vimInputX)
self.agent.vimInput(vimInputY)
return
}
let (absDeltaX, absDeltaY) = (min(Int(ceil(abs(deltaX) / 5.0)), maxScrollDeltaX),
min(Int(ceil(abs(deltaY) / 5.0)), maxScrollDeltaY))
let (horizSign, vertSign) = (deltaX > 0 ? 1 : -1, deltaY > 0 ? 1 : -1)
self.agent.scrollHorizontal(horizSign * absDeltaX, vertical: vertSign * absDeltaY, at: cellPosition)
}
override public func magnify(with event: NSEvent) {
let factor = 1 + event.magnification
let pinchTargetScale = self.pinchTargetScale * factor
let resultingFontSize = round(pinchTargetScale * self.font.pointSize)
if resultingFontSize >= NeoVimView.minFontSize && resultingFontSize <= NeoVimView.maxFontSize {
self.pinchTargetScale = pinchTargetScale
}
switch event.phase {
case NSEventPhase.began:
let pinchImageRep = self.bitmapImageRepForCachingDisplay(in: self.bounds)!
self.cacheDisplay(in: self.bounds, to: pinchImageRep)
self.pinchBitmap = pinchImageRep
self.isCurrentlyPinching = true
self.needsDisplay = true
case NSEventPhase.ended, NSEventPhase.cancelled:
self.isCurrentlyPinching = false
self.updateFontMetaData(NSFontManager.shared().convert(self.font, toSize: resultingFontSize))
self.pinchTargetScale = 1
default:
self.needsDisplay = true
}
}
fileprivate func cellPositionFor(event: NSEvent) -> Position {
let location = self.convert(event.locationInWindow, from: nil)
let row = Int((self.bounds.size.height - location.y - self.yOffset) / self.cellSize.height)
let column = Int((location.x - self.xOffset) / self.cellSize.width)
let cellPosition = Position(row: min(max(0, row), self.grid.size.height - 1),
column: min(max(0, column), self.grid.size.width - 1))
return cellPosition
}
fileprivate func mouse(event: NSEvent, vimName: String) {
let cellPosition = self.cellPositionFor(event: event)
guard self.shouldFireVimInputFor(event: event, newCellPosition: cellPosition) else {
return
}
let vimMouseLocation = self.wrapNamedKeys("\(cellPosition.column),\(cellPosition.row)")
let vimClickCount = self.vimClickCountFrom(event: event)
let result: String
if let vimModifiers = self.vimModifierFlags(event.modifierFlags) {
result = self.wrapNamedKeys("\(vimModifiers)\(vimClickCount)\(vimName)") + vimMouseLocation
} else {
result = self.wrapNamedKeys("\(vimClickCount)\(vimName)") + vimMouseLocation
}
// self.logger.debug("\(#function): \(result)")
self.agent.vimInput(result)
}
fileprivate func shouldFireVimInputFor(event: NSEvent, newCellPosition: Position) -> Bool {
let type = event.type
guard type == .leftMouseDragged
|| type == .rightMouseDragged
|| type == .otherMouseDragged else {
self.lastClickedCellPosition = newCellPosition
return true
}
if self.lastClickedCellPosition == newCellPosition {
return false
}
self.lastClickedCellPosition = newCellPosition
return true
}
fileprivate func vimClickCountFrom(event: NSEvent) -> String {
let clickCount = event.clickCount
guard 2 <= clickCount && clickCount <= 4 else {
return ""
}
switch event.type {
case .leftMouseDown, .leftMouseUp, .rightMouseDown, .rightMouseUp:
return "\(clickCount)-"
default:
return ""
}
}
fileprivate func vimScrollEventNamesFor(deltaX: CGFloat, deltaY: CGFloat) -> (String, String) {
let typeY: String
if deltaY > 0 {
typeY = "ScrollWheelUp"
} else {
typeY = "ScrollWheelDown"
}
let typeX: String
if deltaX < 0 {
typeX = "ScrollWheelRight"
} else {
typeX = "ScrollWheelLeft"
}
return (typeX, typeY)
}
fileprivate func vimScrollInputFor(deltaX: CGFloat, deltaY: CGFloat,
modifierFlags: NSEventModifierFlags,
cellPosition: Position) -> (String, String) {
let vimMouseLocation = self.wrapNamedKeys("\(cellPosition.column),\(cellPosition.row)")
let (typeX, typeY) = self.vimScrollEventNamesFor(deltaX: deltaX, deltaY: deltaY)
let resultX: String
let resultY: String
if let vimModifiers = self.vimModifierFlags(modifierFlags) {
resultX = self.wrapNamedKeys("\(vimModifiers)\(typeX)") + vimMouseLocation
resultY = self.wrapNamedKeys("\(vimModifiers)\(typeY)") + vimMouseLocation
} else {
resultX = self.wrapNamedKeys("\(typeX)") + vimMouseLocation
resultY = self.wrapNamedKeys("\(typeY)") + vimMouseLocation
}
return (resultX, resultY)
}
}
fileprivate let maxScrollDeltaX = 15
fileprivate let maxScrollDeltaY = 15