1// Copyright (c) 2010 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/chromeos/login/update_view.h"
6
7#include <string>
8
9#include "base/utf_string_conversions.h"
10#include "chrome/browser/chromeos/login/helper.h"
11#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
12#include "chrome/browser/chromeos/login/update_screen.h"
13#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
14#include "grit/chromium_strings.h"
15#include "grit/generated_resources.h"
16#include "ui/base/l10n/l10n_util.h"
17#include "ui/base/resource/resource_bundle.h"
18#include "views/border.h"
19#include "views/controls/label.h"
20#include "views/controls/progress_bar.h"
21#include "views/controls/throbber.h"
22#include "views/focus/focus_manager.h"
23#include "views/widget/widget.h"
24
25using views::Background;
26using views::Label;
27using views::View;
28using views::Widget;
29
30namespace {
31
32// TODO(nkostylev): Switch to GridLayout.
33
34// Y offset for the 'installing updates' label.
35const int kInstallingUpdatesLabelYBottomFromProgressBar = 18;
36// Y offset for the progress bar.
37const int kProgressBarY = 130;
38// Y offset for the 'computer will restart' label.
39const int kRebootLabelYFromProgressBar = 55;
40// Y offset for the 'ESCAPE to skip' label.
41const int kEscapeToSkipLabelY = 48;
42// Progress bar width.
43const int kProgressBarWidth = 420;
44// Progress bar height.
45const int kProgressBarHeight = 18;
46// Horizontal spacing (ex. min left and right margins for label on the screen).
47const int kHorizontalSpacing = 65;
48// Horizontal spacing between spinner and label on the curtain screen.
49const int kBetweenSpacing = 25;
50
51// Label color.
52const SkColor kLabelColor = 0xFF000000;
53const SkColor kSkipLabelColor = 0xFFAA0000;
54const SkColor kManualRebootLabelColor = 0xFFAA0000;
55
56}  // namespace
57
58namespace chromeos {
59
60UpdateView::UpdateView(chromeos::ScreenObserver* observer)
61    : installing_updates_label_(NULL),
62      preparing_updates_label_(NULL),
63      reboot_label_(NULL),
64      manual_reboot_label_(NULL),
65      progress_bar_(NULL),
66      show_curtain_(true),
67      show_manual_reboot_label_(false),
68      show_preparing_updates_label_(false),
69      observer_(observer) {
70}
71
72UpdateView::~UpdateView() {
73}
74
75void UpdateView::Init() {
76  // Use rounded-rect background.
77  views::Painter* painter = chromeos::CreateWizardPainter(
78      &chromeos::BorderDefinition::kScreenBorder);
79  set_background(views::Background::CreateBackgroundPainter(true, painter));
80
81  InitLabel(&installing_updates_label_);
82  InitLabel(&preparing_updates_label_);
83  InitLabel(&reboot_label_);
84  InitLabel(&manual_reboot_label_);
85  preparing_updates_label_->SetVisible(false);
86  manual_reboot_label_->SetVisible(false);
87  manual_reboot_label_->SetColor(kManualRebootLabelColor);
88
89  progress_bar_ = new views::ProgressBar();
90  AddChildView(progress_bar_);
91
92  // Curtain view.
93  InitLabel(&checking_label_);
94  throbber_ = CreateDefaultThrobber();
95  AddChildView(throbber_);
96
97#if !defined(OFFICIAL_BUILD)
98  InitLabel(&escape_to_skip_label_);
99  escape_to_skip_label_->SetColor(kSkipLabelColor);
100  escape_to_skip_label_->SetText(
101      L"Press ESCAPE to skip (Non-official builds only)");
102#endif
103
104  UpdateLocalizedStrings();
105  UpdateVisibility();
106}
107
108void UpdateView::Reset() {
109  progress_bar_->SetProgress(0);
110}
111
112void UpdateView::UpdateLocalizedStrings() {
113  installing_updates_label_->SetText(UTF16ToWide(l10n_util::GetStringFUTF16(
114      IDS_INSTALLING_UPDATE,
115      l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME))));
116  preparing_updates_label_->SetText(
117      UTF16ToWide(l10n_util::GetStringUTF16(IDS_UPDATE_AVAILABLE)));
118  reboot_label_->SetText(
119      UTF16ToWide(l10n_util::GetStringUTF16(IDS_INSTALLING_UPDATE_DESC)));
120  manual_reboot_label_->SetText(
121      UTF16ToWide(l10n_util::GetStringUTF16(IDS_UPDATE_COMPLETED)));
122  checking_label_->SetText(
123      UTF16ToWide(l10n_util::GetStringUTF16(IDS_CHECKING_FOR_UPDATES)));
124}
125
126void UpdateView::AddProgress(int ticks) {
127  progress_bar_->AddProgress(ticks);
128}
129
130void UpdateView::SetProgress(int progress) {
131  progress_bar_->SetProgress(progress);
132}
133
134void UpdateView::ShowManualRebootInfo() {
135  show_manual_reboot_label_ = true;
136  UpdateVisibility();
137}
138
139void UpdateView::ShowPreparingUpdatesInfo(bool visible) {
140  show_preparing_updates_label_ = visible;
141  UpdateVisibility();
142}
143
144void UpdateView::ShowCurtain(bool show_curtain) {
145  if (show_curtain_ != show_curtain) {
146    show_curtain_ = show_curtain;
147    UpdateVisibility();
148  }
149}
150
151// Sets the bounds of the view, placing center of the view at the given
152// coordinates (|x| and |y|).
153static void setViewBounds(views::View* view, int x, int y) {
154  int preferred_width = view->GetPreferredSize().width();
155  int preferred_height = view->GetPreferredSize().height();
156  view->SetBounds(
157      x - preferred_width / 2,
158      y - preferred_height / 2,
159      preferred_width,
160      preferred_height);
161}
162
163void UpdateView::Layout() {
164  int max_width = width() - GetInsets().width() - 2 * kHorizontalSpacing;
165  int right_margin = GetInsets().right() + kHorizontalSpacing;
166  int max_height = height() - GetInsets().height();
167  int vertical_center = GetInsets().top() + max_height / 2;
168
169  installing_updates_label_->SizeToFit(max_width);
170  preparing_updates_label_->SizeToFit(max_width);
171  reboot_label_->SizeToFit(max_width);
172  manual_reboot_label_->SizeToFit(max_width);
173
174  progress_bar_->SetBounds(right_margin,
175                           vertical_center - kProgressBarHeight / 2,
176                           max_width,
177                           kProgressBarHeight);
178
179  installing_updates_label_->SetX(right_margin);
180  installing_updates_label_->SetY(
181      progress_bar_->y() -
182      kInstallingUpdatesLabelYBottomFromProgressBar -
183      installing_updates_label_->height());
184  preparing_updates_label_->SetX(installing_updates_label_->x());
185  preparing_updates_label_->SetY(installing_updates_label_->y());
186  reboot_label_->SetX(right_margin);
187  reboot_label_->SetY(
188      progress_bar_->y() +
189      progress_bar_->height() +
190      kRebootLabelYFromProgressBar);
191  manual_reboot_label_->SetX(reboot_label_->x());
192  manual_reboot_label_->SetY(reboot_label_->y());
193  // Curtain layout is independed.
194  int x_center = width() / 2;
195  int throbber_width = throbber_->GetPreferredSize().width();
196  checking_label_->SizeToFit(max_width - throbber_width - kBetweenSpacing);
197  int checking_label_width = checking_label_->GetPreferredSize().width();
198  int space_half = (kBetweenSpacing + 1) / 2;
199  setViewBounds(
200      throbber_, x_center - checking_label_width / 2 - space_half,
201      vertical_center);
202  setViewBounds(
203      checking_label_, x_center + (throbber_width + 1) / 2 + space_half,
204      vertical_center);
205#if !defined(OFFICIAL_BUILD)
206  escape_to_skip_label_->SizeToFit(max_width);
207  escape_to_skip_label_->SetX(right_margin);
208  escape_to_skip_label_->SetY(kEscapeToSkipLabelY);
209#endif
210  SchedulePaint();
211}
212
213void UpdateView::InitLabel(views::Label** label) {
214  *label = new views::Label();
215  (*label)->SetColor(kLabelColor);
216  (*label)->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
217  (*label)->SetMultiLine(true);
218
219  ResourceBundle& res_bundle = ResourceBundle::GetSharedInstance();
220  gfx::Font label_font = res_bundle.GetFont(ResourceBundle::MediumFont);
221  (*label)->SetFont(label_font);
222
223  AddChildView(*label);
224}
225
226void UpdateView::UpdateVisibility() {
227  installing_updates_label_->SetVisible(!show_curtain_ &&
228                                        !show_manual_reboot_label_ &&
229                                        !show_preparing_updates_label_);
230  preparing_updates_label_->SetVisible(!show_curtain_ &&
231                                       !show_manual_reboot_label_ &&
232                                       show_preparing_updates_label_);
233  reboot_label_->SetVisible(!show_curtain_&& !show_manual_reboot_label_);
234  manual_reboot_label_->SetVisible(!show_curtain_ && show_manual_reboot_label_);
235  progress_bar_->SetVisible(!show_curtain_);
236
237  checking_label_->SetVisible(show_curtain_);
238  throbber_->SetVisible(show_curtain_);
239  if (show_curtain_) {
240    throbber_->Start();
241  } else {
242    throbber_->Stop();
243  }
244}
245
246}  // namespace chromeos
247