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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/views/profiles/avatar_menu_button.h" 6 7 #include "base/command_line.h" 8 #include "base/prefs/pref_service.h" 9 #include "chrome/browser/browser_process.h" 10 #include "chrome/browser/chrome_notification_types.h" 11 #include "chrome/browser/profiles/avatar_menu.h" 12 #include "chrome/browser/profiles/profile_avatar_icon_util.h" 13 #include "chrome/browser/profiles/profile_metrics.h" 14 #include "chrome/browser/ui/browser.h" 15 #include "chrome/browser/ui/browser_commands.h" 16 #include "chrome/browser/ui/views/frame/browser_view.h" 17 #include "chrome/browser/ui/views/profiles/avatar_menu_bubble_view.h" 18 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h" 19 #include "chrome/common/pref_names.h" 20 #include "components/signin/core/common/profile_management_switches.h" 21 #include "content/public/browser/notification_service.h" 22 #include "ui/gfx/canvas.h" 23 #include "ui/views/view_targeter.h" 24 #include "ui/views/widget/widget.h" 25 26 static inline int Round(double x) { 27 return static_cast<int>(x + 0.5); 28 } 29 30 // static 31 const char AvatarMenuButton::kViewClassName[] = "AvatarMenuButton"; 32 33 AvatarMenuButton::AvatarMenuButton(Browser* browser, bool disabled) 34 : MenuButton(NULL, base::string16(), this, false), 35 browser_(browser), 36 disabled_(disabled), 37 is_rectangle_(false), 38 old_height_(0), 39 button_on_right_(false) { 40 // In RTL mode, the avatar icon should be looking the opposite direction. 41 EnableCanvasFlippingForRTLUI(true); 42 43 SetEventTargeter( 44 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); 45 } 46 47 AvatarMenuButton::~AvatarMenuButton() { 48 } 49 50 const char* AvatarMenuButton::GetClassName() const { 51 return kViewClassName; 52 } 53 54 void AvatarMenuButton::OnPaint(gfx::Canvas* canvas) { 55 if (!icon_.get()) 56 return; 57 58 if (old_height_ != height() || button_icon_.isNull()) { 59 old_height_ = height(); 60 button_icon_ = *profiles::GetAvatarIconForTitleBar( 61 *icon_, is_rectangle_, width(), height()).ToImageSkia(); 62 } 63 64 // Scale the image to fit the width of the button. 65 int dst_width = std::min(button_icon_.width(), width()); 66 // Truncate rather than rounding, so that for odd widths we put the extra 67 // pixel on the left. 68 int dst_x = (width() - dst_width) / 2; 69 70 // Scale the height and maintain aspect ratio. This means that the 71 // icon may not fit in the view. That's ok, we just vertically center it. 72 float scale = 73 static_cast<float>(dst_width) / static_cast<float>(button_icon_.width()); 74 // Round here so that we minimize the aspect ratio drift. 75 int dst_height = Round(button_icon_.height() * scale); 76 // Round rather than truncating, so that for odd heights we select an extra 77 // pixel below the image center rather than above. This is because the 78 // incognito image has shadows at the top that make the apparent center below 79 // the real center. 80 int dst_y = Round((height() - dst_height) / 2.0); 81 canvas->DrawImageInt(button_icon_, 0, 0, button_icon_.width(), 82 button_icon_.height(), dst_x, dst_y, dst_width, dst_height, false); 83 } 84 85 void AvatarMenuButton::SetAvatarIcon(const gfx::Image& icon, 86 bool is_rectangle) { 87 icon_.reset(new gfx::Image(icon)); 88 button_icon_ = gfx::ImageSkia(); 89 is_rectangle_ = is_rectangle; 90 SchedulePaint(); 91 } 92 93 // views::ViewTargeterDelegate: 94 bool AvatarMenuButton::DoesIntersectRect(const views::View* target, 95 const gfx::Rect& rect) const { 96 CHECK_EQ(target, this); 97 return !disabled_ && 98 views::ViewTargeterDelegate::DoesIntersectRect(target, rect); 99 } 100 101 // views::MenuButtonListener implementation 102 void AvatarMenuButton::OnMenuButtonClicked(views::View* source, 103 const gfx::Point& point) { 104 if (!disabled_) 105 chrome::ShowAvatarMenu(browser_); 106 } 107