summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/tab_view.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/cocoa/tab_view.mm')
-rw-r--r--chrome/browser/cocoa/tab_view.mm128
1 files changed, 128 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/tab_view.mm b/chrome/browser/cocoa/tab_view.mm
index 44d43ac..16d8e10 100644
--- a/chrome/browser/cocoa/tab_view.mm
+++ b/chrome/browser/cocoa/tab_view.mm
@@ -7,11 +7,23 @@
#include "chrome/browser/cocoa/tab_view.h"
#include "chrome/browser/cocoa/tab_window_controller.h"
+
+// Constants for inset and control points for tab shape.
+static const CGFloat kInsetMultiplier = 2.0/3.0;
+static const CGFloat kControlPoint1Multiplier = 1.0/3.0;
+static const CGFloat kControlPoint2Multiplier = 3.0/8.0;
+
+static const CGFloat kToolbarTopOffset = 12;
+static const CGFloat kToolbarMaxHeight = 128;
+
@implementation TabView
+@synthesize state = state_;
+
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
+ [self setShowsDivider:NO];
// TODO(alcor): register for theming, either here or the cell
// [self gtm_registerForThemeNotifications];
}
@@ -19,6 +31,7 @@
}
- (void)awakeFromNib {
+ [self setShowsDivider:NO];
// Set up the tracking rect for the close button mouseover. Add it
// to the |closeButton_| view, but we'll handle the message ourself.
// The mouseover is always enabled, because the close button works
@@ -363,6 +376,121 @@ static const double kDragStartDistance = 3.0;
}
}
+- (NSPoint)patternPhase {
+ NSPoint phase = NSZeroPoint;
+ phase.x -= [self convertRect:[self bounds] toView:nil].origin.x;
+ // offset to start pattern in upper left corner
+ phase.y += NSHeight([self bounds]) - 1;
+ return phase;
+}
+
+- (void)drawRect:(NSRect)rect {
+ [[NSGraphicsContext currentContext] saveGraphicsState];
+ rect = [self bounds];
+ BOOL active = [[self window] isKeyWindow] || [[self window] isMainWindow];
+ BOOL selected = [(NSButton *)self state];
+
+ // Inset by 0.5 in order to draw on pixels rather than on borders (which would
+ // cause blurry pixels). Decrease height by 1 in order to move away from the
+ // edge for the dark shadow.
+ rect = NSInsetRect(rect, 0.5, -0.5);
+ rect.origin.y -= 1;
+
+ NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect));
+ NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect));
+ NSPoint topRight =
+ NSMakePoint(NSMaxX(rect) - kInsetMultiplier * NSHeight(rect),
+ NSMaxY(rect));
+ NSPoint topLeft =
+ NSMakePoint(NSMinX(rect) + kInsetMultiplier * NSHeight(rect),
+ NSMaxY(rect));
+
+ float baseControlPointOutset = NSHeight(rect) * kControlPoint1Multiplier;
+ float bottomControlPointInset = NSHeight(rect) * kControlPoint2Multiplier;
+
+ // Outset many of these values by 1 to cause the fill to bleed outside the
+ // clip area.
+ NSBezierPath *path = [NSBezierPath bezierPath];
+ [path moveToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y + 1)];
+ [path lineToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y)];
+ [path lineToPoint:bottomLeft];
+ [path curveToPoint:topLeft
+ controlPoint1:NSMakePoint(bottomLeft.x + baseControlPointOutset,
+ bottomLeft.y)
+ controlPoint2:NSMakePoint(topLeft.x - bottomControlPointInset,
+ topLeft.y)];
+ [path lineToPoint:topRight];
+ [path curveToPoint:bottomRight
+ controlPoint1:NSMakePoint(topRight.x + bottomControlPointInset,
+ topRight.y)
+ controlPoint2:NSMakePoint(bottomRight.x - baseControlPointOutset,
+ bottomRight.y)];
+ [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y)];
+ [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y + 1)];
+
+ if (selected) {
+ // Stroke with a translucent black.
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:active ? 0.5 : 0.3] set];
+ [[NSGraphicsContext currentContext] saveGraphicsState];
+ scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
+ [shadow setShadowOffset:NSMakeSize(2, -1)];
+ [shadow setShadowBlurRadius:2.0];
+ [path fill];
+ [[NSGraphicsContext currentContext] restoreGraphicsState];
+ } else {
+ // Stroke with a translucent black.
+ [[NSBezierPath bezierPathWithRect:NSOffsetRect([self bounds], 0, 1)]
+ addClip];
+
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:active ? 0.3 : 0.1] set];
+ }
+
+ [[NSGraphicsContext currentContext] saveGraphicsState];
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set];
+ [path setLineWidth:selected ? 2.0 : 1.0];
+ [path stroke];
+ [[NSGraphicsContext currentContext] restoreGraphicsState];
+
+ GTMTheme *theme = [[self self] gtm_theme];
+
+ if (!selected) {
+ NSColor *windowColor =
+ [theme backgroundPatternColorForStyle:GTMThemeStyleWindow
+ state:GTMThemeStateActiveWindow];
+ if (windowColor) {
+ NSPoint phase = [self patternPhase];
+ [windowColor set];
+ [[NSGraphicsContext currentContext] setPatternPhase:phase];
+ } else {
+ [[NSColor colorWithCalibratedWhite:0.6 alpha:1.0] set];
+ }
+ [path fill];
+ }
+
+ // Draw the background.
+ [[NSGraphicsContext currentContext] saveGraphicsState];
+ CGContextRef context =
+ (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
+ CGContextBeginTransparencyLayer(context, 0);
+ if (!selected)
+ CGContextSetAlpha(context, 0.5);
+ [path addClip];
+ [super drawRect:rect];
+
+ CGContextEndTransparencyLayer(context);
+ [[NSGraphicsContext currentContext] restoreGraphicsState];
+
+ // Draw the bottom border.
+ if (!selected) {
+ [path addClip];
+ NSRect borderRect, contentRect;
+ NSDivideRect(rect, &borderRect, &contentRect, 1, NSMinYEdge);
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.4] set];
+ NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
+ }
+ [[NSGraphicsContext currentContext] restoreGraphicsState];
+}
+
// Called when the user hits the right mouse button (or control-clicks) to
// show a context menu.
- (void)rightMouseDown:(NSEvent*)theEvent {