14

I'm trying to write a "highlight" feature on an NSTextView. Currently, everything works great. You select a range of text and the background color of that text changes to yellow. However, while it's still selected, the background is that standard blue of selected text. How do I make that standard selection indicator color not show up in certain cases?

Thanks!

Dexter
  • 5,666
  • 6
  • 33
  • 45

1 Answers1

23

Use -[NSTextView setSelectedTextAttributes:...].

For example:

[textView setSelectedTextAttributes:
     [NSDictionary dictionaryWithObjectsAndKeys:
      [NSColor blackColor], NSBackgroundColorAttributeName,
      [NSColor whiteColor], NSForegroundColorAttributeName,
      nil]];

You can simply pass an empty dictionary if you don't want the selection indicated in any way at all (short of hiding the insertion point).

Another option is to watch for selection changes and apply the "selection" using temporary attributes. Note that temporary attributes are used to show spelling and grammar mistakes and find results; so if you care about preserving these features of NSTextView then make sure only to add and remove temporary attributes, not replace them.

An example of this is (in a NSTextView subclass):

- (void)setSelectedRanges:(NSArray *)ranges affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag;
{
    NSArray *oldRanges = [self selectedRanges];
    for (NSValue *v in oldRanges) {
        NSRange oldRange = [v rangeValue];
        if (oldRange.length > 0)
            [[self layoutManager] removeTemporaryAttribute:NSBackgroundColorAttributeName forCharacterRange:oldRange];
    }

    for (NSValue *v in ranges) {
        NSRange range = [v rangeValue];
        if (range.length > 0)
            [[self layoutManager] addTemporaryAttributes:[NSDictionary dictionaryWithObject:[NSColor blueColor] forKey:NSBackgroundColorAttributeName]
                                       forCharacterRange:range];
    }

    [super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag];
}
Nicholas Riley
  • 43,532
  • 6
  • 101
  • 124
  • By setting the background color to clearColor, the highlight works only after the entire selection is complete. How can I apply these attributes as the selection is underway? – Dexter Nov 29 '10 at 06:34
  • Notifications aren't delivered until the mouse button is released (i.e., you're no longer `stillSelecting`). If you want to handle selections in progress, you need to subclass NSTextView (edited my answer to provide some sample code). – Nicholas Riley Nov 29 '10 at 07:20