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.
5 #ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
6 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_
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"
26 class AnimationContainer;
27 class LinearAnimation;
36 ///////////////////////////////////////////////////////////////////////////////
38 // A View that renders a Tab in a TabStrip.
40 ///////////////////////////////////////////////////////////////////////////////
41 class Tab : public gfx::AnimationDelegate,
42 public views::ButtonListener,
43 public views::ContextMenuController,
46 // The menu button's class name.
47 static const char kViewClassName[];
49 explicit Tab(TabController* controller);
52 // Used to set/check whether this Tab is being animated closed.
53 void set_closing(bool closing) { closing_ = closing; }
54 bool closing() const { return closing_; }
56 // See description above field.
57 void set_dragging(bool dragging) { dragging_ = dragging; }
58 bool dragging() const { return dragging_; }
60 // Used to mark the tab as having been detached. Once this has happened, the
61 // tab should be invisibly closed. This is irreversible.
62 void set_detached() { detached_ = true; }
63 bool detached() const { return detached_; }
65 // Sets the container all animations run from.
66 void set_animation_container(gfx::AnimationContainer* container);
68 // Returns true if this tab is the active tab.
69 bool IsActive() const;
71 // Returns true if the tab is selected.
72 bool IsSelected() const;
74 // Sets the data this tabs displays. Invokes DataChanged.
75 void SetData(const TabRendererData& data);
76 const TabRendererData& data() const { return data_; }
78 // Sets the network state. If the network state changes NetworkStateChanged is
80 void UpdateLoadingAnimation(TabRendererData::NetworkState state);
82 // Starts/Stops a pulse animation.
86 // Start/stop the mini-tab title animation.
87 void StartMiniTabTitleAnimation();
88 void StopMiniTabTitleAnimation();
90 // Set the background offset used to match the image in the inactive tab
91 // to the frame image.
92 void set_background_offset(const gfx::Point& offset) {
93 background_offset_ = offset;
96 // Returns true if this tab became the active tab selected in
97 // response to the last ui::ET_GESTURE_BEGIN gesture dispatched to
98 // this tab. Only used for collecting UMA metrics.
99 // See ash/touch/touch_uma.cc.
100 bool tab_activated_with_last_gesture_begin() const {
101 return tab_activated_with_last_gesture_begin_;
104 views::GlowHoverController* hover_controller() {
105 return &hover_controller_;
108 // Returns the inset within the first dragged tab to use when calculating the
109 // "drag insertion point". If we simply used the x-coordinate of the tab,
110 // we'd be calculating based on a point well before where the user considers
111 // the tab to "be". The value here is chosen to "feel good" based on the
112 // widths of the tab images and the tab overlap.
114 // Note that this must return a value smaller than the midpoint of any tab's
115 // width, or else the user won't be able to drag a tab to the left of the
116 // first tab in the strip.
117 static int leading_width_for_drag() { return 16; }
119 // Returns the minimum possible size of a single unselected Tab.
120 static gfx::Size GetMinimumUnselectedSize();
121 // Returns the minimum possible size of a selected Tab. Selected tabs must
122 // always show a close button and have a larger minimum size than unselected
124 static gfx::Size GetMinimumSelectedSize();
125 // Returns the preferred size of a single Tab, assuming space is
127 static gfx::Size GetStandardSize();
129 // Returns the width for touch tabs.
130 static int GetTouchWidth();
132 // Returns the width for mini-tabs. Mini-tabs always have this width.
133 static int GetMiniWidth();
135 // Returns the height for immersive mode tabs.
136 static int GetImmersiveHeight();
139 friend class TabTest;
140 FRIEND_TEST_ALL_PREFIXES(TabTest, CloseButtonLayout);
142 friend class TabStripTest;
143 FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabHitTestMaskWhenStacked);
144 FRIEND_TEST_ALL_PREFIXES(TabStripTest, ClippedTabCloseButton);
146 // The animation object used to swap the favicon with the sad tab icon.
147 class FaviconCrashAnimation;
148 class TabCloseButton;
150 // Contains a cached image and the values used to generate it.
151 struct ImageCacheEntry {
155 // ID of the resource used.
158 // Scale factor we're drawing it.
159 ui::ScaleFactor scale_factor;
162 gfx::ImageSkia image;
165 typedef std::list<ImageCacheEntry> ImageCache;
167 // Overridden from gfx::AnimationDelegate:
168 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
169 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
170 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
172 // Overridden from views::ButtonListener:
173 virtual void ButtonPressed(views::Button* sender,
174 const ui::Event& event) OVERRIDE;
176 // Overridden from views::ContextMenuController:
177 virtual void ShowContextMenuForView(views::View* source,
178 const gfx::Point& point,
179 ui::MenuSourceType source_type) OVERRIDE;
181 // Overridden from views::View:
182 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
183 virtual void Layout() OVERRIDE;
184 virtual void OnThemeChanged() OVERRIDE;
185 virtual const char* GetClassName() const OVERRIDE;
186 virtual bool HasHitTestMask() const OVERRIDE;
187 virtual void GetHitTestMask(HitTestSource source,
188 gfx::Path* path) const OVERRIDE;
189 virtual bool GetTooltipText(const gfx::Point& p,
190 base::string16* tooltip) const OVERRIDE;
191 virtual bool GetTooltipTextOrigin(const gfx::Point& p,
192 gfx::Point* origin) const OVERRIDE;
193 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
194 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
195 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
196 virtual void OnMouseCaptureLost() OVERRIDE;
197 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
198 virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
199 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
200 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
202 // Overridden from ui::EventHandler:
203 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
205 // Invoked from Layout to adjust the position of the favicon or media
206 // indicator for mini tabs.
207 void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;
209 // Invoked from SetData after |data_| has been updated to the new data.
210 void DataChanged(const TabRendererData& old);
212 // Paint with the normal tab style.
213 void PaintTab(gfx::Canvas* canvas);
215 // Paint with the "immersive mode" light-bar style.
216 void PaintImmersiveTab(gfx::Canvas* canvas);
218 // Paint various portions of the Tab
219 void PaintTabBackground(gfx::Canvas* canvas);
220 void PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas);
221 void PaintInactiveTabBackground(gfx::Canvas* canvas);
222 void PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas,
224 void PaintActiveTabBackground(gfx::Canvas* canvas);
226 // Paints the favicon and media indicator icon, mirrored for RTL if needed.
227 void PaintIcon(gfx::Canvas* canvas);
228 void PaintMediaIndicator(gfx::Canvas* canvas);
230 // Invoked if data_.network_state changes, or the network_state is not none.
231 void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
232 TabRendererData::NetworkState state);
234 // Returns the number of favicon-size elements that can fit in the tab's
236 int IconCapacity() const;
238 // Returns whether the Tab should display a favicon.
239 bool ShouldShowIcon() const;
241 // Returns whether the Tab should display the media indicator.
242 bool ShouldShowMediaIndicator() const;
244 // Returns whether the Tab should display a close button.
245 bool ShouldShowCloseBox() const;
247 // Gets the throb value for the tab. When a tab is not selected the
248 // active background is drawn at |GetThrobValue()|%. This is used for hover,
249 // mini tab title change and pulsing.
250 double GetThrobValue();
252 // Set the temporary offset for the favicon. This is used during the crash
254 void SetFaviconHidingOffset(int offset);
256 void DisplayCrashedFavicon();
257 void ResetCrashedFavicon();
259 void StopCrashAnimation();
260 void StartCrashAnimation();
262 // Returns true if the crash animation is currently running.
263 bool IsPerformingCrashAnimation() const;
265 // Starts the media indicator fade-in/out animation. There's no stop method
266 // because this is not a continuous animation.
267 void StartMediaIndicatorAnimation();
269 // Schedules repaint task for icon.
270 void ScheduleIconPaint();
272 // Returns the rectangle for the light bar in immersive mode.
273 gfx::Rect GetImmersiveBarRect() const;
275 // Gets the tab id and frame id.
276 void GetTabIdAndFrameId(views::Widget* widget,
278 int* frame_id) const;
280 // Performs a one-time initialization of static resources such as tab images.
281 static void InitTabResources();
283 // Returns the minimum possible size of a single unselected Tab, not
284 // including considering touch mode.
285 static gfx::Size GetBasicMinimumUnselectedSize();
287 // Loads the images to be used for the tab background.
288 static void LoadTabImages();
290 // Returns the cached image for the specified arguments, or an empty image if
291 // there isn't one cached.
292 static gfx::ImageSkia GetCachedImage(int resource_id,
293 const gfx::Size& size,
294 ui::ScaleFactor scale_factor);
296 // Caches the specified image.
297 static void SetCachedImage(int resource_id,
298 ui::ScaleFactor scale_factor,
299 const gfx::ImageSkia& image);
301 // The controller, never NULL.
302 TabController* controller_;
304 TabRendererData data_;
306 // True if the tab is being animated closed.
309 // True if the tab is being dragged.
312 // True if the tab has been detached.
315 // The offset used to animate the favicon location. This is used when the tab
317 int favicon_hiding_offset_;
319 // The current index of the loading animation. The range varies depending on
320 // whether the tab is loading or waiting, see AdvanceLoadingAnimation().
321 int loading_animation_frame_;
323 // Step in the immersive loading progress indicator.
324 int immersive_loading_step_;
326 bool should_display_crashed_favicon_;
328 // Whole-tab throbbing "pulse" animation.
329 scoped_ptr<gfx::ThrobAnimation> pulse_animation_;
331 scoped_ptr<gfx::MultiAnimation> mini_title_change_animation_;
333 // Crash icon animation (in place of favicon).
334 scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;
336 // Media indicator fade-in/out animation (i.e., only on show/hide, not a
337 // continuous animation).
338 scoped_ptr<gfx::Animation> media_indicator_animation_;
339 TabMediaState animating_media_state_;
341 scoped_refptr<gfx::AnimationContainer> animation_container_;
343 views::ImageButton* close_button_;
344 views::Label* title_;
346 bool tab_activated_with_last_gesture_begin_;
348 views::GlowHoverController hover_controller_;
350 // The bounds of various sections of the display.
351 gfx::Rect favicon_bounds_;
352 gfx::Rect media_indicator_bounds_;
354 // The offset used to paint the inactive background image.
355 gfx::Point background_offset_;
358 gfx::ImageSkia* image_l;
359 gfx::ImageSkia* image_c;
360 gfx::ImageSkia* image_r;
364 static TabImage tab_active_;
365 static TabImage tab_inactive_;
366 static TabImage tab_alpha_;
368 // Whether we're showing the icon. It is cached so that we can detect when it
369 // changes and layout appropriately.
372 // Whether we're showing the media indicator. It is cached so that we can
373 // detect when it changes and layout appropriately.
374 bool showing_media_indicator_;
376 // Whether we are showing the close button. It is cached so that we can
377 // detect when it changes and layout appropriately.
378 bool showing_close_button_;
380 // The current color of the close button.
381 SkColor close_button_color_;
383 // As the majority of the tabs are inactive, and painting tabs is slowish,
384 // we cache a handful of the inactive tab backgrounds here.
385 static ImageCache* image_cache_;
387 DISALLOW_COPY_AND_ASSIGN(Tab);
390 #endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_H_