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/views/app_list_folder_view.h"
13 #include "ui/base/resource/resource_bundle.h"
14 #include "ui/gfx/canvas.h"
15 #include "ui/resources/grit/ui_resources.h"
16 #include "ui/strings/grit/ui_strings.h"
17 #include "ui/views/border.h"
18 #include "ui/views/controls/button/image_button.h"
19 #include "ui/views/controls/textfield/textfield.h"
20 #include "ui/views/painter.h"
26 const int kPreferredWidth
= 360;
27 const int kPreferredHeight
= 48;
28 const int kIconDimension
= 24;
29 const int kPadding
= 14;
30 const int kBottomSeparatorWidth
= 380;
31 const int kBottomSeparatorHeight
= 1;
32 const int kMaxFolderNameWidth
= 300;
34 const SkColor kHintTextColor
= SkColorSetRGB(0xA0, 0xA0, 0xA0);
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)));
48 virtual ~FolderNameView() {
52 DISALLOW_COPY_AND_ASSIGN(FolderNameView
);
55 FolderHeaderView::FolderHeaderView(FolderHeaderViewDelegate
* delegate
)
57 back_button_(new views::ImageButton(this)),
58 folder_name_view_(new FolderNameView
),
59 folder_name_placeholder_text_(
60 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
61 IDS_APP_LIST_FOLDER_NAME_PLACEHOLDER
)),
63 folder_name_visible_(true) {
64 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
65 back_button_
->SetImage(views::ImageButton::STATE_NORMAL
,
66 rb
.GetImageSkiaNamed(IDR_APP_LIST_FOLDER_BACK_NORMAL
));
67 back_button_
->SetImageAlignment(views::ImageButton::ALIGN_CENTER
,
68 views::ImageButton::ALIGN_MIDDLE
);
69 AddChildView(back_button_
);
70 back_button_
->SetFocusable(true);
71 back_button_
->SetAccessibleName(
72 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
73 IDS_APP_LIST_FOLDER_CLOSE_FOLDER_ACCESSIBILE_NAME
));
75 folder_name_view_
->SetFontList(
76 rb
.GetFontList(ui::ResourceBundle::MediumFont
));
77 folder_name_view_
->set_placeholder_text_color(kHintTextColor
);
78 folder_name_view_
->set_placeholder_text(folder_name_placeholder_text_
);
79 folder_name_view_
->SetBorder(views::Border::NullBorder());
80 folder_name_view_
->SetBackgroundColor(kContentsBackgroundColor
);
81 folder_name_view_
->set_controller(this);
82 AddChildView(folder_name_view_
);
85 FolderHeaderView::~FolderHeaderView() {
87 folder_item_
->RemoveObserver(this);
90 void FolderHeaderView::SetFolderItem(AppListFolderItem
* folder_item
) {
92 folder_item_
->RemoveObserver(this);
94 folder_item_
= folder_item
;
97 folder_item_
->AddObserver(this);
99 folder_name_view_
->SetEnabled(folder_item_
->folder_type() !=
100 AppListFolderItem::FOLDER_TYPE_OEM
);
105 void FolderHeaderView::UpdateFolderNameVisibility(bool visible
) {
106 folder_name_visible_
= visible
;
111 void FolderHeaderView::OnFolderItemRemoved() {
115 void FolderHeaderView::Update() {
119 folder_name_view_
->SetVisible(folder_name_visible_
);
120 if (folder_name_visible_
) {
121 folder_name_view_
->SetText(base::UTF8ToUTF16(folder_item_
->name()));
122 UpdateFolderNameAccessibleName();
128 void FolderHeaderView::UpdateFolderNameAccessibleName() {
129 // Sets |folder_name_view_|'s accessible name to the placeholder text if
130 // |folder_name_view_| is blank; otherwise, clear the accessible name, the
131 // accessible state's value is set to be folder_name_view_->text() by
133 base::string16 accessible_name
= folder_name_view_
->text().empty()
134 ? folder_name_placeholder_text_
136 folder_name_view_
->SetAccessibleName(accessible_name
);
139 const base::string16
& FolderHeaderView::GetFolderNameForTest() {
140 return folder_name_view_
->text();
143 void FolderHeaderView::SetFolderNameForTest(const base::string16
& name
) {
144 folder_name_view_
->SetText(name
);
147 bool FolderHeaderView::IsFolderNameEnabledForTest() const {
148 return folder_name_view_
->enabled();
151 gfx::Size
FolderHeaderView::GetPreferredSize() const {
152 return gfx::Size(kPreferredWidth
, kPreferredHeight
);
155 void FolderHeaderView::Layout() {
156 gfx::Rect
rect(GetContentsBounds());
160 gfx::Rect
back_bounds(rect
);
161 back_bounds
.set_width(kIconDimension
+ 2 * kPadding
);
162 back_button_
->SetBoundsRect(back_bounds
);
164 gfx::Rect
text_bounds(rect
);
165 base::string16 text
= folder_item_
&& !folder_item_
->name().empty()
166 ? base::UTF8ToUTF16(folder_item_
->name())
167 : folder_name_placeholder_text_
;
169 gfx::Canvas::GetStringWidth(text
, folder_name_view_
->GetFontList()) +
170 folder_name_view_
->GetCaretBounds().width();
171 text_width
= std::min(text_width
, kMaxFolderNameWidth
);
172 text_bounds
.set_x(back_bounds
.x() + (rect
.width() - text_width
) / 2);
173 text_bounds
.set_width(text_width
);
174 text_bounds
.ClampToCenteredSize(gfx::Size(text_bounds
.width(),
175 folder_name_view_
->GetPreferredSize().height()));
176 folder_name_view_
->SetBoundsRect(text_bounds
);
179 bool FolderHeaderView::OnKeyPressed(const ui::KeyEvent
& event
) {
180 if (event
.key_code() == ui::VKEY_RETURN
)
181 delegate_
->GiveBackFocusToSearchBox();
186 void FolderHeaderView::OnPaint(gfx::Canvas
* canvas
) {
187 views::View::OnPaint(canvas
);
189 gfx::Rect
rect(GetContentsBounds());
190 if (rect
.IsEmpty() || !folder_name_visible_
)
193 // Draw bottom separator line.
194 rect
.set_x((rect
.width() - kBottomSeparatorWidth
) / 2 + rect
.x());
195 rect
.set_y(rect
.y() + rect
.height() - kBottomSeparatorHeight
);
196 rect
.set_width(kBottomSeparatorWidth
);
197 rect
.set_height(kBottomSeparatorHeight
);
198 canvas
->FillRect(rect
, kTopSeparatorColor
);
201 void FolderHeaderView::ContentsChanged(views::Textfield
* sender
,
202 const base::string16
& new_contents
) {
203 // Temporarily remove from observer to ignore data change caused by us.
207 folder_item_
->RemoveObserver(this);
208 // Enforce the maximum folder name length in UI.
209 std::string name
= base::UTF16ToUTF8(
210 folder_name_view_
->text().substr(0, kMaxFolderNameChars
));
211 if (name
!= folder_item_
->name())
212 delegate_
->SetItemName(folder_item_
, name
);
213 folder_item_
->AddObserver(this);
215 UpdateFolderNameAccessibleName();
220 void FolderHeaderView::ButtonPressed(views::Button
* sender
,
221 const ui::Event
& event
) {
222 delegate_
->NavigateBack(folder_item_
, event
);
225 void FolderHeaderView::ItemNameChanged() {
229 } // namespace app_list