Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(439)

Side by Side Diff: chrome/browser/cocoa/bookmark_bar_folder_controller.mm

Issue 2802025: Cascading menus change growth dirction (right or left) when we hit the... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/cocoa/bookmark_bar_folder_controller.h" 5 #import "chrome/browser/cocoa/bookmark_bar_folder_controller.h"
6 #include "base/mac_util.h" 6 #include "base/mac_util.h"
7 #include "base/nsimage_cache_mac.h" 7 #include "base/nsimage_cache_mac.h"
8 #include "base/sys_string_conversions.h" 8 #include "base/sys_string_conversions.h"
9 #include "chrome/browser/bookmarks/bookmark_model.h" 9 #include "chrome/browser/bookmarks/bookmark_model.h"
10 #include "chrome/browser/bookmarks/bookmark_utils.h" 10 #include "chrome/browser/bookmarks/bookmark_utils.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 - (void)toggleButtonBorderingWhileMouseInside { 98 - (void)toggleButtonBorderingWhileMouseInside {
99 BOOL toggle = [self showsBorderOnlyWhileMouseInside]; 99 BOOL toggle = [self showsBorderOnlyWhileMouseInside];
100 [self setShowsBorderOnlyWhileMouseInside:!toggle]; 100 [self setShowsBorderOnlyWhileMouseInside:!toggle];
101 [self setShowsBorderOnlyWhileMouseInside:toggle]; 101 [self setShowsBorderOnlyWhileMouseInside:toggle];
102 } 102 }
103 103
104 @end 104 @end
105 105
106 @implementation BookmarkBarFolderController 106 @implementation BookmarkBarFolderController
107 107
108 @synthesize subFolderGrowthToRight = subFolderGrowthToRight_;
109
108 - (id)initWithParentButton:(BookmarkButton*)button 110 - (id)initWithParentButton:(BookmarkButton*)button
109 parentController:(BookmarkBarFolderController*)parentController 111 parentController:(BookmarkBarFolderController*)parentController
110 barController:(BookmarkBarController*)barController { 112 barController:(BookmarkBarController*)barController {
111 NSString* nibPath = 113 NSString* nibPath =
112 [mac_util::MainAppBundle() pathForResource:@"BookmarkBarFolderWindow" 114 [mac_util::MainAppBundle() pathForResource:@"BookmarkBarFolderWindow"
113 ofType:@"nib"]; 115 ofType:@"nib"];
114 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { 116 if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
115 parentButton_.reset([button retain]); 117 parentButton_.reset([button retain]);
116 118
117 // We want the button to remain bordered as part of the menu path. 119 // We want the button to remain bordered as part of the menu path.
118 [button forceButtonBorderToStayOnAlways:YES]; 120 [button forceButtonBorderToStayOnAlways:YES];
119 121
120 parentController_.reset([parentController retain]); 122 parentController_.reset([parentController retain]);
123 if (!parentController_)
124 [self setSubFolderGrowthToRight:YES];
125 else
126 [self setSubFolderGrowthToRight:[parentController
127 subFolderGrowthToRight]];
121 barController_ = barController; // WEAK 128 barController_ = barController; // WEAK
122 buttons_.reset([[NSMutableArray alloc] init]); 129 buttons_.reset([[NSMutableArray alloc] init]);
123 folderTarget_.reset([[BookmarkFolderTarget alloc] initWithController:self]); 130 folderTarget_.reset([[BookmarkFolderTarget alloc] initWithController:self]);
124 NSImage* image = nsimage_cache::ImageNamed(@"menu_overflow_up.pdf"); 131 NSImage* image = nsimage_cache::ImageNamed(@"menu_overflow_up.pdf");
125 DCHECK(image); 132 DCHECK(image);
126 verticalScrollArrowHeight_ = [image size].height; 133 verticalScrollArrowHeight_ = [image size].height;
127 [self configureWindow]; 134 [self configureWindow];
128 hoverState_.reset([[BookmarkBarFolderHoverState alloc] init]); 135 hoverState_.reset([[BookmarkBarFolderHoverState alloc] init]);
129 } 136 }
130 return self; 137 return self;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 263
257 // Exposed for testing. 264 // Exposed for testing.
258 - (NSView*)mainView { 265 - (NSView*)mainView {
259 return mainView_; 266 return mainView_;
260 } 267 }
261 268
262 - (id)folderTarget { 269 - (id)folderTarget {
263 return folderTarget_.get(); 270 return folderTarget_.get();
264 } 271 }
265 272
273
274 // Our parent controller is another BookmarkBarFolderController, so
275 // our window is to the right or left of it. We use a little overlap
276 // since it looks much more menu-like than with none. If we would
277 // grow off the screen, switch growth to the other direction. Growth
278 // direction sticks for folder windows which are descendents of us.
279 // If we have tried both directions and neither fits, degrade to a
280 // default.
281 - (CGFloat)childFolderWindowLeftForWidth:(int)windowWidth {
282 // We may legitimately need to try two times (growth to right and
283 // left but not in that order). Limit us to three tries in case
284 // the folder window can't fit on either side of the screen; we
285 // don't want to loop forever.
286 CGFloat x;
287 int tries = 0;
288 while (tries < 2) {
289 // Try to grow right.
290 if ([self subFolderGrowthToRight]) {
291 tries++;
292 x = NSMaxX([[parentButton_ window] frame]) -
293 bookmarks::kBookmarkMenuOverlap;
294 // If off the screen, switch direction.
295 if ((x + windowWidth + bookmarks::kBookmarkHorizontalScreenPadding) >
296 NSMaxX([[[self window] screen] frame])) {
297 [self setSubFolderGrowthToRight:NO];
298 } else {
299 return x;
300 }
301 }
302 // Try to grow left.
303 if (![self subFolderGrowthToRight]) {
304 tries++;
305 x = NSMinX([[parentButton_ window] frame]) +
306 bookmarks::kBookmarkMenuOverlap -
307 windowWidth;
308 // If off the screen, switch direction.
309 if (x < NSMinX([[[self window] screen] frame])) {
310 [self setSubFolderGrowthToRight:YES];
311 } else {
312 return x;
313 }
314 }
315 }
316 // Unhappy; do the best we can.
317 return NSMaxX([[[self window] screen] frame]) - windowWidth;
318 }
319
320
266 // Compute and return the top left point of our window (screen 321 // Compute and return the top left point of our window (screen
267 // coordinates). The top left is positioned in a manner similar to 322 // coordinates). The top left is positioned in a manner similar to
268 // cascading menus. 323 // cascading menus. Windows may grow to either the right or left of
269 - (NSPoint)windowTopLeft { 324 // their parent (if a sub-folder) so we need to know |windowWidth|.
325 - (NSPoint)windowTopLeftForWidth:(int)windowWidth {
270 NSPoint newWindowTopLeft; 326 NSPoint newWindowTopLeft;
271 if (![parentController_ isKindOfClass:[self class]]) { 327 if (![parentController_ isKindOfClass:[self class]]) {
272 // If we're not popping up from one of ourselves, we must be 328 // If we're not popping up from one of ourselves, we must be
273 // popping up from the bookmark bar itself. In this case, start 329 // popping up from the bookmark bar itself. In this case, start
274 // BELOW the parent button. Our left is the button left; our top 330 // BELOW the parent button. Our left is the button left; our top
275 // is bottom of button's parent view. 331 // is bottom of button's parent view.
276 NSPoint buttonBottomLeftInScreen = 332 NSPoint buttonBottomLeftInScreen =
277 [[parentButton_ window] 333 [[parentButton_ window]
278 convertBaseToScreen:[parentButton_ 334 convertBaseToScreen:[parentButton_
279 convertPoint:NSZeroPoint toView:nil]]; 335 convertPoint:NSZeroPoint toView:nil]];
280 NSPoint bookmarkBarBottomLeftInScreen = 336 NSPoint bookmarkBarBottomLeftInScreen =
281 [[parentButton_ window] 337 [[parentButton_ window]
282 convertBaseToScreen:[[parentButton_ superview] 338 convertBaseToScreen:[[parentButton_ superview]
283 convertPoint:NSZeroPoint toView:nil]]; 339 convertPoint:NSZeroPoint toView:nil]];
284 newWindowTopLeft = NSMakePoint(buttonBottomLeftInScreen.x, 340 newWindowTopLeft = NSMakePoint(buttonBottomLeftInScreen.x,
285 bookmarkBarBottomLeftInScreen.y); 341 bookmarkBarBottomLeftInScreen.y);
286 } else { 342 } else {
287 // Our parent controller is another BookmarkBarFolderController. 343 // Parent is a folder; grow right/left.
288 // In this case, start with a slight overlap on the RIGHT of the 344 newWindowTopLeft.x = [self childFolderWindowLeftForWidth:windowWidth];
289 // parent button, which looks much more menu-like than with none.
290 // Start to RIGHT of the button.
291 // TODO(jrg): If too far to right, pop left again.
292 // http://crbug.com/36225
293 newWindowTopLeft.x = NSMaxX([[parentButton_ window] frame]) -
294 bookmarks::kBookmarkMenuOverlap;
295 NSPoint top = NSMakePoint(0, (NSMaxY([parentButton_ frame]) + 345 NSPoint top = NSMakePoint(0, (NSMaxY([parentButton_ frame]) +
296 bookmarks::kBookmarkVerticalPadding)); 346 bookmarks::kBookmarkVerticalPadding));
297 NSPoint topOfWindow = 347 NSPoint topOfWindow =
298 [[parentButton_ window] 348 [[parentButton_ window]
299 convertBaseToScreen:[[parentButton_ superview] 349 convertBaseToScreen:[[parentButton_ superview]
300 convertPoint:top toView:nil]]; 350 convertPoint:top toView:nil]];
301 newWindowTopLeft.y = topOfWindow.y; 351 newWindowTopLeft.y = topOfWindow.y;
302 } 352 }
303 return newWindowTopLeft; 353 return newWindowTopLeft;
304 } 354 }
305 355
306 // Set our window level to the right spot so we're above the menubar, dock, etc. 356 // Set our window level to the right spot so we're above the menubar, dock, etc.
307 // Factored out so we can override/noop in a unit test. 357 // Factored out so we can override/noop in a unit test.
308 - (void)configureWindowLevel { 358 - (void)configureWindowLevel {
309 [[self window] setLevel:NSPopUpMenuWindowLevel]; 359 [[self window] setLevel:NSPopUpMenuWindowLevel];
310 } 360 }
311 361
312 - (void)adjustWindowForHeight:(int)windowHeight { 362 - (void)adjustWindowForHeight:(int)windowHeight {
313 // Adjust all button widths to be consistent, determine the best size for 363 // Adjust all button widths to be consistent, determine the best size for
314 // the window, and set the window frame. 364 // the window, and set the window frame.
315 CGFloat windowWidth = 365 CGFloat windowWidth =
316 [self adjustButtonWidths] + (2 * bookmarks::kBookmarkVerticalPadding) + 366 [self adjustButtonWidths] + (2 * bookmarks::kBookmarkVerticalPadding) +
317 bookmarks::kScrollViewContentWidthMargin; 367 bookmarks::kScrollViewContentWidthMargin;
318 NSPoint newWindowTopLeft = [self windowTopLeft]; 368 NSPoint newWindowTopLeft = [self windowTopLeftForWidth:windowWidth];
319 NSRect windowFrame = NSMakeRect(newWindowTopLeft.x, 369 NSRect windowFrame = NSMakeRect(newWindowTopLeft.x,
320 newWindowTopLeft.y - windowHeight, 370 newWindowTopLeft.y - windowHeight,
321 windowWidth, 371 windowWidth,
322 windowHeight); 372 windowHeight);
323 373
324 // Make the window fit on screen, with a distance of at least |padding| from
325 // the sides.
326 DCHECK([[self window] screen]);
327 NSRect screenFrame = [[[self window] screen] frame];
328 if (NSMaxX(windowFrame) + bookmarks::kBookmarkHorizontalScreenPadding >
329 NSMaxX(screenFrame))
330 windowFrame.origin.x -= NSMaxX(windowFrame) +
331 bookmarks::kBookmarkHorizontalScreenPadding - NSMaxX(screenFrame);
332 // No 'else' to provide preference for the left side of the menu
333 // being visible if neither one fits. Wish I had an "bool isL2R()"
334 // function right here.
335 if (NSMinX(windowFrame) - bookmarks::kBookmarkHorizontalScreenPadding <
336 NSMinX(screenFrame))
337 windowFrame.origin.x += NSMinX(screenFrame) - NSMinX(windowFrame) +
338 bookmarks::kBookmarkHorizontalScreenPadding;
339
340 // Make the scrolled content be the right size (full size). 374 // Make the scrolled content be the right size (full size).
341 NSRect mainViewFrame = NSMakeRect(0, 0, 375 NSRect mainViewFrame = NSMakeRect(0, 0,
342 NSWidth(windowFrame) - 376 NSWidth(windowFrame) -
343 bookmarks::kScrollViewContentWidthMargin, 377 bookmarks::kScrollViewContentWidthMargin,
344 NSHeight(windowFrame)); 378 NSHeight(windowFrame));
345 [mainView_ setFrame:mainViewFrame]; 379 [mainView_ setFrame:mainViewFrame];
346 380
347 // Make sure the window fits on the screen. If not, constrain. 381 // Make sure the window fits on the screen. If not, constrain.
348 // We'll scroll to allow the user to see all the content. 382 // We'll scroll to allow the user to see all the content.
383 NSRect screenFrame = [[[self window] screen] frame];
349 screenFrame = NSInsetRect(screenFrame, 0, kScrollWindowVerticalMargin); 384 screenFrame = NSInsetRect(screenFrame, 0, kScrollWindowVerticalMargin);
350 if (!NSContainsRect(screenFrame, windowFrame)) { 385 if (!NSContainsRect(screenFrame, windowFrame)) {
351 scrollable_ = YES; 386 scrollable_ = YES;
352 windowFrame = NSIntersectionRect(screenFrame, windowFrame); 387 windowFrame = NSIntersectionRect(screenFrame, windowFrame);
353 } else { 388 } else {
354 scrollable_ = NO; 389 scrollable_ = NO;
355 } 390 }
356 [[self window] setFrame:windowFrame display:YES]; 391 [[self window] setFrame:windowFrame display:YES];
357 // If scrollable then offset the view and show the arrows. 392 // If scrollable then offset the view and show the arrows.
358 if (scrollable_) { 393 if (scrollable_) {
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 #pragma mark BookmarkButtonControllerProtocol 996 #pragma mark BookmarkButtonControllerProtocol
962 997
963 // Recursively close all bookmark folders. 998 // Recursively close all bookmark folders.
964 - (void)closeAllBookmarkFolders { 999 - (void)closeAllBookmarkFolders {
965 // Closing the top level implicitly closes all children. 1000 // Closing the top level implicitly closes all children.
966 [barController_ closeAllBookmarkFolders]; 1001 [barController_ closeAllBookmarkFolders];
967 } 1002 }
968 1003
969 // Close our bookmark folder (a sub-controller) if we have one. 1004 // Close our bookmark folder (a sub-controller) if we have one.
970 - (void)closeBookmarkFolder:(id)sender { 1005 - (void)closeBookmarkFolder:(id)sender {
971 // folderController_ may be nil but that's OK. 1006 if (folderController_) {
972 [[folderController_ window] close]; 1007 [self setSubFolderGrowthToRight:YES];
973 folderController_ = nil; 1008 [[folderController_ window] close];
1009 folderController_ = nil;
1010 }
974 } 1011 }
975 1012
976 - (BookmarkModel*)bookmarkModel { 1013 - (BookmarkModel*)bookmarkModel {
977 return [barController_ bookmarkModel]; 1014 return [barController_ bookmarkModel];
978 } 1015 }
979 1016
980 // TODO(jrg): Refactor BookmarkBarFolder common code. http://crbug.com/35966 1017 // TODO(jrg): Refactor BookmarkBarFolder common code. http://crbug.com/35966
981 // Most of the work (e.g. drop indicator) is taken care of in the 1018 // Most of the work (e.g. drop indicator) is taken care of in the
982 // folder_view. Here we handle hover open issues for subfolders. 1019 // folder_view. Here we handle hover open issues for subfolders.
983 // Caution: there are subtle differences between this one and 1020 // Caution: there are subtle differences between this one and
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 return [folderController_ controllerForNode:node]; 1362 return [folderController_ controllerForNode:node];
1326 } 1363 }
1327 1364
1328 #pragma mark TestingAPI Only 1365 #pragma mark TestingAPI Only
1329 1366
1330 - (void)setIgnoreAnimations:(BOOL)ignore { 1367 - (void)setIgnoreAnimations:(BOOL)ignore {
1331 ignoreAnimations_ = ignore; 1368 ignoreAnimations_ = ignore;
1332 } 1369 }
1333 1370
1334 @end // BookmarkBarFolderController 1371 @end // BookmarkBarFolderController
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/bookmark_bar_folder_controller.h ('k') | chrome/browser/cocoa/bookmark_bar_folder_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698