1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
// Copyright (c) 2011 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/infobars/infobar_container_controller.h"
#include "base/logging.h"
#include "chrome/browser/infobars/infobar_service.h"
#import "chrome/browser/ui/cocoa/browser_window_controller.h"
#import "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h"
#import "chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h"
#import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
#import "chrome/browser/ui/cocoa/view_id_util.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_container.h"
@interface InfoBarContainerController ()
// Removes |controller| from the list of controllers in this container and
// removes its view from the view hierarchy. This method is safe to call while
// |controller| is still on the call stack.
- (void)removeController:(InfoBarController*)controller;
@end
@implementation InfoBarContainerController
@synthesize shouldSuppressTopInfoBarTip = shouldSuppressTopInfoBarTip_;
- (id)initWithResizeDelegate:(id<ViewResizer>)resizeDelegate {
DCHECK(resizeDelegate);
if ((self = [super initWithNibName:nil bundle:nil])) {
// This view and its subviews use autoresizing masks, The starting frame
// needs to be reasonably large, although its exactly values don't matter.
// It cannot be NSZeroRect.
base::scoped_nsobject<NSView> view(
[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 800, 100)]);
[view setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin];
view_id_util::SetID(view, VIEW_ID_INFO_BAR_CONTAINER);
[self setView:view];
resizeDelegate_ = resizeDelegate;
containerCocoa_.reset(new InfoBarContainerCocoa(self));
infobarControllers_.reset([[NSMutableArray alloc] init]);
}
return self;
}
- (void)dealloc {
// Delete the container so that any remaining infobars are removed.
containerCocoa_.reset();
DCHECK_EQ([infobarControllers_ count], 0U);
view_id_util::UnsetID([self view]);
[super dealloc];
}
- (BrowserWindowController*)browserWindowController {
id controller = [[[self view] window] windowController];
if (![controller isKindOfClass:[BrowserWindowController class]])
return nil;
return controller;
}
- (CGFloat)infobarArrowX {
LocationBarViewMac* locationBar =
[[self browserWindowController] locationBarBridge];
return locationBar->GetPageInfoBubblePoint().x;
}
- (void)changeWebContents:(content::WebContents*)contents {
currentWebContents_ = contents;
InfoBarService* infobar_service =
contents ? InfoBarService::FromWebContents(contents) : NULL;
containerCocoa_->ChangeInfoBarManager(infobar_service);
}
- (void)tabDetachedWithContents:(content::WebContents*)contents {
if (currentWebContents_ == contents)
[self changeWebContents:NULL];
}
- (CGFloat)overlappingTipHeight {
return containerCocoa_->GetVerticalOverlap(NULL);
}
- (void)addInfoBar:(InfoBarCocoa*)infobar
position:(NSUInteger)position {
InfoBarController* controller = infobar->controller();
[controller setContainerController:self];
[infobarControllers_ insertObject:controller atIndex:position];
NSView* relativeView = nil;
if (position > 0)
relativeView = [[infobarControllers_ objectAtIndex:position - 1] view];
[[self view] addSubview:[controller view]
positioned:NSWindowAbove
relativeTo:relativeView];
}
- (void)removeInfoBar:(InfoBarCocoa*)infobar {
[infobar->controller() infobarWillHide];
[self removeController:infobar->controller()];
}
- (void)positionInfoBarsAndRedraw:(BOOL)isAnimating {
if (isAnimating_ != isAnimating) {
isAnimating_ = isAnimating;
if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
[resizeDelegate_ setAnimationInProgress:isAnimating_];
}
NSRect containerBounds = [[self view] bounds];
int minY = 0;
// Stack the infobars at the bottom of the view, starting with the
// last infobar and working our way to the front of the array. This
// way we ensure that the first infobar added shows up on top, with
// the others below.
for (InfoBarController* controller in
[infobarControllers_ reverseObjectEnumerator]) {
NSRect frame;
frame.origin.x = NSMinX(containerBounds);
frame.origin.y = minY;
frame.size.width = NSWidth(containerBounds);
frame.size.height = [controller infobar]->total_height();
[[controller view] setFrame:frame];
minY += NSHeight(frame) - [controller infobar]->arrow_height();
[controller layoutArrow];
}
[resizeDelegate_ resizeView:[self view] newHeight:[self heightOfInfoBars]];
}
- (void)setShouldSuppressTopInfoBarTip:(BOOL)flag {
if (shouldSuppressTopInfoBarTip_ == flag)
return;
shouldSuppressTopInfoBarTip_ = flag;
[self positionInfoBarsAndRedraw:isAnimating_];
}
- (void)removeController:(InfoBarController*)controller {
if (![infobarControllers_ containsObject:controller])
return;
// This code can be executed while InfoBarController is still on the stack, so
// we retain and autorelease the controller to prevent it from being
// dealloc'ed too early.
[[controller retain] autorelease];
[[controller view] removeFromSuperview];
[infobarControllers_ removeObject:controller];
}
- (void)setMaxTopArrowHeight:(NSInteger)height {
containerCocoa_->SetMaxTopArrowHeight(height, containerCocoa_.get());
}
- (CGFloat)heightOfInfoBars {
CGFloat totalHeight = 0;
for (InfoBarController* controller in infobarControllers_.get()) {
totalHeight += [controller infobar]->total_height() -
[controller infobar]->arrow_height();
}
return totalHeight;
}
@end
|