tray_bluetooth.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 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 "ash/system/bluetooth/tray_bluetooth.h"
6
7#include "ash/shell.h"
8#include "ash/system/tray/system_tray.h"
9#include "ash/system/tray/system_tray_delegate.h"
10#include "ash/system/tray/tray_constants.h"
11#include "ash/system/tray/tray_details_view.h"
12#include "ash/system/tray/tray_item_more.h"
13#include "ash/system/tray/tray_views.h"
14#include "grit/ash_resources.h"
15#include "grit/ash_strings.h"
16#include "ui/base/l10n/l10n_util.h"
17#include "ui/base/resource/resource_bundle.h"
18#include "ui/gfx/image/image.h"
19#include "ui/views/controls/image_view.h"
20#include "ui/views/controls/label.h"
21#include "ui/views/layout/box_layout.h"
22
23namespace {
24const int kDeviceListHeight = 276;
25}
26
27namespace ash {
28namespace internal {
29
30namespace tray {
31
32class BluetoothDefaultView : public TrayItemMore {
33 public:
34  explicit BluetoothDefaultView(SystemTrayItem* owner)
35      : TrayItemMore(owner, true) {
36    ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
37    SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_BLUETOOTH).ToImageSkia());
38    UpdateLabel();
39  }
40
41  virtual ~BluetoothDefaultView() {}
42
43  void UpdateLabel() {
44    ash::SystemTrayDelegate* delegate =
45        ash::Shell::GetInstance()->tray_delegate();
46    if (delegate->GetBluetoothAvailable()) {
47      ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
48      SetLabel(rb.GetLocalizedString(delegate->GetBluetoothEnabled() ?
49          IDS_ASH_STATUS_TRAY_BLUETOOTH_ENABLED :
50          IDS_ASH_STATUS_TRAY_BLUETOOTH_DISABLED));
51      SetVisible(true);
52    } else {
53      SetVisible(false);
54    }
55  }
56
57 private:
58  DISALLOW_COPY_AND_ASSIGN(BluetoothDefaultView);
59};
60
61class BluetoothDetailedView : public TrayDetailsView,
62                              public ViewClickListener,
63                              public views::ButtonListener {
64 public:
65  explicit BluetoothDetailedView(user::LoginStatus login)
66      : login_(login),
67        add_device_(NULL),
68        toggle_bluetooth_(NULL) {
69    BluetoothDeviceList list;
70    Shell::GetInstance()->tray_delegate()->GetAvailableBluetoothDevices(&list);
71    Update(list);
72  }
73
74  virtual ~BluetoothDetailedView() {}
75
76  void Update(const BluetoothDeviceList& list) {
77    Reset();
78
79    add_device_ = NULL;
80    toggle_bluetooth_ = NULL;
81
82    AppendDeviceList(list);
83    AppendSettingsEntries();
84    AppendHeaderEntry();
85
86    Layout();
87  }
88
89 private:
90  void AppendHeaderEntry() {
91    CreateSpecialRow(IDS_ASH_STATUS_TRAY_BLUETOOTH, this);
92
93    if (login_ == user::LOGGED_IN_LOCKED)
94      return;
95
96    // Do not allow toggling bluetooth in the lock screen.
97    ash::SystemTrayDelegate* delegate =
98        ash::Shell::GetInstance()->tray_delegate();
99    toggle_bluetooth_ = new TrayPopupHeaderButton(this,
100        IDR_AURA_UBER_TRAY_BLUETOOTH_ENABLED,
101        IDR_AURA_UBER_TRAY_BLUETOOTH_DISABLED,
102        IDR_AURA_UBER_TRAY_BLUETOOTH_ENABLED_HOVER,
103        IDR_AURA_UBER_TRAY_BLUETOOTH_DISABLED_HOVER,
104        IDS_ASH_STATUS_TRAY_BLUETOOTH);
105    toggle_bluetooth_->SetToggled(!delegate->GetBluetoothEnabled());
106    toggle_bluetooth_->SetTooltipText(
107        l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_BLUETOOTH));
108    toggle_bluetooth_->SetToggledTooltipText(
109        l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_BLUETOOTH));
110    footer()->AddButton(toggle_bluetooth_);
111  }
112
113  void AppendDeviceList(const BluetoothDeviceList& list) {
114    device_map_.clear();
115    CreateScrollableList();
116
117    for (size_t i = 0; i < list.size(); i++) {
118      HoverHighlightView* container =
119          AddScrollListItem(list[i].display_name,
120              list[i].connected ? gfx::Font::BOLD : gfx::Font::NORMAL,
121              list[i].connected);
122      device_map_[container] = list[i].address;
123    }
124
125    // Show user Bluetooth state if there is no bluetooth devices in list.
126    if (list.size() == 0) {
127      ash::SystemTrayDelegate* delegate =
128          ash::Shell::GetInstance()->tray_delegate();
129      int message_id;
130      if (delegate->GetBluetoothAvailable()) {
131        if (!delegate->GetBluetoothEnabled())
132          message_id = IDS_ASH_STATUS_TRAY_BLUETOOTH_TURNED_OFF;
133        else if (delegate->IsBluetoothDiscovering())
134          message_id = IDS_ASH_STATUS_TRAY_BLUETOOTH_DISCOVERING;
135        else
136          message_id = IDS_ASH_STATUS_TRAY_BLUETOOTH_NO_DEVICE;
137        AddScrollListItem(l10n_util::GetStringUTF16(message_id),
138                          gfx::Font::NORMAL, false);
139      }
140    }
141  }
142
143  HoverHighlightView* AddScrollListItem(const string16& text,
144                                        gfx::Font::FontStyle style,
145                                        bool checked) {
146    HoverHighlightView* container = new HoverHighlightView(this);
147    container->set_fixed_height(kTrayPopupItemHeight);
148    container->AddCheckableLabel(text, style, checked);
149    scroll_content()->AddChildView(container);
150    return container;
151  }
152
153  // Add settings entries.
154  void AppendSettingsEntries() {
155    // Add bluetooth device requires a browser window, hide it for non logged in
156    // user.
157    if (login_ == user::LOGGED_IN_NONE ||
158        login_ == user::LOGGED_IN_LOCKED)
159      return;
160
161    ash::SystemTrayDelegate* delegate =
162        ash::Shell::GetInstance()->tray_delegate();
163    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
164    HoverHighlightView* container = new HoverHighlightView(this);
165    container->set_fixed_height(kTrayPopupItemHeight);
166    container->AddLabel(rb.GetLocalizedString(
167        IDS_ASH_STATUS_TRAY_BLUETOOTH_ADD_DEVICE), gfx::Font::NORMAL);
168    container->SetEnabled(delegate->GetBluetoothAvailable());
169    AddChildView(container);
170    add_device_ = container;
171  }
172
173  // Overridden from ViewClickListener.
174  virtual void ClickedOn(views::View* sender) OVERRIDE {
175    ash::SystemTrayDelegate* delegate =
176        ash::Shell::GetInstance()->tray_delegate();
177    if (sender == footer()->content()) {
178      Shell::GetInstance()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
179    } else if (sender == add_device_) {
180      if (!delegate->GetBluetoothEnabled())
181        delegate->ToggleBluetooth();
182      delegate->AddBluetoothDevice();
183    } else {
184      std::map<views::View*, std::string>::iterator find;
185      find = device_map_.find(sender);
186      if (find != device_map_.end()) {
187        std::string device_id = find->second;
188        delegate->ToggleBluetoothConnection(device_id);
189      }
190    }
191  }
192
193  // Overridden from ButtonListener.
194  virtual void ButtonPressed(views::Button* sender,
195                             const ui::Event& event) OVERRIDE {
196    ash::SystemTrayDelegate* delegate =
197        ash::Shell::GetInstance()->tray_delegate();
198    if (sender == toggle_bluetooth_)
199      delegate->ToggleBluetooth();
200    else
201      NOTREACHED();
202  }
203
204  user::LoginStatus login_;
205
206  std::map<views::View*, std::string> device_map_;
207  views::View* add_device_;
208  TrayPopupHeaderButton* toggle_bluetooth_;
209  views::View* settings_;
210
211  DISALLOW_COPY_AND_ASSIGN(BluetoothDetailedView);
212};
213
214}  // namespace tray
215
216TrayBluetooth::TrayBluetooth()
217    : default_(NULL),
218      detailed_(NULL) {
219}
220
221TrayBluetooth::~TrayBluetooth() {
222}
223
224views::View* TrayBluetooth::CreateTrayView(user::LoginStatus status) {
225  return NULL;
226}
227
228views::View* TrayBluetooth::CreateDefaultView(user::LoginStatus status) {
229  CHECK(default_ == NULL);
230  default_ = new tray::BluetoothDefaultView(this);
231  return default_;
232}
233
234views::View* TrayBluetooth::CreateDetailedView(user::LoginStatus status) {
235  if (!Shell::GetInstance()->tray_delegate()->GetBluetoothAvailable())
236    return NULL;
237  CHECK(detailed_ == NULL);
238  detailed_ = new tray::BluetoothDetailedView(status);
239  return detailed_;
240}
241
242void TrayBluetooth::DestroyTrayView() {
243}
244
245void TrayBluetooth::DestroyDefaultView() {
246  default_ = NULL;
247}
248
249void TrayBluetooth::DestroyDetailedView() {
250  detailed_ = NULL;
251}
252
253void TrayBluetooth::UpdateAfterLoginStatusChange(user::LoginStatus status) {
254}
255
256void TrayBluetooth::OnBluetoothRefresh() {
257  BluetoothDeviceList list;
258  Shell::GetInstance()->tray_delegate()->GetAvailableBluetoothDevices(&list);
259  if (default_)
260    default_->UpdateLabel();
261  else if (detailed_)
262    detailed_->Update(list);
263}
264
265void TrayBluetooth::OnBluetoothDiscoveringChanged() {
266  if (!detailed_)
267    return;
268  BluetoothDeviceList list;
269  Shell::GetInstance()->tray_delegate()->GetAvailableBluetoothDevices(&list);
270  detailed_->Update(list);
271}
272
273}  // namespace internal
274}  // namespace ash
275