tab.h revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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  views::GlowHoverController* hover_controller() {
104    return &hover_controller_;
105  }
106
107  // Returns the minimum possible size of a single unselected Tab.
108  static gfx::Size GetMinimumUnselectedSize();
109  // Returns the minimum possible size of a selected Tab. Selected tabs must
110  // always show a close button and have a larger minimum size than unselected
111  // tabs.
112  static gfx::Size GetMinimumSelectedSize();
113  // Returns the preferred size of a single Tab, assuming space is
114  // available.
115  static gfx::Size GetStandardSize();
116
117  // Returns the width for touch tabs.
118  static int GetTouchWidth();
119
120  // Returns the width for mini-tabs. Mini-tabs always have this width.
121  static int GetMiniWidth();
122
123  // Returns the height for immersive mode tabs.
124  static int GetImmersiveHeight();
125
126 private:
127  friend class TabTest;
128  FRIEND_TEST_ALL_PREFIXES(TabTest, CloseButtonLayout);
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 TabAudioIndicator::Delegate:
151  virtual void ScheduleAudioIndicatorPaint() OVERRIDE;
152
153  // Overridden from ui::AnimationDelegate:
154  virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
155  virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE;
156  virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
157
158  // Overridden from views::ButtonListener:
159  virtual void ButtonPressed(views::Button* sender,
160                             const ui::Event& event) OVERRIDE;
161
162  // Overridden from views::ContextMenuController:
163  virtual void ShowContextMenuForView(views::View* source,
164                                      const gfx::Point& point,
165                                      ui::MenuSourceType source_type) OVERRIDE;
166
167  // Overridden from views::View:
168  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
169  virtual void Layout() OVERRIDE;
170  virtual void OnThemeChanged() OVERRIDE;
171  virtual const char* GetClassName() const OVERRIDE;
172  virtual bool HasHitTestMask() const OVERRIDE;
173  virtual void GetHitTestMask(gfx::Path* path) const OVERRIDE;
174  virtual bool GetTooltipText(const gfx::Point& p,
175                              string16* tooltip) const OVERRIDE;
176  virtual bool GetTooltipTextOrigin(const gfx::Point& p,
177                                    gfx::Point* origin) const OVERRIDE;
178  virtual ui::ThemeProvider* GetThemeProvider() const OVERRIDE;
179  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
180  virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
181  virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
182  virtual void OnMouseCaptureLost() OVERRIDE;
183  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
184  virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
185  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
186  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
187
188  // Overridden from ui::EventHandler:
189  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
190
191  // Returns the bounds of the title and icon.
192  const gfx::Rect& GetTitleBounds() const;
193  const gfx::Rect& GetIconBounds() const;
194
195  // Invoked from SetData after |data_| has been updated to the new data.
196  void DataChanged(const TabRendererData& old);
197
198  // Paint with the normal tab style.
199  void PaintTab(gfx::Canvas* canvas);
200
201  // Paint with the "immersive mode" light-bar style.
202  void PaintImmersiveTab(gfx::Canvas* canvas);
203
204  // Paint various portions of the Tab
205  void PaintTabBackground(gfx::Canvas* canvas);
206  void PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas,
207                                                 ui::MultiAnimation* animation);
208  void PaintInactiveTabBackground(gfx::Canvas* canvas);
209  void PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas,
210                                                 int tab_id);
211  void PaintActiveTabBackground(gfx::Canvas* canvas);
212
213  // Paints the icon at the specified coordinates, mirrored for RTL if needed.
214  void PaintIcon(gfx::Canvas* canvas);
215  void PaintCaptureState(gfx::Canvas* canvas, gfx::Rect bounds);
216  void PaintTitle(gfx::Canvas* canvas, SkColor title_color);
217
218  // Invoked if data_.network_state changes, or the network_state is not none.
219  void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
220                               TabRendererData::NetworkState state);
221
222  // Returns the number of favicon-size elements that can fit in the tab's
223  // current size.
224  int IconCapacity() const;
225
226  // Returns whether the Tab should display a favicon.
227  bool ShouldShowIcon() const;
228
229  // Returns whether the Tab should display a close button.
230  bool ShouldShowCloseBox() const;
231
232  // Gets the throb value for the tab. When a tab is not selected the
233  // active background is drawn at |GetThrobValue()|%. This is used for hover,
234  // mini tab title change and pulsing.
235  double GetThrobValue();
236
237  // Set the temporary offset for the favicon. This is used during the crash
238  // animation.
239  void SetFaviconHidingOffset(int offset);
240
241  void DisplayCrashedFavicon();
242  void ResetCrashedFavicon();
243
244  void StopIconAnimation();
245  void StartCrashAnimation();
246  void StartRecordingAnimation();
247
248  // Returns true if the crash animation is currently running.
249  bool IsPerformingCrashAnimation() const;
250
251  // Schedules repaint task for icon.
252  void ScheduleIconPaint();
253
254  // Returns the rectangle for the light bar in immersive mode.
255  gfx::Rect GetImmersiveBarRect() const;
256
257  // Gets the tab id and frame id.
258  void GetTabIdAndFrameId(views::Widget* widget,
259                          int* tab_id,
260                          int* frame_id) const;
261
262  // Performs a one-time initialization of static resources such as tab images.
263  static void InitTabResources();
264
265  // Returns the minimum possible size of a single unselected Tab, not
266  // including considering touch mode.
267  static gfx::Size GetBasicMinimumUnselectedSize();
268
269  // Loads the images to be used for the tab background.
270  static void LoadTabImages();
271
272  // Returns the cached image for the specified arguments, or an empty image if
273  // there isn't one cached.
274  static gfx::ImageSkia GetCachedImage(int resource_id,
275                                       const gfx::Size& size,
276                                       ui::ScaleFactor scale_factor);
277
278  // Caches the specified image.
279  static void SetCachedImage(int resource_id,
280                             ui::ScaleFactor scale_factor,
281                             const gfx::ImageSkia& image);
282
283  // The controller.
284  // WARNING: this is null during detached tab dragging.
285  TabController* controller_;
286
287  TabRendererData data_;
288
289  // True if the tab is being animated closed.
290  bool closing_;
291
292  // True if the tab is being dragged.
293  bool dragging_;
294
295  // The offset used to animate the favicon location. This is used when the tab
296  // crashes.
297  int favicon_hiding_offset_;
298
299  // The current index of the loading animation. The range varies depending on
300  // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
301  int loading_animation_frame_;
302
303  // Step in the immersive loading progress indicator.
304  int immersive_loading_step_;
305
306  bool should_display_crashed_favicon_;
307
308  // The tab and the icon can both be animating. The tab 'throbs' by changing
309  // color. The icon can have one of several of animations like crashing,
310  // recording, projecting, etc. Note that the icon animation related to network
311  // state does not have an animation associated with it.
312  scoped_ptr<ui::Animation> tab_animation_;
313  scoped_ptr<ui::LinearAnimation> icon_animation_;
314
315  scoped_refptr<ui::AnimationContainer> animation_container_;
316
317  scoped_ptr<TabAudioIndicator> tab_audio_indicator_;
318
319  views::ImageButton* close_button_;
320
321  ui::ThemeProvider* theme_provider_;
322
323  views::GlowHoverController hover_controller_;
324
325  // The bounds of various sections of the display.
326  gfx::Rect favicon_bounds_;
327  gfx::Rect title_bounds_;
328
329  // The offset used to paint the inactive background image.
330  gfx::Point background_offset_;
331
332  struct TabImage {
333    gfx::ImageSkia* image_l;
334    gfx::ImageSkia* image_c;
335    gfx::ImageSkia* image_r;
336    int l_width;
337    int r_width;
338    int y_offset;
339  };
340  static TabImage tab_active_;
341  static TabImage tab_inactive_;
342  static TabImage tab_alpha_;
343
344  // Whether we're showing the icon. It is cached so that we can detect when it
345  // changes and layout appropriately.
346  bool showing_icon_;
347
348  // Whether we are showing the close button. It is cached so that we can
349  // detect when it changes and layout appropriately.
350  bool showing_close_button_;
351
352  // The current color of the close button.
353  SkColor close_button_color_;
354
355  static gfx::Font* font_;
356  static int font_height_;
357
358  // As the majority of the tabs are inactive, and painting tabs is slowish,
359  // we cache a handful of the inactive tab backgrounds here.
360  static ImageCache* image_cache_;
361
362  DISALLOW_COPY_AND_ASSIGN(Tab);
363};
364
365#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
366