OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ui/app_list/cocoa/app_list_view_controller.h" | 5 #import "ui/app_list/cocoa/app_list_view_controller.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/mac/foundation_util.h" | 9 #include "base/mac/foundation_util.h" |
10 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "base/strings/sys_string_conversions.h" | 13 #include "base/strings/sys_string_conversions.h" |
| 14 #include "base/strings/utf_string_conversions.h" |
14 #include "skia/ext/skia_utils_mac.h" | 15 #include "skia/ext/skia_utils_mac.h" |
15 #include "ui/app_list/app_list_constants.h" | 16 #include "ui/app_list/app_list_constants.h" |
16 #include "ui/app_list/app_list_model.h" | 17 #include "ui/app_list/app_list_model.h" |
17 #include "ui/app_list/app_list_view_delegate.h" | 18 #include "ui/app_list/app_list_view_delegate.h" |
18 #include "ui/app_list/app_list_view_delegate_observer.h" | 19 #include "ui/app_list/app_list_view_delegate_observer.h" |
19 #import "ui/app_list/cocoa/app_list_pager_view.h" | 20 #import "ui/app_list/cocoa/app_list_pager_view.h" |
20 #import "ui/app_list/cocoa/apps_grid_controller.h" | 21 #import "ui/app_list/cocoa/apps_grid_controller.h" |
21 #include "ui/app_list/search_box_model.h" | 22 #include "ui/app_list/search_box_model.h" |
22 #import "ui/base/cocoa/flipped_view.h" | 23 #import "ui/base/cocoa/flipped_view.h" |
| 24 #import "ui/gfx/image/image_skia_util_mac.h" |
23 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | 25 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
24 | 26 |
25 namespace { | 27 namespace { |
26 | 28 |
27 // The roundedness of the corners of the bubble. | 29 // The roundedness of the corners of the bubble. |
28 const CGFloat kBubbleCornerRadius = 3; | 30 const CGFloat kBubbleCornerRadius = 3; |
29 | 31 |
30 // Height of the pager. | 32 // Height of the pager. |
31 const CGFloat kPagerPreferredHeight = 57; | 33 const CGFloat kPagerPreferredHeight = 57; |
32 | 34 |
33 // Height of separator line drawn between the searchbox and grid view. | 35 // Height of separator line drawn between the searchbox and grid view. |
34 const CGFloat kTopSeparatorSize = 1; | 36 const CGFloat kTopSeparatorSize = 1; |
35 | 37 |
36 // Height of the search input. | 38 // Height of the search input. |
37 const CGFloat kSearchInputHeight = 48; | 39 const CGFloat kSearchInputHeight = 48; |
38 | 40 |
39 // Minimum margin on either side of the pager. If the pager grows beyond this, | 41 // Minimum margin on either side of the pager. If the pager grows beyond this, |
40 // the segment size is reduced. | 42 // the segment size is reduced. |
41 const CGFloat kMinPagerMargin = 40; | 43 const CGFloat kMinPagerMargin = 40; |
42 // Maximum width of a single segment. | 44 // Maximum width of a single segment. |
43 const CGFloat kMaxSegmentWidth = 80; | 45 const CGFloat kMaxSegmentWidth = 80; |
44 | 46 |
45 // Duration of the animation for sliding in and out search results. | 47 // Duration of the animation for sliding in and out search results. |
46 const NSTimeInterval kResultsAnimationDuration = 0.2; | 48 const NSTimeInterval kResultsAnimationDuration = 0.2; |
47 | 49 |
| 50 // Properties of the message rectangle, if it is shown. |
| 51 const NSRect kMessageRect = {{12, 12}, {370, 91}}; |
| 52 const CGFloat kMessageCornerRadius = 2; |
| 53 const CGFloat kSpacingBelowMessageTitle = 6; |
| 54 const SkColor kMessageBackgroundColor = SkColorSetRGB(0xFF, 0xFD, 0xE7); |
| 55 const SkColor kMessageStrokeColor = SkColorSetARGB(0x3d, 0x00, 0x00, 0x00); |
| 56 // The inset should be 16px, but NSTextView has its own inset of 3. |
| 57 const CGFloat kMessageTextInset = 13; |
| 58 |
48 } // namespace | 59 } // namespace |
49 | 60 |
50 @interface BackgroundView : FlippedView; | 61 @interface BackgroundView : FlippedView; |
51 @end | 62 @end |
52 | 63 |
53 @implementation BackgroundView | 64 @implementation BackgroundView |
54 | 65 |
55 - (void)drawRect:(NSRect)dirtyRect { | 66 - (void)drawRect:(NSRect)dirtyRect { |
56 gfx::ScopedNSGraphicsContextSaveGState context; | 67 gfx::ScopedNSGraphicsContextSaveGState context; |
57 NSRect boundsRect = [self bounds]; | 68 NSRect boundsRect = [self bounds]; |
58 NSRect searchAreaRect = NSMakeRect(0, 0, | 69 NSRect searchAreaRect = NSMakeRect(0, 0, |
59 NSWidth(boundsRect), kSearchInputHeight); | 70 NSWidth(boundsRect), kSearchInputHeight); |
60 NSRect separatorRect = NSMakeRect(0, NSMaxY(searchAreaRect), | 71 NSRect separatorRect = NSMakeRect(0, NSMaxY(searchAreaRect), |
61 NSWidth(boundsRect), kTopSeparatorSize); | 72 NSWidth(boundsRect), kTopSeparatorSize); |
62 | 73 |
63 [[NSBezierPath bezierPathWithRoundedRect:boundsRect | 74 [[NSBezierPath bezierPathWithRoundedRect:boundsRect |
64 xRadius:kBubbleCornerRadius | 75 xRadius:kBubbleCornerRadius |
65 yRadius:kBubbleCornerRadius] addClip]; | 76 yRadius:kBubbleCornerRadius] addClip]; |
66 | 77 |
67 [skia::SkColorToSRGBNSColor(app_list::kContentsBackgroundColor) set]; | 78 [skia::SkColorToSRGBNSColor(app_list::kContentsBackgroundColor) set]; |
68 NSRectFill(boundsRect); | 79 NSRectFill(boundsRect); |
69 [skia::SkColorToSRGBNSColor(app_list::kSearchBoxBackground) set]; | 80 [skia::SkColorToSRGBNSColor(app_list::kSearchBoxBackground) set]; |
70 NSRectFill(searchAreaRect); | 81 NSRectFill(searchAreaRect); |
71 [skia::SkColorToSRGBNSColor(app_list::kTopSeparatorColor) set]; | 82 [skia::SkColorToSRGBNSColor(app_list::kTopSeparatorColor) set]; |
72 NSRectFill(separatorRect); | 83 NSRectFill(separatorRect); |
73 } | 84 } |
74 | 85 |
75 @end | 86 @end |
76 | 87 |
| 88 @interface MessageBackgroundView : FlippedView |
| 89 @end |
| 90 |
| 91 @implementation MessageBackgroundView |
| 92 |
| 93 - (void)drawRect:(NSRect)dirtyRect { |
| 94 NSRect boundsRect = [self bounds]; |
| 95 gfx::ScopedNSGraphicsContextSaveGState context; |
| 96 [[NSBezierPath bezierPathWithRoundedRect:boundsRect |
| 97 xRadius:kMessageCornerRadius |
| 98 yRadius:kMessageCornerRadius] addClip]; |
| 99 |
| 100 [skia::SkColorToSRGBNSColor(kMessageStrokeColor) set]; |
| 101 NSRectFill(boundsRect); |
| 102 |
| 103 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(boundsRect, 1, 1) |
| 104 xRadius:kMessageCornerRadius |
| 105 yRadius:kMessageCornerRadius] addClip]; |
| 106 [skia::SkColorToSRGBNSColor(kMessageBackgroundColor) set]; |
| 107 NSRectFill(boundsRect); |
| 108 } |
| 109 |
| 110 @end |
| 111 |
77 @interface AppListViewController () | 112 @interface AppListViewController () |
78 | 113 |
| 114 - (void)updateMessage; |
79 - (void)loadAndSetView; | 115 - (void)loadAndSetView; |
80 - (void)revealSearchResults:(BOOL)show; | 116 - (void)revealSearchResults:(BOOL)show; |
81 | 117 |
82 @end | 118 @end |
83 | 119 |
84 namespace app_list { | 120 namespace app_list { |
85 | 121 |
86 class AppListModelObserverBridge : public AppListViewDelegateObserver { | 122 class AppListModelObserverBridge : public AppListViewDelegateObserver { |
87 public: | 123 public: |
88 AppListModelObserverBridge(AppListViewController* parent); | 124 AppListModelObserverBridge(AppListViewController* parent); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 if (delegate_) { | 205 if (delegate_) { |
170 // Ensure the search box is cleared when switching profiles. | 206 // Ensure the search box is cleared when switching profiles. |
171 if ([self searchBoxModel]) | 207 if ([self searchBoxModel]) |
172 [self searchBoxModel]->SetText(base::string16()); | 208 [self searchBoxModel]->SetText(base::string16()); |
173 | 209 |
174 // First clean up, in reverse order. | 210 // First clean up, in reverse order. |
175 app_list_model_observer_bridge_.reset(); | 211 app_list_model_observer_bridge_.reset(); |
176 [appsSearchResultsController_ setDelegate:nil]; | 212 [appsSearchResultsController_ setDelegate:nil]; |
177 [appsSearchBoxController_ setDelegate:nil]; | 213 [appsSearchBoxController_ setDelegate:nil]; |
178 [appsGridController_ setDelegate:nil]; | 214 [appsGridController_ setDelegate:nil]; |
| 215 [messageText_ setDelegate:nil]; |
179 } | 216 } |
180 delegate_ = newDelegate; | 217 delegate_ = newDelegate; |
181 if (delegate_) { | 218 if (delegate_) { |
182 [loadingIndicator_ stopAnimation:self]; | 219 [loadingIndicator_ stopAnimation:self]; |
183 } else { | 220 } else { |
184 [loadingIndicator_ startAnimation:self]; | 221 [loadingIndicator_ startAnimation:self]; |
185 return; | 222 return; |
186 } | 223 } |
187 | 224 |
188 [appsGridController_ setDelegate:delegate_]; | 225 [appsGridController_ setDelegate:delegate_]; |
189 [appsSearchBoxController_ setDelegate:self]; | 226 [appsSearchBoxController_ setDelegate:self]; |
190 [appsSearchResultsController_ setDelegate:self]; | 227 [appsSearchResultsController_ setDelegate:self]; |
191 app_list_model_observer_bridge_.reset( | 228 app_list_model_observer_bridge_.reset( |
192 new app_list::AppListModelObserverBridge(self)); | 229 new app_list::AppListModelObserverBridge(self)); |
193 [self onProfilesChanged]; | 230 [self onProfilesChanged]; |
| 231 [self updateMessage]; |
194 } | 232 } |
195 | 233 |
196 -(void)loadAndSetView { | 234 - (void)updateMessage { |
| 235 if (![AppsGridController hasFewerRows]) |
| 236 return; |
| 237 |
| 238 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 239 NSFont* messageFont = rb.GetFontWithDelta(0).GetNativeFont(); |
| 240 NSFont* titleFont = rb.GetFontWithDelta(2).GetNativeFont(); |
| 241 |
| 242 base::string16 title = delegate_->GetMessageTitle(); |
| 243 size_t messageBreak; |
| 244 base::string16 messageFull = delegate_->GetMessageText(&messageBreak); |
| 245 base::string16 shortcutName = delegate_->GetAppsShortcutName(); |
| 246 base::string16 learnMore = delegate_->GetLearnMoreText(); |
| 247 base::string16 learnMoreUrl = delegate_->GetLearnMoreLink(); |
| 248 |
| 249 base::string16 messagePre = messageFull.substr(0, messageBreak); |
| 250 base::string16 messagePost = messageFull.substr(messageBreak); |
| 251 |
| 252 NSURL* linkURL = [NSURL URLWithString:base::SysUTF16ToNSString(learnMoreUrl)]; |
| 253 gfx::ImageSkia* icon = delegate_->GetAppsIcon(); |
| 254 |
| 255 // Shift the baseline up so that the graphics align centered. 4 looks nice. It |
| 256 // happens to be the image size minus the font size, but that's a coincidence. |
| 257 const CGFloat kBaselineShift = 4; |
| 258 base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( |
| 259 [[NSMutableParagraphStyle alloc] init]); |
| 260 [paragraphStyle setLineSpacing:kSpacingBelowMessageTitle + kBaselineShift]; |
| 261 |
| 262 NSNumber* baselineOffset = [NSNumber numberWithFloat:kBaselineShift]; |
| 263 base::scoped_nsobject<NSMutableAttributedString> text( |
| 264 [[NSMutableAttributedString alloc] |
| 265 initWithString:base::SysUTF16ToNSString(title) |
| 266 attributes:@{ |
| 267 NSParagraphStyleAttributeName : paragraphStyle, |
| 268 NSFontAttributeName : titleFont |
| 269 }]); |
| 270 |
| 271 NSDictionary* defaultAttributes = @{ |
| 272 NSFontAttributeName : messageFont, |
| 273 NSBaselineOffsetAttributeName : baselineOffset |
| 274 }; |
| 275 |
| 276 base::scoped_nsobject<NSAttributedString> lineBreak( |
| 277 [[NSAttributedString alloc] initWithString:@"\n" |
| 278 attributes:defaultAttributes]); |
| 279 base::scoped_nsobject<NSAttributedString> space([[NSAttributedString alloc] |
| 280 initWithString:@" " |
| 281 attributes:defaultAttributes]); |
| 282 base::scoped_nsobject<NSAttributedString> messagePreString( |
| 283 [[NSAttributedString alloc] |
| 284 initWithString:base::SysUTF16ToNSString(messagePre) |
| 285 attributes:defaultAttributes]); |
| 286 base::scoped_nsobject<NSAttributedString> messagePostString( |
| 287 [[NSAttributedString alloc] |
| 288 initWithString:base::SysUTF16ToNSString(messagePost) |
| 289 attributes:defaultAttributes]); |
| 290 |
| 291 // NSNoUnderlineStyle is broken. |
| 292 base::scoped_nsobject<NSAttributedString> learnMoreString( |
| 293 [[NSAttributedString alloc] |
| 294 initWithString:base::SysUTF16ToNSString(learnMore) |
| 295 attributes:@{ |
| 296 NSParagraphStyleAttributeName : paragraphStyle, |
| 297 NSFontAttributeName : messageFont, |
| 298 NSLinkAttributeName : linkURL, |
| 299 NSBaselineOffsetAttributeName : baselineOffset, |
| 300 NSUnderlineStyleAttributeName : |
| 301 [NSNumber numberWithInt:NSNoUnderlineStyle] |
| 302 }]); |
| 303 base::scoped_nsobject<NSAttributedString> shortcutStringText( |
| 304 [[NSAttributedString alloc] |
| 305 initWithString:base::SysUTF16ToNSString(shortcutName) |
| 306 attributes:defaultAttributes]); |
| 307 base::scoped_nsobject<NSMutableAttributedString> shortcutString( |
| 308 [[NSMutableAttributedString alloc] init]); |
| 309 if (icon) { |
| 310 NSImage* image = gfx::NSImageFromImageSkia(*icon); |
| 311 // The image has a bunch of representations. Ensure the smallest is used. |
| 312 // (Going smaller would make pixels all manky, so don't do that). |
| 313 [image setSize:NSMakeSize(16, 16)]; |
| 314 |
| 315 base::scoped_nsobject<NSTextAttachmentCell> attachmentCell( |
| 316 [[NSTextAttachmentCell alloc] initImageCell:image]); |
| 317 base::scoped_nsobject<NSTextAttachment> attachment( |
| 318 [[NSTextAttachment alloc] init]); |
| 319 [attachment setAttachmentCell:attachmentCell]; |
| 320 [shortcutString |
| 321 appendAttributedString:[NSAttributedString |
| 322 attributedStringWithAttachment:attachment]]; |
| 323 [shortcutString appendAttributedString:space]; |
| 324 } |
| 325 [shortcutString appendAttributedString:shortcutStringText]; |
| 326 |
| 327 [text appendAttributedString:lineBreak]; |
| 328 [text appendAttributedString:messagePreString]; |
| 329 [text appendAttributedString:shortcutString]; |
| 330 [text appendAttributedString:messagePostString]; |
| 331 [text appendAttributedString:space]; |
| 332 [text appendAttributedString:learnMoreString]; |
| 333 |
| 334 [[messageText_ textStorage] setAttributedString:text]; |
| 335 [messageText_ sizeToFit]; |
| 336 |
| 337 // If the user scroller preference is to always show scrollbars, and the |
| 338 // translated message is long, the scroll track may be present. This means |
| 339 // text will be under the scroller. We only want vertical scrolling, but |
| 340 // reducing the width puts the scroll track in a weird spot. So, increase the |
| 341 // width of the scroll view to move the track into the padding towards the |
| 342 // message background border, then reduce the width of the text view. The |
| 343 // non-overlay scroller still looks kinda weird but hopefully not many will |
| 344 // actually see it. |
| 345 CGFloat overlap = |
| 346 NSWidth([messageText_ bounds]) - [messageScrollView_ contentSize].width; |
| 347 if (overlap > 0) { |
| 348 NSRect rect = [messageScrollView_ frame]; |
| 349 rect.size.width += kMessageTextInset - 2; |
| 350 [messageScrollView_ setFrame:rect]; |
| 351 overlap -= kMessageTextInset - 2; |
| 352 DCHECK_GT(overlap, 0); |
| 353 rect = [messageText_ frame]; |
| 354 rect.size.width -= overlap; |
| 355 [messageText_ setFrame:rect]; |
| 356 [messageText_ sizeToFit]; |
| 357 |
| 358 // And after doing all that for some reason Cocoa scrolls to the bottom. So |
| 359 // fix that. |
| 360 [[messageScrollView_ documentView] scrollPoint:NSMakePoint(0, 0)]; |
| 361 } |
| 362 |
| 363 [messageText_ setDelegate:self]; |
| 364 } |
| 365 |
| 366 - (void)loadAndSetView { |
197 pagerControl_.reset([[AppListPagerView alloc] init]); | 367 pagerControl_.reset([[AppListPagerView alloc] init]); |
198 [pagerControl_ setTarget:appsGridController_]; | 368 [pagerControl_ setTarget:appsGridController_]; |
199 [pagerControl_ setAction:@selector(onPagerClicked:)]; | 369 [pagerControl_ setAction:@selector(onPagerClicked:)]; |
200 | 370 |
201 NSRect gridFrame = [[appsGridController_ view] frame]; | 371 NSRect gridFrame = [[appsGridController_ view] frame]; |
202 NSRect contentsRect = NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize, | 372 |
203 NSWidth(gridFrame), NSHeight(gridFrame) + kPagerPreferredHeight - | 373 base::scoped_nsobject<NSView> messageTextBackground; |
204 [AppsGridController scrollerPadding]); | 374 if ([AppsGridController hasFewerRows]) { |
| 375 messageTextBackground.reset( |
| 376 [[MessageBackgroundView alloc] initWithFrame:kMessageRect]); |
| 377 NSRect frameRect = |
| 378 NSInsetRect(kMessageRect, kMessageTextInset, kMessageTextInset); |
| 379 messageText_.reset([[NSTextView alloc] initWithFrame:frameRect]); |
| 380 // Provide a solid background here (as well as the background) so that |
| 381 // subpixel AA works. |
| 382 [messageText_ |
| 383 setBackgroundColor:skia::SkColorToSRGBNSColor(kMessageBackgroundColor)]; |
| 384 [messageText_ setDrawsBackground:YES]; |
| 385 [messageText_ setEditable:NO]; |
| 386 // Ideally setSelectable:NO would also be set here, but that disables mouse |
| 387 // events completely, breaking the "Learn more" link. Instead, selection is |
| 388 // "disabled" via a delegate method which Apple's documentation suggests. In |
| 389 // reality, selection still happens, it just disappears once the mouse is |
| 390 // released. To avoid the selection appearing, also set selected text to |
| 391 // have no special attributes. Sadly, the mouse cursor still displays an |
| 392 // I-beam, but hacking cursor rectangles on the view so that the "Learn |
| 393 // More" link is still correctly handled is too hard. |
| 394 [messageText_ setSelectedTextAttributes:@{}]; |
| 395 gridFrame.origin.y += NSMaxY([messageTextBackground frame]); |
| 396 } |
| 397 |
| 398 [[appsGridController_ view] setFrame:gridFrame]; |
| 399 |
| 400 NSRect contentsRect = |
| 401 NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize, NSWidth(gridFrame), |
| 402 NSMaxY(gridFrame) + kPagerPreferredHeight - |
| 403 [AppsGridController scrollerPadding]); |
205 | 404 |
206 contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]); | 405 contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]); |
207 | 406 |
208 // The contents view contains animations both from an NSCollectionView and the | 407 // The contents view contains animations both from an NSCollectionView and the |
209 // app list's own transitive drag layers. On Mavericks, the subviews need to | 408 // app list's own transitive drag layers. On Mavericks, the subviews need to |
210 // have access to a compositing layer they can share. Otherwise the compositor | 409 // have access to a compositing layer they can share. Otherwise the compositor |
211 // makes tearing artifacts. However, doing this on Mountain Lion or earler | 410 // makes tearing artifacts. However, doing this on Mountain Lion or earler |
212 // results in flickering whilst an item is installing. | 411 // results in flickering whilst an item is installing. |
213 if (base::mac::IsOSMavericksOrLater()) | 412 if (base::mac::IsOSMavericksOrLater()) |
214 [contentsView_ setWantsLayer:YES]; | 413 [contentsView_ setWantsLayer:YES]; |
(...skipping 14 matching lines...) Expand all Loading... |
229 [[NSProgressIndicator alloc] initWithFrame:NSZeroRect]); | 428 [[NSProgressIndicator alloc] initWithFrame:NSZeroRect]); |
230 [loadingIndicator_ setStyle:NSProgressIndicatorSpinningStyle]; | 429 [loadingIndicator_ setStyle:NSProgressIndicatorSpinningStyle]; |
231 [loadingIndicator_ sizeToFit]; | 430 [loadingIndicator_ sizeToFit]; |
232 NSRect indicatorRect = [loadingIndicator_ frame]; | 431 NSRect indicatorRect = [loadingIndicator_ frame]; |
233 indicatorRect.origin.x = NSWidth(contentsRect) / 2 - NSMidX(indicatorRect); | 432 indicatorRect.origin.x = NSWidth(contentsRect) / 2 - NSMidX(indicatorRect); |
234 indicatorRect.origin.y = NSHeight(contentsRect) / 2 - NSMidY(indicatorRect); | 433 indicatorRect.origin.y = NSHeight(contentsRect) / 2 - NSMidY(indicatorRect); |
235 [loadingIndicator_ setFrame:indicatorRect]; | 434 [loadingIndicator_ setFrame:indicatorRect]; |
236 [loadingIndicator_ setDisplayedWhenStopped:NO]; | 435 [loadingIndicator_ setDisplayedWhenStopped:NO]; |
237 [loadingIndicator_ startAnimation:self]; | 436 [loadingIndicator_ startAnimation:self]; |
238 | 437 |
| 438 if (messageText_) { |
| 439 [contentsView_ addSubview:messageTextBackground]; |
| 440 |
| 441 // Add a scroll view in case the translation is long and doesn't fit. Mac |
| 442 // likes to hide scrollbars, so add to the height so the user can see part |
| 443 // of the next line of text: just extend out into the padding towards the |
| 444 // text background's border. Subtract at least 2: one for the border stroke |
| 445 // and one for a bit of padding. |
| 446 NSRect frameRect = [messageText_ frame]; |
| 447 frameRect.size.height += kMessageTextInset - 2; |
| 448 messageScrollView_.reset([[NSScrollView alloc] initWithFrame:frameRect]); |
| 449 [messageScrollView_ setHasVerticalScroller:YES]; |
| 450 [messageScrollView_ setAutohidesScrollers:YES]; |
| 451 |
| 452 // Now the message is going into an NSScrollView, origin should be 0, 0. |
| 453 frameRect = [messageText_ frame]; |
| 454 frameRect.origin = NSMakePoint(0, 0); |
| 455 [messageText_ setFrame:frameRect]; |
| 456 |
| 457 [messageScrollView_ setDocumentView:messageText_]; |
| 458 [contentsView_ addSubview:messageScrollView_]; |
| 459 } |
239 [contentsView_ addSubview:[appsGridController_ view]]; | 460 [contentsView_ addSubview:[appsGridController_ view]]; |
240 [contentsView_ addSubview:pagerControl_]; | 461 [contentsView_ addSubview:pagerControl_]; |
241 [contentsView_ addSubview:loadingIndicator_]; | 462 [contentsView_ addSubview:loadingIndicator_]; |
242 [backgroundView_ addSubview:contentsView_]; | 463 [backgroundView_ addSubview:contentsView_]; |
243 [backgroundView_ addSubview:[appsSearchResultsController_ view]]; | 464 [backgroundView_ addSubview:[appsSearchResultsController_ view]]; |
244 [backgroundView_ addSubview:[appsSearchBoxController_ view]]; | 465 [backgroundView_ addSubview:[appsSearchBoxController_ view]]; |
245 [containerView addSubview:backgroundView_]; | 466 [containerView addSubview:backgroundView_]; |
246 [self setView:containerView]; | 467 [self setView:containerView]; |
247 } | 468 } |
248 | 469 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 if (delegate_) { | 582 if (delegate_) { |
362 delegate_->OpenSearchResult( | 583 delegate_->OpenSearchResult( |
363 result, false /* auto_launch */, 0 /* event flags */); | 584 result, false /* auto_launch */, 0 /* event flags */); |
364 } | 585 } |
365 } | 586 } |
366 | 587 |
367 - (void)onProfilesChanged { | 588 - (void)onProfilesChanged { |
368 [appsSearchBoxController_ rebuildMenu]; | 589 [appsSearchBoxController_ rebuildMenu]; |
369 } | 590 } |
370 | 591 |
| 592 // NSTextViewDelegate implementation. |
| 593 |
| 594 - (BOOL)textView:(NSTextView*)textView |
| 595 clickedOnLink:(id)link |
| 596 atIndex:(NSUInteger)charIndex { |
| 597 DCHECK(delegate_); |
| 598 delegate_->OpenLearnMoreLink(); |
| 599 return YES; |
| 600 } |
| 601 |
| 602 - (NSArray*)textView:(NSTextView*)aTextView |
| 603 willChangeSelectionFromCharacterRanges:(NSArray*)oldSelectedCharRanges |
| 604 toCharacterRanges:(NSArray*)newSelectedCharRanges { |
| 605 return oldSelectedCharRanges; |
| 606 } |
| 607 |
371 @end | 608 @end |
OLD | NEW |