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

Side by Side Diff: chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm

Issue 10870094: Constrained window sheet controller (test patch) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rename Created 8 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_con troller.h"
6
7 #include <map>
8
9 #include "base/logging.h"
10 #include "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_in fo.h"
11 #include "chrome/browser/ui/cocoa/constrained_window/constrained_window_animatio n.h"
12
13 namespace {
14
15 // A list of all sheet controllers.
16 NSMutableArray* g_SheetControllers;
17
18 } // namespace
19
20 // An invisible overlay window placed on top of the sheet's parent view.
21 // This window blocks interaction with the underlying view.
22 @interface CWSheetOverlayWindow : NSWindow {
23 scoped_nsobject<ConstrainedWindowSheetController> controller_;
24 }
25 @end
26
27 @interface ConstrainedWindowSheetController ()
28 - (id)initWithParentWindow:(NSWindow*)parentWindow;
29 - (ConstrainedWindowSheetInfo*)findSheetInfoForParentView:(NSView*)parentView;
30 - (ConstrainedWindowSheetInfo*)findSheetInfoForSheet:(NSWindow*)sheet;
31 - (void)onParentWindowWillClose:(NSNotification*)note;
32 - (void)onParentViewFrameDidChange:(NSNotification*)note;
33 - (void)updateSheetPosition:(NSView*)parentView;
34 - (NSRect)overlayWindowFrameForParentView:(NSView*)parentView;
35 - (NSPoint)originForSheet:(NSWindow*)sheet
36 inContainerRect:(NSRect)containerRect;
37 - (void)onOveralyWindowMouseDown:(CWSheetOverlayWindow*)overlayWindow;
38 - (void)animationDidEnd:(NSAnimation*)animation;
39 - (void)closeSheetWithoutAnimation:(ConstrainedWindowSheetInfo*)info;
40 @end
41
42 @implementation CWSheetOverlayWindow
43
44 - (id)initWithContentRect:(NSRect)rect
45 controller:(ConstrainedWindowSheetController*)controller {
46 if ((self = [super initWithContentRect:rect
47 styleMask:NSBorderlessWindowMask
48 backing:NSBackingStoreBuffered
49 defer:NO])) {
50 [self setOpaque:NO];
51 [self setBackgroundColor:[NSColor clearColor]];
52 [self setIgnoresMouseEvents:NO];
53 [self setReleasedWhenClosed:NO];
54 controller_.reset([controller retain]);
55 }
56 return self;
57 }
58
59 - (void)mouseDown:(NSEvent*)event {
60 [controller_ onOveralyWindowMouseDown:self];
61 }
62
63 @end
64
65 @implementation ConstrainedWindowSheetController
66
67 + (ConstrainedWindowSheetController*)
68 controllerForParentWindow:(NSWindow*)parentWindow {
69 DCHECK(parentWindow);
70 for (ConstrainedWindowSheetController* controller in g_SheetControllers) {
71 if ([parentWindow isEqual:controller->parentWindow_])
72 return controller;
73 }
74
75 scoped_nsobject<ConstrainedWindowSheetController> controller(
76 [[ConstrainedWindowSheetController alloc]
77 initWithParentWindow:parentWindow]);
78 if (!g_SheetControllers)
79 g_SheetControllers = [[NSMutableArray alloc] init];
80 [g_SheetControllers addObject:controller];
81 return controller;
82 }
83
84 + (ConstrainedWindowSheetController*)controllerForSheet:(NSWindow*)sheet {
85 for (ConstrainedWindowSheetController* controller in g_SheetControllers) {
86 if ([controller findSheetInfoForSheet:sheet])
87 return controller;
88 }
89 return nil;
90 }
91
92 - (void)showSheet:(NSWindow*)sheet
93 forParentView:(NSView*)parentView {
94 DCHECK(sheet);
95 DCHECK(parentView);
96 if (!activeView_.get())
97 activeView_.reset([parentView retain]);
98
99 NSRect rect = [self overlayWindowFrameForParentView:parentView];
100 scoped_nsobject<NSWindow> overlayWindow(
101 [[CWSheetOverlayWindow alloc] initWithContentRect:rect
102 controller:self]);
103 [sheet setFrameOrigin:[self originForSheet:sheet inContainerRect:rect]];
104
105 scoped_nsobject<ConstrainedWindowSheetInfo> info(
106 [[ConstrainedWindowSheetInfo alloc] initWithSheet:sheet
107 parentView:parentView
108 overlayWindow:overlayWindow]);
109 [sheets_ addObject:info];
110 if (![activeView_ isEqual:parentView]) {
111 [info hideSheet];
112 } else {
113 scoped_nsobject<NSAnimation> animation(
114 [[ConstrainedWindowAnimationShow alloc] initWithWindow:sheet]);
115 [info setAnimation:animation];
116 [animation startAnimation];
117 }
118
119 [parentWindow_ addChildWindow:overlayWindow
120 ordered:NSWindowAbove];
121 [overlayWindow addChildWindow:sheet
122 ordered:NSWindowAbove];
123
124 [parentView setPostsFrameChangedNotifications:YES];
125 [[NSNotificationCenter defaultCenter]
126 addObserver:self
127 selector:@selector(onParentViewFrameDidChange:)
128 name:NSViewFrameDidChangeNotification
129 object:parentView];
130 }
131
132 - (void)closeSheet:(NSWindow*)sheet {
133 ConstrainedWindowSheetInfo* info = [self findSheetInfoForSheet:sheet];
134 DCHECK(info);
135
136 if (![activeView_ isEqual:[info parentView]]) {
137 [self closeSheetWithoutAnimation:info];
138 return;
139 }
140
141 scoped_nsobject<NSAnimation> animation(
142 [[ConstrainedWindowAnimationHide alloc] initWithWindow:sheet]);
143 [animation setDelegate:self];
144 [info setAnimation:animation];
145 [animation startAnimation];
146 }
147
148
149 - (void)parentViewDidBecomeActive:(NSView*)parentView {
150 [[self findSheetInfoForParentView:activeView_] hideSheet];
151 activeView_.reset([parentView retain]);
152 [[self findSheetInfoForParentView:activeView_] showSheet];
153 }
154
155 - (int)sheetCount {
156 return [sheets_ count];
157 }
158
159 - (void)endAnimationForSheet:(NSWindow*)sheet {
160 [[[self findSheetInfoForSheet:sheet] animation] stopAnimation];
161 }
162
163 - (id)initWithParentWindow:(NSWindow*)parentWindow {
164 if ((self = [super init])) {
165 parentWindow_.reset([parentWindow retain]);
166 sheets_.reset([[NSMutableArray alloc] init]);
167
168 [[NSNotificationCenter defaultCenter]
169 addObserver:self
170 selector:@selector(onParentWindowWillClose:)
171 name:NSWindowWillCloseNotification
172 object:parentWindow_];
173 }
174 return self;
175 }
176
177 - (ConstrainedWindowSheetInfo*)findSheetInfoForParentView:(NSView*)parentView {
178 for (ConstrainedWindowSheetInfo* info in sheets_.get()) {
179 if ([parentView isEqual:[info parentView]])
180 return info;
181 }
182 return NULL;
183 }
184
185 - (ConstrainedWindowSheetInfo*)findSheetInfoForSheet:(NSWindow*)sheet {
186 for (ConstrainedWindowSheetInfo* info in sheets_.get()) {
187 if ([sheet isEqual:[info sheet]])
188 return info;
189 }
190 return NULL;
191 }
192
193 - (void)onParentWindowWillClose:(NSNotification*)note {
194 [[NSNotificationCenter defaultCenter]
195 removeObserver:self
196 name:NSWindowWillCloseNotification
197 object:parentWindow_];
198
199 // Close all sheets.
200 NSArray* sheets = [NSArray arrayWithArray:sheets_];
201 for (ConstrainedWindowSheetInfo* info in sheets)
202 [self closeSheetWithoutAnimation:info];
203
204 // Delete this instance.
205 [g_SheetControllers removeObject:self];
206 if (![g_SheetControllers count]) {
207 [g_SheetControllers release];
208 g_SheetControllers = nil;
209 }
210 }
211
212 - (void)onParentViewFrameDidChange:(NSNotification*)note {
213 [self updateSheetPosition:[note object]];
214 }
215
216 - (void)updateSheetPosition:(NSView*)parentView {
217 if (![activeView_ isEqual:parentView])
218 return;
219 ConstrainedWindowSheetInfo* info =
220 [self findSheetInfoForParentView:parentView];
221 DCHECK(info);
222 NSRect rect = [self overlayWindowFrameForParentView:parentView];
223 [[info overlayWindow] setFrame:rect display:YES];
224 [[info sheet] setFrameOrigin:[self originForSheet:[info sheet]
225 inContainerRect:rect]];
226 }
227
228 - (NSRect)overlayWindowFrameForParentView:(NSView*)parentView {
229 NSRect viewFrame = [parentView frame];
230 viewFrame = [[parentView superview] convertRect:viewFrame toView:nil];
231 viewFrame.origin = [[parentView window] convertBaseToScreen:viewFrame.origin];
232 return viewFrame;
233 }
234
235 - (NSPoint)originForSheet:(NSWindow*)sheet
236 inContainerRect:(NSRect)containerRect {
237 NSSize sheetSize = [sheet frame].size;
238 NSPoint origin;
239 origin.x =
240 NSMinX(containerRect) + (NSWidth(containerRect) - sheetSize.width) / 2.0;
241 origin.y = NSMaxY(containerRect) + 5 - sheetSize.height;
242 return origin;
243 }
244
245 - (void)onOveralyWindowMouseDown:(CWSheetOverlayWindow*)overlayWindow {
246 ConstrainedWindowSheetInfo* info = nil;
247 for (ConstrainedWindowSheetInfo* curInfo in sheets_.get()) {
248 if ([overlayWindow isEqual:[curInfo overlayWindow]]) {
249 info = curInfo;
250 break;
251 }
252 }
253 DCHECK(info);
254 if ([[info animation] isAnimating])
255 return;
256
257 scoped_nsobject<NSAnimation> animation(
258 [[ConstrainedWindowAnimationPulse alloc] initWithWindow:[info sheet]]);
259 [info setAnimation:animation];
260 [animation startAnimation];
261 }
262
263 - (void)animationDidEnd:(NSAnimation*)animation {
264 ConstrainedWindowSheetInfo* info = nil;
265 for (ConstrainedWindowSheetInfo* curInfo in sheets_.get()) {
266 if ([animation isEqual:[curInfo animation]]) {
267 info = curInfo;
268 break;
269 }
270 }
271 DCHECK(info);
272
273 // To avoid reentrancy close the sheet in the next event cycle.
274 [self performSelector:@selector(closeSheetWithoutAnimation:)
275 withObject:info
276 afterDelay:0];
277 }
278
279 - (void)closeSheetWithoutAnimation:(ConstrainedWindowSheetInfo*)info {
280 if (![sheets_ containsObject:info])
281 return;
282
283 [[NSNotificationCenter defaultCenter]
284 removeObserver:self
285 name:NSViewFrameDidChangeNotification
286 object:[info parentView]];
287
288 [[info animation] stopAnimation];
289 [parentWindow_ removeChildWindow:[info overlayWindow]];
290 [[info overlayWindow] removeChildWindow:[info sheet]];
291 [[info sheet] close];
292 [[info overlayWindow] close];
293 [sheets_ removeObject:info];
294 }
295
296 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698