Index: ash/common/system/user/user_card_view.cc |
diff --git a/ash/common/system/user/user_card_view.cc b/ash/common/system/user/user_card_view.cc |
deleted file mode 100644 |
index ff20defe86b522ec68391cabf79198da13e1c853..0000000000000000000000000000000000000000 |
--- a/ash/common/system/user/user_card_view.cc |
+++ /dev/null |
@@ -1,470 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "ash/common/system/user/user_card_view.h" |
- |
-#include <algorithm> |
-#include <memory> |
-#include <vector> |
- |
-#include "ash/common/ash_view_ids.h" |
-#include "ash/common/login_status.h" |
-#include "ash/common/media_controller.h" |
-#include "ash/common/session/session_state_delegate.h" |
-#include "ash/common/system/tray/system_tray_controller.h" |
-#include "ash/common/system/tray/system_tray_delegate.h" |
-#include "ash/common/system/tray/tray_constants.h" |
-#include "ash/common/system/tray/tray_popup_item_style.h" |
-#include "ash/common/system/user/rounded_image_view.h" |
-#include "ash/common/wm_shell.h" |
-#include "ash/resources/vector_icons/vector_icons.h" |
-#include "ash/strings/grit/ash_strings.h" |
-#include "base/i18n/rtl.h" |
-#include "base/memory/ptr_util.h" |
-#include "base/strings/string16.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "components/user_manager/user_info.h" |
-#include "ui/accessibility/ax_node_data.h" |
-#include "ui/base/l10n/l10n_util.h" |
-#include "ui/compositor/compositing_recorder.h" |
-#include "ui/gfx/canvas.h" |
-#include "ui/gfx/color_palette.h" |
-#include "ui/gfx/geometry/insets.h" |
-#include "ui/gfx/geometry/rect.h" |
-#include "ui/gfx/geometry/size.h" |
-#include "ui/gfx/paint_vector_icon.h" |
-#include "ui/gfx/range/range.h" |
-#include "ui/gfx/render_text.h" |
-#include "ui/gfx/text_elider.h" |
-#include "ui/gfx/text_utils.h" |
-#include "ui/views/border.h" |
-#include "ui/views/controls/image_view.h" |
-#include "ui/views/controls/link.h" |
-#include "ui/views/controls/link_listener.h" |
-#include "ui/views/layout/box_layout.h" |
- |
-namespace ash { |
-namespace tray { |
- |
-namespace { |
- |
-const int kUserDetailsVerticalPadding = 5; |
- |
-// The invisible word joiner character, used as a marker to indicate the start |
-// and end of the user's display name in the public account user card's text. |
-const base::char16 kDisplayNameMark[] = {0x2060, 0}; |
- |
-views::View* CreateUserAvatarView(LoginStatus login_status, int user_index) { |
- RoundedImageView* image_view = new RoundedImageView(kTrayItemSize / 2); |
- if (login_status == LoginStatus::GUEST) { |
- gfx::ImageSkia icon = |
- gfx::CreateVectorIcon(kSystemMenuGuestIcon, kMenuIconColor); |
- image_view->SetImage(icon, icon.size()); |
- } else { |
- SessionStateDelegate* delegate = WmShell::Get()->GetSessionStateDelegate(); |
- image_view->SetImage(delegate->GetUserInfo(user_index)->GetImage(), |
- gfx::Size(kTrayItemSize, kTrayItemSize)); |
- } |
- |
- image_view->SetBorder(views::CreateEmptyBorder(gfx::Insets( |
- (kTrayPopupItemMinStartWidth - image_view->GetPreferredSize().width()) / |
- 2))); |
- return image_view; |
-} |
- |
-// The user details shown in public account mode. This is essentially a label |
-// but with custom painting code as the text is styled with multiple colors and |
-// contains a link. |
-class PublicAccountUserDetails : public views::View, |
- public views::LinkListener { |
- public: |
- PublicAccountUserDetails(int max_width); |
- ~PublicAccountUserDetails() override; |
- |
- private: |
- // Overridden from views::View. |
- void Layout() override; |
- gfx::Size GetPreferredSize() const override; |
- void OnPaint(gfx::Canvas* canvas) override; |
- void GetAccessibleNodeData(ui::AXNodeData* node_data) override; |
- |
- // Overridden from views::LinkListener. |
- void LinkClicked(views::Link* source, int event_flags) override; |
- |
- // Calculate a preferred size that ensures the label text and the following |
- // link do not wrap over more than three lines in total for aesthetic reasons |
- // if possible. |
- void CalculatePreferredSize(); |
- |
- base::string16 text_; |
- views::Link* learn_more_; |
- gfx::Size preferred_size_; |
- std::vector<std::unique_ptr<gfx::RenderText>> lines_; |
- |
- DISALLOW_COPY_AND_ASSIGN(PublicAccountUserDetails); |
-}; |
- |
-PublicAccountUserDetails::PublicAccountUserDetails(int max_width) |
- : learn_more_(NULL) { |
- const int inner_padding = |
- kTrayPopupPaddingHorizontal - kTrayPopupPaddingBetweenItems; |
- const bool rtl = base::i18n::IsRTL(); |
- SetBorder(views::CreateEmptyBorder( |
- kUserDetailsVerticalPadding, rtl ? 0 : inner_padding, |
- kUserDetailsVerticalPadding, rtl ? inner_padding : 0)); |
- |
- // Retrieve the user's display name and wrap it with markers. |
- // Note that since this is a public account it always has to be the primary |
- // user. |
- base::string16 display_name = WmShell::Get() |
- ->GetSessionStateDelegate() |
- ->GetUserInfo(0) |
- ->GetDisplayName(); |
- base::RemoveChars(display_name, kDisplayNameMark, &display_name); |
- display_name = kDisplayNameMark[0] + display_name + kDisplayNameMark[0]; |
- // Retrieve the domain managing the device and wrap it with markers. |
- base::string16 domain = base::UTF8ToUTF16( |
- WmShell::Get()->system_tray_delegate()->GetEnterpriseDomain()); |
- base::RemoveChars(domain, kDisplayNameMark, &domain); |
- base::i18n::WrapStringWithLTRFormatting(&domain); |
- // Retrieve the label text, inserting the display name and domain. |
- text_ = l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_PUBLIC_LABEL, |
- display_name, domain); |
- |
- learn_more_ = new views::Link(l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE)); |
- learn_more_->SetUnderline(false); |
- learn_more_->set_listener(this); |
- AddChildView(learn_more_); |
- |
- CalculatePreferredSize(); |
-} |
- |
-PublicAccountUserDetails::~PublicAccountUserDetails() {} |
- |
-void PublicAccountUserDetails::Layout() { |
- lines_.clear(); |
- const gfx::Rect contents_area = GetContentsBounds(); |
- if (contents_area.IsEmpty()) |
- return; |
- |
- // Word-wrap the label text. |
- const gfx::FontList font_list; |
- std::vector<base::string16> lines; |
- gfx::ElideRectangleText(text_, font_list, contents_area.width(), |
- contents_area.height(), gfx::ELIDE_LONG_WORDS, |
- &lines); |
- // Loop through the lines, creating a renderer for each. |
- gfx::Point position = contents_area.origin(); |
- gfx::Range display_name(gfx::Range::InvalidRange()); |
- for (auto it = lines.begin(); it != lines.end(); ++it) { |
- auto line = base::WrapUnique(gfx::RenderText::CreateInstance()); |
- line->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_UI); |
- line->SetText(*it); |
- const gfx::Size size(contents_area.width(), line->GetStringSize().height()); |
- line->SetDisplayRect(gfx::Rect(position, size)); |
- position.set_y(position.y() + size.height()); |
- |
- // Set the default text color for the line. |
- line->SetColor(kPublicAccountUserCardTextColor); |
- |
- // If a range of the line contains the user's display name, apply a custom |
- // text color to it. |
- if (display_name.is_empty()) |
- display_name.set_start(it->find(kDisplayNameMark)); |
- if (!display_name.is_empty()) { |
- display_name.set_end( |
- it->find(kDisplayNameMark, display_name.start() + 1)); |
- gfx::Range line_range(0, it->size()); |
- line->ApplyColor(kPublicAccountUserCardNameColor, |
- display_name.Intersect(line_range)); |
- // Update the range for the next line. |
- if (display_name.end() >= line_range.end()) |
- display_name.set_start(0); |
- else |
- display_name = gfx::Range::InvalidRange(); |
- } |
- |
- lines_.push_back(std::move(line)); |
- } |
- |
- // Position the link after the label text, separated by a space. If it does |
- // not fit onto the last line of the text, wrap the link onto its own line. |
- const gfx::Size last_line_size = lines_.back()->GetStringSize(); |
- const int space_width = |
- gfx::GetStringWidth(base::ASCIIToUTF16(" "), font_list); |
- const gfx::Size link_size = learn_more_->GetPreferredSize(); |
- if (contents_area.width() - last_line_size.width() >= |
- space_width + link_size.width()) { |
- position.set_x(position.x() + last_line_size.width() + space_width); |
- position.set_y(position.y() - last_line_size.height()); |
- } |
- position.set_y(position.y() - learn_more_->GetInsets().top()); |
- gfx::Rect learn_more_bounds(position, link_size); |
- learn_more_bounds.Intersect(contents_area); |
- if (base::i18n::IsRTL()) { |
- const gfx::Insets insets = GetInsets(); |
- learn_more_bounds.Offset(insets.right() - insets.left(), 0); |
- } |
- learn_more_->SetBoundsRect(learn_more_bounds); |
-} |
- |
-gfx::Size PublicAccountUserDetails::GetPreferredSize() const { |
- return preferred_size_; |
-} |
- |
-void PublicAccountUserDetails::OnPaint(gfx::Canvas* canvas) { |
- for (const auto& line : lines_) |
- line->Draw(canvas); |
- |
- views::View::OnPaint(canvas); |
-} |
- |
-void PublicAccountUserDetails::GetAccessibleNodeData( |
- ui::AXNodeData* node_data) { |
- node_data->role = ui::AX_ROLE_STATIC_TEXT; |
- node_data->SetName(text_); |
-} |
- |
-void PublicAccountUserDetails::LinkClicked(views::Link* source, |
- int event_flags) { |
- DCHECK_EQ(source, learn_more_); |
- WmShell::Get()->system_tray_controller()->ShowPublicAccountInfo(); |
-} |
- |
-void PublicAccountUserDetails::CalculatePreferredSize() { |
- const gfx::FontList font_list; |
- const gfx::Size link_size = learn_more_->GetPreferredSize(); |
- const int space_width = |
- gfx::GetStringWidth(base::ASCIIToUTF16(" "), font_list); |
- const gfx::Insets insets = GetInsets(); |
- int min_width = link_size.width(); |
- int max_width = |
- gfx::GetStringWidth(text_, font_list) + space_width + link_size.width(); |
- |
- // Do a binary search for the minimum width that ensures no more than three |
- // lines are needed. The lower bound is the minimum of the current bubble |
- // width and the width of the link (as no wrapping is permitted inside the |
- // link). The upper bound is the maximum of the largest allowed bubble width |
- // and the sum of the label text and link widths when put on a single line. |
- std::vector<base::string16> lines; |
- while (min_width < max_width) { |
- lines.clear(); |
- const int width = (min_width + max_width) / 2; |
- const bool too_narrow = |
- gfx::ElideRectangleText(text_, font_list, width, INT_MAX, |
- gfx::TRUNCATE_LONG_WORDS, &lines) != 0; |
- int line_count = lines.size(); |
- if (!too_narrow && line_count == 3 && |
- width - gfx::GetStringWidth(lines.back(), font_list) <= |
- space_width + link_size.width()) |
- ++line_count; |
- if (too_narrow || line_count > 3) |
- min_width = width + 1; |
- else |
- max_width = width; |
- } |
- |
- // Calculate the corresponding height and set the preferred size. |
- lines.clear(); |
- gfx::ElideRectangleText(text_, font_list, min_width, INT_MAX, |
- gfx::TRUNCATE_LONG_WORDS, &lines); |
- int line_count = lines.size(); |
- if (min_width - gfx::GetStringWidth(lines.back(), font_list) <= |
- space_width + link_size.width()) { |
- ++line_count; |
- } |
- const int line_height = font_list.GetHeight(); |
- const int link_extra_height = std::max( |
- link_size.height() - learn_more_->GetInsets().top() - line_height, 0); |
- preferred_size_ = |
- gfx::Size(min_width + insets.width(), |
- line_count * line_height + link_extra_height + insets.height()); |
-} |
- |
-} // namespace |
- |
-UserCardView::UserCardView(LoginStatus login_status, |
- int max_width, |
- int user_index) |
- : user_index_(user_index), |
- user_name_(nullptr), |
- media_capture_label_(nullptr), |
- media_capture_icon_(nullptr) { |
- auto* layout = new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, |
- kTrayPopupLabelHorizontalPadding); |
- SetLayoutManager(layout); |
- layout->set_minimum_cross_axis_size(kTrayPopupItemMinHeight); |
- layout->set_cross_axis_alignment( |
- views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); |
- // For active users, the left inset is provided by ActiveUserBorder, which |
- // is necessary to make sure the ripple does not cover that part of the row. |
- // For inactive users, we set the inset here and this causes the ripple to |
- // extend all the way to the edges of the menu. |
- if (!is_active_user()) |
- SetBorder(views::CreateEmptyBorder(0, kMenuExtraMarginFromLeftEdge, 0, 0)); |
- |
- WmShell::Get()->media_controller()->AddObserver(this); |
- |
- if (login_status == LoginStatus::PUBLIC) |
- AddPublicModeUserContent(max_width); |
- else |
- AddUserContent(layout, login_status); |
-} |
- |
-UserCardView::~UserCardView() { |
- WmShell::Get()->media_controller()->RemoveObserver(this); |
-} |
- |
-void UserCardView::PaintChildren(const ui::PaintContext& context) { |
- if (!is_active_user()) { |
- ui::CompositingRecorder alpha(context, 0xFF / 2, true); |
- View::PaintChildren(context); |
- } else { |
- View::PaintChildren(context); |
- } |
-} |
- |
-void UserCardView::GetAccessibleNodeData(ui::AXNodeData* node_data) { |
- node_data->role = ui::AX_ROLE_STATIC_TEXT; |
- std::vector<base::string16> labels; |
- |
- // Construct the name by concatenating descendants' names. |
- std::list<views::View*> descendants; |
- descendants.push_back(this); |
- while (!descendants.empty()) { |
- auto* view = descendants.front(); |
- descendants.pop_front(); |
- if (view != this) { |
- ui::AXNodeData descendant_data; |
- view->GetAccessibleNodeData(&descendant_data); |
- base::string16 label = |
- descendant_data.GetString16Attribute(ui::AX_ATTR_NAME); |
- // If we find a non-empty name, use that and don't descend further into |
- // the tree. |
- if (!label.empty()) { |
- labels.push_back(label); |
- continue; |
- } |
- } |
- |
- // This view didn't have its own name, so look over its children. |
- for (int i = view->child_count() - 1; i >= 0; --i) |
- descendants.push_front(view->child_at(i)); |
- } |
- node_data->SetName(base::JoinString(labels, base::ASCIIToUTF16(" "))); |
-} |
- |
-void UserCardView::OnMediaCaptureChanged( |
- const std::vector<mojom::MediaCaptureState>& capture_states) { |
- if (is_active_user()) |
- return; |
- |
- mojom::MediaCaptureState state = capture_states[user_index_]; |
- int res_id = 0; |
- switch (state) { |
- case mojom::MediaCaptureState::AUDIO_VIDEO: |
- res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO_VIDEO; |
- break; |
- case mojom::MediaCaptureState::AUDIO: |
- res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO; |
- break; |
- case mojom::MediaCaptureState::VIDEO: |
- res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_VIDEO; |
- break; |
- case mojom::MediaCaptureState::NONE: |
- break; |
- } |
- if (res_id) |
- media_capture_label_->SetText(l10n_util::GetStringUTF16(res_id)); |
- media_capture_label_->SetVisible(!!res_id); |
- media_capture_icon_->SetVisible(!!res_id); |
- user_name_->SetVisible(!res_id); |
- Layout(); |
-} |
- |
-void UserCardView::AddPublicModeUserContent(int max_width) { |
- views::View* avatar = CreateUserAvatarView(LoginStatus::PUBLIC, 0); |
- AddChildView(avatar); |
- int details_max_width = max_width - avatar->GetPreferredSize().width() - |
- kTrayPopupPaddingBetweenItems; |
- AddChildView(new PublicAccountUserDetails(details_max_width)); |
-} |
- |
-void UserCardView::AddUserContent(views::BoxLayout* layout, |
- LoginStatus login_status) { |
- AddChildView(CreateUserAvatarView(login_status, user_index_)); |
- SessionStateDelegate* delegate = WmShell::Get()->GetSessionStateDelegate(); |
- base::string16 user_name_string = |
- login_status == LoginStatus::GUEST |
- ? l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_GUEST_LABEL) |
- : delegate->GetUserInfo(user_index_)->GetDisplayName(); |
- user_name_ = new views::Label(user_name_string); |
- user_name_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- TrayPopupItemStyle user_name_style( |
- TrayPopupItemStyle::FontStyle::DEFAULT_VIEW_LABEL); |
- user_name_style.SetupLabel(user_name_); |
- |
- TrayPopupItemStyle user_email_style(TrayPopupItemStyle::FontStyle::CAPTION); |
- // Only the active user's email label is lightened (for the inactive user, the |
- // label starts as black and the entire row is 54% opacity). |
- if (is_active_user()) |
- user_email_style.set_color_style(TrayPopupItemStyle::ColorStyle::INACTIVE); |
- auto* user_email = new views::Label(); |
- base::string16 user_email_string; |
- if (login_status != LoginStatus::GUEST) { |
- user_email_string = |
- WmShell::Get()->system_tray_delegate()->IsUserSupervised() |
- ? l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SUPERVISED_LABEL) |
- : base::UTF8ToUTF16( |
- delegate->GetUserInfo(user_index_)->GetDisplayEmail()); |
- } |
- user_email->SetText(user_email_string); |
- user_email->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- user_email_style.SetupLabel(user_email); |
- user_email->SetVisible(!user_email_string.empty()); |
- user_email->set_collapse_when_hidden(true); |
- |
- views::View* stack_of_labels = new views::View; |
- AddChildView(stack_of_labels); |
- layout->SetFlexForView(stack_of_labels, 1); |
- stack_of_labels->SetLayoutManager( |
- new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); |
- stack_of_labels->AddChildView(user_name_); |
- stack_of_labels->AddChildView(user_email); |
- // The name and email have different font sizes. This border is designed |
- // to make both views take up equal space so the whitespace between them |
- // is centered on the vertical midpoint. |
- int user_email_bottom_pad = user_name_->GetPreferredSize().height() - |
- user_email->GetPreferredSize().height(); |
- user_email->SetBorder( |
- views::CreateEmptyBorder(0, 0, user_email_bottom_pad, 0)); |
- |
- // Only inactive users need media capture indicators. |
- if (!is_active_user()) { |
- media_capture_label_ = new views::Label(); |
- media_capture_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- media_capture_label_->SetBorder( |
- views::CreateEmptyBorder(0, 0, user_email_bottom_pad, 0)); |
- user_email_style.SetupLabel(media_capture_label_); |
- stack_of_labels->AddChildView(media_capture_label_); |
- |
- media_capture_icon_ = new views::ImageView; |
- media_capture_icon_->SetImage( |
- gfx::CreateVectorIcon(kSystemTrayRecordingIcon, gfx::kGoogleRed700)); |
- const int media_capture_width = kTrayPopupItemMinEndWidth; |
- media_capture_icon_->SetBorder(views::CreateEmptyBorder( |
- gfx::Insets(0, (media_capture_width - |
- media_capture_icon_->GetPreferredSize().width()) / |
- 2))); |
- |
- media_capture_icon_->set_id(VIEW_ID_USER_VIEW_MEDIA_INDICATOR); |
- AddChildView(media_capture_icon_); |
- |
- WmShell::Get()->media_controller()->RequestCaptureState(); |
- } |
-} |
- |
-} // namespace tray |
-} // namespace ash |