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
|
// Copyright (c) 2009 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_COCOA_TAB_STRIP_CONTROLLER_H_
#define CHROME_BROWSER_COCOA_TAB_STRIP_CONTROLLER_H_
#import <Cocoa/Cocoa.h>
#include <deque>
#include <map>
#include "base/scoped_nsobject.h"
#include "base/scoped_ptr.h"
#import "chrome/browser/cocoa/tab_controller_target.h"
#import "third_party/GTM/AppKit/GTMWindowSheetController.h"
@class TabView;
@class TabStripView;
class Browser;
class ConstrainedWindowMac;
class TabStripModelObserverBridge;
class TabStripModel;
class TabContents;
class ToolbarModel;
// A class that handles managing the tab strip in a browser window. It uses
// a supporting C++ bridge object to register for notifications from the
// TabStripModel. The Obj-C part of this class handles drag and drop and all
// the other Cocoa-y aspects.
//
// When a new tab is created, we create a TabController which manages loading
// the contents, including toolbar, from a separate nib file. This controller
// then handles replacing the contentView of the window. As tabs are switched,
// the single child of the contentView is swapped around to hold the contents
// (toolbar and all) representing that tab.
@interface TabStripController :
NSObject<TabControllerTarget,
GTMWindowSheetControllerDelegate> {
@private
TabContents* currentTab_; // weak, tab for which we're showing state
scoped_nsobject<TabStripView> tabStripView_;
NSView* switchView_; // weak
scoped_nsobject<NSView> dragBlockingView_; // avoid bad window server drags
NSButton* newTabButton_; // weak, obtained from the nib.
// Tracks the newTabButton_ for rollovers.
scoped_nsobject<NSTrackingArea> newTabTrackingArea_;
scoped_ptr<TabStripModelObserverBridge> bridge_;
Browser* browser_; // weak
TabStripModel* tabStripModel_; // weak
// Access to the TabContentsControllers (which own the parent view
// for the toolbar and associated tab contents) given an index. This needs
// to be kept in the same order as the tab strip's model as we will be
// using its index from the TabStripModelObserver calls.
scoped_nsobject<NSMutableArray> tabContentsArray_;
// An array of TabControllers which manage the actual tab views. As above,
// this is kept in the same order as the tab strip model.
scoped_nsobject<NSMutableArray> tabArray_;
// Set of TabControllers that are currently animating closed.
scoped_nsobject<NSMutableSet> closingControllers_;
// These values are only used during a drag, and override tab positioning.
TabView* placeholderTab_; // weak. Tab being dragged
NSRect placeholderFrame_; // Frame to use
CGFloat placeholderStretchiness_; // Vertical force shown by streching tab.
NSRect droppedTabFrame_; // Initial frame of a dropped tab, for animation.
// Frame targets for all the current views.
// target frames are used because repeated requests to [NSView animator].
// aren't coalesced, so we store frames to avoid redundant calls.
scoped_nsobject<NSMutableDictionary> targetFrames_;
NSRect newTabTargetFrame_;
// If YES, do not show the new tab button during layout.
BOOL forceNewTabButtonHidden_;
// YES if we've successfully completed the initial layout. When this is
// NO, we probably don't want to do any animation because we're just coming
// into being.
BOOL initialLayoutComplete_;
// Width available for resizing the tabs (doesn't include the new tab
// button). Used to restrict the available width when closing many tabs at
// once to prevent them from resizing to fit the full width. If the entire
// width should be used, this will have a value of |kUseFullAvailableWidth|.
float availableResizeWidth_;
// A tracking area that's the size of the tab strip used to be notified
// when the mouse moves in the tab strip
scoped_nsobject<NSTrackingArea> trackingArea_;
TabView* hoveredTab_; // weak. Tab that the mouse is hovering over
// Array of subviews which are permanent (and which should never be removed),
// such as the new-tab button, but *not* the tabs themselves.
scoped_nsobject<NSMutableArray> permanentSubviews_;
// The default favicon, so we can use one copy for all buttons.
scoped_nsobject<NSImage> defaultFavIcon_;
// Manages per-tab sheets.
scoped_nsobject<GTMWindowSheetController> sheetController_;
// Is the mouse currently inside the strip;
BOOL mouseInside_;
// GTMWindowSheetController supports only one per-tab sheet at a time.
// Thus, keep a queue of sheets for every tab. The first element in the queue
// is the currently visible sheet, and when this sheet is closed, the next
// sheet in the queue will be shown.
std::map<NSView*, std::deque<ConstrainedWindowMac*> > constrainedWindows_;
}
// Initialize the controller with a view and browser that contains
// everything else we'll need. |switchView| is the view whose contents get
// "switched" every time the user switches tabs. The children of this view
// will be released, so if you want them to stay around, make sure
// you have retained them.
- (id)initWithView:(TabStripView*)view
switchView:(NSView*)switchView
browser:(Browser*)browser;
// Return the view for the currently selected tab.
- (NSView*)selectedTabView;
// Set the frame of the selected tab, also updates the internal frame dict.
- (void)setFrameOfSelectedTab:(NSRect)frame;
// Move the given tab at index |from| in this window to the location of the
// current placeholder.
- (void)moveTabFromIndex:(NSInteger)from;
// Drop a given TabContents at the location of the current placeholder. If there
// is no placeholder, it will go at the end. Used when dragging from another
// window when we don't have access to the TabContents as part of our strip.
// |frame| is in the coordinate system of the tab strip view and represents
// where the user dropped the new tab so it can be animated into its correct
// location when the tab is added to the model.
- (void)dropTabContents:(TabContents*)contents withFrame:(NSRect)frame;
// Returns the index of the subview |view|. Returns -1 if not present. Takes
// closing tabs into account such that this index will correctly match the tab
// model. If |view| is in the process of closing, returns -1, as closing tabs
// are no longer in the model.
- (NSInteger)modelIndexForTabView:(NSView*)view;
// Return the view at a given index.
- (NSView*)viewAtIndex:(NSUInteger)index;
// Set the placeholder for a dragged tab, allowing the |frame| and |strechiness|
// to be specified. This causes this tab to be rendered in an arbitrary position
- (void)insertPlaceholderForTab:(TabView*)tab
frame:(NSRect)frame
yStretchiness:(CGFloat)yStretchiness;
// Returns whether or not |tab| can still be fully seen in the tab strip or if
// its current position would cause it be obscured by things such as the edge
// of the window or the window decorations. Returns YES only if the entire tab
// is visible.
- (BOOL)isTabFullyVisible:(TabView*)tab;
// Show or hide the new tab button. The button is hidden immediately, but
// waits until the next call to |-layoutTabs| to show it again.
- (void)showNewTabButton:(BOOL)show;
// Force the tabs to rearrange themselves to reflect the current model.
- (void)layoutTabs;
// Are we in rapid (tab) closure mode? I.e., is a full layout deferred (while
// the user closes tabs)? Needed to overcome missing clicks during rapid tab
// closure.
- (BOOL)inRapidClosureMode;
// Returns YES if the user is allowed to drag tabs on the strip at this moment.
// For example, this returns NO if there are any pending tab close animtations.
- (BOOL)tabDraggingAllowed;
// Default height for tabs.
+ (CGFloat)defaultTabHeight;
// Effectively an implementation of the |URLDropTargetWindowController|
// protocol, which the |BrowserWindowController| just reflects to us. This
// needed for dropping URLs on the tab strip.
- (void)dropURLs:(NSArray*)urls at:(NSPoint)location;
- (void)indicateDropURLsAt:(NSPoint)location;
- (void)hideDropURLsIndicator;
// Returns the (lazily created) window sheet controller of this window. Used
// for the per-tab sheets.
- (GTMWindowSheetController*)sheetController;
// See comments in browser_window_controller.h for documentation about these
// functions.
- (BOOL)attachConstrainedWindow:(ConstrainedWindowMac*)window;
- (void)removeConstrainedWindow:(ConstrainedWindowMac*)window;
@end
// Notification sent when the number of tabs changes. The object will be this
// controller.
extern NSString* const kTabStripNumberOfTabsChanged;
#endif // CHROME_BROWSER_COCOA_TAB_STRIP_CONTROLLER_H_
|