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

Unified Diff: chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm

Issue 489143002: [Mac] Add tab and keyboard navigation to the new avatar bubble (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 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 | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
diff --git a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
index 96af0e4e162c73ee468511ee7c8ab73cc9072d39..2320823b9f57b10bce827b2dfec30fe272bbc08e 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
@@ -84,6 +84,7 @@ const CGFloat kProfileButtonHeight = 30;
const int kBezelThickness = 3; // Width of the bezel on an NSButton.
const int kImageTitleSpacing = 10;
const int kBlueButtonHeight = 30;
+const CGFloat kFocusRingLineWidth = 2;
// Fixed size for embedded sign in pages as defined in Gaia.
const CGFloat kFixedGaiaViewWidth = 360;
@@ -412,22 +413,32 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return buttonSize;
}
-@end
+- (NSFocusRingType)focusRingType {
+ // This is taken care of by the custom drawing code in the cell.
groby-ooo-7-16 2014/08/21 05:06:02 Isn't "in the cell" implicit?
noms (inactive) 2014/08/25 14:54:43 Done.
+ return NSFocusRingTypeNone;
+}
-// A custom button that has a transparent backround.
-@interface TransparentBackgroundButton : NSButton
-@end
+- (void)drawWithFrame:(NSRect)frame inView:(NSView *)controlView {
groby-ooo-7-16 2014/08/21 05:06:02 I'm still not entirely clear why the normal focus
noms (inactive) 2014/08/21 14:32:05 In the case of this control, the default focus rin
groby-ooo-7-16 2014/08/21 17:59:09 That's exceedingly odd. If I whip up a quick demo
noms (inactive) 2014/08/21 18:23:28 I think this is a HoverImageButton deal. From the
groby-ooo-7-16 2014/08/21 19:07:30 It's a CustomPaddingButtonCell deal :( -drawTitle:
noms (inactive) 2014/08/22 15:48:21 So doing this draws the image fine, but then there
+ [super drawInteriorWithFrame:frame inView:controlView];
-@implementation TransparentBackgroundButton
-- (id)initWithFrame:(NSRect)frameRect {
- if ((self = [super initWithFrame:frameRect])) {
- [self setBordered:NO];
- [self setFont:[NSFont labelFontOfSize:kTextFontSize]];
- [self setButtonType:NSMomentaryChangeButton];
+ // Focus ring.
+ if ([self showsFirstResponder]) {
groby-ooo-7-16 2014/08/21 05:06:02 You might want to leave a TODO to fix this with 10
noms (inactive) 2014/08/25 14:54:43 Done.
+ NSRect focusRingRect = NSInsetRect(frame,
+ kFocusRingLineWidth, kFocusRingLineWidth);
+ [[[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:1] set];
+ NSBezierPath* path = [NSBezierPath bezierPathWithRect:focusRingRect];
+ [path setLineWidth:kFocusRingLineWidth];
+ [path stroke];
}
- return self;
}
+@end
+
+// A custom image view that has a transparent backround.
+@interface TransparentBackgroundImageView : NSImageView
groby-ooo-7-16 2014/08/21 05:06:02 It's technically translucent, not transparent :)
noms (inactive) 2014/08/21 14:32:05 Still needed: the image is the size of the view, b
groby-ooo-7-16 2014/08/21 17:59:09 So the image has alpha, then? (Because otherwise,
noms (inactive) 2014/08/21 18:23:28 Yup, the image is just the center icon, and is tra
+@end
+
+@implementation TransparentBackgroundImageView
- (void)drawRect:(NSRect)dirtyRect {
NSColor* backgroundColor = [NSColor colorWithCalibratedWhite:1 alpha:0.6f];
[backgroundColor setFill];
@@ -436,13 +447,31 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
}
@end
+@interface CustomCircleImageCell : NSButtonCell
+@end
+
+@implementation CustomCircleImageCell
+- (void)drawWithFrame:(NSRect)frame inView:(NSView *)controlView {
+ // Display everything as a circle that spans the entire control.
+ NSBezierPath* path = [NSBezierPath bezierPathWithOvalInRect:frame];
+ [path addClip];
+
+ [super drawImage:[self image] withFrame:frame inView:controlView];
+
+ // Focus ring.
+ if ([self showsFirstResponder]) {
+ [[[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:1] set];
+ [path setLineWidth:kFocusRingLineWidth];
+ [path stroke];
+ }
+}
+@end
+
// A custom image control that shows a "Change" button when moused over.
-@interface EditableProfilePhoto : NSImageView {
+@interface EditableProfilePhoto : HoverImageButton {
@private
AvatarMenu* avatarMenu_; // Weak; Owned by ProfileChooserController.
- base::scoped_nsobject<TransparentBackgroundButton> changePhotoButton_;
- // Used to display the "Change" button on hover.
- ui::ScopedCrTrackingArea trackingArea_;
+ base::scoped_nsobject<TransparentBackgroundImageView> changePhotoImage_;
ProfileChooserController* controller_;
}
@@ -455,16 +484,6 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// Called when the "Change" button is clicked.
- (void)editPhoto:(id)sender;
-// When hovering over the profile photo, show the "Change" button.
-- (void)mouseEntered:(NSEvent*)event;
-
-// When hovering away from the profile photo, hide the "Change" button.
-- (void)mouseExited:(NSEvent*)event;
-@end
-
-@interface EditableProfilePhoto (Private)
-// Create the "Change" avatar photo button.
-- (TransparentBackgroundButton*)changePhotoButtonWithRect:(NSRect)rect;
@end
@implementation EditableProfilePhoto
@@ -476,24 +495,29 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
if ((self = [super initWithFrame:frameRect])) {
avatarMenu_ = avatarMenu;
controller_ = controller;
- [self setImage:CreateProfileImage(
- profileIcon, kLargeImageSide).ToNSImage()];
- // Add a tracking area so that we can show/hide the button when hovering.
- trackingArea_.reset([[CrTrackingArea alloc]
- initWithRect:[self bounds]
- options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways
- owner:self
- userInfo:nil]);
- [self addTrackingArea:trackingArea_.get()];
+ [self setBordered:NO];
+
+ base::scoped_nsobject<CustomCircleImageCell> cell(
+ [[CustomCircleImageCell alloc] init]);
+ [self setCell:cell.get()];
+
+ [self setDefaultImage:CreateProfileImage(
+ profileIcon, kLargeImageSide).ToNSImage()];
+ [self setImagePosition:NSImageOnly];
NSRect bounds = NSMakeRect(0, 0, kLargeImageSide, kLargeImageSide);
if (editingAllowed) {
- changePhotoButton_.reset([self changePhotoButtonWithRect:bounds]);
- [self addSubview:changePhotoButton_];
-
- // Hide the button until the image is hovered over.
- [changePhotoButton_ setHidden:YES];
+ [self setTarget:self];
+ [self setAction:@selector(editPhoto:)];
+ changePhotoImage_.reset([[TransparentBackgroundImageView alloc]
+ initWithFrame:bounds]);
+ [changePhotoImage_ setImage:ui::ResourceBundle::GetSharedInstance().
+ GetNativeImageNamed(IDR_ICON_PROFILES_EDIT_CAMERA).AsNSImage()];
+ [self addSubview:changePhotoImage_];
+
+ // Hide the image until the button is hovered over.
+ [changePhotoImage_ setHidden:YES];
}
// Set the image cell's accessibility strings to be the same as the
@@ -525,36 +549,15 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return self;
}
-- (void)drawRect:(NSRect)dirtyRect {
- NSRect bounds = [self bounds];
-
- // Display the profile picture as a circle.
- NSBezierPath* path = [NSBezierPath bezierPathWithOvalInRect:bounds];
- [path addClip];
- [self.image drawAtPoint:bounds.origin
- fromRect:bounds
- operation:NSCompositeSourceOver
- fraction:1.0];
-
-}
-
- (void)editPhoto:(id)sender {
avatarMenu_->EditProfile(avatarMenu_->GetActiveProfileIndex());
[controller_
postActionPerformed:ProfileMetrics::PROFILE_DESKTOP_MENU_EDIT_IMAGE];
}
-- (void)mouseEntered:(NSEvent*)event {
- [changePhotoButton_ setHidden:NO];
-}
-
-- (void)mouseExited:(NSEvent*)event {
- [changePhotoButton_ setHidden:YES];
-}
-
-// Make sure the element is focusable for accessibility.
-- (BOOL)canBecomeKeyView {
- return YES;
+- (void)setHoverState:(HoverState)state {
+ [super setHoverState:state];
+ [changePhotoImage_ setHidden:([self hoverState] == kHoverStateNone)];
}
- (BOOL)accessibilityIsIgnored {
@@ -574,16 +577,6 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
[super accessibilityPerformAction:action];
}
-- (TransparentBackgroundButton*)changePhotoButtonWithRect:(NSRect)rect {
- TransparentBackgroundButton* button =
- [[TransparentBackgroundButton alloc] initWithFrame:rect];
- [button setImage:ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
- IDR_ICON_PROFILES_EDIT_CAMERA).AsNSImage()];
- [button setImagePosition:NSImageOnly];
- [button setTarget:self];
- [button setAction:@selector(editPhoto:)];
- return button;
-}
@end
// A custom text control that turns into a textfield for editing when clicked.
@@ -775,6 +768,21 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
}
@end
+// A custom dummy button that is used to clear focus from the bubble's controls.
+@interface DummyWindowFocusButton : NSButton
+@end
+
+@implementation DummyWindowFocusButton
+// Ignore accessibility, as this is a placeholder button.
+- (BOOL)accessibilityIsIgnored {
+ return YES;
+}
+- (id)accessibilityAttributeValue:(NSString*)attribute {
+ return @[];
+}
+
+@end
+
@interface ProfileChooserController ()
// Builds the profile chooser view.
- (NSView*)buildProfileChooserView;
@@ -1122,6 +1130,14 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
if (viewMode_ != profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER)
tutorialMode_ = profiles::TUTORIAL_MODE_NONE;
+ // Add a dummy, empty element so that we don't initially display any
+ // focus rings.
+ NSButton* dummyFocusButton =
noms (inactive) 2014/08/20 17:17:38 This is a giant hack. I don't know how to get arou
groby-ooo-7-16 2014/08/21 05:06:02 That's a really bad idea. If there is no focus at
noms (inactive) 2014/08/21 14:32:05 I don't have mocks for tabbing, but always showing
groby-ooo-7-16 2014/08/21 17:59:09 Isn't that pretty bad in terms of a11y? You have n
noms (inactive) 2014/08/21 18:23:28 Oh, no no no, it's not that bad. So when the bubbl
groby-ooo-7-16 2014/08/21 19:07:30 I'd assume the blue circle is an issue for everybo
noms (inactive) 2014/08/21 19:53:39 The blue circle is because the control is round. I
groby-ooo-7-16 2014/08/21 20:53:34 OK. So, [[self window] makeFirstResponder:nil];?
noms (inactive) 2014/08/21 21:25:25 That was my first try, but that still focuses the
+ [[[DummyWindowFocusButton alloc] initWithFrame:NSZeroRect] autorelease];
+ [subView addSubview:dummyFocusButton];
+ [dummyFocusButton setNextKeyView:subView];
+ [[self window] makeFirstResponder:dummyFocusButton];
+
[contentView addSubview:subView];
SetWindowSize([self window],
NSMakeSize(NSWidth([subView frame]), NSHeight([subView frame])));
@@ -1637,7 +1653,8 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
- (NSButton*)createOtherProfileView:(int)itemIndex {
const AvatarMenu::Item& item = avatarMenu_->GetItemAt(itemIndex);
- NSRect rect = NSMakeRect(0, 0, kFixedMenuWidth, kBlueButtonHeight);
+ NSRect rect = NSMakeRect(
+ 0, 0, kFixedMenuWidth, kBlueButtonHeight + kSmallVerticalSpacing);
base::scoped_nsobject<BackgroundColorHoverButton> profileButton(
[[BackgroundColorHoverButton alloc]
initWithFrame:rect
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698