[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / infobars / infobar_container_controller.mm
blobbebd178bc1a2f4f4e73e7ea32472c21ab9461508
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
7 #include "base/logging.h"
8 #include "base/mac/mac_util.h"
9 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
10 #include "chrome/browser/infobars/infobar_service.h"
11 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
12 #import "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h"
13 #import "chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h"
14 #import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
15 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
16 #import "chrome/browser/ui/cocoa/view_id_util.h"
17 #include "components/infobars/core/infobar.h"
18 #include "components/infobars/core/infobar_container.h"
20 @interface InfoBarContainerController ()
21 // Removes |controller| from the list of controllers in this container and
22 // removes its view from the view hierarchy.  This method is safe to call while
23 // |controller| is still on the call stack.
24 - (void)removeController:(InfoBarController*)controller;
25 @end
28 @implementation InfoBarContainerController
30 @synthesize shouldSuppressTopInfoBarTip = shouldSuppressTopInfoBarTip_;
32 - (id)initWithResizeDelegate:(id<ViewResizer>)resizeDelegate {
33   DCHECK(resizeDelegate);
34   if ((self = [super initWithNibName:nil bundle:nil])) {
35     base::scoped_nsobject<NSView> view(
36         [[NSView alloc] initWithFrame:NSZeroRect]);
37     [view setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin];
38     view_id_util::SetID(view, VIEW_ID_INFO_BAR_CONTAINER);
39     [self setView:view];
41     resizeDelegate_ = resizeDelegate;
42     containerCocoa_.reset(new InfoBarContainerCocoa(self));
43     infobarControllers_.reset([[NSMutableArray alloc] init]);
44   }
45   return self;
48 - (void)dealloc {
49   // Delete the container so that any remaining infobars are removed.
50   containerCocoa_.reset();
51   DCHECK_EQ([infobarControllers_ count], 0U);
52   view_id_util::UnsetID([self view]);
53   [super dealloc];
56 - (BrowserWindowController*)browserWindowController {
57   id controller = [[[self view] window] windowController];
58   if (![controller isKindOfClass:[BrowserWindowController class]])
59     return nil;
60   return controller;
63 - (CGFloat)infobarArrowX {
64   LocationBarViewMac* locationBar =
65       [[self browserWindowController] locationBarBridge];
66   return locationBar->GetPageInfoBubblePoint().x;
69 - (void)changeWebContents:(content::WebContents*)contents {
70   currentWebContents_ = contents;
71   InfoBarService* infobar_service =
72       contents ? InfoBarService::FromWebContents(contents) : NULL;
73   containerCocoa_->ChangeInfoBarManager(infobar_service);
76 - (void)tabDetachedWithContents:(content::WebContents*)contents {
77   if (currentWebContents_ == contents)
78     [self changeWebContents:NULL];
81 - (CGFloat)overlappingTipHeight {
82   return containerCocoa_->GetVerticalOverlap(NULL);
85 - (void)addInfoBar:(InfoBarCocoa*)infobar
86           position:(NSUInteger)position {
87   InfoBarController* controller = infobar->controller();
88   [controller setContainerController:self];
89   [infobarControllers_ insertObject:controller atIndex:position];
91   NSView* relativeView = nil;
92   if (position > 0)
93     relativeView = [[infobarControllers_ objectAtIndex:position - 1] view];
94   [[self view] addSubview:[controller view]
95                positioned:NSWindowAbove
96                relativeTo:relativeView];
99 - (void)removeInfoBar:(InfoBarCocoa*)infobar {
100   [infobar->controller() infobarWillHide];
101   [self removeController:infobar->controller()];
104 - (void)positionInfoBarsAndRedraw:(BOOL)isAnimating {
105   if (isAnimating_ != isAnimating) {
106     isAnimating_ = isAnimating;
107     if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
108       [resizeDelegate_ setAnimationInProgress:isAnimating_];
109   }
111   NSRect containerBounds = [[self view] bounds];
112   int minY = 0;
114   // Stack the infobars at the bottom of the view, starting with the
115   // last infobar and working our way to the front of the array.  This
116   // way we ensure that the first infobar added shows up on top, with
117   // the others below.
118   for (InfoBarController* controller in
119            [infobarControllers_ reverseObjectEnumerator]) {
120     NSRect frame;
121     frame.origin.x = NSMinX(containerBounds);
122     frame.origin.y = minY;
123     frame.size.width = NSWidth(containerBounds);
124     frame.size.height = [controller infobar]->total_height();
125     [[controller view] setFrame:frame];
127     minY += NSHeight(frame) - [controller infobar]->arrow_height();
128     [controller layoutArrow];
129   }
131   int totalHeight = 0;
132   int overlap = containerCocoa_->GetVerticalOverlap(&totalHeight);
134   if (NSHeight([[self view] frame]) != totalHeight) {
135     [resizeDelegate_ resizeView:[self view] newHeight:totalHeight];
136   } else if (oldOverlappingTipHeight_ != overlap) {
137     // If the infobar overlap changed but the height didn't change then
138     // explicitly ask for a layout.
139     [[self browserWindowController] layoutInfoBars];
140   }
141   oldOverlappingTipHeight_ = overlap;
144 - (void)setShouldSuppressTopInfoBarTip:(BOOL)flag {
145   if (shouldSuppressTopInfoBarTip_ == flag)
146     return;
147   shouldSuppressTopInfoBarTip_ = flag;
148   [self positionInfoBarsAndRedraw:isAnimating_];
151 - (void)removeController:(InfoBarController*)controller {
152   if (![infobarControllers_ containsObject:controller])
153     return;
155   // This code can be executed while InfoBarController is still on the stack, so
156   // we retain and autorelease the controller to prevent it from being
157   // dealloc'ed too early.
158   [[controller retain] autorelease];
159   [[controller view] removeFromSuperview];
160   [infobarControllers_ removeObject:controller];
163 @end