1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/base/cocoa/controls/hyperlink_text_view.h"
#include "base/mac/scoped_nsobject.h"
#include "ui/base/cocoa/nsview_additions.h"
// The baseline shift for text in the NSTextView.
const float kTextBaselineShift = -1.0;
@interface HyperlinkTextView(Private)
// Initialize the NSTextView properties for this subclass.
- (void)configureTextView;
// Change the current IBeamCursor to an arrowCursor.
- (void)fixupCursor;
@end
@implementation HyperlinkTextView
@synthesize drawsBackgroundUsingSuperview = drawsBackgroundUsingSuperview_;
- (id)initWithCoder:(NSCoder*)decoder {
if ((self = [super initWithCoder:decoder]))
[self configureTextView];
return self;
}
- (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect]))
[self configureTextView];
return self;
}
- (BOOL)acceptsFirstResponder {
return !refusesFirstResponder_;
}
- (void)drawViewBackgroundInRect:(NSRect)rect {
if (drawsBackgroundUsingSuperview_)
[self cr_drawUsingAncestor:[self superview] inRect:rect];
else
[super drawViewBackgroundInRect:rect];
}
// Never draw the insertion point (otherwise, it shows up without any user
// action if full keyboard accessibility is enabled).
- (BOOL)shouldDrawInsertionPoint {
return NO;
}
- (NSRange)selectionRangeForProposedRange:(NSRange)proposedSelRange
granularity:(NSSelectionGranularity)granularity {
// Do not allow selections.
return NSMakeRange(0, 0);
}
// Convince NSTextView to not show an I-Beam cursor when the cursor is over the
// text view but not over actual text.
//
// http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg10791.html
// "NSTextView sets the cursor over itself dynamically, based on considerations
// including the text under the cursor. It does so in -mouseEntered:,
// -mouseMoved:, and -cursorUpdate:, so those would be points to consider
// overriding."
- (void)mouseMoved:(NSEvent*)e {
[super mouseMoved:e];
[self fixupCursor];
}
- (void)mouseEntered:(NSEvent*)e {
[super mouseEntered:e];
[self fixupCursor];
}
- (void)cursorUpdate:(NSEvent*)e {
[super cursorUpdate:e];
[self fixupCursor];
}
- (void)configureTextView {
[self setEditable:NO];
[self setDrawsBackground:NO];
[self setHorizontallyResizable:NO];
[self setVerticallyResizable:NO];
// When text is rendered, linkTextAttributes override anything set via
// addAttributes for text that has NSLinkAttributeName. Set to nil to allow
// custom attributes to take precedence.
[self setLinkTextAttributes:nil];
[self setDisplaysLinkToolTips:NO];
refusesFirstResponder_ = NO;
drawsBackgroundUsingSuperview_ = NO;
}
- (void)fixupCursor {
if ([[NSCursor currentCursor] isEqual:[NSCursor IBeamCursor]])
[[NSCursor arrowCursor] set];
}
- (void)setMessageAndLink:(NSString*)message
withLink:(NSString*)link
atOffset:(NSUInteger)linkOffset
font:(NSFont*)font
messageColor:(NSColor*)messageColor
linkColor:(NSColor*)linkColor {
NSMutableString* finalMessage = [NSMutableString stringWithString:message];
[finalMessage insertString:link atIndex:linkOffset];
[self setMessage:finalMessage withFont:font messageColor:messageColor];
if ([link length] != 0) {
[self addLinkRange:NSMakeRange(linkOffset, [link length])
withName:@""
linkColor:linkColor];
}
}
- (void)setMessage:(NSString*)message
withFont:(NSFont*)font
messageColor:(NSColor*)messageColor {
// Create an attributes dictionary for the message and link.
NSDictionary* attributes = @{
NSForegroundColorAttributeName : messageColor,
NSCursorAttributeName : [NSCursor arrowCursor],
NSFontAttributeName : font,
NSBaselineOffsetAttributeName : @(kTextBaselineShift)
};
// Create the attributed string for the message.
base::scoped_nsobject<NSAttributedString> attributedMessage(
[[NSMutableAttributedString alloc] initWithString:message
attributes:attributes]);
// Update the text view with the new text.
[[self textStorage] setAttributedString:attributedMessage];
}
- (void)addLinkRange:(NSRange)range
withName:(id)name
linkColor:(NSColor*)linkColor {
NSDictionary* attributes = @{
NSForegroundColorAttributeName : linkColor,
NSUnderlineStyleAttributeName : @(YES),
NSCursorAttributeName : [NSCursor pointingHandCursor],
NSLinkAttributeName : name,
NSUnderlineStyleAttributeName : @(NSSingleUnderlineStyle)
};
[[self textStorage] addAttributes:attributes range:range];
}
- (void)setRefusesFirstResponder:(BOOL)refusesFirstResponder {
refusesFirstResponder_ = refusesFirstResponder;
}
@end
|