OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h" | 5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #import "base/mac/bundle_locations.h" | 9 #import "base/mac/bundle_locations.h" |
10 #import "base/mac/foundation_util.h" | 10 #import "base/mac/foundation_util.h" |
(...skipping 25 matching lines...) Expand all Loading... | |
36 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.h" | 36 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.h" |
37 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" | 37 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" |
38 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h" | 38 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h" |
39 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controlle r.h" | 39 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controlle r.h" |
40 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h" | 40 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h" |
41 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h" | 41 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h" |
42 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h" | 42 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h" |
43 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.h" | 43 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.h" |
44 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h" | 44 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h" |
45 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 45 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
46 #import "chrome/browser/ui/cocoa/l10n_util.h" | |
46 #import "chrome/browser/ui/cocoa/menu_button.h" | 47 #import "chrome/browser/ui/cocoa/menu_button.h" |
47 #import "chrome/browser/ui/cocoa/themed_window.h" | 48 #import "chrome/browser/ui/cocoa/themed_window.h" |
48 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" | 49 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" |
49 #import "chrome/browser/ui/cocoa/view_id_util.h" | 50 #import "chrome/browser/ui/cocoa/view_id_util.h" |
50 #import "chrome/browser/ui/cocoa/view_resizer.h" | 51 #import "chrome/browser/ui/cocoa/view_resizer.h" |
51 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 52 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
52 #include "chrome/common/extensions/extension_constants.h" | 53 #include "chrome/common/extensions/extension_constants.h" |
53 #include "chrome/common/extensions/extension_metrics.h" | 54 #include "chrome/common/extensions/extension_metrics.h" |
54 #include "chrome/common/url_constants.h" | 55 #include "chrome/common/url_constants.h" |
55 #include "chrome/grit/generated_resources.h" | 56 #include "chrome/grit/generated_resources.h" |
(...skipping 15 matching lines...) Expand all Loading... | |
71 #include "ui/base/l10n/l10n_util_mac.h" | 72 #include "ui/base/l10n/l10n_util_mac.h" |
72 #include "ui/base/material_design/material_design_controller.h" | 73 #include "ui/base/material_design/material_design_controller.h" |
73 #include "ui/base/resource/resource_bundle.h" | 74 #include "ui/base/resource/resource_bundle.h" |
74 #include "ui/gfx/color_palette.h" | 75 #include "ui/gfx/color_palette.h" |
75 #include "ui/gfx/image/image.h" | 76 #include "ui/gfx/image/image.h" |
76 #include "ui/gfx/image/image_skia_util_mac.h" | 77 #include "ui/gfx/image/image_skia_util_mac.h" |
77 #include "ui/gfx/paint_vector_icon.h" | 78 #include "ui/gfx/paint_vector_icon.h" |
78 #include "ui/resources/grit/ui_resources.h" | 79 #include "ui/resources/grit/ui_resources.h" |
79 | 80 |
80 using base::UserMetricsAction; | 81 using base::UserMetricsAction; |
82 using bookmarks::BookmarkBarLayout; | |
81 using bookmarks::BookmarkModel; | 83 using bookmarks::BookmarkModel; |
82 using bookmarks::BookmarkNode; | 84 using bookmarks::BookmarkNode; |
83 using bookmarks::BookmarkNodeData; | 85 using bookmarks::BookmarkNodeData; |
84 using content::OpenURLParams; | 86 using content::OpenURLParams; |
85 using content::Referrer; | 87 using content::Referrer; |
86 using content::WebContents; | 88 using content::WebContents; |
87 | 89 |
88 // Bookmark bar state changing and animations | 90 // Bookmark bar state changing and animations |
89 // | 91 // |
90 // The bookmark bar has three real states: "showing" (a normal bar attached to | 92 // The bookmark bar has three real states: "showing" (a normal bar attached to |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 // Pointers to animation logic: | 139 // Pointers to animation logic: |
138 // - |-moveToState:withAnimation:| starts animations, deciding which ones we | 140 // - |-moveToState:withAnimation:| starts animations, deciding which ones we |
139 // know how to handle. | 141 // know how to handle. |
140 // - |-doBookmarkBarAnimation| has most of the actual logic. | 142 // - |-doBookmarkBarAnimation| has most of the actual logic. |
141 // - |-getDesiredToolbarHeightCompression| and |-toolbarDividerOpacity| contain | 143 // - |-getDesiredToolbarHeightCompression| and |-toolbarDividerOpacity| contain |
142 // related logic. | 144 // related logic. |
143 // - The BWC's |-layoutSubviews| needs to know how to position things. | 145 // - The BWC's |-layoutSubviews| needs to know how to position things. |
144 // - The BWC should implement |-bookmarkBar:didChangeFromState:toState:| and | 146 // - The BWC should implement |-bookmarkBar:didChangeFromState:toState:| and |
145 // |-bookmarkBar:willAnimateFromState:toState:| in order to inform the | 147 // |-bookmarkBar:willAnimateFromState:toState:| in order to inform the |
146 // toolbar of required changes. | 148 // toolbar of required changes. |
149 // | |
150 // Layout: | |
151 // | |
152 // Several events (initial load, changes to the bookmark model etc.) can | |
153 // require the bar layout to change. In most cases, this is accomplished | |
154 // by building a BookmarkBarLayout from the current state of the view, | |
155 // the bookmark model, and the managed bookmark service. If the calculated | |
156 // layout differs from the previous one, it's applied to the view | |
157 // via |applyLayout:animated:|. This is a cheap way to "coalesce" multiple | |
158 // potentially layout-changing events, since in practice, these events come | |
159 // in bursts and don't require a change. | |
160 // | |
161 // Temporary changes in layout during dragging are an exception to this, | |
162 // since the layout temporarily adjusts to the drag (for example, adding | |
163 // a placeholder space for a mid-drag button or removing the space previously | |
164 // taken up by a button which is being dragged off the bar). In this case, | |
165 // the original stored layout is maintained as the source of truth, and | |
166 // elements are laid out from a combination of the stored layout and the | |
167 // drag state. See |setDropInsertionPos:| for details. | |
147 | 168 |
148 namespace { | 169 namespace { |
149 | 170 |
150 // Duration of the bookmark bar animations. | 171 // Duration of the bookmark bar animations. |
151 const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; | 172 const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; |
152 const NSTimeInterval kDragAndDropAnimationDuration = 0.25; | 173 const NSTimeInterval kDragAndDropAnimationDuration = 0.25; |
153 | 174 |
175 const int kMaxReusePoolSize = 10; | |
176 | |
177 // Min width for no item text field and import bookmarks button. | |
178 const CGFloat kNoItemElementMinWidth = 30; | |
179 | |
154 void RecordAppLaunch(Profile* profile, GURL url) { | 180 void RecordAppLaunch(Profile* profile, GURL url) { |
155 const extensions::Extension* extension = | 181 const extensions::Extension* extension = |
156 extensions::ExtensionRegistry::Get(profile)-> | 182 extensions::ExtensionRegistry::Get(profile)-> |
157 enabled_extensions().GetAppByURL(url); | 183 enabled_extensions().GetAppByURL(url); |
158 if (!extension) | 184 if (!extension) |
159 return; | 185 return; |
160 | 186 |
161 extensions::RecordAppLaunchType(extension_misc::APP_LAUNCH_BOOKMARK_BAR, | 187 extensions::RecordAppLaunchType(extension_misc::APP_LAUNCH_BOOKMARK_BAR, |
162 extension->GetType()); | 188 extension->GetType()); |
163 } | 189 } |
164 | 190 |
191 const CGFloat kBookmarkButtonHeightMinusPadding = | |
192 bookmarks::kBookmarkButtonHeight - bookmarks::kBookmarkVerticalPadding * 2; | |
193 | |
165 } // namespace | 194 } // namespace |
166 | 195 |
167 @interface BookmarkBarController () | 196 namespace bookmarks { |
168 | 197 |
169 // Updates the sizes and positions of the subviews. | 198 BookmarkBarLayout::BookmarkBarLayout() |
170 - (void)layoutSubviews; | 199 : visible_elements(0), |
200 apps_button_offset(0), | |
201 managed_bookmarks_button_offset(0), | |
202 supervised_bookmarks_button_offset(0), | |
203 off_the_side_button_offset(0), | |
204 other_bookmarks_button_offset(0), | |
205 no_item_textfield_offset(0), | |
206 no_item_textfield_width(0), | |
207 import_bookmarks_button_offset(0), | |
208 import_bookmarks_button_width(0), | |
209 max_x(0){}; | |
210 BookmarkBarLayout::~BookmarkBarLayout(){}; | |
211 BookmarkBarLayout::BookmarkBarLayout(BookmarkBarLayout&& other) = default; | |
212 BookmarkBarLayout& BookmarkBarLayout::operator=(BookmarkBarLayout&& other) = | |
213 default; | |
171 | 214 |
172 // Moves to the given next state (from the current state), possibly animating. | 215 bool operator==(const BookmarkBarLayout& lhs, const BookmarkBarLayout& rhs) { |
173 // If |animate| is NO, it will stop any running animation and jump to the given | 216 return std::tie(lhs.visible_elements, lhs.apps_button_offset, |
174 // state. If YES, it may either (depending on implementation) jump to the end of | 217 lhs.managed_bookmarks_button_offset, |
175 // the current animation and begin the next one, or stop the current animation | 218 lhs.supervised_bookmarks_button_offset, |
176 // mid-flight and animate to the next state. | 219 lhs.off_the_side_button_offset, |
177 - (void)moveToState:(BookmarkBar::State)nextState | 220 lhs.other_bookmarks_button_offset, |
178 withAnimation:(BOOL)animate; | 221 lhs.no_item_textfield_offset, lhs.no_item_textfield_width, |
222 lhs.import_bookmarks_button_offset, | |
223 lhs.import_bookmarks_button_width, lhs.button_offsets, | |
224 lhs.max_x) == | |
225 std::tie( | |
226 rhs.visible_elements, rhs.apps_button_offset, | |
227 rhs.managed_bookmarks_button_offset, | |
228 rhs.supervised_bookmarks_button_offset, | |
229 rhs.off_the_side_button_offset, rhs.other_bookmarks_button_offset, | |
230 rhs.no_item_textfield_offset, rhs.no_item_textfield_width, | |
231 rhs.import_bookmarks_button_offset, | |
232 rhs.import_bookmarks_button_width, rhs.button_offsets, rhs.max_x); | |
233 } | |
179 | 234 |
180 // Create buttons for all items in the given bookmark node tree. | 235 bool operator!=(const BookmarkBarLayout& lhs, const BookmarkBarLayout& rhs) { |
181 // Modifies self->buttons_. Do not add more buttons than will fit on the view. | 236 return !(lhs == rhs); |
182 - (void)addNodesToButtonList:(const BookmarkNode*)node; | 237 } |
183 | 238 |
184 // Create an autoreleased button appropriate for insertion into the bookmark | 239 } // namespace bookmarks |
185 // bar. Update |xOffset| with the offset appropriate for the subsequent button. | |
186 - (BookmarkButton*)buttonForNode:(const BookmarkNode*)node | |
187 xOffset:(int*)xOffset; | |
188 | 240 |
189 // Find a parent whose button is visible on the bookmark bar. | 241 @implementation BookmarkBarController { |
190 - (BookmarkButton*)bookmarkButtonToPulseForNode:(const BookmarkNode*)node; | 242 BookmarkBarLayout layout_; |
243 CGFloat originalNoItemTextFieldWidth_; | |
244 CGFloat originalImportBookmarksButtonWidth_; | |
245 CGFloat originalNoItemInterelementPadding_; | |
246 BOOL didCreateExtraButtons_; | |
191 | 247 |
192 // Puts stuff into the final state without animating, stopping a running | 248 // Maps bookmark node IDs to instantiated buttons for ease of lookup. |
193 // animation if necessary. | 249 std::unordered_map<int64_t, base::scoped_nsobject<BookmarkButton>> |
194 - (void)finalizeState; | 250 nodeIdToButtonMap_; |
195 | 251 |
196 // Stops any current animation in its tracks (midway). | 252 // A place to stash bookmark buttons that have been removed from the bar |
197 - (void)stopCurrentAnimation; | 253 // so that they can be reused instead of creating new ones. |
198 | 254 base::scoped_nsobject<NSMutableArray> unusedButtonPool_; |
199 // Show/hide the bookmark bar. | 255 } |
200 // if |animate| is YES, the changes are made using the animator; otherwise they | |
201 // are made immediately. | |
202 - (void)showBookmarkBarWithAnimation:(BOOL)animate; | |
203 | |
204 // Handles animating the resize of the content view. Returns YES if it handled | |
205 // the animation, NO if not (and hence it should be done instantly). | |
206 - (BOOL)doBookmarkBarAnimation; | |
207 | |
208 // |point| is in the base coordinate system of the destination window; | |
209 // it comes from an id<NSDraggingInfo>. |copy| is YES if a copy is to be | |
210 // made and inserted into the new location while leaving the bookmark in | |
211 // the old location, otherwise move the bookmark by removing from its old | |
212 // location and inserting into the new location. | |
213 - (BOOL)dragBookmark:(const BookmarkNode*)sourceNode | |
214 to:(NSPoint)point | |
215 copy:(BOOL)copy; | |
216 | |
217 // Returns the index in the model for a drag to the location given by | |
218 // |point|. This is determined by finding the first button before the center | |
219 // of which |point| falls, scanning left to right. Note that, currently, only | |
220 // the x-coordinate of |point| is considered. Though not currently implemented, | |
221 // we may check for errors, in which case this would return negative value; | |
222 // callers should check for this. | |
223 - (int)indexForDragToPoint:(NSPoint)point; | |
224 | |
225 // Add or remove buttons to/from the bar until it is filled but not overflowed. | |
226 - (void)redistributeButtonsOnBarAsNeeded; | |
227 | |
228 // Determine the nature of the bookmark bar contents based on the number of | |
229 // buttons showing. If too many then show the off-the-side list, if none | |
230 // then show the no items label. | |
231 - (void)reconfigureBookmarkBar; | |
232 | |
233 - (int)preferredHeight; | |
234 - (void)addButtonsToView; | |
235 - (BOOL)setManagedBookmarksButtonVisibility; | |
236 - (BOOL)setSupervisedBookmarksButtonVisibility; | |
237 - (BOOL)setOtherBookmarksButtonVisibility; | |
238 - (BOOL)setAppsPageShortcutButtonVisibility; | |
239 - (BookmarkButton*)createCustomBookmarkButtonForCell:(NSCell*)cell; | |
240 - (void)createManagedBookmarksButton; | |
241 - (void)createSupervisedBookmarksButton; | |
242 - (void)createOtherBookmarksButton; | |
243 - (void)createAppsPageShortcutButton; | |
244 - (void)openAppsPage:(id)sender; | |
245 - (void)centerNoItemsLabel; | |
246 - (void)positionRightSideButtons; | |
247 - (void)watchForExitEvent:(BOOL)watch; | |
248 - (void)resetAllButtonPositionsWithAnimation:(BOOL)animate; | |
249 | |
250 @end | |
251 | |
252 @implementation BookmarkBarController | |
253 | 256 |
254 @synthesize currentState = currentState_; | 257 @synthesize currentState = currentState_; |
255 @synthesize lastState = lastState_; | 258 @synthesize lastState = lastState_; |
256 @synthesize isAnimationRunning = isAnimationRunning_; | 259 @synthesize isAnimationRunning = isAnimationRunning_; |
257 @synthesize delegate = delegate_; | 260 @synthesize delegate = delegate_; |
258 @synthesize stateAnimationsEnabled = stateAnimationsEnabled_; | 261 @synthesize stateAnimationsEnabled = stateAnimationsEnabled_; |
259 @synthesize innerContentAnimationsEnabled = innerContentAnimationsEnabled_; | 262 @synthesize innerContentAnimationsEnabled = innerContentAnimationsEnabled_; |
260 | 263 |
261 - (id)initWithBrowser:(Browser*)browser | 264 - (id)initWithBrowser:(Browser*)browser |
262 initialWidth:(CGFloat)initialWidth | 265 initialWidth:(CGFloat)initialWidth |
263 delegate:(id<BookmarkBarControllerDelegate>)delegate { | 266 delegate:(id<BookmarkBarControllerDelegate>)delegate { |
264 if ((self = [super initWithNibName:@"BookmarkBar" | 267 if ((self = [super initWithNibName:nil bundle:nil])) { |
265 bundle:base::mac::FrameworkBundle()])) { | |
266 currentState_ = BookmarkBar::HIDDEN; | 268 currentState_ = BookmarkBar::HIDDEN; |
267 lastState_ = BookmarkBar::HIDDEN; | 269 lastState_ = BookmarkBar::HIDDEN; |
268 | 270 |
269 browser_ = browser; | 271 browser_ = browser; |
270 initialWidth_ = initialWidth; | 272 initialWidth_ = initialWidth; |
271 bookmarkModel_ = | 273 bookmarkModel_ = |
272 BookmarkModelFactory::GetForBrowserContext(browser_->profile()); | 274 BookmarkModelFactory::GetForBrowserContext(browser_->profile()); |
273 managedBookmarkService_ = | 275 managedBookmarkService_ = |
274 ManagedBookmarkServiceFactory::GetForProfile(browser_->profile()); | 276 ManagedBookmarkServiceFactory::GetForProfile(browser_->profile()); |
275 buttons_.reset([[NSMutableArray alloc] init]); | 277 buttons_.reset([[NSMutableArray alloc] init]); |
278 unusedButtonPool_.reset([[NSMutableArray alloc] init]); | |
276 delegate_ = delegate; | 279 delegate_ = delegate; |
277 folderTarget_.reset( | 280 folderTarget_.reset( |
278 [[BookmarkFolderTarget alloc] initWithController:self | 281 [[BookmarkFolderTarget alloc] initWithController:self |
279 profile:browser_->profile()]); | 282 profile:browser_->profile()]); |
283 didCreateExtraButtons_ = NO; | |
280 | 284 |
281 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 285 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
282 folderImage_.reset( | 286 folderImage_.reset( |
283 rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER).CopyNSImage()); | 287 rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER).CopyNSImage()); |
284 folderImageWhite_.reset( | 288 folderImageWhite_.reset( |
285 rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER_WHITE).CopyNSImage()); | 289 rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER_WHITE).CopyNSImage()); |
286 | 290 |
287 const int kIconSize = 16; | 291 const int kIconSize = 16; |
288 defaultImage_.reset([NSImageFromImageSkia(gfx::CreateVectorIcon( | 292 defaultImage_.reset([NSImageFromImageSkia(gfx::CreateVectorIcon( |
289 omnibox::kHttpIcon, kIconSize, gfx::kChromeIconGrey)) retain]); | 293 omnibox::kHttpIcon, kIconSize, gfx::kChromeIconGrey)) retain]); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
326 initWithFrame:NSMakeRect(0, 0, initialWidth_, 0)] | 330 initWithFrame:NSMakeRect(0, 0, initialWidth_, 0)] |
327 autorelease]]; | 331 autorelease]]; |
328 [[self view] setHidden:YES]; | 332 [[self view] setHidden:YES]; |
329 [[self view] setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin]; | 333 [[self view] setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin]; |
330 [[self controlledView] setController:self]; | 334 [[self controlledView] setController:self]; |
331 [[self controlledView] setDelegate:self]; | 335 [[self controlledView] setDelegate:self]; |
332 | 336 |
333 buttonView_.reset([[BookmarkBarView alloc] | 337 buttonView_.reset([[BookmarkBarView alloc] |
334 initWithController:self | 338 initWithController:self |
335 frame:NSMakeRect(0, -2, 584, 144)]); | 339 frame:NSMakeRect(0, -2, 584, 144)]); |
336 [buttonView_ setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin | | 340 [buttonView_ setAutoresizingMask:NSViewWidthSizable | NSViewMaxXMargin]; |
337 NSViewMaxXMargin]; | |
338 [[buttonView_ importBookmarksButton] setTarget:self]; | 341 [[buttonView_ importBookmarksButton] setTarget:self]; |
339 [[buttonView_ importBookmarksButton] setAction:@selector(importBookmarks:)]; | 342 [[buttonView_ importBookmarksButton] setAction:@selector(importBookmarks:)]; |
340 | 343 |
341 [self createOffTheSideButton]; | 344 [self.view addSubview:buttonView_]; |
342 [buttonView_ addSubview:offTheSideButton_]; | |
343 | 345 |
344 [self.view addSubview:buttonView_]; | 346 // viewDidLoad became part of the API in 10.10. |
345 // viewDidLoad became part of the API in 10.10 | |
346 if (!base::mac::IsAtLeastOS10_10()) | 347 if (!base::mac::IsAtLeastOS10_10()) |
347 [self viewDidLoad]; | 348 [self viewDidLoad]; |
348 } | 349 } |
349 | 350 |
350 - (BookmarkButton*)bookmarkButtonToPulseForNode:(const BookmarkNode*)node { | 351 - (BookmarkButton*)findAncestorButtonOnBarForNode:(const BookmarkNode*)node { |
Avi (use Gerrit)
2017/04/10 20:25:54
Nice rename.
| |
351 // Find the closest parent that is visible on the bar. | 352 // Find the closest parent that is visible on the bar. |
352 while (node) { | 353 while (node) { |
353 // Check if we've reached one of the special buttons. Otherwise, if the next | 354 // Check if we've reached one of the special buttons. Otherwise, if the next |
354 // parent is the boomark bar, find the corresponding button. | 355 // parent is the boomark bar, find the corresponding button. |
355 if ([managedBookmarksButton_ bookmarkNode] == node) | 356 if ([managedBookmarksButton_ bookmarkNode] == node) |
356 return managedBookmarksButton_; | 357 return managedBookmarksButton_; |
357 | 358 |
358 if ([supervisedBookmarksButton_ bookmarkNode] == node) | 359 if ([supervisedBookmarksButton_ bookmarkNode] == node) |
359 return supervisedBookmarksButton_; | 360 return supervisedBookmarksButton_; |
360 | 361 |
(...skipping 14 matching lines...) Expand all Loading... | |
375 | 376 |
376 node = node->parent(); | 377 node = node->parent(); |
377 } | 378 } |
378 NOTREACHED(); | 379 NOTREACHED(); |
379 return nil; | 380 return nil; |
380 } | 381 } |
381 | 382 |
382 - (void)startPulsingBookmarkNode:(const BookmarkNode*)node { | 383 - (void)startPulsingBookmarkNode:(const BookmarkNode*)node { |
383 [self stopPulsingBookmarkNode]; | 384 [self stopPulsingBookmarkNode]; |
384 | 385 |
385 pulsingButton_.reset([self bookmarkButtonToPulseForNode:node], | 386 pulsingButton_.reset([self findAncestorButtonOnBarForNode:node], |
386 base::scoped_policy::RETAIN); | 387 base::scoped_policy::RETAIN); |
387 if (!pulsingButton_) | 388 if (!pulsingButton_) |
388 return; | 389 return; |
389 | 390 |
390 [pulsingButton_ setPulseIsStuckOn:YES]; | 391 [pulsingButton_ setPulseIsStuckOn:YES]; |
391 pulsingBookmarkObserver_.reset( | 392 pulsingBookmarkObserver_.reset( |
392 new BookmarkModelObserverForCocoa(bookmarkModel_, ^() { | 393 new BookmarkModelObserverForCocoa(bookmarkModel_, ^() { |
393 // Stop pulsing if anything happened to the node. | 394 // Stop pulsing if anything happened to the node. |
394 [self stopPulsingBookmarkNode]; | 395 [self stopPulsingBookmarkNode]; |
395 })); | 396 })); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 // Remove our view from its superview so it doesn't attempt to reference | 432 // Remove our view from its superview so it doesn't attempt to reference |
432 // it when the controller is gone. | 433 // it when the controller is gone. |
433 //TODO(dmaclach): Remove -- http://crbug.com/25845 | 434 //TODO(dmaclach): Remove -- http://crbug.com/25845 |
434 [view removeFromSuperview]; | 435 [view removeFromSuperview]; |
435 | 436 |
436 // Be sure there is no dangling pointer. | 437 // Be sure there is no dangling pointer. |
437 if ([view respondsToSelector:@selector(setController:)]) | 438 if ([view respondsToSelector:@selector(setController:)]) |
438 [view performSelector:@selector(setController:) withObject:nil]; | 439 [view performSelector:@selector(setController:) withObject:nil]; |
439 | 440 |
440 // For safety, make sure the buttons can no longer call us. | 441 // For safety, make sure the buttons can no longer call us. |
442 base::scoped_nsobject<NSMutableArray> buttons([buttons_ mutableCopy]); | |
443 [buttons addObjectsFromArray:unusedButtonPool_]; | |
444 if (didCreateExtraButtons_) { | |
445 [buttons addObjectsFromArray:@[ | |
446 appsPageShortcutButton_, managedBookmarksButton_, | |
447 supervisedBookmarksButton_, otherBookmarksButton_, offTheSideButton_ | |
448 ]]; | |
449 } | |
450 | |
441 for (BookmarkButton* button in buttons_.get()) { | 451 for (BookmarkButton* button in buttons_.get()) { |
Avi (use Gerrit)
2017/04/10 20:25:54
Do you mean
for (.... in buttons.get()) ?
Otherw
lgrey
2017/04/26 20:12:56
Doh! Thanks for this catch
| |
442 [button setDelegate:nil]; | 452 [button setDelegate:nil]; |
443 [button setTarget:nil]; | 453 [button setTarget:nil]; |
444 [button setAction:nil]; | 454 [button setAction:nil]; |
445 } | 455 } |
446 | |
447 bridge_.reset(NULL); | 456 bridge_.reset(NULL); |
448 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 457 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
449 [self watchForExitEvent:NO]; | 458 [self watchForExitEvent:NO]; |
450 browser_ = nullptr; | 459 browser_ = nullptr; |
451 } | 460 } |
452 | 461 |
453 - (void)viewDidLoad { | 462 - (void)viewDidLoad { |
454 // We are enabled by default. | 463 // We are enabled by default. |
455 barIsEnabled_ = YES; | 464 barIsEnabled_ = YES; |
456 | 465 |
457 // Remember the original sizes of the 'no items' and 'import bookmarks' | 466 // Remember the original sizes of the 'no items' and 'import bookmarks' |
458 // fields to aid in resizing when the window frame changes. | 467 // fields to aid in resizing when the window frame changes. |
459 originalNoItemsRect_ = [[buttonView_ noItemTextfield] frame]; | 468 NSRect noItemTextFieldFrame = [[buttonView_ noItemTextField] frame]; |
460 originalImportBookmarksRect_ = [[buttonView_ importBookmarksButton] frame]; | 469 NSRect noItemButtonFrame = [[buttonView_ importBookmarksButton] frame]; |
470 originalNoItemTextFieldWidth_ = NSWidth(noItemTextFieldFrame); | |
471 originalImportBookmarksButtonWidth_ = NSWidth(noItemButtonFrame); | |
472 originalNoItemInterelementPadding_ = | |
473 NSMinX(noItemButtonFrame) - NSMaxX(noItemTextFieldFrame); | |
461 | 474 |
462 // Bookmark buttons start farther from the bookmark bar's left edge so | |
463 // adjust the positions of the noItems and importBookmarks textfields. | |
464 const CGFloat kBookmarksTextfieldOffsetX = 14; | |
465 originalNoItemsRect_.origin.x += kBookmarksTextfieldOffsetX; | |
466 [[buttonView_ noItemTextfield] setFrame:originalNoItemsRect_]; | |
467 | |
468 originalImportBookmarksRect_.origin.x += kBookmarksTextfieldOffsetX; | |
469 [[buttonView_ importBookmarksButton] setFrame:originalImportBookmarksRect_]; | |
470 | |
471 // When resized we may need to add new buttons, or remove them (if | |
472 // no longer visible), or add/remove the "off the side" menu. | |
473 [[self view] setPostsFrameChangedNotifications:YES]; | 475 [[self view] setPostsFrameChangedNotifications:YES]; |
474 [[NSNotificationCenter defaultCenter] | 476 [[NSNotificationCenter defaultCenter] |
475 addObserver:self | 477 addObserver:self |
476 selector:@selector(frameDidChange) | 478 selector:@selector(frameDidChange) |
477 name:NSViewFrameDidChangeNotification | 479 name:NSViewFrameDidChangeNotification |
478 object:[self view]]; | 480 object:[self view]]; |
479 | 481 |
480 // Watch for things going to or from fullscreen. | 482 // Watch for things going to or from fullscreen. |
481 [[NSNotificationCenter defaultCenter] | 483 [[NSNotificationCenter defaultCenter] |
482 addObserver:self | 484 addObserver:self |
483 selector:@selector(willEnterOrLeaveFullscreen:) | 485 selector:@selector(willEnterOrLeaveFullscreen:) |
484 name:NSWindowWillEnterFullScreenNotification | 486 name:NSWindowWillEnterFullScreenNotification |
485 object:nil]; | 487 object:nil]; |
486 [[NSNotificationCenter defaultCenter] | 488 [[NSNotificationCenter defaultCenter] |
487 addObserver:self | 489 addObserver:self |
488 selector:@selector(willEnterOrLeaveFullscreen:) | 490 selector:@selector(willEnterOrLeaveFullscreen:) |
489 name:NSWindowWillExitFullScreenNotification | 491 name:NSWindowWillExitFullScreenNotification |
490 object:nil]; | 492 object:nil]; |
493 [self layoutSubviews]; | |
Avi (use Gerrit)
2017/04/10 20:25:54
extra line before, so that's it's not clustered un
lgrey
2017/04/26 20:12:56
Done.
| |
491 | 494 |
492 // Don't pass ourself along (as 'self') until our init is completely | 495 // Don't pass ourself along (as 'self') until our init is completely |
493 // done. Thus, this call is (almost) last. | 496 // done. Thus, this call is (almost) last. |
494 bridge_.reset(new BookmarkBarBridge(browser_->profile(), self, | 497 bridge_.reset(new BookmarkBarBridge(browser_->profile(), self, |
495 bookmarkModel_)); | 498 bookmarkModel_)); |
496 } | 499 } |
497 | 500 |
498 // Called by our main view (a BookmarkBarView) when it gets moved to a | 501 // Called by our main view (a BookmarkBarView) when it gets moved to a |
499 // window. We perform operations which need to know the relevant | 502 // window. We perform operations which need to know the relevant |
500 // window (e.g. watch for a window close) so they can't be performed | 503 // window (e.g. watch for a window close) so they can't be performed |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
546 - (void)parentWindowDidResignMain:(NSNotification*)notification { | 549 - (void)parentWindowDidResignMain:(NSNotification*)notification { |
547 [self closeFolderAndStopTrackingMenus]; | 550 [self closeFolderAndStopTrackingMenus]; |
548 } | 551 } |
549 | 552 |
550 - (void)layoutToFrame:(NSRect)frame { | 553 - (void)layoutToFrame:(NSRect)frame { |
551 // The view should be pinned to the top of the window with a flexible width. | 554 // The view should be pinned to the top of the window with a flexible width. |
552 DCHECK_EQ(NSViewWidthSizable | NSViewMinYMargin, | 555 DCHECK_EQ(NSViewWidthSizable | NSViewMinYMargin, |
553 [[self view] autoresizingMask]); | 556 [[self view] autoresizingMask]); |
554 [[self view] setFrame:frame]; | 557 [[self view] setFrame:frame]; |
555 [self layoutSubviews]; | 558 [self layoutSubviews]; |
559 [self frameDidChange]; | |
556 } | 560 } |
557 | 561 |
558 // Change the layout of the bookmark bar's subviews in response to a visibility | 562 // Change the layout of the bookmark bar's subviews in response to a visibility |
559 // change (e.g., show or hide the bar) or style change (attached or floating). | 563 // change (e.g., show or hide the bar) or style change (attached or floating). |
560 - (void)layoutSubviews { | 564 - (void)layoutSubviews { |
561 NSRect frame = [[self view] frame]; | 565 NSRect frame = [[self view] frame]; |
562 NSRect buttonViewFrame = NSMakeRect(0, 0, NSWidth(frame), NSHeight(frame)); | 566 NSRect buttonViewFrame = NSMakeRect(0, 0, NSWidth(frame), NSHeight(frame)); |
563 | 567 |
564 // Add padding to the detached bookmark bar. | 568 // Add padding to the detached bookmark bar. |
565 // The state of our morph (if any); 1 is total bubble, 0 is the regular bar. | 569 // The state of our morph (if any); 1 is total bubble, 0 is the regular bar. |
566 CGFloat morph = [self detachedMorphProgress]; | 570 CGFloat morph = [self detachedMorphProgress]; |
567 CGFloat padding = 0; | 571 CGFloat padding = 0; |
568 padding = bookmarks::kNTPBookmarkBarPadding; | 572 padding = bookmarks::kNTPBookmarkBarPadding; |
569 buttonViewFrame = | 573 buttonViewFrame = |
570 NSInsetRect(buttonViewFrame, morph * padding, morph * padding); | 574 NSInsetRect(buttonViewFrame, morph * padding, morph * padding); |
571 | |
572 [buttonView_ setFrame:buttonViewFrame]; | 575 [buttonView_ setFrame:buttonViewFrame]; |
573 | 576 |
574 // Update bookmark button backgrounds. | 577 // Update bookmark button backgrounds. |
575 if ([self isAnimationRunning]) { | 578 if ([self isAnimationRunning]) { |
576 for (NSButton* button in buttons_.get()) | 579 for (NSButton* button in buttons_.get()) |
577 [button setNeedsDisplay:YES]; | 580 [button setNeedsDisplay:YES]; |
578 // Update the apps and other buttons explicitly, since they are not in the | 581 // Update the apps and other buttons explicitly, since they are not in the |
579 // buttons_ array. | 582 // buttons_ array. |
580 [appsPageShortcutButton_ setNeedsDisplay:YES]; | 583 [appsPageShortcutButton_ setNeedsDisplay:YES]; |
581 [managedBookmarksButton_ setNeedsDisplay:YES]; | 584 [managedBookmarksButton_ setNeedsDisplay:YES]; |
582 [supervisedBookmarksButton_ setNeedsDisplay:YES]; | 585 [supervisedBookmarksButton_ setNeedsDisplay:YES]; |
583 [otherBookmarksButton_ setNeedsDisplay:YES]; | 586 [otherBookmarksButton_ setNeedsDisplay:YES]; |
584 } | 587 } |
585 } | 588 } |
586 | 589 |
587 // We don't change a preference; we only change visibility. Preference changing | 590 // We don't change a preference; we only change visibility. Preference changing |
588 // (global state) is handled in |chrome::ToggleBookmarkBarWhenVisible()|. We | 591 // (global state) is handled in |chrome::ToggleBookmarkBarWhenVisible()|. We |
589 // simply update based on what we're told. | 592 // simply update based on what we're told. |
590 - (void)updateVisibility { | 593 - (void)updateVisibility { |
591 [self showBookmarkBarWithAnimation:NO]; | 594 [self showBookmarkBarWithAnimation:NO]; |
592 } | 595 } |
593 | 596 |
594 - (void)updateExtraButtonsVisibility { | |
595 if (!appsPageShortcutButton_.get() || | |
596 !managedBookmarksButton_.get() || | |
597 !supervisedBookmarksButton_.get()) { | |
598 return; | |
599 } | |
600 [self setAppsPageShortcutButtonVisibility]; | |
601 [self setManagedBookmarksButtonVisibility]; | |
602 [self setSupervisedBookmarksButtonVisibility]; | |
603 [self resetAllButtonPositionsWithAnimation:NO]; | |
604 [self reconfigureBookmarkBar]; | |
605 } | |
606 | |
607 - (void)updateHiddenState { | 597 - (void)updateHiddenState { |
608 BOOL oldHidden = [[self view] isHidden]; | 598 BOOL oldHidden = [[self view] isHidden]; |
609 BOOL newHidden = ![self isVisible]; | 599 BOOL newHidden = ![self isVisible]; |
610 if (oldHidden != newHidden) | 600 if (oldHidden != newHidden) |
611 [[self view] setHidden:newHidden]; | 601 [[self view] setHidden:newHidden]; |
612 } | 602 } |
613 | 603 |
614 - (void)setBookmarkBarEnabled:(BOOL)enabled { | 604 - (void)setBookmarkBarEnabled:(BOOL)enabled { |
615 if (enabled != barIsEnabled_) { | 605 if (enabled != barIsEnabled_) { |
616 barIsEnabled_ = enabled; | 606 barIsEnabled_ = enabled; |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
821 DCHECK([[sender cell] isKindOfClass:[BookmarkButtonCell class]]); | 811 DCHECK([[sender cell] isKindOfClass:[BookmarkButtonCell class]]); |
822 | 812 |
823 // Only record the action if it's the initial folder being opened. | 813 // Only record the action if it's the initial folder being opened. |
824 if (!showFolderMenus_) | 814 if (!showFolderMenus_) |
825 RecordBookmarkFolderOpen([self bookmarkLaunchLocation]); | 815 RecordBookmarkFolderOpen([self bookmarkLaunchLocation]); |
826 showFolderMenus_ = !showFolderMenus_; | 816 showFolderMenus_ = !showFolderMenus_; |
827 | 817 |
828 // Middle click on chevron should not open bookmarks under it, instead just | 818 // Middle click on chevron should not open bookmarks under it, instead just |
829 // open its folder menu. | 819 // open its folder menu. |
830 if (sender == offTheSideButton_.get()) { | 820 if (sender == offTheSideButton_.get()) { |
831 [[sender cell] setStartingChildIndex:displayedButtonCount_]; | 821 [[sender cell] setStartingChildIndex:layout_.VisibleButtonCount()]; |
832 NSEvent* event = [NSApp currentEvent]; | 822 NSEvent* event = [NSApp currentEvent]; |
833 if ([event type] == NSOtherMouseUp) { | 823 if ([event type] == NSOtherMouseUp) { |
834 [self openOrCloseBookmarkFolderForOffTheSideButton]; | 824 [self openOrCloseBookmarkFolderForOffTheSideButton]; |
835 return; | 825 return; |
836 } | 826 } |
837 } | 827 } |
838 // Toggle presentation of bar folder menus. | 828 // Toggle presentation of bar folder menus. |
839 [folderTarget_ openBookmarkFolderFromButton:sender]; | 829 [folderTarget_ openBookmarkFolderFromButton:sender]; |
840 } | 830 } |
841 | 831 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
884 - (void)themeDidChangeNotification:(NSNotification*)notification { | 874 - (void)themeDidChangeNotification:(NSNotification*)notification { |
885 [self updateTheme:[[[self view] window] themeProvider]]; | 875 [self updateTheme:[[[self view] window] themeProvider]]; |
886 } | 876 } |
887 | 877 |
888 - (BookmarkLaunchLocation)bookmarkLaunchLocation { | 878 - (BookmarkLaunchLocation)bookmarkLaunchLocation { |
889 return currentState_ == BookmarkBar::DETACHED ? | 879 return currentState_ == BookmarkBar::DETACHED ? |
890 BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR : | 880 BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR : |
891 BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR; | 881 BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR; |
892 } | 882 } |
893 | 883 |
894 // Position the right-side buttons including the off-the-side chevron. | |
895 - (void)positionRightSideButtons { | |
896 int maxX = NSMaxX([[self buttonView] bounds]) - | |
897 bookmarks::kBookmarkHorizontalPadding; | |
898 int right = maxX; | |
899 | |
900 int ignored = 0; | |
901 NSRect frame = [self frameForBookmarkButtonFromCell: | |
902 [otherBookmarksButton_ cell] xOffset:&ignored]; | |
903 if (![otherBookmarksButton_ isHidden]) { | |
904 right -= NSWidth(frame); | |
905 frame.origin.x = right; | |
906 } else { | |
907 frame.origin.x = maxX - NSWidth(frame); | |
908 } | |
909 [otherBookmarksButton_ setFrame:frame]; | |
910 | |
911 frame = [offTheSideButton_ frame]; | |
912 frame.size.height = bookmarks::kBookmarkFolderButtonHeight; | |
913 right -= frame.size.width; | |
914 frame.origin.x = right; | |
915 [offTheSideButton_ setFrame:frame]; | |
916 } | |
917 | |
918 // Configure the off-the-side button (e.g. specify the node range, | |
919 // check if we should enable or disable it, etc). | |
920 - (void)configureOffTheSideButtonContentsAndVisibility { | |
921 [[offTheSideButton_ cell] setStartingChildIndex:displayedButtonCount_]; | |
922 [[offTheSideButton_ cell] | |
923 setBookmarkNode:bookmarkModel_->bookmark_bar_node()]; | |
924 int bookmarkChildren = bookmarkModel_->bookmark_bar_node()->child_count(); | |
925 if (bookmarkChildren > displayedButtonCount_) { | |
926 [offTheSideButton_ setHidden:NO]; | |
927 // Set the off the side button as needing re-display. This is needed to | |
928 // avoid the button being shown with a black background the first time | |
929 // it's displayed. See https://codereview.chromium.org/1630453002/ for | |
930 // more context. | |
931 [offTheSideButton_ setNeedsDisplay:YES]; | |
932 } else { | |
933 // If we just deleted the last item in an off-the-side menu so the | |
934 // button will be going away, make sure the menu goes away. | |
935 if (folderController_ && | |
936 ([folderController_ parentButton] == offTheSideButton_)) | |
937 [self closeAllBookmarkFolders]; | |
938 // (And hide the button, too.) | |
939 [offTheSideButton_ setHidden:YES]; | |
940 } | |
941 } | |
942 | |
943 // Main menubar observation code, so we can know to close our fake menus if the | 884 // Main menubar observation code, so we can know to close our fake menus if the |
944 // user clicks on the actual menubar, as multiple unconnected menus sharing | 885 // user clicks on the actual menubar, as multiple unconnected menus sharing |
945 // the screen looks weird. | 886 // the screen looks weird. |
946 // Needed because the local event monitor doesn't see the click on the menubar. | 887 // Needed because the local event monitor doesn't see the click on the menubar. |
947 | 888 |
948 // Gets called when the menubar is clicked. | 889 // Gets called when the menubar is clicked. |
949 - (void)begunTracking:(NSNotification *)notification { | 890 - (void)begunTracking:(NSNotification *)notification { |
950 [self closeFolderAndStopTrackingMenus]; | 891 [self closeFolderAndStopTrackingMenus]; |
951 } | 892 } |
952 | 893 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
989 } | 930 } |
990 } else { | 931 } else { |
991 if (exitEventTap_) { | 932 if (exitEventTap_) { |
992 [NSEvent removeMonitor:exitEventTap_]; | 933 [NSEvent removeMonitor:exitEventTap_]; |
993 exitEventTap_ = nil; | 934 exitEventTap_ = nil; |
994 [self stopObservingMenubar]; | 935 [self stopObservingMenubar]; |
995 } | 936 } |
996 } | 937 } |
997 } | 938 } |
998 | 939 |
999 // Keep the "no items" label centered in response to a frame size change. | 940 // Show/hide the bookmark bar. |
1000 - (void)centerNoItemsLabel { | 941 // If |animate| is YES, the changes are made using the animator; otherwise they |
1001 // Note that this computation is done in the parent's coordinate system, | 942 // are made immediately. |
1002 // which is unflipped. Also, we want the label to be a fixed distance from | |
1003 // the bottom, so that it slides up properly (on animating to hidden). | |
1004 // The textfield sits in the itemcontainer, so to center it we maintain | |
1005 // equal vertical padding on the top and bottom. | |
1006 int yoffset = (NSHeight([[buttonView_ noItemTextfield] frame]) - | |
1007 NSHeight([[buttonView_ noItemContainer] frame])) / 2; | |
1008 [[buttonView_ noItemContainer] setFrameOrigin:NSMakePoint(0, yoffset)]; | |
1009 } | |
1010 | |
1011 // (Private) | |
1012 - (void)showBookmarkBarWithAnimation:(BOOL)animate { | 943 - (void)showBookmarkBarWithAnimation:(BOOL)animate { |
1013 if (animate && stateAnimationsEnabled_) { | 944 if (animate && stateAnimationsEnabled_) { |
1014 // If |-doBookmarkBarAnimation| does the animation, we're done. | 945 // If |-doBookmarkBarAnimation| does the animation, we're done. |
1015 if ([self doBookmarkBarAnimation]) | 946 if ([self doBookmarkBarAnimation]) |
1016 return; | 947 return; |
1017 | 948 |
1018 // Else fall through and do the change instantly. | 949 // Else fall through and do the change instantly. |
1019 } | 950 } |
1020 | 951 |
1021 BookmarkBarToolbarView* view = [self controlledView]; | 952 BookmarkBarToolbarView* view = [self controlledView]; |
1022 | 953 |
1023 // Set our height immediately via -[AnimatableView setHeight:]. | 954 // Set our height immediately via -[AnimatableView setHeight:]. |
1024 [view setHeight:[self preferredHeight]]; | 955 [view setHeight:[self preferredHeight]]; |
1025 | 956 |
1026 // Only show the divider if showing the normal bookmark bar. | 957 // Only show the divider if showing the normal bookmark bar. |
1027 BOOL showsDivider = [self isInState:BookmarkBar::SHOW]; | 958 BOOL showsDivider = [self isInState:BookmarkBar::SHOW]; |
1028 [view setShowsDivider:showsDivider]; | 959 [view setShowsDivider:showsDivider]; |
1029 | 960 |
1030 // Make sure we're shown. | 961 // Make sure we're shown. |
1031 [view setHidden:![self isVisible]]; | 962 [view setHidden:![self isVisible]]; |
1032 | 963 |
1033 // Update everything else. | 964 // Update everything else. |
1034 [self layoutSubviews]; | 965 [self layoutSubviews]; |
1035 [self frameDidChange]; | 966 [self frameDidChange]; |
1036 } | 967 } |
1037 | 968 |
1038 // (Private) | 969 // Handles animating the resize of the content view. Returns YES if it handled |
970 // the animation, NO if not (and hence it should be done instantly). | |
1039 - (BOOL)doBookmarkBarAnimation { | 971 - (BOOL)doBookmarkBarAnimation { |
1040 BookmarkBarToolbarView* view = [self controlledView]; | 972 BookmarkBarToolbarView* view = [self controlledView]; |
1041 if ([self isAnimatingFromState:BookmarkBar::HIDDEN | 973 if ([self isAnimatingFromState:BookmarkBar::HIDDEN |
1042 toState:BookmarkBar::SHOW]) { | 974 toState:BookmarkBar::SHOW]) { |
1043 [view setShowsDivider:YES]; | 975 [view setShowsDivider:YES]; |
1044 [view setHidden:NO]; | 976 [view setHidden:NO]; |
1045 // Height takes into account the extra height we have since the toolbar | 977 // Height takes into account the extra height we have since the toolbar |
1046 // only compresses when we're done. | 978 // only compresses when we're done. |
1047 [view animateToNewHeight:(chrome::kMinimumBookmarkBarHeight - | 979 [view animateToNewHeight:(chrome::kMinimumBookmarkBarHeight - |
1048 bookmarks::kBookmarkBarOverlap) | 980 bookmarks::kBookmarkBarOverlap) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1099 case BookmarkBar::HIDDEN: | 1031 case BookmarkBar::HIDDEN: |
1100 return 0; | 1032 return 0; |
1101 } | 1033 } |
1102 } | 1034 } |
1103 | 1035 |
1104 // Return an appropriate width for the given bookmark button cell. | 1036 // Return an appropriate width for the given bookmark button cell. |
1105 - (CGFloat)widthForBookmarkButtonCell:(NSCell*)cell { | 1037 - (CGFloat)widthForBookmarkButtonCell:(NSCell*)cell { |
1106 return std::min([cell cellSize].width, bookmarks::kDefaultBookmarkWidth); | 1038 return std::min([cell cellSize].width, bookmarks::kDefaultBookmarkWidth); |
1107 } | 1039 } |
1108 | 1040 |
1109 // For the given root node of the bookmark bar, show or hide (as | 1041 - (BookmarkButton*)buttonForNode:(const BookmarkNode*)node { |
1110 // appropriate) the "no items" container (text which says "bookmarks | 1042 BookmarkButton* button = nil; |
1111 // go here"). | 1043 int64_t nodeId = node->id(); |
1112 - (void)showOrHideNoItemContainerForNode:(const BookmarkNode*)node { | 1044 auto buttonIt = nodeIdToButtonMap_.find(nodeId); |
1113 BOOL hideNoItemWarning = !node->empty(); | 1045 if (buttonIt != nodeIdToButtonMap_.end()) { |
1114 [[buttonView_ noItemContainer] setHidden:hideNoItemWarning]; | 1046 button = (*buttonIt).second.get(); |
1115 } | 1047 [self updateTitleAndTooltipForButton:button]; |
1048 } else if ([unusedButtonPool_ count] > 0) { | |
1049 button = [[[unusedButtonPool_ firstObject] retain] autorelease]; | |
1050 [unusedButtonPool_ removeObjectAtIndex:0]; | |
1051 BOOL darkTheme = [[[self view] window] hasDarkTheme]; | |
1052 [[button cell] | |
1053 setBookmarkNode:node | |
1054 image:[self faviconForNode:node forADarkTheme:darkTheme]]; | |
1055 } else { | |
1056 BookmarkButtonCell* cell = [self cellForBookmarkNode:node]; | |
1057 NSRect frame = NSMakeRect(0, bookmarks::kBookmarkVerticalPadding, 0, | |
1058 kBookmarkButtonHeightMinusPadding); | |
1059 button = [[[BookmarkButton alloc] initWithFrame:frame] autorelease]; | |
1060 [button setCell:cell]; | |
1061 [buttonView_ addSubview:button]; | |
1062 [button setDelegate:self]; | |
1063 } | |
1064 DCHECK(button); | |
1116 | 1065 |
1117 // TODO(jrg): write a "build bar" so there is a nice spot for things | 1066 // Do setup. |
1118 // like the contextual menu which is invoked when not over a | 1067 nodeIdToButtonMap_.insert( |
1119 // bookmark. On Safari that menu has a "new folder" option. | 1068 {nodeId, base::scoped_nsobject<BookmarkButton>([button retain])}); |
1120 - (void)addNodesToButtonList:(const BookmarkNode*)node { | |
1121 [self showOrHideNoItemContainerForNode:node]; | |
1122 | |
1123 CGFloat maxViewX = NSMaxX([[self view] bounds]); | |
1124 int xOffset = | |
1125 bookmarks::kBookmarkLeftMargin - bookmarks::kBookmarkHorizontalPadding; | |
1126 | |
1127 // Draw the apps bookmark if needed. | |
1128 if (![appsPageShortcutButton_ isHidden]) { | |
1129 NSRect frame = | |
1130 [self frameForBookmarkButtonFromCell:[appsPageShortcutButton_ cell] | |
1131 xOffset:&xOffset]; | |
1132 [appsPageShortcutButton_ setFrame:frame]; | |
1133 } | |
1134 | |
1135 // Draw the managed bookmark folder if needed. | |
1136 if (![managedBookmarksButton_ isHidden]) { | |
1137 xOffset += bookmarks::kBookmarkHorizontalPadding; | |
1138 NSRect frame = | |
1139 [self frameForBookmarkButtonFromCell:[managedBookmarksButton_ cell] | |
1140 xOffset:&xOffset]; | |
1141 [managedBookmarksButton_ setFrame:frame]; | |
1142 } | |
1143 | |
1144 // Draw the supervised bookmark folder if needed. | |
1145 if (![supervisedBookmarksButton_ isHidden]) { | |
1146 xOffset += bookmarks::kBookmarkHorizontalPadding; | |
1147 NSRect frame = | |
1148 [self frameForBookmarkButtonFromCell:[supervisedBookmarksButton_ cell] | |
1149 xOffset:&xOffset]; | |
1150 [supervisedBookmarksButton_ setFrame:frame]; | |
1151 } | |
1152 | |
1153 for (int i = 0; i < node->child_count(); i++) { | |
1154 const BookmarkNode* child = node->GetChild(i); | |
1155 BookmarkButton* button = [self buttonForNode:child xOffset:&xOffset]; | |
1156 if (NSMinX([button frame]) >= maxViewX) { | |
1157 [button setDelegate:nil]; | |
1158 break; | |
1159 } | |
1160 [buttons_ addObject:button]; | |
1161 } | |
1162 } | |
1163 | |
1164 - (BookmarkButton*)buttonForNode:(const BookmarkNode*)node | |
1165 xOffset:(int*)xOffset { | |
1166 BookmarkButtonCell* cell = [self cellForBookmarkNode:node]; | |
1167 NSRect frame = [self frameForBookmarkButtonFromCell:cell xOffset:xOffset]; | |
1168 | |
1169 base::scoped_nsobject<BookmarkButton> button( | |
1170 [[BookmarkButton alloc] initWithFrame:frame]); | |
1171 DCHECK(button.get()); | |
1172 | |
1173 // [NSButton setCell:] warns to NOT use setCell: other than in the | |
1174 // initializer of a control. However, we are using a basic | |
1175 // NSButton whose initializer does not take an NSCell as an | |
1176 // object. To honor the assumed semantics, we do nothing with | |
1177 // NSButton between alloc/init and setCell:. | |
1178 [button setCell:cell]; | |
1179 [button setDelegate:self]; | |
1180 | |
1181 // We cannot set the button cell's text color until it is placed in | |
1182 // the button (e.g. the [button setCell:cell] call right above). We | |
1183 // also cannot set the cell's text color until the view is added to | |
1184 // the hierarchy. If that second part is now true, set the color. | |
1185 // (If not we'll set the color on the 1st themeChanged: | |
1186 // notification.) | |
1187 const ui::ThemeProvider* themeProvider = [[[self view] window] themeProvider]; | |
1188 if (themeProvider) { | |
1189 NSColor* color = | |
1190 themeProvider->GetNSColor(ThemeProperties::COLOR_BOOKMARK_TEXT); | |
1191 [cell setTextColor:color]; | |
1192 } | |
1193 | |
1194 if (node->is_folder()) { | 1069 if (node->is_folder()) { |
1195 [button setTarget:self]; | 1070 [button setTarget:self]; |
1196 [button setAction:@selector(openBookmarkFolderFromButton:)]; | 1071 [button setAction:@selector(openBookmarkFolderFromButton:)]; |
1197 [[button draggableButton] setActsOnMouseDown:YES]; | 1072 [[button draggableButton] setActsOnMouseDown:YES]; |
1198 // If it has a title, and it will be truncated, show full title in | |
1199 // tooltip. | |
1200 NSString* title = base::SysUTF16ToNSString(node->GetTitle()); | |
1201 if ([title length] && | |
1202 [[button cell] cellSize].width > bookmarks::kDefaultBookmarkWidth) { | |
1203 [button setToolTip:title]; | |
1204 } | |
1205 } else { | 1073 } else { |
1206 // Make the button do something | 1074 // Make the button do something. |
1207 [button setTarget:self]; | 1075 [button setTarget:self]; |
1208 [button setAction:@selector(openBookmark:)]; | 1076 [button setAction:@selector(openBookmark:)]; |
1209 if (node->is_url()) | 1077 [[button draggableButton] setActsOnMouseDown:NO]; |
1210 [button setToolTip:[BookmarkMenuCocoaController tooltipForNode:node]]; | |
1211 } | 1078 } |
1212 return [[button.get() retain] autorelease]; | 1079 [self updateTitleAndTooltipForButton:button]; |
1080 return button; | |
1213 } | 1081 } |
1214 | 1082 |
1215 // Add bookmark buttons to the view only if they are completely | 1083 - (void)updateTitleAndTooltipForButton:(BookmarkButton*)button { |
1216 // visible and don't overlap the "other bookmarks". Remove buttons | 1084 const BookmarkNode* node = [button bookmarkNode]; |
1217 // which are clipped. Called when building the bookmark bar the first time. | 1085 CGFloat buttonWidth = [self widthOfButtonForNode:node]; |
1218 - (void)addButtonsToView { | 1086 NSString* buttonTitle = base::SysUTF16ToNSString(node->GetTitle()); |
1219 displayedButtonCount_ = 0; | 1087 |
1220 NSMutableArray* buttons = [self buttons]; | 1088 if (NSWidth([button frame]) == buttonWidth && |
1221 for (NSButton* button in buttons) { | 1089 [[button title] isEqualToString:buttonTitle]) |
1222 if (NSMaxX([button frame]) > (NSMinX([offTheSideButton_ frame]) - | 1090 return; |
1223 bookmarks::kBookmarkHorizontalPadding)) | 1091 |
1224 break; | 1092 CGRect frame = [button frame]; |
1225 [buttonView_ addSubview:button]; | 1093 frame.size.width = buttonWidth; |
1226 ++displayedButtonCount_; | 1094 [button setFrame:frame]; |
1095 [[button cell] setTitle:buttonTitle]; | |
1096 NSString* tooltip = nil; | |
1097 | |
1098 // Folders show a tooltip iff the title is truncated. | |
1099 if (node->is_folder() && [buttonTitle length] > 0 && | |
1100 [[button cell] cellSize].width < buttonWidth) { | |
1101 tooltip = buttonTitle; | |
1102 } else if (node->is_url()) { | |
1103 tooltip = [BookmarkMenuCocoaController tooltipForNode:node]; | |
1227 } | 1104 } |
1228 NSUInteger removalCount = | |
1229 [buttons count] - (NSUInteger)displayedButtonCount_; | |
1230 if (removalCount > 0) { | |
1231 NSRange removalRange = NSMakeRange(displayedButtonCount_, removalCount); | |
1232 [buttons removeObjectsInRange:removalRange]; | |
1233 } | |
1234 } | |
1235 | 1105 |
1236 // Shows or hides the Managed, Supervised, or Other Bookmarks button as | 1106 [button setToolTip:tooltip]; |
1237 // appropriate, and returns whether it ended up visible. | |
1238 - (BOOL)setBookmarkButtonVisibility:(BookmarkButton*)button | |
1239 canShow:(BOOL)show | |
1240 resetAllButtonPositions:(BOOL)resetButtons { | |
1241 if (!button) | |
1242 return NO; | |
1243 | |
1244 BOOL visible = ![button bookmarkNode]->empty() && show; | |
1245 BOOL currentVisibility = ![button isHidden]; | |
1246 if (currentVisibility != visible) { | |
1247 [button setHidden:!visible]; | |
1248 if (resetButtons) | |
1249 [self resetAllButtonPositionsWithAnimation:NO]; | |
1250 } | |
1251 return visible; | |
1252 } | |
1253 | |
1254 // Shows or hides the Managed Bookmarks button as appropriate, and returns | |
1255 // whether it ended up visible. | |
1256 - (BOOL)setManagedBookmarksButtonVisibility { | |
1257 PrefService* prefs = browser_->profile()->GetPrefs(); | |
1258 BOOL prefIsSet = | |
1259 prefs->GetBoolean(bookmarks::prefs::kShowManagedBookmarksInBookmarkBar); | |
1260 return [self setBookmarkButtonVisibility:managedBookmarksButton_.get() | |
1261 canShow:prefIsSet | |
1262 resetAllButtonPositions:YES]; | |
1263 } | |
1264 | |
1265 // Shows or hides the Supervised Bookmarks button as appropriate, and returns | |
1266 // whether it ended up visible. | |
1267 - (BOOL)setSupervisedBookmarksButtonVisibility { | |
1268 return [self setBookmarkButtonVisibility:supervisedBookmarksButton_.get() | |
1269 canShow:YES | |
1270 resetAllButtonPositions:YES]; | |
1271 } | |
1272 | |
1273 // Shows or hides the Other Bookmarks button as appropriate, and returns | |
1274 // whether it ended up visible. | |
1275 - (BOOL)setOtherBookmarksButtonVisibility { | |
1276 return [self setBookmarkButtonVisibility:otherBookmarksButton_.get() | |
1277 canShow:YES | |
1278 resetAllButtonPositions:NO]; | |
1279 } | |
1280 | |
1281 // Shows or hides the Apps button as appropriate, and returns whether it ended | |
1282 // up visible. | |
1283 - (BOOL)setAppsPageShortcutButtonVisibility { | |
1284 if (!appsPageShortcutButton_.get()) | |
1285 return NO; | |
1286 | |
1287 BOOL visible = | |
1288 bookmarkModel_->loaded() && | |
1289 chrome::ShouldShowAppsShortcutInBookmarkBar(browser_->profile()); | |
1290 [appsPageShortcutButton_ setHidden:!visible]; | |
1291 return visible; | |
1292 } | 1107 } |
1293 | 1108 |
1294 // Creates a bookmark bar button that does not correspond to a regular bookmark | 1109 // Creates a bookmark bar button that does not correspond to a regular bookmark |
1295 // or folder. It is used by the "Other Bookmarks" and the "Apps" buttons. | 1110 // or folder. It is used by the "Other Bookmarks" and the "Apps" buttons. |
1296 - (BookmarkButton*)createCustomBookmarkButtonForCell:(NSCell*)cell { | 1111 - (BookmarkButton*)createCustomBookmarkButtonForCell:(NSCell*)cell { |
1297 BookmarkButton* button = [[BookmarkButton alloc] init]; | 1112 BookmarkButton* button = [[BookmarkButton alloc] init]; |
1298 [[button draggableButton] setDraggable:NO]; | 1113 [[button draggableButton] setDraggable:NO]; |
1299 [[button draggableButton] setActsOnMouseDown:YES]; | 1114 [[button draggableButton] setActsOnMouseDown:YES]; |
1300 [button setCell:cell]; | 1115 [button setCell:cell]; |
1301 [button setDelegate:self]; | 1116 [button setDelegate:self]; |
1302 [button setTarget:self]; | 1117 [button setTarget:self]; |
1303 // Make sure this button, like all other BookmarkButtons, lives | 1118 // Make sure this button, like all other BookmarkButtons, lives |
1304 // until the end of the current event loop. | 1119 // until the end of the current event loop. |
1305 [[button retain] autorelease]; | 1120 [[button retain] autorelease]; |
1306 return button; | 1121 return button; |
1307 } | 1122 } |
1308 | 1123 |
1309 // Creates the button for "Managed Bookmarks", but does not position it. | 1124 // Creates the button for "Managed Bookmarks", but does not position it. |
1310 - (void)createManagedBookmarksButton { | 1125 - (void)createManagedBookmarksButton { |
1311 if (managedBookmarksButton_.get()) { | 1126 if (managedBookmarksButton_.get()) { |
1312 // The node's title might have changed if the user signed in or out. | 1127 // The node's title might have changed if the user signed in or out. |
1313 // Make sure it's up to date now. | 1128 // Make sure it's up to date now. |
1314 const BookmarkNode* node = managedBookmarkService_->managed_node(); | 1129 const BookmarkNode* node = managedBookmarkService_->managed_node(); |
1315 NSString* title = base::SysUTF16ToNSString(node->GetTitle()); | 1130 NSString* title = base::SysUTF16ToNSString(node->GetTitle()); |
1316 NSCell* cell = [managedBookmarksButton_ cell]; | 1131 NSCell* cell = [managedBookmarksButton_ cell]; |
1317 [cell setTitle:title]; | 1132 [cell setTitle:title]; |
1318 | 1133 |
1319 // Its visibility may have changed too. | |
1320 [self setManagedBookmarksButtonVisibility]; | |
1321 | |
1322 return; | 1134 return; |
1323 } | 1135 } |
1324 | 1136 |
1325 NSCell* cell = | 1137 NSCell* cell = |
1326 [self cellForBookmarkNode:managedBookmarkService_->managed_node()]; | 1138 [self cellForBookmarkNode:managedBookmarkService_->managed_node()]; |
1327 managedBookmarksButton_.reset([self createCustomBookmarkButtonForCell:cell]); | 1139 managedBookmarksButton_.reset([self createCustomBookmarkButtonForCell:cell]); |
1328 [managedBookmarksButton_ setAction:@selector(openBookmarkFolderFromButton:)]; | 1140 [managedBookmarksButton_ setAction:@selector(openBookmarkFolderFromButton:)]; |
1329 view_id_util::SetID(managedBookmarksButton_.get(), VIEW_ID_MANAGED_BOOKMARKS); | 1141 view_id_util::SetID(managedBookmarksButton_.get(), VIEW_ID_MANAGED_BOOKMARKS); |
1142 NSRect frame = NSMakeRect(0, bookmarks::kBookmarkVerticalPadding, | |
1143 [self widthForBookmarkButtonCell:cell], | |
1144 kBookmarkButtonHeightMinusPadding); | |
1145 [managedBookmarksButton_ setFrame:frame]; | |
1330 [buttonView_ addSubview:managedBookmarksButton_.get()]; | 1146 [buttonView_ addSubview:managedBookmarksButton_.get()]; |
1331 | 1147 |
1332 [self setManagedBookmarksButtonVisibility]; | |
1333 } | 1148 } |
1334 | 1149 |
1335 // Creates the button for "Supervised Bookmarks", but does not position it. | 1150 // Creates the button for "Supervised Bookmarks", but does not position it. |
1336 - (void)createSupervisedBookmarksButton { | 1151 - (void)createSupervisedBookmarksButton { |
1337 if (supervisedBookmarksButton_.get()) { | 1152 if (supervisedBookmarksButton_.get()) { |
1338 // The button's already there, but its visibility may have changed. | |
1339 [self setSupervisedBookmarksButtonVisibility]; | |
1340 return; | 1153 return; |
1341 } | 1154 } |
1342 | 1155 |
1343 NSCell* cell = | 1156 NSCell* cell = |
1344 [self cellForBookmarkNode:managedBookmarkService_->supervised_node()]; | 1157 [self cellForBookmarkNode:managedBookmarkService_->supervised_node()]; |
1345 supervisedBookmarksButton_.reset( | 1158 supervisedBookmarksButton_.reset( |
1346 [self createCustomBookmarkButtonForCell:cell]); | 1159 [self createCustomBookmarkButtonForCell:cell]); |
1347 [supervisedBookmarksButton_ | 1160 [supervisedBookmarksButton_ |
1348 setAction:@selector(openBookmarkFolderFromButton:)]; | 1161 setAction:@selector(openBookmarkFolderFromButton:)]; |
1349 view_id_util::SetID(supervisedBookmarksButton_.get(), | 1162 view_id_util::SetID(supervisedBookmarksButton_.get(), |
1350 VIEW_ID_SUPERVISED_BOOKMARKS); | 1163 VIEW_ID_SUPERVISED_BOOKMARKS); |
1164 NSRect frame = NSMakeRect(0, bookmarks::kBookmarkVerticalPadding, | |
1165 [self widthForBookmarkButtonCell:cell], | |
1166 kBookmarkButtonHeightMinusPadding); | |
1167 [supervisedBookmarksButton_ setFrame:frame]; | |
1351 [buttonView_ addSubview:supervisedBookmarksButton_.get()]; | 1168 [buttonView_ addSubview:supervisedBookmarksButton_.get()]; |
1352 | |
1353 [self setSupervisedBookmarksButtonVisibility]; | |
1354 } | 1169 } |
1355 | 1170 |
1356 // Creates the button for "Other Bookmarks", but does not position it. | 1171 // Creates the button for "Other Bookmarks", but does not position it. |
1357 - (void)createOtherBookmarksButton { | 1172 - (void)createOtherBookmarksButton { |
1358 // Can't create this until the model is loaded, but only need to | 1173 // Can't create this until the model is loaded, but only need to |
1359 // create it once. | 1174 // create it once. |
1360 if (otherBookmarksButton_.get()) { | 1175 if (otherBookmarksButton_.get()) { |
1361 [self setOtherBookmarksButtonVisibility]; | |
1362 return; | 1176 return; |
1363 } | 1177 } |
1364 | 1178 |
1365 NSCell* cell = [self cellForBookmarkNode:bookmarkModel_->other_node()]; | 1179 NSCell* cell = [self cellForBookmarkNode:bookmarkModel_->other_node()]; |
1366 otherBookmarksButton_.reset([self createCustomBookmarkButtonForCell:cell]); | 1180 otherBookmarksButton_.reset([self createCustomBookmarkButtonForCell:cell]); |
1367 // Peg at right; keep same height as bar. | |
1368 [otherBookmarksButton_ setAutoresizingMask:(NSViewMinXMargin)]; | |
1369 [otherBookmarksButton_ setAction:@selector(openBookmarkFolderFromButton:)]; | 1181 [otherBookmarksButton_ setAction:@selector(openBookmarkFolderFromButton:)]; |
1182 NSRect frame = NSMakeRect(0, bookmarks::kBookmarkVerticalPadding, | |
1183 [self widthForBookmarkButtonCell:cell], | |
1184 kBookmarkButtonHeightMinusPadding); | |
1185 [otherBookmarksButton_ setFrame:frame]; | |
1370 view_id_util::SetID(otherBookmarksButton_.get(), VIEW_ID_OTHER_BOOKMARKS); | 1186 view_id_util::SetID(otherBookmarksButton_.get(), VIEW_ID_OTHER_BOOKMARKS); |
1371 [buttonView_ addSubview:otherBookmarksButton_.get()]; | 1187 [buttonView_ addSubview:otherBookmarksButton_.get()]; |
1372 | |
1373 [self setOtherBookmarksButtonVisibility]; | |
1374 } | 1188 } |
1375 | 1189 |
1376 // Creates the button for "Apps", but does not position it. | 1190 // Creates the button for "Apps", but does not position it. |
1377 - (void)createAppsPageShortcutButton { | 1191 - (void)createAppsPageShortcutButton { |
1378 // Can't create this until the model is loaded, but only need to | |
1379 // create it once. | |
1380 if (appsPageShortcutButton_.get()) { | 1192 if (appsPageShortcutButton_.get()) { |
1381 [self setAppsPageShortcutButtonVisibility]; | |
1382 return; | 1193 return; |
1383 } | 1194 } |
1384 | 1195 |
1385 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 1196 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
1386 NSString* text = l10n_util::GetNSString(IDS_BOOKMARK_BAR_APPS_SHORTCUT_NAME); | 1197 NSString* text = l10n_util::GetNSString(IDS_BOOKMARK_BAR_APPS_SHORTCUT_NAME); |
1387 NSImage* image = rb.GetNativeImageNamed( | 1198 NSImage* image = rb.GetNativeImageNamed( |
1388 IDR_BOOKMARK_BAR_APPS_SHORTCUT).ToNSImage(); | 1199 IDR_BOOKMARK_BAR_APPS_SHORTCUT).ToNSImage(); |
1389 NSCell* cell = [self cellForCustomButtonWithText:text | 1200 NSCell* cell = [self cellForCustomButtonWithText:text |
1390 image:image]; | 1201 image:image]; |
1202 NSRect frame; | |
1203 frame.origin.y = bookmarks::kBookmarkVerticalPadding; | |
1204 frame.size = NSMakeSize([self widthForBookmarkButtonCell:cell], | |
1205 kBookmarkButtonHeightMinusPadding); | |
1391 appsPageShortcutButton_.reset([self createCustomBookmarkButtonForCell:cell]); | 1206 appsPageShortcutButton_.reset([self createCustomBookmarkButtonForCell:cell]); |
1207 [appsPageShortcutButton_ setFrame:frame]; | |
1392 [[appsPageShortcutButton_ draggableButton] setActsOnMouseDown:NO]; | 1208 [[appsPageShortcutButton_ draggableButton] setActsOnMouseDown:NO]; |
1393 [appsPageShortcutButton_ setAction:@selector(openAppsPage:)]; | 1209 [appsPageShortcutButton_ setAction:@selector(openAppsPage:)]; |
1394 NSString* tooltip = | 1210 NSString* tooltip = |
1395 l10n_util::GetNSString(IDS_BOOKMARK_BAR_APPS_SHORTCUT_TOOLTIP); | 1211 l10n_util::GetNSString(IDS_BOOKMARK_BAR_APPS_SHORTCUT_TOOLTIP); |
1396 [appsPageShortcutButton_ setToolTip:tooltip]; | 1212 [appsPageShortcutButton_ setToolTip:tooltip]; |
1397 [buttonView_ addSubview:appsPageShortcutButton_.get()]; | 1213 [buttonView_ addSubview:appsPageShortcutButton_.get()]; |
1398 | |
1399 [self setAppsPageShortcutButtonVisibility]; | |
1400 } | 1214 } |
1401 | 1215 |
1216 // Creates the "off-the-side" (chevron/overflow) button but | |
1217 // does not position it. | |
1402 - (void)createOffTheSideButton { | 1218 - (void)createOffTheSideButton { |
1219 if (offTheSideButton_.get()) { | |
1220 return; | |
1221 } | |
1222 DCHECK(bookmarkModel_->loaded()); | |
1403 offTheSideButton_.reset( | 1223 offTheSideButton_.reset( |
1404 [[BookmarkButton alloc] initWithFrame:NSMakeRect(586, 0, 20, 24)]); | 1224 [[BookmarkButton alloc] initWithFrame:NSMakeRect(0, 0, 20, 24)]); |
1405 id offTheSideCell = [BookmarkButtonCell offTheSideButtonCell]; | 1225 id offTheSideCell = [BookmarkButtonCell offTheSideButtonCell]; |
1406 [offTheSideCell setTag:kMaterialStandardButtonTypeWithLimitedClickFeedback]; | 1226 [offTheSideCell setTag:kMaterialStandardButtonTypeWithLimitedClickFeedback]; |
1407 [offTheSideCell setImagePosition:NSImageOnly]; | 1227 [offTheSideCell setImagePosition:NSImageOnly]; |
1408 | 1228 |
1409 [offTheSideCell setHighlightsBy:NSNoCellMask]; | 1229 [offTheSideCell setHighlightsBy:NSNoCellMask]; |
1410 [offTheSideCell setShowsBorderOnlyWhileMouseInside:YES]; | 1230 [offTheSideCell setShowsBorderOnlyWhileMouseInside:YES]; |
1411 [offTheSideCell setBezelStyle:NSShadowlessSquareBezelStyle]; | 1231 [offTheSideCell setBezelStyle:NSShadowlessSquareBezelStyle]; |
1232 [offTheSideCell setBookmarkNode:bookmarkModel_->bookmark_bar_node()]; | |
1233 | |
1412 [offTheSideButton_ setCell:offTheSideCell]; | 1234 [offTheSideButton_ setCell:offTheSideCell]; |
1413 [offTheSideButton_ setImage:[self offTheSideButtonImage:NO]]; | 1235 [offTheSideButton_ setImage:[self offTheSideButtonImage:NO]]; |
1414 [offTheSideButton_ setButtonType:NSMomentaryLightButton]; | 1236 [offTheSideButton_ setButtonType:NSMomentaryLightButton]; |
1415 | 1237 |
1416 [offTheSideButton_ setTarget:self]; | 1238 [offTheSideButton_ setTarget:self]; |
1417 [offTheSideButton_ setAction:@selector(openOffTheSideFolderFromButton:)]; | 1239 [offTheSideButton_ setAction:@selector(openOffTheSideFolderFromButton:)]; |
1418 [offTheSideButton_ setDelegate:self]; | 1240 [offTheSideButton_ setDelegate:self]; |
1419 [[offTheSideButton_ draggableButton] setDraggable:NO]; | 1241 [[offTheSideButton_ draggableButton] setDraggable:NO]; |
1420 [[offTheSideButton_ draggableButton] setActsOnMouseDown:YES]; | 1242 [[offTheSideButton_ draggableButton] setActsOnMouseDown:YES]; |
1243 [offTheSideButton_ setHidden:YES]; | |
1244 [buttonView_ addSubview:offTheSideButton_]; | |
1245 } | |
1246 | |
1247 - (void)updateExtraButtonsVisibility { | |
1248 [self rebuildLayout:NO]; | |
1249 } | |
1250 | |
1251 - (void)createExtraButtons { | |
1252 DCHECK(!didCreateExtraButtons_); | |
1253 [self createSupervisedBookmarksButton]; | |
1254 [self createManagedBookmarksButton]; | |
1255 [self createOtherBookmarksButton]; | |
1256 [self createAppsPageShortcutButton]; | |
1257 [self createOffTheSideButton]; | |
1258 didCreateExtraButtons_ = YES; | |
1421 } | 1259 } |
1422 | 1260 |
1423 - (void)openAppsPage:(id)sender { | 1261 - (void)openAppsPage:(id)sender { |
1424 WindowOpenDisposition disposition = | 1262 WindowOpenDisposition disposition = |
1425 ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); | 1263 ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); |
1426 [self openURL:GURL(chrome::kChromeUIAppsURL) disposition:disposition]; | 1264 [self openURL:GURL(chrome::kChromeUIAppsURL) disposition:disposition]; |
1427 RecordBookmarkAppsPageOpen([self bookmarkLaunchLocation]); | 1265 RecordBookmarkAppsPageOpen([self bookmarkLaunchLocation]); |
1428 } | 1266 } |
1429 | 1267 |
1430 // To avoid problems with sync, changes that may impact the current | 1268 // To avoid problems with sync, changes that may impact the current |
1431 // bookmark (e.g. deletion) make sure context menus are closed. This | 1269 // bookmark (e.g. deletion) make sure context menus are closed. This |
1432 // prevents deleting a node which no longer exists. | 1270 // prevents deleting a node which no longer exists. |
1433 - (void)cancelMenuTracking { | 1271 - (void)cancelMenuTracking { |
1434 [contextMenuController_ cancelTracking]; | 1272 [contextMenuController_ cancelTracking]; |
1435 } | 1273 } |
1436 | 1274 |
1275 // Moves to the given next state (from the current state), possibly animating. | |
1276 // If |animate| is NO, it will stop any running animation and jump to the given | |
1277 // state. If YES, it may either (depending on implementation) jump to the end of | |
1278 // the current animation and begin the next one, or stop the current animation | |
1279 // mid-flight and animate to the next state. | |
1437 - (void)moveToState:(BookmarkBar::State)nextState | 1280 - (void)moveToState:(BookmarkBar::State)nextState |
1438 withAnimation:(BOOL)animate { | 1281 withAnimation:(BOOL)animate { |
1439 BOOL isAnimationRunning = [self isAnimationRunning]; | 1282 BOOL isAnimationRunning = [self isAnimationRunning]; |
1440 | 1283 |
1441 // No-op if the next state is the same as the "current" one, subject to the | 1284 // No-op if the next state is the same as the "current" one, subject to the |
1442 // following conditions: | 1285 // following conditions: |
1443 // - no animation is running; or | 1286 // - no animation is running; or |
1444 // - an animation is running and |animate| is YES ([*] if it's NO, we'd want | 1287 // - an animation is running and |animate| is YES ([*] if it's NO, we'd want |
1445 // to cancel the animation and jump to the final state). | 1288 // to cancel the animation and jump to the final state). |
1446 if ((nextState == currentState_) && (!isAnimationRunning || animate)) | 1289 if ((nextState == currentState_) && (!isAnimationRunning || animate)) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1493 } | 1336 } |
1494 | 1337 |
1495 // N.B.: |-moveToState:...| will check if this should be a no-op or not. | 1338 // N.B.: |-moveToState:...| will check if this should be a no-op or not. |
1496 - (void)updateState:(BookmarkBar::State)newState | 1339 - (void)updateState:(BookmarkBar::State)newState |
1497 changeType:(BookmarkBar::AnimateChangeType)changeType { | 1340 changeType:(BookmarkBar::AnimateChangeType)changeType { |
1498 BOOL animate = changeType == BookmarkBar::ANIMATE_STATE_CHANGE && | 1341 BOOL animate = changeType == BookmarkBar::ANIMATE_STATE_CHANGE && |
1499 stateAnimationsEnabled_; | 1342 stateAnimationsEnabled_; |
1500 [self moveToState:newState withAnimation:animate]; | 1343 [self moveToState:newState withAnimation:animate]; |
1501 } | 1344 } |
1502 | 1345 |
1503 // (Private) | 1346 // Jump to final state (detached, attached, hidden, etc.) without animating, |
1347 // stopping a running animation if necessary. | |
1504 - (void)finalizeState { | 1348 - (void)finalizeState { |
1505 // We promise that our delegate that the variables will be finalized before | 1349 // We promise that our delegate that the variables will be finalized before |
1506 // the call to |-bookmarkBar:didChangeFromState:toState:|. | 1350 // the call to |-bookmarkBar:didChangeFromState:toState:|. |
1507 BookmarkBar::State oldState = lastState_; | 1351 BookmarkBar::State oldState = lastState_; |
1508 lastState_ = currentState_; | 1352 lastState_ = currentState_; |
1509 isAnimationRunning_ = NO; | 1353 isAnimationRunning_ = NO; |
1510 | 1354 |
1511 // Notify our delegate. | 1355 // Notify our delegate. |
1512 [delegate_ bookmarkBar:self | 1356 [delegate_ bookmarkBar:self |
1513 didChangeFromState:oldState | 1357 didChangeFromState:oldState |
1514 toState:currentState_]; | 1358 toState:currentState_]; |
1515 | 1359 |
1516 // Update ourselves visually. | 1360 // Update ourselves visually. |
1517 [self updateVisibility]; | 1361 [self updateVisibility]; |
1518 } | 1362 } |
1519 | 1363 |
1520 // (Private) | 1364 // Stops any current animation in its tracks (midway). |
1521 - (void)stopCurrentAnimation { | 1365 - (void)stopCurrentAnimation { |
1522 [[self controlledView] stopAnimation]; | 1366 [[self controlledView] stopAnimation]; |
1523 } | 1367 } |
1524 | 1368 |
1525 // Delegate method for |AnimatableView| (a superclass of | 1369 // Delegate method for |AnimatableView| (a superclass of |
1526 // |BookmarkBarToolbarView|). | 1370 // |BookmarkBarToolbarView|). |
1527 - (void)animationDidEnd:(NSAnimation*)animation { | 1371 - (void)animationDidEnd:(NSAnimation*)animation { |
1528 [self finalizeState]; | 1372 [self finalizeState]; |
1529 } | 1373 } |
1530 | 1374 |
1531 - (void)reconfigureBookmarkBar { | |
1532 [self setManagedBookmarksButtonVisibility]; | |
1533 [self setSupervisedBookmarksButtonVisibility]; | |
1534 [self redistributeButtonsOnBarAsNeeded]; | |
1535 [self positionRightSideButtons]; | |
1536 [self configureOffTheSideButtonContentsAndVisibility]; | |
1537 [self centerNoItemsLabel]; | |
1538 } | |
1539 | |
1540 // Determine if the given |view| can completely fit within the constraint of | |
1541 // maximum x, given by |maxViewX|, and, if not, narrow the view up to a minimum | |
1542 // width. If the minimum width is not achievable then hide the view. Return YES | |
1543 // if the view was hidden. | |
1544 - (BOOL)shrinkOrHideView:(NSView*)view forMaxX:(CGFloat)maxViewX { | |
1545 BOOL wasHidden = NO; | |
1546 // See if the view needs to be narrowed. | |
1547 NSRect frame = [view frame]; | |
1548 if (NSMaxX(frame) > maxViewX) { | |
1549 // Resize if more than 30 pixels are showing, otherwise hide. | |
1550 if (NSMinX(frame) + 30.0 < maxViewX) { | |
1551 frame.size.width = maxViewX - NSMinX(frame); | |
1552 [view setFrame:frame]; | |
1553 } else { | |
1554 [view setHidden:YES]; | |
1555 wasHidden = YES; | |
1556 } | |
1557 } | |
1558 return wasHidden; | |
1559 } | |
1560 | |
1561 // Bookmark button menu items that open a new window (e.g., open in new window, | 1375 // Bookmark button menu items that open a new window (e.g., open in new window, |
1562 // open in incognito, edit, etc.) cause us to lose a mouse-exited event | 1376 // open in incognito, edit, etc.) cause us to lose a mouse-exited event |
1563 // on the button, which leaves it in a hover state. | 1377 // on the button, which leaves it in a hover state. |
1564 // Since the showsBorderOnlyWhileMouseInside uses a tracking area, simple | 1378 // Since the showsBorderOnlyWhileMouseInside uses a tracking area, simple |
1565 // tricks (e.g. sending an extra mouseExited: to the button) don't | 1379 // tricks (e.g. sending an extra mouseExited: to the button) don't |
1566 // fix the problem. | 1380 // fix the problem. |
1567 // http://crbug.com/129338 | 1381 // http://crbug.com/129338 |
1568 - (void)unhighlightBookmark:(const BookmarkNode*)node { | 1382 - (void)unhighlightBookmark:(const BookmarkNode*)node { |
1569 // Only relevant if context menu was opened from a button on the | 1383 // Only relevant if context menu was opened from a button on the |
1570 // bookmark bar. | 1384 // bookmark bar. |
1571 const BookmarkNode* parent = node->parent(); | 1385 const BookmarkNode* parent = node->parent(); |
1572 BookmarkNode::Type parentType = parent->type(); | 1386 BookmarkNode::Type parentType = parent->type(); |
1573 if (parentType == BookmarkNode::BOOKMARK_BAR) { | 1387 if (parentType == BookmarkNode::BOOKMARK_BAR) { |
1574 int index = parent->GetIndexOf(node); | 1388 int index = parent->GetIndexOf(node); |
1575 if ((index >= 0) && (static_cast<NSUInteger>(index) < [buttons_ count])) { | 1389 if ((index >= 0) && (static_cast<NSUInteger>(index) < [buttons_ count])) { |
1576 NSButton* button = | 1390 NSButton* button = |
1577 [buttons_ objectAtIndex:static_cast<NSUInteger>(index)]; | 1391 [buttons_ objectAtIndex:static_cast<NSUInteger>(index)]; |
1578 if ([button showsBorderOnlyWhileMouseInside]) { | 1392 if ([button showsBorderOnlyWhileMouseInside]) { |
1579 [button setShowsBorderOnlyWhileMouseInside:NO]; | 1393 [button setShowsBorderOnlyWhileMouseInside:NO]; |
1580 [button setShowsBorderOnlyWhileMouseInside:YES]; | 1394 [button setShowsBorderOnlyWhileMouseInside:YES]; |
1581 } | 1395 } |
1582 } | 1396 } |
1583 } | 1397 } |
1584 } | 1398 } |
1585 | 1399 |
1586 | 1400 - (void)addButtonForNode:(const bookmarks::BookmarkNode*)node |
1587 // Adjust the horizontal width, x position and the visibility of the "For quick | 1401 atIndex:(NSInteger)buttonIndex { |
1588 // access" text field and "Import bookmarks..." button based on the current | 1402 [self rebuildLayout:NO]; |
1589 // width of the containing |buttonView_| (which is affected by window width). | |
1590 - (void)adjustNoItemContainerForMaxX:(CGFloat)maxViewX { | |
1591 if (![[buttonView_ noItemContainer] isHidden]) { | |
1592 // Reset initial frames for the two items, then adjust as necessary. | |
1593 NSTextField* noItemTextfield = [buttonView_ noItemTextfield]; | |
1594 NSRect noItemsRect = originalNoItemsRect_; | |
1595 NSRect importBookmarksRect = originalImportBookmarksRect_; | |
1596 if (![appsPageShortcutButton_ isHidden]) { | |
1597 float width = NSWidth([appsPageShortcutButton_ frame]); | |
1598 noItemsRect.origin.x += width; | |
1599 importBookmarksRect.origin.x += width; | |
1600 } | |
1601 if (![managedBookmarksButton_ isHidden]) { | |
1602 float width = NSWidth([managedBookmarksButton_ frame]); | |
1603 noItemsRect.origin.x += width; | |
1604 importBookmarksRect.origin.x += width; | |
1605 } | |
1606 if (![supervisedBookmarksButton_ isHidden]) { | |
1607 float width = NSWidth([supervisedBookmarksButton_ frame]); | |
1608 noItemsRect.origin.x += width; | |
1609 importBookmarksRect.origin.x += width; | |
1610 } | |
1611 [noItemTextfield setFrame:noItemsRect]; | |
1612 [noItemTextfield setHidden:NO]; | |
1613 NSButton* importBookmarksButton = [buttonView_ importBookmarksButton]; | |
1614 [importBookmarksButton setFrame:importBookmarksRect]; | |
1615 [importBookmarksButton setHidden:NO]; | |
1616 // Check each to see if they need to be shrunk or hidden. | |
1617 if ([self shrinkOrHideView:importBookmarksButton forMaxX:maxViewX]) | |
1618 [self shrinkOrHideView:noItemTextfield forMaxX:maxViewX]; | |
1619 } | |
1620 } | |
1621 | |
1622 // Scans through all buttons from left to right, calculating from scratch where | |
1623 // they should be based on the preceding widths, until it finds the one | |
1624 // requested. | |
1625 // Returns NSZeroRect if there is no such button in the bookmark bar. | |
1626 // Enables you to work out where a button will end up when it is done animating. | |
1627 - (NSRect)finalRectOfButton:(BookmarkButton*)wantedButton { | |
1628 CGFloat left = bookmarks::kBookmarkLeftMargin; | |
1629 NSRect buttonFrame = NSZeroRect; | |
1630 | |
1631 // Draw the apps bookmark if needed. | |
1632 if (![appsPageShortcutButton_ isHidden]) { | |
1633 left = NSMaxX([appsPageShortcutButton_ frame]) + | |
1634 bookmarks::kBookmarkHorizontalPadding; | |
1635 } | |
1636 | |
1637 // Draw the managed bookmarks folder if needed. | |
1638 if (![managedBookmarksButton_ isHidden]) { | |
1639 left = NSMaxX([managedBookmarksButton_ frame]) + | |
1640 bookmarks::kBookmarkHorizontalPadding; | |
1641 } | |
1642 | |
1643 // Draw the supervised bookmarks folder if needed. | |
1644 if (![supervisedBookmarksButton_ isHidden]) { | |
1645 left = NSMaxX([supervisedBookmarksButton_ frame]) + | |
1646 bookmarks::kBookmarkHorizontalPadding; | |
1647 } | |
1648 | |
1649 for (NSButton* button in buttons_.get()) { | |
1650 // Hidden buttons get no space. | |
1651 if ([button isHidden]) | |
1652 continue; | |
1653 buttonFrame = [button frame]; | |
1654 buttonFrame.origin.x = left; | |
1655 left += buttonFrame.size.width + bookmarks::kBookmarkHorizontalPadding; | |
1656 if (button == wantedButton) | |
1657 return buttonFrame; | |
1658 } | |
1659 return NSZeroRect; | |
1660 } | |
1661 | |
1662 // Calculates the final position of the last button in the bar. | |
1663 // We can't just use [[self buttons] lastObject] frame] because the button | |
1664 // may be animating currently. | |
1665 - (NSRect)finalRectOfLastButton { | |
1666 return [self finalRectOfButton:[[self buttons] lastObject]]; | |
1667 } | |
1668 | |
1669 - (CGFloat)buttonViewMaxXWithOffTheSideButtonIsVisible:(BOOL)visible { | |
1670 CGFloat maxViewX = NSMaxX([buttonView_ bounds]); | |
1671 // If necessary, pull in the width to account for the Other Bookmarks button. | |
1672 if ([self setOtherBookmarksButtonVisibility]) { | |
1673 maxViewX = [otherBookmarksButton_ frame].origin.x - | |
1674 bookmarks::kBookmarkRightMargin; | |
1675 } | |
1676 | |
1677 [self positionRightSideButtons]; | |
1678 // If we're already overflowing, then we need to account for the chevron. | |
1679 if (visible) { | |
1680 maxViewX = | |
1681 [offTheSideButton_ frame].origin.x - bookmarks::kBookmarkRightMargin; | |
1682 } | |
1683 | |
1684 return maxViewX; | |
1685 } | |
1686 | |
1687 - (void)redistributeButtonsOnBarAsNeeded { | |
1688 const BookmarkNode* node = bookmarkModel_->bookmark_bar_node(); | |
1689 NSInteger barCount = node->child_count(); | |
1690 | |
1691 // Determine the current maximum extent of the visible buttons. | |
1692 [self positionRightSideButtons]; | |
1693 BOOL offTheSideButtonVisible = (barCount > displayedButtonCount_); | |
1694 CGFloat maxViewX = [self buttonViewMaxXWithOffTheSideButtonIsVisible: | |
1695 offTheSideButtonVisible]; | |
1696 | |
1697 // As a result of pasting or dragging, the bar may now have more buttons | |
1698 // than will fit so remove any which overflow. They will be shown in | |
1699 // the off-the-side folder. | |
1700 while (displayedButtonCount_ > 0) { | |
1701 BookmarkButton* button = [buttons_ lastObject]; | |
1702 if (NSMaxX([self finalRectOfLastButton]) < maxViewX) | |
1703 break; | |
1704 [buttons_ removeLastObject]; | |
1705 [button setDelegate:nil]; | |
1706 [button removeFromSuperview]; | |
1707 --displayedButtonCount_; | |
1708 // Account for the fact that the chevron might now be visible. | |
1709 if (!offTheSideButtonVisible) { | |
1710 offTheSideButtonVisible = YES; | |
1711 maxViewX = [self buttonViewMaxXWithOffTheSideButtonIsVisible:YES]; | |
1712 } | |
1713 } | |
1714 | |
1715 // As a result of cutting, deleting and dragging, the bar may now have room | |
1716 // for more buttons. | |
1717 int xOffset; | |
1718 if (displayedButtonCount_ > 0) { | |
1719 xOffset = NSMaxX([self finalRectOfLastButton]); | |
1720 } else if (![managedBookmarksButton_ isHidden]) { | |
1721 xOffset = NSMaxX([managedBookmarksButton_ frame]) + | |
1722 bookmarks::kBookmarkHorizontalPadding; | |
1723 } else if (![supervisedBookmarksButton_ isHidden]) { | |
1724 xOffset = NSMaxX([supervisedBookmarksButton_ frame]) + | |
1725 bookmarks::kBookmarkHorizontalPadding; | |
1726 } else if (![appsPageShortcutButton_ isHidden]) { | |
1727 xOffset = NSMaxX([appsPageShortcutButton_ frame]) + | |
1728 bookmarks::kBookmarkHorizontalPadding; | |
1729 } else { | |
1730 xOffset = bookmarks::kBookmarkLeftMargin - | |
1731 bookmarks::kBookmarkHorizontalPadding; | |
1732 } | |
1733 for (int i = displayedButtonCount_; i < barCount; ++i) { | |
1734 const BookmarkNode* child = node->GetChild(i); | |
1735 BookmarkButton* button = [self buttonForNode:child xOffset:&xOffset]; | |
1736 // If we're testing against the last possible button then account | |
1737 // for the chevron no longer needing to be shown. | |
1738 if (i == barCount - 1) | |
1739 maxViewX = [self buttonViewMaxXWithOffTheSideButtonIsVisible:NO]; | |
1740 if (NSMaxX([button frame]) > maxViewX) { | |
1741 [button setDelegate:nil]; | |
1742 break; | |
1743 } | |
1744 ++displayedButtonCount_; | |
1745 [buttons_ addObject:button]; | |
1746 [buttonView_ addSubview:button]; | |
1747 } | |
1748 | |
1749 // While we're here, adjust the horizontal width and the visibility | |
1750 // of the "For quick access" and "Import bookmarks..." text fields. | |
1751 if (![buttons_ count]) | |
1752 [self adjustNoItemContainerForMaxX:maxViewX]; | |
1753 } | 1403 } |
1754 | 1404 |
1755 #pragma mark Private Methods Exposed for Testing | 1405 #pragma mark Private Methods Exposed for Testing |
1756 | 1406 |
1757 - (BookmarkBarView*)buttonView { | 1407 - (BookmarkBarView*)buttonView { |
1758 return buttonView_; | 1408 return buttonView_; |
1759 } | 1409 } |
1760 | 1410 |
1761 - (NSMutableArray*)buttons { | 1411 - (NSMutableArray*)buttons { |
1762 return buttons_.get(); | 1412 return buttons_.get(); |
1763 } | 1413 } |
1764 | 1414 |
1765 - (BOOL)offTheSideButtonIsHidden { | |
1766 return [offTheSideButton_ isHidden]; | |
1767 } | |
1768 | |
1769 - (BOOL)appsPageShortcutButtonIsHidden { | |
1770 return [appsPageShortcutButton_ isHidden]; | |
1771 } | |
1772 | |
1773 - (BookmarkButton*)otherBookmarksButton { | 1415 - (BookmarkButton*)otherBookmarksButton { |
1774 return otherBookmarksButton_.get(); | 1416 return otherBookmarksButton_.get(); |
1775 } | 1417 } |
1776 | 1418 |
1419 - (BookmarkButton*)managedBookmarksButton { | |
1420 return managedBookmarksButton_.get(); | |
1421 } | |
1422 | |
1423 - (BookmarkButton*)supervisedBookmarksButton { | |
1424 return supervisedBookmarksButton_.get(); | |
1425 } | |
1426 | |
1777 - (BookmarkBarFolderController*)folderController { | 1427 - (BookmarkBarFolderController*)folderController { |
1778 return folderController_; | 1428 return folderController_; |
1779 } | 1429 } |
1780 | 1430 |
1781 - (id)folderTarget { | 1431 - (id)folderTarget { |
1782 return folderTarget_.get(); | 1432 return folderTarget_.get(); |
1783 } | 1433 } |
1784 | 1434 |
1785 - (int)displayedButtonCount { | |
1786 return displayedButtonCount_; | |
1787 } | |
1788 | |
1789 // Delete all buttons (bookmarks, chevron, "other bookmarks") from the | |
1790 // bookmark bar; reset knowledge of bookmarks. | |
1791 - (void)clearBookmarkBar { | |
1792 [self stopPulsingBookmarkNode]; | |
1793 for (BookmarkButton* button in buttons_.get()) { | |
1794 [button setDelegate:nil]; | |
1795 [button removeFromSuperview]; | |
1796 } | |
1797 [buttons_ removeAllObjects]; | |
1798 displayedButtonCount_ = 0; | |
1799 | |
1800 // Make sure there are no stale pointers in the pasteboard. This | |
1801 // can be important if a bookmark is deleted (via bookmark sync) | |
1802 // while in the middle of a drag. The "drag completed" code | |
1803 // (e.g. [BookmarkBarView performDragOperationForBookmarkButton:]) is | |
1804 // careful enough to bail if there is no data found at "drop" time. | |
1805 [[NSPasteboard pasteboardWithName:NSDragPboard] clearContents]; | |
1806 } | |
1807 | |
1808 // Return an autoreleased NSCell suitable for a bookmark button. | 1435 // Return an autoreleased NSCell suitable for a bookmark button. |
1809 // TODO(jrg): move much of the cell config into the BookmarkButtonCell class. | 1436 // TODO(jrg): move much of the cell config into the BookmarkButtonCell class. |
1810 - (BookmarkButtonCell*)cellForBookmarkNode:(const BookmarkNode*)node { | 1437 - (BookmarkButtonCell*)cellForBookmarkNode:(const BookmarkNode*)node { |
1811 BOOL darkTheme = [[[self view] window] hasDarkTheme]; | 1438 BOOL darkTheme = [[[self view] window] hasDarkTheme]; |
1812 NSImage* image = node ? [self faviconForNode:node forADarkTheme:darkTheme] | 1439 NSImage* image = node ? [self faviconForNode:node forADarkTheme:darkTheme] |
1813 : nil; | 1440 : nil; |
1814 BookmarkButtonCell* cell = | 1441 BookmarkButtonCell* cell = |
1815 [BookmarkButtonCell buttonCellForNode:node | 1442 [BookmarkButtonCell buttonCellForNode:node |
1816 text:nil | 1443 text:nil |
1817 image:image | 1444 image:image |
(...skipping 17 matching lines...) Expand all Loading... | |
1835 menuController:contextMenuController_]; | 1462 menuController:contextMenuController_]; |
1836 [cell setTag:kMaterialStandardButtonTypeWithLimitedClickFeedback]; | 1463 [cell setTag:kMaterialStandardButtonTypeWithLimitedClickFeedback]; |
1837 [cell setHighlightsBy:NSNoCellMask]; | 1464 [cell setHighlightsBy:NSNoCellMask]; |
1838 | 1465 |
1839 // Note: a quirk of setting a cell's text color is that it won't work | 1466 // Note: a quirk of setting a cell's text color is that it won't work |
1840 // until the cell is associated with a button, so we can't theme the cell yet. | 1467 // until the cell is associated with a button, so we can't theme the cell yet. |
1841 | 1468 |
1842 return cell; | 1469 return cell; |
1843 } | 1470 } |
1844 | 1471 |
1845 // Returns a frame appropriate for the given bookmark cell, suitable | |
1846 // for creating an NSButton that will contain it. |xOffset| is the X | |
1847 // offset for the frame; it is increased to be an appropriate X offset | |
1848 // for the next button. | |
1849 - (NSRect)frameForBookmarkButtonFromCell:(NSCell*)cell | |
1850 xOffset:(int*)xOffset { | |
1851 DCHECK(xOffset); | |
1852 NSRect bounds = [buttonView_ bounds]; | |
1853 bounds.size.height = bookmarks::kBookmarkButtonHeight; | |
1854 | |
1855 NSRect frame = NSInsetRect(bounds, | |
1856 bookmarks::kBookmarkHorizontalPadding, | |
1857 bookmarks::kBookmarkVerticalPadding); | |
1858 frame.size.width = [self widthForBookmarkButtonCell:cell]; | |
1859 | |
1860 // Add an X offset based on what we've already done | |
1861 frame.origin.x += *xOffset; | |
1862 | |
1863 // And up the X offset for next time. | |
1864 *xOffset = NSMaxX(frame); | |
1865 | |
1866 return frame; | |
1867 } | |
1868 | |
1869 // A bookmark button's contents changed. Check for growth | |
1870 // (e.g. increase the width up to the maximum). If we grew, move | |
1871 // other bookmark buttons over. | |
1872 - (void)checkForBookmarkButtonGrowth:(NSButton*)changedButton { | |
1873 NSRect frame = [changedButton frame]; | |
1874 CGFloat desiredSize = [self widthForBookmarkButtonCell:[changedButton cell]]; | |
1875 CGFloat delta = desiredSize - frame.size.width; | |
1876 if (delta) { | |
1877 frame.size.width = desiredSize; | |
1878 [changedButton setFrame:frame]; | |
1879 for (NSButton* button in buttons_.get()) { | |
1880 NSRect buttonFrame = [button frame]; | |
1881 if (buttonFrame.origin.x > frame.origin.x) { | |
1882 buttonFrame.origin.x += delta; | |
1883 [button setFrame:buttonFrame]; | |
1884 } | |
1885 } | |
1886 } | |
1887 // We may have just crossed a threshold to enable the off-the-side | |
1888 // button. | |
1889 [self configureOffTheSideButtonContentsAndVisibility]; | |
1890 } | |
1891 | |
1892 // Called when our controlled frame has changed size. | 1472 // Called when our controlled frame has changed size. |
1893 - (void)frameDidChange { | 1473 - (void)frameDidChange { |
1894 if (!bookmarkModel_->loaded()) | 1474 [self rebuildLayout:NO]; |
1895 return; | |
1896 [self updateTheme:[[[self view] window] themeProvider]]; | |
1897 [self reconfigureBookmarkBar]; | |
1898 } | 1475 } |
1899 | 1476 |
1900 // Adapt appearance of buttons to the current theme. Called after | 1477 // Adapt appearance of buttons to the current theme. Called after |
1901 // theme changes, or when our view is added to the view hierarchy. | 1478 // theme changes, or when our view is added to the view hierarchy. |
1902 // Oddly, the view pings us instead of us pinging our view. This is | 1479 // Oddly, the view pings us instead of us pinging our view. This is |
1903 // because our trigger is an [NSView viewWillMoveToWindow:], which the | 1480 // because our trigger is an [NSView viewWillMoveToWindow:], which the |
1904 // controller doesn't normally know about. Otherwise we don't have | 1481 // controller doesn't normally know about. Otherwise we don't have |
1905 // access to the theme before we know what window we will be on. | 1482 // access to the theme before we know what window we will be on. |
1906 - (void)updateTheme:(const ui::ThemeProvider*)themeProvider { | 1483 - (void)updateTheme:(const ui::ThemeProvider*)themeProvider { |
1907 if (!themeProvider) | 1484 if (!themeProvider) |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1982 | 1559 |
1983 // Find something like std::is_between<T>? I can't believe one doesn't exist. | 1560 // Find something like std::is_between<T>? I can't believe one doesn't exist. |
1984 static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { | 1561 static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { |
1985 return ((value >= low) && (value <= high)); | 1562 return ((value >= low) && (value <= high)); |
1986 } | 1563 } |
1987 | 1564 |
1988 // Return the proposed drop target for a hover open button from the | 1565 // Return the proposed drop target for a hover open button from the |
1989 // given array, or nil if none. We use this for distinguishing | 1566 // given array, or nil if none. We use this for distinguishing |
1990 // between a hover-open candidate or drop-indicator draw. | 1567 // between a hover-open candidate or drop-indicator draw. |
1991 // Helper for buttonForDroppingOnAtPoint:. | 1568 // Helper for buttonForDroppingOnAtPoint:. |
1992 // Get UI review on "middle half" ness. | |
1993 // http://crbug.com/36276 | |
1994 - (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point | 1569 - (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point |
1995 fromArray:(NSArray*)array { | 1570 fromArray:(NSArray*)array { |
1996 for (BookmarkButton* button in array) { | 1571 for (BookmarkButton* button in array) { |
1997 // Hidden buttons can overlap valid visible buttons, just ignore. | 1572 // Hidden buttons can overlap valid visible buttons, just ignore. |
1998 if ([button isHidden]) | 1573 if ([button isHidden]) |
1999 continue; | 1574 continue; |
2000 // Break early if we've gone too far. | 1575 // Break early if we've gone too far. |
2001 if ((NSMinX([button frame]) > point.x) || (![button superview])) | 1576 if ((NSMinX([button frame]) > point.x) || (![button superview])) |
2002 return nil; | 1577 return nil; |
2003 // Careful -- this only applies to the bar with horiz buttons. | 1578 // Careful -- this only applies to the bar with horiz buttons. |
(...skipping 30 matching lines...) Expand all Loading... | |
2034 - (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point { | 1609 - (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point { |
2035 point = [[self view] convertPoint:point | 1610 point = [[self view] convertPoint:point |
2036 fromView:[[[self view] window] contentView]]; | 1611 fromView:[[[self view] window] contentView]]; |
2037 | 1612 |
2038 // If there's a hover button, return it if the point is within its bounds. | 1613 // If there's a hover button, return it if the point is within its bounds. |
2039 // Since the logic in -buttonForDroppingOnAtPoint:fromArray: only matches a | 1614 // Since the logic in -buttonForDroppingOnAtPoint:fromArray: only matches a |
2040 // button when the point is over the middle half, this is needed to prevent | 1615 // button when the point is over the middle half, this is needed to prevent |
2041 // the button's folder being closed if the mouse temporarily leaves the | 1616 // the button's folder being closed if the mouse temporarily leaves the |
2042 // middle half but is still within the button bounds. | 1617 // middle half but is still within the button bounds. |
2043 if (hoverButton_ && NSPointInRect(point, [hoverButton_ frame])) | 1618 if (hoverButton_ && NSPointInRect(point, [hoverButton_ frame])) |
2044 return hoverButton_.get(); | 1619 return hoverButton_.get(); |
2045 | 1620 |
2046 BookmarkButton* button = [self buttonForDroppingOnAtPoint:point | 1621 BookmarkButton* button = [self buttonForDroppingOnAtPoint:point |
2047 fromArray:buttons_.get()]; | 1622 fromArray:buttons_.get()]; |
2048 // One more chance -- try "Other Bookmarks" and "off the side" (if visible). | 1623 // One more chance -- try "Other Bookmarks" and "off the side" (if visible). |
2049 // This is different than BookmarkBarFolderController. | 1624 // This is different than BookmarkBarFolderController. |
2050 if (!button) { | 1625 if (!button) { |
2051 NSMutableArray* array = [NSMutableArray array]; | 1626 NSMutableArray* array = [NSMutableArray array]; |
2052 if (![self offTheSideButtonIsHidden]) | 1627 if (layout_.IsOffTheSideButtonVisible()) |
2053 [array addObject:offTheSideButton_]; | 1628 [array addObject:offTheSideButton_]; |
2054 [array addObject:otherBookmarksButton_]; | 1629 [array addObject:otherBookmarksButton_]; |
2055 button = [self buttonForDroppingOnAtPoint:point | 1630 button = [self buttonForDroppingOnAtPoint:point |
2056 fromArray:array]; | 1631 fromArray:array]; |
2057 } | 1632 } |
2058 return button; | 1633 return button; |
2059 } | 1634 } |
2060 | 1635 |
1636 // Returns the index in the model for a drag to the location given by | |
1637 // |point|. This is determined by finding the first button before the center | |
1638 // of which |point| falls, scanning front to back. Note that, currently, only | |
1639 // the x-coordinate of |point| is considered. Though not currently implemented, | |
1640 // we may check for errors, in which case this would return negative value; | |
1641 // callers should check for this. | |
2061 - (int)indexForDragToPoint:(NSPoint)point { | 1642 - (int)indexForDragToPoint:(NSPoint)point { |
2062 // TODO(jrg): revisit position info based on UI team feedback. | |
2063 // dropLocation is in bar local coordinates. | |
2064 NSPoint dropLocation = | 1643 NSPoint dropLocation = |
2065 [[self view] convertPoint:point | 1644 [[self view] convertPoint:point |
2066 fromView:[[[self view] window] contentView]]; | 1645 fromView:[[[self view] window] contentView]]; |
2067 BookmarkButton* buttonToTheRightOfDraggedButton = nil; | 1646 BookmarkButton* buttonAfterDraggedButton = nil; |
1647 BOOL isRTL = cocoa_l10n_util::ShouldDoExperimentalRTLLayout(); | |
2068 for (BookmarkButton* button in buttons_.get()) { | 1648 for (BookmarkButton* button in buttons_.get()) { |
2069 CGFloat midpoint = NSMidX([button frame]); | 1649 CGFloat midpoint = NSMidX([button frame]); |
2070 if (dropLocation.x <= midpoint) { | 1650 if (isRTL ? dropLocation.x >= midpoint : dropLocation.x <= midpoint) { |
2071 buttonToTheRightOfDraggedButton = button; | 1651 buttonAfterDraggedButton = button; |
2072 break; | 1652 break; |
2073 } | 1653 } |
2074 } | 1654 } |
2075 if (buttonToTheRightOfDraggedButton) { | 1655 if (buttonAfterDraggedButton) { |
2076 const BookmarkNode* afterNode = | 1656 const BookmarkNode* afterNode = [buttonAfterDraggedButton bookmarkNode]; |
2077 [buttonToTheRightOfDraggedButton bookmarkNode]; | |
2078 DCHECK(afterNode); | 1657 DCHECK(afterNode); |
2079 int index = afterNode->parent()->GetIndexOf(afterNode); | 1658 size_t index = afterNode->parent()->GetIndexOf(afterNode); |
2080 // Make sure we don't get confused by buttons which aren't visible. | 1659 // Make sure we don't get confused by buttons which aren't visible. |
2081 return std::min(index, displayedButtonCount_); | 1660 return std::min(index, layout_.VisibleButtonCount()); |
2082 } | 1661 } |
2083 | 1662 // If nothing is after me, I am at the end! |
Avi (use Gerrit)
2017/04/10 20:25:54
"me" in this comment is strange. The only other co
lgrey
2017/04/26 20:12:56
Done. Simplified the logic a bit so the other comm
| |
2084 // If nothing is to my right I am at the end! | 1663 return layout_.VisibleButtonCount(); |
2085 return displayedButtonCount_; | |
2086 } | 1664 } |
2087 | 1665 |
1666 // Informs the bar that something representing the bookmark at | |
1667 // |sourceNode| was dragged into the bar. | |
1668 // |point| is in the base coordinate system of the destination window; | |
1669 // it comes from an id<NSDraggingInfo>. |copy| is YES if a copy is to be | |
1670 // made and inserted into the new location while leaving the bookmark in | |
1671 // the old location, otherwise move the bookmark by removing from its old | |
1672 // location and inserting into the new location. | |
1673 // Returns whether the drag was allowed. | |
2088 // TODO(mrossetti,jrg): Yet more duplicated code. | 1674 // TODO(mrossetti,jrg): Yet more duplicated code. |
2089 // http://crbug.com/35966 | 1675 // http://crbug.com/35966 |
2090 - (BOOL)dragBookmark:(const BookmarkNode*)sourceNode | 1676 - (BOOL)dragBookmark:(const BookmarkNode*)sourceNode |
2091 to:(NSPoint)point | 1677 to:(NSPoint)point |
2092 copy:(BOOL)copy { | 1678 copy:(BOOL)copy { |
2093 DCHECK(sourceNode); | 1679 DCHECK(sourceNode); |
2094 // Drop destination. | 1680 // Drop destination. |
2095 const BookmarkNode* destParent = NULL; | 1681 const BookmarkNode* destParent = NULL; |
2096 int destIndex = 0; | 1682 int destIndex = 0; |
2097 | 1683 |
(...skipping 26 matching lines...) Expand all Loading... | |
2124 [self closeFolderAndStopTrackingMenus]; | 1710 [self closeFolderAndStopTrackingMenus]; |
2125 | 1711 |
2126 // Movement of a node triggers observers (like us) to rebuild the | 1712 // Movement of a node triggers observers (like us) to rebuild the |
2127 // bar so we don't have to do so explicitly. | 1713 // bar so we don't have to do so explicitly. |
2128 | 1714 |
2129 return YES; | 1715 return YES; |
2130 } | 1716 } |
2131 | 1717 |
2132 - (void)draggingEnded:(id<NSDraggingInfo>)info { | 1718 - (void)draggingEnded:(id<NSDraggingInfo>)info { |
2133 [self closeFolderAndStopTrackingMenus]; | 1719 [self closeFolderAndStopTrackingMenus]; |
2134 [[BookmarkButton draggedButton] setHidden:NO]; | 1720 layout_ = {}; // Force layout. |
2135 [self resetAllButtonPositionsWithAnimation:YES]; | 1721 [self rebuildLayout:YES]; |
2136 } | 1722 } |
2137 | 1723 |
2138 // Set insertionPos_ and hasInsertionPos_, and make insertion space for a | 1724 // Set insertionPos_ and hasInsertionPos_, and make insertion space for a |
2139 // hypothetical drop with the new button having a left edge of |where|. | 1725 // hypothetical drop with the new button having a left edge of |where|. |
2140 // Gets called only by our view. | |
2141 - (void)setDropInsertionPos:(CGFloat)where { | 1726 - (void)setDropInsertionPos:(CGFloat)where { |
2142 if (!hasInsertionPos_ || where != insertionPos_) { | 1727 if (hasInsertionPos_ && where == insertionPos_) { |
2143 insertionPos_ = where; | 1728 return; |
2144 hasInsertionPos_ = YES; | 1729 } |
2145 CGFloat left; | 1730 insertionPos_ = where; |
2146 if (![supervisedBookmarksButton_ isHidden]) { | 1731 hasInsertionPos_ = YES; |
2147 left = NSMaxX([supervisedBookmarksButton_ frame]) + | 1732 CGFloat paddingWidth = bookmarks::kDefaultBookmarkWidth; |
2148 bookmarks::kBookmarkHorizontalPadding; | 1733 BookmarkButton* draggedButton = [BookmarkButton draggedButton]; |
2149 } else if (![managedBookmarksButton_ isHidden]) { | 1734 BOOL draggedButtonIsOnBar = NO; |
2150 left = NSMaxX([managedBookmarksButton_ frame]) + | 1735 int64_t draggedButtonNodeId; |
2151 bookmarks::kBookmarkHorizontalPadding; | 1736 CGFloat draggedButtonOffset; |
2152 } else if (![appsPageShortcutButton_ isHidden]) { | 1737 if (draggedButton) { |
2153 left = NSMaxX([appsPageShortcutButton_ frame]) + | 1738 paddingWidth = std::min(bookmarks::kDefaultBookmarkWidth, |
2154 bookmarks::kBookmarkHorizontalPadding; | 1739 NSWidth([draggedButton frame])); |
1740 draggedButtonNodeId = [draggedButton bookmarkNode]->id(); | |
1741 auto offsetIt = layout_.button_offsets.find(draggedButtonNodeId); | |
1742 if (offsetIt != layout_.button_offsets.end()) { | |
1743 draggedButtonIsOnBar = YES; | |
1744 draggedButtonOffset = (*offsetIt).second; | |
1745 } | |
1746 } | |
1747 paddingWidth += bookmarks::kBookmarkHorizontalPadding; | |
1748 BOOL isRTL = cocoa_l10n_util::ShouldDoExperimentalRTLLayout(); | |
1749 | |
1750 // If the button being dragged is not currently on the bar | |
1751 // (for example, a drag from the URL bar, a link on the desktop, | |
1752 // a button inside a menu, etc.), buttons in front of the drag position | |
1753 // (to the right in LTR, to the left in RTL), should make room for it. | |
1754 // Otherwise: | |
1755 // If a given button was to the left of the dragged button's original | |
1756 // position, but is to the right of the drag position, or | |
1757 // if it was to the right of the dragged button's original position and | |
1758 // is to the left of the drag position, make room. | |
1759 [NSAnimationContext beginGrouping]; | |
1760 [[NSAnimationContext currentContext] | |
1761 setDuration:kDragAndDropAnimationDuration]; | |
1762 for (BookmarkButton* button in buttons_.get()) { | |
1763 CGRect buttonFrame = [button frame]; | |
1764 int64_t nodeId = [button bookmarkNode]->id(); | |
1765 CGFloat offset = layout_.button_offsets[nodeId]; | |
1766 CGFloat buttonEdge = isRTL ? NSWidth([buttonView_ frame]) - offset : offset; | |
1767 | |
1768 if (draggedButtonIsOnBar) { | |
1769 if (nodeId == draggedButtonNodeId) | |
1770 continue; | |
1771 BOOL wasBefore = offset < draggedButtonOffset; | |
1772 BOOL isBefore = isRTL ? buttonEdge > where : buttonEdge < where; | |
1773 if (isBefore && !wasBefore) { | |
1774 offset -= paddingWidth; | |
1775 } else if (!isBefore && wasBefore) { | |
1776 offset += paddingWidth; | |
1777 } | |
1778 } else if ((isRTL && where > buttonEdge) || | |
1779 where < offset + NSWidth(buttonFrame)) { | |
Avi (use Gerrit)
2017/04/10 20:25:54
This line feels funny. Why do we have one branch o
Elly Fong-Jones
2017/04/26 13:36:02
sometimes this happens because even in RTL the coo
lgrey
2017/04/26 20:12:56
Agree that this was confusing. It was also hiding
| |
1780 offset += paddingWidth; | |
1781 } | |
1782 [self applyXOffset:offset | |
1783 toButton:button | |
1784 animated:innerContentAnimationsEnabled_]; | |
1785 } | |
1786 [NSAnimationContext endGrouping]; | |
1787 } | |
1788 | |
1789 - (BookmarkBarLayout)layoutFromCurrentState { | |
1790 BookmarkBarLayout layout = {}; | |
1791 | |
1792 const BookmarkNode* node = bookmarkModel_->bookmark_bar_node(); | |
1793 CGFloat viewWidth = NSWidth([buttonView_ frame]); | |
1794 CGFloat xOffset = bookmarks::kBookmarkLeftMargin; | |
1795 CGFloat maxX = viewWidth - bookmarks::kBookmarkHorizontalPadding; | |
1796 | |
1797 layout.visible_elements = bookmarks::kVisibleElementsMaskNone; | |
1798 layout.max_x = maxX; | |
1799 | |
1800 // Lay out "extra" buttons (apps, managed, supervised, "Other"). | |
1801 if (chrome::ShouldShowAppsShortcutInBookmarkBar(browser_->profile())) { | |
1802 layout.visible_elements |= bookmarks::kVisibleElementsMaskAppsButton; | |
1803 layout.apps_button_offset = xOffset; | |
1804 xOffset += NSWidth([appsPageShortcutButton_ frame]) + | |
1805 bookmarks::kBookmarkHorizontalPadding; | |
1806 } | |
1807 if (!managedBookmarkService_->managed_node()->empty()) { | |
1808 layout.visible_elements |= | |
1809 bookmarks::kVisibleElementsMaskManagedBookmarksButton; | |
1810 layout.managed_bookmarks_button_offset = xOffset; | |
1811 xOffset += NSWidth([managedBookmarksButton_ frame]) + | |
1812 bookmarks::kBookmarkHorizontalPadding; | |
1813 } | |
1814 if (!managedBookmarkService_->supervised_node()->empty()) { | |
1815 layout.visible_elements |= | |
1816 bookmarks::kVisibleElementsMaskSupervisedBookmarksButton; | |
1817 layout.supervised_bookmarks_button_offset = xOffset; | |
1818 xOffset += NSWidth([supervisedBookmarksButton_ frame]) + | |
1819 bookmarks::kBookmarkHorizontalPadding; | |
1820 } | |
1821 if (!bookmarkModel_->other_node()->empty()) { | |
1822 layout.visible_elements |= | |
1823 bookmarks::kVisibleElementsMaskOtherBookmarksButton; | |
1824 maxX -= NSWidth([otherBookmarksButton_ frame]); | |
1825 layout.other_bookmarks_button_offset = maxX; | |
1826 } | |
1827 | |
1828 // Lay out empty state ("no items" label, import bookmarks button.) | |
1829 if (node->empty()) { | |
1830 CGFloat roomForTextField = | |
1831 maxX - xOffset + bookmarks::kInitialNoItemTextFieldXOrigin; | |
1832 if (roomForTextField >= kNoItemElementMinWidth) { | |
1833 layout.visible_elements |= bookmarks::kVisibleElementsMaskNoItemTextField; | |
1834 xOffset += bookmarks::kInitialNoItemTextFieldXOrigin; | |
1835 layout.no_item_textfield_offset = xOffset; | |
1836 layout.no_item_textfield_width = | |
1837 std::min(maxX - xOffset, originalNoItemTextFieldWidth_); | |
1838 xOffset += | |
1839 layout.no_item_textfield_width + originalNoItemInterelementPadding_; | |
1840 | |
1841 // Does the "import bookmarks" button fit? | |
1842 if (maxX - xOffset >= kNoItemElementMinWidth) { | |
1843 layout.visible_elements |= | |
1844 bookmarks::kVisibleElementsMaskImportBookmarksButton; | |
1845 layout.import_bookmarks_button_offset = xOffset; | |
1846 layout.import_bookmarks_button_width = | |
1847 std::min(maxX - xOffset, originalImportBookmarksButtonWidth_); | |
1848 } | |
1849 } | |
1850 } else { | |
1851 // Lay out bookmark buttons and "off-the-side" chevron. | |
1852 CGFloat offTheSideButtonWidth = NSWidth([offTheSideButton_ frame]); | |
1853 int buttonCount = node->child_count(); | |
1854 for (int i = 0; i < buttonCount; i++) { | |
1855 const BookmarkNode* buttonNode = node->GetChild(i); | |
1856 CGFloat widthOfButton = [self widthOfButtonForNode:buttonNode]; | |
1857 // If it's the last button, we just need to ensure that it can fit. | |
1858 // If not, we need to be able to fit both it and the chevron. | |
1859 CGFloat widthToCheck = i == buttonCount - 1 | |
1860 ? widthOfButton | |
1861 : widthOfButton + offTheSideButtonWidth; | |
1862 if (xOffset + widthToCheck > maxX) { | |
1863 layout.visible_elements |= | |
1864 bookmarks::kVisibleElementsMaskOffTheSideButton; | |
1865 layout.off_the_side_button_offset = maxX - offTheSideButtonWidth; | |
1866 break; | |
1867 } | |
1868 layout.button_offsets.insert({buttonNode->id(), xOffset}); | |
1869 xOffset += widthOfButton + bookmarks::kBookmarkHorizontalPadding; | |
1870 } | |
1871 } | |
1872 return layout; | |
1873 } | |
1874 | |
1875 - (void)rebuildLayout:(BOOL)animated { | |
Avi (use Gerrit)
2017/04/10 20:25:54
You need to have a label for your parameter, other
lgrey
2017/04/26 20:12:56
Done.
| |
1876 if (!bookmarkModel_->loaded()) | |
1877 return; | |
1878 | |
1879 BookmarkBarLayout layout = [self layoutFromCurrentState]; | |
1880 if (layout_ != layout) { | |
1881 layout_ = std::move(layout); | |
1882 [self applyLayout:layout_ animated:animated]; | |
1883 } | |
1884 } | |
1885 | |
1886 - (void)applyLayout:(const BookmarkBarLayout&)layout animated:(BOOL)animated { | |
1887 if (!bookmarkModel_->loaded()) | |
1888 return; | |
1889 | |
1890 if (folderController_) | |
1891 [self closeAllBookmarkFolders]; | |
1892 [self stopPulsingBookmarkNode]; | |
1893 | |
1894 // Hide or show "extra" buttons and position if necessary. | |
1895 [self applyXOffset:layout.apps_button_offset | |
1896 toButton:appsPageShortcutButton_ | |
1897 animated:NO]; | |
1898 [appsPageShortcutButton_ setHidden:!layout.IsAppsButtonVisible()]; | |
1899 | |
1900 [self applyXOffset:layout.managed_bookmarks_button_offset | |
1901 toButton:managedBookmarksButton_ | |
1902 animated:NO]; | |
1903 [managedBookmarksButton_ setHidden:!layout.IsManagedBookmarksButtonVisible()]; | |
1904 | |
1905 [self applyXOffset:layout.supervised_bookmarks_button_offset | |
1906 toButton:supervisedBookmarksButton_ | |
1907 animated:NO]; | |
1908 [supervisedBookmarksButton_ | |
1909 setHidden:!layout.IsSupervisedBookmarksButtonVisible()]; | |
1910 | |
1911 [self applyXOffset:layout.other_bookmarks_button_offset | |
1912 toButton:otherBookmarksButton_ | |
1913 animated:NO]; | |
1914 [otherBookmarksButton_ setHidden:!layout.IsOtherBookmarksButtonVisible()]; | |
1915 | |
1916 [self applyXOffset:layout.off_the_side_button_offset | |
1917 toButton:offTheSideButton_ | |
1918 animated:NO]; | |
1919 [offTheSideButton_ setHidden:!layout.IsOffTheSideButtonVisible()]; | |
1920 if (layout.IsOffTheSideButtonVisible()) { | |
1921 [[offTheSideButton_ cell] | |
1922 setStartingChildIndex:layout_.VisibleButtonCount()]; | |
1923 } | |
1924 | |
1925 // Hide or show empty state and position if necessary. | |
1926 [[buttonView_ noItemTextField] setHidden:!layout.IsNoItemTextFieldVisible()]; | |
1927 [[buttonView_ importBookmarksButton] | |
1928 setHidden:!layout.IsImportBookmarksButtonVisible()]; | |
1929 | |
1930 if (layout.IsNoItemTextFieldVisible()) { | |
1931 NSTextField* noItemTextField = [buttonView_ noItemTextField]; | |
1932 [noItemTextField setHidden:NO]; | |
1933 NSRect textFieldFrame = [noItemTextField frame]; | |
1934 textFieldFrame.size.width = layout.no_item_textfield_width; | |
1935 if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) { | |
1936 textFieldFrame.origin.x = NSWidth([buttonView_ frame]) - | |
1937 layout.no_item_textfield_offset - | |
1938 layout.no_item_textfield_width; | |
2155 } else { | 1939 } else { |
2156 left = bookmarks::kBookmarkLeftMargin; | 1940 textFieldFrame.origin.x = layout.no_item_textfield_offset; |
2157 } | 1941 } |
2158 CGFloat paddingWidth = bookmarks::kDefaultBookmarkWidth; | 1942 [noItemTextField setFrame:textFieldFrame]; |
2159 BookmarkButton* draggedButton = [BookmarkButton draggedButton]; | 1943 if (layout.IsImportBookmarksButtonVisible()) { |
2160 if (draggedButton) { | 1944 NSButton* importBookmarksButton = [buttonView_ importBookmarksButton]; |
2161 paddingWidth = std::min(bookmarks::kDefaultBookmarkWidth, | 1945 NSRect buttonFrame = [importBookmarksButton frame]; |
2162 NSWidth([draggedButton frame])); | 1946 buttonFrame.size.width = layout.import_bookmarks_button_width; |
2163 } | 1947 if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) { |
2164 // Put all the buttons where they belong, with all buttons to the right | 1948 buttonFrame.origin.x = NSWidth([buttonView_ frame]) - |
2165 // of the insertion point shuffling right to make space for it. | 1949 layout.import_bookmarks_button_offset - |
2166 [NSAnimationContext beginGrouping]; | 1950 layout.import_bookmarks_button_width; |
2167 [[NSAnimationContext currentContext] | 1951 } else { |
2168 setDuration:kDragAndDropAnimationDuration]; | 1952 buttonFrame.origin.x = layout.import_bookmarks_button_offset; |
2169 for (NSButton* button in buttons_.get()) { | 1953 } |
2170 // Hidden buttons get no space. | 1954 [importBookmarksButton setFrame:buttonFrame]; |
2171 if ([button isHidden]) | 1955 } |
2172 continue; | 1956 } |
2173 NSRect buttonFrame = [button frame]; | 1957 // 1) Hide all buttons initially. |
2174 buttonFrame.origin.x = left; | 1958 // 2) Show all buttons in the layout. |
2175 // Update "left" for next time around. | 1959 // 3) Remove any buttons that are still hidden (so: not in the layout) |
2176 left += buttonFrame.size.width; | 1960 // from the node ID -> button map and add them to the reuse pool if |
2177 if (left > insertionPos_) | 1961 // there's room. |
2178 buttonFrame.origin.x += paddingWidth; | 1962 for (BookmarkButton* button in buttons_.get()) { |
2179 left += bookmarks::kBookmarkHorizontalPadding; | 1963 [button setHidden:YES]; |
2180 if (innerContentAnimationsEnabled_) | 1964 } |
2181 [[button animator] setFrame:buttonFrame]; | 1965 [buttons_ removeAllObjects]; |
2182 else | 1966 const BookmarkNode* parentNode = bookmarkModel_->bookmark_bar_node(); |
2183 [button setFrame:buttonFrame]; | 1967 for (size_t i = 0; i < layout.VisibleButtonCount(); i++) { |
2184 } | 1968 const BookmarkNode* node = parentNode->GetChild(i); |
2185 [NSAnimationContext endGrouping]; | 1969 DCHECK(node); |
2186 } | 1970 BookmarkButton* button = [self buttonForNode:node]; |
2187 } | 1971 CGFloat offset = layout.button_offsets.at(node->id()); |
2188 | 1972 [self applyXOffset:offset |
2189 // Put all visible bookmark bar buttons in their normal locations, either with | 1973 toButton:button |
2190 // or without animation according to the |animate| flag. | 1974 animated:animated && innerContentAnimationsEnabled_]; |
2191 // This is generally useful, so is called from various places internally. | 1975 [buttons_ addObject:button]; |
2192 - (void)resetAllButtonPositionsWithAnimation:(BOOL)animate { | 1976 [button setHidden:NO]; |
2193 | 1977 } |
2194 // Position the apps bookmark if needed. | 1978 for (auto& item : nodeIdToButtonMap_) { |
2195 CGFloat left = bookmarks::kBookmarkLeftMargin; | 1979 if ([item.second isHidden]) { |
2196 if (![appsPageShortcutButton_ isHidden]) { | 1980 if ([unusedButtonPool_ count] < kMaxReusePoolSize) { |
2197 int xOffset = bookmarks::kBookmarkLeftMargin - | 1981 [unusedButtonPool_ addObject:item.second.get()]; |
2198 bookmarks::kBookmarkHorizontalPadding; | 1982 } else { |
2199 NSRect frame = | 1983 [item.second setDelegate:nil]; |
2200 [self frameForBookmarkButtonFromCell:[appsPageShortcutButton_ cell] | 1984 [item.second removeFromSuperview]; |
2201 xOffset:&xOffset]; | 1985 } |
2202 [appsPageShortcutButton_ setFrame:frame]; | 1986 |
2203 left = xOffset + bookmarks::kBookmarkHorizontalPadding; | 1987 nodeIdToButtonMap_.erase(item.first); |
2204 } | 1988 } |
2205 | 1989 } |
2206 // Position the managed bookmarks folder if needed. | 1990 const ui::ThemeProvider* themeProvider = [[[self view] window] themeProvider]; |
2207 if (![managedBookmarksButton_ isHidden]) { | 1991 [self updateTheme:themeProvider]; |
2208 int xOffset = left; | 1992 } |
2209 NSRect frame = | 1993 |
2210 [self frameForBookmarkButtonFromCell:[managedBookmarksButton_ cell] | 1994 - (void)applyXOffset:(CGFloat)offset |
2211 xOffset:&xOffset]; | 1995 toButton:(BookmarkButton*)button |
2212 [managedBookmarksButton_ setFrame:frame]; | 1996 animated:(BOOL)animated { |
2213 left = xOffset + bookmarks::kBookmarkHorizontalPadding; | 1997 CGRect frame = [button frame]; |
2214 } | 1998 if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) { |
2215 | 1999 frame.origin.x = NSWidth([buttonView_ frame]) - offset - NSWidth(frame); |
2216 // Position the supervised bookmarks folder if needed. | 2000 } else { |
2217 if (![supervisedBookmarksButton_ isHidden]) { | 2001 frame.origin.x = offset; |
2218 int xOffset = left; | 2002 } |
2219 NSRect frame = | 2003 //} |
Avi (use Gerrit)
2017/04/10 20:25:54
blank line, not comment
lgrey
2017/04/26 20:12:56
Done.
| |
2220 [self frameForBookmarkButtonFromCell:[supervisedBookmarksButton_ cell] | 2004 if (animated) { |
2221 xOffset:&xOffset]; | 2005 [[button animator] setFrame:frame]; |
2222 [supervisedBookmarksButton_ setFrame:frame]; | 2006 } else { |
2223 left = xOffset + bookmarks::kBookmarkHorizontalPadding; | 2007 [button setFrame:frame]; |
2224 } | 2008 } |
2225 | 2009 } |
2226 animate &= innerContentAnimationsEnabled_; | 2010 |
2227 | 2011 - (CGFloat)widthOfButtonForNode:(const BookmarkNode*)node { |
2228 for (NSButton* button in buttons_.get()) { | 2012 // TODO(lgrey): Can we get this information without an actual image? |
2229 // Hidden buttons get no space. | 2013 NSImage* image = [self faviconForNode:node forADarkTheme:NO]; |
2230 if ([button isHidden]) | 2014 CGFloat width = [BookmarkButtonCell cellWidthForNode:node image:image]; |
2231 continue; | 2015 return std::min(width, bookmarks::kDefaultBookmarkWidth); |
2232 NSRect buttonFrame = [button frame]; | |
2233 buttonFrame.origin.x = left; | |
2234 left += buttonFrame.size.width + bookmarks::kBookmarkHorizontalPadding; | |
2235 if (animate) | |
2236 [[button animator] setFrame:buttonFrame]; | |
2237 else | |
2238 [button setFrame:buttonFrame]; | |
2239 } | |
2240 } | 2016 } |
2241 | 2017 |
2242 // Clear insertion flag, remove insertion space and put all visible bookmark | 2018 // Clear insertion flag, remove insertion space and put all visible bookmark |
2243 // bar buttons in their normal locations. | 2019 // bar buttons in their normal locations. |
2244 // Gets called only by our view. | 2020 // Gets called only by our view. |
2021 // TODO(lgrey): Is there a sane way to dedupe this with |setDropInsertionPos:|? | |
2245 - (void)clearDropInsertionPos { | 2022 - (void)clearDropInsertionPos { |
2246 if (hasInsertionPos_) { | 2023 if (!hasInsertionPos_) { |
2247 hasInsertionPos_ = NO; | 2024 return; |
2248 [self resetAllButtonPositionsWithAnimation:YES]; | 2025 } |
2249 } | 2026 hasInsertionPos_ = NO; |
2027 BookmarkButton* draggedButton = [BookmarkButton draggedButton]; | |
2028 if (!draggedButton) { | |
2029 [self rebuildLayout:YES]; | |
2030 return; | |
2031 } | |
2032 int64_t draggedButtonNodeId = [draggedButton bookmarkNode]->id(); | |
2033 if (layout_.button_offsets.find(draggedButtonNodeId) == | |
2034 layout_.button_offsets.end()) { | |
2035 [self rebuildLayout:YES]; | |
2036 return; | |
2037 } | |
2038 // The dragged button came from the bar, but is being dragged outside | |
2039 // of it now, so the rest of the buttons should be laid out as if it | |
2040 // were removed. | |
2041 CGFloat draggedButtonOffset = layout_.button_offsets[draggedButtonNodeId]; | |
2042 CGFloat spaceForDraggedButton = | |
2043 NSWidth([draggedButton frame]) + bookmarks::kBookmarkHorizontalPadding; | |
2044 [NSAnimationContext beginGrouping]; | |
2045 [[NSAnimationContext currentContext] | |
2046 setDuration:kDragAndDropAnimationDuration]; | |
2047 | |
2048 for (BookmarkButton* button in buttons_.get()) { | |
2049 int64_t nodeId = [button bookmarkNode]->id(); | |
2050 CGFloat offset = layout_.button_offsets[nodeId]; | |
2051 if (nodeId == draggedButtonNodeId) | |
2052 continue; | |
2053 if (offset > draggedButtonOffset) { | |
2054 offset -= spaceForDraggedButton; | |
2055 [self applyXOffset:offset | |
2056 toButton:button | |
2057 animated:innerContentAnimationsEnabled_]; | |
2058 } | |
2059 } | |
2060 [NSAnimationContext endGrouping]; | |
2250 } | 2061 } |
2251 | 2062 |
2252 #pragma mark Bridge Notification Handlers | 2063 #pragma mark Bridge Notification Handlers |
2253 | 2064 |
2254 // TODO(jrg): for now this is brute force. | |
2255 - (void)loaded:(BookmarkModel*)model { | 2065 - (void)loaded:(BookmarkModel*)model { |
2256 DCHECK(model == bookmarkModel_); | 2066 DCHECK(model == bookmarkModel_); |
2257 if (!model->loaded()) | 2067 if (!model->loaded()) |
2258 return; | 2068 return; |
2069 // Make sure there are no stale pointers in the pasteboard. This | |
2070 // can be important if a bookmark is deleted (via bookmark sync) | |
2071 // while in the middle of a drag. The "drag completed" code | |
Avi (use Gerrit)
2017/04/10 20:25:54
Wow. That sounds like a hell of a story.
Elly Fong-Jones
2017/04/26 13:36:02
yeah... is there a crbug for that?
lgrey
2017/04/26 20:12:56
Agree :D
Blame on this comment goes back to
https
| |
2072 // (e.g. [BookmarkBarView performDragOperationForBookmarkButton:]) is | |
2073 // careful enough to bail if there is no data found at "drop" time. | |
2074 [[NSPasteboard pasteboardWithName:NSDragPboard] clearContents]; | |
2075 | |
2076 if (!didCreateExtraButtons_) { | |
2077 [self createExtraButtons]; | |
2078 } | |
2259 | 2079 |
2260 // If this is a rebuild request while we have a folder open, close it. | 2080 // If this is a rebuild request while we have a folder open, close it. |
2261 // TODO(mrossetti): Eliminate the need for this because it causes the folder | |
2262 // menu to disappear after a cut/copy/paste/delete change. | |
2263 // See: http://crbug.com/36614 | |
2264 if (folderController_) | 2081 if (folderController_) |
2265 [self closeAllBookmarkFolders]; | 2082 [self closeAllBookmarkFolders]; |
2266 | 2083 [self rebuildLayout:NO]; |
2267 // Brute force nuke and build. | 2084 } |
2268 savedFrameWidth_ = NSWidth([[self view] frame]); | |
2269 const BookmarkNode* node = model->bookmark_bar_node(); | |
2270 [self clearBookmarkBar]; | |
2271 [self createAppsPageShortcutButton]; | |
2272 [self createManagedBookmarksButton]; | |
2273 [self createSupervisedBookmarksButton]; | |
2274 [self addNodesToButtonList:node]; | |
2275 [self createOtherBookmarksButton]; | |
2276 [self updateTheme:[[[self view] window] themeProvider]]; | |
2277 [self positionRightSideButtons]; | |
2278 [self addButtonsToView]; | |
2279 [self configureOffTheSideButtonContentsAndVisibility]; | |
2280 [self reconfigureBookmarkBar]; | |
2281 } | |
2282 | |
2283 - (void)nodeAdded:(BookmarkModel*)model | 2085 - (void)nodeAdded:(BookmarkModel*)model |
2284 parent:(const BookmarkNode*)newParent index:(int)newIndex { | 2086 parent:(const BookmarkNode*)newParent index:(int)newIndex { |
2285 // If a context menu is open, close it. | 2087 // If a context menu is open, close it. |
2286 [self cancelMenuTracking]; | 2088 [self cancelMenuTracking]; |
2287 | 2089 |
2288 const BookmarkNode* newNode = newParent->GetChild(newIndex); | 2090 const BookmarkNode* newNode = newParent->GetChild(newIndex); |
2289 id<BookmarkButtonControllerProtocol> newController = | 2091 id<BookmarkButtonControllerProtocol> newController = |
2290 [self controllerForNode:newParent]; | 2092 [self controllerForNode:newParent]; |
2291 [newController addButtonForNode:newNode atIndex:newIndex]; | 2093 [newController addButtonForNode:newNode atIndex:newIndex]; |
2292 // If we go from 0 --> 1 bookmarks we may need to hide the | 2094 [self rebuildLayout:NO]; |
2293 // "bookmarks go here" text container. | |
2294 [self showOrHideNoItemContainerForNode:model->bookmark_bar_node()]; | |
2295 // Cope with chevron or "Other Bookmarks" buttons possibly changing state. | |
2296 [self reconfigureBookmarkBar]; | |
2297 } | 2095 } |
2298 | 2096 |
2299 // TODO(jrg): for now this is brute force. | 2097 // TODO(jrg): for now this is brute force. |
2300 - (void)nodeChanged:(BookmarkModel*)model | 2098 - (void)nodeChanged:(BookmarkModel*)model |
2301 node:(const BookmarkNode*)node { | 2099 node:(const BookmarkNode*)node { |
2302 [self loaded:model]; | 2100 [self loaded:model]; |
2303 } | 2101 } |
2304 | 2102 |
2305 - (void)nodeMoved:(BookmarkModel*)model | 2103 - (void)nodeMoved:(BookmarkModel*)model |
2306 oldParent:(const BookmarkNode*)oldParent oldIndex:(int)oldIndex | 2104 oldParent:(const BookmarkNode*)oldParent oldIndex:(int)oldIndex |
2307 newParent:(const BookmarkNode*)newParent newIndex:(int)newIndex { | 2105 newParent:(const BookmarkNode*)newParent newIndex:(int)newIndex { |
2308 const BookmarkNode* movedNode = newParent->GetChild(newIndex); | 2106 const BookmarkNode* movedNode = newParent->GetChild(newIndex); |
2309 id<BookmarkButtonControllerProtocol> oldController = | 2107 id<BookmarkButtonControllerProtocol> oldController = |
2310 [self controllerForNode:oldParent]; | 2108 [self controllerForNode:oldParent]; |
2311 id<BookmarkButtonControllerProtocol> newController = | 2109 id<BookmarkButtonControllerProtocol> newController = |
2312 [self controllerForNode:newParent]; | 2110 [self controllerForNode:newParent]; |
2313 if (newController == oldController) { | 2111 if (newController == oldController) { |
2314 [oldController moveButtonFromIndex:oldIndex toIndex:newIndex]; | 2112 [oldController moveButtonFromIndex:oldIndex toIndex:newIndex]; |
2315 } else { | 2113 } else { |
2316 [oldController removeButton:oldIndex animate:NO]; | 2114 [oldController removeButton:oldIndex animate:NO]; |
2317 [newController addButtonForNode:movedNode atIndex:newIndex]; | 2115 [newController addButtonForNode:movedNode atIndex:newIndex]; |
2318 } | 2116 } |
2319 // If the bar is one of the parents we may need to update the visibility | 2117 [self rebuildLayout:NO]; |
2320 // of the "bookmarks go here" presentation. | |
2321 [self showOrHideNoItemContainerForNode:model->bookmark_bar_node()]; | |
2322 // Cope with chevron or "Other Bookmarks" buttons possibly changing state. | |
2323 [self reconfigureBookmarkBar]; | |
2324 } | 2118 } |
2325 | 2119 |
2326 - (void)nodeRemoved:(BookmarkModel*)model | 2120 - (void)nodeRemoved:(BookmarkModel*)model |
2327 parent:(const BookmarkNode*)oldParent index:(int)index { | 2121 parent:(const BookmarkNode*)oldParent index:(int)index { |
2328 // If a context menu is open, close it. | 2122 // If a context menu is open, close it. |
2329 [self cancelMenuTracking]; | 2123 [self cancelMenuTracking]; |
2330 | 2124 |
2331 // Locate the parent node. The parent may not be showing, in which case | 2125 // Locate the parent node. The parent may not be showing, in which case |
2332 // we do nothing. | 2126 // we do nothing. |
2333 id<BookmarkButtonControllerProtocol> parentController = | 2127 id<BookmarkButtonControllerProtocol> parentController = |
2334 [self controllerForNode:oldParent]; | 2128 [self controllerForNode:oldParent]; |
2335 [parentController removeButton:index animate:YES]; | 2129 [parentController removeButton:index animate:YES]; |
2336 // If we go from 1 --> 0 bookmarks we may need to show the | 2130 [self rebuildLayout:NO]; |
2337 // "bookmarks go here" text container. | |
2338 [self showOrHideNoItemContainerForNode:model->bookmark_bar_node()]; | |
2339 // If we deleted the only item on the "off the side" menu we no | |
2340 // longer need to show it. | |
2341 [self reconfigureBookmarkBar]; | |
2342 } | 2131 } |
2343 | 2132 |
2344 // TODO(jrg): linear searching is bad. | |
2345 // Need a BookmarkNode-->NSCell mapping. | |
2346 // | |
2347 // TODO(jrg): if the bookmark bar is open on launch, we see the | 2133 // TODO(jrg): if the bookmark bar is open on launch, we see the |
2348 // buttons all placed, then "scooted over" as the favicons load. If | 2134 // buttons all placed, then "scooted over" as the favicons load. If |
2349 // this looks bad I may need to change widthForBookmarkButtonCell to | 2135 // this looks bad I may need to change widthForBookmarkButtonCell to |
2350 // add space for an image even if not there on the assumption that | 2136 // add space for an image even if not there on the assumption that |
2351 // favicons will eventually load. | 2137 // favicons will eventually load. |
2352 - (void)nodeFaviconLoaded:(BookmarkModel*)model | 2138 - (void)nodeFaviconLoaded:(BookmarkModel*)model |
2353 node:(const BookmarkNode*)node { | 2139 node:(const BookmarkNode*)node { |
2354 for (BookmarkButton* button in buttons_.get()) { | 2140 auto buttonIt = nodeIdToButtonMap_.find(node->id()); |
2355 const BookmarkNode* cellnode = [button bookmarkNode]; | 2141 if (buttonIt != nodeIdToButtonMap_.end()) { |
2356 if (cellnode == node) { | 2142 BookmarkButton* button = (*buttonIt).second; |
2357 BOOL darkTheme = [[[self view] window] hasDarkTheme]; | 2143 BOOL darkTheme = [[[self view] window] hasDarkTheme]; |
2358 NSImage* theImage = [self faviconForNode:node forADarkTheme:darkTheme]; | 2144 NSImage* theImage = [self faviconForNode:node forADarkTheme:darkTheme]; |
2359 [[button cell] setBookmarkCellText:[button title] | 2145 [[button cell] setBookmarkCellText:[button title] image:theImage]; |
2360 image:theImage]; | |
2361 // Adding an image means we might need more room for the | |
2362 // bookmark. Test for it by growing the button (if needed) | |
2363 // and shifting everything else over. | |
2364 [self checkForBookmarkButtonGrowth:button]; | |
2365 return; | |
2366 } | |
2367 } | 2146 } |
2368 | 2147 [self rebuildLayout:NO]; |
2369 if (folderController_) | 2148 if (folderController_) |
2370 [folderController_ faviconLoadedForNode:node]; | 2149 [folderController_ faviconLoadedForNode:node]; |
2371 } | 2150 } |
2372 | 2151 |
2373 // TODO(jrg): for now this is brute force. | 2152 // TODO(jrg): for now this is brute force. |
2374 - (void)nodeChildrenReordered:(BookmarkModel*)model | 2153 - (void)nodeChildrenReordered:(BookmarkModel*)model |
2375 node:(const BookmarkNode*)node { | 2154 node:(const BookmarkNode*)node { |
2376 [self loaded:model]; | 2155 [self loaded:model]; |
2377 } | 2156 } |
2378 | 2157 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2502 - (void)didDragBookmarkToTrash:(BookmarkButton*)button { | 2281 - (void)didDragBookmarkToTrash:(BookmarkButton*)button { |
2503 if ([self canDragBookmarkButtonToTrash:button]) { | 2282 if ([self canDragBookmarkButtonToTrash:button]) { |
2504 const BookmarkNode* node = [button bookmarkNode]; | 2283 const BookmarkNode* node = [button bookmarkNode]; |
2505 if (node) | 2284 if (node) |
2506 bookmarkModel_->Remove(node); | 2285 bookmarkModel_->Remove(node); |
2507 } | 2286 } |
2508 } | 2287 } |
2509 | 2288 |
2510 - (void)bookmarkDragDidEnd:(BookmarkButton*)button | 2289 - (void)bookmarkDragDidEnd:(BookmarkButton*)button |
2511 operation:(NSDragOperation)operation { | 2290 operation:(NSDragOperation)operation { |
2512 [button setHidden:NO]; | 2291 [self rebuildLayout:YES]; |
2513 [self resetAllButtonPositionsWithAnimation:YES]; | |
2514 } | 2292 } |
2515 | 2293 |
2516 | 2294 |
2517 #pragma mark BookmarkButtonControllerProtocol | 2295 #pragma mark BookmarkButtonControllerProtocol |
2518 | 2296 |
2519 // Close all bookmark folders. "Folder" here is the fake menu for | 2297 // Close all bookmark folders. "Folder" here is the fake menu for |
2520 // bookmark folders, not a button context menu. | 2298 // bookmark folders, not a button context menu. |
2521 - (void)closeAllBookmarkFolders { | 2299 - (void)closeAllBookmarkFolders { |
2522 [self watchForExitEvent:NO]; | 2300 [self watchForExitEvent:NO]; |
2523 | 2301 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2663 // Return YES if we should show the drop indicator, else NO. | 2441 // Return YES if we should show the drop indicator, else NO. |
2664 - (BOOL)shouldShowIndicatorShownForPoint:(NSPoint)point { | 2442 - (BOOL)shouldShowIndicatorShownForPoint:(NSPoint)point { |
2665 return ![self buttonForDroppingOnAtPoint:point]; | 2443 return ![self buttonForDroppingOnAtPoint:point]; |
2666 } | 2444 } |
2667 | 2445 |
2668 // Return the x position for a drop indicator. | 2446 // Return the x position for a drop indicator. |
2669 - (CGFloat)indicatorPosForDragToPoint:(NSPoint)point { | 2447 - (CGFloat)indicatorPosForDragToPoint:(NSPoint)point { |
2670 CGFloat x = 0; | 2448 CGFloat x = 0; |
2671 CGFloat halfHorizontalPadding = 0.5 * bookmarks::kBookmarkHorizontalPadding; | 2449 CGFloat halfHorizontalPadding = 0.5 * bookmarks::kBookmarkHorizontalPadding; |
2672 int destIndex = [self indexForDragToPoint:point]; | 2450 int destIndex = [self indexForDragToPoint:point]; |
2673 int numButtons = displayedButtonCount_; | 2451 int numButtons = layout_.VisibleButtonCount(); |
2674 | 2452 |
2675 CGFloat leftmostX; | 2453 CGFloat leadingOffset; |
2676 if (![supervisedBookmarksButton_ isHidden]) { | 2454 if (layout_.IsSupervisedBookmarksButtonVisible()) { |
2677 leftmostX = | 2455 leadingOffset = |
2678 NSMaxX([supervisedBookmarksButton_ frame]) + halfHorizontalPadding; | 2456 layout_.supervised_bookmarks_button_offset + halfHorizontalPadding; |
2679 } else if (![managedBookmarksButton_ isHidden]) { | 2457 } else if (layout_.IsManagedBookmarksButtonVisible()) { |
2680 leftmostX = NSMaxX([managedBookmarksButton_ frame]) + halfHorizontalPadding; | 2458 leadingOffset = |
2681 } else if (![appsPageShortcutButton_ isHidden]) { | 2459 layout_.managed_bookmarks_button_offset + halfHorizontalPadding; |
2682 leftmostX = NSMaxX([appsPageShortcutButton_ frame]) + halfHorizontalPadding; | 2460 } else if (layout_.IsAppsButtonVisible()) { |
2461 leadingOffset = layout_.apps_button_offset + halfHorizontalPadding; | |
2683 } else { | 2462 } else { |
2684 leftmostX = bookmarks::kBookmarkLeftMargin - halfHorizontalPadding; | 2463 leadingOffset = bookmarks::kBookmarkLeftMargin - halfHorizontalPadding; |
2685 } | 2464 } |
2686 | 2465 |
2687 // If it's a drop strictly between existing buttons ... | 2466 // If it's a drop strictly between existing buttons ... |
2688 if (destIndex == 0) { | 2467 if (destIndex == 0) { |
2689 x = leftmostX; | 2468 x = leadingOffset; |
2690 } else if (destIndex > 0 && destIndex < numButtons) { | 2469 } else if (destIndex > 0 && destIndex < numButtons) { |
2691 // ... put the indicator right between the buttons. | 2470 // ... put the indicator right between the buttons. |
2692 BookmarkButton* button = | 2471 int64_t nodeId = |
2693 [buttons_ objectAtIndex:static_cast<NSUInteger>(destIndex-1)]; | 2472 bookmarkModel_->bookmark_bar_node()->GetChild(destIndex)->id(); |
2694 DCHECK(button); | 2473 x = layout_.button_offsets[nodeId] - halfHorizontalPadding; |
2695 NSRect buttonFrame = [button frame]; | |
2696 x = NSMaxX(buttonFrame) + halfHorizontalPadding; | |
2697 | |
2698 // If it's a drop at the end (past the last button, if there are any) ... | 2474 // If it's a drop at the end (past the last button, if there are any) ... |
2699 } else if (destIndex == numButtons) { | 2475 } else if (destIndex == numButtons) { |
2700 // and if it's past the last button ... | 2476 // and if it's past the last button ... |
2701 if (numButtons > 0) { | 2477 if (numButtons > 0) { |
2702 // ... find the last button, and put the indicator to its right. | 2478 // ... find the last button, and put the indicator after it. |
2703 BookmarkButton* button = | 2479 const BookmarkNode* node = |
2704 [buttons_ objectAtIndex:static_cast<NSUInteger>(destIndex - 1)]; | 2480 bookmarkModel_->bookmark_bar_node()->GetChild(destIndex - 1); |
2705 DCHECK(button); | 2481 int64_t nodeId = node->id(); |
2706 x = NSMaxX([button frame]) + halfHorizontalPadding; | 2482 x = layout_.button_offsets[nodeId] + [self widthOfButtonForNode:node] + |
2707 | 2483 halfHorizontalPadding; |
2708 // Otherwise, put it right at the beginning. | 2484 // Otherwise, put it right at the beginning. |
2709 } else { | 2485 } else { |
2710 x = leftmostX; | 2486 x = leadingOffset; |
2711 } | 2487 } |
2712 } else { | 2488 } else { |
2713 NOTREACHED(); | 2489 NOTREACHED(); |
2714 } | 2490 } |
2715 | 2491 |
2716 return x; | 2492 return cocoa_l10n_util::ShouldDoExperimentalRTLLayout() |
2493 ? NSWidth([buttonView_ frame]) - x | |
2494 : x; | |
2717 } | 2495 } |
2718 | 2496 |
2719 - (void)childFolderWillShow:(id<BookmarkButtonControllerProtocol>)child { | 2497 - (void)childFolderWillShow:(id<BookmarkButtonControllerProtocol>)child { |
2720 // If the bookmarkbar is not in detached mode, lock bar visibility, forcing | 2498 // If the bookmarkbar is not in detached mode, lock bar visibility, forcing |
2721 // the overlay to stay open when in fullscreen mode. | 2499 // the overlay to stay open when in fullscreen mode. |
2722 if (![self isInState:BookmarkBar::DETACHED] && | 2500 if (![self isInState:BookmarkBar::DETACHED] && |
2723 ![self isAnimatingToState:BookmarkBar::DETACHED]) { | 2501 ![self isAnimatingToState:BookmarkBar::DETACHED]) { |
2724 BrowserWindowController* browserController = | 2502 BrowserWindowController* browserController = |
2725 [BrowserWindowController browserWindowControllerForView:[self view]]; | 2503 [BrowserWindowController browserWindowControllerForView:[self view]]; |
2726 [browserController lockToolbarVisibilityForOwner:child withAnimation:NO]; | 2504 [browserController lockToolbarVisibilityForOwner:child withAnimation:NO]; |
2727 } | 2505 } |
2728 } | 2506 } |
2729 | 2507 |
2730 - (void)childFolderWillClose:(id<BookmarkButtonControllerProtocol>)child { | 2508 - (void)childFolderWillClose:(id<BookmarkButtonControllerProtocol>)child { |
2731 // Release bar visibility, allowing the overlay to close if in fullscreen | 2509 // Release bar visibility, allowing the overlay to close if in fullscreen |
2732 // mode. | 2510 // mode. |
2733 BrowserWindowController* browserController = | 2511 BrowserWindowController* browserController = |
2734 [BrowserWindowController browserWindowControllerForView:[self view]]; | 2512 [BrowserWindowController browserWindowControllerForView:[self view]]; |
2735 [browserController releaseToolbarVisibilityForOwner:child withAnimation:NO]; | 2513 [browserController releaseToolbarVisibilityForOwner:child withAnimation:NO]; |
2736 } | 2514 } |
2737 | 2515 |
2738 // Add a new folder controller as triggered by the given folder button. | 2516 // Add a new folder controller as triggered by the given folder button. |
2739 - (void)addNewFolderControllerWithParentButton:(BookmarkButton*)parentButton { | 2517 - (void)addNewFolderControllerWithParentButton:(BookmarkButton*)parentButton { |
2740 | |
2741 // If doing a close/open, make sure the fullscreen chrome doesn't | 2518 // If doing a close/open, make sure the fullscreen chrome doesn't |
2742 // have a chance to begin animating away in the middle of things. | 2519 // have a chance to begin animating away in the middle of things. |
2743 BrowserWindowController* browserController = | 2520 BrowserWindowController* browserController = |
2744 [BrowserWindowController browserWindowControllerForView:[self view]]; | 2521 [BrowserWindowController browserWindowControllerForView:[self view]]; |
2745 // Confirm we're not re-locking with ourself as an owner before locking. | 2522 // Confirm we're not re-locking with ourself as an owner before locking. |
2746 DCHECK([browserController isToolbarVisibilityLockedForOwner:self] == NO); | 2523 DCHECK([browserController isToolbarVisibilityLockedForOwner:self] == NO); |
2747 [browserController lockToolbarVisibilityForOwner:self withAnimation:NO]; | 2524 [browserController lockToolbarVisibilityForOwner:self withAnimation:NO]; |
2748 | 2525 |
2749 if (folderController_) | 2526 if (folderController_) |
2750 [self closeAllBookmarkFolders]; | 2527 [self closeAllBookmarkFolders]; |
(...skipping 15 matching lines...) Expand all Loading... | |
2766 [browserController releaseToolbarVisibilityForOwner:self withAnimation:NO]; | 2543 [browserController releaseToolbarVisibilityForOwner:self withAnimation:NO]; |
2767 } | 2544 } |
2768 | 2545 |
2769 - (void)openAll:(const BookmarkNode*)node | 2546 - (void)openAll:(const BookmarkNode*)node |
2770 disposition:(WindowOpenDisposition)disposition { | 2547 disposition:(WindowOpenDisposition)disposition { |
2771 [self closeFolderAndStopTrackingMenus]; | 2548 [self closeFolderAndStopTrackingMenus]; |
2772 chrome::OpenAll([[self view] window], browser_, node, disposition, | 2549 chrome::OpenAll([[self view] window], browser_, node, disposition, |
2773 browser_->profile()); | 2550 browser_->profile()); |
2774 } | 2551 } |
2775 | 2552 |
2776 - (void)addButtonForNode:(const BookmarkNode*)node | |
2777 atIndex:(NSInteger)buttonIndex { | |
2778 int newOffset = | |
2779 bookmarks::kBookmarkLeftMargin - bookmarks::kBookmarkHorizontalPadding; | |
2780 if (buttonIndex == -1) | |
2781 buttonIndex = [buttons_ count]; // New button goes at the end. | |
2782 if (buttonIndex <= (NSInteger)[buttons_ count]) { | |
2783 if (buttonIndex) { | |
2784 BookmarkButton* targetButton = [buttons_ objectAtIndex:buttonIndex - 1]; | |
2785 NSRect targetFrame = [targetButton frame]; | |
2786 newOffset = targetFrame.origin.x + NSWidth(targetFrame) + | |
2787 bookmarks::kBookmarkHorizontalPadding; | |
2788 } | |
2789 BookmarkButton* newButton = [self buttonForNode:node xOffset:&newOffset]; | |
2790 ++displayedButtonCount_; | |
2791 [buttons_ insertObject:newButton atIndex:buttonIndex]; | |
2792 [buttonView_ addSubview:newButton]; | |
2793 [self resetAllButtonPositionsWithAnimation:NO]; | |
2794 // See if any buttons need to be pushed off to or brought in from the side. | |
2795 [self reconfigureBookmarkBar]; | |
2796 } else { | |
2797 // A button from somewhere else (not the bar) is being moved to the | |
2798 // off-the-side so insure it gets redrawn if its showing. | |
2799 [self reconfigureBookmarkBar]; | |
2800 [folderController_ reconfigureMenu]; | |
2801 } | |
2802 } | |
2803 | |
2804 // TODO(mrossetti): Duplicate code with BookmarkBarFolderController. | 2553 // TODO(mrossetti): Duplicate code with BookmarkBarFolderController. |
2805 // http://crbug.com/35966 | 2554 // http://crbug.com/35966 |
2806 - (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point { | 2555 - (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point { |
2807 DCHECK([urls count] == [titles count]); | 2556 DCHECK([urls count] == [titles count]); |
2808 BOOL nodesWereAdded = NO; | 2557 BOOL nodesWereAdded = NO; |
2809 // Figure out where these new bookmarks nodes are to be added. | 2558 // Figure out where these new bookmarks nodes are to be added. |
2810 BookmarkButton* button = [self buttonForDroppingOnAtPoint:point]; | 2559 BookmarkButton* button = [self buttonForDroppingOnAtPoint:point]; |
2811 const BookmarkNode* destParent = NULL; | 2560 const BookmarkNode* destParent = NULL; |
2812 int destIndex = 0; | 2561 int destIndex = 0; |
2813 if ([button isFolder]) { | 2562 if ([button isFolder]) { |
(...skipping 27 matching lines...) Expand all Loading... | |
2841 [titles objectAtIndex:i]), | 2590 [titles objectAtIndex:i]), |
2842 gurl); | 2591 gurl); |
2843 nodesWereAdded = YES; | 2592 nodesWereAdded = YES; |
2844 } | 2593 } |
2845 } | 2594 } |
2846 } | 2595 } |
2847 return nodesWereAdded; | 2596 return nodesWereAdded; |
2848 } | 2597 } |
2849 | 2598 |
2850 - (void)moveButtonFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex { | 2599 - (void)moveButtonFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex { |
2851 if (fromIndex != toIndex) { | 2600 int buttonCount = layout_.VisibleButtonCount(); |
2852 NSInteger buttonCount = (NSInteger)[buttons_ count]; | 2601 BOOL isMoveWithinOffTheSideMenu = |
2853 if (toIndex == -1) | 2602 (toIndex >= buttonCount) && (fromIndex >= buttonCount); |
2854 toIndex = buttonCount; | 2603 if (isMoveWithinOffTheSideMenu) { |
2855 // See if we have a simple move within the bar, which will be the case if | 2604 fromIndex -= buttonCount; |
2856 // both button indexes are in the visible space. | 2605 toIndex -= buttonCount; |
2857 if (fromIndex < buttonCount && toIndex < buttonCount) { | 2606 [folderController_ moveButtonFromIndex:fromIndex toIndex:toIndex]; |
2858 BookmarkButton* movedButton = [buttons_ objectAtIndex:fromIndex]; | 2607 } else { |
2859 [buttons_ removeObjectAtIndex:fromIndex]; | 2608 [self rebuildLayout:NO]; |
2860 [buttons_ insertObject:movedButton atIndex:toIndex]; | |
2861 [movedButton setHidden:NO]; | |
2862 [self resetAllButtonPositionsWithAnimation:NO]; | |
2863 } else if (fromIndex < buttonCount) { | |
2864 // A button is being removed from the bar and added to off-the-side. | |
2865 // By now the node has already been inserted into the model so the | |
2866 // button to be added is represented by |toIndex|. Things get | |
2867 // complicated because the off-the-side is showing and must be redrawn | |
2868 // while possibly re-laying out the bookmark bar. | |
2869 [self removeButton:fromIndex animate:NO]; | |
2870 [self reconfigureBookmarkBar]; | |
2871 [folderController_ reconfigureMenu]; | |
2872 } else if (toIndex < buttonCount) { | |
2873 // A button is being added to the bar and removed from off-the-side. | |
2874 // By now the node has already been inserted into the model so the | |
2875 // button to be added is represented by |toIndex|. | |
2876 const BookmarkNode* node = bookmarkModel_->bookmark_bar_node(); | |
2877 const BookmarkNode* movedNode = node->GetChild(toIndex); | |
2878 DCHECK(movedNode); | |
2879 [self addButtonForNode:movedNode atIndex:toIndex]; | |
2880 [self reconfigureBookmarkBar]; | |
2881 } else { | |
2882 // A button is being moved within the off-the-side. | |
2883 fromIndex -= buttonCount; | |
2884 toIndex -= buttonCount; | |
2885 [folderController_ moveButtonFromIndex:fromIndex toIndex:toIndex]; | |
2886 } | |
2887 } | 2609 } |
2888 } | 2610 } |
2889 | 2611 |
2890 - (void)removeButton:(NSInteger)buttonIndex animate:(BOOL)animate { | 2612 - (void)removeButton:(NSInteger)buttonIndex animate:(BOOL)animate { |
2891 if (buttonIndex < (NSInteger)[buttons_ count]) { | 2613 if ((size_t)buttonIndex < layout_.VisibleButtonCount()) { |
2892 // The button being removed is showing in the bar. | 2614 // The button being removed is showing in the bar. |
2893 BookmarkButton* oldButton = [buttons_ objectAtIndex:buttonIndex]; | 2615 BookmarkButton* oldButton = buttons_[buttonIndex]; |
2894 if (oldButton == [folderController_ parentButton]) { | 2616 if (oldButton == [folderController_ parentButton]) { |
2895 // If we are deleting a button whose folder is currently open, close it! | 2617 // If we are deleting a button whose folder is currently open, close it! |
2896 [self closeAllBookmarkFolders]; | 2618 [self closeAllBookmarkFolders]; |
2897 } | 2619 } |
2898 if (animate && innerContentAnimationsEnabled_ && [self isVisible] && | 2620 if (animate && innerContentAnimationsEnabled_ && [self isVisible] && |
2899 [[self browserWindow] isMainWindow]) { | 2621 [[self browserWindow] isMainWindow]) { |
2900 NSPoint poofPoint = [oldButton screenLocationForRemoveAnimation]; | 2622 NSPoint poofPoint = [oldButton screenLocationForRemoveAnimation]; |
2901 NSShowAnimationEffect(NSAnimationEffectDisappearingItemDefault, poofPoint, | 2623 NSShowAnimationEffect(NSAnimationEffectDisappearingItemDefault, poofPoint, |
2902 NSZeroSize, nil, nil, nil); | 2624 NSZeroSize, nil, nil, nil); |
2903 } | 2625 } |
2904 [oldButton setDelegate:nil]; | 2626 [self rebuildLayout:YES]; |
2905 [oldButton removeFromSuperview]; | |
2906 [buttons_ removeObjectAtIndex:buttonIndex]; | |
2907 --displayedButtonCount_; | |
2908 [self resetAllButtonPositionsWithAnimation:YES]; | |
2909 [self reconfigureBookmarkBar]; | |
2910 } else if (folderController_ && | 2627 } else if (folderController_ && |
2911 [folderController_ parentButton] == offTheSideButton_) { | 2628 [folderController_ parentButton] == offTheSideButton_) { |
2912 // The button being removed is in the OTS (off-the-side) and the OTS | 2629 // The button being removed is in the OTS (off-the-side) and the OTS |
2913 // menu is showing so we need to remove the button. | 2630 // menu is showing so we need to remove the button. |
2914 NSInteger index = buttonIndex - displayedButtonCount_; | 2631 NSInteger index = buttonIndex - layout_.VisibleButtonCount(); |
2915 [folderController_ removeButton:index animate:animate]; | 2632 [folderController_ removeButton:index animate:animate]; |
2916 } | 2633 } |
2917 } | 2634 } |
2918 | 2635 |
2919 - (id<BookmarkButtonControllerProtocol>)controllerForNode: | 2636 - (id<BookmarkButtonControllerProtocol>)controllerForNode: |
2920 (const BookmarkNode*)node { | 2637 (const BookmarkNode*)node { |
2921 // See if it's in the bar, then if it is in the hierarchy of visible | 2638 // See if it's in the bar, then if it is in the hierarchy of visible |
2922 // folder menus. | 2639 // folder menus. |
2923 if (bookmarkModel_->bookmark_bar_node() == node) | 2640 if (bookmarkModel_->bookmark_bar_node() == node) |
2924 return self; | 2641 return self; |
2925 return [folderController_ controllerForNode:node]; | 2642 return [folderController_ controllerForNode:node]; |
2926 } | 2643 } |
2927 | 2644 |
2645 // For testing. | |
2646 - (const BookmarkBarLayout&)currentLayout { | |
2647 return layout_; | |
2648 } | |
2649 | |
2928 @end | 2650 @end |
OLD | NEW |