tab.h revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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, either in a TabStrip or in a DraggedTabView.
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  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 audio
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 icon, audio indicator icon, etc., mirrored for RTL if needed.
220  void PaintIcon(gfx::Canvas* canvas);
221  void PaintCaptureState(gfx::Canvas* canvas, gfx::Rect bounds);
222  void PaintAudioIndicator(gfx::Canvas* canvas);
223  void PaintTitle(gfx::Canvas* canvas, SkColor title_color);
224
225  // Invoked if data_.network_state changes, or the network_state is not none.
226  void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
227                               TabRendererData::NetworkState state);
228
229  // Returns the number of favicon-size elements that can fit in the tab's
230  // current size.
231  int IconCapacity() const;
232
233  // Returns whether the Tab should display a favicon.
234  bool ShouldShowIcon() const;
235
236  // Returns whether the Tab should display the audio indicator.
237  bool ShouldShowAudioIndicator() const;
238
239  // Returns whether the Tab should display a close button.
240  bool ShouldShowCloseBox() const;
241
242  // Gets the throb value for the tab. When a tab is not selected the
243  // active background is drawn at |GetThrobValue()|%. This is used for hover,
244  // mini tab title change and pulsing.
245  double GetThrobValue();
246
247  // Set the temporary offset for the favicon. This is used during the crash
248  // animation.
249  void SetFaviconHidingOffset(int offset);
250
251  void DisplayCrashedFavicon();
252  void ResetCrashedFavicon();
253
254  void StopIconAnimation();
255  void StartCrashAnimation();
256  void StartRecordingAnimation();
257
258  // Returns true if the crash animation is currently running.
259  bool IsPerformingCrashAnimation() const;
260
261  // Schedules repaint task for icon.
262  void ScheduleIconPaint();
263
264  // Returns the rectangle for the light bar in immersive mode.
265  gfx::Rect GetImmersiveBarRect() const;
266
267  // Gets the tab id and frame id.
268  void GetTabIdAndFrameId(views::Widget* widget,
269                          int* tab_id,
270                          int* frame_id) const;
271
272  // Performs a one-time initialization of static resources such as tab images.
273  static void InitTabResources();
274
275  // Returns the minimum possible size of a single unselected Tab, not
276  // including considering touch mode.
277  static gfx::Size GetBasicMinimumUnselectedSize();
278
279  // Loads the images to be used for the tab background.
280  static void LoadTabImages();
281
282  // Returns the cached image for the specified arguments, or an empty image if
283  // there isn't one cached.
284  static gfx::ImageSkia GetCachedImage(int resource_id,
285                                       const gfx::Size& size,
286                                       ui::ScaleFactor scale_factor);
287
288  // Caches the specified image.
289  static void SetCachedImage(int resource_id,
290                             ui::ScaleFactor scale_factor,
291                             const gfx::ImageSkia& image);
292
293  // The controller.
294  // WARNING: this is null during detached tab dragging.
295  TabController* controller_;
296
297  TabRendererData data_;
298
299  // True if the tab is being animated closed.
300  bool closing_;
301
302  // True if the tab is being dragged.
303  bool dragging_;
304
305  // The offset used to animate the favicon location. This is used when the tab
306  // crashes.
307  int favicon_hiding_offset_;
308
309  // The current index of the loading animation. The range varies depending on
310  // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
311  int loading_animation_frame_;
312
313  // Step in the immersive loading progress indicator.
314  int immersive_loading_step_;
315
316  bool should_display_crashed_favicon_;
317
318  // The tab and the icon can both be animating. The tab 'throbs' by changing
319  // color. The icon can have one of several of animations like crashing,
320  // recording, projecting, etc. Note that the icon animation related to network
321  // state does not have an animation associated with it.
322  scoped_ptr<gfx::Animation> tab_animation_;
323  scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;
324  scoped_ptr<gfx::Animation> capture_icon_animation_;
325  scoped_refptr<gfx::AnimationContainer> animation_container_;
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  gfx::Rect audio_indicator_bounds_;
339
340  // The offset used to paint the inactive background image.
341  gfx::Point background_offset_;
342
343  struct TabImage {
344    gfx::ImageSkia* image_l;
345    gfx::ImageSkia* image_c;
346    gfx::ImageSkia* image_r;
347    int l_width;
348    int r_width;
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're showing the audio indicator. It is cached so that we can
359  // detect when it changes and layout appropriately.
360  bool showing_audio_indicator_;
361
362  // Whether we are showing the close button. It is cached so that we can
363  // detect when it changes and layout appropriately.
364  bool showing_close_button_;
365
366  // The current color of the close button.
367  SkColor close_button_color_;
368
369  static gfx::Font* font_;
370  static int font_height_;
371
372  // As the majority of the tabs are inactive, and painting tabs is slowish,
373  // we cache a handful of the inactive tab backgrounds here.
374  static ImageCache* image_cache_;
375
376  DISALLOW_COPY_AND_ASSIGN(Tab);
377};
378
379#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
380