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