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(&current);
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