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