| 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 |