Commit 0bb07b62 authored by Qiang Xu's avatar Qiang Xu Committed by Commit Bot

app_list: add suggested apps to all apps launcher page

changes:
(1) refactor AppsGridView's ctor to accept ContentsView*.
(2) move all apps indicator from AppsContainerView to AppsGridView.
(3) host suggested_apps_indicator_, all_apps_indicator_, and
suggestions container view in AppsGridView.
(4) for all apps layout, the first page is 4*5 and all others are 5*5.
(5) update keyboard arrow moving focus for new launcher. See focus
rules in inline comments.
(6) refactor AppsGridViewTest by creating app_list_view_ to test
AppsGridView, also make it parameterized tests to test
EnableFullscreenAppList. Most of the tests are opened for both old
and new launcher.
(7) add tests: CreatePage, HandleSuggestionsMove, 
MoveSelectedOnAllAppsTiles.

UI specification: https://screenshot.googleplex.com/ebJ2ug1xS9Z.

flag, screenshot: https://screenshot.googleplex.com/AbpxexGtKNj
keyboard moving focus works as expected.
also added test coverage.

Bug: 735702
TEST: tested with and without --enable-features=EnableFullscreenAppList
Change-Id: I7fe602c84bdeb8f659013de76285fb2dca9f6ec3
Reviewed-on: https://chromium-review.googlesource.com/564485Reviewed-by: default avatarJenny Zhang <jennyz@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Commit-Queue: Qiang(Joe) Xu <warx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#486186}
parent e45fe4fc
......@@ -54,7 +54,7 @@ AppListFolderView::AppListFolderView(AppsContainerView* container_view,
AddChildView(folder_header_view_);
view_model_->Add(folder_header_view_, kIndexFolderHeader);
items_grid_view_ = new AppsGridView(app_list_main_view_);
items_grid_view_ = new AppsGridView(app_list_main_view_->contents_view());
items_grid_view_->set_folder_delegate(this);
items_grid_view_->SetLayout(
container_view->apps_grid_view()->cols(),
......
......@@ -75,6 +75,10 @@ class APP_LIST_EXPORT AppListMainView : public views::View,
void OnCustomLauncherPageEnabledStateChanged(bool enabled) override;
void OnSearchEngineIsGoogleChanged(bool is_google) override;
// Overridden from AppsGridViewDelegate:
void ActivateApp(AppListItem* item, int event_flags) override;
void CancelDragInActiveFolder() override;
private:
// Adds the ContentsView.
void AddContentsViews();
......@@ -82,10 +86,6 @@ class APP_LIST_EXPORT AppListMainView : public views::View,
// Gets the PaginationModel owned by the AppsGridView.
PaginationModel* GetAppsPaginationModel();
// Overridden from AppsGridViewDelegate:
void ActivateApp(AppListItem* item, int event_flags) override;
void CancelDragInActiveFolder() override;
// Overridden from SearchBoxViewDelegate:
void QueryChanged(SearchBoxView* sender) override;
void BackButtonPressed() override;
......
......@@ -17,29 +17,17 @@
#include "ui/app_list/views/app_list_main_view.h"
#include "ui/app_list/views/apps_grid_view.h"
#include "ui/app_list/views/folder_background_view.h"
#include "ui/app_list/views/indicator_chip_view.h"
#include "ui/app_list/views/suggestions_container_view.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event.h"
#include "ui/strings/grit/ui_strings.h"
namespace app_list {
namespace {
// Layout constants.
constexpr int kAllAppsIndicatorExtraPadding = 2;
} // namespace
AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view,
AppListModel* model)
: is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) {
if (is_fullscreen_app_list_enabled_) {
all_apps_indicator_ = new IndicatorChipView(
l10n_util::GetStringUTF16(IDS_ALL_APPS_INDICATOR));
AddChildView(all_apps_indicator_);
}
apps_grid_view_ = new AppsGridView(app_list_main_view);
apps_grid_view_ = new AppsGridView(app_list_main_view->contents_view());
if (is_fullscreen_app_list_enabled_) {
apps_grid_view_->SetLayout(kPreferredColsFullscreen,
kPreferredRowsFullscreen);
......@@ -133,16 +121,6 @@ void AppsContainerView::Layout() {
switch (show_state_) {
case SHOW_APPS:
if (all_apps_indicator_) {
gfx::Rect indicator_rect(rect);
const gfx::Size indicator_size =
all_apps_indicator_->GetPreferredSize();
indicator_rect.Inset(
(indicator_rect.width() - indicator_size.width()) / 2, 0);
all_apps_indicator_->SetBoundsRect(indicator_rect);
rect.Inset(0, indicator_size.height() + kAllAppsIndicatorExtraPadding,
0, 0);
}
apps_grid_view_->SetBoundsRect(rect);
break;
case SHOW_ACTIVE_FOLDER:
......
......@@ -27,7 +27,6 @@ class AppListFolderView;
class AppListMainView;
class AppListModel;
class FolderBackgroundView;
class IndicatorChipView;
// AppsContainerView contains a root level AppsGridView to render the root level
// app items, and a AppListFolderView to render the app items inside the
......@@ -107,7 +106,6 @@ class AppsContainerView : public AppListPage, public TopIconAnimationObserver {
void PrepareToShowApps(AppListFolderItem* folder_item);
// The views below are owned by views hierarchy.
IndicatorChipView* all_apps_indicator_ = nullptr;
AppsGridView* apps_grid_view_ = nullptr;
AppListFolderView* app_list_folder_view_ = nullptr;
FolderBackgroundView* folder_background_view_ = nullptr;
......
This diff is collapsed.
......@@ -42,8 +42,10 @@ class AppsGridViewTestApi;
class ApplicationDragAndDropHost;
class AppListItemView;
class AppsGridViewDelegate;
class AppsGridViewFolderDelegate;
class ContentsView;
class IndicatorChipView;
class SuggestionsContainerView;
class PageSwitcher;
class PaginationController;
class PulsingBlockView;
......@@ -62,9 +64,7 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
TOUCH,
};
// Constructs the app icon grid view. |delegate| is the delegate of this
// view, which usually is the hosting AppListView.
explicit AppsGridView(AppsGridViewDelegate* delegate);
explicit AppsGridView(ContentsView* contents_view);
~AppsGridView() override;
// Sets fixed layout parameters. After setting this, CalculateLayout below
......@@ -213,6 +213,10 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
const AppListModel* model() const { return model_; }
SuggestionsContainerView* suggestions_container_for_test() const {
return suggestions_container_;
}
private:
friend class test::AppsGridViewTestApi;
......@@ -241,7 +245,21 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
int slot; // Which slot in the page an item view is in.
};
int tiles_per_page() const { return cols_ * rows_per_page_; }
// Creates indicator based on the indicator text message id.
IndicatorChipView* CreateIndicator(int indicator_text_message_id);
// Updates suggestions from app list model.
void UpdateSuggestions();
// Helper method for layouting indicator based on the given bounds |rect|.
void LayoutSuggestedAppsIndicator(gfx::Rect* rect);
void LayoutAllAppsIndicator(gfx::Rect* rect);
// Returns all apps tiles per page based on |page|.
int TilesPerPage(int page) const;
// Returns the last index of |page|.
int LastIndexOfPage(int page) const;
// Updates from model.
void Update();
......@@ -276,6 +294,12 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
void MoveSelected(int page_delta, int slot_x_delta, int slot_y_delta);
// Returns true if the given moving operation should be handled by
// |suggestions_container_|, otherwise false.
bool HandleSuggestionsMove(int page_delta,
int slot_x_delta,
int slot_y_delta);
// Calculates the offset for |page_of_view| based on current page and
// transition target page.
const gfx::Vector2d CalculateTransitionOffset(int page_of_view) const;
......@@ -406,6 +430,11 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
// slot if |point| is outside the page's bounds.
Index GetNearestTileIndexForPoint(const gfx::Point& point) const;
// Gets height on top of the all apps tiles. For the first page, that includes
// suggested apps indicator, suggested apps tiles, all apps indicator
// views; For the non-first pages, that include all apps indicator view only.
int GetHeightOnTopOfAllAppsTiles() const;
// Gets the bounds of the tile located at |slot| on the current page.
gfx::Rect GetExpectedTileBounds(int slot) const;
......@@ -453,20 +482,27 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
// Returns true if the grid view is under an OEM folder.
bool IsUnderOEMFolder();
AppListModel* model_; // Owned by AppListView.
AppListItemList* item_list_; // Not owned.
AppsGridViewDelegate* delegate_;
AppListModel* model_ = nullptr; // Owned by AppListView.
AppListItemList* item_list_ = nullptr; // Not owned.
// This can be NULL. Only grid views inside folders have a folder delegate.
AppsGridViewFolderDelegate* folder_delegate_;
AppsGridViewFolderDelegate* folder_delegate_ = nullptr;
PaginationModel pagination_model_;
// Must appear after |pagination_model_|.
std::unique_ptr<PaginationController> pagination_controller_;
PageSwitcher* page_switcher_view_; // Owned by views hierarchy.
PageSwitcher* page_switcher_view_ = nullptr; // Owned by views hierarchy.
// Created by AppListMainView, owned by views hierarchy.
ContentsView* contents_view_ = nullptr;
// Views below are owned by views hierarchy.
IndicatorChipView* suggested_apps_indicator_ = nullptr;
SuggestionsContainerView* suggestions_container_ = nullptr;
IndicatorChipView* all_apps_indicator_ = nullptr;
int cols_;
int rows_per_page_;
int cols_ = 0;
int rows_per_page_ = 0;
// List of app item views. There is a view per item in |model_|.
views::ViewModelT<AppListItemView> view_model_;
......@@ -474,9 +510,9 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
// List of pulsing block views.
views::ViewModelT<PulsingBlockView> pulsing_blocks_model_;
AppListItemView* selected_view_;
AppListItemView* selected_view_ = nullptr;
AppListItemView* drag_view_;
AppListItemView* drag_view_ = nullptr;
// The index of the drag_view_ when the drag starts.
Index drag_view_init_index_;
......@@ -491,9 +527,9 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
gfx::Point drag_view_start_;
// Page the drag started on.
int drag_start_page_;
int drag_start_page_ = -1;
Pointer drag_pointer_;
Pointer drag_pointer_ = NONE;
// The most recent reorder drop target.
Index reorder_drop_target_;
......@@ -506,7 +542,7 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
Index reorder_placeholder_;
// The current action that ending a drag will perform.
DropAttempt drop_attempt_;
DropAttempt drop_attempt_ = DROP_FOR_NONE;
// Timer for re-ordering the |drop_target_| and |drag_view_|.
base::OneShotTimer reorder_timer_;
......@@ -519,11 +555,11 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
base::OneShotTimer folder_item_reparent_timer_;
// An application target drag and drop host which accepts dnd operations.
ApplicationDragAndDropHost* drag_and_drop_host_;
ApplicationDragAndDropHost* drag_and_drop_host_ = nullptr;
// The drag operation is currently inside the dnd host and events get
// forwarded.
bool forward_events_to_drag_and_drop_host_;
bool forward_events_to_drag_and_drop_host_ = false;
// Last mouse drag location in this view's coordinates.
gfx::Point last_drag_point_;
......@@ -532,7 +568,7 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
base::OneShotTimer page_flip_timer_;
// Target page to switch to when |page_flip_timer_| fires.
int page_flip_target_;
int page_flip_target_ = -1;
// Delay in milliseconds of when |page_flip_timer_| should fire after user
// drags an item near the edges.
......@@ -541,14 +577,14 @@ class APP_LIST_EXPORT AppsGridView : public views::View,
views::BoundsAnimator bounds_animator_;
// The most recent activated folder item view.
AppListItemView* activated_folder_item_view_;
AppListItemView* activated_folder_item_view_ = nullptr;
// Tracks if drag_view_ is dragged out of the folder container bubble
// when dragging a item inside a folder.
bool drag_out_of_folder_container_;
bool drag_out_of_folder_container_ = false;
// True if the drag_view_ item is a folder item being dragged for reparenting.
bool dragging_for_reparent_item_;
bool dragging_for_reparent_item_ = false;
// True if the fullscreen app list feature is enabled.
const bool is_fullscreen_app_list_enabled_;
......
......@@ -36,6 +36,10 @@ void AppsGridViewTestApi::LayoutToIdealBounds() {
view_->Layout();
}
gfx::Rect AppsGridViewTestApi::GetItemTileRectAt(int row, int col) const {
return view_->GetExpectedTileBounds(row, col);
}
void AppsGridViewTestApi::SetPageFlipDelay(int page_flip_delay_in_ms) {
view_->page_flip_delay_in_ms_ = page_flip_delay_in_ms;
}
......@@ -50,5 +54,9 @@ bool AppsGridViewTestApi::HasPendingPageFlip() const {
view_->pagination_model()->has_transition();
}
int AppsGridViewTestApi::TilesPerPage(int page) const {
return view_->TilesPerPage(page);
}
} // namespace test
} // namespace app_list
......@@ -7,6 +7,10 @@
#include "base/macros.h"
namespace gfx {
class Rect;
}
namespace views {
class View;
}
......@@ -26,12 +30,16 @@ class AppsGridViewTestApi {
void LayoutToIdealBounds();
gfx::Rect GetItemTileRectAt(int row, int col) const;
void SetPageFlipDelay(int page_flip_delay_in_ms);
void PressItemAt(int index);
bool HasPendingPageFlip() const;
int TilesPerPage(int page) const;
private:
AppsGridView* view_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment