Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: chrome/browser/cocoa/tab_view.mm

Issue 165499: Updates to clean up default theme and add hover states (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/cocoa/tab_view.h ('k') | chrome/browser/cocoa/tab_view_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/cocoa/nsimage_cache.h" 5 #include "chrome/browser/cocoa/nsimage_cache.h"
6 #include "chrome/browser/cocoa/tab_controller.h" 6 #include "chrome/browser/cocoa/tab_controller.h"
7 #include "chrome/browser/cocoa/tab_view.h" 7 #include "chrome/browser/cocoa/tab_view.h"
8 #include "chrome/browser/cocoa/tab_window_controller.h" 8 #include "chrome/browser/cocoa/tab_window_controller.h"
9 9
10 10
11 // Constants for inset and control points for tab shape. 11 // Constants for inset and control points for tab shape.
12 static const CGFloat kInsetMultiplier = 2.0/3.0; 12 static const CGFloat kInsetMultiplier = 2.0/3.0;
13 static const CGFloat kControlPoint1Multiplier = 1.0/3.0; 13 static const CGFloat kControlPoint1Multiplier = 1.0/3.0;
14 static const CGFloat kControlPoint2Multiplier = 3.0/8.0; 14 static const CGFloat kControlPoint2Multiplier = 3.0/8.0;
15 15
16 static const NSTimeInterval kAnimationShowDuration = 0.2;
17 static const NSTimeInterval kAnimationHideDuration = 0.4;
18
16 @implementation TabView 19 @implementation TabView
17 20
18 @synthesize state = state_; 21 @synthesize state = state_;
22 @synthesize hoverAlpha = hoverAlpha_;
19 23
20 - (id)initWithFrame:(NSRect)frame { 24 - (id)initWithFrame:(NSRect)frame {
21 self = [super initWithFrame:frame]; 25 self = [super initWithFrame:frame];
22 if (self) { 26 if (self) {
23 chromeIsVisible_ = YES; 27 chromeIsVisible_ = YES;
24 [self setShowsDivider:NO]; 28 [self setShowsDivider:NO];
25 // TODO(alcor): register for theming, either here or the cell 29 // TODO(alcor): register for theming, either here or the cell
26 // [self gtm_registerForThemeNotifications]; 30 // [self gtm_registerForThemeNotifications];
27 } 31 }
28 return self; 32 return self;
29 } 33 }
30 34
31 - (void)awakeFromNib { 35 - (void)awakeFromNib {
32 [self setShowsDivider:NO]; 36 [self setShowsDivider:NO];
33 // Set up the tracking rect for the close button mouseover. Add it 37 // Set up the tracking rect for the close button mouseover. Add it
34 // to the |closeButton_| view, but we'll handle the message ourself. 38 // to the |closeButton_| view, but we'll handle the message ourself.
35 // The mouseover is always enabled, because the close button works 39 // The mouseover is always enabled, because the close button works
36 // regardless of key/main/active status. 40 // regardless of key/main/active status.
37 trackingArea_.reset( 41 closeTrackingArea_.reset(
38 [[NSTrackingArea alloc] initWithRect:[closeButton_ bounds] 42 [[NSTrackingArea alloc] initWithRect:[closeButton_ bounds]
39 options:NSTrackingMouseEnteredAndExited | 43 options:NSTrackingMouseEnteredAndExited |
40 NSTrackingActiveAlways 44 NSTrackingActiveAlways
41 owner:self 45 owner:self
42 userInfo:nil]); 46 userInfo:nil]);
43 [closeButton_ addTrackingArea:trackingArea_.get()]; 47 [closeButton_ addTrackingArea:closeTrackingArea_.get()];
44 } 48 }
45 49
46 - (void)dealloc { 50 - (void)dealloc {
47 // [self gtm_unregisterForThemeNotifications]; 51 // [self gtm_unregisterForThemeNotifications];
48 [closeButton_ removeTrackingArea:trackingArea_.get()]; 52 [closeButton_ removeTrackingArea:closeTrackingArea_.get()];
49 [super dealloc]; 53 [super dealloc];
50 } 54 }
51 55
52 // Overridden so that mouse clicks come to this view (the parent of the 56 // Overridden so that mouse clicks come to this view (the parent of the
53 // hierarchy) first. We want to handle clicks and drags in this class and 57 // hierarchy) first. We want to handle clicks and drags in this class and
54 // leave the background button for display purposes only. 58 // leave the background button for display purposes only.
55 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { 59 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent {
56 return YES; 60 return YES;
57 } 61 }
58 62
63 - (void)adjustHoverValue {
64 NSTimeInterval thisUpdate = [NSDate timeIntervalSinceReferenceDate];
65
66 NSTimeInterval elapsed = thisUpdate - lastHoverUpdate_;
67
68 CGFloat opacity = [self hoverAlpha];
69 if (isMouseInside_) {
70 opacity += elapsed / kAnimationShowDuration;
71 } else {
72 opacity -= elapsed / kAnimationHideDuration;
73 }
74
75 if (!isMouseInside_ && opacity < 0) {
76 opacity = 0;
77 } else if (isMouseInside_ && opacity > 1) {
78 opacity = 1;
79 } else {
80 [self performSelector:_cmd withObject:nil afterDelay:0.02];
81 }
82 lastHoverUpdate_ = thisUpdate;
83 [self setHoverAlpha:opacity];
84
85 [self setNeedsDisplay:YES];
86 }
87
59 - (void)mouseEntered:(NSEvent *)theEvent { 88 - (void)mouseEntered:(NSEvent *)theEvent {
60 // We only set up one tracking area, so we know any mouseEntered: 89 if ([theEvent trackingArea] == closeTrackingArea_) {
61 // messages are for close button mouseovers. 90 [closeButton_ setImage:nsimage_cache::ImageNamed(@"close_bar_h.pdf")];
62 [closeButton_ setImage:nsimage_cache::ImageNamed(@"close_bar_h.pdf")]; 91 } else {
92 lastHoverUpdate_ = [NSDate timeIntervalSinceReferenceDate];
93 isMouseInside_ = YES;
94 [self adjustHoverValue];
95 [self setNeedsDisplay:YES];
96 }
97 }
98
99 - (void)mouseMoved:(NSEvent *)theEvent {
100 hoverPoint_ = [self convertPoint:[theEvent locationInWindow]
101 fromView:nil];
102 [self setNeedsDisplay:YES];
63 } 103 }
64 104
65 - (void)mouseExited:(NSEvent *)theEvent { 105 - (void)mouseExited:(NSEvent *)theEvent {
66 // We only set up one tracking area, so we know any mouseExited: 106 if ([theEvent trackingArea] == closeTrackingArea_) {
67 // messages are for close button mouseovers. 107 [closeButton_ setImage:nsimage_cache::ImageNamed(@"close_bar.pdf")];
68 [closeButton_ setImage:nsimage_cache::ImageNamed(@"close_bar.pdf")]; 108 } else {
109 lastHoverUpdate_ = [NSDate timeIntervalSinceReferenceDate];
110 isMouseInside_ = NO;
111 [self adjustHoverValue];
112 [self setNeedsDisplay:YES];
113 }
69 } 114 }
70 115
71 // Determines which view a click in our frame actually hit. It's either this 116 // Determines which view a click in our frame actually hit. It's either this
72 // view or our child close button. 117 // view or our child close button.
73 - (NSView *)hitTest:(NSPoint)aPoint { 118 - (NSView *)hitTest:(NSPoint)aPoint {
74 NSPoint viewPoint = [self convertPoint:aPoint fromView:[self superview]]; 119 NSPoint viewPoint = [self convertPoint:aPoint fromView:[self superview]];
75 NSRect frame = [self frame]; 120 NSRect frame = [self frame];
76 121
77 // Reduce the width of the hit rect slightly to remove the overlap 122 // Reduce the width of the hit rect slightly to remove the overlap
78 // between adjacent tabs. The drawing code in TabCell has the top 123 // between adjacent tabs. The drawing code in TabCell has the top
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 } 269 }
225 } 270 }
226 271
227 // Iterate over possible targets checking for the one the mouse is in. 272 // Iterate over possible targets checking for the one the mouse is in.
228 // The mouse can be in either the tab or window frame. 273 // The mouse can be in either the tab or window frame.
229 TabWindowController* newTarget = nil; 274 TabWindowController* newTarget = nil;
230 for (TabWindowController* target in targets) { 275 for (TabWindowController* target in targets) {
231 NSRect windowFrame = [[target window] frame]; 276 NSRect windowFrame = [[target window] frame];
232 if (NSPointInRect(thisPoint, windowFrame)) { 277 if (NSPointInRect(thisPoint, windowFrame)) {
233 NSRect tabStripFrame = [[target tabStripView] frame]; 278 NSRect tabStripFrame = [[target tabStripView] frame];
234 tabStripFrame = [[target tabStripView] convertRectToBase:tabStripFrame];
235 tabStripFrame.origin = [[target window] 279 tabStripFrame.origin = [[target window]
236 convertBaseToScreen:tabStripFrame.origin]; 280 convertBaseToScreen:tabStripFrame.origin];
237 if (NSPointInRect(thisPoint, tabStripFrame)) { 281 if (NSPointInRect(thisPoint, tabStripFrame)) {
238 newTarget = target; 282 newTarget = target;
239 } 283 }
240 break; 284 break;
241 } 285 }
242 } 286 }
243 287
244 // If we're now targeting a new window, re-layout the tabs in the old 288 // If we're now targeting a new window, re-layout the tabs in the old
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 463
420 - (void)drawRect:(NSRect)rect { 464 - (void)drawRect:(NSRect)rect {
421 [[NSGraphicsContext currentContext] saveGraphicsState]; 465 [[NSGraphicsContext currentContext] saveGraphicsState];
422 rect = [self bounds]; 466 rect = [self bounds];
423 BOOL active = [[self window] isKeyWindow] || [[self window] isMainWindow]; 467 BOOL active = [[self window] isKeyWindow] || [[self window] isMainWindow];
424 BOOL selected = [(NSButton *)self state]; 468 BOOL selected = [(NSButton *)self state];
425 469
426 // Inset by 0.5 in order to draw on pixels rather than on borders (which would 470 // Inset by 0.5 in order to draw on pixels rather than on borders (which would
427 // cause blurry pixels). Decrease height by 1 in order to move away from the 471 // cause blurry pixels). Decrease height by 1 in order to move away from the
428 // edge for the dark shadow. 472 // edge for the dark shadow.
429 rect = NSInsetRect(rect, 0.5, -0.5); 473 rect = NSInsetRect(rect, -0.5, -0.5);
430 rect.origin.y -= 1; 474 rect.origin.y -= 1;
431 475
432 NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect)); 476 NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect) + 2);
433 NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect)); 477 NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect) + 2);
434 NSPoint topRight = 478 NSPoint topRight =
435 NSMakePoint(NSMaxX(rect) - kInsetMultiplier * NSHeight(rect), 479 NSMakePoint(NSMaxX(rect) - kInsetMultiplier * NSHeight(rect),
436 NSMaxY(rect)); 480 NSMaxY(rect));
437 NSPoint topLeft = 481 NSPoint topLeft =
438 NSMakePoint(NSMinX(rect) + kInsetMultiplier * NSHeight(rect), 482 NSMakePoint(NSMinX(rect) + kInsetMultiplier * NSHeight(rect),
439 NSMaxY(rect)); 483 NSMaxY(rect));
440 484
441 float baseControlPointOutset = NSHeight(rect) * kControlPoint1Multiplier; 485 float baseControlPointOutset = NSHeight(rect) * kControlPoint1Multiplier;
442 float bottomControlPointInset = NSHeight(rect) * kControlPoint2Multiplier; 486 float bottomControlPointInset = NSHeight(rect) * kControlPoint2Multiplier;
443 487
444 // Outset many of these values by 1 to cause the fill to bleed outside the 488 // Outset many of these values by 1 to cause the fill to bleed outside the
445 // clip area. 489 // clip area.
446 NSBezierPath *path = [NSBezierPath bezierPath]; 490 NSBezierPath *path = [NSBezierPath bezierPath];
447 [path moveToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y + 1)]; 491 [path moveToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y - 2)];
448 [path lineToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y)]; 492 [path lineToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y)];
449 [path lineToPoint:bottomLeft]; 493 [path lineToPoint:bottomLeft];
450 [path curveToPoint:topLeft 494 [path curveToPoint:topLeft
451 controlPoint1:NSMakePoint(bottomLeft.x + baseControlPointOutset, 495 controlPoint1:NSMakePoint(bottomLeft.x + baseControlPointOutset,
452 bottomLeft.y) 496 bottomLeft.y)
453 controlPoint2:NSMakePoint(topLeft.x - bottomControlPointInset, 497 controlPoint2:NSMakePoint(topLeft.x - bottomControlPointInset,
454 topLeft.y)]; 498 topLeft.y)];
455 [path lineToPoint:topRight]; 499 [path lineToPoint:topRight];
456 [path curveToPoint:bottomRight 500 [path curveToPoint:bottomRight
457 controlPoint1:NSMakePoint(topRight.x + bottomControlPointInset, 501 controlPoint1:NSMakePoint(topRight.x + bottomControlPointInset,
458 topRight.y) 502 topRight.y)
459 controlPoint2:NSMakePoint(bottomRight.x - baseControlPointOutset, 503 controlPoint2:NSMakePoint(bottomRight.x - baseControlPointOutset,
460 bottomRight.y)]; 504 bottomRight.y)];
461 [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y)]; 505 [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y)];
462 [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y + 1)]; 506 [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y - 2)];
463
464 if (selected) {
465 // Stroke with a translucent black.
466 [[NSColor colorWithCalibratedWhite:0.0 alpha:active ? 0.5 : 0.3] set];
467 [[NSGraphicsContext currentContext] saveGraphicsState];
468 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
469 [shadow setShadowOffset:NSMakeSize(2, -1)];
470 [shadow setShadowBlurRadius:2.0];
471 [path fill];
472 [[NSGraphicsContext currentContext] restoreGraphicsState];
473 } else {
474 // Stroke with a translucent black.
475 [[NSBezierPath bezierPathWithRect:NSOffsetRect([self bounds], 0, 1)]
476 addClip];
477
478 [[NSColor colorWithCalibratedWhite:0.0 alpha:active ? 0.3 : 0.1] set];
479 }
480
481 [[NSGraphicsContext currentContext] saveGraphicsState];
482 [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set];
483 [path setLineWidth:selected ? 2.0 : 1.0];
484 [path stroke];
485 [[NSGraphicsContext currentContext] restoreGraphicsState];
486 507
487 GTMTheme *theme = [self gtm_theme]; 508 GTMTheme *theme = [self gtm_theme];
488 509
489 if (!selected) { 510 if (!selected) {
490 NSColor *windowColor = 511 NSColor *windowColor =
491 [theme backgroundPatternColorForStyle:GTMThemeStyleWindow 512 [theme backgroundPatternColorForStyle:GTMThemeStyleWindow
492 state:GTMThemeStateActiveWindow]; 513 state:GTMThemeStateActiveWindow];
493 if (windowColor) { 514 if (windowColor) {
515 [windowColor set];
516
517 [[NSGraphicsContext currentContext] setPatternPhase:[self patternPhase]];
518 } else {
494 NSPoint phase = [self patternPhase]; 519 NSPoint phase = [self patternPhase];
495 [windowColor set]; 520 phase.y += 1;
496 [[NSGraphicsContext currentContext] setPatternPhase:phase]; 521 [[NSGraphicsContext currentContext] setPatternPhase:phase];
522 [[NSColor windowBackgroundColor] set];
523 }
524
525 [path fill];
526
527 NSColor *tabColor =
528 [theme backgroundPatternColorForStyle:GTMThemeStyleTabBarDeselected
529 state:GTMThemeStateActiveWindow];
530 if (tabColor) {
531 [tabColor set];
532 [[NSGraphicsContext currentContext] setPatternPhase:[self patternPhase]];
497 } else { 533 } else {
498 [[NSColor colorWithCalibratedWhite:0.6 alpha:1.0] set]; 534 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.3] set];
499 } 535 }
500 [path fill]; 536 [path fill];
537
501 } 538 }
502 539
503 // Draw the background.
504 [[NSGraphicsContext currentContext] saveGraphicsState]; 540 [[NSGraphicsContext currentContext] saveGraphicsState];
505 CGContextRef context =
506 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
507 CGContextBeginTransparencyLayer(context, 0);
508 if (!selected)
509 CGContextSetAlpha(context, 0.5);
510 [path addClip]; 541 [path addClip];
511 [super drawRect:rect];
512 542
513 CGContextEndTransparencyLayer(context); 543 if (selected || hoverAlpha_ > 0) {
544 // Draw the background.
545 CGFloat backgroundAlpha = hoverAlpha_ * 0.5;
546 [[NSGraphicsContext currentContext] saveGraphicsState];
547 CGContextRef context =
548 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
549 CGContextBeginTransparencyLayer(context, 0);
550 if (!selected)
551 CGContextSetAlpha(context, backgroundAlpha);
552 [path addClip];
553 [super drawRect:rect];
554
555 // Draw a mouse hover gradient for the default themes
556 if (!selected) {
557 if (![theme backgroundImageForStyle:GTMThemeStyleTabBarDeselected
558 state:GTMThemeStateActiveWindow]) {
559 scoped_nsobject<NSGradient> glow([NSGradient alloc]);
560 [glow initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0
561 alpha:1.0 *
562 hoverAlpha_]
563 endingColor:[NSColor colorWithCalibratedWhite:1.0
564 alpha:0.0]];
565
566 NSPoint point = hoverPoint_;
567 point.y = NSHeight(rect);
568 [glow drawFromCenter:point
569 radius:0
570 toCenter:point
571 radius:NSWidth(rect)/3
572 options:NSGradientDrawsBeforeStartingLocation];
573
574 [glow drawInBezierPath:path relativeCenterPosition:hoverPoint_];
575 }
576 }
577
578 CGContextEndTransparencyLayer(context);
579 [[NSGraphicsContext currentContext] restoreGraphicsState];
580 }
581
582 // Draw the top inner highlight.
583 NSAffineTransform* highlightTransform = [NSAffineTransform transform];
584 [highlightTransform translateXBy:1 yBy:-1];
585 scoped_nsobject<NSBezierPath> highlightPath([path copy]);
586 [highlightPath transformUsingAffineTransform:highlightTransform];
587 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 + 0.3 * hoverAlpha_]
588 setStroke];
589 [highlightPath stroke];
590
591 [[NSGraphicsContext currentContext] restoreGraphicsState];
592
593 // Draw the top stroke.
594 [[NSGraphicsContext currentContext] saveGraphicsState];
595 if (selected) {
596 [[NSColor colorWithDeviceWhite:0.0 alpha:active ? 0.3 : 0.15] set];
597 } else {
598 [[NSColor colorWithDeviceWhite:0.0 alpha:active ? 0.2 : 0.15] set];
599 [[NSBezierPath bezierPathWithRect:NSOffsetRect(rect, 0, 2.5)] addClip];
600 }
601 [path setLineWidth:1.0];
602 [path stroke];
514 [[NSGraphicsContext currentContext] restoreGraphicsState]; 603 [[NSGraphicsContext currentContext] restoreGraphicsState];
515 604
516 // Draw the bottom border. 605 // Draw the bottom border.
517 if (!selected) { 606 if (!selected) {
518 [path addClip]; 607 [path addClip];
519 NSRect borderRect, contentRect; 608 NSRect borderRect, contentRect;
520 NSDivideRect(rect, &borderRect, &contentRect, 1, NSMinYEdge); 609 NSDivideRect(rect, &borderRect, &contentRect, 2.5, NSMinYEdge);
521 [[NSColor colorWithCalibratedWhite:0.0 alpha:0.4] set]; 610 [[NSColor colorWithDeviceWhite:0.0 alpha:active ? 0.3 : 0.15] set];
522 NSRectFillUsingOperation(borderRect, NSCompositeSourceOver); 611 NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
523 } 612 }
524 [[NSGraphicsContext currentContext] restoreGraphicsState]; 613 [[NSGraphicsContext currentContext] restoreGraphicsState];
525 } 614 }
526 615
527 // Called when the user hits the right mouse button (or control-clicks) to 616 // Called when the user hits the right mouse button (or control-clicks) to
528 // show a context menu. 617 // show a context menu.
529 - (void)rightMouseDown:(NSEvent*)theEvent { 618 - (void)rightMouseDown:(NSEvent*)theEvent {
530 [NSMenu popUpContextMenu:[self menu] withEvent:theEvent forView:self]; 619 [NSMenu popUpContextMenu:[self menu] withEvent:theEvent forView:self];
531 } 620 }
532 621
533 @end 622 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/tab_view.h ('k') | chrome/browser/cocoa/tab_view_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698