Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 1 | // Copyright 2022 The Chromium Authors |
| 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 "ash/system/phonehub/app_stream_launcher_item.h" |
| 6 | |
Daniel Cheng | 667d190 | 2023-12-01 23:16:32 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 9 | #include "ash/strings/grit/ash_strings.h" |
Daniel Cheng | 667d190 | 2023-12-01 23:16:32 | [diff] [blame] | 10 | #include "base/functional/callback.h" |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 11 | #include "base/hash/hash.h" |
Lei Zhang | c5f765d5 | 2023-11-08 00:53:33 | [diff] [blame] | 12 | #include "base/strings/string_piece.h" |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 13 | #include "base/strings/utf_string_conversions.h" |
| 14 | #include "ui/base/l10n/l10n_util.h" |
Allen Bauer | 912e8ff3 | 2023-11-08 21:13:11 | [diff] [blame] | 15 | #include "ui/base/metadata/metadata_header_macros.h" |
| 16 | #include "ui/base/metadata/metadata_impl_macros.h" |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 17 | #include "ui/gfx/geometry/insets.h" |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 18 | #include "ui/gfx/image/image.h" |
| 19 | #include "ui/gfx/image/image_skia_operations.h" |
Pu Shi | 68350db | 2022-12-05 18:41:03 | [diff] [blame] | 20 | #include "ui/gfx/text_constants.h" |
| 21 | #include "ui/views/border.h" |
| 22 | #include "ui/views/controls/button/label_button.h" |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 23 | #include "ui/views/controls/label.h" |
| 24 | #include "ui/views/layout/box_layout.h" |
| 25 | |
| 26 | namespace ash { |
| 27 | |
| 28 | namespace { |
| 29 | |
Pu Shi | 97ad13a | 2022-11-30 20:08:28 | [diff] [blame] | 30 | constexpr int kEcheAppItemWidth = 50; |
| 31 | constexpr int kEcheAppItemHeight = 60; |
| 32 | constexpr gfx::Size kEcheAppItemSize(kEcheAppItemWidth, kEcheAppItemHeight); |
| 33 | constexpr int kEcheAppItemSpacing = 4; |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 34 | constexpr int kEcheAppNameLabelLineHeight = 14; |
Pu Shi | 97ad13a | 2022-11-30 20:08:28 | [diff] [blame] | 35 | constexpr int kEcheAppNameLabelFontSize = 11; |
Crisrael Lucero | 45d6779 | 2023-05-30 20:57:56 | [diff] [blame] | 36 | constexpr double kAlphaValueForInhibitedIconOpacity = 0.38; |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 37 | |
| 38 | void ConfigureLabel(views::Label* label, int line_height, int font_size) { |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 39 | label->SetLineHeight(line_height); |
Pu Shi | 97ad13a | 2022-11-30 20:08:28 | [diff] [blame] | 40 | label->SetTruncateLength(kEcheAppItemWidth); |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 41 | |
| 42 | gfx::Font default_font; |
| 43 | gfx::Font label_font = |
| 44 | default_font.Derive(font_size - default_font.GetFontSize(), |
| 45 | gfx::Font::NORMAL, gfx::Font::Weight::NORMAL); |
| 46 | gfx::FontList font_list(label_font); |
| 47 | label->SetFontList(font_list); |
| 48 | } |
| 49 | |
Pu Shi | 68350db | 2022-12-05 18:41:03 | [diff] [blame] | 50 | class AppNameLabel : public views::LabelButton { |
Allen Bauer | 912e8ff3 | 2023-11-08 21:13:11 | [diff] [blame] | 51 | METADATA_HEADER(AppNameLabel, views::LabelButton) |
| 52 | |
Pu Shi | 68350db | 2022-12-05 18:41:03 | [diff] [blame] | 53 | public: |
| 54 | explicit AppNameLabel(PressedCallback callback = PressedCallback(), |
| 55 | const std::u16string& text = std::u16string()) |
| 56 | : LabelButton(std::move(callback), text) { |
| 57 | ConfigureLabel(label(), kEcheAppNameLabelLineHeight, |
| 58 | kEcheAppNameLabelFontSize); |
| 59 | SetBorder(views::CreateEmptyBorder(gfx::Insets())); |
| 60 | SetHorizontalAlignment(gfx::ALIGN_CENTER); |
| 61 | } |
| 62 | |
| 63 | ~AppNameLabel() override = default; |
| 64 | AppNameLabel(AppNameLabel&) = delete; |
| 65 | AppNameLabel operator=(AppNameLabel&) = delete; |
| 66 | }; |
| 67 | |
Allen Bauer | 912e8ff3 | 2023-11-08 21:13:11 | [diff] [blame] | 68 | BEGIN_METADATA(AppNameLabel) |
| 69 | END_METADATA |
| 70 | |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 71 | } // namespace |
| 72 | |
| 73 | AppStreamLauncherItem::AppStreamLauncherItem( |
Daniel Cheng | 667d190 | 2023-12-01 23:16:32 | [diff] [blame] | 74 | base::RepeatingClosure callback, |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 75 | const phonehub::Notification::AppMetadata& app_metadata) { |
| 76 | SetPreferredSize(kEcheAppItemSize); |
| 77 | auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( |
| 78 | views::BoxLayout::Orientation::kVertical, gfx::Insets(), |
| 79 | kEcheAppItemSpacing)); |
| 80 | layout->set_cross_axis_alignment( |
| 81 | views::BoxLayout::CrossAxisAlignment::kCenter); |
| 82 | |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 83 | const bool enabled = app_metadata.app_streamability_status == |
| 84 | phonehub::proto::AppStreamabilityStatus::STREAMABLE; |
Crisrael Lucero | 16f9e27 | 2023-04-12 22:21:18 | [diff] [blame] | 85 | gfx::Image image = app_metadata.color_icon; |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 86 | if (!enabled) { |
| 87 | // Fade the image in order to make it look like grayed out. |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 88 | image = gfx::Image(gfx::ImageSkiaOperations::CreateTransparentImage( |
| 89 | image.AsImageSkia(), kAlphaValueForInhibitedIconOpacity)); |
| 90 | } |
| 91 | |
| 92 | std::u16string accessible_name; |
| 93 | switch (app_metadata.app_streamability_status) { |
| 94 | case phonehub::proto::STREAMABLE: |
| 95 | accessible_name = app_metadata.visible_app_name; |
| 96 | break; |
| 97 | case phonehub::proto::BLOCKED_BY_APP: |
| 98 | accessible_name = l10n_util::GetStringUTF16( |
| 99 | IDS_ASH_PHONE_HUB_STREAM_NOT_SUPPORTED_BY_APP); |
| 100 | break; |
| 101 | case phonehub::proto::BLOCK_LISTED: |
| 102 | default: |
| 103 | accessible_name = |
| 104 | l10n_util::GetStringUTF16(IDS_ASH_PHONE_HUB_STREAM_NOT_SUPPORTED); |
| 105 | break; |
| 106 | } |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 107 | recent_app_button_ = AddChildView(std::make_unique<PhoneHubRecentAppButton>( |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 108 | image, app_metadata.visible_app_name, callback)); |
| 109 | recent_app_button_->SetAccessibleName(accessible_name); |
| 110 | recent_app_button_->SetTooltipText(accessible_name); |
| 111 | recent_app_button_->SetEnabled(enabled); |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 112 | |
Daniel Cheng | 667d190 | 2023-12-01 23:16:32 | [diff] [blame] | 113 | label_ = AddChildView(std::make_unique<AppNameLabel>( |
| 114 | std::move(callback), app_metadata.visible_app_name)); |
Abbas Nayebi | b6ad3cc | 2022-12-12 22:04:25 | [diff] [blame] | 115 | label_->SetEnabled(enabled); |
| 116 | label_->SetAccessibleName(accessible_name); |
| 117 | label_->SetTooltipText(accessible_name); |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | AppStreamLauncherItem::~AppStreamLauncherItem() = default; |
| 121 | |
| 122 | bool AppStreamLauncherItem::HasFocus() const { |
| 123 | return recent_app_button_->HasFocus() || label_->HasFocus(); |
| 124 | } |
| 125 | |
| 126 | void AppStreamLauncherItem::RequestFocus() { |
| 127 | recent_app_button_->RequestFocus(); |
| 128 | } |
| 129 | |
Pu Shi | 68350db | 2022-12-05 18:41:03 | [diff] [blame] | 130 | views::LabelButton* AppStreamLauncherItem::GetLabelForTest() { |
Abbas Nayebi | 223ebe8 | 2022-11-29 20:29:34 | [diff] [blame] | 131 | return label_; |
| 132 | } |
| 133 | PhoneHubRecentAppButton* AppStreamLauncherItem::GetIconForTest() { |
| 134 | return recent_app_button_; |
| 135 | } |
| 136 | |
Allen Bauer | 912e8ff3 | 2023-11-08 21:13:11 | [diff] [blame] | 137 | BEGIN_METADATA(AppStreamLauncherItem) |
| 138 | END_METADATA |
| 139 | |
Pu Shi | 5375b53 | 2022-11-17 19:34:39 | [diff] [blame] | 140 | } // namespace ash |