Home | History | Annotate | Download | only in infobars
      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 
     16 class InfoBar;
     17 class 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.
     26 class 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