Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / ash / system / ime / tray_ime_chromeos.cc
blob4896a5923e151b9071dd9bb2eb815512aa877196
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_chromeos.h"
7 #include <vector>
9 #include "ash/metrics/user_metrics_recorder.h"
10 #include "ash/root_window_controller.h"
11 #include "ash/session/session_state_delegate.h"
12 #include "ash/shelf/shelf_widget.h"
13 #include "ash/shell.h"
14 #include "ash/system/tray/hover_highlight_view.h"
15 #include "ash/system/tray/system_tray.h"
16 #include "ash/system/tray/system_tray_delegate.h"
17 #include "ash/system/tray/system_tray_notifier.h"
18 #include "ash/system/tray/tray_constants.h"
19 #include "ash/system/tray/tray_details_view.h"
20 #include "ash/system/tray/tray_item_more.h"
21 #include "ash/system/tray/tray_item_view.h"
22 #include "ash/system/tray/tray_utils.h"
23 #include "ash/system/tray_accessibility.h"
24 #include "ash/virtual_keyboard_controller.h"
25 #include "base/logging.h"
26 #include "base/strings/utf_string_conversions.h"
27 #include "grit/ash_resources.h"
28 #include "grit/ash_strings.h"
29 #include "ui/accessibility/ax_enums.h"
30 #include "ui/accessibility/ax_view_state.h"
31 #include "ui/base/resource/resource_bundle.h"
32 #include "ui/gfx/font.h"
33 #include "ui/gfx/image/image.h"
34 #include "ui/keyboard/keyboard_util.h"
35 #include "ui/views/controls/label.h"
36 #include "ui/views/layout/box_layout.h"
37 #include "ui/views/widget/widget.h"
39 namespace ash {
40 namespace tray {
42 // A |HoverHighlightView| that uses bold or normal font depending on whether
43 // it is selected. This view exposes itself as a checkbox to the accessibility
44 // framework.
45 class SelectableHoverHighlightView : public HoverHighlightView {
46 public:
47 SelectableHoverHighlightView(ViewClickListener* listener,
48 const base::string16& label,
49 bool selected)
50 : HoverHighlightView(listener), selected_(selected) {
51 AddLabel(label, gfx::ALIGN_LEFT, selected);
54 ~SelectableHoverHighlightView() override {}
56 protected:
57 // Overridden from views::View.
58 void GetAccessibleState(ui::AXViewState* state) override {
59 HoverHighlightView::GetAccessibleState(state);
60 state->role = ui::AX_ROLE_CHECK_BOX;
61 if (selected_)
62 state->AddStateFlag(ui::AX_STATE_CHECKED);
65 private:
66 bool selected_;
68 DISALLOW_COPY_AND_ASSIGN(SelectableHoverHighlightView);
71 class IMEDefaultView : public TrayItemMore {
72 public:
73 explicit IMEDefaultView(SystemTrayItem* owner, const base::string16& label)
74 : TrayItemMore(owner, true) {
75 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
76 SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_IME).ToImageSkia());
77 UpdateLabel(label);
80 ~IMEDefaultView() override {}
82 void UpdateLabel(const base::string16& label) {
83 SetLabel(label);
84 SetAccessibleName(label);
87 private:
88 DISALLOW_COPY_AND_ASSIGN(IMEDefaultView);
91 class IMEDetailedView : public TrayDetailsView, public ViewClickListener {
92 public:
93 IMEDetailedView(SystemTrayItem* owner,
94 user::LoginStatus login,
95 bool show_keyboard_toggle)
96 : TrayDetailsView(owner), login_(login) {
97 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
98 IMEInfoList list;
99 delegate->GetAvailableIMEList(&list);
100 IMEPropertyInfoList property_list;
101 delegate->GetCurrentIMEProperties(&property_list);
102 Update(list, property_list, show_keyboard_toggle);
105 ~IMEDetailedView() override {}
107 void Update(const IMEInfoList& list,
108 const IMEPropertyInfoList& property_list,
109 bool show_keyboard_toggle) {
110 Reset();
111 ime_map_.clear();
112 property_map_.clear();
113 CreateScrollableList();
115 if (list.size() > 1)
116 AppendIMEList(list);
117 if (!property_list.empty())
118 AppendIMEProperties(property_list);
120 if (show_keyboard_toggle) {
121 if (list.size() > 1 || !property_list.empty())
122 AddScrollSeparator();
123 AppendKeyboardStatus();
126 bool userAddingRunning = ash::Shell::GetInstance()
127 ->session_state_delegate()
128 ->IsInSecondaryLoginScreen();
129 if (login_ != user::LOGGED_IN_NONE && login_ != user::LOGGED_IN_LOCKED &&
130 !userAddingRunning)
131 AppendSettings();
132 AppendHeaderEntry();
134 Layout();
135 SchedulePaint();
138 private:
139 void AppendHeaderEntry() { CreateSpecialRow(IDS_ASH_STATUS_TRAY_IME, this); }
141 // Appends the IMEs to the scrollable area of the detailed view.
142 void AppendIMEList(const IMEInfoList& list) {
143 DCHECK(ime_map_.empty());
144 for (size_t i = 0; i < list.size(); i++) {
145 HoverHighlightView* container = new SelectableHoverHighlightView(
146 this, list[i].name, list[i].selected);
147 scroll_content()->AddChildView(container);
148 ime_map_[container] = list[i].id;
152 // Appends the IME listed to the scrollable area of the detailed
153 // view.
154 void AppendIMEProperties(const IMEPropertyInfoList& property_list) {
155 DCHECK(property_map_.empty());
156 for (size_t i = 0; i < property_list.size(); i++) {
157 HoverHighlightView* container = new SelectableHoverHighlightView(
158 this, property_list[i].name, property_list[i].selected);
159 if (i == 0)
160 container->SetBorder(views::Border::CreateSolidSidedBorder(
161 1, 0, 0, 0, kBorderLightColor));
162 scroll_content()->AddChildView(container);
163 property_map_[container] = property_list[i].key;
167 void AppendKeyboardStatus() {
168 HoverHighlightView* container = new HoverHighlightView(this);
169 int id = keyboard::IsKeyboardEnabled()
170 ? IDS_ASH_STATUS_TRAY_DISABLE_KEYBOARD
171 : IDS_ASH_STATUS_TRAY_ENABLE_KEYBOARD;
172 container->AddLabel(
173 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(id),
174 gfx::ALIGN_LEFT, false /* highlight */);
175 scroll_content()->AddChildView(container);
176 keyboard_status_ = container;
179 void AppendSettings() {
180 HoverHighlightView* container = new HoverHighlightView(this);
181 container->AddLabel(
182 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
183 IDS_ASH_STATUS_TRAY_IME_SETTINGS),
184 gfx::ALIGN_LEFT, false /* highlight */);
185 AddChildView(container);
186 settings_ = container;
189 // Overridden from ViewClickListener.
190 void OnViewClicked(views::View* sender) override {
191 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
192 if (sender == footer()->content()) {
193 TransitionToDefaultView();
194 } else if (sender == settings_) {
195 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
196 ash::UMA_STATUS_AREA_IME_SHOW_DETAILED);
197 delegate->ShowIMESettings();
198 } else if (sender == keyboard_status_) {
199 Shell::GetInstance()->virtual_keyboard_controller()
200 ->ToggleIgnoreExternalKeyboard();
201 } else {
202 std::map<views::View*, std::string>::const_iterator ime_find;
203 ime_find = ime_map_.find(sender);
204 if (ime_find != ime_map_.end()) {
205 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
206 ash::UMA_STATUS_AREA_IME_SWITCH_MODE);
207 std::string ime_id = ime_find->second;
208 delegate->SwitchIME(ime_id);
209 GetWidget()->Close();
210 } else {
211 std::map<views::View*, std::string>::const_iterator prop_find;
212 prop_find = property_map_.find(sender);
213 if (prop_find != property_map_.end()) {
214 const std::string key = prop_find->second;
215 delegate->ActivateIMEProperty(key);
216 GetWidget()->Close();
222 user::LoginStatus login_;
224 std::map<views::View*, std::string> ime_map_;
225 std::map<views::View*, std::string> property_map_;
226 views::View* settings_;
227 views::View* keyboard_status_;
229 DISALLOW_COPY_AND_ASSIGN(IMEDetailedView);
232 } // namespace tray
234 TrayIME::TrayIME(SystemTray* system_tray)
235 : SystemTrayItem(system_tray),
236 tray_label_(NULL),
237 default_(NULL),
238 detailed_(NULL),
239 keyboard_suppressed_(false) {
240 Shell::GetInstance()->system_tray_notifier()->AddIMEObserver(this);
241 Shell::GetInstance()->system_tray_notifier()->AddVirtualKeyboardObserver(
242 this);
243 Shell::GetInstance()->system_tray_notifier()->AddAccessibilityObserver(this);
246 TrayIME::~TrayIME() {
247 Shell::GetInstance()->system_tray_notifier()->RemoveIMEObserver(this);
248 Shell::GetInstance()->system_tray_notifier()->RemoveAccessibilityObserver(
249 this);
250 Shell::GetInstance()->system_tray_notifier()->RemoveVirtualKeyboardObserver(
251 this);
254 void TrayIME::OnKeyboardSuppressionChanged(bool suppressed) {
255 keyboard_suppressed_ = suppressed;
256 Update();
259 void TrayIME::OnAccessibilityModeChanged(
260 ui::AccessibilityNotificationVisibility notify) {
261 Update();
264 void TrayIME::Update() {
265 UpdateTrayLabel(current_ime_, ime_list_.size());
266 if (default_) {
267 default_->SetVisible(ShouldDefaultViewBeVisible());
268 default_->UpdateLabel(GetDefaultViewLabel(ime_list_.size() > 1));
270 if (detailed_)
271 detailed_->Update(ime_list_, property_list_, ShouldShowKeyboardToggle());
274 void TrayIME::UpdateTrayLabel(const IMEInfo& current, size_t count) {
275 if (tray_label_) {
276 bool visible = count > 1;
277 tray_label_->SetVisible(visible);
278 // Do not change label before hiding because this change is noticeable.
279 if (!visible)
280 return;
281 if (current.third_party) {
282 tray_label_->label()->SetText(current.short_name +
283 base::UTF8ToUTF16("*"));
284 } else {
285 tray_label_->label()->SetText(current.short_name);
287 SetTrayLabelItemBorder(tray_label_, system_tray()->shelf_alignment());
288 tray_label_->Layout();
292 bool TrayIME::ShouldShowKeyboardToggle() {
293 return keyboard_suppressed_ &&
294 !Shell::GetInstance()
295 ->accessibility_delegate()
296 ->IsVirtualKeyboardEnabled();
299 base::string16 TrayIME::GetDefaultViewLabel(bool show_ime_label) {
300 if (show_ime_label) {
301 IMEInfo current;
302 Shell::GetInstance()->system_tray_delegate()->GetCurrentIME(&current);
303 return current.name;
304 } else {
305 // Display virtual keyboard status instead.
306 int id = keyboard::IsKeyboardEnabled()
307 ? IDS_ASH_STATUS_TRAY_KEYBOARD_ENABLED
308 : IDS_ASH_STATUS_TRAY_KEYBOARD_DISABLED;
309 return ui::ResourceBundle::GetSharedInstance().GetLocalizedString(id);
313 views::View* TrayIME::CreateTrayView(user::LoginStatus status) {
314 CHECK(tray_label_ == NULL);
315 tray_label_ = new TrayItemView(this);
316 tray_label_->CreateLabel();
317 SetupLabelForTray(tray_label_->label());
318 // Hide IME tray when it is created, it will be updated when it is notified
319 // of the IME refresh event.
320 tray_label_->SetVisible(false);
321 return tray_label_;
324 views::View* TrayIME::CreateDefaultView(user::LoginStatus status) {
325 CHECK(default_ == NULL);
326 default_ =
327 new tray::IMEDefaultView(this, GetDefaultViewLabel(ime_list_.size() > 1));
328 default_->SetVisible(ShouldDefaultViewBeVisible());
329 return default_;
332 views::View* TrayIME::CreateDetailedView(user::LoginStatus status) {
333 CHECK(detailed_ == NULL);
334 detailed_ =
335 new tray::IMEDetailedView(this, status, ShouldShowKeyboardToggle());
336 return detailed_;
339 void TrayIME::DestroyTrayView() {
340 tray_label_ = NULL;
343 void TrayIME::DestroyDefaultView() {
344 default_ = NULL;
347 void TrayIME::DestroyDetailedView() {
348 detailed_ = NULL;
351 void TrayIME::UpdateAfterLoginStatusChange(user::LoginStatus status) {
354 void TrayIME::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
355 SetTrayLabelItemBorder(tray_label_, alignment);
356 tray_label_->Layout();
359 void TrayIME::OnIMERefresh() {
360 // Caches the current ime state.
361 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
362 ime_list_.clear();
363 property_list_.clear();
364 delegate->GetCurrentIME(&current_ime_);
365 delegate->GetAvailableIMEList(&ime_list_);
366 delegate->GetCurrentIMEProperties(&property_list_);
368 Update();
371 bool TrayIME::ShouldDefaultViewBeVisible() {
372 return ime_list_.size() > 1 || property_list_.size() > 1 ||
373 ShouldShowKeyboardToggle();
376 } // namespace ash