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

Unified Diff: chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm

Issue 242443005: Changes cocoa implementation of permission bubble to better match mocks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: one more edit Created 6 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/browser/ui/cocoa/website_settings/permission_bubble_controller_unittest.mm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
diff --git a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
index 0b6f6f03f8b6c240922da6e39e02ff2e961e8f46..71832b1b701c59e09566ec1610d90aba7c25ec46 100644
--- a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/mac/bind_objc_block.h"
#include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
@@ -20,12 +21,15 @@
#import "chrome/browser/ui/cocoa/info_bubble_view.h"
#import "chrome/browser/ui/cocoa/info_bubble_window.h"
#include "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h"
+#include "chrome/browser/ui/cocoa/website_settings/permission_selector_button.h"
#include "chrome/browser/ui/cocoa/website_settings/split_block_button.h"
#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
#include "chrome/browser/ui/website_settings/permission_bubble_view.h"
+#include "chrome/browser/ui/website_settings/permission_menu_model.h"
#include "content/public/browser/user_metrics.h"
#include "grit/generated_resources.h"
#include "skia/ext/skia_utils_mac.h"
+#import "ui/base/cocoa/menu_controller.h"
#include "ui/base/cocoa/window_size_constants.h"
#import "ui/base/cocoa/menu_controller.h"
#include "ui/base/l10n/l10n_util_mac.h"
@@ -39,9 +43,10 @@ const CGFloat kHorizontalPadding = 20.0f;
const CGFloat kVerticalPadding = 20.0f;
const CGFloat kButtonPadding = 10.0f;
const CGFloat kTitlePaddingX = 50.0f;
-const CGFloat kCheckboxYAdjustment = 2.0f;
+const CGFloat kTitleFontSize = 15.0f;
+const CGFloat kPermissionFontSize = 12.0f;
+const CGFloat kPermissionButtonTitleRightPadding = 4.0f;
-const CGFloat kFontSize = 15.0f;
class MenuDelegate : public ui::SimpleMenuModel::Delegate {
public:
explicit MenuDelegate(PermissionBubbleController* bubble)
@@ -50,10 +55,7 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
return false;
}
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
- // TODO(leng): Change this to true once setting the bubble to be
- // customizable works properly. Ideally, the bubble will alter its
- // contents, rather than reshowing completely.
- return false;
+ return true;
}
virtual bool GetAcceleratorForCommandId(
int command_id,
@@ -70,6 +72,63 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
} // namespace
+// NSPopUpButton with a menu containing two items: allow and block.
+// One AllowBlockMenuButton is used for each requested permission, but only when
+// the permission bubble is in 'customize' mode.
+@interface AllowBlockMenuButton : NSPopUpButton {
+ @private
+ scoped_ptr<PermissionMenuModel> menuModel_;
+ base::scoped_nsobject<MenuController> menuController_;
+}
+
+- (id)initForURL:(const GURL&)url
+ allowed:(BOOL)allow
+ index:(int)index
+ delegate:(PermissionBubbleView::Delegate*)delegate;
+@end
+
+@implementation AllowBlockMenuButton
+
+- (id)initForURL:(const GURL&)url
+ allowed:(BOOL)allow
+ index:(int)index
+ delegate:(PermissionBubbleView::Delegate*)delegate {
+ if (self = [super initWithFrame:NSMakeRect(0, 0, 1, 1) pullsDown:NO]) {
groby-ooo-7-16 2014/04/25 19:25:28 Why not NSZeroRect?
leng 2014/04/25 22:18:56 Done.
+ ContentSetting setting =
+ allow ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
+ [self setFont:[NSFont systemFontOfSize:kPermissionFontSize]];
+ [self setBordered:NO];
+
+ __block PermissionBubbleView::Delegate* blockDelegate = delegate;
+ PermissionMenuModel::ChangeCallback changeCallback =
+ base::BindBlock(^(const WebsiteSettingsUI::PermissionInfo& permission) {
groby-ooo-7-16 2014/04/25 19:25:28 I just realized we created an ObjC block for the O
leng 2014/04/25 22:18:56 On 2014/04/25 19:25:28, groby wrote: > I just real
+ blockDelegate->ToggleAccept(
+ index, permission.setting == CONTENT_SETTING_ALLOW);
+ });
+
+ menuModel_.reset(new PermissionMenuModel(url, setting, changeCallback));
+ menuController_.reset([[MenuController alloc] initWithModel:menuModel_.get()
+ useWithPopUpButtonCell:NO]);
+ [self setMenu:[menuController_ menu]];
+ [self selectItemAtIndex:menuModel_->GetIndexOfCommandId(setting)];
+ [self sizeToFit];
+ // Adjust the size to fit the current title. Using only -sizeToFit leaves
+ // an ugly amount of whitespace between the title and the arrows.
groby-ooo-7-16 2014/04/25 19:25:28 Ah. That's because NSPopUpButton's sizeToFit fits
leng 2014/04/25 22:18:56 Done.
+ // TODO(leng): This was copied from PermissionSelectorButton. Move to a
+ // shared location, so that the code is not duplicated.
+ NSDictionary* textAttributes = @{NSFontAttributeName : [self font]};
groby-ooo-7-16 2014/04/25 19:25:28 You could call [[self attributedTitle] attribut
leng 2014/04/25 22:18:56 Done.
+ NSSize titleSize = [[self title] sizeWithAttributes:textAttributes];
+ NSRect frame = [self frame];
+ NSRect titleRect = [[self cell] titleRectForBounds:frame];
+ CGFloat width = titleSize.width + NSWidth(frame) - NSWidth(titleRect);
+ [self setFrameSize:NSMakeSize(width + kPermissionButtonTitleRightPadding,
+ NSHeight(frame))];
+ }
+ return self;
+}
+
+@end
+
@interface PermissionBubbleController ()
// Returns an autoreleased NSView displaying the icon and label for |request|.
@@ -79,10 +138,11 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
// requesting settings for |host|.
- (NSView*)titleWithHostname:(const std::string&)host;
-// Returns an autoreleased NSView displaying a checkbox for |request|. The
-// checkbox will be initialized as checked if |checked| is YES.
-- (NSView*)checkboxForRequest:(PermissionBubbleRequest*)request
- checked:(BOOL)checked;
+// Returns an autoreleased NSView displaying a menu for |request|. The
+// menu will be initialized as 'allow' if |allow| is YES.
+- (NSView*)menuForRequest:(PermissionBubbleRequest*)request
+ atIndex:(int)index
+ allow:(BOOL)allow;
// Returns an autoreleased NSView of a button with |title| and |action|.
- (NSView*)buttonWithTitle:(NSString*)title
@@ -98,10 +158,6 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
// Returns an autoreleased NSView displaying the close 'x' button.
- (NSView*)closeButton;
-// Sets the width of both |viewA| and |viewB| to be the larger of the
-// two views' widths. Does not change either view's origin or height.
-- (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB;
-
// Called when the 'ok' button is pressed.
- (void)ok:(id)sender;
@@ -117,8 +173,13 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
// Called when the 'customize' button is pressed.
- (void)onCustomize:(id)sender;
-// Called when a checkbox changes from checked to unchecked, or vice versa.
-- (void)onCheckboxChanged:(id)sender;
+// Sets the width of both |viewA| and |viewB| to be the larger of the
+// two views' widths. Does not change either view's origin or height.
++ (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB;
+
+// Sets the offset of |viewA| so that its vertical center is aligned with the
+// vertical center of |viewB|.
++ (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB;
@end
@@ -176,25 +237,32 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]);
BOOL singlePermission = requests.size() == 1;
- checkboxes_.reset(customizationMode ? [[NSMutableArray alloc] init] : nil);
+ base::scoped_nsobject<NSMutableArray> permissionMenus;
+ if (customizationMode)
+ permissionMenus.reset([[NSMutableArray alloc] init]);
+
for (auto it = requests.begin(); it != requests.end(); it++) {
- base::scoped_nsobject<NSView> permissionView;
- if (customizationMode) {
- int index = it - requests.begin();
- permissionView.reset(
- [[self checkboxForRequest:(*it)
- checked:acceptStates[index] ? YES : NO] retain]);
- [base::mac::ObjCCastStrict<NSButton>(permissionView) setTag:index];
- [checkboxes_ addObject:permissionView];
- } else {
- permissionView.reset([[self labelForRequest:(*it)] retain]);
- }
+ base::scoped_nsobject<NSView> permissionView(
+ [[self labelForRequest:(*it)] retain]);
NSPoint origin = [permissionView frame].origin;
origin.x += kHorizontalPadding;
origin.y += yOffset;
[permissionView setFrameOrigin:origin];
[contentView addSubview:permissionView];
+ if (customizationMode) {
+ int index = it - requests.begin();
+ base::scoped_nsobject<NSView> menu(
+ [[self menuForRequest:(*it)
+ atIndex:index
+ allow:acceptStates[index] ? YES : NO] retain]);
+ // Align vertically. Horizontal alignment will be adjusted once the
+ // widest permission is know.
+ [PermissionBubbleController alignCenterOf:menu
+ verticallyToCenterOf:permissionView];
+ [permissionMenus addObject:menu];
+ [contentView addSubview:menu];
+ }
yOffset += NSHeight([permissionView frame]);
}
@@ -207,6 +275,18 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
bubbleFrame, NSInsetRect([view frame], -kHorizontalPadding, 0));
}
+ if (customizationMode) {
+ // Adjust the horizontal origin for each menu.
+ CGFloat xOffset = NSWidth(bubbleFrame) - kHorizontalPadding;
+ CGFloat maxMenuWidth = 0;
+ for (NSView* view in permissionMenus.get()) {
+ [view setFrameOrigin:NSMakePoint(xOffset, NSMinY([view frame]))];
+ maxMenuWidth = std::max(maxMenuWidth, NSWidth([view frame]));
+ }
+ // And add the menu width to the bubble's width.
+ bubbleFrame.size.width += maxMenuWidth;
+ }
+
base::scoped_nsobject<NSView> titleView(
[[self titleWithHostname:requests[0]->GetRequestingHostname().host()]
retain]);
@@ -242,7 +322,8 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
blockButton.reset([[self blockButton] retain]);
else
blockButton.reset([[self blockButtonWithCustomizeMenu] retain]);
- CGFloat width = [self matchWidthsOf:blockButton andOf:allowOrOkButton];
+ CGFloat width = [PermissionBubbleController matchWidthsOf:blockButton
+ andOf:allowOrOkButton];
// Ensure the allow/ok button is still in the correct position.
xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding;
[allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)];
@@ -290,6 +371,7 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
[permissionLabel setBezeled:NO];
[permissionLabel setEditable:NO];
[permissionLabel setSelectable:NO];
+ [permissionLabel setFont:[NSFont systemFontOfSize:kPermissionFontSize]];
[permissionLabel setStringValue:base::SysUTF16ToNSString(label)];
[permissionLabel sizeToFit];
[permissionLabel setFrameOrigin:
@@ -326,7 +408,7 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
[titleView setStringValue:
l10n_util::GetNSStringF(IDS_PERMISSIONS_BUBBLE_PROMPT,
base::UTF8ToUTF16(host))];
- [titleView setFont:[NSFont systemFontOfSize:kFontSize]];
+ [titleView setFont:[NSFont systemFontOfSize:kTitleFontSize]];
[titleView sizeToFit];
NSRect titleFrame = [titleView frame];
[titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX,
@@ -334,20 +416,17 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
return titleView.autorelease();
}
-- (NSView*)checkboxForRequest:(PermissionBubbleRequest*)request
- checked:(BOOL)checked {
+- (NSView*)menuForRequest:(PermissionBubbleRequest*)request
+ atIndex:(int)index
+ allow:(BOOL)allow {
DCHECK(request);
- base::scoped_nsobject<NSButton> checkbox(
- [[NSButton alloc] initWithFrame:NSZeroRect]);
- [checkbox setButtonType:NSSwitchButton];
- base::string16 permission = request->GetMessageTextFragment();
- [checkbox setTitle:base::SysUTF16ToNSString(permission)];
- [checkbox setState:(checked ? NSOnState : NSOffState)];
- [checkbox setTarget:self];
- [checkbox setAction:@selector(onCheckboxChanged:)];
- [checkbox sizeToFit];
- [checkbox setFrameOrigin:NSMakePoint(0, kCheckboxYAdjustment)];
- return checkbox.autorelease();
+ DCHECK(delegate_);
+ base::scoped_nsobject<AllowBlockMenuButton> button(
+ [[AllowBlockMenuButton alloc] initForURL:request->GetRequestingHostname()
+ allowed:allow
+ index:index
+ delegate:delegate_]);
+ return button.autorelease();
}
- (NSView*)buttonWithTitle:(NSString*)title
@@ -389,15 +468,6 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
return button.autorelease();
}
-- (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB {
- NSRect frameA = [viewA frame];
- NSRect frameB = [viewB frame];
- CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB));
- [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))];
- [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))];
- return width;
-}
-
- (void)ok:(id)sender {
DCHECK(delegate_);
delegate_->Closing();
@@ -423,15 +493,26 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
delegate_->SetCustomizationMode();
}
-- (void)onCheckboxChanged:(id)sender {
- DCHECK(delegate_);
- NSButton* checkbox = base::mac::ObjCCastStrict<NSButton>(sender);
- delegate_->ToggleAccept([checkbox tag], [checkbox state] == NSOnState);
-}
-
- (void)onMenuItemClicked:(int)commandId {
DCHECK(commandId == 0);
[self onCustomize:nil];
}
++ (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB {
+ NSRect frameA = [viewA frame];
+ NSRect frameB = [viewB frame];
+ CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB));
+ [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))];
+ [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))];
+ return width;
+}
+
++ (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB {
+ NSRect frameA = [viewA frame];
+ NSRect frameB = [viewB frame];
+ frameA.origin.y =
+ NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2);
+ [viewA setFrameOrigin:frameA.origin];
+}
+
@end // implementation PermissionBubbleController
« no previous file with comments | « no previous file | chrome/browser/ui/cocoa/website_settings/permission_bubble_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698