avatar_menu_button.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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 26static inline int Round(double x) { 27 return static_cast<int>(x + 0.5); 28} 29 30// static 31const char AvatarMenuButton::kViewClassName[] = "AvatarMenuButton"; 32 33AvatarMenuButton::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 47AvatarMenuButton::~AvatarMenuButton() { 48} 49 50const char* AvatarMenuButton::GetClassName() const { 51 return kViewClassName; 52} 53 54void 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 85void 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: 94bool 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 102void AvatarMenuButton::OnMenuButtonClicked(views::View* source, 103 const gfx::Point& point) { 104 if (!disabled_) 105 chrome::ShowAvatarMenu(browser_); 106} 107