| 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 |