| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/website_settings/permission_bubble_controller.h
" | 5 #import "chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.h
" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/mac/bind_objc_block.h" | 9 #include "base/mac/bind_objc_block.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 class MenuDelegate : public ui::SimpleMenuModel::Delegate { | 50 class MenuDelegate : public ui::SimpleMenuModel::Delegate { |
| 51 public: | 51 public: |
| 52 explicit MenuDelegate(PermissionBubbleController* bubble) | 52 explicit MenuDelegate(PermissionBubbleController* bubble) |
| 53 : bubble_controller_(bubble) {} | 53 : bubble_controller_(bubble) {} |
| 54 bool IsCommandIdChecked(int command_id) const override { return false; } | 54 bool IsCommandIdChecked(int command_id) const override { return false; } |
| 55 bool IsCommandIdEnabled(int command_id) const override { return true; } | 55 bool IsCommandIdEnabled(int command_id) const override { return true; } |
| 56 bool GetAcceleratorForCommandId(int command_id, | 56 bool GetAcceleratorForCommandId(int command_id, |
| 57 ui::Accelerator* accelerator) override { | 57 ui::Accelerator* accelerator) override { |
| 58 return false; | 58 return false; |
| 59 } | 59 } |
| 60 void ExecuteCommand(int command_id, int event_flags) override { | |
| 61 [bubble_controller_ onMenuItemClicked:command_id]; | |
| 62 } | |
| 63 private: | 60 private: |
| 64 PermissionBubbleController* bubble_controller_; // Weak, owns us. | 61 PermissionBubbleController* bubble_controller_; // Weak, owns us. |
| 65 DISALLOW_COPY_AND_ASSIGN(MenuDelegate); | 62 DISALLOW_COPY_AND_ASSIGN(MenuDelegate); |
| 66 }; | 63 }; |
| 67 | 64 |
| 68 } // namespace | 65 } // namespace |
| 69 | 66 |
| 70 // NSPopUpButton with a menu containing two items: allow and block. | 67 // NSPopUpButton with a menu containing two items: allow and block. |
| 71 // One AllowBlockMenuButton is used for each requested permission, but only when | 68 // One AllowBlockMenuButton is used for each requested permission when there are |
| 72 // the permission bubble is in 'customize' mode. | 69 // multiple permissions in the bubble. |
| 73 @interface AllowBlockMenuButton : NSPopUpButton { | 70 @interface AllowBlockMenuButton : NSPopUpButton { |
| 74 @private | 71 @private |
| 75 scoped_ptr<PermissionMenuModel> menuModel_; | 72 scoped_ptr<PermissionMenuModel> menuModel_; |
| 76 base::scoped_nsobject<MenuController> menuController_; | 73 base::scoped_nsobject<MenuController> menuController_; |
| 77 } | 74 } |
| 78 | 75 |
| 79 - (id)initForURL:(const GURL&)url | 76 - (id)initForURL:(const GURL&)url |
| 80 allowed:(BOOL)allow | 77 allowed:(BOOL)allow |
| 81 index:(int)index | 78 index:(int)index |
| 82 delegate:(PermissionBubbleView::Delegate*)delegate; | 79 delegate:(PermissionBubbleView::Delegate*)delegate; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 atIndex:(int)index | 173 atIndex:(int)index |
| 177 allow:(BOOL)allow; | 174 allow:(BOOL)allow; |
| 178 | 175 |
| 179 // Returns an autoreleased NSView of a button with |title| and |action|. | 176 // Returns an autoreleased NSView of a button with |title| and |action|. |
| 180 - (NSView*)buttonWithTitle:(NSString*)title | 177 - (NSView*)buttonWithTitle:(NSString*)title |
| 181 action:(SEL)action; | 178 action:(SEL)action; |
| 182 | 179 |
| 183 // Returns an autoreleased NSView displaying a block button. | 180 // Returns an autoreleased NSView displaying a block button. |
| 184 - (NSView*)blockButton; | 181 - (NSView*)blockButton; |
| 185 | 182 |
| 186 // Returns an autoreleased NSView with a block button and a drop-down menu | |
| 187 // with one item, which will change the UI to allow customizing the permissions. | |
| 188 - (NSView*)blockButtonWithCustomizeMenu; | |
| 189 | |
| 190 // Returns an autoreleased NSView displaying the close 'x' button. | 183 // Returns an autoreleased NSView displaying the close 'x' button. |
| 191 - (NSView*)closeButton; | 184 - (NSView*)closeButton; |
| 192 | 185 |
| 193 // Called when the 'ok' button is pressed. | 186 // Called when the 'ok' button is pressed. |
| 194 - (void)ok:(id)sender; | 187 - (void)ok:(id)sender; |
| 195 | 188 |
| 196 // Called when the 'allow' button is pressed. | 189 // Called when the 'allow' button is pressed. |
| 197 - (void)onAllow:(id)sender; | 190 - (void)onAllow:(id)sender; |
| 198 | 191 |
| 199 // Called when the 'block' button is pressed. | 192 // Called when the 'block' button is pressed. |
| 200 - (void)onBlock:(id)sender; | 193 - (void)onBlock:(id)sender; |
| 201 | 194 |
| 202 // Called when the 'close' button is pressed. | 195 // Called when the 'close' button is pressed. |
| 203 - (void)onClose:(id)sender; | 196 - (void)onClose:(id)sender; |
| 204 | 197 |
| 205 // Called when the 'customize' button is pressed. | |
| 206 - (void)onCustomize:(id)sender; | |
| 207 | |
| 208 // Sets the width of both |viewA| and |viewB| to be the larger of the | 198 // Sets the width of both |viewA| and |viewB| to be the larger of the |
| 209 // two views' widths. Does not change either view's origin or height. | 199 // two views' widths. Does not change either view's origin or height. |
| 210 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB; | 200 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB; |
| 211 | 201 |
| 212 // Sets the offset of |viewA| so that its vertical center is aligned with the | 202 // Sets the offset of |viewA| so that its vertical center is aligned with the |
| 213 // vertical center of |viewB|. | 203 // vertical center of |viewB|. |
| 214 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB; | 204 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB; |
| 215 | 205 |
| 216 @end | 206 @end |
| 217 | 207 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 } | 250 } |
| 261 | 251 |
| 262 - (void)parentWindowDidMove:(NSNotification*)notification { | 252 - (void)parentWindowDidMove:(NSNotification*)notification { |
| 263 DCHECK(bridge_); | 253 DCHECK(bridge_); |
| 264 [self setAnchorPoint:bridge_->GetAnchorPoint()]; | 254 [self setAnchorPoint:bridge_->GetAnchorPoint()]; |
| 265 } | 255 } |
| 266 | 256 |
| 267 - (void)showAtAnchor:(NSPoint)anchorPoint | 257 - (void)showAtAnchor:(NSPoint)anchorPoint |
| 268 withDelegate:(PermissionBubbleView::Delegate*)delegate | 258 withDelegate:(PermissionBubbleView::Delegate*)delegate |
| 269 forRequests:(const std::vector<PermissionBubbleRequest*>&)requests | 259 forRequests:(const std::vector<PermissionBubbleRequest*>&)requests |
| 270 acceptStates:(const std::vector<bool>&)acceptStates | 260 acceptStates:(const std::vector<bool>&)acceptStates { |
| 271 customizationMode:(BOOL)customizationMode { | |
| 272 DCHECK(!requests.empty()); | 261 DCHECK(!requests.empty()); |
| 273 DCHECK(delegate); | 262 DCHECK(delegate); |
| 274 DCHECK(!customizationMode || (requests.size() == acceptStates.size())); | |
| 275 delegate_ = delegate; | 263 delegate_ = delegate; |
| 276 | 264 |
| 277 NSView* contentView = [[self window] contentView]; | 265 NSView* contentView = [[self window] contentView]; |
| 278 [contentView setSubviews:@[]]; | 266 [contentView setSubviews:@[]]; |
| 279 | 267 |
| 268 BOOL singlePermission = requests.size() == 1; |
| 269 |
| 280 // Create one button to use as a guide for the permissions' y-offsets. | 270 // Create one button to use as a guide for the permissions' y-offsets. |
| 281 base::scoped_nsobject<NSView> allowOrOkButton; | 271 base::scoped_nsobject<NSView> allowOrOkButton; |
| 282 if (customizationMode) { | 272 if (singlePermission) { |
| 273 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW); |
| 274 allowOrOkButton.reset([[self buttonWithTitle:allowTitle |
| 275 action:@selector(onAllow:)] retain]); |
| 276 } else { |
| 283 NSString* okTitle = l10n_util::GetNSString(IDS_OK); | 277 NSString* okTitle = l10n_util::GetNSString(IDS_OK); |
| 284 allowOrOkButton.reset([[self buttonWithTitle:okTitle | 278 allowOrOkButton.reset([[self buttonWithTitle:okTitle |
| 285 action:@selector(ok:)] retain]); | 279 action:@selector(ok:)] retain]); |
| 286 } else { | |
| 287 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW); | |
| 288 allowOrOkButton.reset([[self buttonWithTitle:allowTitle | |
| 289 action:@selector(onAllow:)] retain]); | |
| 290 } | 280 } |
| 291 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]); | 281 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]); |
| 292 BOOL singlePermission = requests.size() == 1; | |
| 293 | 282 |
| 294 base::scoped_nsobject<NSMutableArray> permissionMenus; | 283 base::scoped_nsobject<NSMutableArray> permissionMenus; |
| 295 if (customizationMode) | 284 if (!singlePermission) |
| 296 permissionMenus.reset([[NSMutableArray alloc] init]); | 285 permissionMenus.reset([[NSMutableArray alloc] init]); |
| 297 | 286 |
| 298 CGFloat maxPermissionLineWidth = 0; | 287 CGFloat maxPermissionLineWidth = 0; |
| 299 for (auto it = requests.begin(); it != requests.end(); it++) { | 288 for (auto it = requests.begin(); it != requests.end(); it++) { |
| 300 base::scoped_nsobject<NSView> permissionView( | 289 base::scoped_nsobject<NSView> permissionView( |
| 301 [[self labelForRequest:(*it)] retain]); | 290 [[self labelForRequest:(*it)] retain]); |
| 302 NSPoint origin = [permissionView frame].origin; | 291 NSPoint origin = [permissionView frame].origin; |
| 303 origin.x += kHorizontalPadding; | 292 origin.x += kHorizontalPadding; |
| 304 origin.y += yOffset; | 293 origin.y += yOffset; |
| 305 [permissionView setFrameOrigin:origin]; | 294 [permissionView setFrameOrigin:origin]; |
| 306 [contentView addSubview:permissionView]; | 295 [contentView addSubview:permissionView]; |
| 307 | 296 |
| 308 if (customizationMode) { | 297 if (!singlePermission) { |
| 309 int index = it - requests.begin(); | 298 int index = it - requests.begin(); |
| 310 base::scoped_nsobject<NSView> menu( | 299 base::scoped_nsobject<NSView> menu( |
| 311 [[self menuForRequest:(*it) | 300 [[self menuForRequest:(*it) |
| 312 atIndex:index | 301 atIndex:index |
| 313 allow:acceptStates[index] ? YES : NO] retain]); | 302 allow:acceptStates[index] ? YES : NO] retain]); |
| 314 // Align vertically. Horizontal alignment will be adjusted once the | 303 // Align vertically. Horizontal alignment will be adjusted once the |
| 315 // widest permission is know. | 304 // widest permission is know. |
| 316 [PermissionBubbleController alignCenterOf:menu | 305 [PermissionBubbleController alignCenterOf:menu |
| 317 verticallyToCenterOf:permissionView]; | 306 verticallyToCenterOf:permissionView]; |
| 318 [permissionMenus addObject:menu]; | 307 [permissionMenus addObject:menu]; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 335 | 324 |
| 336 // Determine the dimensions of the bubble. | 325 // Determine the dimensions of the bubble. |
| 337 // Once the height and width are set, the buttons and permission menus can | 326 // Once the height and width are set, the buttons and permission menus can |
| 338 // be laid out correctly. | 327 // be laid out correctly. |
| 339 NSRect bubbleFrame = NSMakeRect(0, 0, kBubbleMinWidth, 0); | 328 NSRect bubbleFrame = NSMakeRect(0, 0, kBubbleMinWidth, 0); |
| 340 | 329 |
| 341 // Fix the height of the bubble relative to the title. | 330 // Fix the height of the bubble relative to the title. |
| 342 bubbleFrame.size.height = NSMaxY([titleView frame]) + kVerticalPadding + | 331 bubbleFrame.size.height = NSMaxY([titleView frame]) + kVerticalPadding + |
| 343 info_bubble::kBubbleArrowHeight; | 332 info_bubble::kBubbleArrowHeight; |
| 344 | 333 |
| 345 if (customizationMode) { | 334 if (!singlePermission) { |
| 346 // Add the maximum menu width to the bubble width. | 335 // Add the maximum menu width to the bubble width. |
| 347 CGFloat maxMenuWidth = 0; | 336 CGFloat maxMenuWidth = 0; |
| 348 for (AllowBlockMenuButton* button in permissionMenus.get()) { | 337 for (AllowBlockMenuButton* button in permissionMenus.get()) { |
| 349 maxMenuWidth = std::max(maxMenuWidth, [button maximumTitleWidth]); | 338 maxMenuWidth = std::max(maxMenuWidth, [button maximumTitleWidth]); |
| 350 } | 339 } |
| 351 maxPermissionLineWidth += maxMenuWidth; | 340 maxPermissionLineWidth += maxMenuWidth; |
| 352 } | 341 } |
| 353 | 342 |
| 354 // The title and 'x' button row must fit within the bubble. | 343 // The title and 'x' button row must fit within the bubble. |
| 355 CGFloat titleRowWidth = NSMaxX([titleView frame]) + | 344 CGFloat titleRowWidth = NSMaxX([titleView frame]) + |
| (...skipping 17 matching lines...) Expand all Loading... |
| 373 | 362 |
| 374 [closeButton setFrameOrigin:closeButtonOrigin]; | 363 [closeButton setFrameOrigin:closeButtonOrigin]; |
| 375 [contentView addSubview:closeButton]; | 364 [contentView addSubview:closeButton]; |
| 376 | 365 |
| 377 // Position the allow/ok button. | 366 // Position the allow/ok button. |
| 378 CGFloat xOrigin = NSWidth(bubbleFrame) - NSWidth([allowOrOkButton frame]) - | 367 CGFloat xOrigin = NSWidth(bubbleFrame) - NSWidth([allowOrOkButton frame]) - |
| 379 kButtonRightEdgePadding; | 368 kButtonRightEdgePadding; |
| 380 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 369 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
| 381 [contentView addSubview:allowOrOkButton]; | 370 [contentView addSubview:allowOrOkButton]; |
| 382 | 371 |
| 383 if (customizationMode) { | 372 if (singlePermission) { |
| 384 // Adjust the horizontal origin for each menu so that its right edge | |
| 385 // lines up with the right edge of the ok button. | |
| 386 CGFloat rightEdge = NSMaxX([allowOrOkButton frame]); | |
| 387 for (NSView* view in permissionMenus.get()) { | |
| 388 [view setFrameOrigin:NSMakePoint(rightEdge - NSWidth([view frame]), | |
| 389 NSMinY([view frame]))]; | |
| 390 } | |
| 391 } else { | |
| 392 base::scoped_nsobject<NSView> blockButton; | 373 base::scoped_nsobject<NSView> blockButton; |
| 393 if (singlePermission) | 374 blockButton.reset([[self blockButton] retain]); |
| 394 blockButton.reset([[self blockButton] retain]); | |
| 395 else | |
| 396 blockButton.reset([[self blockButtonWithCustomizeMenu] retain]); | |
| 397 CGFloat width = [PermissionBubbleController matchWidthsOf:blockButton | 375 CGFloat width = [PermissionBubbleController matchWidthsOf:blockButton |
| 398 andOf:allowOrOkButton]; | 376 andOf:allowOrOkButton]; |
| 399 // Ensure the allow/ok button is still in the correct position. | 377 // Ensure the allow/ok button is still in the correct position. |
| 400 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding; | 378 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding; |
| 401 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 379 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
| 402 // Line up the block button. | 380 // Line up the block button. |
| 403 xOrigin = NSMinX([allowOrOkButton frame]) - width - kBetweenButtonsPadding; | 381 xOrigin = NSMinX([allowOrOkButton frame]) - width - kBetweenButtonsPadding; |
| 404 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 382 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
| 405 [contentView addSubview:blockButton]; | 383 [contentView addSubview:blockButton]; |
| 384 } else { |
| 385 // Adjust the horizontal origin for each menu so that its right edge |
| 386 // lines up with the right edge of the ok button. |
| 387 CGFloat rightEdge = NSMaxX([allowOrOkButton frame]); |
| 388 for (NSView* view in permissionMenus.get()) { |
| 389 [view setFrameOrigin:NSMakePoint(rightEdge - NSWidth([view frame]), |
| 390 NSMinY([view frame]))]; |
| 391 } |
| 406 } | 392 } |
| 407 | 393 |
| 408 bubbleFrame = [[self window] frameRectForContentRect:bubbleFrame]; | 394 bubbleFrame = [[self window] frameRectForContentRect:bubbleFrame]; |
| 409 if ([[self window] isVisible]) { | 395 if ([[self window] isVisible]) { |
| 410 // Unfortunately, calling -setFrame followed by -setFrameOrigin (called | 396 // Unfortunately, calling -setFrame followed by -setFrameOrigin (called |
| 411 // within -setAnchorPoint) causes flickering. Avoid the flickering by | 397 // within -setAnchorPoint) causes flickering. Avoid the flickering by |
| 412 // manually adjusting the new frame's origin so that the top left stays the | 398 // manually adjusting the new frame's origin so that the top left stays the |
| 413 // same, and only calling -setFrame. | 399 // same, and only calling -setFrame. |
| 414 NSRect currentWindowFrame = [[self window] frame]; | 400 NSRect currentWindowFrame = [[self window] frame]; |
| 415 bubbleFrame.origin = currentWindowFrame.origin; | 401 bubbleFrame.origin = currentWindowFrame.origin; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 [button sizeToFit]; | 497 [button sizeToFit]; |
| 512 return button.autorelease(); | 498 return button.autorelease(); |
| 513 } | 499 } |
| 514 | 500 |
| 515 - (NSView*)blockButton { | 501 - (NSView*)blockButton { |
| 516 NSString* blockTitle = l10n_util::GetNSString(IDS_PERMISSION_DENY); | 502 NSString* blockTitle = l10n_util::GetNSString(IDS_PERMISSION_DENY); |
| 517 return [self buttonWithTitle:blockTitle | 503 return [self buttonWithTitle:blockTitle |
| 518 action:@selector(onBlock:)]; | 504 action:@selector(onBlock:)]; |
| 519 } | 505 } |
| 520 | 506 |
| 521 - (NSView*)blockButtonWithCustomizeMenu { | |
| 522 menuDelegate_.reset(new MenuDelegate(self)); | |
| 523 base::scoped_nsobject<SplitBlockButton> blockButton([[SplitBlockButton alloc] | |
| 524 initWithMenuDelegate:menuDelegate_.get()]); | |
| 525 [blockButton sizeToFit]; | |
| 526 [blockButton setEnabled:YES]; | |
| 527 [blockButton setAction:@selector(onBlock:)]; | |
| 528 [blockButton setTarget:self]; | |
| 529 return blockButton.autorelease(); | |
| 530 } | |
| 531 | |
| 532 - (NSView*)closeButton { | 507 - (NSView*)closeButton { |
| 533 int dimension = chrome_style::GetCloseButtonSize(); | 508 int dimension = chrome_style::GetCloseButtonSize(); |
| 534 NSRect frame = NSMakeRect(0, 0, dimension, dimension); | 509 NSRect frame = NSMakeRect(0, 0, dimension, dimension); |
| 535 base::scoped_nsobject<NSButton> button( | 510 base::scoped_nsobject<NSButton> button( |
| 536 [[WebUIHoverCloseButton alloc] initWithFrame:frame]); | 511 [[WebUIHoverCloseButton alloc] initWithFrame:frame]); |
| 537 [button setAction:@selector(onClose:)]; | 512 [button setAction:@selector(onClose:)]; |
| 538 [button setTarget:self]; | 513 [button setTarget:self]; |
| 539 return button.autorelease(); | 514 return button.autorelease(); |
| 540 } | 515 } |
| 541 | 516 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 552 - (void)onBlock:(id)sender { | 527 - (void)onBlock:(id)sender { |
| 553 DCHECK(delegate_); | 528 DCHECK(delegate_); |
| 554 delegate_->Deny(); | 529 delegate_->Deny(); |
| 555 } | 530 } |
| 556 | 531 |
| 557 - (void)onClose:(id)sender { | 532 - (void)onClose:(id)sender { |
| 558 DCHECK(delegate_); | 533 DCHECK(delegate_); |
| 559 delegate_->Closing(); | 534 delegate_->Closing(); |
| 560 } | 535 } |
| 561 | 536 |
| 562 - (void)onCustomize:(id)sender { | |
| 563 DCHECK(delegate_); | |
| 564 delegate_->SetCustomizationMode(); | |
| 565 } | |
| 566 | |
| 567 - (void)onMenuItemClicked:(int)commandId { | |
| 568 DCHECK(commandId == 0); | |
| 569 [self onCustomize:nil]; | |
| 570 } | |
| 571 | |
| 572 - (void)activateTabWithContents:(content::WebContents*)newContents | 537 - (void)activateTabWithContents:(content::WebContents*)newContents |
| 573 previousContents:(content::WebContents*)oldContents | 538 previousContents:(content::WebContents*)oldContents |
| 574 atIndex:(NSInteger)index | 539 atIndex:(NSInteger)index |
| 575 reason:(int)reason { | 540 reason:(int)reason { |
| 576 // The show/hide of this bubble is handled by the PermissionBubbleManager. | 541 // The show/hide of this bubble is handled by the PermissionBubbleManager. |
| 577 // So bypass the base class, which would close the bubble here. | 542 // So bypass the base class, which would close the bubble here. |
| 578 } | 543 } |
| 579 | 544 |
| 580 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB { | 545 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB { |
| 581 NSRect frameA = [viewA frame]; | 546 NSRect frameA = [viewA frame]; |
| 582 NSRect frameB = [viewB frame]; | 547 NSRect frameB = [viewB frame]; |
| 583 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB)); | 548 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB)); |
| 584 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))]; | 549 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))]; |
| 585 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))]; | 550 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))]; |
| 586 return width; | 551 return width; |
| 587 } | 552 } |
| 588 | 553 |
| 589 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB { | 554 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB { |
| 590 NSRect frameA = [viewA frame]; | 555 NSRect frameA = [viewA frame]; |
| 591 NSRect frameB = [viewB frame]; | 556 NSRect frameB = [viewB frame]; |
| 592 frameA.origin.y = | 557 frameA.origin.y = |
| 593 NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2); | 558 NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2); |
| 594 [viewA setFrameOrigin:frameA.origin]; | 559 [viewA setFrameOrigin:frameA.origin]; |
| 595 } | 560 } |
| 596 | 561 |
| 597 @end // implementation PermissionBubbleController | 562 @end // implementation PermissionBubbleController |
| OLD | NEW |