tab.h revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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
22class TabController;
23
24namespace gfx {
25class Animation;
26class AnimationContainer;
27class Font;
28class LinearAnimation;
29class MultiAnimation;
30}
31namespace views {
32class ImageButton;
33}
34
35///////////////////////////////////////////////////////////////////////////////
36//
37//  A View that renders a Tab in a TabStrip.
38//
39///////////////////////////////////////////////////////////////////////////////
40class 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  // Used to set/check whether this Tab is being animated closed.
52  void set_closing(bool closing) { closing_ = closing; }
53  bool closing() const { return closing_; }
54
55  // See description above field.
56  void set_dragging(bool dragging) { dragging_ = dragging; }
57  bool dragging() const { return dragging_; }
58
59  // Sets the container all animations run from.
60  void set_animation_container(gfx::AnimationContainer* container);
61
62  // Returns true if this tab is the active tab.
63  bool IsActive() const;
64
65  // Returns true if the tab is selected.
66  bool IsSelected() const;
67
68  // Sets the data this tabs displays. Invokes DataChanged.
69  void SetData(const TabRendererData& data);
70  const TabRendererData& data() const { return data_; }
71
72  // Sets the network state. If the network state changes NetworkStateChanged is
73  // invoked.
74  void UpdateLoadingAnimation(TabRendererData::NetworkState state);
75
76  // Starts/Stops a pulse animation.
77  void StartPulse();
78  void StopPulse();
79
80  // Start/stop the mini-tab title animation.
81  void StartMiniTabTitleAnimation();
82  void StopMiniTabTitleAnimation();
83
84  // Set the background offset used to match the image in the inactive tab
85  // to the frame image.
86  void set_background_offset(const gfx::Point& offset) {
87    background_offset_ = offset;
88  }
89
90  // Returns true if this tab became the active tab selected in
91  // response to the last ui::ET_GESTURE_BEGIN gesture dispatched to
92  // this tab. Only used for collecting UMA metrics.
93  // See ash/touch/touch_uma.cc.
94  bool tab_activated_with_last_gesture_begin() const {
95    return tab_activated_with_last_gesture_begin_;
96  }
97
98  views::GlowHoverController* hover_controller() {
99    return &hover_controller_;
100  }
101
102  // Returns the minimum possible size of a single unselected Tab.
103  static gfx::Size GetMinimumUnselectedSize();
104  // Returns the minimum possible size of a selected Tab. Selected tabs must
105  // always show a close button and have a larger minimum size than unselected
106  // tabs.
107  static gfx::Size GetMinimumSelectedSize();
108  // Returns the preferred size of a single Tab, assuming space is
109  // available.
110  static gfx::Size GetStandardSize();
111
112  // Returns the width for touch tabs.
113  static int GetTouchWidth();
114
115  // Returns the width for mini-tabs. Mini-tabs always have this width.
116  static int GetMiniWidth();
117
118  // Returns the height for immersive mode tabs.
119  static int GetImmersiveHeight();
120
121 private:
122  friend class TabTest;
123  FRIEND_TEST_ALL_PREFIXES(TabTest, CloseButtonLayout);
124
125  friend class TabStripTest;
126  FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabHitTestMaskWhenStacked);
127  FRIEND_TEST_ALL_PREFIXES(TabStripTest, ClippedTabCloseButton);
128
129  // The animation object used to swap the favicon with the sad tab icon.
130  class FaviconCrashAnimation;
131  class TabCloseButton;
132
133  // Contains a cached image and the values used to generate it.
134  struct ImageCacheEntry {
135    ImageCacheEntry();
136    ~ImageCacheEntry();
137
138    // ID of the resource used.
139    int resource_id;
140
141    // Scale factor we're drawing it.
142    ui::ScaleFactor scale_factor;
143
144    // The image.
145    gfx::ImageSkia image;
146  };
147
148  typedef std::list<ImageCacheEntry> ImageCache;
149
150  // Overridden from gfx::AnimationDelegate:
151  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
152  virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
153  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
154
155  // Overridden from views::ButtonListener:
156  virtual void ButtonPressed(views::Button* sender,
157                             const ui::Event& event) OVERRIDE;
158
159  // Overridden from views::ContextMenuController:
160  virtual void ShowContextMenuForView(views::View* source,
161                                      const gfx::Point& point,
162                                      ui::MenuSourceType source_type) OVERRIDE;
163
164  // Overridden from views::View:
165  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
166  virtual void Layout() OVERRIDE;
167  virtual void OnThemeChanged() OVERRIDE;
168  virtual const char* GetClassName() const OVERRIDE;
169  virtual bool HasHitTestMask() const OVERRIDE;
170  virtual void GetHitTestMask(HitTestSource source,
171                              gfx::Path* path) const OVERRIDE;
172  virtual bool GetTooltipText(const gfx::Point& p,
173                              base::string16* tooltip) const OVERRIDE;
174  virtual bool GetTooltipTextOrigin(const gfx::Point& p,
175                                    gfx::Point* origin) const OVERRIDE;
176  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
177  virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
178  virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
179  virtual void OnMouseCaptureLost() OVERRIDE;
180  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
181  virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
182  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
183  virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
184
185  // Overridden from ui::EventHandler:
186  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
187
188  // Returns the bounds of the title and icon.
189  const gfx::Rect& GetTitleBounds() const;
190  const gfx::Rect& GetIconBounds() const;
191
192  // Invoked from Layout to adjust the position of the favicon or media
193  // indicator for mini tabs.
194  void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;
195
196  // Invoked from SetData after |data_| has been updated to the new data.
197  void DataChanged(const TabRendererData& old);
198
199  // Paint with the normal tab style.
200  void PaintTab(gfx::Canvas* canvas);
201
202  // Paint with the "immersive mode" light-bar style.
203  void PaintImmersiveTab(gfx::Canvas* canvas);
204
205  // Paint various portions of the Tab
206  void PaintTabBackground(gfx::Canvas* canvas);
207  void PaintInactiveTabBackgroundWithTitleChange(
208      gfx::Canvas* canvas,
209      gfx::MultiAnimation* animation);
210  void PaintInactiveTabBackground(gfx::Canvas* canvas);
211  void PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas,
212                                                 int tab_id);
213  void PaintActiveTabBackground(gfx::Canvas* canvas);
214
215  // Paints the favicon, media indicator icon, etc., mirrored for RTL if needed.
216  void PaintIcon(gfx::Canvas* canvas);
217  void PaintMediaIndicator(gfx::Canvas* canvas);
218  void PaintTitle(gfx::Canvas* canvas, SkColor title_color);
219
220  // Invoked if data_.network_state changes, or the network_state is not none.
221  void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
222                               TabRendererData::NetworkState state);
223
224  // Returns the number of favicon-size elements that can fit in the tab's
225  // current size.
226  int IconCapacity() const;
227
228  // Returns whether the Tab should display a favicon.
229  bool ShouldShowIcon() const;
230
231  // Returns whether the Tab should display the media indicator.
232  bool ShouldShowMediaIndicator() const;
233
234  // Returns whether the Tab should display a close button.
235  bool ShouldShowCloseBox() const;
236
237  // Gets the throb value for the tab. When a tab is not selected the
238  // active background is drawn at |GetThrobValue()|%. This is used for hover,
239  // mini tab title change and pulsing.
240  double GetThrobValue();
241
242  // Set the temporary offset for the favicon. This is used during the crash
243  // animation.
244  void SetFaviconHidingOffset(int offset);
245
246  void DisplayCrashedFavicon();
247  void ResetCrashedFavicon();
248
249  void StopCrashAnimation();
250  void StartCrashAnimation();
251
252  // Returns true if the crash animation is currently running.
253  bool IsPerformingCrashAnimation() const;
254
255  // Starts the media indicator fade-in/out animation. There's no stop method
256  // because this is not a continuous animation.
257  void StartMediaIndicatorAnimation();
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, never NULL.
292  TabController* controller_;
293
294  TabRendererData data_;
295
296  // True if the tab is being animated closed.
297  bool closing_;
298
299  // True if the tab is being dragged.
300  bool dragging_;
301
302  // The offset used to animate the favicon location. This is used when the tab
303  // crashes.
304  int favicon_hiding_offset_;
305
306  // The current index of the loading animation. The range varies depending on
307  // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
308  int loading_animation_frame_;
309
310  // Step in the immersive loading progress indicator.
311  int immersive_loading_step_;
312
313  bool should_display_crashed_favicon_;
314
315  // Whole-tab throbbing "pulse" animation.
316  scoped_ptr<gfx::Animation> tab_animation_;
317
318  // Crash icon animation (in place of favicon).
319  scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;
320
321  // Media indicator fade-in/out animation (i.e., only on show/hide, not a
322  // continuous animation).
323  scoped_ptr<gfx::Animation> media_indicator_animation_;
324  TabMediaState animating_media_state_;
325
326  scoped_refptr<gfx::AnimationContainer> animation_container_;
327
328  views::ImageButton* close_button_;
329
330  bool tab_activated_with_last_gesture_begin_;
331
332  views::GlowHoverController hover_controller_;
333
334  // The bounds of various sections of the display.
335  gfx::Rect favicon_bounds_;
336  gfx::Rect title_bounds_;
337  gfx::Rect media_indicator_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're showing the media indicator. It is cached so that we can
358  // detect when it changes and layout appropriately.
359  bool showing_media_indicator_;
360
361  // Whether we are showing the close button. It is cached so that we can
362  // detect when it changes and layout appropriately.
363  bool showing_close_button_;
364
365  // The current color of the close button.
366  SkColor close_button_color_;
367
368  static gfx::Font* font_;
369  static int font_height_;
370
371  // As the majority of the tabs are inactive, and painting tabs is slowish,
372  // we cache a handful of the inactive tab backgrounds here.
373  static ImageCache* image_cache_;
374
375  DISALLOW_COPY_AND_ASSIGN(Tab);
376};
377
378#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
379