Chromium Code Reviews| Index: chrome/browser/cocoa/base_bubble_controller.mm |
| diff --git a/chrome/browser/cocoa/base_bubble_controller.mm b/chrome/browser/cocoa/base_bubble_controller.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b155a4f75c47cdca1d61ae775dc2d9879b6cfbf4 |
| --- /dev/null |
| +++ b/chrome/browser/cocoa/base_bubble_controller.mm |
| @@ -0,0 +1,123 @@ |
| +// Copyright (c) 2010 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/cocoa/base_bubble_controller.h" |
| + |
| +#include "app/l10n_util.h" |
| +#include "base/logging.h" |
| +#include "base/mac_util.h" |
| +#include "base/string_util.h" |
| +#import "chrome/browser/cocoa/info_bubble_view.h" |
| +#include "grit/generated_resources.h" |
| + |
| +@implementation BaseBubbleController |
| + |
| +@synthesize bubble = bubble_; |
| + |
| +- (id)initWithWindowNibPath:(NSString*)nibPath |
| + parentWindow:(NSWindow*)parentWindow |
| + anchoredAt:(NSPoint)anchoredAt { |
| + nibPath = [mac_util::MainAppBundle() pathForResource:nibPath |
| + ofType:@"nib"]; |
| + if ((self = [super initWithWindowNibPath:nibPath owner:self])) { |
| + parentWindow_ = parentWindow; |
| + anchor_ = anchoredAt; |
| + |
| + // Watch to see if the parent window closes, and if so, close this one. |
| + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; |
| + [center addObserver:self |
| + selector:@selector(parentWindowWillClose:) |
| + name:NSWindowWillCloseNotification |
| + object:parentWindow_]; |
| + } |
| + return self; |
| +} |
| + |
| +- (id)initWithWindowNibPath:(NSString*)nibPath |
| + relativeToView:(NSView*)view |
| + offset:(NSPoint)offset { |
| + DCHECK([view window]); |
| + NSWindow* window = [view window]; |
| + NSRect bounds = [view convertRect:[view bounds] toView:nil]; |
| + NSPoint anchor = NSMakePoint(NSMinX(bounds) + offset.x, |
| + NSMinY(bounds) + offset.y); |
| + anchor = [window convertBaseToScreen:anchor]; |
| + return [self initWithWindowNibPath:nibPath |
| + parentWindow:window |
| + anchoredAt:anchor]; |
| +} |
| + |
| + |
| +- (void)awakeFromNib { |
| + // Check all connections have been made in Interface Builder. |
| + DCHECK([self window]); |
| + DCHECK(bubble_); |
| + DCHECK_EQ(self, [[self window] delegate]); |
| + |
| + [bubble_ setBubbleType:info_bubble::kWhiteInfoBubble]; |
| + [bubble_ setArrowLocation:info_bubble::kTopRight]; |
| +} |
| + |
| +- (void)dealloc { |
| + [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| + [super dealloc]; |
| +} |
| + |
| +- (void)parentWindowWillClose:(NSNotification*)notification { |
| + [self close]; |
| +} |
| + |
| +- (void)windowWillClose:(NSNotification*)notification { |
| + // We caught a close so we don't need to watch for the parent closing. |
| + [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| + [self autorelease]; |
| +} |
| + |
| +// We want this to be a child of a browser window. addChildWindow: |
| +// (called from this function) will bring the window on-screen; |
| +// unfortunately, [NSWindowController showWindow:] will also bring it |
| +// on-screen (but will cause unexpected changes to the window's |
| +// position). We cannot have an addChildWindow: and a subsequent |
| +// showWindow:. Thus, we have our own version. |
| +- (void)showWindow:(id)sender { |
| + NSWindow* window = [self window]; // completes nib load |
|
jeremy
2010/06/27 12:46:42
nit: Completes nib load.
|
| + |
| + NSPoint origin = anchor_; |
| + NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset + |
| + info_bubble::kBubbleArrowWidth / 2.0, 0); |
| + offsets = [[parentWindow_ contentView] convertSize:offsets toView:nil]; |
| + origin.x += offsets.width; |
| + if ([bubble_ arrowLocation] == info_bubble::kTopRight) |
| + origin.x -= NSWidth([window frame]); |
| + origin.y -= NSHeight([window frame]); |
| + [window setFrameOrigin:origin]; |
| + [parentWindow_ addChildWindow:window ordered:NSWindowAbove]; |
| + [window makeKeyAndOrderFront:self]; |
| +} |
| + |
| +- (void)close { |
| + [parentWindow_ removeChildWindow:[self window]]; |
| + [super close]; |
| +} |
| + |
| +// The controller is the delegate of the window so it receives did resign key |
| +// notifications. When key is resigned mirror Windows behavior and close the |
| +// window. |
| +- (void)windowDidResignKey:(NSNotification*)notification { |
| + NSWindow* window = [self window]; |
| + DCHECK_EQ([notification object], window); |
| + if ([window isVisible]) { |
| + // If the window isn't visible, it is already closed, and this notification |
| + // has been sent as part of the closing operation, so no need to close. |
| + [self close]; |
| + } |
| +} |
| + |
| +// By implementing this, ESC causes the window to go away. |
| +- (IBAction)cancel:(id)sender { |
| + // This is not a "real" cancel as potential changes to the radio group are not |
| + // undone. That's ok. |
|
jeremy
2010/06/27 12:46:42
Could you expand this comment: which radio group?
|
| + [self close]; |
| +} |
| +@end // BaseBubbleController |