LEFT | RIGHT |
1 // | 1 // |
2 // GTMWindowSheetController.m | 2 // GTMWindowSheetController.m |
3 // | 3 // |
4 // Copyright 2009 Google Inc. | 4 // Copyright 2009 Google Inc. |
5 // | 5 // |
6 // Licensed under the Apache License, Version 2.0 (the "License"); you may not | 6 // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
7 // use this file except in compliance with the License. You may obtain a copy | 7 // use this file except in compliance with the License. You may obtain a copy |
8 // of the License at | 8 // of the License at |
9 // | 9 // |
10 // http://www.apache.org/licenses/LICENSE-2.0 | 10 // http://www.apache.org/licenses/LICENSE-2.0 |
11 // | 11 // |
12 // Unless required by applicable law or agreed to in writing, software | 12 // Unless required by applicable law or agreed to in writing, software |
13 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 13 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
14 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 14 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
15 // License for the specific language governing permissions and limitations unde
r | 15 // License for the specific language governing permissions and limitations unde
r |
16 // the License. | 16 // the License. |
17 // | 17 // |
18 | 18 |
19 #import "GTMWindowSheetController.h" | 19 #import "GTMWindowSheetController.h" |
20 | 20 |
21 #import "DebugUtils/GTMDebugSelectorValidation.h" | 21 #import "DebugUtils/GTMDebugSelectorValidation.h" |
22 #import "GTMDefines.h" | 22 #import "GTMDefines.h" |
23 | 23 |
24 @interface GTMWSCSheetInfo : NSObject { | 24 @interface GTMWSCSheetInfo : NSObject { |
25 @public | 25 @public |
26 __weak NSWindow* overlayWindow_; | 26 __weak NSWindow* overlayWindow_; |
27 | 27 |
28 // selector to call for frame (rectangle) | 28 // selector to call for frame (rectangle) |
29 SEL frameSelector_; | 29 SEL frameSelector_; |
| 30 ·· |
| 31 // selector to call to position sheet |
| 32 SEL positionSelector_; |
30 | 33 |
31 // delegate data | 34 // delegate data |
32 __weak id modalDelegate_; | 35 __weak id modalDelegate_; |
33 SEL didEndSelector_; | 36 SEL didEndSelector_; |
34 void* contextInfo_; | 37 void* contextInfo_; |
35 | 38 |
36 // sheet info | 39 // sheet info |
37 CGFloat sheetAlpha_; | 40 CGFloat sheetAlpha_; |
38 NSRect sheetFrame_; // relative to overlay window | 41 NSSize sheetSize_; |
39 BOOL sheetAutoresizesSubviews_; | 42 BOOL sheetAutoresizesSubviews_; |
40 } | 43 } |
41 @end | 44 @end |
42 | 45 |
43 @implementation GTMWSCSheetInfo | 46 @implementation GTMWSCSheetInfo |
44 @end | 47 @end |
45 | 48 |
46 // The information about how to call up various AppKit-implemented sheets | 49 // The information about how to call up various AppKit-implemented sheets |
47 | 50 |
48 struct GTMWSCSystemSheetInfo { | 51 struct GTMWSCSystemSheetInfo { |
49 NSString* className_; | 52 NSString* className_; |
50 NSString* methodSignature_; | 53 NSString* methodSignature_; |
51 NSUInteger modalForWindowIndex_; | 54 NSUInteger modalForWindowIndex_; |
52 NSUInteger modalDelegateIndex_; | 55 NSUInteger modalDelegateIndex_; |
53 NSUInteger didEndSelectorIndex_; | 56 NSUInteger didEndSelectorIndex_; |
54 NSUInteger contextInfoIndex_; | 57 NSUInteger contextInfoIndex_; |
55 // Callbacks invariably take three parameters. The first is always an id, the | 58 // Callbacks invariably take three parameters. The first is always an id, the |
56 // third always a void*, but the second can be a BOOL (8 bits), an int (32 | 59 // third always a void*, but the second can be a BOOL (8 bits), an int (32 |
57 // bits), or an id or NSInteger (64 bits in 64 bit mode). This is the size of | 60 // bits), or an id or NSInteger (64 bits in 64 bit mode). This is the size of |
58 // the argument in 64-bit mode. | 61 // the argument in 64-bit mode. |
59 NSUInteger arg1OfEndSelectorSize_; | 62 NSUInteger arg1OfEndSelectorSize_; |
60 }; | 63 }; |
61 | 64 |
62 @interface GTMWindowSheetController (PrivateMethods) | 65 @interface GTMWindowSheetController (PrivateMethods) |
63 - (void)beginSystemSheet:(id)systemSheet | 66 - (void)beginSystemSheet:(id)systemSheet |
64 withInfo:(const struct GTMWSCSystemSheetInfo*)info | 67 withInfo:(const struct GTMWSCSystemSheetInfo*)info |
65 modalForView:(NSView*)view | 68 modalForView:(NSView*)view |
66 frameSelector:(SEL)frameSelector | 69 frameSelector:(SEL)frameSelector |
| 70 positionSelector:(SEL)positionSelector |
67 withParameters:(NSArray*)params; | 71 withParameters:(NSArray*)params; |
68 - (const struct GTMWSCSystemSheetInfo*)infoForSheet:(id)systemSheet; | 72 - (const struct GTMWSCSystemSheetInfo*)infoForSheet:(id)systemSheet; |
69 - (void)notificationHappened:(NSNotification*)notification; | 73 - (void)notificationHappened:(NSNotification*)notification; |
70 - (void)viewDidChangeSize:(NSView*)view; | 74 - (void)viewDidChangeSize:(NSView*)view; |
71 - (NSRect)screenFrameOfView:(NSView*)view | 75 - (NSRect)screenFrameOfView:(NSView*)view |
72 frameSelector:(SEL)frameSelector; | 76 frameSelector:(SEL)frameSelector; |
73 - (void)sheetDidEnd:(id)sheet | 77 - (void)sheetDidEnd:(id)sheet |
74 returnCode8:(char)returnCode | 78 returnCode8:(char)returnCode |
75 contextInfo:(void*)contextInfo; | 79 contextInfo:(void*)contextInfo; |
76 - (void)sheetDidEnd:(id)sheet | 80 - (void)sheetDidEnd:(id)sheet |
77 returnCode32:(int)returnCode | 81 returnCode32:(int)returnCode |
78 contextInfo:(void*)contextInfo; | 82 contextInfo:(void*)contextInfo; |
79 - (void)sheetDidEnd:(id)sheet | 83 - (void)sheetDidEnd:(id)sheet |
80 returnCode64:(NSInteger)returnCode | 84 returnCode64:(NSInteger)returnCode |
81 contextInfo:(void*)contextInfo; | 85 contextInfo:(void*)contextInfo; |
82 - (void)sheetDidEnd:(id)sheet | 86 - (void)sheetDidEnd:(id)sheet |
83 returnCode:(NSInteger)returnCode | 87 returnCode:(NSInteger)returnCode |
84 contextInfo:(void*)contextInfo | 88 contextInfo:(void*)contextInfo |
85 arg1Size:(int)size; | 89 arg1Size:(int)size; |
86 - (void)systemRequestsVisibilityForWindow:(NSWindow*)window; | 90 - (void)systemRequestsVisibilityForWindow:(NSWindow*)window; |
87 - (NSRect)window:(NSWindow*)window | 91 - (NSRect)window:(NSWindow*)window |
88 willPositionSheet:(NSWindow*)sheet | 92 willPositionSheet:(NSWindow*)sheet |
89 usingRect:(NSRect)defaultSheetRect; | 93 usingRect:(NSRect)defaultSheetRect; |
| 94 - (NSRect)callPositionSelector:(SEL)positionSelector |
| 95 onView:(NSView*)view |
| 96 withSheet:(NSWindow*)sheet |
| 97 andRect:(NSRect)rect; |
| 98 - (void)positionSheet:(NSWindow*)sheet |
| 99 withSize:(NSSize)size |
| 100 inView:(NSView*)view |
| 101 overlayWindow:(NSWindow*)overlayWindow; |
90 @end | 102 @end |
91 | 103 |
92 @interface GTMWSCOverlayWindow : NSWindow { | 104 @interface GTMWSCOverlayWindow : NSWindow { |
93 GTMWindowSheetController* sheetController_; | 105 GTMWindowSheetController* sheetController_; |
94 } | 106 } |
95 | 107 |
96 - (id)initWithContentRect:(NSRect)contentRect | 108 - (id)initWithContentRect:(NSRect)contentRect |
97 sheetController:(GTMWindowSheetController*)sheetController; | 109 sheetController:(GTMWindowSheetController*)sheetController; |
98 - (void)makeKeyAndOrderFront:(id)sender; | 110 - (void)makeKeyAndOrderFront:(id)sender; |
99 | 111 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 contextInfo:(void*)contextInfo { | 172 contextInfo:(void*)contextInfo { |
161 NSArray* params = | 173 NSArray* params = |
162 [NSArray arrayWithObjects:sheet, | 174 [NSArray arrayWithObjects:sheet, |
163 [NSNull null], | 175 [NSNull null], |
164 modalDelegate, | 176 modalDelegate, |
165 [NSValue valueWithPointer:didEndSelector], | 177 [NSValue valueWithPointer:didEndSelector], |
166 [NSValue valueWithPointer:contextInfo], | 178 [NSValue valueWithPointer:contextInfo], |
167 nil]; | 179 nil]; |
168 [self beginSystemSheet:[NSApplication sharedApplication] | 180 [self beginSystemSheet:[NSApplication sharedApplication] |
169 modalForView:view | 181 modalForView:view |
170 frameSelector:@selector(frame) | 182 frameSelector:nil |
| 183 positionSelector:nil |
171 withParameters:params]; | 184 withParameters:params]; |
172 } | 185 } |
173 | 186 |
174 - (void)beginSheet:(NSWindow*)sheet | 187 - (void)beginSheet:(NSWindow*)sheet |
175 modalForView:(NSView*)view | 188 modalForView:(NSView*)view |
176 frameSelector:(SEL)frameSelector | 189 frameSelector:(SEL)frameSelector |
| 190 positionSelector:(SEL)positionSelector |
177 modalDelegate:(id)modalDelegate | 191 modalDelegate:(id)modalDelegate |
178 didEndSelector:(SEL)didEndSelector | 192 didEndSelector:(SEL)didEndSelector |
179 contextInfo:(void *)contextInfo { | 193 contextInfo:(void *)contextInfo { |
180 NSArray* params = | 194 NSArray* params = |
181 [NSArray arrayWithObjects:sheet, | 195 [NSArray arrayWithObjects:sheet, |
182 [NSNull null], | 196 [NSNull null], |
183 modalDelegate, | 197 modalDelegate, |
184 [NSValue valueWithPointer:didEndSelector], | 198 [NSValue valueWithPointer:didEndSelector], |
185 [NSValue valueWithPointer:contextInfo], | 199 [NSValue valueWithPointer:contextInfo], |
186 nil]; | 200 nil]; |
187 [self beginSystemSheet:[NSApplication sharedApplication] | 201 [self beginSystemSheet:[NSApplication sharedApplication] |
188 modalForView:view | 202 modalForView:view |
189 frameSelector:frameSelector | 203 frameSelector:frameSelector |
| 204 positionSelector:positionSelector |
190 withParameters:params]; | 205 withParameters:params]; |
191 } | 206 } |
192 | 207 |
193 - (void)beginSystemSheet:(id)systemSheet | 208 - (void)beginSystemSheet:(id)systemSheet |
194 modalForView:(NSView*)view | 209 modalForView:(NSView*)view |
195 withParameters:(NSArray*)params { | 210 withParameters:(NSArray*)params { |
196 const struct GTMWSCSystemSheetInfo* info = [self infoForSheet:systemSheet]; | 211 const struct GTMWSCSystemSheetInfo* info = [self infoForSheet:systemSheet]; |
197 if (info) { | 212 if (info) { |
198 [self beginSystemSheet:systemSheet | 213 [self beginSystemSheet:systemSheet |
199 withInfo:info | 214 withInfo:info |
200 modalForView:view | 215 modalForView:view |
201 frameSelector:@selector(frame) | 216 frameSelector:nil |
| 217 positionSelector:nil |
202 withParameters:params]; | 218 withParameters:params]; |
203 } // else already logged | 219 } // else already logged |
204 } | 220 } |
205 | 221 |
206 - (void)beginSystemSheet:(id)systemSheet | 222 - (void)beginSystemSheet:(id)systemSheet |
207 modalForView:(NSView*)view | 223 modalForView:(NSView*)view |
208 frameSelector:(SEL)frameSelector | 224 frameSelector:(SEL)frameSelector |
| 225 positionSelector:(SEL)positionSelector |
209 withParameters:(NSArray*)params { | 226 withParameters:(NSArray*)params { |
210 const struct GTMWSCSystemSheetInfo* info = [self infoForSheet:systemSheet]; | 227 const struct GTMWSCSystemSheetInfo* info = [self infoForSheet:systemSheet]; |
211 if (info) { | 228 if (info) { |
212 [self beginSystemSheet:systemSheet | 229 [self beginSystemSheet:systemSheet |
213 withInfo:info | 230 withInfo:info |
214 modalForView:view | 231 modalForView:view |
215 frameSelector:frameSelector | 232 frameSelector:frameSelector |
| 233 positionSelector:positionSelector |
216 withParameters:params]; | 234 withParameters:params]; |
217 } // else already logged | 235 } // else already logged |
218 } | 236 } |
219 | 237 |
220 | 238 |
221 - (BOOL)isSheetAttachedToView:(NSView*)view { | 239 - (BOOL)isSheetAttachedToView:(NSView*)view { |
222 NSValue* viewValue = [NSValue valueWithNonretainedObject:view]; | 240 NSValue* viewValue = [NSValue valueWithNonretainedObject:view]; |
223 return [sheets_ objectForKey:viewValue] != nil; | 241 return [sheets_ objectForKey:viewValue] != nil; |
224 } | 242 } |
225 | 243 |
(...skipping 22 matching lines...) Expand all Loading... |
248 // - Keeping it local but alpha 0 means we get good Expose behavior | 266 // - Keeping it local but alpha 0 means we get good Expose behavior |
249 // - Resizing it to 0 means we get no blurring effect left over | 267 // - Resizing it to 0 means we get no blurring effect left over |
250 | 268 |
251 oldSheetInfo->sheetAlpha_ = [sheetWindow alphaValue]; | 269 oldSheetInfo->sheetAlpha_ = [sheetWindow alphaValue]; |
252 [sheetWindow setAlphaValue:(CGFloat)0.0]; | 270 [sheetWindow setAlphaValue:(CGFloat)0.0]; |
253 | 271 |
254 oldSheetInfo->sheetAutoresizesSubviews_ = | 272 oldSheetInfo->sheetAutoresizesSubviews_ = |
255 [[sheetWindow contentView] autoresizesSubviews]; | 273 [[sheetWindow contentView] autoresizesSubviews]; |
256 [[sheetWindow contentView] setAutoresizesSubviews:NO]; | 274 [[sheetWindow contentView] setAutoresizesSubviews:NO]; |
257 | 275 |
258 NSRect overlayFrame = [overlayWindow frame]; | 276 // Save the size of the sheet and resize to zero. |
259 oldSheetInfo->sheetFrame_ = [sheetWindow frame]; | 277 oldSheetInfo->sheetSize_ = [sheetWindow frame].size; |
260 oldSheetInfo->sheetFrame_.origin.x -= overlayFrame.origin.x; | |
261 oldSheetInfo->sheetFrame_.origin.y -= overlayFrame.origin.y; | |
262 [sheetWindow setFrame:NSZeroRect display:NO]; | 278 [sheetWindow setFrame:NSZeroRect display:NO]; |
263 | 279 |
264 [overlayWindow setIgnoresMouseEvents:YES]; | 280 [overlayWindow setIgnoresMouseEvents:YES]; |
265 | 281 |
266 // Make sure the now invisible sheet doesn't keep keyboard focus | 282 // Make sure the now invisible sheet doesn't keep keyboard focus |
267 [[overlayWindow parentWindow] makeKeyWindow]; | 283 [[overlayWindow parentWindow] makeKeyWindow]; |
268 } | 284 } |
269 | 285 |
270 activeView_ = view; | 286 activeView_ = view; |
271 | 287 |
272 // Show new sheet | 288 // Show new sheet |
273 | 289 |
274 NSValue* newViewValue = [NSValue valueWithNonretainedObject:view]; | 290 NSValue* newViewValue = [NSValue valueWithNonretainedObject:view]; |
275 GTMWSCSheetInfo* newSheetInfo = [sheets_ objectForKey:newViewValue]; | 291 GTMWSCSheetInfo* newSheetInfo = [sheets_ objectForKey:newViewValue]; |
276 if (newSheetInfo) { | 292 if (newSheetInfo) { |
277 NSWindow* overlayWindow = newSheetInfo->overlayWindow_; | 293 NSWindow* overlayWindow = newSheetInfo->overlayWindow_; |
278 _GTMDevAssert(overlayWindow, @"New sheet info has no overlay window"); | 294 _GTMDevAssert(overlayWindow, @"New sheet info has no overlay window"); |
279 NSWindow* sheetWindow = [overlayWindow attachedSheet]; | 295 NSWindow* sheetWindow = [overlayWindow attachedSheet]; |
280 _GTMDevAssert(sheetWindow, @"New sheet info has no active sheet"); | 296 _GTMDevAssert(sheetWindow, @"New sheet info has no active sheet"); |
281 | 297 |
282 [overlayWindow setIgnoresMouseEvents:NO]; | 298 [overlayWindow setIgnoresMouseEvents:NO]; |
283 | 299 |
284 NSRect overlayFrame = [overlayWindow frame]; | 300 // We need to give the view the opportunity to custom-reposition the sheet. |
285 newSheetInfo->sheetFrame_.origin.x += overlayFrame.origin.x; | 301 [self positionSheet:sheetWindow |
286 newSheetInfo->sheetFrame_.origin.y += overlayFrame.origin.y; | 302 withSize:newSheetInfo->sheetSize_ |
287 [sheetWindow setFrame:newSheetInfo->sheetFrame_ display:NO]; | 303 inView:view |
| 304 overlayWindow:overlayWindow]; |
288 | 305 |
289 [[sheetWindow contentView] | 306 [[sheetWindow contentView] |
290 setAutoresizesSubviews:newSheetInfo->sheetAutoresizesSubviews_]; | 307 setAutoresizesSubviews:newSheetInfo->sheetAutoresizesSubviews_]; |
291 | 308 |
292 [sheetWindow setAlphaValue:newSheetInfo->sheetAlpha_]; | 309 [sheetWindow setAlphaValue:newSheetInfo->sheetAlpha_]; |
293 | 310 |
294 [self viewDidChangeSize:view]; | 311 [self viewDidChangeSize:view]; |
295 | 312 |
296 [overlayWindow makeKeyWindow]; | 313 [overlayWindow makeKeyWindow]; |
297 } | 314 } |
298 } | 315 } |
299 | 316 |
300 @end | 317 @end |
301 | 318 |
302 @implementation GTMWindowSheetController (PrivateMethods) | 319 @implementation GTMWindowSheetController (PrivateMethods) |
303 | 320 |
304 - (void)beginSystemSheet:(id)systemSheet | 321 - (void)beginSystemSheet:(id)systemSheet |
305 withInfo:(const struct GTMWSCSystemSheetInfo*)info | 322 withInfo:(const struct GTMWSCSystemSheetInfo*)info |
306 modalForView:(NSView*)view | 323 modalForView:(NSView*)view |
307 frameSelector:(SEL)frameSelector | 324 frameSelector:(SEL)frameSelector |
| 325 positionSelector:(SEL)positionSelector |
308 withParameters:(NSArray*)params { | 326 withParameters:(NSArray*)params { |
309 _GTMDevAssert([view window] == window_, | 327 _GTMDevAssert([view window] == window_, |
310 @"Cannot show a sheet for a window for which we are not " | 328 @"Cannot show a sheet for a window for which we are not " |
311 @"managing sheets"); | 329 @"managing sheets"); |
312 _GTMDevAssert(![self isSheetAttachedToView:view], | 330 _GTMDevAssert(![self isSheetAttachedToView:view], |
313 @"Cannot show another sheet for a view while already managing " | 331 @"Cannot show another sheet for a view while already managing " |
314 @"one"); | 332 @"one"); |
315 _GTMDevAssert(frameSelector, | |
316 @"Frame selector not provided"); | |
317 GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments( | 333 GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments( |
318 view, frameSelector, @encode(NSRect), NULL); | 334 view, frameSelector, @encode(NSRect), NULL); |
| 335 GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments( |
| 336 view, positionSelector, @encode(NSRect), @encode(NSWindow*), |
| 337 @encode(NSRect), NULL); |
319 _GTMDevAssert(info, @"Missing info for the type of sheet"); | 338 _GTMDevAssert(info, @"Missing info for the type of sheet"); |
320 | 339 |
321 GTMWSCSheetInfo* sheetInfo = [[[GTMWSCSheetInfo alloc] init] autorelease]; | 340 GTMWSCSheetInfo* sheetInfo = [[[GTMWSCSheetInfo alloc] init] autorelease]; |
322 | 341 |
323 sheetInfo->frameSelector_ = frameSelector; | 342 sheetInfo->frameSelector_ = frameSelector ? frameSelector : @selector(frame); |
| 343 sheetInfo->positionSelector_ = positionSelector; |
324 sheetInfo->modalDelegate_ = [params objectAtIndex:info->modalDelegateIndex_]; | 344 sheetInfo->modalDelegate_ = [params objectAtIndex:info->modalDelegateIndex_]; |
325 sheetInfo->didEndSelector_ = | 345 sheetInfo->didEndSelector_ = |
326 [[params objectAtIndex:info->didEndSelectorIndex_] pointerValue]; | 346 [[params objectAtIndex:info->didEndSelectorIndex_] pointerValue]; |
327 sheetInfo->contextInfo_ = | 347 sheetInfo->contextInfo_ = |
328 [[params objectAtIndex:info->contextInfoIndex_] pointerValue]; | 348 [[params objectAtIndex:info->contextInfoIndex_] pointerValue]; |
329 | 349 |
330 GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments( | 350 GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments( |
331 sheetInfo->modalDelegate_, sheetInfo->didEndSelector_, | 351 sheetInfo->modalDelegate_, sheetInfo->didEndSelector_, |
332 @encode(void), @encode(NSWindow*), @encode(NSInteger), @encode(void*), | 352 @encode(void), @encode(NSWindow*), @encode(NSInteger), @encode(void*), |
333 NULL); | 353 NULL); |
334 | 354 |
335 [view setPostsFrameChangedNotifications:YES]; | 355 [view setPostsFrameChangedNotifications:YES]; |
336 [[NSNotificationCenter defaultCenter] | 356 [[NSNotificationCenter defaultCenter] |
337 addObserver:self | 357 addObserver:self |
338 selector:@selector(notificationHappened:) | 358 selector:@selector(notificationHappened:) |
339 name:NSViewFrameDidChangeNotification | 359 name:NSViewFrameDidChangeNotification |
340 object:view]; | 360 object:view]; |
341 | 361 |
342 sheetInfo->overlayWindow_ = | 362 sheetInfo->overlayWindow_ = |
343 [[GTMWSCOverlayWindow alloc] | 363 [[GTMWSCOverlayWindow alloc] |
344 initWithContentRect:[self screenFrameOfView:view | 364 initWithContentRect:[self screenFrameOfView:view |
345 frameSelector:frameSelector] | 365 frameSelector:sheetInfo->frameSelector_] |
346 sheetController:self]; | 366 sheetController:self]; |
| 367 // -window:willPositionSheet:usingRect is a delegate method. |
| 368 [sheetInfo->overlayWindow_ setDelegate:self]; |
347 | 369 |
348 [sheets_ setObject:sheetInfo | 370 [sheets_ setObject:sheetInfo |
349 forKey:[NSValue valueWithNonretainedObject:view]]; | 371 forKey:[NSValue valueWithNonretainedObject:view]]; |
350 | 372 |
351 [window_ addChildWindow:sheetInfo->overlayWindow_ | 373 [window_ addChildWindow:sheetInfo->overlayWindow_ |
352 ordered:NSWindowAbove]; | 374 ordered:NSWindowAbove]; |
353 | 375 |
354 SEL methodSelector = NSSelectorFromString((NSString*)info->methodSignature_); | 376 SEL methodSelector = NSSelectorFromString((NSString*)info->methodSignature_); |
355 NSInvocation* invocation = | 377 NSInvocation* invocation = |
356 [NSInvocation invocationWithMethodSignature: | 378 [NSInvocation invocationWithMethodSignature: |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 if (sheetInfo->overlayWindow_ == window) { | 648 if (sheetInfo->overlayWindow_ == window) { |
627 NSView* view = [key nonretainedObjectValue]; | 649 NSView* view = [key nonretainedObjectValue]; |
628 [delegate_ gtm_systemRequestsVisibilityForView:view]; | 650 [delegate_ gtm_systemRequestsVisibilityForView:view]; |
629 } | 651 } |
630 } | 652 } |
631 } | 653 } |
632 | 654 |
633 - (NSRect)window:(NSWindow*)window | 655 - (NSRect)window:(NSWindow*)window |
634 willPositionSheet:(NSWindow*)sheet | 656 willPositionSheet:(NSWindow*)sheet |
635 usingRect:(NSRect)defaultSheetRect { | 657 usingRect:(NSRect)defaultSheetRect { |
636 // Ensure that the sheets come out of the very top of the overlay windows. | 658 // By default, sheets already come out of the very top of the overlay windows. |
637 NSRect windowFrame = [window frame]; | 659 // We need to map (overlay window) -> (view); just search for it. |
638 defaultSheetRect.origin.y = windowFrame.size.height; | 660 NSValue* key; |
| 661 GTM_FOREACH_KEY(key, sheets_) { |
| 662 GTMWSCSheetInfo* sheetInfo = [sheets_ objectForKey:key]; |
| 663 if (sheetInfo->overlayWindow_ == window) { |
| 664 // Found it! |
| 665 defaultSheetRect = [self callPositionSelector:sheetInfo->positionSelector_ |
| 666 onView:[key nonretainedObjectValue] |
| 667 withSheet:sheet |
| 668 andRect:defaultSheetRect]; |
| 669 |
| 670 // We found our view, so we should stop. |
| 671 break; |
| 672 } |
| 673 } |
| 674 |
639 return defaultSheetRect; | 675 return defaultSheetRect; |
640 } | 676 } |
641 | 677 |
| 678 // If |positionSelector| is nil, this just passes |rect| through. |
| 679 - (NSRect)callPositionSelector:(SEL)positionSelector |
| 680 onView:(NSView*)view |
| 681 withSheet:(NSWindow*)sheet |
| 682 andRect:(NSRect)rect { |
| 683 // If we have a position selector, call it. |
| 684 if (positionSelector) { |
| 685 // Call the |positionSelector| (double whew) and get the rectangle. |
| 686 NSInvocation* invocation = |
| 687 [NSInvocation invocationWithMethodSignature: |
| 688 [view methodSignatureForSelector:positionSelector]]; |
| 689 [invocation setSelector:positionSelector]; |
| 690 // Remember that args 0 and 1 are the target and selector |
| 691 [invocation setArgument:&sheet atIndex:2]; |
| 692 [invocation setArgument:&rect atIndex:3]; |
| 693 [invocation invokeWithTarget:view]; |
| 694 [invocation getReturnValue:&rect]; |
| 695 } |
| 696 return rect; |
| 697 } |
| 698 |
| 699 - (void)positionSheet:(NSWindow*)sheet |
| 700 withSize:(NSSize)size |
| 701 inView:(NSView*)view |
| 702 overlayWindow:(NSWindow*)overlayWindow { |
| 703 NSRect overlayFrame = [overlayWindow frame]; |
| 704 |
| 705 // Make a |-window:willPositionSheet:usingRect:|-style "rectangle" so we can |
| 706 // call our position selector (if we have one). |
| 707 NSRect defaultRect; |
| 708 defaultRect.origin.x = 0.0; |
| 709 defaultRect.origin.y = overlayFrame.size.height; |
| 710 defaultRect.size.width = overlayFrame.size.width; |
| 711 defaultRect.size.height = 0.0; |
| 712 |
| 713 NSValue* viewValue = [NSValue valueWithNonretainedObject:view]; |
| 714 GTMWSCSheetInfo* sheetInfo = [sheets_ objectForKey:viewValue]; |
| 715 defaultRect = [self callPositionSelector:sheetInfo->positionSelector_ |
| 716 onView:view |
| 717 withSheet:sheet |
| 718 andRect:defaultRect]; |
| 719 |
| 720 // Now |defaultRect.origin.y| is the top, and we horizontally center relative |
| 721 // to |defaultRect.origin.x| and |defaultRect.size.width|. |
| 722 // We need only calculate the origin. |
| 723 NSRect newFrame; |
| 724 newFrame.size = size; |
| 725 // Calculate the origin as indicated above. |
| 726 newFrame.origin.x = overlayFrame.origin.x |
| 727 + defaultRect.origin.x + defaultRect.size.width/2.0 |
| 728 - size.width/2.0; |
| 729 newFrame.origin.y = overlayFrame.origin.y |
| 730 + defaultRect.origin.y - size.height; |
| 731 |
| 732 // And set it. |
| 733 [sheet setFrame:newFrame display:NO]; |
| 734 } |
| 735 |
642 @end | 736 @end |
LEFT | RIGHT |