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/masked_targeter_delegate.h"
     21 #include "ui/views/view.h"
     22 
     23 class MediaIndicatorButton;
     24 class TabController;
     25 
     26 namespace gfx {
     27 class Animation;
     28 class AnimationContainer;
     29 class LinearAnimation;
     30 class MultiAnimation;
     31 class ThrobAnimation;
     32 }
     33 namespace views {
     34 class ImageButton;
     35 class Label;
     36 }
     37 
     38 ///////////////////////////////////////////////////////////////////////////////
     39 //
     40 //  A View that renders a Tab in a TabStrip.
     41 //
     42 ///////////////////////////////////////////////////////////////////////////////
     43 class Tab : public gfx::AnimationDelegate,
     44             public views::ButtonListener,
     45             public views::ContextMenuController,
     46             public views::MaskedTargeterDelegate,
     47             public views::View {
     48  public:
     49   // The Tab'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   // Used to mark the tab as having been detached.  Once this has happened, the
     66   // tab should be invisibly closed.  This is irreversible.
     67   void set_detached() { detached_ = true; }
     68   bool detached() const { return detached_; }
     69 
     70   // Sets the container all animations run from.
     71   void set_animation_container(gfx::AnimationContainer* container);
     72 
     73   // Returns true if this tab is the active tab.
     74   bool IsActive() const;
     75 
     76   // Returns true if the tab is selected.
     77   bool IsSelected() const;
     78 
     79   // Sets the data this tabs displays. Invokes DataChanged.
     80   void SetData(const TabRendererData& data);
     81   const TabRendererData& data() const { return data_; }
     82 
     83   // Sets the network state. If the network state changes NetworkStateChanged is
     84   // invoked.
     85   void UpdateLoadingAnimation(TabRendererData::NetworkState state);
     86 
     87   // Starts/Stops a pulse animation.
     88   void StartPulse();
     89   void StopPulse();
     90 
     91   // Start/stop the mini-tab title animation.
     92   void StartMiniTabTitleAnimation();
     93   void StopMiniTabTitleAnimation();
     94 
     95   // Set the background offset used to match the image in the inactive tab
     96   // to the frame image.
     97   void set_background_offset(const gfx::Point& offset) {
     98     background_offset_ = offset;
     99   }
    100 
    101   // Returns true if this tab became the active tab selected in
    102   // response to the last ui::ET_TAP_DOWN gesture dispatched to
    103   // this tab. Only used for collecting UMA metrics.
    104   // See ash/touch/touch_uma.cc.
    105   bool tab_activated_with_last_tap_down() const {
    106     return tab_activated_with_last_tap_down_;
    107   }
    108 
    109   views::GlowHoverController* hover_controller() {
    110     return &hover_controller_;
    111   }
    112 
    113   // Returns the inset within the first dragged tab to use when calculating the
    114   // "drag insertion point".  If we simply used the x-coordinate of the tab,
    115   // we'd be calculating based on a point well before where the user considers
    116   // the tab to "be".  The value here is chosen to "feel good" based on the
    117   // widths of the tab images and the tab overlap.
    118   //
    119   // Note that this must return a value smaller than the midpoint of any tab's
    120   // width, or else the user won't be able to drag a tab to the left of the
    121   // first tab in the strip.
    122   static int leading_width_for_drag() { return 16; }
    123 
    124   // Returns the minimum possible size of a single unselected Tab.
    125   static gfx::Size GetMinimumUnselectedSize();
    126   // Returns the minimum possible size of a selected Tab. Selected tabs must
    127   // always show a close button and have a larger minimum size than unselected
    128   // tabs.
    129   static gfx::Size GetMinimumSelectedSize();
    130   // Returns the preferred size of a single Tab, assuming space is
    131   // available.
    132   static gfx::Size GetStandardSize();
    133 
    134   // Returns the width for touch tabs.
    135   static int GetTouchWidth();
    136 
    137   // Returns the width for mini-tabs. Mini-tabs always have this width.
    138   static int GetMiniWidth();
    139 
    140   // Returns the height for immersive mode tabs.
    141   static int GetImmersiveHeight();
    142 
    143  private:
    144   friend class TabTest;
    145   FRIEND_TEST_ALL_PREFIXES(TabTest, CloseButtonLayout);
    146 
    147   friend class TabStripTest;
    148   FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabHitTestMaskWhenStacked);
    149   FRIEND_TEST_ALL_PREFIXES(TabStripTest, ClippedTabCloseButton);
    150 
    151   // The animation object used to swap the favicon with the sad tab icon.
    152   class FaviconCrashAnimation;
    153   class TabCloseButton;
    154 
    155   // Contains a cached image and the values used to generate it.
    156   struct ImageCacheEntry {
    157     ImageCacheEntry();
    158     ~ImageCacheEntry();
    159 
    160     // ID of the resource used.
    161     int resource_id;
    162 
    163     // Scale factor we're drawing it.
    164     ui::ScaleFactor scale_factor;
    165 
    166     // The image.
    167     gfx::ImageSkia image;
    168   };
    169 
    170   typedef std::list<ImageCacheEntry> ImageCache;
    171 
    172   // gfx::AnimationDelegate:
    173   virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
    174   virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
    175   virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
    176 
    177   // views::ButtonListener:
    178   virtual void ButtonPressed(views::Button* sender,
    179                              const ui::Event& event) OVERRIDE;
    180 
    181   // views::ContextMenuController:
    182   virtual void ShowContextMenuForView(views::View* source,
    183                                       const gfx::Point& point,
    184                                       ui::MenuSourceType source_type) OVERRIDE;
    185 
    186   // views::MaskedTargeterDelegate:
    187   virtual bool GetHitTestMask(gfx::Path* mask) const OVERRIDE;
    188 
    189   // views::View:
    190   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
    191   virtual void Layout() OVERRIDE;
    192   virtual void OnThemeChanged() OVERRIDE;
    193   virtual const char* GetClassName() const OVERRIDE;
    194   virtual bool GetTooltipText(const gfx::Point& p,
    195                               base::string16* tooltip) const OVERRIDE;
    196   virtual bool GetTooltipTextOrigin(const gfx::Point& p,
    197                                     gfx::Point* origin) const OVERRIDE;
    198   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
    199   virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
    200   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
    201   virtual void OnMouseCaptureLost() OVERRIDE;
    202   virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
    203   virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
    204   virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
    205   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
    206 
    207   // ui::EventHandler:
    208   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
    209 
    210   // Invoked from Layout to adjust the position of the favicon or media
    211   // indicator for mini tabs.
    212   void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;
    213 
    214   // Invoked from SetData after |data_| has been updated to the new data.
    215   void DataChanged(const TabRendererData& old);
    216 
    217   // Paint with the normal tab style.
    218   void PaintTab(gfx::Canvas* canvas);
    219 
    220   // Paint with the "immersive mode" light-bar style.
    221   void PaintImmersiveTab(gfx::Canvas* canvas);
    222 
    223   // Paint various portions of the Tab
    224   void PaintTabBackground(gfx::Canvas* canvas);
    225   void PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas);
    226   void PaintInactiveTabBackground(gfx::Canvas* canvas);
    227   void PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas,
    228                                                  int tab_id);
    229   void PaintActiveTabBackground(gfx::Canvas* canvas);
    230 
    231   // Paints the favicon, mirrored for RTL if needed.
    232   void PaintIcon(gfx::Canvas* canvas);
    233 
    234   // Invoked if data_.network_state changes, or the network_state is not none.
    235   void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
    236                                TabRendererData::NetworkState state);
    237 
    238   // Returns the number of favicon-size elements that can fit in the tab's
    239   // current size.
    240   int IconCapacity() const;
    241 
    242   // Returns whether the Tab should display a favicon.
    243   bool ShouldShowIcon() const;
    244 
    245   // Returns whether the Tab should display the media indicator.
    246   bool ShouldShowMediaIndicator() const;
    247 
    248   // Returns whether the Tab should display a close button.
    249   bool ShouldShowCloseBox() const;
    250 
    251   // Gets the throb value for the tab. When a tab is not selected the
    252   // active background is drawn at |GetThrobValue()|%. This is used for hover,
    253   // mini tab title change and pulsing.
    254   double GetThrobValue();
    255 
    256   // Set the temporary offset for the favicon. This is used during the crash
    257   // animation.
    258   void SetFaviconHidingOffset(int offset);
    259 
    260   void DisplayCrashedFavicon();
    261   void ResetCrashedFavicon();
    262 
    263   void StopCrashAnimation();
    264   void StartCrashAnimation();
    265 
    266   // Returns true if the crash animation is currently running.
    267   bool IsPerformingCrashAnimation() const;
    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   // Returns |media_indicator_button_|, creating it on-demand.
    281   MediaIndicatorButton* GetMediaIndicatorButton();
    282 
    283   // Performs a one-time initialization of static resources such as tab images.
    284   static void InitTabResources();
    285 
    286   // Returns the minimum possible size of a single unselected Tab, not
    287   // including considering touch mode.
    288   static gfx::Size GetBasicMinimumUnselectedSize();
    289 
    290   // Loads the images to be used for the tab background.
    291   static void LoadTabImages();
    292 
    293   // Returns the cached image for the specified arguments, or an empty image if
    294   // there isn't one cached.
    295   static gfx::ImageSkia GetCachedImage(int resource_id,
    296                                        const gfx::Size& size,
    297                                        ui::ScaleFactor scale_factor);
    298 
    299   // Caches the specified image.
    300   static void SetCachedImage(int resource_id,
    301                              ui::ScaleFactor scale_factor,
    302                              const gfx::ImageSkia& image);
    303 
    304   // The controller, never NULL.
    305   TabController* const controller_;
    306 
    307   TabRendererData data_;
    308 
    309   // True if the tab is being animated closed.
    310   bool closing_;
    311 
    312   // True if the tab is being dragged.
    313   bool dragging_;
    314 
    315   // True if the tab has been detached.
    316   bool detached_;
    317 
    318   // The offset used to animate the favicon location. This is used when the tab
    319   // crashes.
    320   int favicon_hiding_offset_;
    321 
    322   // The current index of the loading animation. The range varies depending on
    323   // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
    324   int loading_animation_frame_;
    325 
    326   // Step in the immersive loading progress indicator.
    327   int immersive_loading_step_;
    328 
    329   bool should_display_crashed_favicon_;
    330 
    331   // Whole-tab throbbing "pulse" animation.
    332   scoped_ptr<gfx::ThrobAnimation> pulse_animation_;
    333 
    334   scoped_ptr<gfx::MultiAnimation> mini_title_change_animation_;
    335 
    336   // Crash icon animation (in place of favicon).
    337   scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;
    338 
    339   scoped_refptr<gfx::AnimationContainer> animation_container_;
    340 
    341   views::ImageButton* close_button_;
    342   MediaIndicatorButton* media_indicator_button_;  // NULL until first use.
    343   views::Label* title_;
    344 
    345   bool tab_activated_with_last_tap_down_;
    346 
    347   views::GlowHoverController hover_controller_;
    348 
    349   // The bounds of various sections of the display.
    350   gfx::Rect favicon_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   // As the majority of the tabs are inactive, and painting tabs is slowish,
    382   // we cache a handful of the inactive tab backgrounds here.
    383   static ImageCache* image_cache_;
    384 
    385   DISALLOW_COPY_AND_ASSIGN(Tab);
    386 };
    387 
    388 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
    389