2013-04-18 22 views
7

Giá trị mặc định cho [NSTextView selectedTextAttributes] không sử dụng được trong ứng dụng của tôi, bởi vì tôi cho phép người dùng chọn màu (tô sáng cú pháp) gần giống hệt như màu nền.Làm cách nào để đặt [NSTextView selectedTextAttributes] trên cửa sổ nền?

Tôi đã viết một số toán học để xác định một màu sắc phù hợp và có thể sử dụng để thiết lập nó:

textView.selectedTextAttributes = @{ 
    NSBackgroundColorAttributeName: [NSColor yellowColor], 
    NSForegroundColorAttributeName: [NSColor redColor] 
    }; 

Nhưng khi cửa sổ được ở chế độ nền, nó vẫn sử dụng ánh sáng màu xám mặc định của hệ thống.

Tôi đã đính kèm ảnh chụp màn hình của mã ở trên với cửa sổ hoạt động và không hoạt động. Thế nào tôi có thể thay đổi màu nền văn bản đã chọn của cửa sổ không hoạt động?

active inactive

+0

Bạn đã thử subclassing NSWindow và ghi đè 'resignKeyWindow'? – CodaFi

+0

@CodaFi Tôi nên làm gì trong phương pháp đó? Tôi chỉ cố gắng thiết lập selectedTextAttirbutes nhưng nó không có hiệu lực. –

+1

Hm ... Kiểm tra NSWindow.h. Có một tải trọng thuyền các chức năng bạn có thể sử dụng để lấy bất cứ khi nào cửa sổ từ chức/tăng trạng thái khóa. Bạn có thể gán các thuộc tính từ đó. – CodaFi

Trả lời

6

Bạn có thể ghi đè màu bằng phương pháp vẽ ghi đè 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() 
    } 
} 

Và thay thế NSTextView trình quản lý bố cục của nó.

textView.textContainer!.replaceLayoutManager(layoutManager1) 

Đây là full working example.


Vì @Kyle hỏi lý do setFill, tôi thêm một số cập nhật.

Từ Apple dẫn sử dụng:

... các charRange và các thông số màu sắc được truyền trong đơn thuần nhằm mục đích cung cấp thông tin; màu sắc là đã được đặt ở trạng thái đồ họa. Nếu vì bất kỳ lý do gì bạn sửa đổi nó, bạn phải khôi phục nó trước khi trở về từ phương pháp này. ...

có nghĩa là đi qua trong màu khác vào super cuộc gọi không có tác dụng, và bạn chỉ cần NSColor.setFill để làm cho nó làm việc với super gọi. Ngoài ra, hướng dẫn sử dụng yêu cầu đặt lại thành bản gốc.

+0

Chỉ cần tò mò, tại sao gọi 'setFill'? Tôi hy vọng việc truyền màu mới cho 'fillBackgroundRectArray' sẽ xử lý mọi thứ đúng cách? – Kyle

+1

@Kyle Tôi đã cập nhật câu trả lời của mình để cung cấp thông tin đó. Quá dài để nhận xét. – Eonil

5

Nó không phải khi cửa sổ được trong nền đó là khi các NSTextView không được chọn. Tôi không nghĩ rằng bạn có thể thay đổi hành vi đó. enter image description here

Bạn có thể tạo chuỗi được phân bổ và thêm thuộc tính NSBackgroundColorAttributeName vào phạm vi của văn bản đã chọn khi văn bản mất tiêu điểm. Chuỗi được phân bổ vẫn giữ nguyên màu ngay cả khi tiêu điểm bị mất.

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]; 

enter image description here

EDIT bởi Abhi Beckert: đây là cách tôi thực hiện câu trả lời này (lưu ý tôi cũng phải vô hiệu hóa việc xây dựng trong các thuộc tính văn bản đã chọn, nếu không họ ghi đè lên những cái tôi đang thiết):

@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 
+0

Cảm ơn bạn! Tôi đã ghi đè subclass của tôi setSelectedRange: để áp dụng các thuộc tính vào lưu trữ văn bản theo cách thủ công, sau đó đặt selectedTextAttribtues thành một từ điển trống và nó hoạt động. Tôi sẽ chỉnh sửa câu trả lời của bạn sau một giây để có mã tôi đã sử dụng. –

+0

Vui vì tôi có thể giúp! –

+0

Hãy coi chừng rằng việc thiết lập các thuộc tính cho lưu trữ văn bản có nghĩa là bạn lưu các thuộc tính như là một phần của văn bản màu, giống như bạn làm trong các trình soạn thảo văn bản đa dạng thức. Tôi khuyên bạn nên sử dụng thuộc tính tạm thời của NSLayoutManager để thay thế, được nhắm mục tiêu cho kiểu dáng tạm thời như thế này. – ctietze