// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/app_list/views/folder_header_view.h" #include #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_folder_item.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/resources/grit/app_list_resources.h" #include "ui/app_list/views/app_list_folder_view.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/border.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/painter.h" namespace app_list { namespace { const int kPreferredWidth = 360; const int kPreferredHeight = 48; const int kIconDimension = 24; const int kBackButtonPadding = 14; const int kBottomSeparatorPadding = 9; // Non-experimental app list only. const int kBottomSeparatorHeight = 1; const int kMaxFolderNameWidth = 300; } // namespace class FolderHeaderView::FolderNameView : public views::Textfield { public: FolderNameView() { SetBorder(views::Border::CreateEmptyBorder(1, 1, 1, 1)); const SkColor kFocusBorderColor = SkColorSetRGB(64, 128, 250); SetFocusPainter(views::Painter::CreateSolidFocusPainter( kFocusBorderColor, gfx::Insets(0, 0, 1, 1))); SetTextColor(kFolderTitleColor); } ~FolderNameView() override {} private: DISALLOW_COPY_AND_ASSIGN(FolderNameView); }; FolderHeaderView::FolderHeaderView(FolderHeaderViewDelegate* delegate) : folder_item_(nullptr), back_button_(nullptr), folder_name_view_(new FolderNameView), folder_name_placeholder_text_( ui::ResourceBundle::GetSharedInstance().GetLocalizedString( IDS_APP_LIST_FOLDER_NAME_PLACEHOLDER)), delegate_(delegate), folder_name_visible_(true) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); if (!app_list::switches::IsExperimentalAppListEnabled()) { back_button_ = new views::ImageButton(this); back_button_->SetImage( views::ImageButton::STATE_NORMAL, rb.GetImageSkiaNamed(IDR_APP_LIST_FOLDER_BACK_NORMAL)); back_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE); AddChildView(back_button_); back_button_->SetFocusable(true); back_button_->SetAccessibleName( ui::ResourceBundle::GetSharedInstance().GetLocalizedString( IDS_APP_LIST_FOLDER_CLOSE_FOLDER_ACCESSIBILE_NAME)); } folder_name_view_->SetFontList( rb.GetFontList(ui::ResourceBundle::MediumFont)); folder_name_view_->set_placeholder_text_color(kFolderTitleHintTextColor); folder_name_view_->set_placeholder_text(folder_name_placeholder_text_); folder_name_view_->SetBorder(views::Border::NullBorder()); folder_name_view_->SetBackgroundColor(kContentsBackgroundColor); folder_name_view_->set_controller(this); AddChildView(folder_name_view_); } FolderHeaderView::~FolderHeaderView() { if (folder_item_) folder_item_->RemoveObserver(this); } void FolderHeaderView::SetFolderItem(AppListFolderItem* folder_item) { if (folder_item_) folder_item_->RemoveObserver(this); folder_item_ = folder_item; if (!folder_item_) return; folder_item_->AddObserver(this); folder_name_view_->SetEnabled(folder_item_->folder_type() != AppListFolderItem::FOLDER_TYPE_OEM); Update(); } void FolderHeaderView::UpdateFolderNameVisibility(bool visible) { folder_name_visible_ = visible; Update(); SchedulePaint(); } void FolderHeaderView::OnFolderItemRemoved() { folder_item_ = NULL; } void FolderHeaderView::SetTextFocus() { if (!folder_name_view_->HasFocus()) { views::FocusManager* focus_manager = GetFocusManager(); if (focus_manager) focus_manager->SetFocusedView(folder_name_view_); } } bool FolderHeaderView::HasTextFocus() const { return folder_name_view_->HasFocus(); } void FolderHeaderView::Update() { if (!folder_item_) return; folder_name_view_->SetVisible(folder_name_visible_); if (folder_name_visible_) { folder_name_view_->SetText(base::UTF8ToUTF16(folder_item_->name())); UpdateFolderNameAccessibleName(); } Layout(); } void FolderHeaderView::UpdateFolderNameAccessibleName() { // Sets |folder_name_view_|'s accessible name to the placeholder text if // |folder_name_view_| is blank; otherwise, clear the accessible name, the // accessible state's value is set to be folder_name_view_->text() by // TextField. base::string16 accessible_name = folder_name_view_->text().empty() ? folder_name_placeholder_text_ : base::string16(); folder_name_view_->SetAccessibleName(accessible_name); } const base::string16& FolderHeaderView::GetFolderNameForTest() { return folder_name_view_->text(); } void FolderHeaderView::SetFolderNameForTest(const base::string16& name) { folder_name_view_->SetText(name); } bool FolderHeaderView::IsFolderNameEnabledForTest() const { return folder_name_view_->enabled(); } gfx::Size FolderHeaderView::GetPreferredSize() const { return gfx::Size(kPreferredWidth, kPreferredHeight); } void FolderHeaderView::Layout() { gfx::Rect rect(GetContentsBounds()); if (rect.IsEmpty()) return; if (!switches::IsExperimentalAppListEnabled()) { gfx::Rect back_bounds; DCHECK(back_button_); back_bounds = rect; back_bounds.set_width(kIconDimension + 2 * kBackButtonPadding); back_button_->SetBoundsRect(back_bounds); } gfx::Rect text_bounds(rect); base::string16 text = folder_item_ && !folder_item_->name().empty() ? base::UTF8ToUTF16(folder_item_->name()) : folder_name_placeholder_text_; int text_width = gfx::Canvas::GetStringWidth(text, folder_name_view_->GetFontList()) + folder_name_view_->GetCaretBounds().width() + folder_name_view_->GetInsets().width(); text_width = std::min(text_width, kMaxFolderNameWidth); text_bounds.set_x(rect.x() + (rect.width() - text_width) / 2); text_bounds.set_width(text_width); text_bounds.ClampToCenteredSize(gfx::Size(text_bounds.width(), folder_name_view_->GetPreferredSize().height())); folder_name_view_->SetBoundsRect(text_bounds); } bool FolderHeaderView::OnKeyPressed(const ui::KeyEvent& event) { if (event.key_code() == ui::VKEY_RETURN) delegate_->GiveBackFocusToSearchBox(); return false; } void FolderHeaderView::OnPaint(gfx::Canvas* canvas) { views::View::OnPaint(canvas); gfx::Rect rect(GetContentsBounds()); if (rect.IsEmpty() || !folder_name_visible_) return; // Draw bottom separator line. int horizontal_padding = app_list::switches::IsExperimentalAppListEnabled() ? kExperimentalAppsGridPadding : kBottomSeparatorPadding; rect.Inset(horizontal_padding, 0); rect.set_y(rect.bottom() - kBottomSeparatorHeight); rect.set_height(kBottomSeparatorHeight); canvas->FillRect(rect, kTopSeparatorColor); } void FolderHeaderView::ContentsChanged(views::Textfield* sender, const base::string16& new_contents) { // Temporarily remove from observer to ignore data change caused by us. if (!folder_item_) return; folder_item_->RemoveObserver(this); // Enforce the maximum folder name length in UI. std::string name = base::UTF16ToUTF8( folder_name_view_->text().substr(0, kMaxFolderNameChars)); if (name != folder_item_->name()) delegate_->SetItemName(folder_item_, name); folder_item_->AddObserver(this); UpdateFolderNameAccessibleName(); Layout(); } void FolderHeaderView::ButtonPressed(views::Button* sender, const ui::Event& event) { delegate_->NavigateBack(folder_item_, event); } void FolderHeaderView::ItemNameChanged() { Update(); } } // namespace app_list