Home | History | Annotate | Download | only in tabs
      1 // Copyright (c) 2012 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_UI_VIEWS_TABS_TAB_H_
      6 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
      7 
      8 #include <list>
      9 #include <string>
     10 
     11 #include "base/memory/ref_counted.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
     14 #include "ui/base/layout.h"
     15 #include "ui/gfx/animation/animation_delegate.h"
     16 #include "ui/gfx/point.h"
     17 #include "ui/views/context_menu_controller.h"
     18 #include "ui/views/controls/button/button.h"
     19 #include "ui/views/controls/glow_hover_controller.h"
     20 #include "ui/views/view.h"
     21 
     22 class TabController;
     23 
     24 namespace gfx {
     25 class Animation;
     26 class AnimationContainer;
     27 class Font;
     28 class LinearAnimation;
     29 class MultiAnimation;
     30 }
     31 namespace views {
     32 class ImageButton;
     33 }
     34 
     35 ///////////////////////////////////////////////////////////////////////////////
     36 //
     37 //  A View that renders a Tab, either in a TabStrip or in a DraggedTabView.
     38 //
     39 ///////////////////////////////////////////////////////////////////////////////
     40 class Tab : public gfx::AnimationDelegate,
     41             public views::ButtonListener,
     42             public views::ContextMenuController,
     43             public views::View {
     44  public:
     45   // The menu button's class name.
     46   static const char kViewClassName[];
     47 
     48   explicit Tab(TabController* controller);
     49   virtual ~Tab();
     50 
     51   TabController* controller() const { return controller_; }
     52 
     53   // Used to set/check whether this Tab is being animated closed.
     54   void set_closing(bool closing) { closing_ = closing; }
     55   bool closing() const { return closing_; }
     56 
     57   // See description above field.
     58   void set_dragging(bool dragging) { dragging_ = dragging; }
     59   bool dragging() const { return dragging_; }
     60 
     61   // Sets the container all animations run from.
     62   void set_animation_container(gfx::AnimationContainer* container);
     63 
     64   // Set the theme provider - because we get detached, we are frequently
     65   // outside of a hierarchy with a theme provider at the top. This should be
     66   // called whenever we're detached or attached to a hierarchy.
     67   void set_theme_provider(ui::ThemeProvider* provider) {
     68     theme_provider_ = provider;
     69   }
     70 
     71   // Returns true if this tab is the active tab.
     72   bool IsActive() const;
     73 
     74   // Returns true if the tab is selected.
     75   bool IsSelected() const;
     76 
     77   // Sets the data this tabs displays. Invokes DataChanged.
     78   void SetData(const TabRendererData& data);
     79   const TabRendererData& data() const { return data_; }
     80 
     81   // Sets the network state. If the network state changes NetworkStateChanged is
     82   // invoked.
     83   void UpdateLoadingAnimation(TabRendererData::NetworkState state);
     84 
     85   // Starts/Stops a pulse animation.
     86   void StartPulse();
     87   void StopPulse();
     88 
     89   // Start/stop the mini-tab title animation.
     90   void StartMiniTabTitleAnimation();
     91   void StopMiniTabTitleAnimation();
     92 
     93   // Set the background offset used to match the image in the inactive tab
     94   // to the frame image.
     95   void set_background_offset(const gfx::Point& offset) {
     96     background_offset_ = offset;
     97   }
     98 
     99   // Returns true if this tab became the active tab selected in
    100   // response to the last ui::ET_GESTURE_BEGIN gesture dispatched to
    101   // this tab. Only used for collecting UMA metrics.
    102   // See ash/touch/touch_uma.cc.
    103   bool tab_activated_with_last_gesture_begin() const {
    104     return tab_activated_with_last_gesture_begin_;
    105   }
    106 
    107   views::GlowHoverController* hover_controller() {
    108     return &hover_controller_;
    109   }
    110 
    111   // Returns the minimum possible size of a single unselected Tab.
    112   static gfx::Size GetMinimumUnselectedSize();
    113   // Returns the minimum possible size of a selected Tab. Selected tabs must
    114   // always show a close button and have a larger minimum size than unselected
    115   // tabs.
    116   static gfx::Size GetMinimumSelectedSize();
    117   // Returns the preferred size of a single Tab, assuming space is
    118   // available.
    119   static gfx::Size GetStandardSize();
    120 
    121   // Returns the width for touch tabs.
    122   static int GetTouchWidth();
    123 
    124   // Returns the width for mini-tabs. Mini-tabs always have this width.
    125   static int GetMiniWidth();
    126 
    127   // Returns the height for immersive mode tabs.
    128   static int GetImmersiveHeight();
    129 
    130  private:
    131   friend class TabTest;
    132   FRIEND_TEST_ALL_PREFIXES(TabTest, CloseButtonLayout);
    133 
    134   friend class TabStripTest;
    135   FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabHitTestMaskWhenStacked);
    136   FRIEND_TEST_ALL_PREFIXES(TabStripTest, ClippedTabCloseButton);
    137 
    138   // The animation object used to swap the favicon with the sad tab icon.
    139   class FaviconCrashAnimation;
    140   class TabCloseButton;
    141 
    142   // Contains a cached image and the values used to generate it.
    143   struct ImageCacheEntry {
    144     ImageCacheEntry();
    145     ~ImageCacheEntry();
    146 
    147     // ID of the resource used.
    148     int resource_id;
    149 
    150     // Scale factor we're drawing it.
    151     ui::ScaleFactor scale_factor;
    152 
    153     // The image.
    154     gfx::ImageSkia image;
    155   };
    156 
    157   typedef std::list<ImageCacheEntry> ImageCache;
    158 
    159   // Overridden from gfx::AnimationDelegate:
    160   virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
    161   virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
    162   virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
    163 
    164   // Overridden from views::ButtonListener:
    165   virtual void ButtonPressed(views::Button* sender,
    166                              const ui::Event& event) OVERRIDE;
    167 
    168   // Overridden from views::ContextMenuController:
    169   virtual void ShowContextMenuForView(views::View* source,
    170                                       const gfx::Point& point,
    171                                       ui::MenuSourceType source_type) OVERRIDE;
    172 
    173   // Overridden from views::View:
    174   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
    175   virtual void Layout() OVERRIDE;
    176   virtual void OnThemeChanged() OVERRIDE;
    177   virtual const char* GetClassName() const OVERRIDE;
    178   virtual bool HasHitTestMask() const OVERRIDE;
    179   virtual void GetHitTestMask(HitTestSource source,
    180                               gfx::Path* path) const OVERRIDE;
    181   virtual bool GetTooltipText(const gfx::Point& p,
    182                               base::string16* tooltip) const OVERRIDE;
    183   virtual bool GetTooltipTextOrigin(const gfx::Point& p,
    184                                     gfx::Point* origin) const OVERRIDE;
    185   virtual ui::ThemeProvider* GetThemeProvider() const OVERRIDE;
    186   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
    187   virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
    188   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
    189   virtual void OnMouseCaptureLost() OVERRIDE;
    190   virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
    191   virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
    192   virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
    193   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
    194 
    195   // Overridden from ui::EventHandler:
    196   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
    197 
    198   // Returns the bounds of the title and icon.
    199   const gfx::Rect& GetTitleBounds() const;
    200   const gfx::Rect& GetIconBounds() const;
    201 
    202   // Invoked from Layout to adjust the position of the favicon or media
    203   // indicator for mini tabs.
    204   void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;
    205 
    206   // Invoked from SetData after |data_| has been updated to the new data.
    207   void DataChanged(const TabRendererData& old);
    208 
    209   // Paint with the normal tab style.
    210   void PaintTab(gfx::Canvas* canvas);
    211 
    212   // Paint with the "immersive mode" light-bar style.
    213   void PaintImmersiveTab(gfx::Canvas* canvas);
    214 
    215   // Paint various portions of the Tab
    216   void PaintTabBackground(gfx::Canvas* canvas);
    217   void PaintInactiveTabBackgroundWithTitleChange(
    218       gfx::Canvas* canvas,
    219       gfx::MultiAnimation* animation);
    220   void PaintInactiveTabBackground(gfx::Canvas* canvas);
    221   void PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas,
    222                                                  int tab_id);
    223   void PaintActiveTabBackground(gfx::Canvas* canvas);
    224 
    225   // Paints the favicon, media indicator icon, etc., mirrored for RTL if needed.
    226   void PaintIcon(gfx::Canvas* canvas);
    227   void PaintMediaIndicator(gfx::Canvas* canvas);
    228   void PaintTitle(gfx::Canvas* canvas, SkColor title_color);
    229 
    230   // Invoked if data_.network_state changes, or the network_state is not none.
    231   void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
    232                                TabRendererData::NetworkState state);
    233 
    234   // Returns the number of favicon-size elements that can fit in the tab's
    235   // current size.
    236   int IconCapacity() const;
    237 
    238   // Returns whether the Tab should display a favicon.
    239   bool ShouldShowIcon() const;
    240 
    241   // Returns whether the Tab should display the media indicator.
    242   bool ShouldShowMediaIndicator() const;
    243 
    244   // Returns whether the Tab should display a close button.
    245   bool ShouldShowCloseBox() const;
    246 
    247   // Gets the throb value for the tab. When a tab is not selected the
    248   // active background is drawn at |GetThrobValue()|%. This is used for hover,
    249   // mini tab title change and pulsing.
    250   double GetThrobValue();
    251 
    252   // Set the temporary offset for the favicon. This is used during the crash
    253   // animation.
    254   void SetFaviconHidingOffset(int offset);
    255 
    256   void DisplayCrashedFavicon();
    257   void ResetCrashedFavicon();
    258 
    259   void StopCrashAnimation();
    260   void StartCrashAnimation();
    261 
    262   // Returns true if the crash animation is currently running.
    263   bool IsPerformingCrashAnimation() const;
    264 
    265   // Starts the media indicator fade-in/out animation. There's no stop method
    266   // because this is not a continuous animation.
    267   void StartMediaIndicatorAnimation();
    268 
    269   // Schedules repaint task for icon.
    270   void ScheduleIconPaint();
    271 
    272   // Returns the rectangle for the light bar in immersive mode.
    273   gfx::Rect GetImmersiveBarRect() const;
    274 
    275   // Gets the tab id and frame id.
    276   void GetTabIdAndFrameId(views::Widget* widget,
    277                           int* tab_id,
    278                           int* frame_id) const;
    279 
    280   // Performs a one-time initialization of static resources such as tab images.
    281   static void InitTabResources();
    282 
    283   // Returns the minimum possible size of a single unselected Tab, not
    284   // including considering touch mode.
    285   static gfx::Size GetBasicMinimumUnselectedSize();
    286 
    287   // Loads the images to be used for the tab background.
    288   static void LoadTabImages();
    289 
    290   // Returns the cached image for the specified arguments, or an empty image if
    291   // there isn't one cached.
    292   static gfx::ImageSkia GetCachedImage(int resource_id,
    293                                        const gfx::Size& size,
    294                                        ui::ScaleFactor scale_factor);
    295 
    296   // Caches the specified image.
    297   static void SetCachedImage(int resource_id,
    298                              ui::ScaleFactor scale_factor,
    299                              const gfx::ImageSkia& image);
    300 
    301   // The controller.
    302   // WARNING: this is null during detached tab dragging.
    303   TabController* controller_;
    304 
    305   TabRendererData data_;
    306 
    307   // True if the tab is being animated closed.
    308   bool closing_;
    309 
    310   // True if the tab is being dragged.
    311   bool dragging_;
    312 
    313   // The offset used to animate the favicon location. This is used when the tab
    314   // crashes.
    315   int favicon_hiding_offset_;
    316 
    317   // The current index of the loading animation. The range varies depending on
    318   // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
    319   int loading_animation_frame_;
    320 
    321   // Step in the immersive loading progress indicator.
    322   int immersive_loading_step_;
    323 
    324   bool should_display_crashed_favicon_;
    325 
    326   // Whole-tab throbbing "pulse" animation.
    327   scoped_ptr<gfx::Animation> tab_animation_;
    328 
    329   // Crash icon animation (in place of favicon).
    330   scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;
    331 
    332   // Media indicator fade-in/out animation (i.e., only on show/hide, not a
    333   // continuous animation).
    334   scoped_ptr<gfx::Animation> media_indicator_animation_;
    335   TabMediaState animating_media_state_;
    336 
    337   scoped_refptr<gfx::AnimationContainer> animation_container_;
    338 
    339   views::ImageButton* close_button_;
    340 
    341   ui::ThemeProvider* theme_provider_;
    342 
    343   bool tab_activated_with_last_gesture_begin_;
    344 
    345   views::GlowHoverController hover_controller_;
    346 
    347   // The bounds of various sections of the display.
    348   gfx::Rect favicon_bounds_;
    349   gfx::Rect title_bounds_;
    350   gfx::Rect media_indicator_bounds_;
    351 
    352   // The offset used to paint the inactive background image.
    353   gfx::Point background_offset_;
    354 
    355   struct TabImage {
    356     gfx::ImageSkia* image_l;
    357     gfx::ImageSkia* image_c;
    358     gfx::ImageSkia* image_r;
    359     int l_width;
    360     int r_width;
    361   };
    362   static TabImage tab_active_;
    363   static TabImage tab_inactive_;
    364   static TabImage tab_alpha_;
    365 
    366   // Whether we're showing the icon. It is cached so that we can detect when it
    367   // changes and layout appropriately.
    368   bool showing_icon_;
    369 
    370   // Whether we're showing the media indicator. It is cached so that we can
    371   // detect when it changes and layout appropriately.
    372   bool showing_media_indicator_;
    373 
    374   // Whether we are showing the close button. It is cached so that we can
    375   // detect when it changes and layout appropriately.
    376   bool showing_close_button_;
    377 
    378   // The current color of the close button.
    379   SkColor close_button_color_;
    380 
    381   static gfx::Font* font_;
    382   static int font_height_;
    383 
    384   // As the majority of the tabs are inactive, and painting tabs is slowish,
    385   // we cache a handful of the inactive tab backgrounds here.
    386   static ImageCache* image_cache_;
    387 
    388   DISALLOW_COPY_AND_ASSIGN(Tab);
    389 };
    390 
    391 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
    392