diff options
Diffstat (limited to 'chrome/browser/cocoa/base_bubble_controller.mm')
-rw-r--r-- | chrome/browser/cocoa/base_bubble_controller.mm | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/base_bubble_controller.mm b/chrome/browser/cocoa/base_bubble_controller.mm new file mode 100644 index 0000000..b155a4f --- /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 + + 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. + [self close]; +} +@end // BaseBubbleController |