1// Copyright 2014 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 "athena/system/public/system_ui.h"
6
7#include "athena/screen/public/screen_manager.h"
8#include "athena/system/background_controller.h"
9#include "athena/system/orientation_controller.h"
10#include "athena/system/power_button_controller.h"
11#include "athena/system/status_icon_container_view.h"
12#include "athena/system/time_view.h"
13#include "athena/util/container_priorities.h"
14#include "athena/util/fill_layout_manager.h"
15#include "base/logging.h"
16#include "base/memory/ref_counted.h"
17#include "base/memory/scoped_ptr.h"
18#include "ui/aura/window.h"
19#include "ui/views/view.h"
20
21namespace athena {
22namespace {
23
24SystemUI* instance = NULL;
25
26// View which positions the TimeView on the left and the StatusIconView on the
27// right.
28class SystemInfoView : public views::View {
29 public:
30  SystemInfoView(SystemUI::ColorScheme color_scheme,
31                 aura::Window* system_modal_container)
32      : time_view_(new TimeView(color_scheme)),
33        status_icon_view_(
34            new StatusIconContainerView(color_scheme, system_modal_container)) {
35    AddChildView(time_view_);
36    AddChildView(status_icon_view_);
37  }
38
39  virtual ~SystemInfoView() {
40  }
41
42  // views::View:
43  virtual gfx::Size GetPreferredSize() const OVERRIDE {
44    // The view should be as wide as its parent view.
45    return gfx::Size(0,
46                     std::max(time_view_->GetPreferredSize().height(),
47                              status_icon_view_->GetPreferredSize().height()));
48  }
49
50  virtual void Layout() OVERRIDE {
51    time_view_->SetBoundsRect(gfx::Rect(time_view_->GetPreferredSize()));
52    gfx::Size status_icon_preferred_size =
53        status_icon_view_->GetPreferredSize();
54    status_icon_view_->SetBoundsRect(
55        gfx::Rect(width() - status_icon_preferred_size.width(),
56                  0,
57                  status_icon_preferred_size.width(),
58                  status_icon_preferred_size.height()));
59  }
60
61  virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE {
62    // Relayout to take into account changes in |status_icon_view_|'s width.
63    // Assume that |time_view_|'s and |status_icon_view_|'s preferred height
64    // does not change.
65    Layout();
66  }
67
68 private:
69  views::View* time_view_;
70  views::View* status_icon_view_;
71
72  DISALLOW_COPY_AND_ASSIGN(SystemInfoView);
73};
74
75class SystemUIImpl : public SystemUI {
76 public:
77  SystemUIImpl(scoped_refptr<base::TaskRunner> blocking_task_runner)
78      : orientation_controller_(new OrientationController()),
79        background_container_(NULL),
80        system_modal_container_(NULL) {
81    orientation_controller_->InitWith(blocking_task_runner);
82  }
83
84  virtual ~SystemUIImpl() {
85    // Stops file watching now if exists. Waiting until message loop shutdon
86    // leads to FilePathWatcher crash.
87    orientation_controller_->Shutdown();
88  }
89
90  void Init() {
91    ScreenManager* screen_manager = ScreenManager::Get();
92    background_container_ = screen_manager->CreateContainer(
93        ScreenManager::ContainerParams("AthenaBackground", CP_BACKGROUND));
94    background_container_->SetLayoutManager(
95        new FillLayoutManager(background_container_));
96    ScreenManager::ContainerParams system_modal_params(
97        "AthenaSystemModalContainer", CP_SYSTEM_MODAL);
98    system_modal_params.can_activate_children = true;
99    system_modal_container_ =
100        screen_manager->CreateContainer(system_modal_params);
101    login_screen_system_modal_container_ = screen_manager->CreateContainer(
102        ScreenManager::ContainerParams("AthenaLoginScreenSystemModalContainer",
103                                       CP_LOGIN_SCREEN_SYSTEM_MODAL));
104
105    // Use |login_screen_system_modal_container_| for the power button's dialog
106    // because it needs to show over the login screen.
107    // TODO(pkotwicz): Pick the most appropriate container based on whether the
108    // user has logged in.
109    power_button_controller_.reset(
110        new PowerButtonController(login_screen_system_modal_container_));
111    background_controller_.reset(
112        new BackgroundController(background_container_));
113  }
114
115  virtual void SetBackgroundImage(const gfx::ImageSkia& image) OVERRIDE {
116    background_controller_->SetImage(image);
117  }
118
119  virtual views::View* CreateSystemInfoView(ColorScheme color_scheme) OVERRIDE {
120    return new SystemInfoView(color_scheme, system_modal_container_);
121  }
122
123 private:
124  scoped_ptr<OrientationController> orientation_controller_;
125  scoped_ptr<PowerButtonController> power_button_controller_;
126  scoped_ptr<BackgroundController> background_controller_;
127
128  // The parent container for the background.
129  aura::Window* background_container_;
130
131  // The parent container used by system modal dialogs.
132  aura::Window* system_modal_container_;
133
134  // The parent container used by system modal dialogs when the login screen is
135  // visible.
136  aura::Window* login_screen_system_modal_container_;
137
138  DISALLOW_COPY_AND_ASSIGN(SystemUIImpl);
139};
140
141}  // namespace
142
143// static
144SystemUI* SystemUI::Create(
145    scoped_refptr<base::TaskRunner> blocking_task_runner) {
146  SystemUIImpl* system_ui = new SystemUIImpl(blocking_task_runner);
147  instance = system_ui;
148  system_ui->Init();
149  return instance;
150}
151
152// static
153SystemUI* SystemUI::Get() {
154  DCHECK(instance);
155  return instance;
156}
157
158// static
159void SystemUI::Shutdown() {
160  CHECK(instance);
161  delete instance;
162  instance = NULL;
163}
164
165}  // namespace athena
166