summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/views/tabs/tab.h
blob: d5b71cdef3c8f3104d686a13cadec324f0df8aa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_

#include <list>
#include <string>

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
#include "ui/base/layout.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/point.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/glow_hover_controller.h"
#include "ui/views/view.h"

class TabController;

namespace gfx {
class Animation;
class AnimationContainer;
class Font;
class LinearAnimation;
class MultiAnimation;
}
namespace views {
class ImageButton;
}

///////////////////////////////////////////////////////////////////////////////
//
//  A View that renders a Tab in a TabStrip.
//
///////////////////////////////////////////////////////////////////////////////
class Tab : public gfx::AnimationDelegate,
            public views::ButtonListener,
            public views::ContextMenuController,
            public views::View {
 public:
  // The menu button's class name.
  static const char kViewClassName[];

  explicit Tab(TabController* controller);
  virtual ~Tab();

  // Used to set/check whether this Tab is being animated closed.
  void set_closing(bool closing) { closing_ = closing; }
  bool closing() const { return closing_; }

  // See description above field.
  void set_dragging(bool dragging) { dragging_ = dragging; }
  bool dragging() const { return dragging_; }

  // Sets the container all animations run from.
  void set_animation_container(gfx::AnimationContainer* container);

  // Returns true if this tab is the active tab.
  bool IsActive() const;

  // Returns true if the tab is selected.
  bool IsSelected() const;

  // Sets the data this tabs displays. Invokes DataChanged.
  void SetData(const TabRendererData& data);
  const TabRendererData& data() const { return data_; }

  // Sets the network state. If the network state changes NetworkStateChanged is
  // invoked.
  void UpdateLoadingAnimation(TabRendererData::NetworkState state);

  // Starts/Stops a pulse animation.
  void StartPulse();
  void StopPulse();

  // Start/stop the mini-tab title animation.
  void StartMiniTabTitleAnimation();
  void StopMiniTabTitleAnimation();

  // Set the background offset used to match the image in the inactive tab
  // to the frame image.
  void set_background_offset(const gfx::Point& offset) {
    background_offset_ = offset;
  }

  // Returns true if this tab became the active tab selected in
  // response to the last ui::ET_GESTURE_BEGIN gesture dispatched to
  // this tab. Only used for collecting UMA metrics.
  // See ash/touch/touch_uma.cc.
  bool tab_activated_with_last_gesture_begin() const {
    return tab_activated_with_last_gesture_begin_;
  }

  views::GlowHoverController* hover_controller() {
    return &hover_controller_;
  }

  // Returns the minimum possible size of a single unselected Tab.
  static gfx::Size GetMinimumUnselectedSize();
  // Returns the minimum possible size of a selected Tab. Selected tabs must
  // always show a close button and have a larger minimum size than unselected
  // tabs.
  static gfx::Size GetMinimumSelectedSize();
  // Returns the preferred size of a single Tab, assuming space is
  // available.
  static gfx::Size GetStandardSize();

  // Returns the width for touch tabs.
  static int GetTouchWidth();

  // Returns the width for mini-tabs. Mini-tabs always have this width.
  static int GetMiniWidth();

  // Returns the height for immersive mode tabs.
  static int GetImmersiveHeight();

 private:
  friend class TabTest;
  FRIEND_TEST_ALL_PREFIXES(TabTest, CloseButtonLayout);

  friend class TabStripTest;
  FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabHitTestMaskWhenStacked);
  FRIEND_TEST_ALL_PREFIXES(TabStripTest, ClippedTabCloseButton);

  // The animation object used to swap the favicon with the sad tab icon.
  class FaviconCrashAnimation;
  class TabCloseButton;

  // Contains a cached image and the values used to generate it.
  struct ImageCacheEntry {
    ImageCacheEntry();
    ~ImageCacheEntry();

    // ID of the resource used.
    int resource_id;

    // Scale factor we're drawing it.
    ui::ScaleFactor scale_factor;

    // The image.
    gfx::ImageSkia image;
  };

  typedef std::list<ImageCacheEntry> ImageCache;

  // Overridden from gfx::AnimationDelegate:
  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
  virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;

  // Overridden from views::ButtonListener:
  virtual void ButtonPressed(views::Button* sender,
                             const ui::Event& event) OVERRIDE;

  // Overridden from views::ContextMenuController:
  virtual void ShowContextMenuForView(views::View* source,
                                      const gfx::Point& point,
                                      ui::MenuSourceType source_type) OVERRIDE;

  // Overridden from views::View:
  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
  virtual void Layout() OVERRIDE;
  virtual void OnThemeChanged() OVERRIDE;
  virtual const char* GetClassName() const OVERRIDE;
  virtual bool HasHitTestMask() const OVERRIDE;
  virtual void GetHitTestMask(HitTestSource source,
                              gfx::Path* path) const OVERRIDE;
  virtual bool GetTooltipText(const gfx::Point& p,
                              base::string16* tooltip) const OVERRIDE;
  virtual bool GetTooltipTextOrigin(const gfx::Point& p,
                                    gfx::Point* origin) const OVERRIDE;
  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
  virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
  virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
  virtual void OnMouseCaptureLost() OVERRIDE;
  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
  virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
  virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;

  // Overridden from ui::EventHandler:
  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;

  // Returns the bounds of the title and icon.
  const gfx::Rect& GetTitleBounds() const;
  const gfx::Rect& GetIconBounds() const;

  // Invoked from Layout to adjust the position of the favicon or media
  // indicator for mini tabs.
  void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;

  // Invoked from SetData after |data_| has been updated to the new data.
  void DataChanged(const TabRendererData& old);

  // Paint with the normal tab style.
  void PaintTab(gfx::Canvas* canvas);

  // Paint with the "immersive mode" light-bar style.
  void PaintImmersiveTab(gfx::Canvas* canvas);

  // Paint various portions of the Tab
  void PaintTabBackground(gfx::Canvas* canvas);
  void PaintInactiveTabBackgroundWithTitleChange(
      gfx::Canvas* canvas,
      gfx::MultiAnimation* animation);
  void PaintInactiveTabBackground(gfx::Canvas* canvas);
  void PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas,
                                                 int tab_id);
  void PaintActiveTabBackground(gfx::Canvas* canvas);

  // Paints the favicon, media indicator icon, etc., mirrored for RTL if needed.
  void PaintIcon(gfx::Canvas* canvas);
  void PaintMediaIndicator(gfx::Canvas* canvas);
  void PaintTitle(gfx::Canvas* canvas, SkColor title_color);

  // Invoked if data_.network_state changes, or the network_state is not none.
  void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
                               TabRendererData::NetworkState state);

  // Returns the number of favicon-size elements that can fit in the tab's
  // current size.
  int IconCapacity() const;

  // Returns whether the Tab should display a favicon.
  bool ShouldShowIcon() const;

  // Returns whether the Tab should display the media indicator.
  bool ShouldShowMediaIndicator() const;

  // Returns whether the Tab should display a close button.
  bool ShouldShowCloseBox() const;

  // Gets the throb value for the tab. When a tab is not selected the
  // active background is drawn at |GetThrobValue()|%. This is used for hover,
  // mini tab title change and pulsing.
  double GetThrobValue();

  // Set the temporary offset for the favicon. This is used during the crash
  // animation.
  void SetFaviconHidingOffset(int offset);

  void DisplayCrashedFavicon();
  void ResetCrashedFavicon();

  void StopCrashAnimation();
  void StartCrashAnimation();

  // Returns true if the crash animation is currently running.
  bool IsPerformingCrashAnimation() const;

  // Starts the media indicator fade-in/out animation. There's no stop method
  // because this is not a continuous animation.
  void StartMediaIndicatorAnimation();

  // Schedules repaint task for icon.
  void ScheduleIconPaint();

  // Returns the rectangle for the light bar in immersive mode.
  gfx::Rect GetImmersiveBarRect() const;

  // Gets the tab id and frame id.
  void GetTabIdAndFrameId(views::Widget* widget,
                          int* tab_id,
                          int* frame_id) const;

  // Performs a one-time initialization of static resources such as tab images.
  static void InitTabResources();

  // Returns the minimum possible size of a single unselected Tab, not
  // including considering touch mode.
  static gfx::Size GetBasicMinimumUnselectedSize();

  // Loads the images to be used for the tab background.
  static void LoadTabImages();

  // Returns the cached image for the specified arguments, or an empty image if
  // there isn't one cached.
  static gfx::ImageSkia GetCachedImage(int resource_id,
                                       const gfx::Size& size,
                                       ui::ScaleFactor scale_factor);

  // Caches the specified image.
  static void SetCachedImage(int resource_id,
                             ui::ScaleFactor scale_factor,
                             const gfx::ImageSkia& image);

  // The controller, never NULL.
  TabController* controller_;

  TabRendererData data_;

  // True if the tab is being animated closed.
  bool closing_;

  // True if the tab is being dragged.
  bool dragging_;

  // The offset used to animate the favicon location. This is used when the tab
  // crashes.
  int favicon_hiding_offset_;

  // The current index of the loading animation. The range varies depending on
  // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
  int loading_animation_frame_;

  // Step in the immersive loading progress indicator.
  int immersive_loading_step_;

  bool should_display_crashed_favicon_;

  // Whole-tab throbbing "pulse" animation.
  scoped_ptr<gfx::Animation> tab_animation_;

  // Crash icon animation (in place of favicon).
  scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;

  // Media indicator fade-in/out animation (i.e., only on show/hide, not a
  // continuous animation).
  scoped_ptr<gfx::Animation> media_indicator_animation_;
  TabMediaState animating_media_state_;

  scoped_refptr<gfx::AnimationContainer> animation_container_;

  views::ImageButton* close_button_;

  bool tab_activated_with_last_gesture_begin_;

  views::GlowHoverController hover_controller_;

  // The bounds of various sections of the display.
  gfx::Rect favicon_bounds_;
  gfx::Rect title_bounds_;
  gfx::Rect media_indicator_bounds_;

  // The offset used to paint the inactive background image.
  gfx::Point background_offset_;

  struct TabImage {
    gfx::ImageSkia* image_l;
    gfx::ImageSkia* image_c;
    gfx::ImageSkia* image_r;
    int l_width;
    int r_width;
  };
  static TabImage tab_active_;
  static TabImage tab_inactive_;
  static TabImage tab_alpha_;

  // Whether we're showing the icon. It is cached so that we can detect when it
  // changes and layout appropriately.
  bool showing_icon_;

  // Whether we're showing the media indicator. It is cached so that we can
  // detect when it changes and layout appropriately.
  bool showing_media_indicator_;

  // Whether we are showing the close button. It is cached so that we can
  // detect when it changes and layout appropriately.
  bool showing_close_button_;

  // The current color of the close button.
  SkColor close_button_color_;

  static gfx::Font* font_;
  static int font_height_;

  // As the majority of the tabs are inactive, and painting tabs is slowish,
  // we cache a handful of the inactive tab backgrounds here.
  static ImageCache* image_cache_;

  DISALLOW_COPY_AND_ASSIGN(Tab);
};

#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_