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#ifndef CHROME_BROWSER_INFOBARS_INFOBAR_CONTAINER_H_ 6#define CHROME_BROWSER_INFOBARS_INFOBAR_CONTAINER_H_ 7 8#include <vector> 9 10#include "base/compiler_specific.h" 11#include "base/time/time.h" 12#include "content/public/browser/notification_observer.h" 13#include "content/public/browser/notification_registrar.h" 14#include "third_party/skia/include/core/SkColor.h" 15 16class InfoBar; 17class InfoBarDelegate; 18class InfoBarService; 19 20// InfoBarContainer is a cross-platform base class to handle the visibility- 21// related aspects of InfoBars. While InfoBars own themselves, the 22// InfoBarContainer is responsible for telling particular InfoBars that they 23// should be hidden or visible. 24// 25// Platforms need to subclass this to implement a few platform-specific 26// functions, which are pure virtual here. 27class InfoBarContainer : public content::NotificationObserver { 28 public: 29 class Delegate { 30 public: 31 // The separator color may vary depending on where the container is hosted. 32 virtual SkColor GetInfoBarSeparatorColor() const = 0; 33 34 // The delegate is notified each time the infobar container changes height, 35 // as well as when it stops animating. 36 virtual void InfoBarContainerStateChanged(bool is_animating) = 0; 37 38 // The delegate needs to tell us whether "unspoofable" arrows should be 39 // drawn, and if so, at what |x| coordinate. |x| may be NULL. 40 virtual bool DrawInfoBarArrows(int* x) const = 0; 41 42 protected: 43 virtual ~Delegate(); 44 }; 45 46 explicit InfoBarContainer(Delegate* delegate); 47 virtual ~InfoBarContainer(); 48 49 // Changes the InfoBarService for which this container is showing infobars. 50 // This will remove all current infobars from the container, add the infobars 51 // from |infobar_service|, and show them all. |infobar_service| may be NULL. 52 void ChangeInfoBarService(InfoBarService* infobar_service); 53 54 // Returns the amount by which to overlap the toolbar above, and, when 55 // |total_height| is non-NULL, set it to the height of the InfoBarContainer 56 // (including overlap). 57 int GetVerticalOverlap(int* total_height); 58 59 // Called by the delegate when the distance between what the top infobar's 60 // "unspoofable" arrow would point to and the top infobar itself changes. 61 // This enables the top infobar to show a longer arrow (e.g. because of a 62 // visible bookmark bar) or shorter (e.g. due to being in a popup window) if 63 // desired. 64 // 65 // IMPORTANT: This MUST NOT result in a call back to 66 // Delegate::InfoBarContainerStateChanged() unless it causes an actual 67 // change, lest we infinitely recurse. 68 void SetMaxTopArrowHeight(int height); 69 70 // Called when a contained infobar has animated or by some other means changed 71 // its height, or when it stops animating. The container is expected to do 72 // anything necessary to respond, e.g. re-layout. 73 void OnInfoBarStateChanged(bool is_animating); 74 75 // Called by |infobar| to request that it be removed from the container. At 76 // this point, |infobar| should already be hidden. Once the infobar is 77 // removed, it is guaranteed to delete itself and will not be re-added again. 78 void RemoveInfoBar(InfoBar* infobar); 79 80 const Delegate* delegate() const { return delegate_; } 81 82 protected: 83 // Subclasses must call this during destruction, so that we can remove 84 // infobars (which will call the pure virtual functions below) while the 85 // subclass portion of |this| has not yet been destroyed. 86 void RemoveAllInfoBarsForDestruction(); 87 88 // These must be implemented on each platform to e.g. adjust the visible 89 // object hierarchy. The first two functions should each be called exactly 90 // once during an infobar's life (see comments on RemoveInfoBar() and 91 // AddInfoBar()). 92 virtual void PlatformSpecificAddInfoBar(InfoBar* infobar, 93 size_t position) = 0; 94 virtual void PlatformSpecificRemoveInfoBar(InfoBar* infobar) = 0; 95#if defined(OS_ANDROID) 96 // This is a temporary hook that can be removed once infobar code for 97 // Android is upstreamed and the translate infobar implemented as three 98 // different infobars like GTK does. 99 virtual void PlatformSpecificReplaceInfoBar(InfoBar* old_infobar, 100 InfoBar* new_infobar) {} 101#endif 102 virtual void PlatformSpecificInfoBarStateChanged(bool is_animating) {} 103 104 private: 105 typedef std::vector<InfoBar*> InfoBars; 106 107 // content::NotificationObserver: 108 virtual void Observe(int type, 109 const content::NotificationSource& source, 110 const content::NotificationDetails& details) OVERRIDE; 111 112 // Hides an InfoBar for the specified delegate, in response to a notification 113 // from the selected InfoBarService. The InfoBar's disappearance will be 114 // animated if |use_animation| is true. The InfoBar will call back to 115 // RemoveInfoBar() to remove itself once it's hidden (which may mean 116 // synchronously). Returns the position within |infobars_| the infobar was 117 // previously at. 118 size_t HideInfoBar(InfoBar* infobar, bool use_animation); 119 120 // Find an existing infobar in the container. 121 InfoBar* FindInfoBar(InfoBarDelegate* delegate); 122 123 // Hides all infobars in this container without animation. 124 void HideAllInfoBars(); 125 126 void ReplaceInfoBar(InfoBarDelegate* old_delegate, 127 InfoBarDelegate* new_delegate); 128 129 // Adds |infobar| to this container before the existing infobar at position 130 // |position| and calls Show() on it. |animate| is passed along to 131 // infobar->Show(). Depending on the value of |callback_status|, this calls 132 // infobar->set_container(this) either before or after the call to Show() so 133 // that OnInfoBarStateChanged() either will or won't be called as a result. 134 // 135 // This should be called only once for an infobar -- once it's added, it can 136 // be repeatedly shown and hidden, but not removed and then re-added (see 137 // comments on RemoveInfoBar()). 138 enum CallbackStatus { NO_CALLBACK, WANT_CALLBACK }; 139 void AddInfoBar(InfoBar* infobar, 140 size_t position, 141 bool animate, 142 CallbackStatus callback_status); 143 144 void UpdateInfoBarArrowTargetHeights(); 145 int ArrowTargetHeightForInfoBar(size_t infobar_index) const; 146 147 content::NotificationRegistrar registrar_; 148 Delegate* delegate_; 149 InfoBarService* infobar_service_; 150 InfoBars infobars_; 151 152 // Calculated in SetMaxTopArrowHeight(). 153 int top_arrow_target_height_; 154 155 DISALLOW_COPY_AND_ASSIGN(InfoBarContainer); 156}; 157 158#endif // CHROME_BROWSER_INFOBARS_INFOBAR_CONTAINER_H_ 159