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 InfoBarService; 18 19// InfoBarContainer is a cross-platform base class to handle the visibility- 20// related aspects of InfoBars. While InfoBarService owns the InfoBars, the 21// InfoBarContainer is responsible for telling particular InfoBars that they 22// should be hidden or visible. 23// 24// Platforms need to subclass this to implement a few platform-specific 25// functions, which are pure virtual here. 26class InfoBarContainer : public content::NotificationObserver { 27 public: 28 class Delegate { 29 public: 30 // The separator color may vary depending on where the container is hosted. 31 virtual SkColor GetInfoBarSeparatorColor() const = 0; 32 33 // The delegate is notified each time the infobar container changes height, 34 // as well as when it stops animating. 35 virtual void InfoBarContainerStateChanged(bool is_animating) = 0; 36 37 // The delegate needs to tell us whether "unspoofable" arrows should be 38 // drawn, and if so, at what |x| coordinate. |x| may be NULL. 39 virtual bool DrawInfoBarArrows(int* x) const = 0; 40 41 protected: 42 virtual ~Delegate(); 43 }; 44 45 explicit InfoBarContainer(Delegate* delegate); 46 virtual ~InfoBarContainer(); 47 48 // Changes the InfoBarService for which this container is showing infobars. 49 // This will hide all current infobars, remove them from the container, add 50 // the infobars from |infobar_service|, and show them all. |infobar_service| 51 // 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. 77 void RemoveInfoBar(InfoBar* infobar); 78 79 const Delegate* delegate() const { return delegate_; } 80 81 protected: 82 // Subclasses must call this during destruction, so that we can remove 83 // infobars (which will call the pure virtual functions below) while the 84 // subclass portion of |this| has not yet been destroyed. 85 void RemoveAllInfoBarsForDestruction(); 86 87 // These must be implemented on each platform to e.g. adjust the visible 88 // object hierarchy. The first two functions should each be called exactly 89 // once during an infobar's life (see comments on RemoveInfoBar() and 90 // AddInfoBar()). 91 virtual void PlatformSpecificAddInfoBar(InfoBar* infobar, 92 size_t position) = 0; 93 // TODO(miguelg): Remove this; it is only necessary for Android, and only 94 // until the translate infobar is implemented as three different infobars like 95 // GTK does. 96 virtual void PlatformSpecificReplaceInfoBar(InfoBar* old_infobar, 97 InfoBar* new_infobar) {} 98 virtual void PlatformSpecificRemoveInfoBar(InfoBar* infobar) = 0; 99 virtual void PlatformSpecificInfoBarStateChanged(bool is_animating) {} 100 101 private: 102 typedef std::vector<InfoBar*> InfoBars; 103 104 // content::NotificationObserver: 105 virtual void Observe(int type, 106 const content::NotificationSource& source, 107 const content::NotificationDetails& details) OVERRIDE; 108 109 // Hides all infobars in this container without animation. 110 void HideAllInfoBars(); 111 112 // Adds |infobar| to this container before the existing infobar at position 113 // |position| and calls Show() on it. |animate| is passed along to 114 // infobar->Show(). Depending on the value of |callback_status|, this calls 115 // infobar->set_container(this) either before or after the call to Show() so 116 // that OnInfoBarStateChanged() either will or won't be called as a result. 117 enum CallbackStatus { NO_CALLBACK, WANT_CALLBACK }; 118 void AddInfoBar(InfoBar* infobar, 119 size_t position, 120 bool animate, 121 CallbackStatus callback_status); 122 123 void UpdateInfoBarArrowTargetHeights(); 124 int ArrowTargetHeightForInfoBar(size_t infobar_index) const; 125 126 content::NotificationRegistrar registrar_; 127 Delegate* delegate_; 128 InfoBarService* infobar_service_; 129 InfoBars infobars_; 130 131 // Calculated in SetMaxTopArrowHeight(). 132 int top_arrow_target_height_; 133 134 DISALLOW_COPY_AND_ASSIGN(InfoBarContainer); 135}; 136 137#endif // CHROME_BROWSER_INFOBARS_INFOBAR_CONTAINER_H_ 138