tab.h revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <list>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string>
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/ref_counted.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/layout.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/animation/animation_delegate.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/point.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/context_menu_controller.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/controls/button/button.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/controls/glow_hover_controller.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/view.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TabController;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace gfx {
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Animation;
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class AnimationContainer;
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Font;
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class LinearAnimation;
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MultiAnimation;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace views {
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ImageButton;
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//  A View that renders a Tab, either in a TabStrip or in a DraggedTabView.
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Tab : public gfx::AnimationDelegate,
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            public views::ButtonListener,
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            public views::ContextMenuController,
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            public views::View {
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The menu button's class name.
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const char kViewClassName[];
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
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  // The animation object used to swap the favicon with the sad tab icon.
134  class FaviconCrashAnimation;
135  class TabCloseButton;
136
137  // Contains a cached image and the values used to generate it.
138  struct ImageCacheEntry {
139    ImageCacheEntry();
140    ~ImageCacheEntry();
141
142    // ID of the resource used.
143    int resource_id;
144
145    // Scale factor we're drawing it.
146    ui::ScaleFactor scale_factor;
147
148    // The image.
149    gfx::ImageSkia image;
150  };
151
152  typedef std::list<ImageCacheEntry> ImageCache;
153
154  // Overridden from gfx::AnimationDelegate:
155  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
156  virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
157  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
158
159  // Overridden from views::ButtonListener:
160  virtual void ButtonPressed(views::Button* sender,
161                             const ui::Event& event) OVERRIDE;
162
163  // Overridden from views::ContextMenuController:
164  virtual void ShowContextMenuForView(views::View* source,
165                                      const gfx::Point& point,
166                                      ui::MenuSourceType source_type) OVERRIDE;
167
168  // Overridden from views::View:
169  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
170  virtual void Layout() OVERRIDE;
171  virtual void OnThemeChanged() OVERRIDE;
172  virtual const char* GetClassName() const OVERRIDE;
173  virtual bool HasHitTestMask() const OVERRIDE;
174  virtual void GetHitTestMask(gfx::Path* path) const OVERRIDE;
175  virtual bool GetTooltipText(const gfx::Point& p,
176                              string16* tooltip) const OVERRIDE;
177  virtual bool GetTooltipTextOrigin(const gfx::Point& p,
178                                    gfx::Point* origin) const OVERRIDE;
179  virtual ui::ThemeProvider* GetThemeProvider() const OVERRIDE;
180  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
181  virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
182  virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
183  virtual void OnMouseCaptureLost() OVERRIDE;
184  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
185  virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
186  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
187  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
188
189  // Overridden from ui::EventHandler:
190  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
191
192  // Returns the bounds of the title and icon.
193  const gfx::Rect& GetTitleBounds() const;
194  const gfx::Rect& GetIconBounds() const;
195
196  // Invoked from Layout to adjust the position of the favicon or media
197  // indicator for mini tabs.
198  void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;
199
200  // Invoked from SetData after |data_| has been updated to the new data.
201  void DataChanged(const TabRendererData& old);
202
203  // Paint with the normal tab style.
204  void PaintTab(gfx::Canvas* canvas);
205
206  // Paint with the "immersive mode" light-bar style.
207  void PaintImmersiveTab(gfx::Canvas* canvas);
208
209  // Paint various portions of the Tab
210  void PaintTabBackground(gfx::Canvas* canvas);
211  void PaintInactiveTabBackgroundWithTitleChange(
212      gfx::Canvas* canvas,
213      gfx::MultiAnimation* animation);
214  void PaintInactiveTabBackground(gfx::Canvas* canvas);
215  void PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas,
216                                                 int tab_id);
217  void PaintActiveTabBackground(gfx::Canvas* canvas);
218
219  // Paints the favicon, media indicator icon, etc., mirrored for RTL if needed.
220  void PaintIcon(gfx::Canvas* canvas);
221  void PaintMediaIndicator(gfx::Canvas* canvas);
222  void PaintTitle(gfx::Canvas* canvas, SkColor title_color);
223
224  // Invoked if data_.network_state changes, or the network_state is not none.
225  void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
226                               TabRendererData::NetworkState state);
227
228  // Returns the number of favicon-size elements that can fit in the tab's
229  // current size.
230  int IconCapacity() const;
231
232  // Returns whether the Tab should display a favicon.
233  bool ShouldShowIcon() const;
234
235  // Returns whether the Tab should display the media indicator.
236  bool ShouldShowMediaIndicator() const;
237
238  // Returns whether the Tab should display a close button.
239  bool ShouldShowCloseBox() const;
240
241  // Gets the throb value for the tab. When a tab is not selected the
242  // active background is drawn at |GetThrobValue()|%. This is used for hover,
243  // mini tab title change and pulsing.
244  double GetThrobValue();
245
246  // Set the temporary offset for the favicon. This is used during the crash
247  // animation.
248  void SetFaviconHidingOffset(int offset);
249
250  void DisplayCrashedFavicon();
251  void ResetCrashedFavicon();
252
253  void StopCrashAnimation();
254  void StartCrashAnimation();
255
256  // Returns true if the crash animation is currently running.
257  bool IsPerformingCrashAnimation() const;
258
259  // Starts the media indicator fade-in/out animation. There's no stop method
260  // because this is not a continuous animation.
261  void StartMediaIndicatorAnimation();
262
263  // Schedules repaint task for icon.
264  void ScheduleIconPaint();
265
266  // Returns the rectangle for the light bar in immersive mode.
267  gfx::Rect GetImmersiveBarRect() const;
268
269  // Gets the tab id and frame id.
270  void GetTabIdAndFrameId(views::Widget* widget,
271                          int* tab_id,
272                          int* frame_id) const;
273
274  // Performs a one-time initialization of static resources such as tab images.
275  static void InitTabResources();
276
277  // Returns the minimum possible size of a single unselected Tab, not
278  // including considering touch mode.
279  static gfx::Size GetBasicMinimumUnselectedSize();
280
281  // Loads the images to be used for the tab background.
282  static void LoadTabImages();
283
284  // Returns the cached image for the specified arguments, or an empty image if
285  // there isn't one cached.
286  static gfx::ImageSkia GetCachedImage(int resource_id,
287                                       const gfx::Size& size,
288                                       ui::ScaleFactor scale_factor);
289
290  // Caches the specified image.
291  static void SetCachedImage(int resource_id,
292                             ui::ScaleFactor scale_factor,
293                             const gfx::ImageSkia& image);
294
295  // The controller.
296  // WARNING: this is null during detached tab dragging.
297  TabController* controller_;
298
299  TabRendererData data_;
300
301  // True if the tab is being animated closed.
302  bool closing_;
303
304  // True if the tab is being dragged.
305  bool dragging_;
306
307  // The offset used to animate the favicon location. This is used when the tab
308  // crashes.
309  int favicon_hiding_offset_;
310
311  // The current index of the loading animation. The range varies depending on
312  // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
313  int loading_animation_frame_;
314
315  // Step in the immersive loading progress indicator.
316  int immersive_loading_step_;
317
318  bool should_display_crashed_favicon_;
319
320  // Whole-tab throbbing "pulse" animation.
321  scoped_ptr<gfx::Animation> tab_animation_;
322
323  // Crash icon animation (in place of favicon).
324  scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;
325
326  // Media indicator fade-in/out animation (i.e., only on show/hide, not a
327  // continuous animation).
328  scoped_ptr<gfx::Animation> media_indicator_animation_;
329  TabMediaState animating_media_state_;
330
331  scoped_refptr<gfx::AnimationContainer> animation_container_;
332
333  views::ImageButton* close_button_;
334
335  ui::ThemeProvider* theme_provider_;
336
337  bool tab_activated_with_last_gesture_begin_;
338
339  views::GlowHoverController hover_controller_;
340
341  // The bounds of various sections of the display.
342  gfx::Rect favicon_bounds_;
343  gfx::Rect title_bounds_;
344  gfx::Rect media_indicator_bounds_;
345
346  // The offset used to paint the inactive background image.
347  gfx::Point background_offset_;
348
349  struct TabImage {
350    gfx::ImageSkia* image_l;
351    gfx::ImageSkia* image_c;
352    gfx::ImageSkia* image_r;
353    int l_width;
354    int r_width;
355  };
356  static TabImage tab_active_;
357  static TabImage tab_inactive_;
358  static TabImage tab_alpha_;
359
360  // Whether we're showing the icon. It is cached so that we can detect when it
361  // changes and layout appropriately.
362  bool showing_icon_;
363
364  // Whether we're showing the media indicator. It is cached so that we can
365  // detect when it changes and layout appropriately.
366  bool showing_media_indicator_;
367
368  // Whether we are showing the close button. It is cached so that we can
369  // detect when it changes and layout appropriately.
370  bool showing_close_button_;
371
372  // The current color of the close button.
373  SkColor close_button_color_;
374
375  static gfx::Font* font_;
376  static int font_height_;
377
378  // As the majority of the tabs are inactive, and painting tabs is slowish,
379  // we cache a handful of the inactive tab backgrounds here.
380  static ImageCache* image_cache_;
381
382  DISALLOW_COPY_AND_ASSIGN(Tab);
383};
384
385#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
386