Repo // Implementing set() for NSWindowController.
This commit is contained in:
parent
c7347f0efb
commit
5832136e05
|
@ -52,7 +52,7 @@ open class CtlCandidate: NSWindowController, CtlCandidateProtocol {
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.set(windowTopLeftPoint: newValue, bottomOutOfScreenAdjustmentHeight: 0)
|
self.set(windowTopLeftPoint: newValue, bottomOutOfScreenAdjustmentHeight: 0, useGCD: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,37 +72,6 @@ open class CtlCandidate: NSWindowController, CtlCandidateProtocol {
|
||||||
visible = false
|
visible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 設定選字窗的顯示位置。
|
|
||||||
///
|
|
||||||
/// 需注意:該函數會藉由設定選字窗左上角頂點的方式、使選字窗始終位於某個螢幕之內。
|
|
||||||
///
|
|
||||||
/// - Parameters:
|
|
||||||
/// - windowTopLeftPoint: 給定的視窗顯示位置。
|
|
||||||
/// - heightDelta: 為了「防止選字窗抻出螢幕下方」而給定的預留高度。
|
|
||||||
public func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight heightDelta: Double) {
|
|
||||||
DispatchQueue.main.async { [self] in
|
|
||||||
guard let window = window, var screenFrame = NSScreen.main?.visibleFrame else { return }
|
|
||||||
let windowSize = window.frame.size
|
|
||||||
|
|
||||||
var adjustedPoint = windowTopLeftPoint
|
|
||||||
var delta = heightDelta
|
|
||||||
for frame in NSScreen.screens.map(\.visibleFrame).filter({ $0.contains(windowTopLeftPoint) }) {
|
|
||||||
screenFrame = frame
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if delta > screenFrame.size.height / 2.0 { delta = 0.0 }
|
|
||||||
|
|
||||||
if adjustedPoint.y < screenFrame.minY + windowSize.height {
|
|
||||||
adjustedPoint.y = windowTopLeftPoint.y + windowSize.height + delta
|
|
||||||
}
|
|
||||||
adjustedPoint.y = min(adjustedPoint.y, screenFrame.maxY - 1.0)
|
|
||||||
adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width - 1.0)
|
|
||||||
|
|
||||||
window.setFrameTopLeftPoint(adjustedPoint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - 不需要在這裡仔細實作的內容。
|
// MARK: - 不需要在這裡仔細實作的內容。
|
||||||
|
|
||||||
@available(*, unavailable)
|
@available(*, unavailable)
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||||
|
// ====================
|
||||||
|
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
|
||||||
|
// ... with NTL restriction stating that:
|
||||||
|
// No trademark license is granted to use the trade names, trademarks, service
|
||||||
|
// marks, or product names of Contributor, except as required to fulfill notice
|
||||||
|
// requirements defined in MIT License.
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
import InputMethodKit
|
||||||
|
|
||||||
|
extension NSWindowController {
|
||||||
|
/// 設定選字窗的顯示位置。
|
||||||
|
///
|
||||||
|
/// 需注意:該函式會藉由設定選字窗左上角頂點的方式、使選字窗始終位於某個螢幕之內。
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - windowTopLeftPoint: 給定的視窗顯示位置。
|
||||||
|
/// - heightDelta: 為了「防止選字窗抻出螢幕下方」而給定的預留高度。
|
||||||
|
public func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight heightDelta: Double, useGCD: Bool) {
|
||||||
|
func doSet() {
|
||||||
|
guard let window = window, var screenFrame = NSScreen.main?.visibleFrame else { return }
|
||||||
|
let windowSize = window.frame.size
|
||||||
|
|
||||||
|
var adjustedPoint = windowTopLeftPoint
|
||||||
|
var delta = heightDelta
|
||||||
|
for frame in NSScreen.screens.map(\.visibleFrame).filter({ $0.contains(windowTopLeftPoint) }) {
|
||||||
|
screenFrame = frame
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if delta > screenFrame.size.height / 2.0 { delta = 0.0 }
|
||||||
|
|
||||||
|
if adjustedPoint.y < screenFrame.minY + windowSize.height {
|
||||||
|
adjustedPoint.y = windowTopLeftPoint.y + windowSize.height + delta
|
||||||
|
}
|
||||||
|
adjustedPoint.y = min(adjustedPoint.y, screenFrame.maxY - 1.0)
|
||||||
|
adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width - 1.0)
|
||||||
|
|
||||||
|
window.setFrameTopLeftPoint(adjustedPoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !useGCD { doSet() } else { DispatchQueue.main.async { doSet() } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension IMKCandidates {
|
||||||
|
/// 設定選字窗的顯示位置。
|
||||||
|
///
|
||||||
|
/// 需注意:該函式會藉由設定選字窗左上角頂點的方式、使選字窗始終位於某個螢幕之內。
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - windowTopLeftPoint: 給定的視窗顯示位置。
|
||||||
|
/// - heightDelta: 為了「防止選字窗抻出螢幕下方」而給定的預留高度。
|
||||||
|
public func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight heightDelta: Double, useGCD: Bool) {
|
||||||
|
func doSet() {
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
|
guard var screenFrame = NSScreen.main?.visibleFrame else { return }
|
||||||
|
var adjustedPoint = windowTopLeftPoint
|
||||||
|
let windowSize = candidateFrame().size
|
||||||
|
var delta = heightDelta
|
||||||
|
for frame in NSScreen.screens.map(\.visibleFrame).filter({ $0.contains(windowTopLeftPoint) }) {
|
||||||
|
screenFrame = frame
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if delta > screenFrame.size.height / 2.0 { delta = 0.0 }
|
||||||
|
|
||||||
|
if adjustedPoint.y < screenFrame.minY + windowSize.height {
|
||||||
|
adjustedPoint.y = windowTopLeftPoint.y + windowSize.height + delta
|
||||||
|
}
|
||||||
|
adjustedPoint.y = min(adjustedPoint.y, screenFrame.maxY - 1.0)
|
||||||
|
adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width - 1.0)
|
||||||
|
|
||||||
|
setCandidateFrameTopLeft(adjustedPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if useGCD { doSet() } else { DispatchQueue.main.async { doSet() } }
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,5 +36,5 @@ public protocol CtlCandidateProtocol {
|
||||||
func highlightNextCandidate() -> Bool
|
func highlightNextCandidate() -> Bool
|
||||||
func highlightPreviousCandidate() -> Bool
|
func highlightPreviousCandidate() -> Bool
|
||||||
func candidateIndexAtKeyLabelIndex(_: Int) -> Int
|
func candidateIndexAtKeyLabelIndex(_: Int) -> Int
|
||||||
func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight height: Double)
|
func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight height: Double, useGCD: Bool)
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,10 @@ public class TooltipUI: NSWindowController {
|
||||||
) {
|
) {
|
||||||
self.direction = direction
|
self.direction = direction
|
||||||
self.tooltip = tooltip
|
self.tooltip = tooltip
|
||||||
|
window?.setIsVisible(false)
|
||||||
window?.orderFront(nil)
|
window?.orderFront(nil)
|
||||||
set(windowTopLeftPoint: point, bottomOutOfScreenAdjustmentHeight: heightDelta)
|
set(windowTopLeftPoint: point, bottomOutOfScreenAdjustmentHeight: heightDelta, useGCD: false)
|
||||||
|
window?.setIsVisible(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setColor(state: TooltipColorState) {
|
public func setColor(state: TooltipColorState) {
|
||||||
|
@ -118,29 +120,6 @@ public class TooltipUI: NSWindowController {
|
||||||
window?.orderOut(nil)
|
window?.orderOut(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight heightDelta: Double) {
|
|
||||||
guard let window = window else { return }
|
|
||||||
let windowSize = window.frame.size
|
|
||||||
|
|
||||||
var adjustedPoint = windowTopLeftPoint
|
|
||||||
var delta = heightDelta
|
|
||||||
var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
|
|
||||||
for frame in NSScreen.screens.map(\.visibleFrame).filter({ $0.contains(windowTopLeftPoint) }) {
|
|
||||||
screenFrame = frame
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if delta > screenFrame.size.height / 2.0 { delta = 0.0 }
|
|
||||||
|
|
||||||
if adjustedPoint.y < screenFrame.minY + windowSize.height {
|
|
||||||
adjustedPoint.y = windowTopLeftPoint.y + windowSize.height + delta
|
|
||||||
}
|
|
||||||
adjustedPoint.y = min(adjustedPoint.y, screenFrame.maxY - 1.0)
|
|
||||||
adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width - 1.0)
|
|
||||||
|
|
||||||
window.setFrameTopLeftPoint(adjustedPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func adjustSize() {
|
private func adjustSize() {
|
||||||
var rect = messageText.shrinkFrame()
|
var rect = messageText.shrinkFrame()
|
||||||
var bigRect = rect
|
var bigRect = rect
|
||||||
|
|
|
@ -133,12 +133,14 @@ extension SessionCtl {
|
||||||
windowTopLeftPoint: NSPoint(
|
windowTopLeftPoint: NSPoint(
|
||||||
x: lineHeightRect().origin.x + lineHeightRect().size.width + 4.0, y: lineHeightRect().origin.y - 4.0
|
x: lineHeightRect().origin.x + lineHeightRect().size.width + 4.0, y: lineHeightRect().origin.y - 4.0
|
||||||
),
|
),
|
||||||
bottomOutOfScreenAdjustmentHeight: lineHeightRect().size.height + 4.0
|
bottomOutOfScreenAdjustmentHeight: lineHeightRect().size.height + 4.0,
|
||||||
|
useGCD: true
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ctlCandidateCurrent.set(
|
ctlCandidateCurrent.set(
|
||||||
windowTopLeftPoint: NSPoint(x: lineHeightRect().origin.x, y: lineHeightRect().origin.y - 4.0),
|
windowTopLeftPoint: NSPoint(x: lineHeightRect().origin.x, y: lineHeightRect().origin.y - 4.0),
|
||||||
bottomOutOfScreenAdjustmentHeight: lineHeightRect().size.height + 4.0
|
bottomOutOfScreenAdjustmentHeight: lineHeightRect().size.height + 4.0,
|
||||||
|
useGCD: true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class CtlCandidateIMK: IMKCandidates, CtlCandidateProtocol {
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.set(windowTopLeftPoint: newValue, bottomOutOfScreenAdjustmentHeight: 0)
|
self.set(windowTopLeftPoint: newValue, bottomOutOfScreenAdjustmentHeight: 0, useGCD: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,33 +146,6 @@ public class CtlCandidateIMK: IMKCandidates, CtlCandidateProtocol {
|
||||||
get { selectedCandidate() }
|
get { selectedCandidate() }
|
||||||
set { selectCandidate(withIdentifier: newValue) }
|
set { selectCandidate(withIdentifier: newValue) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight height: Double) {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.doSet(windowTopLeftPoint: windowTopLeftPoint, bottomOutOfScreenAdjustmentHeight: height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func doSet(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight heightDelta: Double) {
|
|
||||||
guard var screenFrame = NSScreen.main?.visibleFrame else { return }
|
|
||||||
var adjustedPoint = windowTopLeftPoint
|
|
||||||
let windowSize = candidateFrame().size
|
|
||||||
var delta = heightDelta
|
|
||||||
for frame in NSScreen.screens.map(\.visibleFrame).filter({ $0.contains(windowTopLeftPoint) }) {
|
|
||||||
screenFrame = frame
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if delta > screenFrame.size.height / 2.0 { delta = 0.0 }
|
|
||||||
|
|
||||||
if adjustedPoint.y < screenFrame.minY + windowSize.height {
|
|
||||||
adjustedPoint.y = windowTopLeftPoint.y + windowSize.height + delta
|
|
||||||
}
|
|
||||||
adjustedPoint.y = min(adjustedPoint.y, screenFrame.maxY - 1.0)
|
|
||||||
adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width - 1.0)
|
|
||||||
|
|
||||||
setCandidateFrameTopLeft(adjustedPoint)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Generate TISInputSource Object
|
// MARK: - Generate TISInputSource Object
|
||||||
|
|
Loading…
Reference in New Issue