tab.h revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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
23class TabController;
24
25namespace gfx {
26class Font;
27}
28namespace ui {
29class Animation;
30class AnimationContainer;
31class LinearAnimation;
32class MultiAnimation;
33}
34namespace views {
35class ImageButton;
36}
37
38///////////////////////////////////////////////////////////////////////////////
39//
40//  A View that renders a Tab, either in a TabStrip or in a DraggedTabView.
41//
42///////////////////////////////////////////////////////////////////////////////
43class 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    int y_offset;
349  };
350  static TabImage tab_active_;
351  static TabImage tab_inactive_;
352  static TabImage tab_alpha_;
353
354  // Whether we're showing the icon. It is cached so that we can detect when it
355  // changes and layout appropriately.
356  bool showing_icon_;
357
358  // Whether we are showing the close button. It is cached so that we can
359  // detect when it changes and layout appropriately.
360  bool showing_close_button_;
361
362  // The current color of the close button.
363  SkColor close_button_color_;
364
365  static gfx::Font* font_;
366  static int font_height_;
367
368  // As the majority of the tabs are inactive, and painting tabs is slowish,
369  // we cache a handful of the inactive tab backgrounds here.
370  static ImageCache* image_cache_;
371
372  DISALLOW_COPY_AND_ASSIGN(Tab);
373};
374
375#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
376