簡體   English   中英

如何在背景窗口上設置 [NSTextView selectedTextAttributes]?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM