tray_ime.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/ime/tray_ime.h" 6 7#include <vector> 8 9#include "ash/metrics/user_metrics_recorder.h" 10#include "ash/root_window_controller.h" 11#include "ash/shelf/shelf_widget.h" 12#include "ash/shell.h" 13#include "ash/system/tray/hover_highlight_view.h" 14#include "ash/system/tray/system_tray.h" 15#include "ash/system/tray/system_tray_delegate.h" 16#include "ash/system/tray/system_tray_notifier.h" 17#include "ash/system/tray/tray_constants.h" 18#include "ash/system/tray/tray_details_view.h" 19#include "ash/system/tray/tray_item_more.h" 20#include "ash/system/tray/tray_item_view.h" 21#include "ash/system/tray/tray_utils.h" 22#include "base/logging.h" 23#include "base/strings/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" 33 34namespace ash { 35namespace internal { 36namespace tray { 37 38class IMEDefaultView : public TrayItemMore { 39 public: 40 explicit IMEDefaultView(SystemTrayItem* owner) 41 : TrayItemMore(owner, true) { 42 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 43 44 SetImage(bundle.GetImageNamed( 45 IDR_AURA_UBER_TRAY_IME).ToImageSkia()); 46 47 IMEInfo info; 48 Shell::GetInstance()->system_tray_delegate()->GetCurrentIME(&info); 49 UpdateLabel(info); 50 } 51 52 virtual ~IMEDefaultView() {} 53 54 void UpdateLabel(const IMEInfo& info) { 55 SetLabel(info.name); 56 SetAccessibleName(info.name); 57 } 58 59 private: 60 DISALLOW_COPY_AND_ASSIGN(IMEDefaultView); 61}; 62 63class IMEDetailedView : public TrayDetailsView, 64 public ViewClickListener { 65 public: 66 IMEDetailedView(SystemTrayItem* owner, user::LoginStatus login) 67 : TrayDetailsView(owner), 68 login_(login) { 69 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate(); 70 IMEInfoList list; 71 delegate->GetAvailableIMEList(&list); 72 IMEPropertyInfoList property_list; 73 delegate->GetCurrentIMEProperties(&property_list); 74 Update(list, property_list); 75 } 76 77 virtual ~IMEDetailedView() {} 78 79 void Update(const IMEInfoList& list, 80 const IMEPropertyInfoList& property_list) { 81 Reset(); 82 83 AppendIMEList(list); 84 if (!property_list.empty()) 85 AppendIMEProperties(property_list); 86 if (login_ != user::LOGGED_IN_NONE && login_ != user::LOGGED_IN_LOCKED) 87 AppendSettings(); 88 AppendHeaderEntry(); 89 90 Layout(); 91 SchedulePaint(); 92 } 93 94 private: 95 void AppendHeaderEntry() { 96 CreateSpecialRow(IDS_ASH_STATUS_TRAY_IME, this); 97 } 98 99 void AppendIMEList(const IMEInfoList& list) { 100 ime_map_.clear(); 101 CreateScrollableList(); 102 for (size_t i = 0; i < list.size(); i++) { 103 HoverHighlightView* container = new HoverHighlightView(this); 104 container->AddLabel(list[i].name, 105 list[i].selected ? gfx::Font::BOLD : gfx::Font::NORMAL); 106 scroll_content()->AddChildView(container); 107 ime_map_[container] = list[i].id; 108 } 109 } 110 111 void AppendIMEProperties(const IMEPropertyInfoList& property_list) { 112 property_map_.clear(); 113 for (size_t i = 0; i < property_list.size(); i++) { 114 HoverHighlightView* container = new HoverHighlightView(this); 115 container->AddLabel( 116 property_list[i].name, 117 property_list[i].selected ? gfx::Font::BOLD : gfx::Font::NORMAL); 118 if (i == 0) 119 container->SetBorder(views::Border::CreateSolidSidedBorder( 120 1, 0, 0, 0, kBorderLightColor)); 121 scroll_content()->AddChildView(container); 122 property_map_[container] = property_list[i].key; 123 } 124 } 125 126 void AppendSettings() { 127 HoverHighlightView* container = new HoverHighlightView(this); 128 container->AddLabel(ui::ResourceBundle::GetSharedInstance(). 129 GetLocalizedString(IDS_ASH_STATUS_TRAY_IME_SETTINGS), 130 gfx::Font::NORMAL); 131 AddChildView(container); 132 settings_ = container; 133 } 134 135 // Overridden from ViewClickListener. 136 virtual void OnViewClicked(views::View* sender) OVERRIDE { 137 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate(); 138 if (sender == footer()->content()) { 139 TransitionToDefaultView(); 140 } else if (sender == settings_) { 141 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 142 ash::UMA_STATUS_AREA_IME_SHOW_DETAILED); 143 delegate->ShowIMESettings(); 144 } else { 145 std::map<views::View*, std::string>::const_iterator ime_find; 146 ime_find = ime_map_.find(sender); 147 if (ime_find != ime_map_.end()) { 148 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 149 ash::UMA_STATUS_AREA_IME_SWITCH_MODE); 150 std::string ime_id = ime_find->second; 151 delegate->SwitchIME(ime_id); 152 GetWidget()->Close(); 153 } else { 154 std::map<views::View*, std::string>::const_iterator prop_find; 155 prop_find = property_map_.find(sender); 156 if (prop_find != property_map_.end()) { 157 const std::string key = prop_find->second; 158 delegate->ActivateIMEProperty(key); 159 GetWidget()->Close(); 160 } 161 } 162 } 163 } 164 165 user::LoginStatus login_; 166 167 std::map<views::View*, std::string> ime_map_; 168 std::map<views::View*, std::string> property_map_; 169 views::View* settings_; 170 171 DISALLOW_COPY_AND_ASSIGN(IMEDetailedView); 172}; 173 174} // namespace tray 175 176TrayIME::TrayIME(SystemTray* system_tray) 177 : SystemTrayItem(system_tray), 178 tray_label_(NULL), 179 default_(NULL), 180 detailed_(NULL) { 181 Shell::GetInstance()->system_tray_notifier()->AddIMEObserver(this); 182} 183 184TrayIME::~TrayIME() { 185 Shell::GetInstance()->system_tray_notifier()->RemoveIMEObserver(this); 186} 187 188void TrayIME::UpdateTrayLabel(const IMEInfo& current, size_t count) { 189 if (tray_label_) { 190 bool visible = count > 1; 191 tray_label_->SetVisible(visible); 192 // Do not change label before hiding because this change is noticeable. 193 if (!visible) 194 return; 195 if (current.third_party) { 196 tray_label_->label()->SetText( 197 current.short_name + base::UTF8ToUTF16("*")); 198 } else { 199 tray_label_->label()->SetText(current.short_name); 200 } 201 SetTrayLabelItemBorder(tray_label_, system_tray()->shelf_alignment()); 202 tray_label_->Layout(); 203 } 204} 205 206views::View* TrayIME::CreateTrayView(user::LoginStatus status) { 207 CHECK(tray_label_ == NULL); 208 tray_label_ = new TrayItemView(this); 209 tray_label_->CreateLabel(); 210 SetupLabelForTray(tray_label_->label()); 211 // Hide IME tray when it is created, it will be updated when it is notified 212 // for IME refresh event. 213 tray_label_->SetVisible(false); 214 return tray_label_; 215} 216 217views::View* TrayIME::CreateDefaultView(user::LoginStatus status) { 218 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate(); 219 IMEInfoList list; 220 IMEPropertyInfoList property_list; 221 delegate->GetAvailableIMEList(&list); 222 delegate->GetCurrentIMEProperties(&property_list); 223 if (list.size() <= 1 && property_list.size() <= 1) 224 return NULL; 225 CHECK(default_ == NULL); 226 default_ = new tray::IMEDefaultView(this); 227 return default_; 228} 229 230views::View* TrayIME::CreateDetailedView(user::LoginStatus status) { 231 CHECK(detailed_ == NULL); 232 detailed_ = new tray::IMEDetailedView(this, status); 233 return detailed_; 234} 235 236void TrayIME::DestroyTrayView() { 237 tray_label_ = NULL; 238} 239 240void TrayIME::DestroyDefaultView() { 241 default_ = NULL; 242} 243 244void TrayIME::DestroyDetailedView() { 245 detailed_ = NULL; 246} 247 248void TrayIME::UpdateAfterLoginStatusChange(user::LoginStatus status) { 249} 250 251void TrayIME::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { 252 SetTrayLabelItemBorder(tray_label_, alignment); 253 tray_label_->Layout(); 254} 255 256void TrayIME::OnIMERefresh() { 257 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate(); 258 IMEInfoList list; 259 IMEInfo current; 260 IMEPropertyInfoList property_list; 261 delegate->GetCurrentIME(¤t); 262 delegate->GetAvailableIMEList(&list); 263 delegate->GetCurrentIMEProperties(&property_list); 264 265 UpdateTrayLabel(current, list.size()); 266 267 if (default_) 268 default_->UpdateLabel(current); 269 if (detailed_) 270 detailed_->Update(list, property_list); 271} 272 273} // namespace internal 274} // namespace ash 275