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.h"
9 #include "ash/root_window_controller.h"
10 #include "ash/shelf/shelf_widget.h"
11 #include "ash/shell.h"
12 #include "ash/system/tray/hover_highlight_view.h"
13 #include "ash/system/tray/system_tray.h"
14 #include "ash/system/tray/system_tray_delegate.h"
15 #include "ash/system/tray/system_tray_notifier.h"
16 #include "ash/system/tray/tray_constants.h"
17 #include "ash/system/tray/tray_details_view.h"
18 #include "ash/system/tray/tray_item_more.h"
19 #include "ash/system/tray/tray_item_view.h"
20 #include "ash/system/tray/tray_notification_view.h"
21 #include "base/logging.h"
22 #include "base/timer.h"
23 #include "base/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"
39 class IMEDefaultView
: public TrayItemMore
{
41 explicit IMEDefaultView(SystemTrayItem
* owner
)
42 : TrayItemMore(owner
, true) {
43 ui::ResourceBundle
& bundle
= ui::ResourceBundle::GetSharedInstance();
45 SetImage(bundle
.GetImageNamed(
46 IDR_AURA_UBER_TRAY_IME
).ToImageSkia());
49 Shell::GetInstance()->system_tray_delegate()->GetCurrentIME(&info
);
53 virtual ~IMEDefaultView() {}
55 void UpdateLabel(const IMEInfo
& info
) {
57 SetAccessibleName(info
.name
);
61 DISALLOW_COPY_AND_ASSIGN(IMEDefaultView
);
64 class IMEDetailedView
: public TrayDetailsView
,
65 public ViewClickListener
{
67 IMEDetailedView(SystemTrayItem
* owner
, user::LoginStatus login
)
68 : TrayDetailsView(owner
),
70 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
72 delegate
->GetAvailableIMEList(&list
);
73 IMEPropertyInfoList property_list
;
74 delegate
->GetCurrentIMEProperties(&property_list
);
75 Update(list
, property_list
);
78 virtual ~IMEDetailedView() {}
80 void Update(const IMEInfoList
& list
,
81 const IMEPropertyInfoList
& property_list
) {
85 if (!property_list
.empty())
86 AppendIMEProperties(property_list
);
87 if (login_
!= user::LOGGED_IN_NONE
&& login_
!= user::LOGGED_IN_LOCKED
)
96 void AppendHeaderEntry() {
97 CreateSpecialRow(IDS_ASH_STATUS_TRAY_IME
, this);
100 void AppendIMEList(const IMEInfoList
& list
) {
102 CreateScrollableList();
103 for (size_t i
= 0; i
< list
.size(); i
++) {
104 HoverHighlightView
* container
= new HoverHighlightView(this);
105 container
->AddLabel(list
[i
].name
,
106 list
[i
].selected
? gfx::Font::BOLD
: gfx::Font::NORMAL
);
107 scroll_content()->AddChildView(container
);
108 ime_map_
[container
] = list
[i
].id
;
112 void AppendIMEProperties(const IMEPropertyInfoList
& property_list
) {
113 property_map_
.clear();
114 for (size_t i
= 0; i
< property_list
.size(); i
++) {
115 HoverHighlightView
* container
= new HoverHighlightView(this);
117 property_list
[i
].name
,
118 property_list
[i
].selected
? gfx::Font::BOLD
: gfx::Font::NORMAL
);
120 container
->set_border(views::Border::CreateSolidSidedBorder(1, 0, 0, 0,
122 scroll_content()->AddChildView(container
);
123 property_map_
[container
] = property_list
[i
].key
;
127 void AppendSettings() {
128 HoverHighlightView
* container
= new HoverHighlightView(this);
129 container
->AddLabel(ui::ResourceBundle::GetSharedInstance().
130 GetLocalizedString(IDS_ASH_STATUS_TRAY_IME_SETTINGS
),
132 AddChildView(container
);
133 settings_
= container
;
136 // Overridden from ViewClickListener.
137 virtual void OnViewClicked(views::View
* sender
) OVERRIDE
{
138 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
139 if (sender
== footer()->content()) {
140 owner()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING
);
141 } else if (sender
== settings_
) {
142 delegate
->ShowIMESettings();
144 std::map
<views::View
*, std::string
>::const_iterator ime_find
;
145 ime_find
= ime_map_
.find(sender
);
146 if (ime_find
!= ime_map_
.end()) {
147 std::string ime_id
= ime_find
->second
;
148 delegate
->SwitchIME(ime_id
);
149 GetWidget()->Close();
151 std::map
<views::View
*, std::string
>::const_iterator prop_find
;
152 prop_find
= property_map_
.find(sender
);
153 if (prop_find
!= property_map_
.end()) {
154 const std::string key
= prop_find
->second
;
155 delegate
->ActivateIMEProperty(key
);
156 GetWidget()->Close();
162 user::LoginStatus login_
;
164 std::map
<views::View
*, std::string
> ime_map_
;
165 std::map
<views::View
*, std::string
> property_map_
;
166 views::View
* settings_
;
168 DISALLOW_COPY_AND_ASSIGN(IMEDetailedView
);
171 class IMENotificationView
: public TrayNotificationView
{
173 explicit IMENotificationView(TrayIME
* owner
)
174 : TrayNotificationView(owner
, IDR_AURA_UBER_TRAY_IME
) {
175 InitView(GetLabel());
179 RestartAutoCloseTimer();
180 UpdateView(GetLabel());
183 void StartAutoCloseTimer(int seconds
) {
185 autoclose_delay_
= seconds
;
186 if (autoclose_delay_
) {
187 autoclose_
.Start(FROM_HERE
,
188 base::TimeDelta::FromSeconds(autoclose_delay_
),
189 this, &IMENotificationView::Close
);
193 void StopAutoCloseTimer() {
197 void RestartAutoCloseTimer() {
198 if (autoclose_delay_
)
199 StartAutoCloseTimer(autoclose_delay_
);
202 // Overridden from TrayNotificationView.
203 virtual void OnClickAction() OVERRIDE
{
204 owner()->PopupDetailedView(0, true);
209 owner()->HideNotificationView();
212 views::Label
* GetLabel() {
213 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
215 delegate
->GetCurrentIME(¤t
);
217 // TODO(zork): Use IDS_ASH_STATUS_TRAY_THIRD_PARTY_IME_TURNED_ON_BUBBLE for
219 views::Label
* label
= new views::Label(
220 l10n_util::GetStringFUTF16(
221 IDS_ASH_STATUS_TRAY_IME_TURNED_ON_BUBBLE
,
222 current
.medium_name
));
223 label
->SetMultiLine(true);
224 label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
229 int autoclose_delay_
;
230 base::OneShotTimer
<IMENotificationView
> autoclose_
;
232 DISALLOW_COPY_AND_ASSIGN(IMENotificationView
);
238 TrayIME::TrayIME(SystemTray
* system_tray
)
239 : SystemTrayItem(system_tray
),
244 message_shown_(false) {
245 Shell::GetInstance()->system_tray_notifier()->AddIMEObserver(this);
248 TrayIME::~TrayIME() {
249 Shell::GetInstance()->system_tray_notifier()->RemoveIMEObserver(this);
252 void TrayIME::UpdateTrayLabel(const IMEInfo
& current
, size_t count
) {
254 if (current
.third_party
) {
255 tray_label_
->label()->SetText(current
.short_name
+ UTF8ToUTF16("*"));
257 tray_label_
->label()->SetText(current
.short_name
);
259 tray_label_
->SetVisible(count
> 1);
260 SetTrayLabelItemBorder(tray_label_
, system_tray()->shelf_alignment());
261 tray_label_
->Layout();
265 views::View
* TrayIME::CreateTrayView(user::LoginStatus status
) {
266 CHECK(tray_label_
== NULL
);
267 tray_label_
= new TrayItemView(this);
268 tray_label_
->CreateLabel();
269 SetupLabelForTray(tray_label_
->label());
273 views::View
* TrayIME::CreateDefaultView(user::LoginStatus status
) {
274 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
276 IMEPropertyInfoList property_list
;
277 delegate
->GetAvailableIMEList(&list
);
278 delegate
->GetCurrentIMEProperties(&property_list
);
279 if (list
.size() <= 1 && property_list
.size() <= 1)
281 CHECK(default_
== NULL
);
282 default_
= new tray::IMEDefaultView(this);
286 views::View
* TrayIME::CreateDetailedView(user::LoginStatus status
) {
287 CHECK(detailed_
== NULL
);
288 detailed_
= new tray::IMEDetailedView(this, status
);
292 views::View
* TrayIME::CreateNotificationView(user::LoginStatus status
) {
293 DCHECK(notification_
== NULL
);
294 notification_
= new tray::IMENotificationView(this);
295 notification_
->StartAutoCloseTimer(kTrayPopupAutoCloseDelayForTextInSeconds
);
296 return notification_
;
299 void TrayIME::DestroyTrayView() {
303 void TrayIME::DestroyDefaultView() {
307 void TrayIME::DestroyDetailedView() {
311 void TrayIME::DestroyNotificationView() {
312 notification_
= NULL
;
315 void TrayIME::UpdateAfterLoginStatusChange(user::LoginStatus status
) {
318 void TrayIME::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment
) {
319 SetTrayLabelItemBorder(tray_label_
, alignment
);
322 void TrayIME::OnIMERefresh(bool show_message
) {
323 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
326 IMEPropertyInfoList property_list
;
327 delegate
->GetCurrentIME(¤t
);
328 delegate
->GetAvailableIMEList(&list
);
329 delegate
->GetCurrentIMEProperties(&property_list
);
331 UpdateTrayLabel(current
, list
.size());
334 default_
->UpdateLabel(current
);
336 detailed_
->Update(list
, property_list
);
338 if (list
.size() > 1 && show_message
) {
339 // If the notification is still visible, hide it and clear the flag so it is
342 notification_
->UpdateLabel();
343 } else if (!Shell::GetPrimaryRootWindowController()->shelf()->IsVisible() ||
345 ShowNotificationView();
346 message_shown_
= true;
351 } // namespace internal