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