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