blob: da44d8f36de1588b3044e2520a72c0cfcc9e7281 [file] [log] [blame]
// 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