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/metrics/user_metrics_recorder.h"
10 #include "ash/root_window_controller.h"
11 #include "ash/session/session_state_delegate.h"
12 #include "ash/shelf/shelf_widget.h"
13 #include "ash/shell.h"
14 #include "ash/system/tray/hover_highlight_view.h"
15 #include "ash/system/tray/system_tray.h"
16 #include "ash/system/tray/system_tray_delegate.h"
17 #include "ash/system/tray/system_tray_notifier.h"
18 #include "ash/system/tray/tray_constants.h"
19 #include "ash/system/tray/tray_details_view.h"
20 #include "ash/system/tray/tray_item_more.h"
21 #include "ash/system/tray/tray_item_view.h"
22 #include "ash/system/tray/tray_utils.h"
23 #include "base/logging.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "grit/ash_resources.h"
26 #include "grit/ash_strings.h"
27 #include "ui/accessibility/ax_enums.h"
28 #include "ui/accessibility/ax_view_state.h"
29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/gfx/font.h"
31 #include "ui/gfx/image/image.h"
32 #include "ui/views/controls/label.h"
33 #include "ui/views/layout/box_layout.h"
34 #include "ui/views/widget/widget.h"
39 // A |HoverHighlightView| that uses bold or normal font depending on whetehr
40 // it is selected. This view exposes itself as a checkbox to the accessibility
42 class SelectableHoverHighlightView
: public HoverHighlightView
{
44 SelectableHoverHighlightView(ViewClickListener
* listener
,
45 const base::string16
& label
,
47 : HoverHighlightView(listener
), selected_(selected
) {
49 label
, gfx::ALIGN_LEFT
, selected
? gfx::Font::BOLD
: gfx::Font::NORMAL
);
52 virtual ~SelectableHoverHighlightView() {}
55 // Overridden from views::View.
56 virtual void GetAccessibleState(ui::AXViewState
* state
) override
{
57 HoverHighlightView::GetAccessibleState(state
);
58 state
->role
= ui::AX_ROLE_CHECK_BOX
;
60 state
->AddStateFlag(ui::AX_STATE_CHECKED
);
66 DISALLOW_COPY_AND_ASSIGN(SelectableHoverHighlightView
);
69 class IMEDefaultView
: public TrayItemMore
{
71 explicit IMEDefaultView(SystemTrayItem
* owner
)
72 : TrayItemMore(owner
, true) {
73 ui::ResourceBundle
& bundle
= ui::ResourceBundle::GetSharedInstance();
75 SetImage(bundle
.GetImageNamed(
76 IDR_AURA_UBER_TRAY_IME
).ToImageSkia());
79 Shell::GetInstance()->system_tray_delegate()->GetCurrentIME(&info
);
83 virtual ~IMEDefaultView() {}
85 void UpdateLabel(const IMEInfo
& info
) {
87 SetAccessibleName(info
.name
);
91 DISALLOW_COPY_AND_ASSIGN(IMEDefaultView
);
94 class IMEDetailedView
: public TrayDetailsView
,
95 public ViewClickListener
{
97 IMEDetailedView(SystemTrayItem
* owner
, user::LoginStatus login
)
98 : TrayDetailsView(owner
),
100 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
102 delegate
->GetAvailableIMEList(&list
);
103 IMEPropertyInfoList property_list
;
104 delegate
->GetCurrentIMEProperties(&property_list
);
105 Update(list
, property_list
);
108 virtual ~IMEDetailedView() {}
110 void Update(const IMEInfoList
& list
,
111 const IMEPropertyInfoList
& property_list
) {
115 if (!property_list
.empty())
116 AppendIMEProperties(property_list
);
117 bool userAddingRunning
= ash::Shell::GetInstance()
118 ->session_state_delegate()
119 ->IsInSecondaryLoginScreen();
121 if (login_
!= user::LOGGED_IN_NONE
&& login_
!= user::LOGGED_IN_LOCKED
&&
131 void AppendHeaderEntry() {
132 CreateSpecialRow(IDS_ASH_STATUS_TRAY_IME
, this);
135 void AppendIMEList(const IMEInfoList
& list
) {
137 CreateScrollableList();
138 for (size_t i
= 0; i
< list
.size(); i
++) {
139 HoverHighlightView
* container
= new SelectableHoverHighlightView(
140 this, list
[i
].name
, list
[i
].selected
);
141 scroll_content()->AddChildView(container
);
142 ime_map_
[container
] = list
[i
].id
;
146 void AppendIMEProperties(const IMEPropertyInfoList
& property_list
) {
147 property_map_
.clear();
148 for (size_t i
= 0; i
< property_list
.size(); i
++) {
149 HoverHighlightView
* container
= new SelectableHoverHighlightView(
150 this, property_list
[i
].name
, property_list
[i
].selected
);
152 container
->SetBorder(views::Border::CreateSolidSidedBorder(
153 1, 0, 0, 0, kBorderLightColor
));
154 scroll_content()->AddChildView(container
);
155 property_map_
[container
] = property_list
[i
].key
;
159 void AppendSettings() {
160 HoverHighlightView
* container
= new HoverHighlightView(this);
162 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
163 IDS_ASH_STATUS_TRAY_IME_SETTINGS
),
166 AddChildView(container
);
167 settings_
= container
;
170 // Overridden from ViewClickListener.
171 virtual void OnViewClicked(views::View
* sender
) override
{
172 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
173 if (sender
== footer()->content()) {
174 TransitionToDefaultView();
175 } else if (sender
== settings_
) {
176 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
177 ash::UMA_STATUS_AREA_IME_SHOW_DETAILED
);
178 delegate
->ShowIMESettings();
180 std::map
<views::View
*, std::string
>::const_iterator ime_find
;
181 ime_find
= ime_map_
.find(sender
);
182 if (ime_find
!= ime_map_
.end()) {
183 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
184 ash::UMA_STATUS_AREA_IME_SWITCH_MODE
);
185 std::string ime_id
= ime_find
->second
;
186 delegate
->SwitchIME(ime_id
);
187 GetWidget()->Close();
189 std::map
<views::View
*, std::string
>::const_iterator prop_find
;
190 prop_find
= property_map_
.find(sender
);
191 if (prop_find
!= property_map_
.end()) {
192 const std::string key
= prop_find
->second
;
193 delegate
->ActivateIMEProperty(key
);
194 GetWidget()->Close();
200 user::LoginStatus login_
;
202 std::map
<views::View
*, std::string
> ime_map_
;
203 std::map
<views::View
*, std::string
> property_map_
;
204 views::View
* settings_
;
206 DISALLOW_COPY_AND_ASSIGN(IMEDetailedView
);
211 TrayIME::TrayIME(SystemTray
* system_tray
)
212 : SystemTrayItem(system_tray
),
216 Shell::GetInstance()->system_tray_notifier()->AddIMEObserver(this);
219 TrayIME::~TrayIME() {
220 Shell::GetInstance()->system_tray_notifier()->RemoveIMEObserver(this);
223 void TrayIME::UpdateTrayLabel(const IMEInfo
& current
, size_t count
) {
225 bool visible
= count
> 1;
226 tray_label_
->SetVisible(visible
);
227 // Do not change label before hiding because this change is noticeable.
230 if (current
.third_party
) {
231 tray_label_
->label()->SetText(
232 current
.short_name
+ base::UTF8ToUTF16("*"));
234 tray_label_
->label()->SetText(current
.short_name
);
236 SetTrayLabelItemBorder(tray_label_
, system_tray()->shelf_alignment());
237 tray_label_
->Layout();
241 views::View
* TrayIME::CreateTrayView(user::LoginStatus status
) {
242 CHECK(tray_label_
== NULL
);
243 tray_label_
= new TrayItemView(this);
244 tray_label_
->CreateLabel();
245 SetupLabelForTray(tray_label_
->label());
246 // Hide IME tray when it is created, it will be updated when it is notified
247 // for IME refresh event.
248 tray_label_
->SetVisible(false);
252 views::View
* TrayIME::CreateDefaultView(user::LoginStatus status
) {
253 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
255 IMEPropertyInfoList property_list
;
256 delegate
->GetAvailableIMEList(&list
);
257 delegate
->GetCurrentIMEProperties(&property_list
);
258 if (list
.size() <= 1 && property_list
.size() <= 1)
260 CHECK(default_
== NULL
);
261 default_
= new tray::IMEDefaultView(this);
265 views::View
* TrayIME::CreateDetailedView(user::LoginStatus status
) {
266 CHECK(detailed_
== NULL
);
267 detailed_
= new tray::IMEDetailedView(this, status
);
271 void TrayIME::DestroyTrayView() {
275 void TrayIME::DestroyDefaultView() {
279 void TrayIME::DestroyDetailedView() {
283 void TrayIME::UpdateAfterLoginStatusChange(user::LoginStatus status
) {
286 void TrayIME::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment
) {
287 SetTrayLabelItemBorder(tray_label_
, alignment
);
288 tray_label_
->Layout();
291 void TrayIME::OnIMERefresh() {
292 SystemTrayDelegate
* delegate
= Shell::GetInstance()->system_tray_delegate();
295 IMEPropertyInfoList property_list
;
296 delegate
->GetCurrentIME(¤t
);
297 delegate
->GetAvailableIMEList(&list
);
298 delegate
->GetCurrentIMEProperties(&property_list
);
300 UpdateTrayLabel(current
, list
.size());
303 default_
->UpdateLabel(current
);
305 detailed_
->Update(list
, property_list
);