| // Copyright 2020 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/ambient/ui/glanceable_info_view.h" |
| |
| #include <memory> |
| #include <string> |
| |
| #include "ash/ambient/model/ambient_backend_model.h" |
| #include "ash/ambient/ui/ambient_view_delegate.h" |
| #include "ash/ambient/ui/ambient_view_ids.h" |
| #include "ash/ambient/util/ambient_util.h" |
| #include "ash/shell.h" |
| #include "ash/strings/grit/ash_strings.h" |
| #include "ash/system/model/clock_model.h" |
| #include "ash/system/model/system_tray_model.h" |
| #include "ash/system/time/time_view.h" |
| #include "ash/system/tray/tray_constants.h" |
| #include "base/i18n/number_formatting.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/metadata/metadata_impl_macros.h" |
| #include "ui/compositor/layer.h" |
| #include "ui/gfx/font_list.h" |
| #include "ui/gfx/geometry/insets.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/image/image_skia_operations.h" |
| #include "ui/views/background.h" |
| #include "ui/views/border.h" |
| #include "ui/views/controls/image_view.h" |
| #include "ui/views/controls/label.h" |
| #include "ui/views/layout/box_layout.h" |
| #include "ui/views/view.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| // Appearance. |
| constexpr int kSpacingBetweenTimeAndWeatherDip = 24; |
| constexpr int kSpacingBetweenWeatherIconAndTempDip = 8; |
| constexpr int kWeatherIconSizeDip = 32; |
| |
| // Typography. |
| constexpr int kDefaultFontSizeDip = 64; |
| constexpr int kWeatherTemperatureFontSizeDip = 32; |
| |
| // Returns the fontlist used for the time text. |
| const gfx::FontList& GetTimeFontList() { |
| return ambient::util::GetDefaultFontlist(); |
| } |
| |
| // Returns the fontlist used for the temperature text. |
| gfx::FontList GetWeatherTemperatureFontList() { |
| int temperature_font_size_delta = |
| kWeatherTemperatureFontSizeDip - kDefaultFontSizeDip; |
| return ambient::util::GetDefaultFontlist().DeriveWithSizeDelta( |
| temperature_font_size_delta); |
| } |
| |
| int GetTimeFontDescent() { |
| return GetTimeFontList().GetHeight() - GetTimeFontList().GetBaseline(); |
| } |
| |
| int GetTemperatureFontDescent() { |
| return GetWeatherTemperatureFontList().GetHeight() - |
| GetWeatherTemperatureFontList().GetBaseline(); |
| } |
| |
| } // namespace |
| |
| GlanceableInfoView::GlanceableInfoView(AmbientViewDelegate* delegate) |
| : delegate_(delegate) { |
| DCHECK(delegate); |
| SetID(AmbientViewID::kAmbientGlanceableInfoView); |
| auto* backend_model = delegate_->GetAmbientBackendModel(); |
| scoped_backend_model_observer_.Observe(backend_model); |
| |
| InitLayout(); |
| |
| if (!backend_model->weather_condition_icon().isNull()) { |
| // already has weather info, show immediately. |
| Show(); |
| } |
| } |
| |
| GlanceableInfoView::~GlanceableInfoView() = default; |
| void GlanceableInfoView::OnWeatherInfoUpdated() { |
| Show(); |
| } |
| |
| void GlanceableInfoView::Show() { |
| AmbientBackendModel* ambient_backend_model = |
| delegate_->GetAmbientBackendModel(); |
| |
| // When ImageView has an |image_| with different size than the |image_size_|, |
| // it will resize and draw the |image_|. The quality is not as good as if we |
| // resize the |image_| to be the same as the |image_size_| with |RESIZE_BEST| |
| // method. |
| gfx::ImageSkia icon = ambient_backend_model->weather_condition_icon(); |
| gfx::ImageSkia icon_resized = gfx::ImageSkiaOperations::CreateResizedImage( |
| icon, skia::ImageOperations::RESIZE_BEST, |
| gfx::Size(kWeatherIconSizeDip, kWeatherIconSizeDip)); |
| weather_condition_icon_->SetImage(icon_resized); |
| |
| temperature_->SetText(GetTemperatureText()); |
| } |
| |
| std::u16string GlanceableInfoView::GetTemperatureText() const { |
| AmbientBackendModel* ambient_backend_model = |
| delegate_->GetAmbientBackendModel(); |
| if (ambient_backend_model->show_celsius()) { |
| return l10n_util::GetStringFUTF16Int( |
| IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_CELSIUS, |
| static_cast<int>(ambient_backend_model->GetTemperatureInCelsius())); |
| } |
| return l10n_util::GetStringFUTF16Int( |
| IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_FAHRENHEIT, |
| static_cast<int>(ambient_backend_model->temperature_fahrenheit())); |
| } |
| |
| void GlanceableInfoView::InitLayout() { |
| // The children of |GlanceableInfoView| will be drawn on their own |
| // layer instead of the layer of |PhotoView| with a solid black background. |
| SetPaintToLayer(); |
| layer()->SetFillsBoundsOpaquely(false); |
| |
| views::BoxLayout* layout = |
| SetLayoutManager(std::make_unique<views::BoxLayout>( |
| views::BoxLayout::Orientation::kHorizontal)); |
| layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kStart); |
| layout->set_cross_axis_alignment(views::BoxLayout::CrossAxisAlignment::kEnd); |
| |
| gfx::ShadowValues text_shadow_values = ambient::util::GetTextShadowValues(); |
| gfx::Insets shadow_insets = gfx::ShadowValue::GetMargin(text_shadow_values); |
| |
| // Inits the time view. |
| time_view_ = AddChildView(std::make_unique<tray::TimeView>( |
| ash::tray::TimeView::ClockLayout::HORIZONTAL_CLOCK, |
| Shell::Get()->system_tray_model()->clock())); |
| time_view_->SetTextFont(GetTimeFontList()); |
| time_view_->SetTextColor( |
| ambient::util::GetContentLayerColor( |
| AshColorProvider::ContentLayerType::kTextColorPrimary), |
| /*auto_color_readability_enabled=*/false); |
| time_view_->SetTextShadowValues(text_shadow_values); |
| // Remove the internal spacing in `time_view_` and adjust spacing for shadows. |
| time_view_->SetBorder(views::CreateEmptyBorder( |
| -kUnifiedTrayTextTopPadding, -kUnifiedTrayTimeLeftPadding, 0, |
| kSpacingBetweenTimeAndWeatherDip + shadow_insets.right())); |
| |
| // Inits the icon view. |
| weather_condition_icon_ = AddChildView(std::make_unique<views::ImageView>()); |
| const gfx::Size size = gfx::Size(kWeatherIconSizeDip, kWeatherIconSizeDip); |
| weather_condition_icon_->SetSize(size); |
| weather_condition_icon_->SetImageSize(size); |
| constexpr int kIconInternalPaddingDip = 4; |
| weather_condition_icon_->SetBorder(views::CreateEmptyBorder( |
| 0, 0, |
| GetTimeFontDescent() - shadow_insets.bottom() - kIconInternalPaddingDip, |
| kSpacingBetweenWeatherIconAndTempDip + shadow_insets.left())); |
| |
| // Inits the temp view. |
| temperature_ = AddChildView(std::make_unique<views::Label>()); |
| temperature_->SetAutoColorReadabilityEnabled(false); |
| temperature_->SetEnabledColor(ambient::util::GetContentLayerColor( |
| AshColorProvider::ContentLayerType::kTextColorPrimary)); |
| temperature_->SetFontList(GetWeatherTemperatureFontList()); |
| temperature_->SetShadows(text_shadow_values); |
| temperature_->SetBorder(views::CreateEmptyBorder( |
| 0, 0, GetTimeFontDescent() - GetTemperatureFontDescent(), 0)); |
| } |
| |
| BEGIN_METADATA(GlanceableInfoView, views::View) |
| END_METADATA |
| |
| } // namespace ash |