1 // Copyright (c) 2013 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 "ui/app_list/views/folder_header_view.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "ui/app_list/app_list_constants.h"
11 #include "ui/app_list/app_list_folder_item.h"
12 #include "ui/app_list/app_list_switches.h"
13 #include "ui/app_list/views/app_list_folder_view.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/gfx/canvas.h"
16 #include "ui/resources/grit/ui_resources.h"
17 #include "ui/strings/grit/ui_strings.h"
18 #include "ui/views/border.h"
19 #include "ui/views/controls/button/image_button.h"
20 #include "ui/views/controls/textfield/textfield.h"
21 #include "ui/views/focus/focus_manager.h"
22 #include "ui/views/painter.h"
28 const int kPreferredWidth
= 360;
29 const int kPreferredHeight
= 48;
30 const int kIconDimension
= 24;
31 const int kBackButtonPadding
= 14;
32 const int kBottomSeparatorPadding
= 9; // Non-experimental app list only.
33 const int kBottomSeparatorHeight
= 1;
34 const int kMaxFolderNameWidth
= 300;
38 class FolderHeaderView::FolderNameView
: public views::Textfield
{
41 SetBorder(views::Border::CreateEmptyBorder(1, 1, 1, 1));
42 const SkColor kFocusBorderColor
= SkColorSetRGB(64, 128, 250);
43 SetFocusPainter(views::Painter::CreateSolidFocusPainter(
45 gfx::Insets(0, 0, 1, 1)));
47 SetTextColor(kFolderTitleColor
);
50 ~FolderNameView() override
{}
53 DISALLOW_COPY_AND_ASSIGN(FolderNameView
);
56 FolderHeaderView::FolderHeaderView(FolderHeaderViewDelegate
* delegate
)
57 : folder_item_(nullptr),
58 back_button_(nullptr),
59 folder_name_view_(new FolderNameView
),
60 folder_name_placeholder_text_(
61 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
62 IDS_APP_LIST_FOLDER_NAME_PLACEHOLDER
)),
64 folder_name_visible_(true) {
65 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
66 if (!app_list::switches::IsExperimentalAppListEnabled()) {
67 back_button_
= new views::ImageButton(this);
68 back_button_
->SetImage(
69 views::ImageButton::STATE_NORMAL
,
70 rb
.GetImageSkiaNamed(IDR_APP_LIST_FOLDER_BACK_NORMAL
));
71 back_button_
->SetImageAlignment(views::ImageButton::ALIGN_CENTER
,
72 views::ImageButton::ALIGN_MIDDLE
);
73 AddChildView(back_button_
);
74 back_button_
->SetFocusable(true);
75 back_button_
->SetAccessibleName(
76 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
77 IDS_APP_LIST_FOLDER_CLOSE_FOLDER_ACCESSIBILE_NAME
));
80 folder_name_view_
->SetFontList(
81 rb
.GetFontList(ui::ResourceBundle::MediumFont
));
82 folder_name_view_
->set_placeholder_text_color(kFolderTitleHintTextColor
);
83 folder_name_view_
->set_placeholder_text(folder_name_placeholder_text_
);
84 folder_name_view_
->SetBorder(views::Border::NullBorder());
85 folder_name_view_
->SetBackgroundColor(kContentsBackgroundColor
);
86 folder_name_view_
->set_controller(this);
87 AddChildView(folder_name_view_
);
90 FolderHeaderView::~FolderHeaderView() {
92 folder_item_
->RemoveObserver(this);
95 void FolderHeaderView::SetFolderItem(AppListFolderItem
* folder_item
) {
97 folder_item_
->RemoveObserver(this);
99 folder_item_
= folder_item
;
102 folder_item_
->AddObserver(this);
104 folder_name_view_
->SetEnabled(folder_item_
->folder_type() !=
105 AppListFolderItem::FOLDER_TYPE_OEM
);
110 void FolderHeaderView::UpdateFolderNameVisibility(bool visible
) {
111 folder_name_visible_
= visible
;
116 void FolderHeaderView::OnFolderItemRemoved() {
120 void FolderHeaderView::SetTextFocus() {
121 if (!folder_name_view_
->HasFocus()) {
122 views::FocusManager
* focus_manager
= GetFocusManager();
124 focus_manager
->SetFocusedView(folder_name_view_
);
128 bool FolderHeaderView::HasTextFocus() const {
129 return folder_name_view_
->HasFocus();
132 void FolderHeaderView::Update() {
136 folder_name_view_
->SetVisible(folder_name_visible_
);
137 if (folder_name_visible_
) {
138 folder_name_view_
->SetText(base::UTF8ToUTF16(folder_item_
->name()));
139 UpdateFolderNameAccessibleName();
145 void FolderHeaderView::UpdateFolderNameAccessibleName() {
146 // Sets |folder_name_view_|'s accessible name to the placeholder text if
147 // |folder_name_view_| is blank; otherwise, clear the accessible name, the
148 // accessible state's value is set to be folder_name_view_->text() by
150 base::string16 accessible_name
= folder_name_view_
->text().empty()
151 ? folder_name_placeholder_text_
153 folder_name_view_
->SetAccessibleName(accessible_name
);
156 const base::string16
& FolderHeaderView::GetFolderNameForTest() {
157 return folder_name_view_
->text();
160 void FolderHeaderView::SetFolderNameForTest(const base::string16
& name
) {
161 folder_name_view_
->SetText(name
);
164 bool FolderHeaderView::IsFolderNameEnabledForTest() const {
165 return folder_name_view_
->enabled();
168 gfx::Size
FolderHeaderView::GetPreferredSize() const {
169 return gfx::Size(kPreferredWidth
, kPreferredHeight
);
172 void FolderHeaderView::Layout() {
173 gfx::Rect
rect(GetContentsBounds());
177 if (!switches::IsExperimentalAppListEnabled()) {
178 gfx::Rect back_bounds
;
179 DCHECK(back_button_
);
181 back_bounds
.set_width(kIconDimension
+ 2 * kBackButtonPadding
);
182 back_button_
->SetBoundsRect(back_bounds
);
185 gfx::Rect
text_bounds(rect
);
186 base::string16 text
= folder_item_
&& !folder_item_
->name().empty()
187 ? base::UTF8ToUTF16(folder_item_
->name())
188 : folder_name_placeholder_text_
;
190 gfx::Canvas::GetStringWidth(text
, folder_name_view_
->GetFontList()) +
191 folder_name_view_
->GetCaretBounds().width() +
192 folder_name_view_
->GetInsets().width();
193 text_width
= std::min(text_width
, kMaxFolderNameWidth
);
194 text_bounds
.set_x(rect
.x() + (rect
.width() - text_width
) / 2);
195 text_bounds
.set_width(text_width
);
196 text_bounds
.ClampToCenteredSize(gfx::Size(text_bounds
.width(),
197 folder_name_view_
->GetPreferredSize().height()));
198 folder_name_view_
->SetBoundsRect(text_bounds
);
201 bool FolderHeaderView::OnKeyPressed(const ui::KeyEvent
& event
) {
202 if (event
.key_code() == ui::VKEY_RETURN
)
203 delegate_
->GiveBackFocusToSearchBox();
208 void FolderHeaderView::OnPaint(gfx::Canvas
* canvas
) {
209 views::View::OnPaint(canvas
);
211 gfx::Rect
rect(GetContentsBounds());
212 if (rect
.IsEmpty() || !folder_name_visible_
)
215 // Draw bottom separator line.
216 int horizontal_padding
= app_list::switches::IsExperimentalAppListEnabled()
217 ? kExperimentalAppsGridPadding
218 : kBottomSeparatorPadding
;
219 rect
.Inset(horizontal_padding
, 0);
220 rect
.set_y(rect
.bottom() - kBottomSeparatorHeight
);
221 rect
.set_height(kBottomSeparatorHeight
);
222 canvas
->FillRect(rect
, kTopSeparatorColor
);
225 void FolderHeaderView::ContentsChanged(views::Textfield
* sender
,
226 const base::string16
& new_contents
) {
227 // Temporarily remove from observer to ignore data change caused by us.
231 folder_item_
->RemoveObserver(this);
232 // Enforce the maximum folder name length in UI.
233 std::string name
= base::UTF16ToUTF8(
234 folder_name_view_
->text().substr(0, kMaxFolderNameChars
));
235 if (name
!= folder_item_
->name())
236 delegate_
->SetItemName(folder_item_
, name
);
237 folder_item_
->AddObserver(this);
239 UpdateFolderNameAccessibleName();
244 void FolderHeaderView::ButtonPressed(views::Button
* sender
,
245 const ui::Event
& event
) {
246 delegate_
->NavigateBack(folder_item_
, event
);
249 void FolderHeaderView::ItemNameChanged() {
253 } // namespace app_list