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/tabs/tab_view.h" | 5 #import "chrome/browser/ui/cocoa/tabs/tab_view.h" |
| 6 | 6 |
| 7 #include "base/i18n/rtl.h" | 7 #include "base/i18n/rtl.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/mac/sdk_forward_declarations.h" | 9 #include "base/mac/sdk_forward_declarations.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 const NSTimeInterval kAlertHideDuration = 0.4; | 38 const NSTimeInterval kAlertHideDuration = 0.4; |
| 39 | 39 |
| 40 // The default time interval in seconds between glow updates (when | 40 // The default time interval in seconds between glow updates (when |
| 41 // increasing/decreasing). | 41 // increasing/decreasing). |
| 42 const NSTimeInterval kGlowUpdateInterval = 0.025; | 42 const NSTimeInterval kGlowUpdateInterval = 0.025; |
| 43 | 43 |
| 44 // This is used to judge whether the mouse has moved during rapid closure; if it | 44 // This is used to judge whether the mouse has moved during rapid closure; if it |
| 45 // has moved less than the threshold, we want to close the tab. | 45 // has moved less than the threshold, we want to close the tab. |
| 46 const CGFloat kRapidCloseDist = 2.5; | 46 const CGFloat kRapidCloseDist = 2.5; |
| 47 | 47 |
| 48 @interface TabView(MaterialDesign) | 48 // This class contains the logic for drawing Material Design tab images. The |
| 49 // |setTabEdgeStrokeColor| method is overridden by |TabHeavyImageMaker| to draw | |
| 50 // high-contrast tabs. | |
| 51 @interface TabImageMaker : NSObject | |
| 49 + (void)drawTabLeftMaskImage; | 52 + (void)drawTabLeftMaskImage; |
| 50 + (void)drawTabRightMaskImage; | 53 + (void)drawTabRightMaskImage; |
| 51 + (void)drawTabLeftEdgeImage; | 54 + (void)drawTabLeftEdgeImage; |
| 52 + (void)drawTabMiddleEdgeImage; | 55 + (void)drawTabMiddleEdgeImage; |
| 53 + (void)drawTabRightEdgeImage; | 56 + (void)drawTabRightEdgeImage; |
| 57 + (void)setTabEdgeStrokeColor; | |
| 58 @end | |
| 59 | |
| 60 @interface TabHeavyImageMaker : TabImageMaker | |
| 61 + (void)setTabEdgeStrokeColor; | |
| 54 @end | 62 @end |
| 55 | 63 |
| 56 @interface TabController(Private) | 64 @interface TabController(Private) |
| 57 // The TabView's close button. | 65 // The TabView's close button. |
| 58 - (HoverCloseButton*)closeButton; | 66 - (HoverCloseButton*)closeButton; |
| 59 @end | 67 @end |
| 60 | 68 |
| 69 extern NSString* const _Nonnull NSWorkspaceAccessibilityDisplayOptionsDidChangeN otification; | |
| 70 | |
| 61 namespace { | 71 namespace { |
| 62 | 72 |
| 63 NSImage* imageForResourceID(int resource_id) { | 73 NSImage* imageForResourceID(int resource_id, bool heavy_stroke) { |
|
Nico
2016/06/21 20:40:21
nit: prefer enums over bool params,
imageForResou
| |
| 64 if (!ui::MaterialDesignController::IsModeMaterial()) { | 74 if (!ui::MaterialDesignController::IsModeMaterial()) { |
| 65 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 75 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 66 return [rb.GetNativeImageNamed(resource_id).CopyNSImage() autorelease]; | 76 return [rb.GetNativeImageNamed(resource_id).CopyNSImage() autorelease]; |
| 67 } | 77 } |
| 68 | 78 |
| 69 CGFloat imageWidth = resource_id == IDR_TAB_ACTIVE_CENTER ? 1 : 18; | 79 CGFloat imageWidth = resource_id == IDR_TAB_ACTIVE_CENTER ? 1 : 18; |
| 70 SEL theSelector = 0; | 80 SEL theSelector = 0; |
| 71 switch (resource_id) { | 81 switch (resource_id) { |
| 72 case IDR_TAB_ACTIVE_LEFT: | 82 case IDR_TAB_ACTIVE_LEFT: |
| 73 theSelector = @selector(drawTabLeftEdgeImage); | 83 theSelector = @selector(drawTabLeftEdgeImage); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 84 case IDR_TAB_ALPHA_LEFT: | 94 case IDR_TAB_ALPHA_LEFT: |
| 85 theSelector = @selector(drawTabLeftMaskImage); | 95 theSelector = @selector(drawTabLeftMaskImage); |
| 86 break; | 96 break; |
| 87 | 97 |
| 88 case IDR_TAB_ALPHA_RIGHT: | 98 case IDR_TAB_ALPHA_RIGHT: |
| 89 theSelector = @selector(drawTabRightMaskImage); | 99 theSelector = @selector(drawTabRightMaskImage); |
| 90 break; | 100 break; |
| 91 } | 101 } |
| 92 DCHECK(theSelector); | 102 DCHECK(theSelector); |
| 93 | 103 |
| 104 Class makerClass = | |
| 105 heavy_stroke ? [TabHeavyImageMaker class] : [TabImageMaker class]; | |
| 94 base::scoped_nsobject<NSCustomImageRep> imageRep([[NSCustomImageRep alloc] | 106 base::scoped_nsobject<NSCustomImageRep> imageRep([[NSCustomImageRep alloc] |
| 95 initWithDrawSelector:theSelector | 107 initWithDrawSelector:theSelector |
| 96 delegate:[TabView class]]); | 108 delegate:makerClass]); |
| 97 | 109 |
| 98 NSImage* newTabButtonImage = | 110 NSImage* newTabButtonImage = |
| 99 [[[NSImage alloc] initWithSize:NSMakeSize(imageWidth, 29)] autorelease]; | 111 [[[NSImage alloc] initWithSize:NSMakeSize(imageWidth, 29)] autorelease]; |
| 100 [newTabButtonImage setCacheMode:NSImageCacheAlways]; | 112 [newTabButtonImage setCacheMode:NSImageCacheAlways]; |
| 101 [newTabButtonImage addRepresentation:imageRep]; | 113 [newTabButtonImage addRepresentation:imageRep]; |
| 102 | 114 |
| 103 return newTabButtonImage; | 115 return newTabButtonImage; |
| 104 } | 116 } |
| 105 | 117 |
| 106 ui::ThreePartImage& GetMaskImage() { | 118 ui::ThreePartImage& GetMaskImage() { |
| 107 CR_DEFINE_STATIC_LOCAL(ui::ThreePartImage, mask, | 119 CR_DEFINE_STATIC_LOCAL( |
| 108 (imageForResourceID(IDR_TAB_ALPHA_LEFT), nullptr, | 120 ui::ThreePartImage, mask, |
| 109 imageForResourceID(IDR_TAB_ALPHA_RIGHT))); | 121 (imageForResourceID(IDR_TAB_ALPHA_LEFT, false), nullptr, |
| 122 imageForResourceID(IDR_TAB_ALPHA_RIGHT, false))); | |
| 110 | 123 |
| 111 return mask; | 124 return mask; |
| 112 } | 125 } |
| 113 | 126 |
| 114 ui::ThreePartImage& GetStrokeImage(bool active) { | 127 ui::ThreePartImage& GetStrokeImage(bool active, bool increase_contrast) { |
| 115 if (!ui::MaterialDesignController::IsModeMaterial() && !active) { | 128 if (!ui::MaterialDesignController::IsModeMaterial() && !active) { |
| 116 CR_DEFINE_STATIC_LOCAL( | 129 CR_DEFINE_STATIC_LOCAL(ui::ThreePartImage, inactiveStroke, |
| 117 ui::ThreePartImage, inactiveStroke, | 130 (imageForResourceID(IDR_TAB_INACTIVE_LEFT, false), |
| 118 (imageForResourceID(IDR_TAB_INACTIVE_LEFT), | 131 imageForResourceID(IDR_TAB_INACTIVE_CENTER, false), |
| 119 imageForResourceID(IDR_TAB_INACTIVE_CENTER), | 132 imageForResourceID(IDR_TAB_INACTIVE_RIGHT, false))); |
| 120 imageForResourceID(IDR_TAB_INACTIVE_RIGHT))); | |
| 121 return inactiveStroke; | 133 return inactiveStroke; |
| 122 } | 134 } |
| 123 CR_DEFINE_STATIC_LOCAL( | 135 CR_DEFINE_STATIC_LOCAL(ui::ThreePartImage, stroke, |
| 124 ui::ThreePartImage, stroke, | 136 (imageForResourceID(IDR_TAB_ACTIVE_LEFT, false), |
| 125 (imageForResourceID(IDR_TAB_ACTIVE_LEFT), | 137 imageForResourceID(IDR_TAB_ACTIVE_CENTER, false), |
| 126 imageForResourceID(IDR_TAB_ACTIVE_CENTER), | 138 imageForResourceID(IDR_TAB_ACTIVE_RIGHT, false))); |
| 127 imageForResourceID(IDR_TAB_ACTIVE_RIGHT))); | 139 CR_DEFINE_STATIC_LOCAL(ui::ThreePartImage, heavyStroke, |
| 140 (imageForResourceID(IDR_TAB_ACTIVE_LEFT, true), | |
| 141 imageForResourceID(IDR_TAB_ACTIVE_CENTER, true), | |
| 142 imageForResourceID(IDR_TAB_ACTIVE_RIGHT, true))); | |
| 128 | 143 |
| 129 return stroke; | 144 return increase_contrast ? heavyStroke : stroke; |
| 130 } | 145 } |
| 131 | 146 |
| 132 CGFloat LineWidthFromContext(CGContextRef context) { | 147 CGFloat LineWidthFromContext(CGContextRef context) { |
| 133 CGRect unitRect = CGRectMake(0.0, 0.0, 1.0, 1.0); | 148 CGRect unitRect = CGRectMake(0.0, 0.0, 1.0, 1.0); |
| 134 CGRect deviceRect = CGContextConvertRectToDeviceSpace(context, unitRect); | 149 CGRect deviceRect = CGContextConvertRectToDeviceSpace(context, unitRect); |
| 135 return 1.0 / deviceRect.size.height; | 150 return 1.0 / deviceRect.size.height; |
| 136 } | 151 } |
| 137 | 152 |
| 138 } // namespace | 153 } // namespace |
| 139 | 154 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 171 titleView_.reset([[NSTextField alloc] init]); | 186 titleView_.reset([[NSTextField alloc] init]); |
| 172 [titleView_ setAutoresizingMask:NSViewWidthSizable]; | 187 [titleView_ setAutoresizingMask:NSViewWidthSizable]; |
| 173 base::scoped_nsobject<GTMFadeTruncatingTextFieldCell> labelCell( | 188 base::scoped_nsobject<GTMFadeTruncatingTextFieldCell> labelCell( |
| 174 [[GTMFadeTruncatingTextFieldCell alloc] initTextCell:@"Label"]); | 189 [[GTMFadeTruncatingTextFieldCell alloc] initTextCell:@"Label"]); |
| 175 [labelCell setControlSize:NSSmallControlSize]; | 190 [labelCell setControlSize:NSSmallControlSize]; |
| 176 // Font size is 12, per Material Design spec. | 191 // Font size is 12, per Material Design spec. |
| 177 CGFloat fontSize = 12; | 192 CGFloat fontSize = 12; |
| 178 if (!ui::MaterialDesignController::IsModeMaterial()) { | 193 if (!ui::MaterialDesignController::IsModeMaterial()) { |
| 179 fontSize = [NSFont systemFontSizeForControlSize:NSSmallControlSize]; | 194 fontSize = [NSFont systemFontSizeForControlSize:NSSmallControlSize]; |
| 180 } | 195 } |
| 181 [labelCell setFont:[NSFont systemFontOfSize:fontSize]]; | |
| 182 [titleView_ setCell:labelCell]; | 196 [titleView_ setCell:labelCell]; |
| 183 titleViewCell_ = labelCell; | 197 titleViewCell_ = labelCell; |
| 184 | 198 |
| 185 [self setWantsLayer:YES]; // -drawFill: needs a layer. | 199 [self setWantsLayer:YES]; // -drawFill: needs a layer. |
| 200 | |
| 201 if (NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification) { | |
| 202 NSNotificationCenter* center = | |
| 203 [[NSWorkspace sharedWorkspace] notificationCenter]; | |
| 204 [center | |
| 205 addObserver:self | |
| 206 selector:@selector(accessibilityOptionsDidChange:) | |
| 207 name: | |
| 208 NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification | |
|
Nico
2016/06/21 20:40:21
(uber nit: i'd have a local constant with a much s
| |
| 209 object:nil]; | |
| 210 } | |
| 186 } | 211 } |
| 187 return self; | 212 return self; |
| 188 } | 213 } |
| 189 | 214 |
| 190 - (void)dealloc { | 215 - (void)dealloc { |
| 191 // Cancel any delayed requests that may still be pending (drags or hover). | 216 // Cancel any delayed requests that may still be pending (drags or hover). |
| 192 [NSObject cancelPreviousPerformRequestsWithTarget:self]; | 217 [NSObject cancelPreviousPerformRequestsWithTarget:self]; |
| 218 if (NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification) { | |
| 219 NSNotificationCenter* center = | |
| 220 [[NSWorkspace sharedWorkspace] notificationCenter]; | |
| 221 [center removeObserver:self]; | |
| 222 } | |
| 193 [super dealloc]; | 223 [super dealloc]; |
| 194 } | 224 } |
| 195 | 225 |
| 196 // Called to obtain the context menu for when the user hits the right mouse | 226 // Called to obtain the context menu for when the user hits the right mouse |
| 197 // button (or control-clicks). (Note that -rightMouseDown: is *not* called for | 227 // button (or control-clicks). (Note that -rightMouseDown: is *not* called for |
| 198 // control-click.) | 228 // control-click.) |
| 199 - (NSMenu*)menu { | 229 - (NSMenu*)menu { |
| 200 if ([self isClosing]) | 230 if ([self isClosing]) |
| 201 return nil; | 231 return nil; |
| 202 | 232 |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 NSRect bounds = [self bounds]; | 512 NSRect bounds = [self bounds]; |
| 483 if (ui::MaterialDesignController::IsModeMaterial()) { | 513 if (ui::MaterialDesignController::IsModeMaterial()) { |
| 484 // In Material Design the tab strip separator is always 1 pixel high - | 514 // In Material Design the tab strip separator is always 1 pixel high - |
| 485 // add a clip rect to avoid drawing the tab edge over it. | 515 // add a clip rect to avoid drawing the tab edge over it. |
| 486 NSRect clipRect = bounds; | 516 NSRect clipRect = bounds; |
| 487 clipRect.origin.y += [self cr_lineWidth]; | 517 clipRect.origin.y += [self cr_lineWidth]; |
| 488 NSRectClip(clipRect); | 518 NSRectClip(clipRect); |
| 489 // In MD, the tab stroke is always opaque. | 519 // In MD, the tab stroke is always opaque. |
| 490 alpha = 1; | 520 alpha = 1; |
| 491 } | 521 } |
| 492 GetStrokeImage(state_ == NSOnState) | 522 GetStrokeImage(state_ == NSOnState, |
| 523 [[self window] themeProvider]->ShouldIncreaseContrast()) | |
| 493 .DrawInRect(bounds, NSCompositeSourceOver, alpha); | 524 .DrawInRect(bounds, NSCompositeSourceOver, alpha); |
| 494 } | 525 } |
| 495 | 526 |
| 496 - (void)drawRect:(NSRect)dirtyRect { | 527 - (void)drawRect:(NSRect)dirtyRect { |
| 497 [self drawFill:dirtyRect]; | 528 [self drawFill:dirtyRect]; |
| 498 [self drawStroke:dirtyRect]; | 529 [self drawStroke:dirtyRect]; |
| 499 | 530 |
| 500 // We draw the title string directly instead of using a NSTextField subview. | 531 // We draw the title string directly instead of using a NSTextField subview. |
| 501 // This is so that we can get font smoothing to work on earlier OS, and even | 532 // This is so that we can get font smoothing to work on earlier OS, and even |
| 502 // when the tab background is a pattern image (when using themes). | 533 // when the tab background is a pattern image (when using themes). |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 591 if (titleHidden == [titleView_ isHidden]) | 622 if (titleHidden == [titleView_ isHidden]) |
| 592 return; | 623 return; |
| 593 [titleView_ setHidden:titleHidden]; | 624 [titleView_ setHidden:titleHidden]; |
| 594 [self setNeedsDisplayInRect:[titleView_ frame]]; | 625 [self setNeedsDisplayInRect:[titleView_ frame]]; |
| 595 } | 626 } |
| 596 | 627 |
| 597 - (SkColor)closeButtonColor { | 628 - (SkColor)closeButtonColor { |
| 598 return [[controller_ closeButton] iconColor]; | 629 return [[controller_ closeButton] iconColor]; |
| 599 } | 630 } |
| 600 | 631 |
| 632 - (void)accessibilityOptionsDidChange:(id)ignored { | |
| 633 [self updateLabelFont]; | |
| 634 [self setNeedsDisplay:YES]; | |
| 635 } | |
| 636 | |
| 637 - (void)updateLabelFont { | |
| 638 CGFloat fontSize = [titleViewCell_ font].pointSize; | |
| 639 if ([[self window] themeProvider]->ShouldIncreaseContrast() && | |
| 640 state_ == NSOnState) { | |
| 641 [titleViewCell_ setFont:[NSFont boldSystemFontOfSize:fontSize]]; | |
| 642 } else { | |
| 643 [titleViewCell_ setFont:[NSFont systemFontOfSize:fontSize]]; | |
| 644 } | |
| 645 } | |
| 646 | |
| 601 - (void)setState:(NSCellStateValue)state { | 647 - (void)setState:(NSCellStateValue)state { |
| 602 if (state_ == state) | 648 if (state_ == state) |
| 603 return; | 649 return; |
| 604 state_ = state; | 650 state_ = state; |
| 651 [self updateLabelFont]; | |
| 605 [self setNeedsDisplay:YES]; | 652 [self setNeedsDisplay:YES]; |
| 606 } | 653 } |
| 607 | 654 |
| 608 - (void)setClosing:(BOOL)closing { | 655 - (void)setClosing:(BOOL)closing { |
| 609 closing_ = closing; // Safe because the property is nonatomic. | 656 closing_ = closing; // Safe because the property is nonatomic. |
| 610 // When closing, ensure clicks to the close button go nowhere. | 657 // When closing, ensure clicks to the close button go nowhere. |
| 611 if (closing) { | 658 if (closing) { |
| 612 [closeButton_ setTarget:nil]; | 659 [closeButton_ setTarget:nil]; |
| 613 [closeButton_ setAction:nil]; | 660 [closeButton_ setAction:nil]; |
| 614 } | 661 } |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 | 861 |
| 815 if (nextUpdate < kNoUpdate) | 862 if (nextUpdate < kNoUpdate) |
| 816 [self performSelector:_cmd withObject:nil afterDelay:nextUpdate]; | 863 [self performSelector:_cmd withObject:nil afterDelay:nextUpdate]; |
| 817 | 864 |
| 818 [self resetLastGlowUpdateTime]; | 865 [self resetLastGlowUpdateTime]; |
| 819 [self setNeedsDisplay:YES]; | 866 [self setNeedsDisplay:YES]; |
| 820 } | 867 } |
| 821 | 868 |
| 822 @end // @implementation TabView(Private) | 869 @end // @implementation TabView(Private) |
| 823 | 870 |
| 824 | 871 @implementation TabImageMaker |
| 825 @implementation TabView(MaterialDesign) | |
| 826 | 872 |
| 827 + (NSBezierPath*)tabLeftEdgeBezierPathForContext:(CGContextRef)context { | 873 + (NSBezierPath*)tabLeftEdgeBezierPathForContext:(CGContextRef)context { |
| 828 NSBezierPath* bezierPath = [NSBezierPath bezierPath]; | 874 NSBezierPath* bezierPath = [NSBezierPath bezierPath]; |
| 829 | 875 |
| 830 [bezierPath moveToPoint:NSMakePoint(-2, 0)]; | 876 [bezierPath moveToPoint:NSMakePoint(-2, 0)]; |
| 831 [bezierPath curveToPoint:NSMakePoint(2.5, 2) | 877 [bezierPath curveToPoint:NSMakePoint(2.5, 2) |
| 832 controlPoint1:NSMakePoint(1.805, -0.38) | 878 controlPoint1:NSMakePoint(1.805, -0.38) |
| 833 controlPoint2:NSMakePoint(2.17, 1.415)]; | 879 controlPoint2:NSMakePoint(2.17, 1.415)]; |
| 834 | 880 |
| 835 [bezierPath lineToPoint:NSMakePoint(14, 27)]; | 881 [bezierPath lineToPoint:NSMakePoint(14, 27)]; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 867 + (void)setTabEdgeStrokeColor { | 913 + (void)setTabEdgeStrokeColor { |
| 868 static NSColor* strokeColor = | 914 static NSColor* strokeColor = |
| 869 [skia::SkColorToSRGBNSColor(SkColorSetARGB(76, 0, 0, 0)) retain]; | 915 [skia::SkColorToSRGBNSColor(SkColorSetARGB(76, 0, 0, 0)) retain]; |
| 870 [strokeColor set]; | 916 [strokeColor set]; |
| 871 } | 917 } |
| 872 | 918 |
| 873 + (void)drawTabLeftEdgeImage { | 919 + (void)drawTabLeftEdgeImage { |
| 874 CGContextRef context = static_cast<CGContextRef>( | 920 CGContextRef context = static_cast<CGContextRef>( |
| 875 [[NSGraphicsContext currentContext] graphicsPort]); | 921 [[NSGraphicsContext currentContext] graphicsPort]); |
| 876 | 922 |
| 877 [TabView setTabEdgeStrokeColor]; | 923 [self setTabEdgeStrokeColor]; |
| 878 [[self tabLeftEdgeBezierPathForContext:context] stroke]; | 924 [[self tabLeftEdgeBezierPathForContext:context] stroke]; |
| 879 } | 925 } |
| 880 | 926 |
| 881 + (void)drawTabMiddleEdgeImage { | 927 + (void)drawTabMiddleEdgeImage { |
| 882 NSBezierPath* middleEdgePath = [NSBezierPath bezierPath]; | 928 NSBezierPath* middleEdgePath = [NSBezierPath bezierPath]; |
| 883 [middleEdgePath moveToPoint:NSMakePoint(0, 29)]; | 929 [middleEdgePath moveToPoint:NSMakePoint(0, 29)]; |
| 884 [middleEdgePath lineToPoint:NSMakePoint(1, 29)]; | 930 [middleEdgePath lineToPoint:NSMakePoint(1, 29)]; |
| 885 [middleEdgePath setLineCapStyle:NSSquareLineCapStyle]; | 931 [middleEdgePath setLineCapStyle:NSSquareLineCapStyle]; |
| 886 | 932 |
| 887 CGContextRef context = static_cast<CGContextRef>( | 933 CGContextRef context = static_cast<CGContextRef>( |
| 888 [[NSGraphicsContext currentContext] graphicsPort]); | 934 [[NSGraphicsContext currentContext] graphicsPort]); |
| 889 CGFloat lineWidth = LineWidthFromContext(context); | 935 CGFloat lineWidth = LineWidthFromContext(context); |
| 890 | 936 |
| 891 // Line width is always 1px. | 937 // Line width is always 1px. |
| 892 [middleEdgePath setLineWidth:lineWidth]; | 938 [middleEdgePath setLineWidth:lineWidth]; |
| 893 | 939 |
| 894 // Align to device pixels. | 940 // Align to device pixels. |
| 895 NSAffineTransform* translationTransform = [NSAffineTransform transform]; | 941 NSAffineTransform* translationTransform = [NSAffineTransform transform]; |
| 896 [translationTransform translateXBy:0 yBy:-1 + lineWidth / 2.]; | 942 [translationTransform translateXBy:0 yBy:-1 + lineWidth / 2.]; |
| 897 [middleEdgePath transformUsingAffineTransform:translationTransform]; | 943 [middleEdgePath transformUsingAffineTransform:translationTransform]; |
| 898 | 944 |
| 899 [TabView setTabEdgeStrokeColor]; | 945 [self setTabEdgeStrokeColor]; |
| 900 [middleEdgePath stroke]; | 946 [middleEdgePath stroke]; |
| 901 } | 947 } |
| 902 | 948 |
| 903 + (void)drawTabRightEdgeImage { | 949 + (void)drawTabRightEdgeImage { |
| 904 CGContextRef context = static_cast<CGContextRef>( | 950 CGContextRef context = static_cast<CGContextRef>( |
| 905 [[NSGraphicsContext currentContext] graphicsPort]); | 951 [[NSGraphicsContext currentContext] graphicsPort]); |
| 906 | 952 |
| 907 NSBezierPath* leftEdgePath = [self tabLeftEdgeBezierPathForContext:context]; | 953 NSBezierPath* leftEdgePath = [self tabLeftEdgeBezierPathForContext:context]; |
| 908 | 954 |
| 909 // Draw the right edge path by flipping the left edge path vertically. | 955 // Draw the right edge path by flipping the left edge path vertically. |
| 910 NSAffineTransform* transform = [NSAffineTransform transform]; | 956 NSAffineTransform* transform = [NSAffineTransform transform]; |
| 911 [transform scaleXBy:-1 yBy:1]; | 957 [transform scaleXBy:-1 yBy:1]; |
| 912 [transform translateXBy:-18 yBy:0]; | 958 [transform translateXBy:-18 yBy:0]; |
| 913 [leftEdgePath transformUsingAffineTransform:transform]; | 959 [leftEdgePath transformUsingAffineTransform:transform]; |
| 914 | 960 |
| 915 [TabView setTabEdgeStrokeColor]; | 961 [self setTabEdgeStrokeColor]; |
| 916 [leftEdgePath stroke]; | 962 [leftEdgePath stroke]; |
| 917 } | 963 } |
| 918 | 964 |
| 919 + (NSBezierPath*)tabLeftMaskBezierPath { | 965 + (NSBezierPath*)tabLeftMaskBezierPath { |
| 920 NSBezierPath* bezierPath = [self tabLeftEdgeBezierPathForContext:nullptr]; | 966 NSBezierPath* bezierPath = [self tabLeftEdgeBezierPathForContext:nullptr]; |
| 921 | 967 |
| 922 // Box in the open edges. | 968 // Box in the open edges. |
| 923 [bezierPath lineToPoint:NSMakePoint(18, 0)]; | 969 [bezierPath lineToPoint:NSMakePoint(18, 0)]; |
| 924 [bezierPath lineToPoint:NSMakePoint(0, 0)]; | 970 [bezierPath lineToPoint:NSMakePoint(0, 0)]; |
| 925 | 971 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 944 NSBezierPath* bezierPath = [self tabLeftMaskBezierPath]; | 990 NSBezierPath* bezierPath = [self tabLeftMaskBezierPath]; |
| 945 NSAffineTransform* transform = [NSAffineTransform transform]; | 991 NSAffineTransform* transform = [NSAffineTransform transform]; |
| 946 [transform scaleXBy:-1 yBy:1]; | 992 [transform scaleXBy:-1 yBy:1]; |
| 947 [transform translateXBy:-17.5 yBy:-0.25]; | 993 [transform translateXBy:-17.5 yBy:-0.25]; |
| 948 [bezierPath transformUsingAffineTransform:transform]; | 994 [bezierPath transformUsingAffineTransform:transform]; |
| 949 | 995 |
| 950 [[NSColor whiteColor] set]; | 996 [[NSColor whiteColor] set]; |
| 951 [bezierPath fill]; | 997 [bezierPath fill]; |
| 952 } | 998 } |
| 953 | 999 |
| 954 @end // @implementation TabView(MaterialDesign) | 1000 @end |
| 1001 | |
| 1002 @implementation TabHeavyImageMaker | |
| 1003 | |
| 1004 // For "Increase Contrast" mode, use flat black instead of semitransparent black | |
| 1005 // for the tab edge stroke. | |
| 1006 + (void)setTabEdgeStrokeColor { | |
|
Nico
2016/06/21 20:40:21
overriding static methods is a bit clever, maybe t
| |
| 1007 static NSColor* heavyStrokeColor = | |
| 1008 [skia::SkColorToSRGBNSColor(SK_ColorBLACK) retain]; | |
| 1009 [heavyStrokeColor set]; | |
| 1010 } | |
| 1011 | |
| 1012 @end | |
| OLD | NEW |