diff options
Diffstat (limited to 'chromium/ui/app_list/views')
21 files changed, 475 insertions, 305 deletions
diff --git a/chromium/ui/app_list/views/app_list_item_view.cc b/chromium/ui/app_list/views/app_list_item_view.cc index 1b9aaf701d1..2717f51a825 100644 --- a/chromium/ui/app_list/views/app_list_item_view.cc +++ b/chromium/ui/app_list/views/app_list_item_view.cc @@ -13,11 +13,11 @@ #include "ui/app_list/views/cached_label.h" #include "ui/app_list/views/progress_bar_view.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/animation/throb_animation.h" #include "ui/base/dragdrop/drag_utils.h" #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" #include "ui/gfx/image/image_skia_operations.h" @@ -130,6 +130,11 @@ void AppListItemView::UpdateIcon() { icon_->SetImage(resized); } +void AppListItemView::UpdateTooltip() { + title_->SetTooltipText(model_->title() == model_->full_name() ? + string16() : UTF8ToUTF16(model_->full_name())); +} + void AppListItemView::SetUIState(UIState state) { if (ui_state_ == state) return; @@ -193,6 +198,7 @@ void AppListItemView::ItemIconChanged() { void AppListItemView::ItemTitleChanged() { title_->SetText(UTF8ToUTF16(model_->title())); title_->Invalidate(); + UpdateTooltip(); Layout(); } diff --git a/chromium/ui/app_list/views/app_list_item_view.h b/chromium/ui/app_list/views/app_list_item_view.h index 0738d83c7e7..311d7219456 100644 --- a/chromium/ui/app_list/views/app_list_item_view.h +++ b/chromium/ui/app_list/views/app_list_item_view.h @@ -62,6 +62,9 @@ class APP_LIST_EXPORT AppListItemView : public views::CustomButton, // Get icon from model and schedule background processing. void UpdateIcon(); + // Update the tooltip text from the model. + void UpdateTooltip(); + void SetUIState(UIState state); // Sets |touch_dragging_| flag and updates UI. diff --git a/chromium/ui/app_list/views/app_list_main_view.cc b/chromium/ui/app_list/views/app_list_main_view.cc index fa0de27ce0e..f08fef82d9b 100644 --- a/chromium/ui/app_list/views/app_list_main_view.cc +++ b/chromium/ui/app_list/views/app_list_main_view.cc @@ -6,8 +6,10 @@ #include <algorithm> +#include "base/bind.h" #include "base/callback.h" #include "base/files/file_path.h" +#include "base/message_loop/message_loop.h" #include "base/strings/string_util.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_item_model.h" @@ -77,13 +79,14 @@ class AppListMainView::IconLoader : public AppListItemModelObserver { AppListMainView::AppListMainView(AppListViewDelegate* delegate, AppListModel* model, PaginationModel* pagination_model, - views::View* anchor) + gfx::NativeView parent) : delegate_(delegate), model_(model), search_box_view_(NULL), - contents_view_(NULL) { + contents_view_(NULL), + weak_ptr_factory_(this) { // Starts icon loading early. - PreloadIcons(pagination_model, anchor); + PreloadIcons(pagination_model, parent); SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, kInnerPadding, @@ -127,6 +130,7 @@ void AppListMainView::ShowAppListWhenReady() { void AppListMainView::Close() { icon_loading_wait_timer_.Stop(); + contents_view_->CancelDrag(); } void AppListMainView::Prerender() { @@ -134,17 +138,15 @@ void AppListMainView::Prerender() { } void AppListMainView::SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host) { + ApplicationDragAndDropHost* drag_and_drop_host) { contents_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); } void AppListMainView::PreloadIcons(PaginationModel* pagination_model, - views::View* anchor) { + gfx::NativeView parent) { ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_100P; - if (anchor && anchor->GetWidget()) { - scale_factor = ui::GetScaleFactorForNativeView( - anchor->GetWidget()->GetNativeView()); - } + if (parent) + scale_factor = ui::GetScaleFactorForNativeView(parent); // |pagination_model| could have -1 as the initial selected page and // assumes first page (i.e. index 0) will be used in this case. @@ -230,7 +232,13 @@ void AppListMainView::OnResultInstalled(SearchResult* result) { } void AppListMainView::OnResultUninstalled(SearchResult* result) { - QueryChanged(search_box_view_); + // Resubmit the query via a posted task so that all observers for the + // uninstall notification are notified. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&AppListMainView::QueryChanged, + weak_ptr_factory_.GetWeakPtr(), + search_box_view_)); } } // namespace app_list diff --git a/chromium/ui/app_list/views/app_list_main_view.h b/chromium/ui/app_list/views/app_list_main_view.h index 1909d97c1da..0c9a7383e12 100644 --- a/chromium/ui/app_list/views/app_list_main_view.h +++ b/chromium/ui/app_list/views/app_list_main_view.h @@ -8,10 +8,11 @@ #include <string> #include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" #include "base/timer/timer.h" -#include "ui/app_list/apps_grid_view_delegate.h" -#include "ui/app_list/search_box_view_delegate.h" -#include "ui/app_list/search_result_list_view_delegate.h" +#include "ui/app_list/views/apps_grid_view_delegate.h" +#include "ui/app_list/views/search_box_view_delegate.h" +#include "ui/app_list/views/search_result_list_view_delegate.h" #include "ui/views/view.h" namespace views { @@ -39,7 +40,7 @@ class AppListMainView : public views::View, explicit AppListMainView(AppListViewDelegate* delegate, AppListModel* model, PaginationModel* pagination_model, - views::View* anchor); + gfx::NativeView parent); virtual ~AppListMainView(); void ShowAppListWhenReady(); @@ -59,9 +60,9 @@ class AppListMainView : public views::View, class IconLoader; // Loads icon image for the apps in the selected page of |pagination_model|. - // |anchor| is used to determine the image scale factor to use. + // |parent| is used to determine the image scale factor to use. void PreloadIcons(PaginationModel* pagination_model, - views::View* anchor); + gfx::NativeView parent); // Invoked when |icon_loading_wait_timer_| fires. void OnIconLoadingWaitTimer(); @@ -99,6 +100,8 @@ class AppListMainView : public views::View, ScopedVector<IconLoader> pending_icon_loaders_; + base::WeakPtrFactory<AppListMainView> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(AppListMainView); }; diff --git a/chromium/ui/app_list/views/app_list_menu_views.cc b/chromium/ui/app_list/views/app_list_menu_views.cc index 0eb853607f0..04c1f2155b4 100644 --- a/chromium/ui/app_list/views/app_list_menu_views.cc +++ b/chromium/ui/app_list/views/app_list_menu_views.cc @@ -5,6 +5,7 @@ #include "ui/app_list/views/app_list_menu_views.h" #include "grit/ui_resources.h" +#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/base/resource/resource_bundle.h" #include "ui/views/controls/button/menu_button.h" @@ -19,114 +20,10 @@ using views::MenuItemView; namespace app_list { -namespace { - -class CurrentUserView : public views::View { - public: - CurrentUserView(const base::string16& user_name, - const base::string16& user_email, - const gfx::ImageSkia& icon) { - const views::MenuConfig& menu_config = views::MenuConfig::instance(NULL); - views::GridLayout* layout = new views::GridLayout(this); - int item_right_padding = menu_config.label_to_arrow_padding + - menu_config.arrow_width + - menu_config.arrow_to_edge_padding; - - layout->SetInsets(0, 0, 0, item_right_padding); - SetLayoutManager(layout); - - views::ColumnSet* columns = layout->AddColumnSet(0); - columns->AddColumn(views::GridLayout::FILL, - views::GridLayout::FILL, - 0, - views::GridLayout::USE_PREF, - 0, - menu_config.check_width + menu_config.item_left_margin); - columns->AddColumn(views::GridLayout::FILL, - views::GridLayout::FILL, - 1, - views::GridLayout::USE_PREF, - 0, - 0); - - layout->StartRow(0, 0); - views::ImageView* image_view = new views::ImageView(); - image_view->SetImage(icon); - layout->AddView(image_view); - - views::Label* user_name_view = new views::Label(user_name); - user_name_view->SetHorizontalAlignment(gfx::ALIGN_LEFT); - layout->AddView(user_name_view); - - layout->StartRow(0, 0); - views::Label* user_email_view = new views::Label(user_email); - user_email_view->SetHorizontalAlignment(gfx::ALIGN_LEFT); - user_email_view->SetEnabled(false); - layout->SkipColumns(1); - layout->AddView(user_email_view); - } - - private: - DISALLOW_COPY_AND_ASSIGN(CurrentUserView); -}; - -class CurrentUserMenuItem : public MenuItemView { - public: - CurrentUserMenuItem(MenuItemView* parent, - int id, - const base::string16& user_name, - const base::string16& user_email, - const gfx::ImageSkia& icon) - : MenuItemView(parent, id, MenuItemView::NORMAL) { - AddChildView(new CurrentUserView(user_name, user_email, icon)); - } - - private: - DISALLOW_COPY_AND_ASSIGN(CurrentUserMenuItem); -}; - -class AppListMenuModelAdapter : public views::MenuModelAdapter { - public: - AppListMenuModelAdapter(ui::MenuModel* menu_model, - AppListViewDelegate* delegate) - : views::MenuModelAdapter(menu_model), - delegate_(delegate) {} - virtual ~AppListMenuModelAdapter() {} - - // Overridden from views::MenuModelAdapter: - virtual MenuItemView* AppendMenuItem(MenuItemView* menu, - ui::MenuModel* model, - int index) OVERRIDE { - if (!delegate_) - return NULL; - - int id = model->GetCommandIdAt(index); - if (id != AppListMenu::CURRENT_USER) - return MenuModelAdapter::AppendMenuItem(menu, model, index); - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - MenuItemView* item = new CurrentUserMenuItem( - menu, - id, - delegate_->GetCurrentUserName(), - delegate_->GetCurrentUserEmail(), - *rb.GetImageSkiaNamed(IDR_APP_LIST_USER_INDICATOR)); - menu->CreateSubmenu(); - menu->GetSubmenu()->AddChildViewAt(item, index); - return item; - } - - private: - AppListViewDelegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(AppListMenuModelAdapter); -}; - -} // namespace - -AppListMenuViews::AppListMenuViews(AppListViewDelegate* delegate) - : AppListMenu(delegate) { - menu_delegate_.reset(new AppListMenuModelAdapter(menu_model(), delegate)); +AppListMenuViews::AppListMenuViews(AppListViewDelegate* delegate, + AppListModel* app_list_model) + : AppListMenu(delegate, app_list_model->users()) { + menu_delegate_.reset(new views::MenuModelAdapter(menu_model())); menu_ = new MenuItemView(menu_delegate_.get()); menu_runner_.reset(new views::MenuRunner(menu_)); menu_delegate_->BuildMenu(menu_); diff --git a/chromium/ui/app_list/views/app_list_menu_views.h b/chromium/ui/app_list/views/app_list_menu_views.h index 15f3dbb1f85..2dc3d01f046 100644 --- a/chromium/ui/app_list/views/app_list_menu_views.h +++ b/chromium/ui/app_list/views/app_list_menu_views.h @@ -20,11 +20,14 @@ class MenuButton; namespace app_list { +class AppListModel; + // Views implementation of the app list menu. // TODO(benwells): We should consider moving this into Chrome. -class AppListMenuViews : public app_list::AppListMenu { +class AppListMenuViews : public AppListMenu { public: - explicit AppListMenuViews(AppListViewDelegate* delegate); + AppListMenuViews(AppListViewDelegate* delegate, + AppListModel* model); virtual ~AppListMenuViews(); void RunMenuAt(views::MenuButton* button, const gfx::Point& point); diff --git a/chromium/ui/app_list/views/app_list_view.cc b/chromium/ui/app_list/views/app_list_view.cc index 118ab2b3409..ae4647ff2c3 100644 --- a/chromium/ui/app_list/views/app_list_view.cc +++ b/chromium/ui/app_list/views/app_list_view.cc @@ -4,6 +4,7 @@ #include "ui/app_list/views/app_list_view.h" +#include "base/callback.h" #include "base/command_line.h" #include "base/strings/string_util.h" #include "ui/app_list/app_list_constants.h" @@ -37,6 +38,8 @@ namespace app_list { namespace { +base::Closure g_next_paint_callback; + // The distance between the arrow tip and edge of the anchor view. const int kArrowOffset = 10; @@ -51,83 +54,38 @@ AppListView::AppListView(AppListViewDelegate* delegate) app_list_main_view_(NULL), signin_view_(NULL) { if (delegate_) - delegate_->SetModel(model_.get()); - if (GetSigninDelegate()) - GetSigninDelegate()->AddObserver(this); + delegate_->InitModel(model_.get()); + model_->AddObserver(this); } AppListView::~AppListView() { - if (GetSigninDelegate()) - GetSigninDelegate()->RemoveObserver(this); - + model_->RemoveObserver(this); // Models are going away, ensure their references are cleared. RemoveAllChildViews(true); } -void AppListView::InitAsBubble(gfx::NativeView parent, - PaginationModel* pagination_model, - views::View* anchor, - const gfx::Point& anchor_point, - views::BubbleBorder::Arrow arrow, - bool border_accepts_events) { - app_list_main_view_ = new AppListMainView(delegate_.get(), - model_.get(), - pagination_model, - anchor); - AddChildView(app_list_main_view_); -#if defined(USE_AURA) - app_list_main_view_->SetPaintToLayer(true); - app_list_main_view_->SetFillsBoundsOpaquely(false); - app_list_main_view_->layer()->SetMasksToBounds(true); -#endif - - signin_view_ = new SigninView( - GetSigninDelegate(), - app_list_main_view_->GetPreferredSize().width()); - AddChildView(signin_view_); - - OnSigninStatusChanged(); - +void AppListView::InitAsBubbleAttachedToAnchor( + gfx::NativeView parent, + PaginationModel* pagination_model, + views::View* anchor, + const gfx::Vector2d& anchor_offset, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events) { set_anchor_view(anchor); - set_anchor_rect(gfx::Rect(anchor_point, gfx::Size())); - set_color(kContentsBackgroundColor); - set_margins(gfx::Insets()); - set_move_with_anchor(true); - set_parent_window(parent); - set_close_on_deactivate(false); - set_close_on_esc(false); - set_anchor_view_insets(gfx::Insets(kArrowOffset, kArrowOffset, - kArrowOffset, kArrowOffset)); - set_border_accepts_events(border_accepts_events); - set_shadow(views::BubbleBorder::BIG_SHADOW); -#if defined(USE_AURA) && defined(OS_WIN) - if (!ui::win::IsAeroGlassEnabled() || - CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableDwmComposition)) { - set_shadow(views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER); - } -#endif - views::BubbleDelegateView::CreateBubble(this); - SetBubbleArrow(arrow); - -#if defined(USE_AURA) - GetWidget()->GetNativeWindow()->layer()->SetMasksToBounds(true); - GetBubbleFrameView()->set_background(new AppListBackground( - GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), - app_list_main_view_)); - set_background(NULL); -#else - set_background(new AppListBackground( - GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), - app_list_main_view_)); + InitAsBubbleInternal( + parent, pagination_model, arrow, border_accepts_events, anchor_offset); +} - // On non-aura the bubble has two widgets, and it's possible for the border - // to be shown independently in odd situations. Explicitly hide the bubble - // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the - // window manager do not have the SWP_SHOWWINDOW flag set which would cause - // the border to be shown. See http://crbug.com/231687 . - GetWidget()->Hide(); -#endif +void AppListView::InitAsBubbleAtFixedLocation( + gfx::NativeView parent, + PaginationModel* pagination_model, + const gfx::Point& anchor_point_in_screen, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events) { + set_anchor_view(NULL); + set_anchor_rect(gfx::Rect(anchor_point_in_screen, gfx::Size())); + InitAsBubbleInternal( + parent, pagination_model, arrow, border_accepts_events, gfx::Vector2d()); } void AppListView::SetBubbleArrow(views::BubbleBorder::Arrow arrow) { @@ -142,7 +100,7 @@ void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) { } void AppListView::SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host) { + ApplicationDragAndDropHost* drag_and_drop_host) { app_list_main_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); } @@ -166,6 +124,14 @@ gfx::Size AppListView::GetPreferredSize() { return app_list_main_view_->GetPreferredSize(); } +void AppListView::Paint(gfx::Canvas* canvas) { + views::BubbleDelegateView::Paint(canvas); + if (!g_next_paint_callback.is_null()) { + g_next_paint_callback.Run(); + g_next_paint_callback.Reset(); + } +} + bool AppListView::ShouldHandleSystemCommands() const { return true; } @@ -175,14 +141,28 @@ void AppListView::Prerender() { } void AppListView::OnSigninStatusChanged() { - const bool needs_signin = - GetSigninDelegate() && GetSigninDelegate()->NeedSignin(); - - signin_view_->SetVisible(needs_signin); - app_list_main_view_->SetVisible(!needs_signin); + signin_view_->SetVisible(!model_->signed_in()); + app_list_main_view_->SetVisible(model_->signed_in()); app_list_main_view_->search_box_view()->InvalidateMenu(); } +void AppListView::SetProfileByPath(const base::FilePath& profile_path) { + delegate_->SetProfileByPath(profile_path); +} + +void AppListView::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void AppListView::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +// static +void AppListView::SetNextPaintCallback(const base::Closure& callback) { + g_next_paint_callback = callback; +} + #if defined(OS_WIN) HWND AppListView::GetHWND() const { #if defined(USE_AURA) @@ -195,6 +175,71 @@ HWND AppListView::GetHWND() const { } #endif +void AppListView::InitAsBubbleInternal(gfx::NativeView parent, + PaginationModel* pagination_model, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events, + const gfx::Vector2d& anchor_offset) { + app_list_main_view_ = new AppListMainView(delegate_.get(), + model_.get(), + pagination_model, + parent); + AddChildView(app_list_main_view_); +#if defined(USE_AURA) + app_list_main_view_->SetPaintToLayer(true); + app_list_main_view_->SetFillsBoundsOpaquely(false); + app_list_main_view_->layer()->SetMasksToBounds(true); +#endif + + signin_view_ = new SigninView( + delegate_ ? delegate_->GetSigninDelegate() + : NULL, + app_list_main_view_->GetPreferredSize().width()); + AddChildView(signin_view_); + + OnSigninStatusChanged(); + set_color(kContentsBackgroundColor); + set_margins(gfx::Insets()); + set_move_with_anchor(true); + set_parent_window(parent); + set_close_on_deactivate(false); + set_close_on_esc(false); + set_anchor_view_insets(gfx::Insets(kArrowOffset + anchor_offset.y(), + kArrowOffset + anchor_offset.x(), + kArrowOffset - anchor_offset.y(), + kArrowOffset - anchor_offset.x())); + set_border_accepts_events(border_accepts_events); + set_shadow(views::BubbleBorder::BIG_SHADOW); +#if defined(USE_AURA) && defined(OS_WIN) + if (!ui::win::IsAeroGlassEnabled() || + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableDwmComposition)) { + set_shadow(views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER); + } +#endif + views::BubbleDelegateView::CreateBubble(this); + SetBubbleArrow(arrow); + +#if defined(USE_AURA) + GetWidget()->GetNativeWindow()->layer()->SetMasksToBounds(true); + GetBubbleFrameView()->set_background(new AppListBackground( + GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), + app_list_main_view_)); + set_background(NULL); +#else + set_background(new AppListBackground( + GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), + app_list_main_view_)); + + // On non-aura the bubble has two widgets, and it's possible for the border + // to be shown independently in odd situations. Explicitly hide the bubble + // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the + // window manager do not have the SWP_SHOWWINDOW flag set which would cause + // the border to be shown. See http://crbug.com/231687 . + GetWidget()->Hide(); +#endif +} + views::View* AppListView::GetInitiallyFocusedView() { return app_list_main_view_->search_box_view()->search_box(); } @@ -247,8 +292,9 @@ void AppListView::OnWidgetActivationChanged(views::Widget* widget, bool active) { // Do not called inherited function as the bubble delegate auto close // functionality is not used. - if (delegate_ && widget == GetWidget()) - delegate_->ViewActivationChanged(active); + if (widget == GetWidget()) + FOR_EACH_OBSERVER(Observer, observers_, + OnActivationChanged(widget, active)); } void AppListView::OnWidgetVisibilityChanged(views::Widget* widget, @@ -268,12 +314,12 @@ void AppListView::OnWidgetVisibilityChanged(views::Widget* widget, Layout(); } -void AppListView::OnSigninSuccess() { +void AppListView::OnAppListModelSigninStatusChanged() { OnSigninStatusChanged(); } -SigninDelegate* AppListView::GetSigninDelegate() { - return delegate_ ? delegate_->GetSigninDelegate() : NULL; +void AppListView::OnAppListModelUsersChanged() { + OnSigninStatusChanged(); } } // namespace app_list diff --git a/chromium/ui/app_list/views/app_list_view.h b/chromium/ui/app_list/views/app_list_view.h index fff4815ba1b..38564949307 100644 --- a/chromium/ui/app_list/views/app_list_view.h +++ b/chromium/ui/app_list/views/app_list_view.h @@ -5,11 +5,17 @@ #ifndef UI_APP_LIST_VIEWS_APP_LIST_VIEW_H_ #define UI_APP_LIST_VIEWS_APP_LIST_VIEW_H_ +#include "base/callback_forward.h" #include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/signin_delegate_observer.h" +#include "ui/app_list/app_list_model_observer.h" #include "ui/views/bubble/bubble_delegate.h" +namespace base { +class FilePath; +} + namespace views { class Widget; } @@ -26,19 +32,33 @@ class SigninView; // AppListView is the top-level view and controller of app list UI. It creates // and hosts a AppsGridView and passes AppListModel to it for display. class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, - public SigninDelegateObserver { + public AppListModelObserver { public: + class Observer { + public: + virtual void OnActivationChanged(views::Widget* widget, bool active) = 0; + }; + // Takes ownership of |delegate|. explicit AppListView(AppListViewDelegate* delegate); virtual ~AppListView(); - // Initializes the widget. - void InitAsBubble(gfx::NativeView parent, - PaginationModel* pagination_model, - views::View* anchor, - const gfx::Point& anchor_point, - views::BubbleBorder::Arrow arrow, - bool border_accepts_events); + // Initializes the widget and use a given |anchor| plus an |anchor_offset| for + // positioning. + void InitAsBubbleAttachedToAnchor(gfx::NativeView parent, + PaginationModel* pagination_model, + views::View* anchor, + const gfx::Vector2d& anchor_offset, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events); + + // Initializes the widget and use a fixed |anchor_point_in_screen| for + // positioning. + void InitAsBubbleAtFixedLocation(gfx::NativeView parent, + PaginationModel* pagination_model, + const gfx::Point& anchor_point_in_screen, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events); void SetBubbleArrow(views::BubbleBorder::Arrow arrow); @@ -49,7 +69,7 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, // InitAsBubble was called since the app list object needs to exist so that // it can set the host. void SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host); + ApplicationDragAndDropHost* drag_and_drop_host); // Shows the UI when there are no pending icon loads. Otherwise, starts a // timer to show the UI when a maximum allowed wait time has expired. @@ -61,6 +81,7 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, // Overridden from views::View: virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual void Paint(gfx::Canvas* canvas) OVERRIDE; // WidgetDelegate overrides: virtual bool ShouldHandleSystemCommands() const OVERRIDE; @@ -70,11 +91,27 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, // Invoked when the sign-in status is changed to switch on/off sign-in view. void OnSigninStatusChanged(); + void SetProfileByPath(const base::FilePath& profile_path); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Set a callback to be called the next time any app list paints. + static void SetNextPaintCallback(const base::Closure& callback); + #if defined(OS_WIN) HWND GetHWND() const; #endif + AppListModel* model() { return model_.get(); } + private: + void InitAsBubbleInternal(gfx::NativeView parent, + PaginationModel* pagination_model, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events, + const gfx::Vector2d& anchor_offset); + // Overridden from views::WidgetDelegateView: virtual views::View* GetInitiallyFocusedView() OVERRIDE; virtual gfx::ImageSkia GetWindowIcon() OVERRIDE; @@ -92,8 +129,9 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, virtual void OnWidgetActivationChanged( views::Widget* widget, bool active) OVERRIDE; - // Overridden from SigninDelegateObserver: - virtual void OnSigninSuccess() OVERRIDE; + // Overridden from AppListModelObserver: + virtual void OnAppListModelSigninStatusChanged() OVERRIDE; + virtual void OnAppListModelUsersChanged() OVERRIDE; SigninDelegate* GetSigninDelegate(); @@ -103,6 +141,8 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, AppListMainView* app_list_main_view_; SigninView* signin_view_; + ObserverList<Observer> observers_; + DISALLOW_COPY_AND_ASSIGN(AppListView); }; diff --git a/chromium/ui/app_list/views/apps_grid_view.cc b/chromium/ui/app_list/views/apps_grid_view.cc index 1e9b2bfeda5..9135dda7344 100644 --- a/chromium/ui/app_list/views/apps_grid_view.cc +++ b/chromium/ui/app_list/views/apps_grid_view.cc @@ -7,15 +7,15 @@ #include <algorithm> #include "ui/app_list/app_list_item_model.h" -#include "ui/app_list/apps_grid_view_delegate.h" #include "ui/app_list/pagination_model.h" #include "ui/app_list/views/app_list_drag_and_drop_host.h" #include "ui/app_list/views/app_list_item_view.h" +#include "ui/app_list/views/apps_grid_view_delegate.h" #include "ui/app_list/views/page_switcher.h" #include "ui/app_list/views/pulsing_block_view.h" -#include "ui/base/animation/animation.h" -#include "ui/base/events/event.h" #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/events/event.h" +#include "ui/gfx/animation/animation.h" #include "ui/views/border.h" #include "ui/views/view_model_utils.h" #include "ui/views/widget/widget.h" @@ -34,6 +34,8 @@ #include "ui/base/dragdrop/os_exchange_data_provider_win.h" #endif +namespace app_list { + namespace { // Distance a drag needs to be from the app grid to be considered 'outside', at @@ -66,7 +68,7 @@ const int kPrerenderPages = 1; const float kDragAndDropProxyScale = 1.5f; // For testing we remember the last created grid view. -app_list::AppsGridView* last_created_grid_view_for_test = NULL; +AppsGridView* last_created_grid_view_for_test = NULL; // RowMoveAnimationDelegate is used when moving an item into a different row. // Before running the animation, the item's layer is re-created and kept in @@ -86,8 +88,8 @@ class RowMoveAnimationDelegate } virtual ~RowMoveAnimationDelegate() {} - // ui::AnimationDelegate overrides: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE { + // gfx::AnimationDelegate overrides: + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE { view_->layer()->SetOpacity(animation->GetCurrentValue()); view_->layer()->ScheduleDraw(); @@ -98,11 +100,11 @@ class RowMoveAnimationDelegate layer_->ScheduleDraw(); } } - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE { + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE { view_->layer()->SetOpacity(1.0f); view_->layer()->ScheduleDraw(); } - virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE { + virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE { view_->layer()->SetOpacity(1.0f); view_->layer()->ScheduleDraw(); } @@ -120,8 +122,6 @@ class RowMoveAnimationDelegate } // namespace -namespace app_list { - #if defined(OS_WIN) && !defined(USE_AURA) // Interprets drag events sent from Windows via the drag/drop API and forwards // them to AppsGridView. @@ -134,16 +134,15 @@ namespace app_list { // Windows drag that never enters the synchronous drag phase. class SynchronousDrag : public ui::DragSourceWin { public: - SynchronousDrag(app_list::AppsGridView* grid_view, - app_list::AppListItemView* drag_view, - const gfx::Point& drag_view_offset) + SynchronousDrag(AppsGridView* grid_view, + AppListItemView* drag_view, + const gfx::Point& drag_view_offset) : grid_view_(grid_view), drag_view_(drag_view), drag_view_offset_(drag_view_offset), has_shortcut_path_(false), running_(false), - canceled_(false) { - } + canceled_(false) {} void set_shortcut_path(const base::FilePath& shortcut_path) { has_shortcut_path_ = true; @@ -187,8 +186,7 @@ class SynchronousDrag : public ui::DragSourceWin { } virtual void OnDragSourceMove() OVERRIDE { - grid_view_->UpdateDrag(app_list::AppsGridView::MOUSE, - GetCursorInGridViewCoords()); + grid_view_->UpdateDrag(AppsGridView::MOUSE, GetCursorInGridViewCoords()); } void SetupExchangeData(ui::OSExchangeData* data) { @@ -221,8 +219,8 @@ class SynchronousDrag : public ui::DragSourceWin { return grid_view_pt; } - app_list::AppsGridView* grid_view_; - app_list::AppListItemView* drag_view_; + AppsGridView* grid_view_; + AppListItemView* drag_view_; gfx::Point drag_view_offset_; bool has_shortcut_path_; base::FilePath shortcut_path_; @@ -256,6 +254,13 @@ AppsGridView::AppsGridView(AppsGridViewDelegate* delegate, } AppsGridView::~AppsGridView() { + // Coming here |drag_view_| should already be canceled since otherwise the + // drag would disappear after the app list got animated away and closed, + // which would look odd. + DCHECK(!drag_view_); + if (drag_view_) + EndDrag(true); + if (model_) { model_->RemoveObserver(this); model_->apps()->RemoveObserver(this); @@ -347,9 +352,12 @@ void AppsGridView::OnGotShortcutPath(const base::FilePath& path) { void AppsGridView::StartSettingUpSynchronousDrag() { #if defined(OS_WIN) && !defined(USE_AURA) + if (!delegate_) + return; + delegate_->GetShortcutPathForApp( - drag_view_->model()->app_id(), - base::Bind(&AppsGridView::OnGotShortcutPath, base::Unretained(this))); + drag_view_->model()->app_id(), + base::Bind(&AppsGridView::OnGotShortcutPath, base::Unretained(this))); synchronous_drag_ = new SynchronousDrag(this, drag_view_, drag_view_offset_); #endif } @@ -431,7 +439,8 @@ void AppsGridView::EndDrag(bool cancel) { // EndDrag was called before if |drag_view_| is NULL. if (!drag_view_) return; - + // Coming here a drag and drop was in progress. + bool landed_in_drag_and_drop_host = forward_events_to_drag_and_drop_host_; if (forward_events_to_drag_and_drop_host_) { forward_events_to_drag_and_drop_host_ = false; drag_and_drop_host_->EndDrag(cancel); @@ -445,7 +454,17 @@ void AppsGridView::EndDrag(bool cancel) { // If we had a drag and drop proxy icon, we delete it and make the real // item visible again. drag_and_drop_host_->DestroyDragIconProxy(); - HideView(drag_view_, false); + if (landed_in_drag_and_drop_host) { + // Move the item directly to the target location, avoiding the "zip back" + // animation if the user was pinning it to the shelf. + int i = drop_target_.slot; + gfx::Rect bounds = view_model_.ideal_bounds(i); + drag_view_->SetBoundsRect(bounds); + } + // Fade in slowly if it landed in the shelf. + SetViewHidden(drag_view_, + false /* hide */, + !landed_in_drag_and_drop_host /* animate */); } // The drag can be ended after the synchronous drag is created but before it @@ -969,7 +988,9 @@ void AppsGridView::StartDragAndDropHostDrag(const gfx::Point& grid_location) { drag_view_, delta, kDragAndDropProxyScale); - HideView(drag_view_, true); + SetViewHidden(drag_view_, + true /* hide */, + true /* no animation */); } void AppsGridView::DispatchDragEventToDragAndDropHost( @@ -1170,10 +1191,12 @@ void AppsGridView::OnAppListModelStatusChanged() { SchedulePaint(); } -void AppsGridView::HideView(views::View* view, bool hide) { +void AppsGridView::SetViewHidden(views::View* view, bool hide, bool immediate) { #if defined(USE_AURA) ui::ScopedLayerAnimationSettings animator(view->layer()->GetAnimator()); - animator.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); + animator.SetPreemptionStrategy( + immediate ? ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET : + ui::LayerAnimator::BLEND_WITH_CURRENT_ANIMATION); view->layer()->SetOpacity(hide ? 0 : 1); #endif } diff --git a/chromium/ui/app_list/views/apps_grid_view.h b/chromium/ui/app_list/views/apps_grid_view.h index 9c201641f15..2b7b51d0b88 100644 --- a/chromium/ui/app_list/views/apps_grid_view.h +++ b/chromium/ui/app_list/views/apps_grid_view.h @@ -135,7 +135,7 @@ class APP_LIST_EXPORT AppsGridView : public views::View, } private: - friend class app_list::test::AppsGridViewTestApi; + friend class test::AppsGridViewTestApi; // Represents the index to an item view in the grid. struct Index { @@ -246,8 +246,10 @@ class APP_LIST_EXPORT AppsGridView : public views::View, virtual void OnAppListModelStatusChanged() OVERRIDE; // Hide a given view temporarily without losing (mouse) events and / or - // changing the size of it. - void HideView(views::View* view, bool hide); + // changing the size of it. If |immediate| is set the change will be + // immediately applied - otherwise it will change gradually. + // If |hide| is set the view will get hidden, otherwise it gets shown. + void SetViewHidden(views::View* view, bool hide, bool immediate); AppListModel* model_; // Owned by AppListView. AppsGridViewDelegate* delegate_; diff --git a/chromium/ui/app_list/views/apps_grid_view_delegate.h b/chromium/ui/app_list/views/apps_grid_view_delegate.h new file mode 100644 index 00000000000..83430b0fa40 --- /dev/null +++ b/chromium/ui/app_list/views/apps_grid_view_delegate.h @@ -0,0 +1,37 @@ +// Copyright 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. + +#ifndef UI_APP_LIST_VIEWS_APPS_GRID_VIEW_DELEGATE_H_ +#define UI_APP_LIST_VIEWS_APPS_GRID_VIEW_DELEGATE_H_ + +#include "base/callback_forward.h" +#include "ui/app_list/app_list_export.h" + +namespace base { +class FilePath; +} + +namespace app_list { + +class AppListItemModel; + +class APP_LIST_EXPORT AppsGridViewDelegate { + public: + // Invoked when an item is activated on the grid view. |event_flags| contains + // the flags of the keyboard/mouse event that triggers the activation request. + virtual void ActivateApp(AppListItemModel* item, int event_flags) = 0; + + // Gets the path to a shortcut for the app represented by |item|. |callback| + // may be run immediately. + virtual void GetShortcutPathForApp( + const std::string& app_id, + const base::Callback<void(const base::FilePath&)>& callback) = 0; + + protected: + virtual ~AppsGridViewDelegate() {} +}; + +} // namespace app_list + +#endif // UI_APP_LIST_VIEWS_APPS_GRID_VIEW_DELEGATE_H_ diff --git a/chromium/ui/app_list/views/apps_grid_view_unittest.cc b/chromium/ui/app_list/views/apps_grid_view_unittest.cc index 87d5f672c12..9e0cc5c0340 100644 --- a/chromium/ui/app_list/views/apps_grid_view_unittest.cc +++ b/chromium/ui/app_list/views/apps_grid_view_unittest.cc @@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/strings/utf_string_conversions.h" #include "base/timer/timer.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_item_model.h" @@ -47,10 +48,14 @@ class PageFlipWaiter : public PaginationModelObserver { DCHECK(!wait_); wait_ = true; page_changed_ = false; - wait_timer_.Stop(); - wait_timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(time_out_ms), - this, &PageFlipWaiter::OnWaitTimeOut); + + if (time_out_ms) { + wait_timer_.Stop(); + wait_timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(time_out_ms), + this, &PageFlipWaiter::OnWaitTimeOut); + } + ui_loop_->Run(); wait_ = false; return page_changed_; @@ -260,15 +265,7 @@ TEST_F(AppsGridViewTest, MouseDrag) { test_api_->LayoutToIdealBounds(); } -// Test fails sometimes on chrome os. -// http://crbug.com/242248 -#if defined(OS_CHROMEOS) -#define MAYBE_MouseDragFlipPage DISABLED_MouseDragFlipPage -#else -#define MAYBE_MouseDragFlipPage MouseDragFlipPage -#endif // defined(OS_CHROMEOS) - -TEST_F(AppsGridViewTest, MAYBE_MouseDragFlipPage) { +TEST_F(AppsGridViewTest, MouseDragFlipPage) { test_api_->SetPageFlipDelay(10); pagination_model_->SetTransitionDurations(10, 10); @@ -288,11 +285,11 @@ TEST_F(AppsGridViewTest, MAYBE_MouseDragFlipPage) { SimulateDrag(AppsGridView::MOUSE, from, to); // Page should be flipped after sometime. - EXPECT_TRUE(page_flip_waiter.Wait(100)); + EXPECT_TRUE(page_flip_waiter.Wait(0)); EXPECT_EQ(1, pagination_model_->selected_page()); // Stay there and page should be flipped again. - EXPECT_TRUE(page_flip_waiter.Wait(100)); + EXPECT_TRUE(page_flip_waiter.Wait(0)); EXPECT_EQ(2, pagination_model_->selected_page()); // Stay there longer and no page flip happen since we are at the last page. @@ -306,10 +303,10 @@ TEST_F(AppsGridViewTest, MAYBE_MouseDragFlipPage) { SimulateDrag(AppsGridView::MOUSE, from, to); - EXPECT_TRUE(page_flip_waiter.Wait(100)); + EXPECT_TRUE(page_flip_waiter.Wait(0)); EXPECT_EQ(1, pagination_model_->selected_page()); - EXPECT_TRUE(page_flip_waiter.Wait(100)); + EXPECT_TRUE(page_flip_waiter.Wait(0)); EXPECT_EQ(0, pagination_model_->selected_page()); EXPECT_FALSE(page_flip_waiter.Wait(100)); @@ -428,5 +425,37 @@ TEST_F(AppsGridViewTest, HighlightWithKeyboard) { first_index_on_page2))); } +TEST_F(AppsGridViewTest, ItemLabelShortNameOverride) { + // If the app's full name and short name differ, the title label's tooltip + // should always be the full name of the app. + std::string expected_text("xyz"); + std::string expected_tooltip("tooltip"); + model_->AddItem(expected_text, expected_tooltip); + + string16 actual_tooltip; + AppListItemView* item_view = GetItemViewAt(0); + ASSERT_TRUE(item_view); + const views::Label* title_label = item_view->title(); + EXPECT_TRUE(title_label->GetTooltipText( + title_label->bounds().CenterPoint(), &actual_tooltip)); + EXPECT_EQ(expected_tooltip, UTF16ToUTF8(actual_tooltip)); + EXPECT_EQ(expected_text, UTF16ToUTF8(title_label->text())); +} + +TEST_F(AppsGridViewTest, ItemLabelNoShortName) { + // If the app's full name and short name are the same, use the default tooltip + // behavior of the label (only show a tooltip if the title is truncated). + std::string title("a"); + model_->AddItem(title, title); + + string16 actual_tooltip; + AppListItemView* item_view = GetItemViewAt(0); + ASSERT_TRUE(item_view); + const views::Label* title_label = item_view->title(); + EXPECT_FALSE(title_label->GetTooltipText( + title_label->bounds().CenterPoint(), &actual_tooltip)); + EXPECT_EQ(title, UTF16ToUTF8(title_label->text())); +} + } // namespace test } // namespace app_list diff --git a/chromium/ui/app_list/views/contents_view.cc b/chromium/ui/app_list/views/contents_view.cc index 5211eb1e6d7..3ecc276b75f 100644 --- a/chromium/ui/app_list/views/contents_view.cc +++ b/chromium/ui/app_list/views/contents_view.cc @@ -12,7 +12,7 @@ #include "ui/app_list/views/app_list_main_view.h" #include "ui/app_list/views/apps_grid_view.h" #include "ui/app_list/views/search_result_list_view.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/animation/bounds_animator.h" #include "ui/views/view_model.h" #include "ui/views/view_model_utils.h" @@ -76,8 +76,13 @@ ContentsView::ContentsView(AppListMainView* app_list_main_view, ContentsView::~ContentsView() { } +void ContentsView::CancelDrag() { + if (apps_grid_view_ && apps_grid_view_->has_dragged_view()) + apps_grid_view_->EndDrag(true); +} + void ContentsView::SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host) { + ApplicationDragAndDropHost* drag_and_drop_host) { apps_grid_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); } diff --git a/chromium/ui/app_list/views/contents_view.h b/chromium/ui/app_list/views/contents_view.h index f0b974cf12b..b9447734b50 100644 --- a/chromium/ui/app_list/views/contents_view.h +++ b/chromium/ui/app_list/views/contents_view.h @@ -34,10 +34,13 @@ class ContentsView : public views::View { AppListModel* model); virtual ~ContentsView(); + // The app list gets closed and drag and drop operations need to be cancelled. + void CancelDrag(); + // If |drag_and_drop| is not NULL it will be called upon drag and drop // operations outside the application list. void SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host); + ApplicationDragAndDropHost* drag_and_drop_host); void ShowSearchResults(bool show); diff --git a/chromium/ui/app_list/views/page_switcher.cc b/chromium/ui/app_list/views/page_switcher.cc index 665b0230713..99e9749d154 100644 --- a/chromium/ui/app_list/views/page_switcher.cc +++ b/chromium/ui/app_list/views/page_switcher.cc @@ -9,12 +9,14 @@ #include "third_party/skia/include/core/SkPath.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/pagination_model.h" -#include "ui/base/animation/throb_animation.h" +#include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/skia_util.h" #include "ui/views/controls/button/custom_button.h" #include "ui/views/layout/box_layout.h" +namespace app_list { + namespace { const int kPreferredHeight = 57; @@ -52,11 +54,10 @@ class PageSwitcherButton : public views::CustomButton { } virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { - if (state() == STATE_HOVERED) { - PaintButton(canvas, app_list::kPagerHoverColor); - } else { - PaintButton(canvas, app_list::kPagerNormalColor); - } + if (state() == STATE_HOVERED) + PaintButton(canvas, kPagerHoverColor); + else + PaintButton(canvas, kPagerNormalColor); } private: @@ -94,7 +95,7 @@ class PageSwitcherButton : public views::CustomButton { selected_path.addRoundRect(gfx::RectToSkRect(selected_rect), SkIntToScalar(kButtonCornerRadius), SkIntToScalar(kButtonCornerRadius)); - paint.setColor(app_list::kPagerSelectedColor); + paint.setColor(kPagerSelectedColor); canvas->DrawPath(selected_path, paint); } } @@ -116,8 +117,6 @@ PageSwitcherButton* GetButtonByIndex(views::View* buttons, int index) { } // namespace -namespace app_list { - PageSwitcher::PageSwitcher(PaginationModel* model) : model_(model), buttons_(new views::View) { diff --git a/chromium/ui/app_list/views/search_box_view.cc b/chromium/ui/app_list/views/search_box_view.cc index 1d997e5e7ef..9b96d3eec0a 100644 --- a/chromium/ui/app_list/views/search_box_view.cc +++ b/chromium/ui/app_list/views/search_box_view.cc @@ -9,10 +9,10 @@ #include "grit/ui_resources.h" #include "ui/app_list/app_list_model.h" #include "ui/app_list/search_box_model.h" -#include "ui/app_list/search_box_view_delegate.h" #include "ui/app_list/views/app_list_menu_views.h" -#include "ui/base/events/event.h" +#include "ui/app_list/views/search_box_view_delegate.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/event.h" #include "ui/views/controls/button/menu_button.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/textfield/textfield.h" @@ -40,7 +40,7 @@ SearchBoxView::SearchBoxView(SearchBoxViewDelegate* delegate, AppListModel* model) : delegate_(delegate), view_delegate_(view_delegate), - model_(model->search_box()), + model_(model), icon_view_(new views::ImageView), search_box_(new views::Textfield), contents_view_(NULL) { @@ -65,13 +65,13 @@ SearchBoxView::SearchBoxView(SearchBoxViewDelegate* delegate, search_box_->SetController(this); AddChildView(search_box_); - model_->AddObserver(this); + model_->search_box()->AddObserver(this); IconChanged(); HintTextChanged(); } SearchBoxView::~SearchBoxView() { - model_->RemoveObserver(this); + model_->search_box()->RemoveObserver(this); } bool SearchBoxView::HasSearch() const { @@ -132,10 +132,10 @@ bool SearchBoxView::OnMouseWheel(const ui::MouseWheelEvent& event) { void SearchBoxView::UpdateModel() { // Temporarily remove from observer to ignore notifications caused by us. - model_->RemoveObserver(this); - model_->SetText(search_box_->text()); - model_->SetSelectionModel(search_box_->GetSelectionModel()); - model_->AddObserver(this); + model_->search_box()->RemoveObserver(this); + model_->search_box()->SetText(search_box_->text()); + model_->search_box()->SetSelectionModel(search_box_->GetSelectionModel()); + model_->search_box()->AddObserver(this); } void SearchBoxView::NotifyQueryChanged() { @@ -160,7 +160,7 @@ bool SearchBoxView::HandleKeyEvent(views::Textfield* sender, void SearchBoxView::OnMenuButtonClicked(View* source, const gfx::Point& point) { if (!menu_) - menu_.reset(new AppListMenuViews(view_delegate_)); + menu_.reset(new AppListMenuViews(view_delegate_, model_)); const gfx::Point menu_location = menu_button_->GetBoundsInScreen().bottom_right() + @@ -169,19 +169,20 @@ void SearchBoxView::OnMenuButtonClicked(View* source, const gfx::Point& point) { } void SearchBoxView::IconChanged() { - icon_view_->SetImage(model_->icon()); + icon_view_->SetImage(model_->search_box()->icon()); } void SearchBoxView::HintTextChanged() { - search_box_->set_placeholder_text(model_->hint_text()); + search_box_->set_placeholder_text(model_->search_box()->hint_text()); } void SearchBoxView::SelectionModelChanged() { - search_box_->SelectSelectionModel(model_->selection_model()); + search_box_->SelectSelectionModel(model_->search_box()->selection_model()); } void SearchBoxView::TextChanged() { - search_box_->SetText(model_->text()); + search_box_->SetText(model_->search_box()->text()); + NotifyQueryChanged(); } } // namespace app_list diff --git a/chromium/ui/app_list/views/search_box_view.h b/chromium/ui/app_list/views/search_box_view.h index 439a4cf291b..c06990262a5 100644 --- a/chromium/ui/app_list/views/search_box_view.h +++ b/chromium/ui/app_list/views/search_box_view.h @@ -21,8 +21,8 @@ class Textfield; namespace app_list { class AppListMenuViews; -class AppListViewDelegate; class AppListModel; +class AppListViewDelegate; class SearchBoxModel; class SearchBoxViewDelegate; @@ -80,7 +80,7 @@ class SearchBoxView : public views::View, SearchBoxViewDelegate* delegate_; // Not owned. AppListViewDelegate* view_delegate_; // Not owned. - SearchBoxModel* model_; // Owned by AppListModel. + AppListModel* model_; // Owned by AppListView. scoped_ptr<AppListMenuViews> menu_; diff --git a/chromium/ui/app_list/views/search_box_view_delegate.h b/chromium/ui/app_list/views/search_box_view_delegate.h new file mode 100644 index 00000000000..cdbf23878bb --- /dev/null +++ b/chromium/ui/app_list/views/search_box_view_delegate.h @@ -0,0 +1,25 @@ +// Copyright 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. + +#ifndef UI_APP_LIST_VIEWS_SEARCH_BOX_VIEW_DELEGATE_H_ +#define UI_APP_LIST_VIEWS_SEARCH_BOX_VIEW_DELEGATE_H_ + +#include "ui/app_list/app_list_export.h" + +namespace app_list { + +class SearchBoxView; + +class APP_LIST_EXPORT SearchBoxViewDelegate { + public: + // Invoked when query text has changed by the user. + virtual void QueryChanged(SearchBoxView* sender) = 0; + + protected: + virtual ~SearchBoxViewDelegate() {} +}; + +} // namespace app_list + +#endif // UI_APP_LIST_VIEWS_SEARCH_BOX_VIEW_DELEGATE_H_ diff --git a/chromium/ui/app_list/views/search_result_list_view.cc b/chromium/ui/app_list/views/search_result_list_view.cc index 5eaad3c688f..3387cecad10 100644 --- a/chromium/ui/app_list/views/search_result_list_view.cc +++ b/chromium/ui/app_list/views/search_result_list_view.cc @@ -8,9 +8,9 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" -#include "ui/app_list/search_result_list_view_delegate.h" +#include "ui/app_list/views/search_result_list_view_delegate.h" #include "ui/app_list/views/search_result_view.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/layout/box_layout.h" namespace { diff --git a/chromium/ui/app_list/views/search_result_list_view_delegate.h b/chromium/ui/app_list/views/search_result_list_view_delegate.h new file mode 100644 index 00000000000..405094b31a5 --- /dev/null +++ b/chromium/ui/app_list/views/search_result_list_view_delegate.h @@ -0,0 +1,40 @@ +// Copyright 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. + +#ifndef UI_APP_LIST_VIEWS_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ +#define UI_APP_LIST_VIEWS_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ + +#include "ui/app_list/app_list_export.h" + +namespace app_list { + +class SearchResult; + +class APP_LIST_EXPORT SearchResultListViewDelegate { + public: + // Invoked to open given |result|. |event_flags| contains the flags of the + // keyboard/mouse event that triggers the "open" request. Delegate could use + // the |event_flags| information to choose different ways to open the result. + virtual void OpenResult(SearchResult* result, + int event_flags) = 0; + + // Called to invoke a custom action on |result|. |action_index| corresponds + // to the index of the icon in |result.action_icons()| that was activated. + virtual void InvokeResultAction(SearchResult* result, + int action_index, + int event_flags) = 0; + + // Called when the app represented by |result| is installed. + virtual void OnResultInstalled(SearchResult* result) = 0; + + // Called when the app represented by |result| is uninstalled. + virtual void OnResultUninstalled(SearchResult* result) = 0; + + protected: + virtual ~SearchResultListViewDelegate() {} +}; + +} // namespace app_list + +#endif // UI_APP_LIST_VIEWS_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ diff --git a/chromium/ui/app_list/views/search_result_view.cc b/chromium/ui/app_list/views/search_result_view.cc index 55b9e0b653d..9e7fe51f648 100644 --- a/chromium/ui/app_list/views/search_result_view.cc +++ b/chromium/ui/app_list/views/search_result_view.cc @@ -20,6 +20,8 @@ #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/controls/menu/menu_runner.h" +namespace app_list { + namespace { const int kPreferredWidth = 300; @@ -36,24 +38,24 @@ const int kActionButtonRightMargin = 8; // Creates a RenderText of given |text| and |styles|. Caller takes ownership // of returned RenderText. gfx::RenderText* CreateRenderText(const base::string16& text, - const app_list::SearchResult::Tags& tags) { + const SearchResult::Tags& tags) { gfx::RenderText* render_text = gfx::RenderText::CreateInstance(); render_text->SetText(text); - render_text->SetColor(app_list::kResultDefaultTextColor); + render_text->SetColor(kResultDefaultTextColor); - for (app_list::SearchResult::Tags::const_iterator it = tags.begin(); + for (SearchResult::Tags::const_iterator it = tags.begin(); it != tags.end(); ++it) { // NONE means default style so do nothing. - if (it->styles == app_list::SearchResult::Tag::NONE) + if (it->styles == SearchResult::Tag::NONE) continue; - if (it->styles & app_list::SearchResult::Tag::MATCH) + if (it->styles & SearchResult::Tag::MATCH) render_text->ApplyStyle(gfx::BOLD, true, it->range); - if (it->styles & app_list::SearchResult::Tag::DIM) - render_text->ApplyColor(app_list::kResultDimmedTextColor, it->range); - else if (it->styles & app_list::SearchResult::Tag::URL) - render_text->ApplyColor(app_list::kResultURLTextColor, it->range); + if (it->styles & SearchResult::Tag::DIM) + render_text->ApplyColor(kResultDimmedTextColor, it->range); + else if (it->styles & SearchResult::Tag::URL) + render_text->ApplyColor(kResultURLTextColor, it->range); } return render_text; @@ -61,8 +63,6 @@ gfx::RenderText* CreateRenderText(const base::string16& text, } // namespace -namespace app_list { - // static const char SearchResultView::kViewClassName[] = "ui/app_list/SearchResultView"; |