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

Side by Side Diff: chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm

Issue 471703002: [Mac] Add accessibility features to the new avatar menu (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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <Cocoa/Cocoa.h> 5 #import <Cocoa/Cocoa.h>
6 6
7 #import "chrome/browser/ui/cocoa/profiles/profile_chooser_controller.h" 7 #import "chrome/browser/ui/cocoa/profiles/profile_chooser_controller.h"
8 8
9 #include "base/mac/bundle_locations.h" 9 #include "base/mac/bundle_locations.h"
10 #include "base/prefs/pref_service.h" 10 #include "base/prefs/pref_service.h"
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 withController:(ProfileChooserController*)controller; 448 withController:(ProfileChooserController*)controller;
449 449
450 // Called when the "Change" button is clicked. 450 // Called when the "Change" button is clicked.
451 - (void)editPhoto:(id)sender; 451 - (void)editPhoto:(id)sender;
452 452
453 // When hovering over the profile photo, show the "Change" button. 453 // When hovering over the profile photo, show the "Change" button.
454 - (void)mouseEntered:(NSEvent*)event; 454 - (void)mouseEntered:(NSEvent*)event;
455 455
456 // When hovering away from the profile photo, hide the "Change" button. 456 // When hovering away from the profile photo, hide the "Change" button.
457 - (void)mouseExited:(NSEvent*)event; 457 - (void)mouseExited:(NSEvent*)event;
458
459 - (BOOL)acceptsFirstResponder;
460 - (BOOL)canBecomeKeyView;
461 - (BOOL)accessibilityIsIgnored;
462 - (NSArray*)accessibilityActionNames;
463 - (void)accessibilityPerformAction:(NSString*)action;
groby-ooo-7-16 2014/08/15 00:38:35 No need to declare any of them - they're all imple
noms (inactive) 2014/08/15 19:26:47 Argh, sorry. I never know when to declare and when
groby-ooo-7-16 2014/08/15 19:52:07 This is one of the few places ObjC pretends to not
458 @end 464 @end
459 465
460 @interface EditableProfilePhoto (Private) 466 @interface EditableProfilePhoto (Private)
461 // Create the "Change" avatar photo button. 467 // Create the "Change" avatar photo button.
462 - (TransparentBackgroundButton*)changePhotoButtonWithRect:(NSRect)rect; 468 - (TransparentBackgroundButton*)changePhotoButtonWithRect:(NSRect)rect;
463 @end 469 @end
464 470
465 @implementation EditableProfilePhoto 471 @implementation EditableProfilePhoto
466 - (id)initWithFrame:(NSRect)frameRect 472 - (id)initWithFrame:(NSRect)frameRect
467 avatarMenu:(AvatarMenu*)avatarMenu 473 avatarMenu:(AvatarMenu*)avatarMenu
(...skipping 15 matching lines...) Expand all
483 [self addTrackingArea:trackingArea_.get()]; 489 [self addTrackingArea:trackingArea_.get()];
484 490
485 NSRect bounds = NSMakeRect(0, 0, kLargeImageSide, kLargeImageSide); 491 NSRect bounds = NSMakeRect(0, 0, kLargeImageSide, kLargeImageSide);
486 if (editingAllowed) { 492 if (editingAllowed) {
487 changePhotoButton_.reset([self changePhotoButtonWithRect:bounds]); 493 changePhotoButton_.reset([self changePhotoButtonWithRect:bounds]);
488 [self addSubview:changePhotoButton_]; 494 [self addSubview:changePhotoButton_];
489 495
490 // Hide the button until the image is hovered over. 496 // Hide the button until the image is hovered over.
491 [changePhotoButton_ setHidden:YES]; 497 [changePhotoButton_ setHidden:YES];
492 } 498 }
499
500 // Set the image cell's accessibility strings to be the same as the
501 // button's strings.
502 [[self cell] accessibilitySetOverrideValue:l10n_util::GetNSString(
503 editingAllowed ?
504 IDS_PROFILES_NEW_AVATAR_MENU_CHANGE_PHOTO_ACCESSIBLE_NAME :
505 IDS_PROFILES_NEW_AVATAR_MENU_PHOTO_ACCESSIBLE_NAME)
506 forAttribute:NSAccessibilityTitleAttribute];
507 [[self cell] accessibilitySetOverrideValue:
508 editingAllowed ? NSAccessibilityButtonRole : NSAccessibilityImageRole
509 forAttribute:NSAccessibilityRoleAttribute];
510 [[self cell] accessibilitySetOverrideValue:
511 NSAccessibilityRoleDescription(NSAccessibilityButtonRole, nil)
512 forAttribute:NSAccessibilityRoleDescriptionAttribute];
513
514 // The button and the cell should read the same thing.
515 [self accessibilitySetOverrideValue:l10n_util::GetNSString(
516 editingAllowed ?
517 IDS_PROFILES_NEW_AVATAR_MENU_CHANGE_PHOTO_ACCESSIBLE_NAME :
518 IDS_PROFILES_NEW_AVATAR_MENU_PHOTO_ACCESSIBLE_NAME)
519 forAttribute:NSAccessibilityTitleAttribute];
520 [self accessibilitySetOverrideValue:NSAccessibilityButtonRole
521 forAttribute:NSAccessibilityRoleAttribute];
522 [self accessibilitySetOverrideValue:
523 NSAccessibilityRoleDescription(NSAccessibilityButtonRole, nil)
524 forAttribute:NSAccessibilityRoleDescriptionAttribute];
493 } 525 }
494 return self; 526 return self;
495 } 527 }
496 528
497 - (void)drawRect:(NSRect)dirtyRect { 529 - (void)drawRect:(NSRect)dirtyRect {
498 NSRect bounds = [self bounds]; 530 NSRect bounds = [self bounds];
499 531
500 // Display the profile picture as a circle. 532 // Display the profile picture as a circle.
501 NSBezierPath* path = [NSBezierPath bezierPathWithOvalInRect:bounds]; 533 NSBezierPath* path = [NSBezierPath bezierPathWithOvalInRect:bounds];
502 [path addClip]; 534 [path addClip];
(...skipping 11 matching lines...) Expand all
514 } 546 }
515 547
516 - (void)mouseEntered:(NSEvent*)event { 548 - (void)mouseEntered:(NSEvent*)event {
517 [changePhotoButton_ setHidden:NO]; 549 [changePhotoButton_ setHidden:NO];
518 } 550 }
519 551
520 - (void)mouseExited:(NSEvent*)event { 552 - (void)mouseExited:(NSEvent*)event {
521 [changePhotoButton_ setHidden:YES]; 553 [changePhotoButton_ setHidden:YES];
522 } 554 }
523 555
556 // Make sure the element is focusable for accessibility.
557 - (BOOL)canBecomeKeyView {
558 return YES;
559 }
560
561 - (BOOL)acceptsFirstResponder {
562 return YES;
563 }
564
565 - (BOOL)accessibilityIsIgnored {
566 return NO;
567 }
568
569 - (NSArray*)accessibilityActionNames {
570 NSArray* parentActions = [super accessibilityActionNames];
571 return [parentActions arrayByAddingObject:NSAccessibilityPressAction];
572 }
573
574 - (void)accessibilityPerformAction:(NSString*)action {
575 if ([action isEqualToString:NSAccessibilityPressAction]) {
576 avatarMenu_->EditProfile(avatarMenu_->GetActiveProfileIndex());
577 }
578
579 [super accessibilityPerformAction:action];
580 }
581
524 - (TransparentBackgroundButton*)changePhotoButtonWithRect:(NSRect)rect { 582 - (TransparentBackgroundButton*)changePhotoButtonWithRect:(NSRect)rect {
525 TransparentBackgroundButton* button = 583 TransparentBackgroundButton* button =
526 [[TransparentBackgroundButton alloc] initWithFrame:rect]; 584 [[TransparentBackgroundButton alloc] initWithFrame:rect];
527 [button setImage:ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( 585 [button setImage:ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
528 IDR_ICON_PROFILES_EDIT_CAMERA).AsNSImage()]; 586 IDR_ICON_PROFILES_EDIT_CAMERA).AsNSImage()];
529 [button setImagePosition:NSImageOnly]; 587 [button setImagePosition:NSImageOnly];
530 [button setTarget:self]; 588 [button setTarget:self];
531 [button setAction:@selector(editPhoto:)]; 589 [button setAction:@selector(editPhoto:)];
532 return button; 590 return button;
533 } 591 }
(...skipping 12 matching lines...) Expand all
546 profileName:(NSString*)profileName 604 profileName:(NSString*)profileName
547 editingAllowed:(BOOL)editingAllowed 605 editingAllowed:(BOOL)editingAllowed
548 withController:(ProfileChooserController*)controller; 606 withController:(ProfileChooserController*)controller;
549 607
550 // Called when the button is clicked. 608 // Called when the button is clicked.
551 - (void)showEditableView:(id)sender; 609 - (void)showEditableView:(id)sender;
552 610
553 // Called when enter is pressed in the text field. 611 // Called when enter is pressed in the text field.
554 - (void)saveProfileName:(id)sender; 612 - (void)saveProfileName:(id)sender;
555 613
614 - (BOOL)acceptsFirstResponder;
615
556 @end 616 @end
557 617
558 @implementation EditableProfileNameButton 618 @implementation EditableProfileNameButton
559 - (id)initWithFrame:(NSRect)frameRect 619 - (id)initWithFrame:(NSRect)frameRect
560 profile:(Profile*)profile 620 profile:(Profile*)profile
561 profileName:(NSString*)profileName 621 profileName:(NSString*)profileName
562 editingAllowed:(BOOL)editingAllowed 622 editingAllowed:(BOOL)editingAllowed
563 withController:(ProfileChooserController*)controller { 623 withController:(ProfileChooserController*)controller {
564 if ((self = [super initWithFrame:frameRect])) { 624 if ((self = [super initWithFrame:frameRect])) {
565 profile_ = profile; 625 profile_ = profile;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 [[profileNameTextField_ cell] setLineBreakMode: 666 [[profileNameTextField_ cell] setLineBreakMode:
607 NSLineBreakByTruncatingTail]; 667 NSLineBreakByTruncatingTail];
608 [self addSubview:profileNameTextField_]; 668 [self addSubview:profileNameTextField_];
609 [profileNameTextField_ setTarget:self]; 669 [profileNameTextField_ setTarget:self];
610 [profileNameTextField_ setAction:@selector(saveProfileName:)]; 670 [profileNameTextField_ setAction:@selector(saveProfileName:)];
611 671
612 // Hide the textfield until the user clicks on the button. 672 // Hide the textfield until the user clicks on the button.
613 [profileNameTextField_ setHidden:YES]; 673 [profileNameTextField_ setHidden:YES];
614 } 674 }
615 675
676 [[self cell] accessibilitySetOverrideValue:NSAccessibilityButtonRole
677 forAttribute:NSAccessibilityRoleAttribute];
678 [[self cell] accessibilitySetOverrideValue:
679 NSAccessibilityRoleDescription(NSAccessibilityButtonRole, nil)
680 forAttribute:NSAccessibilityRoleDescriptionAttribute];
681
616 [self setBordered:NO]; 682 [self setBordered:NO];
617 [self setFont:[NSFont labelFontOfSize:kTitleFontSize]]; 683 [self setFont:[NSFont labelFontOfSize:kTitleFontSize]];
618 [self setAlignment:NSCenterTextAlignment]; 684 [self setAlignment:NSCenterTextAlignment];
619 [[self cell] setLineBreakMode:NSLineBreakByTruncatingTail]; 685 [[self cell] setLineBreakMode:NSLineBreakByTruncatingTail];
620 [self setTitle:profileName]; 686 [self setTitle:profileName];
621 } 687 }
622 return self; 688 return self;
623 } 689 }
624 690
625 - (void)saveProfileName:(id)sender { 691 - (void)saveProfileName:(id)sender {
626 NSString* text = [profileNameTextField_ stringValue]; 692 NSString* text = [profileNameTextField_ stringValue];
627 // Empty profile names are not allowed, and are treated as a cancel. 693 // Empty profile names are not allowed, and are treated as a cancel.
628 if ([text length] > 0) { 694 if ([text length] > 0) {
629 profiles::UpdateProfileName(profile_, base::SysNSStringToUTF16(text)); 695 profiles::UpdateProfileName(profile_, base::SysNSStringToUTF16(text));
630 [controller_ 696 [controller_
631 postActionPerformed:ProfileMetrics::PROFILE_DESKTOP_MENU_EDIT_NAME]; 697 postActionPerformed:ProfileMetrics::PROFILE_DESKTOP_MENU_EDIT_NAME];
632 [self setTitle:text]; 698 [self setTitle:text];
633 } 699 }
634 [profileNameTextField_ setHidden:YES]; 700 [profileNameTextField_ setHidden:YES];
635 } 701 }
636 702
637 - (void)showEditableView:(id)sender { 703 - (void)showEditableView:(id)sender {
638 [profileNameTextField_ setHidden:NO]; 704 [profileNameTextField_ setHidden:NO];
639 [[self window] makeFirstResponder:profileNameTextField_]; 705 [[self window] makeFirstResponder:profileNameTextField_];
640 } 706 }
641 707
708 - (BOOL)acceptsFirstResponder {
groby-ooo-7-16 2014/08/15 00:38:35 Technically, a control's -acceptsFirstResponder is
noms (inactive) 2014/08/15 19:26:47 No. I think I just hoped these would make regular
709 return YES;
710 }
711
642 @end 712 @end
643 713
644 // A custom button that allows for setting a background color when hovered over. 714 // A custom button that allows for setting a background color when hovered over.
645 @interface BackgroundColorHoverButton : HoverImageButton { 715 @interface BackgroundColorHoverButton : HoverImageButton {
646 @private 716 @private
647 base::scoped_nsobject<NSColor> backgroundColor_; 717 base::scoped_nsobject<NSColor> backgroundColor_;
648 base::scoped_nsobject<NSColor> hoverColor_; 718 base::scoped_nsobject<NSColor> hoverColor_;
649 } 719 }
650 @end 720 @end
651 721
(...skipping 27 matching lines...) Expand all
679 } 749 }
680 750
681 - (void)setHoverState:(HoverState)state { 751 - (void)setHoverState:(HoverState)state {
682 [super setHoverState:state]; 752 [super setHoverState:state];
683 bool isHighlighted = ([self hoverState] != kHoverStateNone); 753 bool isHighlighted = ([self hoverState] != kHoverStateNone);
684 754
685 NSColor* backgroundColor = isHighlighted ? hoverColor_ : backgroundColor_; 755 NSColor* backgroundColor = isHighlighted ? hoverColor_ : backgroundColor_;
686 [[self cell] setBackgroundColor:backgroundColor]; 756 [[self cell] setBackgroundColor:backgroundColor];
687 } 757 }
688 758
759 - (BOOL)acceptsFirstResponder {
760 return YES;
761 }
762
689 @end 763 @end
690 764
691 // A custom view with the given background color. 765 // A custom view with the given background color.
692 @interface BackgroundColorView : NSView { 766 @interface BackgroundColorView : NSView {
693 @private 767 @private
694 base::scoped_nsobject<NSColor> backgroundColor_; 768 base::scoped_nsobject<NSColor> backgroundColor_;
695 } 769 }
696 @end 770 @end
697 771
698 @implementation BackgroundColorView 772 @implementation BackgroundColorView
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 // If view mode is PROFILE_CHOOSER but there is an auth error, force 1049 // If view mode is PROFILE_CHOOSER but there is an auth error, force
976 // ACCOUNT_MANAGEMENT mode. 1050 // ACCOUNT_MANAGEMENT mode.
977 if (viewMode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER && 1051 if (viewMode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER &&
978 HasAuthError(browser_->profile()) && 1052 HasAuthError(browser_->profile()) &&
979 switches::IsEnableAccountConsistency() && 1053 switches::IsEnableAccountConsistency() &&
980 avatarMenu_->GetItemAt(avatarMenu_->GetActiveProfileIndex()). 1054 avatarMenu_->GetItemAt(avatarMenu_->GetActiveProfileIndex()).
981 signed_in) { 1055 signed_in) {
982 viewMode_ = profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT; 1056 viewMode_ = profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT;
983 } 1057 }
984 1058
1059 [window accessibilitySetOverrideValue:
1060 l10n_util::GetNSString(IDS_PROFILES_NEW_AVATAR_MENU_ACCESSIBLE_NAME)
1061 forAttribute:NSAccessibilityTitleAttribute];
1062 [window accessibilitySetOverrideValue:
1063 l10n_util::GetNSString(IDS_PROFILES_NEW_AVATAR_MENU_ACCESSIBLE_NAME)
1064 forAttribute:NSAccessibilityHelpAttribute];
1065
985 [[self bubble] setAlignment:info_bubble::kAlignRightEdgeToAnchorEdge]; 1066 [[self bubble] setAlignment:info_bubble::kAlignRightEdgeToAnchorEdge];
986 [[self bubble] setArrowLocation:info_bubble::kNoArrow]; 1067 [[self bubble] setArrowLocation:info_bubble::kNoArrow];
987 [[self bubble] setBackgroundColor:GetDialogBackgroundColor()]; 1068 [[self bubble] setBackgroundColor:GetDialogBackgroundColor()];
988 [self initMenuContentsWithView:viewMode_]; 1069 [self initMenuContentsWithView:viewMode_];
989 } 1070 }
990 1071
991 return self; 1072 return self;
992 } 1073 }
993 1074
994 - (void)initMenuContentsWithView:(profiles::BubbleViewMode)viewToDisplay { 1075 - (void)initMenuContentsWithView:(profiles::BubbleViewMode)viewToDisplay {
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 link = [self linkButtonWithTitle:email 1468 link = [self linkButtonWithTitle:email
1388 frameOrigin:rect.origin 1469 frameOrigin:rect.origin
1389 action:nil]; 1470 action:nil];
1390 [link setImage:ui::ResourceBundle::GetSharedInstance(). 1471 [link setImage:ui::ResourceBundle::GetSharedInstance().
1391 GetNativeImageNamed(IDR_ICON_PROFILES_ACCOUNT_BUTTON_ERROR). 1472 GetNativeImageNamed(IDR_ICON_PROFILES_ACCOUNT_BUTTON_ERROR).
1392 ToNSImage()]; 1473 ToNSImage()];
1393 [link setImagePosition:NSImageRight]; 1474 [link setImagePosition:NSImageRight];
1394 [link setTarget:self]; 1475 [link setTarget:self];
1395 [link setAction:@selector(showAccountReauthenticationView:)]; 1476 [link setAction:@selector(showAccountReauthenticationView:)];
1396 [link setTag:kPrimaryProfileTag]; 1477 [link setTag:kPrimaryProfileTag];
1478 [[link cell]
1479 accessibilitySetOverrideValue:l10n_util::GetNSStringF(
1480 IDS_PROFILES_ACCOUNT_BUTTON_AUTH_ERROR_ACCESSIBLE_NAME,
1481 item.sync_state)
1482 forAttribute:NSAccessibilityTitleAttribute];
1397 } else { 1483 } else {
1398 NSTextField* label = BuildLabel(email, rect.origin, nil); 1484 NSTextField* label = BuildLabel(email, rect.origin, nil);
1399 [label setAlignment:NSCenterTextAlignment]; 1485 [label setAlignment:NSCenterTextAlignment];
1400 [label setFrame:rect]; 1486 [label setFrame:rect];
1401 [container addSubview:label]; 1487 [container addSubview:label];
1402 } 1488 }
1403 } 1489 }
1404 // -linkButtonWithTitle sizeToFit's the link, so re-stretch it so that it 1490 // -linkButtonWithTitle sizeToFit's the link, so re-stretch it so that it
1405 // can be centered correctly in the view. 1491 // can be centered correctly in the view.
1406 if (link) { 1492 if (link) {
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
1961 } 2047 }
1962 2048
1963 - (bool)shouldShowGoIncognito { 2049 - (bool)shouldShowGoIncognito {
1964 bool incognitoAvailable = 2050 bool incognitoAvailable =
1965 IncognitoModePrefs::GetAvailability(browser_->profile()->GetPrefs()) != 2051 IncognitoModePrefs::GetAvailability(browser_->profile()->GetPrefs()) !=
1966 IncognitoModePrefs::DISABLED; 2052 IncognitoModePrefs::DISABLED;
1967 return incognitoAvailable && !browser_->profile()->IsGuestSession(); 2053 return incognitoAvailable && !browser_->profile()->IsGuestSession();
1968 } 2054 }
1969 2055
1970 @end 2056 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698