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

Unified 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, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..9c53891918d2377a3a9c6cc486b8fb32c999e1ed
--- /dev/null
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm
@@ -0,0 +1,296 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_info.h"
+#include "chrome/browser/ui/cocoa/constrained_window/constrained_window_animation.h"
+
+namespace {
+
+// A list of all sheet controllers.
+NSMutableArray* g_SheetControllers;
+
+} // namespace
+
+// An invisible overlay window placed on top of the sheet's parent view.
+// This window blocks interaction with the underlying view.
+@interface CWSheetOverlayWindow : NSWindow {
+ scoped_nsobject<ConstrainedWindowSheetController> controller_;
+}
+@end
+
+@interface ConstrainedWindowSheetController ()
+- (id)initWithParentWindow:(NSWindow*)parentWindow;
+- (ConstrainedWindowSheetInfo*)findSheetInfoForParentView:(NSView*)parentView;
+- (ConstrainedWindowSheetInfo*)findSheetInfoForSheet:(NSWindow*)sheet;
+- (void)onParentWindowWillClose:(NSNotification*)note;
+- (void)onParentViewFrameDidChange:(NSNotification*)note;
+- (void)updateSheetPosition:(NSView*)parentView;
+- (NSRect)overlayWindowFrameForParentView:(NSView*)parentView;
+- (NSPoint)originForSheet:(NSWindow*)sheet
+ inContainerRect:(NSRect)containerRect;
+- (void)onOveralyWindowMouseDown:(CWSheetOverlayWindow*)overlayWindow;
+- (void)animationDidEnd:(NSAnimation*)animation;
+- (void)closeSheetWithoutAnimation:(ConstrainedWindowSheetInfo*)info;
+@end
+
+@implementation CWSheetOverlayWindow
+
+- (id)initWithContentRect:(NSRect)rect
+ controller:(ConstrainedWindowSheetController*)controller {
+ if ((self = [super initWithContentRect:rect
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO])) {
+ [self setOpaque:NO];
+ [self setBackgroundColor:[NSColor clearColor]];
+ [self setIgnoresMouseEvents:NO];
+ [self setReleasedWhenClosed:NO];
+ controller_.reset([controller retain]);
+ }
+ return self;
+}
+
+- (void)mouseDown:(NSEvent*)event {
+ [controller_ onOveralyWindowMouseDown:self];
+}
+
+@end
+
+@implementation ConstrainedWindowSheetController
+
++ (ConstrainedWindowSheetController*)
+ controllerForParentWindow:(NSWindow*)parentWindow {
+ DCHECK(parentWindow);
+ for (ConstrainedWindowSheetController* controller in g_SheetControllers) {
+ if ([parentWindow isEqual:controller->parentWindow_])
+ return controller;
+ }
+
+ scoped_nsobject<ConstrainedWindowSheetController> controller(
+ [[ConstrainedWindowSheetController alloc]
+ initWithParentWindow:parentWindow]);
+ if (!g_SheetControllers)
+ g_SheetControllers = [[NSMutableArray alloc] init];
+ [g_SheetControllers addObject:controller];
+ return controller;
+}
+
++ (ConstrainedWindowSheetController*)controllerForSheet:(NSWindow*)sheet {
+ for (ConstrainedWindowSheetController* controller in g_SheetControllers) {
+ if ([controller findSheetInfoForSheet:sheet])
+ return controller;
+ }
+ return nil;
+}
+
+- (void)showSheet:(NSWindow*)sheet
+ forParentView:(NSView*)parentView {
+ DCHECK(sheet);
+ DCHECK(parentView);
+ if (!activeView_.get())
+ activeView_.reset([parentView retain]);
+
+ NSRect rect = [self overlayWindowFrameForParentView:parentView];
+ scoped_nsobject<NSWindow> overlayWindow(
+ [[CWSheetOverlayWindow alloc] initWithContentRect:rect
+ controller:self]);
+ [sheet setFrameOrigin:[self originForSheet:sheet inContainerRect:rect]];
+
+ scoped_nsobject<ConstrainedWindowSheetInfo> info(
+ [[ConstrainedWindowSheetInfo alloc] initWithSheet:sheet
+ parentView:parentView
+ overlayWindow:overlayWindow]);
+ [sheets_ addObject:info];
+ if (![activeView_ isEqual:parentView]) {
+ [info hideSheet];
+ } else {
+ scoped_nsobject<NSAnimation> animation(
+ [[ConstrainedWindowAnimationShow alloc] initWithWindow:sheet]);
+ [info setAnimation:animation];
+ [animation startAnimation];
+ }
+
+ [parentWindow_ addChildWindow:overlayWindow
+ ordered:NSWindowAbove];
+ [overlayWindow addChildWindow:sheet
+ ordered:NSWindowAbove];
+
+ [parentView setPostsFrameChangedNotifications:YES];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(onParentViewFrameDidChange:)
+ name:NSViewFrameDidChangeNotification
+ object:parentView];
+}
+
+- (void)closeSheet:(NSWindow*)sheet {
+ ConstrainedWindowSheetInfo* info = [self findSheetInfoForSheet:sheet];
+ DCHECK(info);
+
+ if (![activeView_ isEqual:[info parentView]]) {
+ [self closeSheetWithoutAnimation:info];
+ return;
+ }
+
+ scoped_nsobject<NSAnimation> animation(
+ [[ConstrainedWindowAnimationHide alloc] initWithWindow:sheet]);
+ [animation setDelegate:self];
+ [info setAnimation:animation];
+ [animation startAnimation];
+}
+
+
+- (void)parentViewDidBecomeActive:(NSView*)parentView {
+ [[self findSheetInfoForParentView:activeView_] hideSheet];
+ activeView_.reset([parentView retain]);
+ [[self findSheetInfoForParentView:activeView_] showSheet];
+}
+
+- (int)sheetCount {
+ return [sheets_ count];
+}
+
+- (void)endAnimationForSheet:(NSWindow*)sheet {
+ [[[self findSheetInfoForSheet:sheet] animation] stopAnimation];
+}
+
+- (id)initWithParentWindow:(NSWindow*)parentWindow {
+ if ((self = [super init])) {
+ parentWindow_.reset([parentWindow retain]);
+ sheets_.reset([[NSMutableArray alloc] init]);
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(onParentWindowWillClose:)
+ name:NSWindowWillCloseNotification
+ object:parentWindow_];
+ }
+ return self;
+}
+
+- (ConstrainedWindowSheetInfo*)findSheetInfoForParentView:(NSView*)parentView {
+ for (ConstrainedWindowSheetInfo* info in sheets_.get()) {
+ if ([parentView isEqual:[info parentView]])
+ return info;
+ }
+ return NULL;
+}
+
+- (ConstrainedWindowSheetInfo*)findSheetInfoForSheet:(NSWindow*)sheet {
+ for (ConstrainedWindowSheetInfo* info in sheets_.get()) {
+ if ([sheet isEqual:[info sheet]])
+ return info;
+ }
+ return NULL;
+}
+
+- (void)onParentWindowWillClose:(NSNotification*)note {
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:NSWindowWillCloseNotification
+ object:parentWindow_];
+
+ // Close all sheets.
+ NSArray* sheets = [NSArray arrayWithArray:sheets_];
+ for (ConstrainedWindowSheetInfo* info in sheets)
+ [self closeSheetWithoutAnimation:info];
+
+ // Delete this instance.
+ [g_SheetControllers removeObject:self];
+ if (![g_SheetControllers count]) {
+ [g_SheetControllers release];
+ g_SheetControllers = nil;
+ }
+}
+
+- (void)onParentViewFrameDidChange:(NSNotification*)note {
+ [self updateSheetPosition:[note object]];
+}
+
+- (void)updateSheetPosition:(NSView*)parentView {
+ if (![activeView_ isEqual:parentView])
+ return;
+ ConstrainedWindowSheetInfo* info =
+ [self findSheetInfoForParentView:parentView];
+ DCHECK(info);
+ NSRect rect = [self overlayWindowFrameForParentView:parentView];
+ [[info overlayWindow] setFrame:rect display:YES];
+ [[info sheet] setFrameOrigin:[self originForSheet:[info sheet]
+ inContainerRect:rect]];
+}
+
+- (NSRect)overlayWindowFrameForParentView:(NSView*)parentView {
+ NSRect viewFrame = [parentView frame];
+ viewFrame = [[parentView superview] convertRect:viewFrame toView:nil];
+ viewFrame.origin = [[parentView window] convertBaseToScreen:viewFrame.origin];
+ return viewFrame;
+}
+
+- (NSPoint)originForSheet:(NSWindow*)sheet
+ inContainerRect:(NSRect)containerRect {
+ NSSize sheetSize = [sheet frame].size;
+ NSPoint origin;
+ origin.x =
+ NSMinX(containerRect) + (NSWidth(containerRect) - sheetSize.width) / 2.0;
+ origin.y = NSMaxY(containerRect) + 5 - sheetSize.height;
+ return origin;
+}
+
+- (void)onOveralyWindowMouseDown:(CWSheetOverlayWindow*)overlayWindow {
+ ConstrainedWindowSheetInfo* info = nil;
+ for (ConstrainedWindowSheetInfo* curInfo in sheets_.get()) {
+ if ([overlayWindow isEqual:[curInfo overlayWindow]]) {
+ info = curInfo;
+ break;
+ }
+ }
+ DCHECK(info);
+ if ([[info animation] isAnimating])
+ return;
+
+ scoped_nsobject<NSAnimation> animation(
+ [[ConstrainedWindowAnimationPulse alloc] initWithWindow:[info sheet]]);
+ [info setAnimation:animation];
+ [animation startAnimation];
+}
+
+- (void)animationDidEnd:(NSAnimation*)animation {
+ ConstrainedWindowSheetInfo* info = nil;
+ for (ConstrainedWindowSheetInfo* curInfo in sheets_.get()) {
+ if ([animation isEqual:[curInfo animation]]) {
+ info = curInfo;
+ break;
+ }
+ }
+ DCHECK(info);
+
+ // To avoid reentrancy close the sheet in the next event cycle.
+ [self performSelector:@selector(closeSheetWithoutAnimation:)
+ withObject:info
+ afterDelay:0];
+}
+
+- (void)closeSheetWithoutAnimation:(ConstrainedWindowSheetInfo*)info {
+ if (![sheets_ containsObject:info])
+ return;
+
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:NSViewFrameDidChangeNotification
+ object:[info parentView]];
+
+ [[info animation] stopAnimation];
+ [parentWindow_ removeChildWindow:[info overlayWindow]];
+ [[info overlayWindow] removeChildWindow:[info sheet]];
+ [[info sheet] close];
+ [[info overlayWindow] close];
+ [sheets_ removeObject:info];
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698