| 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 #include "chrome/browser/ui/cocoa/gradient_button_cell.h" | 5 #include "chrome/browser/ui/cocoa/gradient_button_cell.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #import "base/mac/scoped_nsobject.h" | 10 #import "base/mac/scoped_nsobject.h" |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 YES : NO; | 199 YES : NO; |
| 200 } | 200 } |
| 201 | 201 |
| 202 #if 1 | 202 #if 1 |
| 203 // If we are not continuously pulsing, perform a pulse animation to | 203 // If we are not continuously pulsing, perform a pulse animation to |
| 204 // reflect our new state. | 204 // reflect our new state. |
| 205 - (void)setMouseInside:(BOOL)flag animate:(BOOL)animated { | 205 - (void)setMouseInside:(BOOL)flag animate:(BOOL)animated { |
| 206 isMouseInside_ = flag; | 206 isMouseInside_ = flag; |
| 207 if (pulseState_ != gradient_button_cell::kPulsingContinuous) { | 207 if (pulseState_ != gradient_button_cell::kPulsingContinuous) { |
| 208 if (animated) { | 208 if (animated) { |
| 209 // In Material Design, if the button is already fully on, don't pulse it |
| 210 // on again if the mouse is within its bounds. |
| 211 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback && |
| 212 isMouseInside_ && pulseState_ == gradient_button_cell::kPulsedOn) { |
| 213 return; |
| 214 } |
| 215 |
| 209 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsingOn : | 216 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsingOn : |
| 210 gradient_button_cell::kPulsingOff)]; | 217 gradient_button_cell::kPulsingOff)]; |
| 211 } else { | 218 } else { |
| 212 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsedOn : | 219 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsedOn : |
| 213 gradient_button_cell::kPulsedOff)]; | 220 gradient_button_cell::kPulsedOff)]; |
| 214 } | 221 } |
| 215 } | 222 } |
| 216 } | 223 } |
| 217 #else | 224 #else |
| 218 | 225 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 } | 319 } |
| 313 | 320 |
| 314 - (void)mouseExited:(NSEvent*)theEvent { | 321 - (void)mouseExited:(NSEvent*)theEvent { |
| 315 [self setMouseInside:NO animate:YES]; | 322 [self setMouseInside:NO animate:YES]; |
| 316 } | 323 } |
| 317 | 324 |
| 318 - (BOOL)isMouseInside { | 325 - (BOOL)isMouseInside { |
| 319 return trackingArea_ && isMouseInside_; | 326 return trackingArea_ && isMouseInside_; |
| 320 } | 327 } |
| 321 | 328 |
| 329 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView { |
| 330 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback) { |
| 331 // The user has just clicked down in the button. In Material Design, set the |
| 332 // pulsed (hover) state to off now so that if the user keeps the mouse held |
| 333 // down while dragging it out of the button's bounds, the button will draw |
| 334 // itself in its normal state. This is unrelated to dragging the button |
| 335 // in the button bar, which takes a different path through the code. |
| 336 [self setPulseState:gradient_button_cell::kPulsedOff]; |
| 337 } |
| 338 |
| 339 return [super startTrackingAt:startPoint inView:controlView]; |
| 340 } |
| 341 |
| 322 // Since we have our own drawWithFrame:, we need to also have our own | 342 // Since we have our own drawWithFrame:, we need to also have our own |
| 323 // logic for determining when the mouse is inside for honoring this | 343 // logic for determining when the mouse is inside for honoring this |
| 324 // request. | 344 // request. |
| 325 - (void)setShowsBorderOnlyWhileMouseInside:(BOOL)showOnly { | 345 - (void)setShowsBorderOnlyWhileMouseInside:(BOOL)showOnly { |
| 326 [super setShowsBorderOnlyWhileMouseInside:showOnly]; | 346 [super setShowsBorderOnlyWhileMouseInside:showOnly]; |
| 327 if (showOnly) { | 347 if (showOnly) { |
| 328 [self updateTrackingAreas]; | 348 [self updateTrackingAreas]; |
| 329 } else { | 349 } else { |
| 330 if (trackingArea_) { | 350 if (trackingArea_) { |
| 331 [[self controlView] removeTrackingArea:trackingArea_]; | 351 [[self controlView] removeTrackingArea:trackingArea_]; |
| 332 trackingArea_.reset(nil); | 352 trackingArea_.reset(nil); |
| 333 if (isMouseInside_) { | 353 if (isMouseInside_) { |
| 334 isMouseInside_ = NO; | 354 isMouseInside_ = NO; |
| 335 [[self controlView] setNeedsDisplay:YES]; | 355 [[self controlView] setNeedsDisplay:YES]; |
| 336 } | 356 } |
| 337 } | 357 } |
| 338 } | 358 } |
| 339 } | 359 } |
| 340 | 360 |
| 341 // TODO(viettrungluu): clean up/reorganize. | 361 // TODO(viettrungluu): clean up/reorganize. |
| 342 - (void)drawBorderAndFillForTheme:(const ui::ThemeProvider*)themeProvider | 362 - (void)drawBorderAndFillForTheme:(const ui::ThemeProvider*)themeProvider |
| 343 controlView:(NSView*)controlView | 363 controlView:(NSView*)controlView |
| 344 innerPath:(NSBezierPath*)innerPath | 364 innerPath:(NSBezierPath*)innerPath |
| 345 showClickedGradient:(BOOL)showClickedGradient | 365 showClickedGradient:(BOOL)showClickedGradient |
| 346 showHighlightGradient:(BOOL)showHighlightGradient | 366 showHighlightGradient:(BOOL)showHighlightGradient |
| 347 hoverAlpha:(CGFloat)hoverAlpha | 367 hoverAlpha:(CGFloat)hoverAlpha |
| 348 active:(BOOL)active | 368 active:(BOOL)active |
| 349 cellFrame:(NSRect)cellFrame | 369 cellFrame:(NSRect)cellFrame |
| 350 defaultGradient:(NSGradient*)defaultGradient { | 370 defaultGradient:(NSGradient*)defaultGradient { |
| 371 // For Material Design, draw a solid rounded rect behind the button, based on |
| 372 // the hover and pressed states. |
| 373 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback) { |
| 374 const CGFloat kEightPercentAlpha = 0.08; |
| 375 const CGFloat kFourPercentAlpha = 0.04; |
| 376 |
| 377 // The alpha is always at least 8%. Default the color to black. |
| 378 CGFloat alpha = kEightPercentAlpha; |
| 379 CGFloat color = 0.0; |
| 380 // If a dark theme, incrase the opacity slightly and use white. |
| 381 if ([[controlView window] hasDarkTheme]) { |
| 382 alpha += kFourPercentAlpha; |
| 383 color = 1.0; |
| 384 } |
| 385 // If clicked or highlighted, the background is slightly more opaque. If not |
| 386 // clicked or highlighted, adjust the alpha by the animation fade in |
| 387 // percentage. |
| 388 if (showClickedGradient || showHighlightGradient) { |
| 389 alpha += kFourPercentAlpha; |
| 390 } else { |
| 391 alpha *= hoverAlpha; |
| 392 } |
| 393 |
| 394 // Fill the path. |
| 395 [[NSColor colorWithCalibratedWhite:color alpha:alpha] set]; |
| 396 [innerPath fill]; |
| 397 return; |
| 398 } |
| 399 |
| 351 BOOL isFlatButton = [self showsBorderOnlyWhileMouseInside]; | 400 BOOL isFlatButton = [self showsBorderOnlyWhileMouseInside]; |
| 352 | 401 |
| 353 // For flat (unbordered when not hovered) buttons, never use the toolbar | 402 // For flat (unbordered when not hovered) buttons, never use the toolbar |
| 354 // button background image, but the modest gradient used for themed buttons. | 403 // button background image, but the modest gradient used for themed buttons. |
| 355 // To make things even more modest, scale the hover alpha down by 40 percent | 404 // To make things even more modest, scale the hover alpha down by 40 percent |
| 356 // unless clicked. | 405 // unless clicked. |
| 357 NSColor* backgroundImageColor; | 406 NSColor* backgroundImageColor; |
| 358 BOOL useThemeGradient; | 407 BOOL useThemeGradient; |
| 359 if (isFlatButton) { | 408 if (isFlatButton) { |
| 360 backgroundImageColor = nil; | 409 backgroundImageColor = nil; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 [innerPath stroke]; | 503 [innerPath stroke]; |
| 455 } | 504 } |
| 456 | 505 |
| 457 // TODO(viettrungluu): clean this up. | 506 // TODO(viettrungluu): clean this up. |
| 458 // (Private) | 507 // (Private) |
| 459 - (void)getDrawParamsForFrame:(NSRect)cellFrame | 508 - (void)getDrawParamsForFrame:(NSRect)cellFrame |
| 460 inView:(NSView*)controlView | 509 inView:(NSView*)controlView |
| 461 innerFrame:(NSRect*)returnInnerFrame | 510 innerFrame:(NSRect*)returnInnerFrame |
| 462 innerPath:(NSBezierPath**)returnInnerPath | 511 innerPath:(NSBezierPath**)returnInnerPath |
| 463 clipPath:(NSBezierPath**)returnClipPath { | 512 clipPath:(NSBezierPath**)returnClipPath { |
| 464 const CGFloat lineWidth = [controlView cr_lineWidth]; | 513 const CGFloat kLineWidth = [controlView cr_lineWidth]; |
| 465 const CGFloat halfLineWidth = lineWidth / 2.0; | 514 const CGFloat kHalfLineWidth = kLineWidth / 2.0; |
| 466 | 515 |
| 467 // Constants from Cole. Will kConstant them once the feedback loop | 516 NSRect drawFrame = cellFrame; |
| 468 // is complete. | 517 NSRect innerFrame = NSInsetRect(cellFrame, kLineWidth, kLineWidth); |
| 469 NSRect drawFrame = NSInsetRect(cellFrame, 1.5 * lineWidth, 1.5 * lineWidth); | 518 CGFloat cornerRadius = 2; |
| 470 NSRect innerFrame = NSInsetRect(cellFrame, lineWidth, lineWidth); | 519 if ([self tag] != kMaterialStandardButtonTypeWithLimitedClickFeedback) { |
| 471 const CGFloat radius = 3; | 520 drawFrame = NSInsetRect(cellFrame, 1.5 * kLineWidth, 1.5 * kLineWidth); |
| 521 cornerRadius = 3; |
| 522 } |
| 472 | 523 |
| 473 ButtonType type = [[(NSControl*)controlView cell] tag]; | 524 ButtonType type = [[(NSControl*)controlView cell] tag]; |
| 474 switch (type) { | 525 switch (type) { |
| 475 case kMiddleButtonType: | 526 case kMiddleButtonType: |
| 476 drawFrame.size.width += 20; | 527 drawFrame.size.width += 20; |
| 477 innerFrame.size.width += 2; | 528 innerFrame.size.width += 2; |
| 478 // Fallthrough | 529 // Fallthrough |
| 479 case kRightButtonType: | 530 case kRightButtonType: |
| 480 drawFrame.origin.x -= 20; | 531 drawFrame.origin.x -= 20; |
| 481 innerFrame.origin.x -= 2; | 532 innerFrame.origin.x -= 2; |
| 482 // Fallthrough | 533 // Fallthrough |
| 483 case kLeftButtonType: | 534 case kLeftButtonType: |
| 484 case kLeftButtonWithShadowType: | 535 case kLeftButtonWithShadowType: |
| 485 drawFrame.size.width += 20; | 536 drawFrame.size.width += 20; |
| 486 innerFrame.size.width += 2; | 537 innerFrame.size.width += 2; |
| 487 default: | 538 default: |
| 488 break; | 539 break; |
| 489 } | 540 } |
| 490 if (type == kLeftButtonWithShadowType) | 541 if (type == kLeftButtonWithShadowType) |
| 491 innerFrame.size.width -= 1.0; | 542 innerFrame.size.width -= 1.0; |
| 492 | 543 |
| 493 // Return results if |return...| not null. | 544 // Return results if |return...| not null. |
| 494 if (returnInnerFrame) | 545 if (returnInnerFrame) |
| 495 *returnInnerFrame = innerFrame; | 546 *returnInnerFrame = innerFrame; |
| 496 if (returnInnerPath) { | 547 if (returnInnerPath) { |
| 497 DCHECK(*returnInnerPath == nil); | 548 DCHECK(*returnInnerPath == nil); |
| 498 *returnInnerPath = [NSBezierPath bezierPathWithRoundedRect:drawFrame | 549 *returnInnerPath = [NSBezierPath bezierPathWithRoundedRect:drawFrame |
| 499 xRadius:radius | 550 xRadius:cornerRadius |
| 500 yRadius:radius]; | 551 yRadius:cornerRadius]; |
| 501 [*returnInnerPath setLineWidth:lineWidth]; | 552 [*returnInnerPath setLineWidth:kLineWidth]; |
| 502 } | 553 } |
| 503 if (returnClipPath) { | 554 if (returnClipPath) { |
| 504 DCHECK(*returnClipPath == nil); | 555 DCHECK(*returnClipPath == nil); |
| 505 NSRect clipPathRect = | 556 NSRect clipPathRect = |
| 506 NSInsetRect(drawFrame, -halfLineWidth, -halfLineWidth); | 557 NSInsetRect(drawFrame, -kHalfLineWidth, -kHalfLineWidth); |
| 507 *returnClipPath = [NSBezierPath | 558 *returnClipPath = [NSBezierPath |
| 508 bezierPathWithRoundedRect:clipPathRect | 559 bezierPathWithRoundedRect:clipPathRect |
| 509 xRadius:radius + halfLineWidth | 560 xRadius:cornerRadius + kHalfLineWidth |
| 510 yRadius:radius + halfLineWidth]; | 561 yRadius:cornerRadius + kHalfLineWidth]; |
| 511 } | 562 } |
| 512 } | 563 } |
| 513 | 564 |
| 514 // TODO(viettrungluu): clean this up. | 565 // TODO(viettrungluu): clean this up. |
| 515 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { | 566 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { |
| 516 NSRect innerFrame; | 567 NSRect innerFrame; |
| 517 NSBezierPath* innerPath = nil; | 568 NSBezierPath* innerPath = nil; |
| 518 [self getDrawParamsForFrame:cellFrame | 569 [self getDrawParamsForFrame:cellFrame |
| 519 inView:controlView | 570 inView:controlView |
| 520 innerFrame:&innerFrame | 571 innerFrame:&innerFrame |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE) : | 609 ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE) : |
| 559 [NSColor blackColor]; | 610 [NSColor blackColor]; |
| 560 | 611 |
| 561 [[stroke colorWithAlphaComponent:0.2] set]; | 612 [[stroke colorWithAlphaComponent:0.2] set]; |
| 562 NSRectFillUsingOperation(NSInsetRect(borderRect, 0, 2), | 613 NSRectFillUsingOperation(NSInsetRect(borderRect, 0, 2), |
| 563 NSCompositeSourceOver); | 614 NSCompositeSourceOver); |
| 564 } | 615 } |
| 565 [self drawInteriorWithFrame:innerFrame inView:controlView]; | 616 [self drawInteriorWithFrame:innerFrame inView:controlView]; |
| 566 } | 617 } |
| 567 | 618 |
| 619 - (CGFloat)textStartXOffset { |
| 620 // 11 is the magic number needed to make this match the native |
| 621 // NSButtonCell's label display. |
| 622 return [[self image] size].width + 11; |
| 623 } |
| 624 |
| 568 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { | 625 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { |
| 569 const CGFloat lineWidth = [controlView cr_lineWidth]; | 626 const CGFloat lineWidth = [controlView cr_lineWidth]; |
| 570 | 627 |
| 571 if (shouldTheme_) { | 628 if (shouldTheme_) { |
| 572 BOOL isTemplate = [[self image] isTemplate]; | 629 BOOL isTemplate = [[self image] isTemplate]; |
| 573 | 630 |
| 574 gfx::ScopedNSGraphicsContextSaveGState scopedGState; | 631 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
| 575 | 632 |
| 576 CGContextRef context = | 633 CGContextRef context = |
| 577 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); | 634 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 // get it to work with NSButtonCell. | 695 // get it to work with NSButtonCell. |
| 639 // TODO(jeremy): Move this to GTM. | 696 // TODO(jeremy): Move this to GTM. |
| 640 - (NSRect)drawTitle:(NSAttributedString*)title | 697 - (NSRect)drawTitle:(NSAttributedString*)title |
| 641 withFrame:(NSRect)cellFrame | 698 withFrame:(NSRect)cellFrame |
| 642 inView:(NSView*)controlView { | 699 inView:(NSView*)controlView { |
| 643 NSSize size = [title size]; | 700 NSSize size = [title size]; |
| 644 | 701 |
| 645 // Empirically, Cocoa will draw an extra 2 pixels past NSWidth(cellFrame) | 702 // Empirically, Cocoa will draw an extra 2 pixels past NSWidth(cellFrame) |
| 646 // before it clips the text. | 703 // before it clips the text. |
| 647 const CGFloat kOverflowBeforeClip = 2; | 704 const CGFloat kOverflowBeforeClip = 2; |
| 648 BOOL clipping = YES; | 705 BOOL isModeMaterial = |
| 706 [self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback; |
| 707 // For Material Design we don't want to clip the text. For all other button |
| 708 // cell modes, we do. |
| 709 BOOL shouldClipTheTitle = !isModeMaterial; |
| 649 if (std::floor(size.width) <= (NSWidth(cellFrame) + kOverflowBeforeClip)) { | 710 if (std::floor(size.width) <= (NSWidth(cellFrame) + kOverflowBeforeClip)) { |
| 650 cellFrame.origin.y += ([self verticalTextOffset] - 1); | 711 cellFrame.origin.y += ([self verticalTextOffset] - 1); |
| 651 clipping = NO; | 712 shouldClipTheTitle = NO; |
| 652 } | 713 } |
| 653 | 714 |
| 654 // Gradient is about twice our line height long. | 715 // Gradient is about twice our line height long. |
| 655 CGFloat gradientWidth = MIN(size.height * 2, NSWidth(cellFrame) / 4); | 716 CGFloat gradientWidth = MIN(size.height * 2, NSWidth(cellFrame) / 4); |
| 656 | 717 |
| 657 NSRect solidPart, gradientPart; | 718 NSRect solidPart, gradientPart; |
| 658 NSDivideRect(cellFrame, &gradientPart, &solidPart, gradientWidth, NSMaxXEdge); | 719 NSDivideRect(cellFrame, &gradientPart, &solidPart, gradientWidth, NSMaxXEdge); |
| 659 | 720 |
| 660 // Draw non-gradient part without transparency layer, as light text on a dark | 721 // Draw non-gradient part without transparency layer, as light text on a dark |
| 661 // background looks bad with a gradient layer. | 722 // background looks bad with a gradient layer. |
| 662 NSPoint textOffset = NSZeroPoint; | 723 NSPoint textOffset = NSZeroPoint; |
| 663 { | 724 { |
| 664 gfx::ScopedNSGraphicsContextSaveGState scopedGState; | 725 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
| 665 if (clipping) | 726 if (shouldClipTheTitle) |
| 666 [NSBezierPath clipRect:solidPart]; | 727 [NSBezierPath clipRect:solidPart]; |
| 667 | 728 |
| 668 // 11 is the magic number needed to make this match the native | 729 CGFloat textLeft = [self textStartXOffset]; |
| 669 // NSButtonCell's label display. | |
| 670 CGFloat textLeft = [[self image] size].width + 11; | |
| 671 | 730 |
| 672 // For some reason, the height of cellFrame as passed in is totally bogus. | 731 // For some reason, the height of cellFrame as passed in is totally bogus. |
| 673 // For vertical centering purposes, we need the bounds of the containing | 732 // For vertical centering purposes, we need the bounds of the containing |
| 674 // view. | 733 // view. |
| 675 NSRect buttonFrame = [[self controlView] frame]; | 734 NSRect buttonFrame = [[self controlView] frame]; |
| 676 | 735 |
| 677 // Call the vertical offset to match native NSButtonCell's version. | 736 // Call the vertical offset to match native NSButtonCell's version. |
| 678 textOffset = NSMakePoint(textLeft, | 737 textOffset = NSMakePoint(textLeft, |
| 679 (NSHeight(buttonFrame) - size.height) / 2 + | 738 (NSHeight(buttonFrame) - size.height) / 2 + |
| 680 [self verticalTextOffset]); | 739 [self verticalTextOffset]); |
| 681 [title drawAtPoint:textOffset]; | 740 // WIth Material Design we want an ellipsis if the title is too long to fit, |
| 741 // so have to use drawInRect: instead of drawAtPoint:. |
| 742 if (isModeMaterial) { |
| 743 NSRect textBounds = NSMakeRect(textOffset.x, |
| 744 textOffset.y, |
| 745 NSWidth(buttonFrame) - textOffset.x, |
| 746 NSHeight(buttonFrame)); |
| 747 [title drawInRect:textBounds]; |
| 748 } else { |
| 749 [title drawAtPoint:textOffset]; |
| 750 } |
| 682 } | 751 } |
| 683 | 752 |
| 684 if (!clipping) | 753 if (!shouldClipTheTitle) |
| 685 return cellFrame; | 754 return cellFrame; |
| 686 | 755 |
| 687 // Draw the gradient part with a transparency layer. This makes the text look | 756 // Draw the gradient part with a transparency layer. This makes the text look |
| 688 // suboptimal, but since it fades out, that's ok. | 757 // suboptimal, but since it fades out, that's ok. |
| 689 gfx::ScopedNSGraphicsContextSaveGState scopedGState; | 758 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
| 690 [NSBezierPath clipRect:gradientPart]; | 759 [NSBezierPath clipRect:gradientPart]; |
| 691 CGContextRef context = static_cast<CGContextRef>( | 760 CGContextRef context = static_cast<CGContextRef>( |
| 692 [[NSGraphicsContext currentContext] graphicsPort]); | 761 [[NSGraphicsContext currentContext] graphicsPort]); |
| 693 CGContextBeginTransparencyLayerWithRect(context, | 762 CGContextBeginTransparencyLayerWithRect(context, |
| 694 NSRectToCGRect(gradientPart), 0); | 763 NSRectToCGRect(gradientPart), 0); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 options:options | 828 options:options |
| 760 owner:self | 829 owner:self |
| 761 userInfo:nil]); | 830 userInfo:nil]); |
| 762 if (isMouseInside_ != mouseInView) { | 831 if (isMouseInside_ != mouseInView) { |
| 763 [self setMouseInside:mouseInView animate:NO]; | 832 [self setMouseInside:mouseInView animate:NO]; |
| 764 [controlView setNeedsDisplay:YES]; | 833 [controlView setNeedsDisplay:YES]; |
| 765 } | 834 } |
| 766 } | 835 } |
| 767 | 836 |
| 768 @end | 837 @end |
| OLD | NEW |