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