Chromium Code Reviews| 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 |
| 79 - (void)loadAndSetView; | 114 - (void)loadAndSetView; |
| 80 - (void)revealSearchResults:(BOOL)show; | 115 - (void)revealSearchResults:(BOOL)show; |
| 81 | 116 |
| 82 @end | 117 @end |
| 83 | 118 |
| 84 namespace app_list { | 119 namespace app_list { |
| 85 | 120 |
| 86 class AppListModelObserverBridge : public AppListViewDelegateObserver { | 121 class AppListModelObserverBridge : public AppListViewDelegateObserver { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 if (delegate_) { | 204 if (delegate_) { |
| 170 // Ensure the search box is cleared when switching profiles. | 205 // Ensure the search box is cleared when switching profiles. |
| 171 if ([self searchBoxModel]) | 206 if ([self searchBoxModel]) |
| 172 [self searchBoxModel]->SetText(base::string16()); | 207 [self searchBoxModel]->SetText(base::string16()); |
| 173 | 208 |
| 174 // First clean up, in reverse order. | 209 // First clean up, in reverse order. |
| 175 app_list_model_observer_bridge_.reset(); | 210 app_list_model_observer_bridge_.reset(); |
| 176 [appsSearchResultsController_ setDelegate:nil]; | 211 [appsSearchResultsController_ setDelegate:nil]; |
| 177 [appsSearchBoxController_ setDelegate:nil]; | 212 [appsSearchBoxController_ setDelegate:nil]; |
| 178 [appsGridController_ setDelegate:nil]; | 213 [appsGridController_ setDelegate:nil]; |
| 214 [messageText_ setDelegate:nil]; | |
| 179 } | 215 } |
| 180 delegate_ = newDelegate; | 216 delegate_ = newDelegate; |
| 181 if (delegate_) { | 217 if (delegate_) { |
| 182 [loadingIndicator_ stopAnimation:self]; | 218 [loadingIndicator_ stopAnimation:self]; |
| 183 } else { | 219 } else { |
| 184 [loadingIndicator_ startAnimation:self]; | 220 [loadingIndicator_ startAnimation:self]; |
| 185 return; | 221 return; |
| 186 } | 222 } |
| 187 | 223 |
| 188 [appsGridController_ setDelegate:delegate_]; | 224 [appsGridController_ setDelegate:delegate_]; |
| 189 [appsSearchBoxController_ setDelegate:self]; | 225 [appsSearchBoxController_ setDelegate:self]; |
| 190 [appsSearchResultsController_ setDelegate:self]; | 226 [appsSearchResultsController_ setDelegate:self]; |
| 191 app_list_model_observer_bridge_.reset( | 227 app_list_model_observer_bridge_.reset( |
| 192 new app_list::AppListModelObserverBridge(self)); | 228 new app_list::AppListModelObserverBridge(self)); |
| 193 [self onProfilesChanged]; | 229 [self onProfilesChanged]; |
| 230 | |
| 231 if (![AppsGridController hasFewerRows]) | |
| 232 return; | |
| 233 | |
| 234 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 235 NSFont* messageFont = rb.GetFontWithDelta(0).GetNativeFont(); | |
| 236 NSFont* titleFont = rb.GetFontWithDelta(2).GetNativeFont(); | |
| 237 | |
| 238 base::string16 title = delegate_->GetMessageTitle(); | |
| 239 base::string16 message_full = delegate_->GetMessageText(); | |
| 240 base::string16 shortcutName = delegate_->GetAppsShortcutName(); | |
| 241 base::string16 learnMore = delegate_->GetLearnMoreText(); | |
| 242 base::string16 learnMoreUrl = delegate_->GetLearnMoreLink(); | |
| 243 | |
| 244 size_t messageBreak = message_full.find(base::ASCIIToUTF16("$1")); | |
|
Matt Giuca
2016/03/22 03:28:06
I don't think you should be parsing this yourself.
tapted
2016/03/22 04:19:50
oh groovy - I'll patch in your thingy.
tapted
2016/03/22 04:58:14
Done.
| |
| 245 DCHECK_NE(base::string16::npos, messageBreak); | |
| 246 base::string16 messagePre = message_full.substr(0, messageBreak); | |
| 247 base::string16 messagePost = message_full.substr(messageBreak + 2); | |
| 248 | |
| 249 NSURL* linkURL = [NSURL URLWithString:base::SysUTF16ToNSString(learnMoreUrl)]; | |
| 250 gfx::ImageSkia* icon = delegate_->GetAppsIcon(); | |
| 251 | |
| 252 // Shift the baseline up so that the graphics align centered. 4 looks nice. It | |
| 253 // happens to be the image size minus the font size, but that's a coincidence. | |
| 254 const CGFloat kBaselineShift = 4; | |
| 255 base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( | |
| 256 [[NSMutableParagraphStyle alloc] init]); | |
| 257 [paragraphStyle setLineSpacing:kSpacingBelowMessageTitle + kBaselineShift]; | |
| 258 | |
| 259 NSNumber* baselineOffset = [NSNumber numberWithFloat:kBaselineShift]; | |
| 260 base::scoped_nsobject<NSMutableAttributedString> text( | |
| 261 [[NSMutableAttributedString alloc] | |
| 262 initWithString:base::SysUTF16ToNSString(title) | |
| 263 attributes:@{ | |
| 264 NSParagraphStyleAttributeName : paragraphStyle, | |
| 265 NSFontAttributeName : titleFont | |
| 266 }]); | |
| 267 | |
| 268 NSDictionary* defaultAttributes = @{ | |
| 269 NSFontAttributeName : messageFont, | |
| 270 NSBaselineOffsetAttributeName : baselineOffset | |
| 271 }; | |
| 272 | |
| 273 base::scoped_nsobject<NSAttributedString> lineBreak( | |
| 274 [[NSAttributedString alloc] initWithString:@"\n" | |
| 275 attributes:defaultAttributes]); | |
| 276 base::scoped_nsobject<NSAttributedString> space([[NSAttributedString alloc] | |
| 277 initWithString:@" " | |
| 278 attributes:defaultAttributes]); | |
| 279 base::scoped_nsobject<NSAttributedString> messagePreString( | |
| 280 [[NSAttributedString alloc] | |
| 281 initWithString:base::SysUTF16ToNSString(messagePre) | |
| 282 attributes:defaultAttributes]); | |
| 283 base::scoped_nsobject<NSAttributedString> messagePostString( | |
| 284 [[NSAttributedString alloc] | |
| 285 initWithString:base::SysUTF16ToNSString(messagePost) | |
| 286 attributes:defaultAttributes]); | |
| 287 | |
| 288 // NSNoUnderlineStyle is broken. | |
| 289 base::scoped_nsobject<NSAttributedString> learnMoreString( | |
| 290 [[NSAttributedString alloc] | |
| 291 initWithString:base::SysUTF16ToNSString(learnMore) | |
| 292 attributes:@{ | |
| 293 NSParagraphStyleAttributeName : paragraphStyle, | |
| 294 NSFontAttributeName : messageFont, | |
| 295 NSLinkAttributeName : linkURL, | |
| 296 NSBaselineOffsetAttributeName : baselineOffset, | |
| 297 NSUnderlineStyleAttributeName : | |
| 298 [NSNumber numberWithInt:NSNoUnderlineStyle] | |
| 299 }]); | |
| 300 base::scoped_nsobject<NSAttributedString> shortcutStringText( | |
| 301 [[NSAttributedString alloc] | |
| 302 initWithString:base::SysUTF16ToNSString(shortcutName) | |
| 303 attributes:defaultAttributes]); | |
| 304 base::scoped_nsobject<NSMutableAttributedString> shortcutString( | |
| 305 [[NSMutableAttributedString alloc] init]); | |
| 306 if (icon) { | |
| 307 NSImage* image = gfx::NSImageFromImageSkia(*icon); | |
| 308 // The image has a bunch of representations. Ensure the smallest is used. | |
| 309 // (Going smaller would make pixels all manky, so don't do that). | |
| 310 [image setSize:NSMakeSize(16, 16)]; | |
| 311 | |
| 312 base::scoped_nsobject<NSTextAttachmentCell> attachmentCell( | |
| 313 [[NSTextAttachmentCell alloc] initImageCell:image]); | |
| 314 base::scoped_nsobject<NSTextAttachment> attachment( | |
| 315 [[NSTextAttachment alloc] init]); | |
| 316 [attachment setAttachmentCell:attachmentCell]; | |
| 317 [shortcutString | |
| 318 appendAttributedString:[NSAttributedString | |
| 319 attributedStringWithAttachment:attachment]]; | |
| 320 [shortcutString appendAttributedString:space]; | |
| 321 } | |
| 322 [shortcutString appendAttributedString:shortcutStringText]; | |
| 323 | |
| 324 [text appendAttributedString:lineBreak]; | |
| 325 [text appendAttributedString:messagePreString]; | |
| 326 [text appendAttributedString:shortcutString]; | |
| 327 [text appendAttributedString:messagePostString]; | |
| 328 [text appendAttributedString:space]; | |
| 329 [text appendAttributedString:learnMoreString]; | |
| 330 | |
| 331 [[messageText_ textStorage] setAttributedString:text]; | |
| 332 [messageText_ sizeToFit]; | |
| 333 | |
| 334 // If the user scroller preference is to always show scrollbars, and the | |
| 335 // translated message is long, the scroll track may be present. This means | |
| 336 // text will be under the scroller. We only want vertical scrolling, but | |
| 337 // reducing the width puts the scroll track in a weird spot. So, increase the | |
| 338 // width of the scroll view to move the track into the padding towards the | |
| 339 // message background border, then reduce the width of the text view. The | |
| 340 // non-overlay scroller still looks kinda weird but hopefully not many will | |
| 341 // actually see it. | |
| 342 CGFloat overlap = | |
| 343 NSWidth([messageText_ bounds]) - [messageScrollView_ contentSize].width; | |
| 344 if (overlap > 0) { | |
| 345 NSRect rect = [messageScrollView_ frame]; | |
| 346 rect.size.width += kMessageTextInset - 2; | |
| 347 [messageScrollView_ setFrame:rect]; | |
| 348 overlap -= kMessageTextInset - 2; | |
| 349 DCHECK_GT(overlap, 0); | |
| 350 rect = [messageText_ frame]; | |
| 351 rect.size.width -= overlap; | |
| 352 [messageText_ setFrame:rect]; | |
| 353 [messageText_ sizeToFit]; | |
| 354 | |
| 355 // And after doing all that for some reason Cocoa scrolls to the bottom. So | |
| 356 // fix that. | |
| 357 [[messageScrollView_ documentView] scrollPoint:NSMakePoint(0, 0)]; | |
| 358 } | |
| 359 | |
| 360 [messageText_ setDelegate:self]; | |
| 194 } | 361 } |
| 195 | 362 |
| 196 -(void)loadAndSetView { | 363 -(void)loadAndSetView { |
| 197 pagerControl_.reset([[AppListPagerView alloc] init]); | 364 pagerControl_.reset([[AppListPagerView alloc] init]); |
| 198 [pagerControl_ setTarget:appsGridController_]; | 365 [pagerControl_ setTarget:appsGridController_]; |
| 199 [pagerControl_ setAction:@selector(onPagerClicked:)]; | 366 [pagerControl_ setAction:@selector(onPagerClicked:)]; |
| 200 | 367 |
| 201 NSRect gridFrame = [[appsGridController_ view] frame]; | 368 NSRect gridFrame = [[appsGridController_ view] frame]; |
| 202 NSRect contentsRect = NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize, | 369 |
| 203 NSWidth(gridFrame), NSHeight(gridFrame) + kPagerPreferredHeight - | 370 base::scoped_nsobject<NSView> messageTextBackground; |
| 204 [AppsGridController scrollerPadding]); | 371 if ([AppsGridController hasFewerRows]) { |
| 372 messageTextBackground.reset( | |
| 373 [[MessageBackgroundView alloc] initWithFrame:kMessageRect]); | |
| 374 NSRect frameRect = | |
| 375 NSInsetRect(kMessageRect, kMessageTextInset, kMessageTextInset); | |
| 376 messageText_.reset([[NSTextView alloc] initWithFrame:frameRect]); | |
| 377 // Provide a solid background here (as well as the background) so that | |
| 378 // subpixel AA works. | |
| 379 [messageText_ | |
| 380 setBackgroundColor:skia::SkColorToSRGBNSColor(kMessageBackgroundColor)]; | |
| 381 [messageText_ setDrawsBackground:YES]; | |
| 382 [messageText_ setEditable:NO]; | |
| 383 // Ideally setSelectable:NO would also be set here, but that disables mouse | |
| 384 // events completely, breaking the "Learn more" link. Instead, selection is | |
| 385 // "disabled" via a delegate method which Apple's documentation suggests. In | |
| 386 // reality, selection still happens, it just disappears once the mouse is | |
| 387 // released. To avoid the selection appearing, also set selected text to | |
| 388 // have no special attributes. Sadly, the mouse cursor still displays an | |
| 389 // I-beam, but hacking cursor rectangles on the view so that the "Learn | |
| 390 // More" link is still correctly handled is too hard. | |
| 391 [messageText_ setSelectedTextAttributes:@{}]; | |
| 392 gridFrame.origin.y += NSMaxY([messageTextBackground frame]); | |
| 393 } | |
| 394 | |
| 395 [[appsGridController_ view] setFrame:gridFrame]; | |
| 396 | |
| 397 NSRect contentsRect = | |
| 398 NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize, NSWidth(gridFrame), | |
| 399 NSMaxY(gridFrame) + kPagerPreferredHeight - | |
| 400 [AppsGridController scrollerPadding]); | |
| 205 | 401 |
| 206 contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]); | 402 contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]); |
| 207 | 403 |
| 208 // The contents view contains animations both from an NSCollectionView and the | 404 // 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 | 405 // 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 | 406 // have access to a compositing layer they can share. Otherwise the compositor |
| 211 // makes tearing artifacts. However, doing this on Mountain Lion or earler | 407 // makes tearing artifacts. However, doing this on Mountain Lion or earler |
| 212 // results in flickering whilst an item is installing. | 408 // results in flickering whilst an item is installing. |
| 213 if (base::mac::IsOSMavericksOrLater()) | 409 if (base::mac::IsOSMavericksOrLater()) |
| 214 [contentsView_ setWantsLayer:YES]; | 410 [contentsView_ setWantsLayer:YES]; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 229 [[NSProgressIndicator alloc] initWithFrame:NSZeroRect]); | 425 [[NSProgressIndicator alloc] initWithFrame:NSZeroRect]); |
| 230 [loadingIndicator_ setStyle:NSProgressIndicatorSpinningStyle]; | 426 [loadingIndicator_ setStyle:NSProgressIndicatorSpinningStyle]; |
| 231 [loadingIndicator_ sizeToFit]; | 427 [loadingIndicator_ sizeToFit]; |
| 232 NSRect indicatorRect = [loadingIndicator_ frame]; | 428 NSRect indicatorRect = [loadingIndicator_ frame]; |
| 233 indicatorRect.origin.x = NSWidth(contentsRect) / 2 - NSMidX(indicatorRect); | 429 indicatorRect.origin.x = NSWidth(contentsRect) / 2 - NSMidX(indicatorRect); |
| 234 indicatorRect.origin.y = NSHeight(contentsRect) / 2 - NSMidY(indicatorRect); | 430 indicatorRect.origin.y = NSHeight(contentsRect) / 2 - NSMidY(indicatorRect); |
| 235 [loadingIndicator_ setFrame:indicatorRect]; | 431 [loadingIndicator_ setFrame:indicatorRect]; |
| 236 [loadingIndicator_ setDisplayedWhenStopped:NO]; | 432 [loadingIndicator_ setDisplayedWhenStopped:NO]; |
| 237 [loadingIndicator_ startAnimation:self]; | 433 [loadingIndicator_ startAnimation:self]; |
| 238 | 434 |
| 435 if (messageText_) { | |
| 436 [contentsView_ addSubview:messageTextBackground]; | |
| 437 | |
| 438 // Add a scroll view in case the translation is long and doesn't fit. Mac | |
| 439 // likes to hide scrollbars, so add to the height so the user can see part | |
| 440 // of the next line of text: just extend out into the padding towards the | |
| 441 // text background's border. Subtract at least 2: one for the border stroke | |
| 442 // and one for a bit of padding. | |
| 443 NSRect frameRect = [messageText_ frame]; | |
| 444 frameRect.size.height += kMessageTextInset - 2; | |
| 445 messageScrollView_.reset([[NSScrollView alloc] initWithFrame:frameRect]); | |
| 446 [messageScrollView_ setHasVerticalScroller:YES]; | |
| 447 [messageScrollView_ setAutohidesScrollers:YES]; | |
| 448 | |
| 449 // Now the message is going into an NSScrollView, origin should be 0, 0. | |
| 450 frameRect = [messageText_ frame]; | |
| 451 frameRect.origin = NSMakePoint(0, 0); | |
| 452 [messageText_ setFrame:frameRect]; | |
| 453 | |
| 454 [messageScrollView_ setDocumentView:messageText_]; | |
| 455 [contentsView_ addSubview:messageScrollView_]; | |
| 456 } | |
| 239 [contentsView_ addSubview:[appsGridController_ view]]; | 457 [contentsView_ addSubview:[appsGridController_ view]]; |
| 240 [contentsView_ addSubview:pagerControl_]; | 458 [contentsView_ addSubview:pagerControl_]; |
| 241 [contentsView_ addSubview:loadingIndicator_]; | 459 [contentsView_ addSubview:loadingIndicator_]; |
| 242 [backgroundView_ addSubview:contentsView_]; | 460 [backgroundView_ addSubview:contentsView_]; |
| 243 [backgroundView_ addSubview:[appsSearchResultsController_ view]]; | 461 [backgroundView_ addSubview:[appsSearchResultsController_ view]]; |
| 244 [backgroundView_ addSubview:[appsSearchBoxController_ view]]; | 462 [backgroundView_ addSubview:[appsSearchBoxController_ view]]; |
| 245 [containerView addSubview:backgroundView_]; | 463 [containerView addSubview:backgroundView_]; |
| 246 [self setView:containerView]; | 464 [self setView:containerView]; |
| 247 } | 465 } |
| 248 | 466 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 if (delegate_) { | 579 if (delegate_) { |
| 362 delegate_->OpenSearchResult( | 580 delegate_->OpenSearchResult( |
| 363 result, false /* auto_launch */, 0 /* event flags */); | 581 result, false /* auto_launch */, 0 /* event flags */); |
| 364 } | 582 } |
| 365 } | 583 } |
| 366 | 584 |
| 367 - (void)onProfilesChanged { | 585 - (void)onProfilesChanged { |
| 368 [appsSearchBoxController_ rebuildMenu]; | 586 [appsSearchBoxController_ rebuildMenu]; |
| 369 } | 587 } |
| 370 | 588 |
| 589 // NSTextViewDelegate implementation. | |
| 590 | |
| 591 - (BOOL)textView:(NSTextView*)textView | |
| 592 clickedOnLink:(id)link | |
| 593 atIndex:(NSUInteger)charIndex { | |
| 594 DCHECK(delegate_); | |
| 595 delegate_->OpenLearnMoreLink(); | |
| 596 return YES; | |
| 597 } | |
| 598 | |
| 599 - (NSArray*)textView:(NSTextView*)aTextView | |
| 600 willChangeSelectionFromCharacterRanges:(NSArray*)oldSelectedCharRanges | |
| 601 toCharacterRanges:(NSArray*)newSelectedCharRanges { | |
| 602 return oldSelectedCharRanges; | |
| 603 } | |
| 604 | |
| 371 @end | 605 @end |
| OLD | NEW |