OLD | NEW |
| (Empty) |
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/common/system/ime/tray_ime_chromeos.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "ash/common/material_design/material_design_controller.h" | |
10 #include "ash/common/session/session_state_delegate.h" | |
11 #include "ash/common/system/tray/hover_highlight_view.h" | |
12 #include "ash/common/system/tray/system_tray.h" | |
13 #include "ash/common/system/tray/system_tray_controller.h" | |
14 #include "ash/common/system/tray/system_tray_delegate.h" | |
15 #include "ash/common/system/tray/system_tray_notifier.h" | |
16 #include "ash/common/system/tray/tray_constants.h" | |
17 #include "ash/common/system/tray/tray_details_view.h" | |
18 #include "ash/common/system/tray/tray_item_more.h" | |
19 #include "ash/common/system/tray/tray_item_view.h" | |
20 #include "ash/common/system/tray/tray_popup_item_style.h" | |
21 #include "ash/common/system/tray/tray_popup_utils.h" | |
22 #include "ash/common/system/tray/tray_utils.h" | |
23 #include "ash/common/system/tray/tri_view.h" | |
24 #include "ash/common/system/tray_accessibility.h" | |
25 #include "ash/common/wm_shell.h" | |
26 #include "ash/resources/grit/ash_resources.h" | |
27 #include "ash/resources/vector_icons/vector_icons.h" | |
28 #include "ash/strings/grit/ash_strings.h" | |
29 #include "base/logging.h" | |
30 #include "base/strings/utf_string_conversions.h" | |
31 #include "ui/accessibility/ax_enums.h" | |
32 #include "ui/accessibility/ax_node_data.h" | |
33 #include "ui/base/l10n/l10n_util.h" | |
34 #include "ui/base/resource/resource_bundle.h" | |
35 #include "ui/gfx/font.h" | |
36 #include "ui/gfx/image/image.h" | |
37 #include "ui/gfx/paint_vector_icon.h" | |
38 #include "ui/keyboard/keyboard_util.h" | |
39 #include "ui/views/controls/image_view.h" | |
40 #include "ui/views/controls/label.h" | |
41 #include "ui/views/layout/box_layout.h" | |
42 #include "ui/views/widget/widget.h" | |
43 | |
44 namespace ash { | |
45 namespace tray { | |
46 | |
47 // A |HoverHighlightView| that uses bold or normal font depending on whether | |
48 // it is selected. This view exposes itself as a checkbox to the accessibility | |
49 // framework. | |
50 class SelectableHoverHighlightView : public HoverHighlightView { | |
51 public: | |
52 SelectableHoverHighlightView(ViewClickListener* listener, | |
53 const base::string16& label, | |
54 bool selected) | |
55 : HoverHighlightView(listener), selected_(selected) { | |
56 AddLabel(label, gfx::ALIGN_LEFT, selected); | |
57 } | |
58 | |
59 ~SelectableHoverHighlightView() override {} | |
60 | |
61 protected: | |
62 // Overridden from views::View. | |
63 void GetAccessibleNodeData(ui::AXNodeData* node_data) override { | |
64 HoverHighlightView::GetAccessibleNodeData(node_data); | |
65 node_data->role = ui::AX_ROLE_CHECK_BOX; | |
66 if (selected_) | |
67 node_data->AddStateFlag(ui::AX_STATE_CHECKED); | |
68 } | |
69 | |
70 private: | |
71 bool selected_; | |
72 | |
73 DISALLOW_COPY_AND_ASSIGN(SelectableHoverHighlightView); | |
74 }; | |
75 | |
76 class IMEDefaultView : public TrayItemMore { | |
77 public: | |
78 IMEDefaultView(SystemTrayItem* owner, const base::string16& label) | |
79 : TrayItemMore(owner) { | |
80 if (MaterialDesignController::IsSystemTrayMenuMaterial()) { | |
81 SetImage(gfx::CreateVectorIcon(kSystemMenuKeyboardIcon, kMenuIconColor)); | |
82 } else { | |
83 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
84 SetImage(*bundle.GetImageNamed(IDR_AURA_UBER_TRAY_IME).ToImageSkia()); | |
85 } | |
86 UpdateLabel(label); | |
87 } | |
88 | |
89 ~IMEDefaultView() override {} | |
90 | |
91 void UpdateLabel(const base::string16& label) { | |
92 SetLabel(label); | |
93 SetAccessibleName(label); | |
94 } | |
95 | |
96 protected: | |
97 // TrayItemMore: | |
98 void UpdateStyle() override { | |
99 TrayItemMore::UpdateStyle(); | |
100 | |
101 if (!MaterialDesignController::IsSystemTrayMenuMaterial()) | |
102 return; | |
103 | |
104 std::unique_ptr<TrayPopupItemStyle> style = CreateStyle(); | |
105 SetImage( | |
106 gfx::CreateVectorIcon(kSystemMenuKeyboardIcon, style->GetIconColor())); | |
107 } | |
108 | |
109 private: | |
110 DISALLOW_COPY_AND_ASSIGN(IMEDefaultView); | |
111 }; | |
112 | |
113 class IMEDetailedView : public ImeListView { | |
114 public: | |
115 IMEDetailedView(SystemTrayItem* owner, LoginStatus login) | |
116 : ImeListView(owner), | |
117 login_(login), | |
118 settings_(nullptr), | |
119 settings_button_(nullptr) {} | |
120 | |
121 ~IMEDetailedView() override {} | |
122 | |
123 void SetImeManagedMessage(base::string16 ime_managed_message) { | |
124 ime_managed_message_ = ime_managed_message; | |
125 } | |
126 | |
127 void Update(const IMEInfoList& list, | |
128 const IMEPropertyInfoList& property_list, | |
129 bool show_keyboard_toggle, | |
130 SingleImeBehavior single_ime_behavior) override { | |
131 ImeListView::Update(list, property_list, show_keyboard_toggle, | |
132 single_ime_behavior); | |
133 if (!MaterialDesignController::IsSystemTrayMenuMaterial() && | |
134 TrayPopupUtils::CanOpenWebUISettings(login_)) { | |
135 AppendSettings(); | |
136 } | |
137 | |
138 CreateTitleRow(IDS_ASH_STATUS_TRAY_IME); | |
139 } | |
140 | |
141 private: | |
142 // ImeListView: | |
143 void HandleViewClicked(views::View* view) override { | |
144 ImeListView::HandleViewClicked(view); | |
145 if (view == settings_) | |
146 ShowSettings(); | |
147 } | |
148 | |
149 void ResetImeListView() override { | |
150 ImeListView::ResetImeListView(); | |
151 settings_button_ = nullptr; | |
152 controlled_setting_icon_ = nullptr; | |
153 } | |
154 | |
155 void HandleButtonPressed(views::Button* sender, | |
156 const ui::Event& event) override { | |
157 ImeListView::HandleButtonPressed(sender, event); | |
158 if (sender == settings_button_) | |
159 ShowSettings(); | |
160 } | |
161 | |
162 void CreateExtraTitleRowButtons() override { | |
163 if (MaterialDesignController::IsSystemTrayMenuMaterial()) { | |
164 if (!ime_managed_message_.empty()) { | |
165 controlled_setting_icon_ = TrayPopupUtils::CreateMainImageView(); | |
166 controlled_setting_icon_->SetImage( | |
167 gfx::CreateVectorIcon(kSystemMenuBusinessIcon, kMenuIconColor)); | |
168 controlled_setting_icon_->SetTooltipText(ime_managed_message_); | |
169 tri_view()->AddView(TriView::Container::END, controlled_setting_icon_); | |
170 } | |
171 | |
172 tri_view()->SetContainerVisible(TriView::Container::END, true); | |
173 settings_button_ = | |
174 CreateSettingsButton(login_, IDS_ASH_STATUS_TRAY_IME_SETTINGS); | |
175 tri_view()->AddView(TriView::Container::END, settings_button_); | |
176 } | |
177 } | |
178 | |
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; | |
187 } | |
188 | |
189 void ShowSettings() { | |
190 WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_IME_SHOW_DETAILED); | |
191 WmShell::Get()->system_tray_controller()->ShowIMESettings(); | |
192 if (owner()->system_tray()) | |
193 owner()->system_tray()->CloseSystemBubble(); | |
194 } | |
195 | |
196 LoginStatus login_; | |
197 | |
198 // Not used in material design. | |
199 views::View* settings_; | |
200 | |
201 // Only used in material design. | |
202 views::Button* settings_button_; | |
203 | |
204 // This icon says that the IMEs are managed by policy. | |
205 views::ImageView* controlled_setting_icon_; | |
206 // If non-empty, a controlled setting icon should be displayed with this | |
207 // string as tooltip. | |
208 base::string16 ime_managed_message_; | |
209 | |
210 DISALLOW_COPY_AND_ASSIGN(IMEDetailedView); | |
211 }; | |
212 | |
213 } // namespace tray | |
214 | |
215 TrayIME::TrayIME(SystemTray* system_tray) | |
216 : SystemTrayItem(system_tray, UMA_IME), | |
217 tray_label_(NULL), | |
218 default_(NULL), | |
219 detailed_(NULL), | |
220 keyboard_suppressed_(false), | |
221 is_visible_(true) { | |
222 SystemTrayNotifier* tray_notifier = WmShell::Get()->system_tray_notifier(); | |
223 tray_notifier->AddVirtualKeyboardObserver(this); | |
224 tray_notifier->AddAccessibilityObserver(this); | |
225 tray_notifier->AddIMEObserver(this); | |
226 } | |
227 | |
228 TrayIME::~TrayIME() { | |
229 SystemTrayNotifier* tray_notifier = WmShell::Get()->system_tray_notifier(); | |
230 tray_notifier->RemoveIMEObserver(this); | |
231 tray_notifier->RemoveAccessibilityObserver(this); | |
232 tray_notifier->RemoveVirtualKeyboardObserver(this); | |
233 } | |
234 | |
235 void TrayIME::OnKeyboardSuppressionChanged(bool suppressed) { | |
236 keyboard_suppressed_ = suppressed; | |
237 Update(); | |
238 } | |
239 | |
240 void TrayIME::OnAccessibilityModeChanged( | |
241 AccessibilityNotificationVisibility notify) { | |
242 Update(); | |
243 } | |
244 | |
245 void TrayIME::Update() { | |
246 UpdateTrayLabel(current_ime_, ime_list_.size()); | |
247 if (default_) { | |
248 default_->SetVisible(ShouldDefaultViewBeVisible()); | |
249 default_->UpdateLabel(GetDefaultViewLabel(ime_list_.size() > 1)); | |
250 } | |
251 if (detailed_) { | |
252 detailed_->SetImeManagedMessage(ime_managed_message_); | |
253 detailed_->Update(ime_list_, property_list_, ShouldShowKeyboardToggle(), | |
254 GetSingleImeBehavior()); | |
255 } | |
256 } | |
257 | |
258 void TrayIME::UpdateTrayLabel(const IMEInfo& current, size_t count) { | |
259 if (tray_label_) { | |
260 bool visible = ShouldShowImeTrayItem(count) && is_visible_; | |
261 tray_label_->SetVisible(visible); | |
262 // Do not change label before hiding because this change is noticeable. | |
263 if (!visible) | |
264 return; | |
265 if (current.third_party) { | |
266 tray_label_->label()->SetText(current.short_name + | |
267 base::UTF8ToUTF16("*")); | |
268 } else { | |
269 tray_label_->label()->SetText(current.short_name); | |
270 } | |
271 SetTrayLabelItemBorder(tray_label_, system_tray()->shelf_alignment()); | |
272 tray_label_->Layout(); | |
273 } | |
274 } | |
275 | |
276 bool TrayIME::ShouldShowKeyboardToggle() { | |
277 return keyboard_suppressed_ && | |
278 !WmShell::Get()->accessibility_delegate()->IsVirtualKeyboardEnabled(); | |
279 } | |
280 | |
281 base::string16 TrayIME::GetDefaultViewLabel(bool show_ime_label) { | |
282 if (show_ime_label) { | |
283 IMEInfo current; | |
284 WmShell::Get()->system_tray_delegate()->GetCurrentIME(¤t); | |
285 return current.name; | |
286 } else { | |
287 // Display virtual keyboard status instead. | |
288 int id = keyboard::IsKeyboardEnabled() | |
289 ? IDS_ASH_STATUS_TRAY_KEYBOARD_ENABLED | |
290 : IDS_ASH_STATUS_TRAY_KEYBOARD_DISABLED; | |
291 return ui::ResourceBundle::GetSharedInstance().GetLocalizedString(id); | |
292 } | |
293 } | |
294 | |
295 views::View* TrayIME::CreateTrayView(LoginStatus status) { | |
296 CHECK(tray_label_ == NULL); | |
297 tray_label_ = new TrayItemView(this); | |
298 tray_label_->CreateLabel(); | |
299 SetupLabelForTray(tray_label_->label()); | |
300 // Hide IME tray when it is created, it will be updated when it is notified | |
301 // of the IME refresh event. | |
302 tray_label_->SetVisible(false); | |
303 return tray_label_; | |
304 } | |
305 | |
306 views::View* TrayIME::CreateDefaultView(LoginStatus status) { | |
307 CHECK(default_ == NULL); | |
308 default_ = new tray::IMEDefaultView( | |
309 this, GetDefaultViewLabel(ShouldShowImeTrayItem(ime_list_.size()))); | |
310 default_->SetVisible(ShouldDefaultViewBeVisible()); | |
311 return default_; | |
312 } | |
313 | |
314 views::View* TrayIME::CreateDetailedView(LoginStatus status) { | |
315 CHECK(detailed_ == NULL); | |
316 detailed_ = new tray::IMEDetailedView(this, status); | |
317 detailed_->SetImeManagedMessage(ime_managed_message_); | |
318 detailed_->Init(ShouldShowKeyboardToggle(), GetSingleImeBehavior()); | |
319 return detailed_; | |
320 } | |
321 | |
322 void TrayIME::DestroyTrayView() { | |
323 tray_label_ = NULL; | |
324 } | |
325 | |
326 void TrayIME::DestroyDefaultView() { | |
327 default_ = NULL; | |
328 } | |
329 | |
330 void TrayIME::DestroyDetailedView() { | |
331 detailed_ = NULL; | |
332 } | |
333 | |
334 void TrayIME::UpdateAfterLoginStatusChange(LoginStatus status) {} | |
335 | |
336 void TrayIME::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { | |
337 SetTrayLabelItemBorder(tray_label_, alignment); | |
338 tray_label_->Layout(); | |
339 } | |
340 | |
341 void TrayIME::OnIMERefresh() { | |
342 // Caches the current ime state. | |
343 SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate(); | |
344 ime_list_.clear(); | |
345 property_list_.clear(); | |
346 delegate->GetCurrentIME(¤t_ime_); | |
347 delegate->GetAvailableIMEList(&ime_list_); | |
348 delegate->GetCurrentIMEProperties(&property_list_); | |
349 ime_managed_message_ = delegate->GetIMEManagedMessage(); | |
350 | |
351 Update(); | |
352 } | |
353 | |
354 void TrayIME::OnIMEMenuActivationChanged(bool is_active) { | |
355 is_visible_ = !is_active; | |
356 if (is_visible_) | |
357 OnIMERefresh(); | |
358 else | |
359 Update(); | |
360 } | |
361 | |
362 bool TrayIME::IsIMEManaged() { | |
363 return !ime_managed_message_.empty(); | |
364 } | |
365 | |
366 bool TrayIME::ShouldDefaultViewBeVisible() { | |
367 return is_visible_ && | |
368 (ShouldShowImeTrayItem(ime_list_.size()) || | |
369 property_list_.size() > 1 || ShouldShowKeyboardToggle()); | |
370 } | |
371 | |
372 bool TrayIME::ShouldShowImeTrayItem(size_t ime_count) { | |
373 // If managed, we want to show the tray icon even if there's only one input | |
374 // method to choose from. | |
375 size_t threshold = IsIMEManaged() ? 1 : 2; | |
376 return ime_count >= threshold; | |
377 } | |
378 | |
379 ImeListView::SingleImeBehavior TrayIME::GetSingleImeBehavior() { | |
380 // If managed, we also want to show a single IME. | |
381 return IsIMEManaged() ? ImeListView::SHOW_SINGLE_IME | |
382 : ImeListView::HIDE_SINGLE_IME; | |
383 } | |
384 | |
385 } // namespace ash | |
OLD | NEW |