OLD | NEW |
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 #import "chrome/browser/ui/cocoa/fast_resize_view.h" | 5 #import "chrome/browser/ui/cocoa/fast_resize_view.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/command_line.h" | |
11 #include "base/mac/scoped_nsobject.h" | 10 #include "base/mac/scoped_nsobject.h" |
12 #include "ui/base/cocoa/animation_utils.h" | 11 #include "ui/base/cocoa/animation_utils.h" |
13 #include "ui/base/ui_base_switches.h" | |
14 | 12 |
15 namespace { | 13 namespace { |
16 | 14 |
17 // The radius of the rounded corners. | 15 // The radius of the rounded corners. |
18 const CGFloat kRoundedCornerRadius = 4; | 16 const CGFloat kRoundedCornerRadius = 4; |
19 | 17 |
20 } // namespace | 18 } // namespace |
21 | 19 |
22 @interface FastResizeView (PrivateMethods) | 20 @interface FastResizeView (PrivateMethods) |
23 // Lays out this views subviews. If fast resize mode is on, does not resize any | |
24 // subviews and instead pegs them to the top left. If fast resize mode is off, | |
25 // sets the subviews' frame to be equal to this view's bounds. | |
26 - (void)layoutSubviews; | |
27 | |
28 // Creates a path whose bottom two corners are rounded. | 21 // Creates a path whose bottom two corners are rounded. |
29 // Caller takes ownership of the path. | 22 // Caller takes ownership of the path. |
30 - (CGPathRef)createRoundedBottomCornersPath:(NSSize)size; | 23 - (CGPathRef)createRoundedBottomCornersPath:(NSSize)size; |
31 | 24 |
32 // Updates the path of the layer mask to reflect the current value of | 25 // Updates the path of the layer mask to reflect the current value of |
33 // roundedBottomCorners_ and fastResizeMode_. | 26 // roundedBottomCorners_. |
34 - (void)updateLayerMask; | 27 - (void)updateLayerMask; |
35 @end | 28 @end |
36 | 29 |
37 @implementation FastResizeView | 30 @implementation FastResizeView |
38 | 31 |
39 - (id)initWithFrame:(NSRect)frameRect { | 32 - (id)initWithFrame:(NSRect)frameRect { |
40 if ((self = [super initWithFrame:frameRect])) { | 33 if ((self = [super initWithFrame:frameRect])) { |
41 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 34 ScopedCAActionDisabler disabler; |
42 switches::kDisableCoreAnimation)) { | 35 base::scoped_nsobject<CALayer> layer([[CALayer alloc] init]); |
43 ScopedCAActionDisabler disabler; | 36 [layer setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; |
44 base::scoped_nsobject<CALayer> layer([[CALayer alloc] init]); | 37 [self setLayer:layer]; |
45 [layer setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; | 38 [self setWantsLayer:YES]; |
46 [self setLayer:layer]; | |
47 [self setWantsLayer:YES]; | |
48 | 39 |
49 roundedBottomCorners_ = YES; | 40 roundedBottomCorners_ = YES; |
50 [self updateLayerMask]; | 41 [self updateLayerMask]; |
51 } | |
52 } | 42 } |
53 return self; | 43 return self; |
54 } | 44 } |
55 | 45 |
56 - (BOOL)isOpaque { | 46 - (BOOL)isOpaque { |
57 return YES; | 47 return YES; |
58 } | 48 } |
59 | 49 |
60 - (void)setFastResizeMode:(BOOL)fastResizeMode { | |
61 if (fastResizeMode_ == fastResizeMode) | |
62 return; | |
63 | |
64 fastResizeMode_ = fastResizeMode; | |
65 [self updateLayerMask]; | |
66 | |
67 // Force a relayout when coming out of fast resize mode. | |
68 if (!fastResizeMode_) | |
69 [self layoutSubviews]; | |
70 | |
71 [self setNeedsDisplay:YES]; | |
72 } | |
73 | |
74 - (void)setRoundedBottomCorners:(BOOL)roundedBottomCorners { | 50 - (void)setRoundedBottomCorners:(BOOL)roundedBottomCorners { |
75 if (roundedBottomCorners == roundedBottomCorners_) | 51 if (roundedBottomCorners == roundedBottomCorners_) |
76 return; | 52 return; |
77 | 53 |
78 roundedBottomCorners_ = roundedBottomCorners; | 54 roundedBottomCorners_ = roundedBottomCorners; |
79 [self updateLayerMask]; | 55 [self updateLayerMask]; |
80 } | 56 } |
81 | 57 |
82 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize { | |
83 [self layoutSubviews]; | |
84 } | |
85 | |
86 - (void)drawRect:(NSRect)dirtyRect { | |
87 // If we are in fast resize mode, our subviews may not completely cover our | |
88 // bounds, so we fill with white. If we are not in fast resize mode, we do | |
89 // not need to draw anything. | |
90 if (!fastResizeMode_) | |
91 return; | |
92 | |
93 [[NSColor whiteColor] set]; | |
94 NSRectFill(dirtyRect); | |
95 } | |
96 | |
97 // Every time the frame's size changes, the layer mask needs to be updated. | 58 // Every time the frame's size changes, the layer mask needs to be updated. |
98 - (void)setFrameSize:(NSSize)newSize { | 59 - (void)setFrameSize:(NSSize)newSize { |
99 [super setFrameSize:newSize]; | 60 [super setFrameSize:newSize]; |
100 [self updateLayerMask]; | 61 [self updateLayerMask]; |
101 } | 62 } |
102 | 63 |
103 @end | 64 @end |
104 | 65 |
105 @implementation FastResizeView (PrivateMethods) | 66 @implementation FastResizeView (PrivateMethods) |
106 | 67 |
107 - (void)layoutSubviews { | |
108 // There should never be more than one subview. There can be zero, if we are | |
109 // in the process of switching tabs or closing the window. In those cases, no | |
110 // layout is needed. | |
111 NSArray* subviews = [self subviews]; | |
112 DCHECK([subviews count] <= 1); | |
113 if ([subviews count] < 1) | |
114 return; | |
115 | |
116 NSView* subview = [subviews objectAtIndex:0]; | |
117 NSRect bounds = [self bounds]; | |
118 | |
119 if (fastResizeMode_) { | |
120 NSRect frame = [subview frame]; | |
121 frame.origin.x = 0; | |
122 frame.origin.y = NSHeight(bounds) - NSHeight(frame); | |
123 [subview setFrame:frame]; | |
124 } else { | |
125 [subview setFrame:bounds]; | |
126 } | |
127 } | |
128 | |
129 - (CGPathRef)createRoundedBottomCornersPath:(NSSize)size { | 68 - (CGPathRef)createRoundedBottomCornersPath:(NSSize)size { |
130 CGMutablePathRef path = CGPathCreateMutable(); | 69 CGMutablePathRef path = CGPathCreateMutable(); |
131 CGFloat width = size.width; | 70 CGFloat width = size.width; |
132 CGFloat height = size.height; | 71 CGFloat height = size.height; |
133 CGFloat cornerRadius = kRoundedCornerRadius; | 72 CGFloat cornerRadius = kRoundedCornerRadius; |
134 | 73 |
135 // Top left corner. | 74 // Top left corner. |
136 CGPathMoveToPoint(path, NULL, 0, height); | 75 CGPathMoveToPoint(path, NULL, 0, height); |
137 | 76 |
138 // Top right corner. | 77 // Top right corner. |
(...skipping 19 matching lines...) Expand all Loading... |
158 -M_PI, | 97 -M_PI, |
159 true); | 98 true); |
160 | 99 |
161 // Draw line back to top-left corner. | 100 // Draw line back to top-left corner. |
162 CGPathAddLineToPoint(path, NULL, 0, height); | 101 CGPathAddLineToPoint(path, NULL, 0, height); |
163 CGPathCloseSubpath(path); | 102 CGPathCloseSubpath(path); |
164 return path; | 103 return path; |
165 } | 104 } |
166 | 105 |
167 - (void)updateLayerMask { | 106 - (void)updateLayerMask { |
168 if (fastResizeMode_ || !roundedBottomCorners_) { | 107 if (!roundedBottomCorners_) { |
169 [self layer].mask = nil; | 108 [self layer].mask = nil; |
170 layerMask_ = nil; | 109 layerMask_ = nil; |
171 return; | 110 return; |
172 } | 111 } |
173 | 112 |
174 if (![self layer].mask) { | 113 if (![self layer].mask) { |
175 layerMask_ = [CAShapeLayer layer]; | 114 layerMask_ = [CAShapeLayer layer]; |
176 [self layer].mask = layerMask_; | 115 [self layer].mask = layerMask_; |
177 } | 116 } |
178 | 117 |
179 CGPathRef path = [self createRoundedBottomCornersPath:self.bounds.size]; | 118 CGPathRef path = [self createRoundedBottomCornersPath:self.bounds.size]; |
180 layerMask_.path = path; | 119 layerMask_.path = path; |
181 CGPathRelease(path); | 120 CGPathRelease(path); |
182 } | 121 } |
183 | 122 |
184 @end | 123 @end |
OLD | NEW |