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/widget/widget.h" 24 25 static inline int Round(double x) { 26 return static_cast<int>(x + 0.5); 27 } 28 29 // static 30 const char AvatarMenuButton::kViewClassName[] = "AvatarMenuButton"; 31 32 AvatarMenuButton::AvatarMenuButton(Browser* browser, bool disabled) 33 : MenuButton(NULL, base::string16(), this, false), 34 browser_(browser), 35 disabled_(disabled), 36 is_rectangle_(false), 37 old_height_(0) { 38 // In RTL mode, the avatar icon should be looking the opposite direction. 39 EnableCanvasFlippingForRTLUI(true); 40 } 41 42 AvatarMenuButton::~AvatarMenuButton() { 43 } 44 45 const char* AvatarMenuButton::GetClassName() const { 46 return kViewClassName; 47 } 48 49 void AvatarMenuButton::OnPaint(gfx::Canvas* canvas) { 50 if (!icon_.get()) 51 return; 52 53 if (old_height_ != height() || button_icon_.isNull()) { 54 old_height_ = height(); 55 button_icon_ = *profiles::GetAvatarIconForTitleBar( 56 *icon_, is_rectangle_, width(), height()).ToImageSkia(); 57 } 58 59 // Scale the image to fit the width of the button. 60 int dst_width = std::min(button_icon_.width(), width()); 61 // Truncate rather than rounding, so that for odd widths we put the extra 62 // pixel on the left. 63 int dst_x = (width() - dst_width) / 2; 64 65 // Scale the height and maintain aspect ratio. This means that the 66 // icon may not fit in the view. That's ok, we just vertically center it. 67 float scale = 68 static_cast<float>(dst_width) / static_cast<float>(button_icon_.width()); 69 // Round here so that we minimize the aspect ratio drift. 70 int dst_height = Round(button_icon_.height() * scale); 71 // Round rather than truncating, so that for odd heights we select an extra 72 // pixel below the image center rather than above. This is because the 73 // incognito image has shadows at the top that make the apparent center below 74 // the real center. 75 int dst_y = Round((height() - dst_height) / 2.0); 76 canvas->DrawImageInt(button_icon_, 0, 0, button_icon_.width(), 77 button_icon_.height(), dst_x, dst_y, dst_width, dst_height, false); 78 } 79 80 bool AvatarMenuButton::HitTestRect(const gfx::Rect& rect) const { 81 return !disabled_ && views::MenuButton::HitTestRect(rect); 82 } 83 84 void AvatarMenuButton::SetAvatarIcon(const gfx::Image& icon, 85 bool is_rectangle) { 86 icon_.reset(new gfx::Image(icon)); 87 button_icon_ = gfx::ImageSkia(); 88 is_rectangle_ = is_rectangle; 89 SchedulePaint(); 90 } 91 92 // views::MenuButtonListener implementation 93 void AvatarMenuButton::OnMenuButtonClicked(views::View* source, 94 const gfx::Point& point) { 95 if (!disabled_) 96 chrome::ShowAvatarMenu(browser_); 97 } 98