1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/timer/timer.h"
#include "chrome/browser/ui/views/tabs/tab.h"
#include "chrome/browser/ui/views/tabs/tab_controller.h"
#include "ui/gfx/animation/animation_container.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/views/animation/bounds_animator.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/mouse_watcher.h"
#include "ui/views/view.h"
#include "ui/views/view_model.h"
#include "ui/views/view_targeter_delegate.h"
class NewTabButton;
class StackedTabStripLayout;
class Tab;
class TabDragController;
class TabStripController;
class TabStripObserver;
namespace ui {
class ListSelectionModel;
}
namespace views {
class ImageView;
}
///////////////////////////////////////////////////////////////////////////////
//
// TabStrip
//
// A View that represents the TabStripModel. The TabStrip has the
// following responsibilities:
// - It implements the TabStripModelObserver interface, and acts as a
// container for Tabs, and is also responsible for creating them.
// - It takes part in Tab Drag & Drop with Tab, TabDragHelper and
// DraggedTab, focusing on tasks that require reshuffling other tabs
// in response to dragged tabs.
//
///////////////////////////////////////////////////////////////////////////////
class TabStrip : public views::View,
public views::ButtonListener,
public views::MouseWatcherListener,
public views::ViewTargeterDelegate,
public TabController {
public:
static const char kViewClassName[];
// Horizontal offset for the new tab button to bring it closer to the
// rightmost tab.
static const int kNewTabButtonHorizontalOffset;
// The vertical offset of the tab strip button. This offset applies only to
// restored windows.
static const int kNewTabButtonVerticalOffset;
explicit TabStrip(TabStripController* controller);
virtual ~TabStrip();
// Add and remove observers to changes within this TabStrip.
void AddObserver(TabStripObserver* observer);
void RemoveObserver(TabStripObserver* observer);
// If |adjust_layout| is true the stacked layout changes based on whether the
// user uses a mouse or a touch device with the tabstrip.
void set_adjust_layout(bool adjust_layout) { adjust_layout_ = adjust_layout; }
// |stacked_layout_| defines what should happen when the tabs won't fit at
// their ideal size. When |stacked_layout_| is true the tabs are always sized
// to their ideal size and stacked on top of each other so that only a certain
// set of tabs are visible. This is used when the user uses a touch device.
// When |stacked_layout_| is false the tabs shrink to accommodate the
// available space. This is the default.
bool stacked_layout() const { return stacked_layout_; }
// Sets |stacked_layout_| and animates if necessary.
void SetStackedLayout(bool stacked_layout);
// Returns the bounds of the new tab button.
gfx::Rect GetNewTabButtonBounds();
// Returns true if the new tab button should be sized to the top of the tab
// strip.
bool SizeTabButtonToTopOfTabStrip();
// Starts highlighting the tab at the specified index.
void StartHighlight(int model_index);
// Stops all tab higlighting.
void StopAllHighlighting();
// Adds a tab at the specified index.
void AddTabAt(int model_index, const TabRendererData& data, bool is_active);
// Moves a tab.
void MoveTab(int from_model_index,
int to_model_index,
const TabRendererData& data);
// Removes a tab at the specified index.
void RemoveTabAt(int model_index);
// Sets the tab data at the specified model index.
void SetTabData(int model_index, const TabRendererData& data);
// Returns true if the tab is not partly or fully clipped (due to overflow),
// and the tab couldn't become partly clipped due to changing the selected tab
// (for example, if currently the strip has the last tab selected, and
// changing that to the first tab would cause |tab| to be pushed over enough
// to clip).
bool ShouldTabBeVisible(const Tab* tab) const;
// Invoked from the controller when the close initiates from the TabController
// (the user clicked the tab close button or middle clicked the tab). This is
// invoked from Close. Because of unload handlers Close is not always
// immediately followed by RemoveTabAt.
void PrepareForCloseAt(int model_index, CloseTabSource source);
// Invoked when the selection changes from |old_selection| to
// |new_selection|.
void SetSelection(const ui::ListSelectionModel& old_selection,
const ui::ListSelectionModel& new_selection);
// Invoked when the title of a tab changes and the tab isn't loading.
void TabTitleChangedNotLoading(int model_index);
// Retrieves the ideal bounds for the Tab at the specified index.
const gfx::Rect& ideal_bounds(int tab_data_index) {
return tabs_.ideal_bounds(tab_data_index);
}
// Returns the Tab at |index|.
Tab* tab_at(int index) const {
return static_cast<Tab*>(tabs_.view_at(index));
}
// Returns the index of the specified tab in the model coordinate system, or
// -1 if tab is closing or not valid.
int GetModelIndexOfTab(const Tab* tab) const;
// Gets the number of Tabs in the tab strip.
int tab_count() const { return tabs_.view_size(); }
// Cover method for TabStripController::GetCount.
int GetModelCount() const;
// Cover method for TabStripController::IsValidIndex.
bool IsValidModelIndex(int model_index) const;
TabStripController* controller() const { return controller_.get(); }
// Returns true if a drag session is currently active.
bool IsDragSessionActive() const;
// Returns true if a tab is being dragged into this tab strip.
bool IsActiveDropTarget() const;
// Returns true if the tab strip is editable. Returns false if the tab strip
// is being dragged or animated to prevent extensions from messing things up
// while that's happening.
bool IsTabStripEditable() const;
// Returns false when there is a drag operation in progress so that the frame
// doesn't close.
bool IsTabStripCloseable() const;
// Updates the loading animations displayed by tabs in the tabstrip to the
// next frame.
void UpdateLoadingAnimations();
// Returns true if the specified point (in TabStrip coordinates) is in the
// window caption area of the browser window.
bool IsPositionInWindowCaption(const gfx::Point& point);
// Returns true if the specified rect (in TabStrip coordinates) intersects
// the window caption area of the browser window.
bool IsRectInWindowCaption(const gfx::Rect& rect);
// Set the background offset used by inactive tabs to match the frame image.
void SetBackgroundOffset(const gfx::Point& offset);
// Sets a painting style with miniature "tab indicator" rectangles at the top.
void SetImmersiveStyle(bool enable);
// Returns true if Tabs in this TabStrip are currently changing size or
// position.
bool IsAnimating() const;
// Stops any ongoing animations. If |layout| is true and an animation is
// ongoing this does a layout.
void StopAnimating(bool layout);
// Called to indicate whether the given URL is a supported file.
void FileSupported(const GURL& url, bool supported);
// TabController overrides:
virtual const ui::ListSelectionModel& GetSelectionModel() OVERRIDE;
virtual bool SupportsMultipleSelection() OVERRIDE;
virtual void SelectTab(Tab* tab) OVERRIDE;
virtual void ExtendSelectionTo(Tab* tab) OVERRIDE;
virtual void ToggleSelected(Tab* tab) OVERRIDE;
virtual void AddSelectionFromAnchorTo(Tab* tab) OVERRIDE;
virtual void CloseTab(Tab* tab, CloseTabSource source) OVERRIDE;
virtual void ToggleTabAudioMute(Tab* tab) OVERRIDE;
virtual void ShowContextMenuForTab(Tab* tab,
const gfx::Point& p,
ui::MenuSourceType source_type) OVERRIDE;
virtual bool IsActiveTab(const Tab* tab) const OVERRIDE;
virtual bool IsTabSelected(const Tab* tab) const OVERRIDE;
virtual bool IsTabPinned(const Tab* tab) const OVERRIDE;
virtual void MaybeStartDrag(
Tab* tab,
const ui::LocatedEvent& event,
const ui::ListSelectionModel& original_selection) OVERRIDE;
virtual void ContinueDrag(views::View* view,
const ui::LocatedEvent& event) OVERRIDE;
virtual bool EndDrag(EndDragReason reason) OVERRIDE;
virtual Tab* GetTabAt(Tab* tab,
const gfx::Point& tab_in_tab_coordinates) OVERRIDE;
virtual void OnMouseEventInTab(views::View* source,
const ui::MouseEvent& event) OVERRIDE;
virtual bool ShouldPaintTab(const Tab* tab, gfx::Rect* clip) OVERRIDE;
virtual bool IsImmersiveStyle() const OVERRIDE;
virtual void UpdateTabAccessibilityState(const Tab* tab,
ui::AXViewState* state) OVERRIDE;
// MouseWatcherListener overrides:
virtual void MouseMovedOutOfHost() OVERRIDE;
// views::View overrides:
virtual void Layout() OVERRIDE;
virtual void PaintChildren(gfx::Canvas* canvas,
const views::CullSet& cull_set) OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual gfx::Size GetPreferredSize() const OVERRIDE;
// NOTE: the drag and drop methods are invoked from FrameView. This is done
// to allow for a drop region that extends outside the bounds of the TabStrip.
virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE;
virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE;
virtual void OnDragExited() OVERRIDE;
virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual views::View* GetTooltipHandlerForPoint(
const gfx::Point& point) OVERRIDE;
// Returns preferred height in immersive style.
static int GetImmersiveHeight();
private:
typedef std::vector<Tab*> Tabs;
typedef std::map<int, Tabs> TabsClosingMap;
typedef std::pair<TabsClosingMap::iterator,
Tabs::iterator> FindClosingTabResult;
class RemoveTabDelegate;
friend class TabDragController;
friend class TabDragControllerTest;
FRIEND_TEST_ALL_PREFIXES(TabDragControllerTest, GestureEndShouldEndDragTest);
friend class TabStripTest;
FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabHitTestMaskWhenStacked);
FRIEND_TEST_ALL_PREFIXES(TabStripTest, ClippedTabCloseButton);
// Used during a drop session of a url. Tracks the position of the drop as
// well as a window used to highlight where the drop occurs.
struct DropInfo {
DropInfo(int drop_index,
bool drop_before,
bool point_down,
views::Widget* context);
~DropInfo();
// Index of the tab to drop on. If drop_before is true, the drop should
// occur between the tab at drop_index - 1 and drop_index.
// WARNING: if drop_before is true it is possible this will == tab_count,
// which indicates the drop should create a new tab at the end of the tabs.
int drop_index;
bool drop_before;
// Direction the arrow should point in. If true, the arrow is displayed
// above the tab and points down. If false, the arrow is displayed beneath
// the tab and points up.
bool point_down;
// Renders the drop indicator.
views::Widget* arrow_window;
views::ImageView* arrow_view;
// The URL for the drop event.
GURL url;
// Whether the MIME type of the file pointed to by |url| is supported.
bool file_supported;
private:
DISALLOW_COPY_AND_ASSIGN(DropInfo);
};
// Horizontal gap between mini and non-mini-tabs.
static const int kMiniToNonMiniGap;
// The size of the new tab button must be hardcoded because we need to be
// able to lay it out before we are able to get its image from the
// ui::ThemeProvider. It also makes sense to do this, because the size of the
// new tab button should not need to be calculated dynamically.
static const int kNewTabButtonAssetWidth;
static const int kNewTabButtonAssetHeight;
void Init();
// Creates and returns a new tab. The caller owners the returned tab.
Tab* CreateTab();
// Invoked from |AddTabAt| after the newly created tab has been inserted.
void StartInsertTabAnimation(int model_index);
// Invoked from |MoveTab| after |tab_data_| has been updated to animate the
// move.
void StartMoveTabAnimation();
// Starts the remove tab animation.
void StartRemoveTabAnimation(int model_index);
// Schedules the animations and bounds changes necessary for a remove tab
// animation.
void ScheduleRemoveTabAnimation(Tab* tab);
// Animates all the views to their ideal bounds.
// NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds
// currently set in ideal_bounds.
void AnimateToIdealBounds();
// Returns whether the highlight button should be highlighted after a remove.
bool ShouldHighlightCloseButtonAfterRemove();
// Invoked from Layout if the size changes or layout is really needed.
void DoLayout();
// Sets the visibility state of all tabs based on ShouldTabBeVisible().
void SetTabVisibility();
// Drags the active tab by |delta|. |initial_positions| is the x-coordinates
// of the tabs when the drag started.
void DragActiveTab(const std::vector<int>& initial_positions, int delta);
// Sets the ideal bounds x-coordinates to |positions|.
void SetIdealBoundsFromPositions(const std::vector<int>& positions);
// Stacks the dragged tabs. This is used if the drag operation is
// MOVE_VISIBLE_TABS and the tabs don't fill the tabstrip. When this happens
// the active tab follows the mouse and the other tabs stack around it.
void StackDraggedTabs(int delta);
// Returns true if dragging has resulted in temporarily stacking the tabs.
bool IsStackingDraggedTabs() const;
// Invoked during drag to layout the tabs being dragged in |tabs| at
// |location|. If |initial_drag| is true, this is the initial layout after the
// user moved the mouse far enough to trigger a drag.
void LayoutDraggedTabsAt(const Tabs& tabs,
Tab* active_tab,
const gfx::Point& location,
bool initial_drag);
// Calculates the bounds needed for each of the tabs, placing the result in
// |bounds|.
void CalculateBoundsForDraggedTabs(const Tabs& tabs,
std::vector<gfx::Rect>* bounds);
// Returns the size needed for the specified tabs. This is invoked during drag
// and drop to calculate offsets and positioning.
int GetSizeNeededForTabs(const Tabs& tabs);
// Returns the number of mini-tabs.
int GetMiniTabCount() const;
// Returns the last tab in the strip that's actually visible. This will be
// the actual last tab unless the strip is in the overflow state.
const Tab* GetLastVisibleTab() const;
// Adds the tab at |index| to |tabs_closing_map_| and removes the tab from
// |tabs_|.
void RemoveTabFromViewModel(int index);
// Cleans up the Tab from the TabStrip. This is called from the tab animation
// code and is not a general-purpose method.
void RemoveAndDeleteTab(Tab* tab);
// Adjusts the indices of all tabs in |tabs_closing_map_| whose index is
// >= |index| to have a new index of |index + delta|.
void UpdateTabsClosingMap(int index, int delta);
// Used by TabDragController when the user starts or stops dragging tabs.
void StartedDraggingTabs(const Tabs& tabs);
// Invoked when TabDragController detaches a set of tabs.
void DraggedTabsDetached();
// Used by TabDragController when the user stops dragging tabs. |move_only| is
// true if the move behavior is TabDragController::MOVE_VISIBILE_TABS.
// |completed| is true if the drag operation completed successfully, false if
// it was reverted.
void StoppedDraggingTabs(const Tabs& tabs,
const std::vector<int>& initial_positions,
bool move_only,
bool completed);
// Invoked from StoppedDraggingTabs to cleanup |tab|. If |tab| is known
// |is_first_tab| is set to true.
void StoppedDraggingTab(Tab* tab, bool* is_first_tab);
// Takes ownership of |controller|.
void OwnDragController(TabDragController* controller);
// Destroys the current TabDragController. This cancel the existing drag
// operation.
void DestroyDragController();
// Releases ownership of the current TabDragController.
TabDragController* ReleaseDragController();
// Finds |tab| in the |tab_closing_map_| and returns a pair of iterators
// indicating precisely where it is.
FindClosingTabResult FindClosingTab(const Tab* tab);
// Paints all the tabs in |tabs_closing_map_[index]|.
void PaintClosingTabs(gfx::Canvas* canvas,
int index,
const views::CullSet& cull_set);
// Invoked when a mouse event occurs over |source|. Potentially switches the
// |stacked_layout_|.
void UpdateStackedLayoutFromMouseEvent(views::View* source,
const ui::MouseEvent& event);
// -- Tab Resize Layout -----------------------------------------------------
// Returns the exact (unrounded) current width of each tab.
void GetCurrentTabWidths(double* unselected_width,
double* selected_width) const;
// Returns the exact (unrounded) desired width of each tab, based on the
// desired strip width and number of tabs. If
// |width_of_tabs_for_mouse_close_| is nonnegative we use that value in
// calculating the desired strip width; otherwise we use the current width.
// |mini_tab_count| gives the number of mini-tabs and |tab_count| the number
// of mini and non-mini-tabs.
void GetDesiredTabWidths(int tab_count,
int mini_tab_count,
double* unselected_width,
double* selected_width) const;
// Perform an animated resize-relayout of the TabStrip immediately.
void ResizeLayoutTabs();
// Invokes ResizeLayoutTabs() as long as we're not in a drag session. If we
// are in a drag session this restarts the timer.
void ResizeLayoutTabsFromTouch();
// Restarts |resize_layout_timer_|.
void StartResizeLayoutTabsFromTouchTimer();
// Sets the bounds of the tabs to |tab_bounds|.
void SetTabBoundsForDrag(const std::vector<gfx::Rect>& tab_bounds);
// Ensure that the message loop observer used for event spying is added and
// removed appropriately so we can tell when to resize layout the tab strip.
void AddMessageLoopObserver();
void RemoveMessageLoopObserver();
// -- Link Drag & Drop ------------------------------------------------------
// Returns the bounds to render the drop at, in screen coordinates. Sets
// |is_beneath| to indicate whether the arrow is beneath the tab, or above
// it.
gfx::Rect GetDropBounds(int drop_index, bool drop_before, bool* is_beneath);
// Updates the location of the drop based on the event.
void UpdateDropIndex(const ui::DropTargetEvent& event);
// Sets the location of the drop, repainting as necessary.
void SetDropIndex(int tab_data_index, bool drop_before);
// Returns the drop effect for dropping a URL on the tab strip. This does
// not query the data in anyway, it only looks at the source operations.
int GetDropEffect(const ui::DropTargetEvent& event);
// Returns the image to use for indicating a drop on a tab. If is_down is
// true, this returns an arrow pointing down.
static gfx::ImageSkia* GetDropArrowImage(bool is_down);
// -- Animations ------------------------------------------------------------
// Invoked prior to starting a new animation.
void PrepareForAnimation();
// Generates the ideal bounds for each of the tabs as well as the new tab
// button.
void GenerateIdealBounds();
// Generates the ideal bounds for the mini tabs. Returns the index to position
// the first non-mini tab and sets |first_non_mini_index| to the index of the
// first non-mini tab.
int GenerateIdealBoundsForMiniTabs(int* first_non_mini_index);
// Returns the width needed for the new tab button (and padding).
static int new_tab_button_width() {
return kNewTabButtonAssetWidth + kNewTabButtonHorizontalOffset;
}
// Returns the width of the area that contains tabs. This does not include
// the width of the new tab button.
int tab_area_width() const { return width() - new_tab_button_width(); }
// Starts various types of TabStrip animations.
void StartResizeLayoutAnimation();
void StartMiniTabAnimation();
void StartMouseInitiatedRemoveTabAnimation(int model_index);
// Returns true if the specified point in TabStrip coords is within the
// hit-test region of the specified Tab.
bool IsPointInTab(Tab* tab, const gfx::Point& point_in_tabstrip_coords);
// -- Touch Layout ----------------------------------------------------------
// Returns the position normal tabs start at.
int GetStartXForNormalTabs() const;
// Returns the tab to use for event handling. This uses FindTabForEventFrom()
// to do the actual searching.
Tab* FindTabForEvent(const gfx::Point& point);
// Returns the tab to use for event handling starting at index |start| and
// iterating by |delta|.
Tab* FindTabForEventFrom(const gfx::Point& point, int start, int delta);
// For a given point, finds a tab that is hit by the point. If the point hits
// an area on which two tabs are overlapping, the tab is selected as follows:
// - If one of the tabs is active, select it.
// - Select the left one.
// If no tabs are hit, returns NULL.
views::View* FindTabHitByPoint(const gfx::Point& point);
// Returns the x-coordinates of the tabs.
std::vector<int> GetTabXCoordinates();
// Creates/Destroys |touch_layout_| as necessary.
void SwapLayoutIfNecessary();
// Returns true if |touch_layout_| is needed.
bool NeedsTouchLayout() const;
// Sets the value of |reset_to_shrink_on_exit_|. If true |mouse_watcher_| is
// used to track when the mouse truly exits the tabstrip and the stacked
// layout is reset.
void SetResetToShrinkOnExit(bool value);
// views::ButtonListener implementation:
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE;
// View overrides.
virtual const views::View* GetViewByID(int id) const OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseCaptureLost() OVERRIDE;
virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
// ui::EventHandler overrides.
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// views::ViewTargeterDelegate:
virtual views::View* TargetForRect(views::View* root,
const gfx::Rect& rect) OVERRIDE;
// -- Member Variables ------------------------------------------------------
// There is a one-to-one mapping between each of the tabs in the
// TabStripController (TabStripModel) and |tabs_|. Because we animate tab
// removal there exists a period of time where a tab is displayed but not in
// the model. When this occurs the tab is removed from |tabs_| and placed in
// |tabs_closing_map_|. When the animation completes the tab is removed from
// |tabs_closing_map_|. The painting code ensures both sets of tabs are
// painted, and the event handling code ensures only tabs in |tabs_| are used.
views::ViewModel tabs_;
TabsClosingMap tabs_closing_map_;
scoped_ptr<TabStripController> controller_;
// The "New Tab" button.
NewTabButton* newtab_button_;
// Ideal bounds of the new tab button.
gfx::Rect newtab_button_bounds_;
// The current widths of various types of tabs. We save these so that, as
// users close tabs while we're holding them at the same size, we can lay out
// tabs exactly and eliminate the "pixel jitter" we'd get from just leaving
// them all at their existing, rounded widths.
double current_unselected_width_;
double current_selected_width_;
// If this value is nonnegative, it is used in GetDesiredTabWidths() to
// calculate how much space in the tab strip to use for tabs. Most of the
// time this will be -1, but while we're handling closing a tab via the mouse,
// we'll set this to the edge of the last tab before closing, so that if we
// are closing the last tab and need to resize immediately, we'll resize only
// back to this width, thus once again placing the last tab under the mouse
// cursor.
int available_width_for_tabs_;
// True if PrepareForCloseAt has been invoked. When true remove animations
// preserve current tab bounds.
bool in_tab_close_;
// Valid for the lifetime of a drag over us.
scoped_ptr<DropInfo> drop_info_;
// To ensure all tabs pulse at the same time they share the same animation
// container. This is that animation container.
scoped_refptr<gfx::AnimationContainer> animation_container_;
// MouseWatcher is used for two things:
// . When a tab is closed to reset the layout.
// . When a mouse is used and the layout dynamically adjusts and is currently
// stacked (|stacked_layout_| is true).
scoped_ptr<views::MouseWatcher> mouse_watcher_;
// The controller for a drag initiated from a Tab. Valid for the lifetime of
// the drag session.
scoped_ptr<TabDragController> drag_controller_;
views::BoundsAnimator bounds_animator_;
// Size we last layed out at.
gfx::Size last_layout_size_;
// See description above stacked_layout().
bool stacked_layout_;
// Should the layout dynamically adjust?
bool adjust_layout_;
// Only used while in touch mode.
scoped_ptr<StackedTabStripLayout> touch_layout_;
// If true the |stacked_layout_| is set to false when the mouse exits the
// tabstrip (as determined using MouseWatcher).
bool reset_to_shrink_on_exit_;
// Location of the mouse at the time of the last move.
gfx::Point last_mouse_move_location_;
// Time of the last mouse move event.
base::TimeTicks last_mouse_move_time_;
// Number of mouse moves.
int mouse_move_count_;
// Timer used when a tab is closed and we need to relayout. Only used when a
// tab close comes from a touch device.
base::OneShotTimer<TabStrip> resize_layout_timer_;
// True if tabs are painted as rectangular light-bars.
bool immersive_style_;
// Our observers.
typedef ObserverList<TabStripObserver> TabStripObservers;
TabStripObservers observers_;
DISALLOW_COPY_AND_ASSIGN(TabStrip);
};
#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_
|