Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / ash / system / ime / tray_ime.cc
blobc931f464cba814ce857841e7c52bf1d1e3a5b679
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.
5 #include "ash/system/ime/tray_ime.h"
7 #include <vector>
9 #include "ash/root_window_controller.h"
10 #include "ash/shelf/shelf_widget.h"
11 #include "ash/shell.h"
12 #include "ash/system/tray/hover_highlight_view.h"
13 #include "ash/system/tray/system_tray.h"
14 #include "ash/system/tray/system_tray_delegate.h"
15 #include "ash/system/tray/system_tray_notifier.h"
16 #include "ash/system/tray/tray_constants.h"
17 #include "ash/system/tray/tray_details_view.h"
18 #include "ash/system/tray/tray_item_more.h"
19 #include "ash/system/tray/tray_item_view.h"
20 #include "ash/system/tray/tray_notification_view.h"
21 #include "base/logging.h"
22 #include "base/timer.h"
23 #include "base/utf_string_conversions.h"
24 #include "grit/ash_resources.h"
25 #include "grit/ash_strings.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/gfx/font.h"
29 #include "ui/gfx/image/image.h"
30 #include "ui/views/controls/label.h"
31 #include "ui/views/layout/box_layout.h"
32 #include "ui/views/widget/widget.h"
34 namespace ash {
35 namespace internal {
37 namespace tray {
39 class IMEDefaultView : public TrayItemMore {
40 public:
41 explicit IMEDefaultView(SystemTrayItem* owner)
42 : TrayItemMore(owner, true) {
43 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
45 SetImage(bundle.GetImageNamed(
46 IDR_AURA_UBER_TRAY_IME).ToImageSkia());
48 IMEInfo info;
49 Shell::GetInstance()->system_tray_delegate()->GetCurrentIME(&info);
50 UpdateLabel(info);
53 virtual ~IMEDefaultView() {}
55 void UpdateLabel(const IMEInfo& info) {
56 SetLabel(info.name);
57 SetAccessibleName(info.name);
60 private:
61 DISALLOW_COPY_AND_ASSIGN(IMEDefaultView);
64 class IMEDetailedView : public TrayDetailsView,
65 public ViewClickListener {
66 public:
67 IMEDetailedView(SystemTrayItem* owner, user::LoginStatus login)
68 : TrayDetailsView(owner),
69 login_(login) {
70 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
71 IMEInfoList list;
72 delegate->GetAvailableIMEList(&list);
73 IMEPropertyInfoList property_list;
74 delegate->GetCurrentIMEProperties(&property_list);
75 Update(list, property_list);
78 virtual ~IMEDetailedView() {}
80 void Update(const IMEInfoList& list,
81 const IMEPropertyInfoList& property_list) {
82 Reset();
84 AppendIMEList(list);
85 if (!property_list.empty())
86 AppendIMEProperties(property_list);
87 if (login_ != user::LOGGED_IN_NONE && login_ != user::LOGGED_IN_LOCKED)
88 AppendSettings();
89 AppendHeaderEntry();
91 Layout();
92 SchedulePaint();
95 private:
96 void AppendHeaderEntry() {
97 CreateSpecialRow(IDS_ASH_STATUS_TRAY_IME, this);
100 void AppendIMEList(const IMEInfoList& list) {
101 ime_map_.clear();
102 CreateScrollableList();
103 for (size_t i = 0; i < list.size(); i++) {
104 HoverHighlightView* container = new HoverHighlightView(this);
105 container->AddLabel(list[i].name,
106 list[i].selected ? gfx::Font::BOLD : gfx::Font::NORMAL);
107 scroll_content()->AddChildView(container);
108 ime_map_[container] = list[i].id;
112 void AppendIMEProperties(const IMEPropertyInfoList& property_list) {
113 property_map_.clear();
114 for (size_t i = 0; i < property_list.size(); i++) {
115 HoverHighlightView* container = new HoverHighlightView(this);
116 container->AddLabel(
117 property_list[i].name,
118 property_list[i].selected ? gfx::Font::BOLD : gfx::Font::NORMAL);
119 if (i == 0)
120 container->set_border(views::Border::CreateSolidSidedBorder(1, 0, 0, 0,
121 kBorderLightColor));
122 scroll_content()->AddChildView(container);
123 property_map_[container] = property_list[i].key;
127 void AppendSettings() {
128 HoverHighlightView* container = new HoverHighlightView(this);
129 container->AddLabel(ui::ResourceBundle::GetSharedInstance().
130 GetLocalizedString(IDS_ASH_STATUS_TRAY_IME_SETTINGS),
131 gfx::Font::NORMAL);
132 AddChildView(container);
133 settings_ = container;
136 // Overridden from ViewClickListener.
137 virtual void OnViewClicked(views::View* sender) OVERRIDE {
138 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
139 if (sender == footer()->content()) {
140 owner()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
141 } else if (sender == settings_) {
142 delegate->ShowIMESettings();
143 } else {
144 std::map<views::View*, std::string>::const_iterator ime_find;
145 ime_find = ime_map_.find(sender);
146 if (ime_find != ime_map_.end()) {
147 std::string ime_id = ime_find->second;
148 delegate->SwitchIME(ime_id);
149 GetWidget()->Close();
150 } else {
151 std::map<views::View*, std::string>::const_iterator prop_find;
152 prop_find = property_map_.find(sender);
153 if (prop_find != property_map_.end()) {
154 const std::string key = prop_find->second;
155 delegate->ActivateIMEProperty(key);
156 GetWidget()->Close();
162 user::LoginStatus login_;
164 std::map<views::View*, std::string> ime_map_;
165 std::map<views::View*, std::string> property_map_;
166 views::View* settings_;
168 DISALLOW_COPY_AND_ASSIGN(IMEDetailedView);
171 class IMENotificationView : public TrayNotificationView {
172 public:
173 explicit IMENotificationView(TrayIME* owner)
174 : TrayNotificationView(owner, IDR_AURA_UBER_TRAY_IME) {
175 InitView(GetLabel());
178 void UpdateLabel() {
179 RestartAutoCloseTimer();
180 UpdateView(GetLabel());
183 void StartAutoCloseTimer(int seconds) {
184 autoclose_.Stop();
185 autoclose_delay_ = seconds;
186 if (autoclose_delay_) {
187 autoclose_.Start(FROM_HERE,
188 base::TimeDelta::FromSeconds(autoclose_delay_),
189 this, &IMENotificationView::Close);
193 void StopAutoCloseTimer() {
194 autoclose_.Stop();
197 void RestartAutoCloseTimer() {
198 if (autoclose_delay_)
199 StartAutoCloseTimer(autoclose_delay_);
202 // Overridden from TrayNotificationView.
203 virtual void OnClickAction() OVERRIDE {
204 owner()->PopupDetailedView(0, true);
207 private:
208 void Close() {
209 owner()->HideNotificationView();
212 views::Label* GetLabel() {
213 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
214 IMEInfo current;
215 delegate->GetCurrentIME(&current);
217 // TODO(zork): Use IDS_ASH_STATUS_TRAY_THIRD_PARTY_IME_TURNED_ON_BUBBLE for
218 // third party IMEs
219 views::Label* label = new views::Label(
220 l10n_util::GetStringFUTF16(
221 IDS_ASH_STATUS_TRAY_IME_TURNED_ON_BUBBLE,
222 current.medium_name));
223 label->SetMultiLine(true);
224 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
225 return label;
229 int autoclose_delay_;
230 base::OneShotTimer<IMENotificationView> autoclose_;
232 DISALLOW_COPY_AND_ASSIGN(IMENotificationView);
236 } // namespace tray
238 TrayIME::TrayIME(SystemTray* system_tray)
239 : SystemTrayItem(system_tray),
240 tray_label_(NULL),
241 default_(NULL),
242 detailed_(NULL),
243 notification_(NULL),
244 message_shown_(false) {
245 Shell::GetInstance()->system_tray_notifier()->AddIMEObserver(this);
248 TrayIME::~TrayIME() {
249 Shell::GetInstance()->system_tray_notifier()->RemoveIMEObserver(this);
252 void TrayIME::UpdateTrayLabel(const IMEInfo& current, size_t count) {
253 if (tray_label_) {
254 if (current.third_party) {
255 tray_label_->label()->SetText(current.short_name + UTF8ToUTF16("*"));
256 } else {
257 tray_label_->label()->SetText(current.short_name);
259 tray_label_->SetVisible(count > 1);
260 SetTrayLabelItemBorder(tray_label_, system_tray()->shelf_alignment());
261 tray_label_->Layout();
265 views::View* TrayIME::CreateTrayView(user::LoginStatus status) {
266 CHECK(tray_label_ == NULL);
267 tray_label_ = new TrayItemView(this);
268 tray_label_->CreateLabel();
269 SetupLabelForTray(tray_label_->label());
270 return tray_label_;
273 views::View* TrayIME::CreateDefaultView(user::LoginStatus status) {
274 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
275 IMEInfoList list;
276 IMEPropertyInfoList property_list;
277 delegate->GetAvailableIMEList(&list);
278 delegate->GetCurrentIMEProperties(&property_list);
279 if (list.size() <= 1 && property_list.size() <= 1)
280 return NULL;
281 CHECK(default_ == NULL);
282 default_ = new tray::IMEDefaultView(this);
283 return default_;
286 views::View* TrayIME::CreateDetailedView(user::LoginStatus status) {
287 CHECK(detailed_ == NULL);
288 detailed_ = new tray::IMEDetailedView(this, status);
289 return detailed_;
292 views::View* TrayIME::CreateNotificationView(user::LoginStatus status) {
293 DCHECK(notification_ == NULL);
294 notification_ = new tray::IMENotificationView(this);
295 notification_->StartAutoCloseTimer(kTrayPopupAutoCloseDelayForTextInSeconds);
296 return notification_;
299 void TrayIME::DestroyTrayView() {
300 tray_label_ = NULL;
303 void TrayIME::DestroyDefaultView() {
304 default_ = NULL;
307 void TrayIME::DestroyDetailedView() {
308 detailed_ = NULL;
311 void TrayIME::DestroyNotificationView() {
312 notification_ = NULL;
315 void TrayIME::UpdateAfterLoginStatusChange(user::LoginStatus status) {
318 void TrayIME::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
319 SetTrayLabelItemBorder(tray_label_, alignment);
322 void TrayIME::OnIMERefresh(bool show_message) {
323 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
324 IMEInfoList list;
325 IMEInfo current;
326 IMEPropertyInfoList property_list;
327 delegate->GetCurrentIME(&current);
328 delegate->GetAvailableIMEList(&list);
329 delegate->GetCurrentIMEProperties(&property_list);
331 UpdateTrayLabel(current, list.size());
333 if (default_)
334 default_->UpdateLabel(current);
335 if (detailed_)
336 detailed_->Update(list, property_list);
338 if (list.size() > 1 && show_message) {
339 // If the notification is still visible, hide it and clear the flag so it is
340 // refreshed.
341 if (notification_) {
342 notification_->UpdateLabel();
343 } else if (!Shell::GetPrimaryRootWindowController()->shelf()->IsVisible() ||
344 !message_shown_) {
345 ShowNotificationView();
346 message_shown_ = true;
351 } // namespace internal
352 } // namespace ash