Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/ui/cocoa/download/download_shelf_controller.h" | 5 #import "chrome/browser/ui/cocoa/download/download_shelf_controller.h" |
| 6 | 6 |
| 7 #include "base/mac/bundle_locations.h" | 7 #include "base/mac/bundle_locations.h" |
| 8 #include "base/mac/mac_util.h" | 8 #include "base/mac/mac_util.h" |
| 9 #include "base/sys_string_conversions.h" | 9 #include "base/sys_string_conversions.h" |
| 10 #include "chrome/browser/download/download_util.h" | 10 #include "chrome/browser/download/download_util.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 // Amount of time between when the mouse is moved off the shelf and the shelf is | 64 // Amount of time between when the mouse is moved off the shelf and the shelf is |
| 65 // autoclosed, in seconds. | 65 // autoclosed, in seconds. |
| 66 const NSTimeInterval kAutoCloseDelaySeconds = 5; | 66 const NSTimeInterval kAutoCloseDelaySeconds = 5; |
| 67 | 67 |
| 68 // The size of the x button by default. | 68 // The size of the x button by default. |
| 69 const NSSize kHoverCloseButtonDefaultSize = { 18, 18 }; | 69 const NSSize kHoverCloseButtonDefaultSize = { 18, 18 }; |
| 70 | 70 |
| 71 } // namespace | 71 } // namespace |
| 72 | 72 |
| 73 @interface DownloadShelfController(Private) | 73 @interface DownloadShelfController(Private) |
| 74 - (void)showDownloadShelf:(BOOL)enable; | 74 - (void)viewFrameDidChange:(NSNotification*)notification; |
| 75 - (void)layoutItems:(BOOL)skipFirst; | 75 - (void)layoutItems:(BOOL)skipFirst; |
| 76 - (void)closed; | 76 - (void)closed; |
| 77 - (BOOL)canAutoClose; | 77 - (void)maybeAutoCloseAfterDelay; |
| 78 | 78 - (void)autoClose; |
| 79 - (void)viewFrameDidChange:(NSNotification*)notification; | |
| 80 | |
| 81 - (void)installTrackingArea; | 79 - (void)installTrackingArea; |
| 82 - (void)cancelAutoCloseAndRemoveTrackingArea; | 80 - (void)cancelAutoCloseAndRemoveTrackingArea; |
| 83 | |
| 84 - (void)willEnterFullscreen; | 81 - (void)willEnterFullscreen; |
| 85 - (void)willLeaveFullscreen; | 82 - (void)willLeaveFullscreen; |
| 86 - (void)updateCloseButton; | 83 - (void)updateCloseButton; |
| 87 @end | 84 @end |
| 88 | 85 |
| 89 | 86 |
| 90 @implementation DownloadShelfController | 87 @implementation DownloadShelfController |
| 91 | 88 |
| 92 - (id)initWithBrowser:(Browser*)browser | 89 - (id)initWithBrowser:(Browser*)browser |
| 93 resizeDelegate:(id<ViewResizer>)resizeDelegate { | 90 resizeDelegate:(id<ViewResizer>)resizeDelegate { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 | 140 |
| 144 - (void)dealloc { | 141 - (void)dealloc { |
| 145 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 142 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 146 [self cancelAutoCloseAndRemoveTrackingArea]; | 143 [self cancelAutoCloseAndRemoveTrackingArea]; |
| 147 | 144 |
| 148 // The controllers will unregister themselves as observers when they are | 145 // The controllers will unregister themselves as observers when they are |
| 149 // deallocated. No need to do that here. | 146 // deallocated. No need to do that here. |
| 150 [super dealloc]; | 147 [super dealloc]; |
| 151 } | 148 } |
| 152 | 149 |
| 153 // Called after the frame's rect has changed; usually when the height is | 150 - (IBAction)showDownloadsTab:(id)sender { |
| 154 // animated. | |
| 155 - (void)viewFrameDidChange:(NSNotification*)notification { | |
|
asanka
2013/03/22 20:11:01
Methods were re-ordered to match declaration order
Nico
2013/03/22 20:24:11
Can you land that part as a separate CL? That woul
asanka
2013/03/22 21:22:13
I undid the re-ordering. I see the point about mes
| |
| 156 // Anchor subviews at the top of |view|, so that it looks like the shelf | |
| 157 // is sliding out. | |
| 158 CGFloat newShelfHeight = NSHeight([[self view] frame]); | |
| 159 if (newShelfHeight == currentShelfHeight_) | |
| 160 return; | |
| 161 | |
| 162 for (NSView* view in [[self view] subviews]) { | |
| 163 NSRect frame = [view frame]; | |
| 164 frame.origin.y -= currentShelfHeight_ - newShelfHeight; | |
| 165 [view setFrame:frame]; | |
| 166 } | |
| 167 currentShelfHeight_ = newShelfHeight; | |
| 168 } | |
| 169 | |
| 170 - (AnimatableView*)animatableView { | |
| 171 return static_cast<AnimatableView*>([self view]); | |
| 172 } | |
| 173 | |
| 174 - (void)showDownloadsTab:(id)sender { | |
| 175 chrome::ShowDownloads(bridge_->browser()); | 151 chrome::ShowDownloads(bridge_->browser()); |
| 176 } | 152 } |
| 177 | 153 |
| 178 - (void)remove:(DownloadItemController*)download { | 154 - (IBAction)handleClose:(id)sender { |
| 179 // Look for the download in our controller array and remove it. This will | 155 bridge_->Close(DownloadShelf::USER_ACTION); |
| 180 // explicity release it so that it removes itself as an Observer of the | |
| 181 // DownloadItem. We don't want to wait for autorelease since the DownloadItem | |
| 182 // we are observing will likely be gone by then. | |
| 183 [[NSNotificationCenter defaultCenter] removeObserver:download]; | |
| 184 | |
| 185 // TODO(dmaclach): Remove -- http://crbug.com/25845 | |
| 186 [[download view] removeFromSuperview]; | |
| 187 | |
| 188 [downloadItemControllers_ removeObject:download]; | |
| 189 | |
| 190 [self layoutItems]; | |
| 191 | |
| 192 // Check to see if we have any downloads remaining and if not, hide the shelf. | |
| 193 if (![downloadItemControllers_ count]) | |
| 194 [self showDownloadShelf:NO]; | |
| 195 } | 156 } |
| 196 | 157 |
| 197 - (void)downloadWasOpened:(DownloadItemController*)item_controller { | 158 - (void)showDownloadShelf:(BOOL)show |
| 198 // This should only be called on the main thead. | 159 isUserAction:(BOOL)isUserAction { |
| 199 DCHECK([NSThread isMainThread]); | 160 if ([self isVisible] == show) |
| 200 | |
| 201 if ([self canAutoClose]) | |
| 202 [self installTrackingArea]; | |
| 203 } | |
| 204 | |
| 205 // We need to explicitly release our download controllers here since they need | |
| 206 // to remove themselves as observers before the remaining shutdown happens. | |
| 207 - (void)exiting { | |
| 208 [[self animatableView] stopAnimation]; | |
| 209 [self cancelAutoCloseAndRemoveTrackingArea]; | |
| 210 downloadItemControllers_.reset(); | |
| 211 } | |
| 212 | |
| 213 // Show or hide the bar based on the value of |enable|. Handles animating the | |
| 214 // resize of the content view. | |
| 215 - (void)showDownloadShelf:(BOOL)enable { | |
| 216 if ([self isVisible] == enable) | |
| 217 return; | 161 return; |
| 218 | 162 |
| 163 if (!show) { | |
| 164 [self cancelAutoCloseAndRemoveTrackingArea]; | |
| 165 int numInProgress = 0; | |
| 166 for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) { | |
| 167 if ([[downloadItemControllers_ objectAtIndex:i]download]->IsInProgress()) | |
| 168 ++numInProgress; | |
| 169 } | |
| 170 download_util::RecordShelfClose( | |
| 171 [downloadItemControllers_ count], numInProgress, !isUserAction); | |
| 172 } | |
| 219 // Animate the shelf out, but not in. | 173 // Animate the shelf out, but not in. |
| 220 // TODO(rohitrao): We do not animate on the way in because Cocoa is already | 174 // TODO(rohitrao): We do not animate on the way in because Cocoa is already |
| 221 // doing a lot of work to set up the download arrow animation. I've chosen to | 175 // doing a lot of work to set up the download arrow animation. I've chosen to |
| 222 // do no animation over janky animation. Find a way to make animating in | 176 // do no animation over janky animation. Find a way to make animating in |
| 223 // smoother. | 177 // smoother. |
| 224 AnimatableView* view = [self animatableView]; | 178 AnimatableView* view = [self animatableView]; |
| 225 if (enable) | 179 if (show) |
| 226 [view setHeight:maxShelfHeight_]; | 180 [view setHeight:maxShelfHeight_]; |
| 227 else | 181 else |
| 228 [view animateToNewHeight:0 duration:kDownloadShelfCloseDuration]; | 182 [view animateToNewHeight:0 duration:kDownloadShelfCloseDuration]; |
| 229 | 183 |
| 230 barIsVisible_ = enable; | 184 barIsVisible_ = show; |
| 231 [self updateCloseButton]; | 185 [self updateCloseButton]; |
| 232 } | 186 } |
| 233 | 187 |
| 234 - (DownloadShelf*)bridge { | |
| 235 return bridge_.get(); | |
| 236 } | |
| 237 | |
| 238 - (BOOL)isVisible { | |
| 239 return barIsVisible_; | |
| 240 } | |
| 241 | |
| 242 - (void)show:(id)sender { | |
| 243 [self showDownloadShelf:YES]; | |
| 244 } | |
| 245 | |
| 246 - (void)hide:(id)sender { | |
| 247 [self cancelAutoCloseAndRemoveTrackingArea]; | |
| 248 | |
| 249 // If |sender| isn't nil, then we're being closed from the UI by the user and | |
| 250 // we need to tell our shelf implementation to close. Otherwise, we're being | |
| 251 // closed programmatically by our shelf implementation. | |
| 252 bool auto_closed = (sender == nil); | |
| 253 | |
| 254 int numInProgress = 0; | |
| 255 for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) { | |
| 256 if ([[downloadItemControllers_ objectAtIndex:i]download]->IsInProgress()) | |
| 257 ++numInProgress; | |
| 258 } | |
| 259 download_util::RecordShelfClose( | |
| 260 [downloadItemControllers_ count], numInProgress, auto_closed); | |
| 261 if (auto_closed) | |
| 262 [self showDownloadShelf:NO]; | |
| 263 else | |
| 264 bridge_->Close(); | |
| 265 } | |
| 266 | |
| 267 - (void)animationDidEnd:(NSAnimation*)animation { | |
| 268 if (![self isVisible]) | |
| 269 [self closed]; | |
| 270 } | |
| 271 | |
| 272 - (float)height { | |
| 273 return maxShelfHeight_; | |
| 274 } | |
| 275 | |
| 276 // If |skipFirst| is true, the frame of the leftmost item is not set. | |
| 277 - (void)layoutItems:(BOOL)skipFirst { | |
| 278 CGFloat currentX = 0; | |
| 279 for (DownloadItemController* itemController | |
| 280 in downloadItemControllers_.get()) { | |
| 281 NSRect frame = [[itemController view] frame]; | |
| 282 frame.origin.x = currentX; | |
| 283 frame.size.width = [itemController preferredSize].width; | |
| 284 if (!skipFirst) | |
| 285 [[[itemController view] animator] setFrame:frame]; | |
| 286 currentX += frame.size.width + kDownloadItemPadding; | |
| 287 skipFirst = NO; | |
| 288 } | |
| 289 } | |
| 290 | |
| 291 - (void)layoutItems { | 188 - (void)layoutItems { |
| 292 [self layoutItems:NO]; | 189 [self layoutItems:NO]; |
| 293 } | 190 } |
| 294 | 191 |
| 295 - (void)addDownloadItem:(DownloadItem*)downloadItem { | 192 - (void)addDownloadItem:(DownloadItem*)downloadItem { |
| 296 DCHECK([NSThread isMainThread]); | 193 DCHECK([NSThread isMainThread]); |
| 297 [self cancelAutoCloseAndRemoveTrackingArea]; | 194 [self cancelAutoCloseAndRemoveTrackingArea]; |
| 298 | 195 |
| 299 // Insert new item at the left. | 196 // Insert new item at the left. |
| 300 scoped_nsobject<DownloadItemController> controller( | 197 scoped_nsobject<DownloadItemController> controller( |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 // there's no point in animating the removal. | 240 // there's no point in animating the removal. |
| 344 [self remove:[downloadItemControllers_ lastObject]]; | 241 [self remove:[downloadItemControllers_ lastObject]]; |
| 345 } | 242 } |
| 346 | 243 |
| 347 // Finally, move the remaining items to the right. Skip the first item when | 244 // Finally, move the remaining items to the right. Skip the first item when |
| 348 // laying out the items, so that the longer animation duration we set up above | 245 // laying out the items, so that the longer animation duration we set up above |
| 349 // is not overwritten. | 246 // is not overwritten. |
| 350 [self layoutItems:YES]; | 247 [self layoutItems:YES]; |
| 351 } | 248 } |
| 352 | 249 |
| 250 - (void)remove:(DownloadItemController*)download { | |
| 251 // Look for the download in our controller array and remove it. This will | |
| 252 // explicity release it so that it removes itself as an Observer of the | |
| 253 // DownloadItem. We don't want to wait for autorelease since the DownloadItem | |
| 254 // we are observing will likely be gone by then. | |
| 255 [[NSNotificationCenter defaultCenter] removeObserver:download]; | |
| 256 | |
| 257 // TODO(dmaclach): Remove -- http://crbug.com/25845 | |
| 258 [[download view] removeFromSuperview]; | |
| 259 | |
| 260 [downloadItemControllers_ removeObject:download]; | |
| 261 [self layoutItems]; | |
| 262 | |
| 263 // If there are no more downloads or if all the remaining downloads have been | |
| 264 // opened, we can close the shelf. | |
| 265 [self maybeAutoCloseAfterDelay]; | |
| 266 } | |
| 267 | |
| 268 - (void)downloadWasOpened:(DownloadItemController*)item_controller { | |
| 269 // This should only be called on the main thead. | |
| 270 DCHECK([NSThread isMainThread]); | |
| 271 [self maybeAutoCloseAfterDelay]; | |
| 272 } | |
| 273 | |
| 274 // We need to explicitly release our download controllers here since they need | |
| 275 // to remove themselves as observers before the remaining shutdown happens. | |
| 276 - (void)exiting { | |
| 277 [[self animatableView] stopAnimation]; | |
| 278 [self cancelAutoCloseAndRemoveTrackingArea]; | |
| 279 downloadItemControllers_.reset(); | |
| 280 } | |
| 281 | |
| 282 - (AnimatableView*)animatableView { | |
| 283 return static_cast<AnimatableView*>([self view]); | |
| 284 } | |
| 285 | |
| 286 - (DownloadShelf*)bridge { | |
| 287 return bridge_.get(); | |
| 288 } | |
| 289 | |
| 290 - (BOOL)isVisible { | |
| 291 return barIsVisible_; | |
| 292 } | |
| 293 | |
| 294 - (float)height { | |
| 295 return maxShelfHeight_; | |
| 296 } | |
| 297 | |
| 298 // Called after the frame's rect has changed; usually when the height is | |
| 299 // animated. | |
| 300 - (void)viewFrameDidChange:(NSNotification*)notification { | |
| 301 // Anchor subviews at the top of |view|, so that it looks like the shelf | |
| 302 // is sliding out. | |
| 303 CGFloat newShelfHeight = NSHeight([[self view] frame]); | |
| 304 if (newShelfHeight == currentShelfHeight_) | |
| 305 return; | |
| 306 | |
| 307 for (NSView* view in [[self view] subviews]) { | |
| 308 NSRect frame = [view frame]; | |
| 309 frame.origin.y -= currentShelfHeight_ - newShelfHeight; | |
| 310 [view setFrame:frame]; | |
| 311 } | |
| 312 currentShelfHeight_ = newShelfHeight; | |
| 313 } | |
| 314 | |
| 315 - (void)animationDidEnd:(NSAnimation*)animation { | |
| 316 if (![self isVisible]) | |
| 317 [self closed]; | |
| 318 } | |
| 319 | |
| 320 // If |skipFirst| is true, the frame of the leftmost item is not set. | |
| 321 - (void)layoutItems:(BOOL)skipFirst { | |
| 322 CGFloat currentX = 0; | |
| 323 for (DownloadItemController* itemController | |
| 324 in downloadItemControllers_.get()) { | |
| 325 NSRect frame = [[itemController view] frame]; | |
| 326 frame.origin.x = currentX; | |
| 327 frame.size.width = [itemController preferredSize].width; | |
| 328 if (!skipFirst) | |
| 329 [[[itemController view] animator] setFrame:frame]; | |
| 330 currentX += frame.size.width + kDownloadItemPadding; | |
| 331 skipFirst = NO; | |
| 332 } | |
| 333 } | |
| 334 | |
| 353 - (void)closed { | 335 - (void)closed { |
| 354 // Don't remove completed downloads if the shelf is just being auto-hidden | 336 // Don't remove completed downloads if the shelf is just being auto-hidden |
| 355 // rather than explicitly closed by the user. | 337 // rather than explicitly closed by the user. |
| 356 if (bridge_->is_hidden()) | 338 if (bridge_->is_hidden()) |
| 357 return; | 339 return; |
| 358 NSUInteger i = 0; | 340 NSUInteger i = 0; |
| 359 while (i < [downloadItemControllers_ count]) { | 341 while (i < [downloadItemControllers_ count]) { |
| 360 DownloadItemController* itemController = | 342 DownloadItemController* itemController = |
| 361 [downloadItemControllers_ objectAtIndex:i]; | 343 [downloadItemControllers_ objectAtIndex:i]; |
| 362 DownloadItem* download = [itemController download]; | 344 DownloadItem* download = [itemController download]; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 376 | 358 |
| 377 - (void)mouseEntered:(NSEvent*)event { | 359 - (void)mouseEntered:(NSEvent*)event { |
| 378 // If the mouse re-enters the download shelf, cancel the auto-close. Further | 360 // If the mouse re-enters the download shelf, cancel the auto-close. Further |
| 379 // mouse exits should not trigger autoclose, so also remove the tracking area. | 361 // mouse exits should not trigger autoclose, so also remove the tracking area. |
| 380 [self cancelAutoCloseAndRemoveTrackingArea]; | 362 [self cancelAutoCloseAndRemoveTrackingArea]; |
| 381 } | 363 } |
| 382 | 364 |
| 383 - (void)mouseExited:(NSEvent*)event { | 365 - (void)mouseExited:(NSEvent*)event { |
| 384 // Cancel any previous hide requests, just to be safe. | 366 // Cancel any previous hide requests, just to be safe. |
| 385 [NSObject cancelPreviousPerformRequestsWithTarget:self | 367 [NSObject cancelPreviousPerformRequestsWithTarget:self |
| 386 selector:@selector(hide:) | 368 selector:@selector(autoClose) |
| 387 object:self]; | 369 object:nil]; |
| 388 | 370 |
| 389 // Schedule an autoclose after a delay. If the mouse is moved back into the | 371 // Schedule an autoclose after a delay. If the mouse is moved back into the |
| 390 // view, or if an item is added to the shelf, the timer will be canceled. | 372 // view, or if an item is added to the shelf, the timer will be canceled. |
| 391 [self performSelector:@selector(hide:) | 373 [self performSelector:@selector(autoClose) |
| 392 withObject:self | 374 withObject:nil |
| 393 afterDelay:kAutoCloseDelaySeconds]; | 375 afterDelay:kAutoCloseDelaySeconds]; |
| 394 } | 376 } |
| 395 | 377 |
| 396 - (BOOL)canAutoClose { | 378 - (void)maybeAutoCloseAfterDelay { |
| 379 // We can close the shelf automatically if all the downloads on the shelf have | |
| 380 // been opened. | |
| 397 for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) { | 381 for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) { |
| 398 DownloadItemController* itemController = | 382 DownloadItemController* itemController = |
| 399 [downloadItemControllers_ objectAtIndex:i]; | 383 [downloadItemControllers_ objectAtIndex:i]; |
| 400 if (![itemController download]->GetOpened()) | 384 if (![itemController download]->GetOpened()) |
| 401 return NO; | 385 return; |
| 402 } | 386 } |
| 403 return YES; | 387 |
| 388 if ([self isVisible] && [downloadItemControllers_ count] > 0) { | |
| 389 // If the shelf is visible and has download items remaining on it, close the | |
| 390 // shelf after the user moves the mouse out of the download shelf. | |
| 391 [self installTrackingArea]; | |
| 392 } else { | |
| 393 // We notify the DownloadShelf of our intention to close even if the shelf | |
| 394 // is currently hidden. If the shelf was temporarily hidden (e.g. because | |
| 395 // the browser window entered fullscreen mode), then this prevents the shelf | |
| 396 // from being shown again when the browser exits fullscreen mode. | |
| 397 [self autoClose]; | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 - (void)autoClose { | |
| 402 bridge_->Close(DownloadShelf::AUTOMATIC); | |
| 404 } | 403 } |
| 405 | 404 |
| 406 - (void)installTrackingArea { | 405 - (void)installTrackingArea { |
| 407 // Install the tracking area to listen for mouseExited messages and trigger | 406 // Install the tracking area to listen for mouseExited messages and trigger |
| 408 // the shelf autoclose. | 407 // the shelf autoclose. |
| 409 if (trackingArea_.get()) | 408 if (trackingArea_.get()) |
| 410 return; | 409 return; |
| 411 | 410 |
| 412 trackingArea_.reset([[NSTrackingArea alloc] | 411 trackingArea_.reset([[NSTrackingArea alloc] |
| 413 initWithRect:[[self view] bounds] | 412 initWithRect:[[self view] bounds] |
| 414 options:NSTrackingMouseEnteredAndExited | | 413 options:NSTrackingMouseEnteredAndExited | |
| 415 NSTrackingActiveAlways | 414 NSTrackingActiveAlways |
| 416 owner:self | 415 owner:self |
| 417 userInfo:nil]); | 416 userInfo:nil]); |
| 418 [[self view] addTrackingArea:trackingArea_]; | 417 [[self view] addTrackingArea:trackingArea_]; |
| 419 } | 418 } |
| 420 | 419 |
| 421 - (void)cancelAutoCloseAndRemoveTrackingArea { | 420 - (void)cancelAutoCloseAndRemoveTrackingArea { |
| 422 [NSObject cancelPreviousPerformRequestsWithTarget:self | 421 [NSObject cancelPreviousPerformRequestsWithTarget:self |
| 423 selector:@selector(hide:) | 422 selector:@selector(autoClose) |
| 424 object:self]; | 423 object:nil]; |
| 425 | 424 |
| 426 if (trackingArea_.get()) { | 425 if (trackingArea_.get()) { |
| 427 [[self view] removeTrackingArea:trackingArea_]; | 426 [[self view] removeTrackingArea:trackingArea_]; |
| 428 trackingArea_.reset(nil); | 427 trackingArea_.reset(nil); |
| 429 } | 428 } |
| 430 } | 429 } |
| 431 | 430 |
| 432 - (void)willEnterFullscreen { | 431 - (void)willEnterFullscreen { |
| 433 isFullscreen_ = YES; | 432 isFullscreen_ = YES; |
| 434 [self updateCloseButton]; | 433 [self updateCloseButton]; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 459 } | 458 } |
| 460 | 459 |
| 461 // Set the tracking off to create a new tracking area for the control. | 460 // Set the tracking off to create a new tracking area for the control. |
| 462 // When changing the bounds/frame on a HoverButton, the tracking isn't updated | 461 // When changing the bounds/frame on a HoverButton, the tracking isn't updated |
| 463 // correctly, it needs to be turned off and back on. | 462 // correctly, it needs to be turned off and back on. |
| 464 [hoverCloseButton_ setTrackingEnabled:NO]; | 463 [hoverCloseButton_ setTrackingEnabled:NO]; |
| 465 [hoverCloseButton_ setFrame:bounds]; | 464 [hoverCloseButton_ setFrame:bounds]; |
| 466 [hoverCloseButton_ setTrackingEnabled:YES]; | 465 [hoverCloseButton_ setTrackingEnabled:YES]; |
| 467 } | 466 } |
| 468 @end | 467 @end |
| OLD | NEW |