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