[英]How can I set [NSTextView selectedTextAttributes] on a background window?
[NSTextView selectedTextAttributes]
的默認值在我的應用程序中不可用,因為我允許用戶選擇與背景顏色幾乎完全相同的顏色(語法高亮)。
我已經寫了一些數學來確定合適的顏色,並可以使用它來設置它:
textView.selectedTextAttributes = @{
NSBackgroundColorAttributeName: [NSColor yellowColor],
NSForegroundColorAttributeName: [NSColor redColor]
};
但是當窗口在后台時,它仍然使用系統默認的淺灰色。
我附上了上述代碼的屏幕截圖,其中包含活動窗口和非活動窗口。 — 如何更改非活動窗口的選定文本背景顏色?
您可以通過覆蓋NSLayoutManager
繪圖方法來覆蓋顏色。
final class LayoutManager1: NSLayoutManager {
override func fillBackgroundRectArray(rectArray: UnsafePointer<NSRect>, count rectCount: Int, forCharacterRange charRange: NSRange, color: NSColor) {
let color1 = color == NSColor.secondarySelectedControlColor() ? NSColor.redColor() : color
color1.setFill()
super.fillBackgroundRectArray(rectArray, count: rectCount, forCharacterRange: charRange, color: color1)
color.setFill()
}
}
並將NSTextView
的布局管理器替換為它。
textView.textContainer!.replaceLayoutManager(layoutManager1)
這是完整的工作示例。
至於@Kyle詢問原因setFill
,我添加一些更新。
來自蘋果手冊:
... charRange 和 color 參數僅用於提供信息; 顏色已在圖形狀態中設置。 如果出於任何原因修改它,則必須在從該方法返回之前恢復它。 ...
這意味着在super
call 中傳入其他顏色沒有任何效果,您只需要NSColor.setFill
使其與super
call 一起工作。 此外,手冊要求將其設置回原來的。
不是當窗口在背景中時,而是在未選擇 NSTextView 時。 我認為你無法改變這種行為。
您可以創建一個屬性字符串,並在失去焦點時將 NSBackgroundColorAttributeName 屬性添加到所選文本的范圍內。 即使失去焦點,屬性字符串也保持相同的顏色。
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"hello world"];
[string addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(1, 7)];
[string addAttribute:NSBackgroundColorAttributeName value:[NSColor yellowColor] range:NSMakeRange(1, 7)];
[self.myTextView insertText:string];
Abhi Beckert 編輯:這就是我實現這個答案的方式(注意我還必須禁用內置的選定文本屬性,否則它們會覆蓋我正在設置的屬性):
@implementation MyTextView
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (!(self = [super initWithCoder:aDecoder]))
return nil;
// disable built in selected text attributes
self.selectedTextAttributes = @{};
return self;
}
- (id)initWithFrame:(NSRect)frameRect textContainer:(NSTextContainer *)container
{
if (!(self = [super initWithFrame:frameRect textContainer:container]))
return nil;
// disable built in selected text attributes
self.selectedTextAttributes = @{};
return self;
}
- (void)setSelectedRanges:(NSArray *)ranges affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag
{
// remove from old ranges
for (NSValue *value in self.selectedRanges) {
if (value.rangeValue.length == 0)
continue;
[self.textStorage removeAttribute:NSBackgroundColorAttributeName range:value.rangeValue];
}
// apply to new ranges
for (NSValue *value in ranges) {
if (value.rangeValue.length == 0)
continue;
[self.textStorage addAttribute:NSBackgroundColorAttributeName value:[NSColor yellowColor] range:value.rangeValue];
}
[super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag];
}
@end
您可以通過覆蓋NSLayoutManager 中的layoutManagerOwnsFirstResponder(in:)來指定您的 NSTextView 應被視為第一響應者,並且選擇將使用您定義的屬性。
在Swift 5.1中將是:
override func layoutManagerOwnsFirstResponder(in window: NSWindow) -> Bool {
true
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.