动态NSTooltips:影响工具提示的事件键修饰符

时间:2019-07-04 15:52:36

标签: swift macos key-value-observing nsnotifications

是否有工具提示的通知机制,然后可以使用键修饰符使它们动态化?我不知道有什么方法可以捕捉到正在创建的工具提示视图,并在发生键事件时尝试触发重绘。

我监视关键修饰符(在我的应用程序委托中);这里重点关注SHIFT,但是任何按键修饰符都可以:

var localKeyDownMonitor : Any? = nil
var globalKeyDownMonitor : Any? = nil
var shiftKeyDown : Bool = false {
    didSet {
        let notif = Notification(name: Notification.Name(rawValue: "shiftKeyDown"),
                                 object: NSNumber(booleanLiteral: shiftKeyDown));
        NotificationCenter.default.post(notif)
    }
}

应用程序的启动过程将在其中安装...

// Local/Global Monitor
_ /*accessEnabled*/ = AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true] as CFDictionary)
globalKeyDownMonitor = NSEvent.addGlobalMonitorForEvents(matching: NSEventMask.flagsChanged) { (event) -> Void in
    _ = self.keyDownMonitor(event: event)
}
localKeyDownMonitor = NSEvent.addLocalMonitorForEvents(matching: NSEventMask.flagsChanged) { (event) -> NSEvent? in
    return self.keyDownMonitor(event: event) ? nil : event
}

,然后通过上面的应用程序委托didSet进行拦截以发布通知(因此,当值更改时,将发送通知!):

func keyDownMonitor(event: NSEvent) -> Bool {
    switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
    case [.shift]:
        self.shiftKeyDown = true
        return true

    default:
        //  Only clear when true
        if shiftKeyDown { self.shiftKeyDown = false }
        return false
    }
}

对于单例工具提示绑定,可以通过通知通知(某些键的KVO)来动态化,我希望视图委托例程对此采取行动:

func tableView(_ tableView: NSTableView, toolTipFor cell: NSCell, rect: NSRectPointer, tableColumn: NSTableColumn?, row: Int, mouseLocation: NSPoint) -> String {
    if tableView == playlistTableView
    {
        let play = (playlistArrayController.arrangedObjects as! [PlayList])[row]

        if shiftKeyDown {
            return String(format: "%ld play(s)", play.plays)
        }
        else
        {
            return String(format: "%ld item(s)", play.list.count)
        }
    }
    ...

所以我希望我的通知处理程序做类似的事情

internal func shiftKeyDown(_ note: Notification) {
    let keyPaths = ["cornerImage","cornerTooltip","<table-view>.<column-view>"]
    for keyPath in (keyPaths)
    {
        self.willChangeValue(forKey: keyPath)
    }
    if subview.className == "NSCustomToolTipDrawView" {
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "CustomToolTipView"), object: subview)
    }
    for keyPath in (keyPaths)
    {
        self.didChangeValue(forKey: keyPath)
    }
}

我想强制工具提示重绘,但是什么也没发生。

我要做的是获取工具提示视图,目的是观看任何通知(使用nil名称做到这一点),该通知看起来很有希望并发现了一个-通过监视所有通知,因此我将其发布到感兴趣的视图控制器,它是tableView的委托。视图控制器正在观察“ CustomToolTipView”,并记住对象发送-tooltipView;这是创建的新工具提示视图。

但是什么也没发生-shiftKeyDown()重绘视图。

我怀疑它不会在当前事件循环中更新,但我确实看到了调试输出。

1 个答案:

答案 0 :(得分:0)

根据Willeke's的建议,我将tableView迁移为基于单元格的方法,为工具提示添加了get属性,并具有相关对象的init()例行注册通知,以了解移位键的更改。这导致更少的代码。双赢:-)