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