• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/masked_targeter_delegate.h"
21 #include "ui/views/view.h"
22 
23 class MediaIndicatorButton;
24 class TabController;
25 
26 namespace gfx {
27 class Animation;
28 class AnimationContainer;
29 class LinearAnimation;
30 class MultiAnimation;
31 class ThrobAnimation;
32 }
33 namespace views {
34 class ImageButton;
35 class Label;
36 }
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 //
40 //  A View that renders a Tab in a TabStrip.
41 //
42 ///////////////////////////////////////////////////////////////////////////////
43 class Tab : public gfx::AnimationDelegate,
44             public views::ButtonListener,
45             public views::ContextMenuController,
46             public views::MaskedTargeterDelegate,
47             public views::View {
48  public:
49   // The Tab's class name.
50   static const char kViewClassName[];
51 
52   explicit Tab(TabController* controller);
53   virtual ~Tab();
54 
controller()55   TabController* controller() const { return controller_; }
56 
57   // Used to set/check whether this Tab is being animated closed.
set_closing(bool closing)58   void set_closing(bool closing) { closing_ = closing; }
closing()59   bool closing() const { return closing_; }
60 
61   // See description above field.
set_dragging(bool dragging)62   void set_dragging(bool dragging) { dragging_ = dragging; }
dragging()63   bool dragging() const { return dragging_; }
64 
65   // Used to mark the tab as having been detached.  Once this has happened, the
66   // tab should be invisibly closed.  This is irreversible.
set_detached()67   void set_detached() { detached_ = true; }
detached()68   bool detached() const { return detached_; }
69 
70   // Sets the container all animations run from.
71   void set_animation_container(gfx::AnimationContainer* container);
72 
73   // Returns true if this tab is the active tab.
74   bool IsActive() const;
75 
76   // Returns true if the tab is selected.
77   bool IsSelected() const;
78 
79   // Sets the data this tabs displays. Invokes DataChanged.
80   void SetData(const TabRendererData& data);
data()81   const TabRendererData& data() const { return data_; }
82 
83   // Sets the network state. If the network state changes NetworkStateChanged is
84   // invoked.
85   void UpdateLoadingAnimation(TabRendererData::NetworkState state);
86 
87   // Starts/Stops a pulse animation.
88   void StartPulse();
89   void StopPulse();
90 
91   // Start/stop the mini-tab title animation.
92   void StartMiniTabTitleAnimation();
93   void StopMiniTabTitleAnimation();
94 
95   // Set the background offset used to match the image in the inactive tab
96   // to the frame image.
set_background_offset(const gfx::Point & offset)97   void set_background_offset(const gfx::Point& offset) {
98     background_offset_ = offset;
99   }
100 
101   // Returns true if this tab became the active tab selected in
102   // response to the last ui::ET_TAP_DOWN gesture dispatched to
103   // this tab. Only used for collecting UMA metrics.
104   // See ash/touch/touch_uma.cc.
tab_activated_with_last_tap_down()105   bool tab_activated_with_last_tap_down() const {
106     return tab_activated_with_last_tap_down_;
107   }
108 
hover_controller()109   views::GlowHoverController* hover_controller() {
110     return &hover_controller_;
111   }
112 
113   // Returns the inset within the first dragged tab to use when calculating the
114   // "drag insertion point".  If we simply used the x-coordinate of the tab,
115   // we'd be calculating based on a point well before where the user considers
116   // the tab to "be".  The value here is chosen to "feel good" based on the
117   // widths of the tab images and the tab overlap.
118   //
119   // Note that this must return a value smaller than the midpoint of any tab's
120   // width, or else the user won't be able to drag a tab to the left of the
121   // first tab in the strip.
leading_width_for_drag()122   static int leading_width_for_drag() { return 16; }
123 
124   // Returns the minimum possible size of a single unselected Tab.
125   static gfx::Size GetMinimumUnselectedSize();
126   // Returns the minimum possible size of a selected Tab. Selected tabs must
127   // always show a close button and have a larger minimum size than unselected
128   // tabs.
129   static gfx::Size GetMinimumSelectedSize();
130   // Returns the preferred size of a single Tab, assuming space is
131   // available.
132   static gfx::Size GetStandardSize();
133 
134   // Returns the width for touch tabs.
135   static int GetTouchWidth();
136 
137   // Returns the width for mini-tabs. Mini-tabs always have this width.
138   static int GetMiniWidth();
139 
140   // Returns the height for immersive mode tabs.
141   static int GetImmersiveHeight();
142 
143  private:
144   friend class TabTest;
145   FRIEND_TEST_ALL_PREFIXES(TabTest, CloseButtonLayout);
146 
147   friend class TabStripTest;
148   FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabHitTestMaskWhenStacked);
149   FRIEND_TEST_ALL_PREFIXES(TabStripTest, ClippedTabCloseButton);
150 
151   // The animation object used to swap the favicon with the sad tab icon.
152   class FaviconCrashAnimation;
153   class TabCloseButton;
154 
155   // Contains a cached image and the values used to generate it.
156   struct ImageCacheEntry {
157     ImageCacheEntry();
158     ~ImageCacheEntry();
159 
160     // ID of the resource used.
161     int resource_id;
162 
163     // Scale factor we're drawing it.
164     ui::ScaleFactor scale_factor;
165 
166     // The image.
167     gfx::ImageSkia image;
168   };
169 
170   typedef std::list<ImageCacheEntry> ImageCache;
171 
172   // gfx::AnimationDelegate:
173   virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
174   virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
175   virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
176 
177   // views::ButtonListener:
178   virtual void ButtonPressed(views::Button* sender,
179                              const ui::Event& event) OVERRIDE;
180 
181   // views::ContextMenuController:
182   virtual void ShowContextMenuForView(views::View* source,
183                                       const gfx::Point& point,
184                                       ui::MenuSourceType source_type) OVERRIDE;
185 
186   // views::MaskedTargeterDelegate:
187   virtual bool GetHitTestMask(gfx::Path* mask) const OVERRIDE;
188 
189   // views::View:
190   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
191   virtual void Layout() OVERRIDE;
192   virtual void OnThemeChanged() OVERRIDE;
193   virtual const char* GetClassName() const OVERRIDE;
194   virtual bool GetTooltipText(const gfx::Point& p,
195                               base::string16* tooltip) const OVERRIDE;
196   virtual bool GetTooltipTextOrigin(const gfx::Point& p,
197                                     gfx::Point* origin) const OVERRIDE;
198   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
199   virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
200   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
201   virtual void OnMouseCaptureLost() OVERRIDE;
202   virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
203   virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
204   virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
205   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
206 
207   // ui::EventHandler:
208   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
209 
210   // Invoked from Layout to adjust the position of the favicon or media
211   // indicator for mini tabs.
212   void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;
213 
214   // Invoked from SetData after |data_| has been updated to the new data.
215   void DataChanged(const TabRendererData& old);
216 
217   // Paint with the normal tab style.
218   void PaintTab(gfx::Canvas* canvas);
219 
220   // Paint with the "immersive mode" light-bar style.
221   void PaintImmersiveTab(gfx::Canvas* canvas);
222 
223   // Paint various portions of the Tab
224   void PaintTabBackground(gfx::Canvas* canvas);
225   void PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas);
226   void PaintInactiveTabBackground(gfx::Canvas* canvas);
227   void PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas,
228                                                  int tab_id);
229   void PaintActiveTabBackground(gfx::Canvas* canvas);
230 
231   // Paints the favicon, mirrored for RTL if needed.
232   void PaintIcon(gfx::Canvas* canvas);
233 
234   // Invoked if data_.network_state changes, or the network_state is not none.
235   void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
236                                TabRendererData::NetworkState state);
237 
238   // Returns the number of favicon-size elements that can fit in the tab's
239   // current size.
240   int IconCapacity() const;
241 
242   // Returns whether the Tab should display a favicon.
243   bool ShouldShowIcon() const;
244 
245   // Returns whether the Tab should display the media indicator.
246   bool ShouldShowMediaIndicator() const;
247 
248   // Returns whether the Tab should display a close button.
249   bool ShouldShowCloseBox() const;
250 
251   // Gets the throb value for the tab. When a tab is not selected the
252   // active background is drawn at |GetThrobValue()|%. This is used for hover,
253   // mini tab title change and pulsing.
254   double GetThrobValue();
255 
256   // Set the temporary offset for the favicon. This is used during the crash
257   // animation.
258   void SetFaviconHidingOffset(int offset);
259 
260   void DisplayCrashedFavicon();
261   void ResetCrashedFavicon();
262 
263   void StopCrashAnimation();
264   void StartCrashAnimation();
265 
266   // Returns true if the crash animation is currently running.
267   bool IsPerformingCrashAnimation() const;
268 
269   // Schedules repaint task for icon.
270   void ScheduleIconPaint();
271 
272   // Returns the rectangle for the light bar in immersive mode.
273   gfx::Rect GetImmersiveBarRect() const;
274 
275   // Gets the tab id and frame id.
276   void GetTabIdAndFrameId(views::Widget* widget,
277                           int* tab_id,
278                           int* frame_id) const;
279 
280   // Returns |media_indicator_button_|, creating it on-demand.
281   MediaIndicatorButton* GetMediaIndicatorButton();
282 
283   // Performs a one-time initialization of static resources such as tab images.
284   static void InitTabResources();
285 
286   // Returns the minimum possible size of a single unselected Tab, not
287   // including considering touch mode.
288   static gfx::Size GetBasicMinimumUnselectedSize();
289 
290   // Loads the images to be used for the tab background.
291   static void LoadTabImages();
292 
293   // Returns the cached image for the specified arguments, or an empty image if
294   // there isn't one cached.
295   static gfx::ImageSkia GetCachedImage(int resource_id,
296                                        const gfx::Size& size,
297                                        ui::ScaleFactor scale_factor);
298 
299   // Caches the specified image.
300   static void SetCachedImage(int resource_id,
301                              ui::ScaleFactor scale_factor,
302                              const gfx::ImageSkia& image);
303 
304   // The controller, never NULL.
305   TabController* const controller_;
306 
307   TabRendererData data_;
308 
309   // True if the tab is being animated closed.
310   bool closing_;
311 
312   // True if the tab is being dragged.
313   bool dragging_;
314 
315   // True if the tab has been detached.
316   bool detached_;
317 
318   // The offset used to animate the favicon location. This is used when the tab
319   // crashes.
320   int favicon_hiding_offset_;
321 
322   // The current index of the loading animation. The range varies depending on
323   // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
324   int loading_animation_frame_;
325 
326   // Step in the immersive loading progress indicator.
327   int immersive_loading_step_;
328 
329   bool should_display_crashed_favicon_;
330 
331   // Whole-tab throbbing "pulse" animation.
332   scoped_ptr<gfx::ThrobAnimation> pulse_animation_;
333 
334   scoped_ptr<gfx::MultiAnimation> mini_title_change_animation_;
335 
336   // Crash icon animation (in place of favicon).
337   scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;
338 
339   scoped_refptr<gfx::AnimationContainer> animation_container_;
340 
341   views::ImageButton* close_button_;
342   MediaIndicatorButton* media_indicator_button_;  // NULL until first use.
343   views::Label* title_;
344 
345   bool tab_activated_with_last_tap_down_;
346 
347   views::GlowHoverController hover_controller_;
348 
349   // The bounds of various sections of the display.
350   gfx::Rect favicon_bounds_;
351 
352   // The offset used to paint the inactive background image.
353   gfx::Point background_offset_;
354 
355   struct TabImage {
356     gfx::ImageSkia* image_l;
357     gfx::ImageSkia* image_c;
358     gfx::ImageSkia* image_r;
359     int l_width;
360     int r_width;
361   };
362   static TabImage tab_active_;
363   static TabImage tab_inactive_;
364   static TabImage tab_alpha_;
365 
366   // Whether we're showing the icon. It is cached so that we can detect when it
367   // changes and layout appropriately.
368   bool showing_icon_;
369 
370   // Whether we're showing the media indicator. It is cached so that we can
371   // detect when it changes and layout appropriately.
372   bool showing_media_indicator_;
373 
374   // Whether we are showing the close button. It is cached so that we can
375   // detect when it changes and layout appropriately.
376   bool showing_close_button_;
377 
378   // The current color of the close button.
379   SkColor close_button_color_;
380 
381   // As the majority of the tabs are inactive, and painting tabs is slowish,
382   // we cache a handful of the inactive tab backgrounds here.
383   static ImageCache* image_cache_;
384 
385   DISALLOW_COPY_AND_ASSIGN(Tab);
386 };
387 
388 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
389