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