Commit f29b8e7c authored by David Black's avatar David Black Committed by Commit Bot

Reland "Rough in support for multiple selection in holding space."

This is a reland of 5aa92900

Original change's description:
> Rough in support for multiple selection in holding space.
>
> Holding space needs to support selection of multiple holding space items
> to perform bulk context menu and drag/drop operations on them at a time.
>
> This CL refactors HoldingSpaceItemContextMenu into a shared
> HoldingSpaceItemViewDelegate to facilitate these requirements.
>
> Note that this CL does not change any existing behavior, just lays the
> groundwork for supporting multiple selection.
>
> Bug: 1129981
> Change-Id: If4da6c19ba01bd7104a1b1487350c362d7be1dd4
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2419136
> Commit-Queue: David Black <dmblack@google.com>
> Reviewed-by: Ahmed Mehfooz <amehfooz@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#809625}

Bug: 1129981
Change-Id: I122a335d92a3df5e51933fc2eadf35080d0e87c0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2425894
Commit-Queue: David Black <dmblack@google.com>
Reviewed-by: default avatarAhmed Mehfooz <amehfooz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#810054}
parent 1da6cb8a
...@@ -926,12 +926,12 @@ component("ash") { ...@@ -926,12 +926,12 @@ component("ash") {
"system/holding_space/holding_space_item_chip_view.h", "system/holding_space/holding_space_item_chip_view.h",
"system/holding_space/holding_space_item_chips_container.cc", "system/holding_space/holding_space_item_chips_container.cc",
"system/holding_space/holding_space_item_chips_container.h", "system/holding_space/holding_space_item_chips_container.h",
"system/holding_space/holding_space_item_context_menu.cc",
"system/holding_space/holding_space_item_context_menu.h",
"system/holding_space/holding_space_item_screenshot_view.cc", "system/holding_space/holding_space_item_screenshot_view.cc",
"system/holding_space/holding_space_item_screenshot_view.h", "system/holding_space/holding_space_item_screenshot_view.h",
"system/holding_space/holding_space_item_view.cc", "system/holding_space/holding_space_item_view.cc",
"system/holding_space/holding_space_item_view.h", "system/holding_space/holding_space_item_view.h",
"system/holding_space/holding_space_item_view_delegate.cc",
"system/holding_space/holding_space_item_view_delegate.h",
"system/holding_space/holding_space_item_views_container.cc", "system/holding_space/holding_space_item_views_container.cc",
"system/holding_space/holding_space_item_views_container.h", "system/holding_space/holding_space_item_views_container.h",
"system/holding_space/holding_space_tray.cc", "system/holding_space/holding_space_tray.cc",
......
...@@ -30,8 +30,10 @@ ...@@ -30,8 +30,10 @@
namespace ash { namespace ash {
HoldingSpaceItemChipView::HoldingSpaceItemChipView(const HoldingSpaceItem* item) HoldingSpaceItemChipView::HoldingSpaceItemChipView(
: HoldingSpaceItemView(item) { HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item)
: HoldingSpaceItemView(delegate, item) {
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, views::BoxLayout::Orientation::kHorizontal,
gfx::Insets(kHoldingSpaceChipPadding), kHoldingSpaceChipChildSpacing)); gfx::Insets(kHoldingSpaceChipPadding), kHoldingSpaceChipChildSpacing));
......
...@@ -21,6 +21,7 @@ class ToggleImageButton; ...@@ -21,6 +21,7 @@ class ToggleImageButton;
namespace ash { namespace ash {
class HoldingSpaceItem; class HoldingSpaceItem;
class HoldingSpaceItemViewDelegate;
namespace tray { namespace tray {
class RoundedImageView; class RoundedImageView;
...@@ -33,7 +34,8 @@ class ASH_EXPORT HoldingSpaceItemChipView : public HoldingSpaceItemView, ...@@ -33,7 +34,8 @@ class ASH_EXPORT HoldingSpaceItemChipView : public HoldingSpaceItemView,
public: public:
METADATA_HEADER(HoldingSpaceItemChipView); METADATA_HEADER(HoldingSpaceItemChipView);
explicit HoldingSpaceItemChipView(const HoldingSpaceItem* item); HoldingSpaceItemChipView(HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item);
HoldingSpaceItemChipView(const HoldingSpaceItemChipView&) = delete; HoldingSpaceItemChipView(const HoldingSpaceItemChipView&) = delete;
HoldingSpaceItemChipView& operator=(const HoldingSpaceItemChipView&) = delete; HoldingSpaceItemChipView& operator=(const HoldingSpaceItemChipView&) = delete;
~HoldingSpaceItemChipView() override; ~HoldingSpaceItemChipView() override;
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
#include "ash/system/holding_space/holding_space_item_chips_container.h" #include "ash/system/holding_space/holding_space_item_chips_container.h"
#include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_constants.h"
#include "ash/public/cpp/holding_space/holding_space_item.h"
#include "ash/system/holding_space/holding_space_item_chip_view.h"
#include "base/debug/stack_trace.h"
#include "ui/views/layout/layout_manager_base.h" #include "ui/views/layout/layout_manager_base.h"
#include "ui/views/layout/proposed_layout.h" #include "ui/views/layout/proposed_layout.h"
......
...@@ -10,8 +10,7 @@ ...@@ -10,8 +10,7 @@
namespace ash { namespace ash {
// A container view which automatically arranges item chips into a 2 column // A container view which arranges item chips into a 2 column grid.
// grid.
class HoldingSpaceItemChipsContainer : public views::View { class HoldingSpaceItemChipsContainer : public views::View {
public: public:
HoldingSpaceItemChipsContainer(); HoldingSpaceItemChipsContainer();
......
// Copyright 2020 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 ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_
#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_
#include <memory>
#include "ash/ash_export.h"
#include "ash/public/cpp/holding_space/holding_space_item.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/context_menu_controller.h"
namespace views {
class MenuRunner;
} // namespace views
namespace ash {
// This class handles creation of the context menu view and handling
// commands available in the menu.
class ASH_EXPORT HoldingSpaceItemContextMenu
: public views::ContextMenuController,
public ui::SimpleMenuModel::Delegate {
public:
explicit HoldingSpaceItemContextMenu(const HoldingSpaceItem* item);
HoldingSpaceItemContextMenu(const HoldingSpaceItemContextMenu&) = delete;
HoldingSpaceItemContextMenu& operator=(const HoldingSpaceItemContextMenu&) =
delete;
~HoldingSpaceItemContextMenu() override;
// views::ContextMenuController:
void ShowContextMenuForViewImpl(views::View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) override;
// SimpleMenuModel::Delegate:
void ExecuteCommand(int command_id, int event_flags) override;
private:
ui::SimpleMenuModel* BuildMenuModel();
std::unique_ptr<ui::SimpleMenuModel> context_menu_model_;
std::unique_ptr<views::MenuRunner> context_menu_runner_;
// The holding space item that this context menu's actions will effect.
const HoldingSpaceItem* const item_;
};
} // namespace ash
#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_
...@@ -16,8 +16,9 @@ ...@@ -16,8 +16,9 @@
namespace ash { namespace ash {
HoldingSpaceItemScreenshotView::HoldingSpaceItemScreenshotView( HoldingSpaceItemScreenshotView::HoldingSpaceItemScreenshotView(
HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item) const HoldingSpaceItem* item)
: HoldingSpaceItemView(item) { : HoldingSpaceItemView(delegate, item) {
SetLayoutManager(std::make_unique<views::FillLayout>()); SetLayoutManager(std::make_unique<views::FillLayout>());
image_ = AddChildView( image_ = AddChildView(
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
namespace ash { namespace ash {
class HoldingSpaceItem; class HoldingSpaceItem;
class HoldingSpaceItemViewDelegate;
namespace tray { namespace tray {
class RoundedImageView; class RoundedImageView;
...@@ -22,7 +23,8 @@ class ASH_EXPORT HoldingSpaceItemScreenshotView : public HoldingSpaceItemView { ...@@ -22,7 +23,8 @@ class ASH_EXPORT HoldingSpaceItemScreenshotView : public HoldingSpaceItemView {
public: public:
METADATA_HEADER(HoldingSpaceItemScreenshotView); METADATA_HEADER(HoldingSpaceItemScreenshotView);
explicit HoldingSpaceItemScreenshotView(const HoldingSpaceItem* item); HoldingSpaceItemScreenshotView(HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item);
HoldingSpaceItemScreenshotView(const HoldingSpaceItemScreenshotView&) = HoldingSpaceItemScreenshotView(const HoldingSpaceItemScreenshotView&) =
delete; delete;
HoldingSpaceItemScreenshotView& operator=( HoldingSpaceItemScreenshotView& operator=(
......
...@@ -4,43 +4,38 @@ ...@@ -4,43 +4,38 @@
#include "ash/system/holding_space/holding_space_item_view.h" #include "ash/system/holding_space/holding_space_item_view.h"
#include "ash/public/cpp/holding_space/holding_space_client.h"
#include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_constants.h"
#include "ash/public/cpp/holding_space/holding_space_controller.h"
#include "ash/public/cpp/holding_space/holding_space_item.h" #include "ash/public/cpp/holding_space/holding_space_item.h"
#include "ash/public/cpp/shelf_config.h" #include "ash/public/cpp/shelf_config.h"
#include "ash/strings/grit/ash_strings.h" #include "ash/system/holding_space/holding_space_item_view_delegate.h"
#include "ash/system/holding_space/holding_space_item_context_menu.h" #include "ui/base/class_property.h"
#include "base/bind_helpers.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/focus_ring.h" #include "ui/views/controls/focus_ring.h"
#include "ui/views/controls/highlight_path_generator.h" #include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/metadata/metadata_impl_macros.h" #include "ui/views/metadata/metadata_impl_macros.h"
namespace ash { namespace ash {
namespace { namespace {
// Helpers --------------------------------------------------------------------- // A UI class property used to identify if a view is an instance of
// `HoldingSpaceItemView`. Class name is not an adequate identifier as it may be
// Attempts to open the specified holding space `item`. // overridden by subclasses.
void OpenItem(const HoldingSpaceItem& item) { DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsHoldingSpaceItemViewProperty, false)
HoldingSpaceController::Get()->client()->OpenItem(item, base::DoNothing());
}
} // namespace } // namespace
// HoldingSpaceItemView -------------------------------------------------------- // HoldingSpaceItemView --------------------------------------------------------
HoldingSpaceItemView::HoldingSpaceItemView(const HoldingSpaceItem* item) HoldingSpaceItemView::HoldingSpaceItemView(
: item_(item), HoldingSpaceItemViewDelegate* delegate,
context_menu_(std::make_unique<HoldingSpaceItemContextMenu>(item_)) { const HoldingSpaceItem* item)
set_context_menu_controller(context_menu_.get()); : delegate_(delegate), item_(item) {
SetProperty(kIsHoldingSpaceItemViewProperty, true);
set_context_menu_controller(delegate_);
set_drag_controller(delegate_);
SetPaintToLayer(); SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false); layer()->SetFillsBoundsOpaquely(false);
...@@ -64,10 +59,14 @@ HoldingSpaceItemView::HoldingSpaceItemView(const HoldingSpaceItem* item) ...@@ -64,10 +59,14 @@ HoldingSpaceItemView::HoldingSpaceItemView(const HoldingSpaceItem* item)
kHoldingSpaceCornerRadius); kHoldingSpaceCornerRadius);
} }
HoldingSpaceItemView::~HoldingSpaceItemView() = default; HoldingSpaceItemView::~HoldingSpaceItemView() {
delegate_->OnHoldingSpaceItemViewDestroyed(this);
}
int HoldingSpaceItemView::GetDragOperations(const gfx::Point& point) { // static
return ui::DragDropTypes::DRAG_COPY; HoldingSpaceItemView* HoldingSpaceItemView::Cast(views::View* view) {
DCHECK(view->GetProperty(kIsHoldingSpaceItemViewProperty));
return static_cast<HoldingSpaceItemView*>(view);
} }
SkColor HoldingSpaceItemView::GetInkDropBaseColor() const { SkColor HoldingSpaceItemView::GetInkDropBaseColor() const {
...@@ -75,29 +74,15 @@ SkColor HoldingSpaceItemView::GetInkDropBaseColor() const { ...@@ -75,29 +74,15 @@ SkColor HoldingSpaceItemView::GetInkDropBaseColor() const {
} }
void HoldingSpaceItemView::OnGestureEvent(ui::GestureEvent* event) { void HoldingSpaceItemView::OnGestureEvent(ui::GestureEvent* event) {
if (event->type() == ui::ET_GESTURE_TAP) delegate_->OnHoldingSpaceItemViewGestureEvent(this, *event);
OpenItem(*item());
} }
bool HoldingSpaceItemView::OnKeyPressed(const ui::KeyEvent& event) { bool HoldingSpaceItemView::OnKeyPressed(const ui::KeyEvent& event) {
if (event.key_code() == ui::KeyboardCode::VKEY_RETURN) { return delegate_->OnHoldingSpaceItemViewKeyPressed(this, event);
OpenItem(*item());
return true;
}
return false;
} }
bool HoldingSpaceItemView::OnMousePressed(const ui::MouseEvent& event) { bool HoldingSpaceItemView::OnMousePressed(const ui::MouseEvent& event) {
if (event.flags() & ui::EF_IS_DOUBLE_CLICK) { return delegate_->OnHoldingSpaceItemViewMousePressed(this, event);
OpenItem(*item());
return true;
}
return false;
}
void HoldingSpaceItemView::WriteDragData(const gfx::Point& point,
ui::OSExchangeData* data) {
data->SetFilename(item_->file_path());
} }
void HoldingSpaceItemView::SetSelected(bool selected) { void HoldingSpaceItemView::SetSelected(bool selected) {
......
...@@ -5,35 +5,34 @@ ...@@ -5,35 +5,34 @@
#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_ #ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_
#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_ #define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_
#include <memory>
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/views/animation/ink_drop_host_view.h" #include "ui/views/animation/ink_drop_host_view.h"
#include "ui/views/metadata/metadata_header_macros.h" #include "ui/views/metadata/metadata_header_macros.h"
namespace ash { namespace ash {
class HoldingSpaceItem; class HoldingSpaceItem;
class HoldingSpaceItemContextMenu; class HoldingSpaceItemViewDelegate;
// Base class for HoldingSpaceItemChipView and HoldingSpaceItemScreenshotView. // Base class for HoldingSpaceItemChipView and HoldingSpaceItemScreenshotView.
class ASH_EXPORT HoldingSpaceItemView : public views::InkDropHostView { class ASH_EXPORT HoldingSpaceItemView : public views::InkDropHostView {
public: public:
METADATA_HEADER(HoldingSpaceItemView); METADATA_HEADER(HoldingSpaceItemView);
explicit HoldingSpaceItemView(const HoldingSpaceItem* item); HoldingSpaceItemView(HoldingSpaceItemViewDelegate*, const HoldingSpaceItem*);
HoldingSpaceItemView(const HoldingSpaceItemView&) = delete; HoldingSpaceItemView(const HoldingSpaceItemView&) = delete;
HoldingSpaceItemView& operator=(const HoldingSpaceItemView&) = delete; HoldingSpaceItemView& operator=(const HoldingSpaceItemView&) = delete;
~HoldingSpaceItemView() override; ~HoldingSpaceItemView() override;
// Returns `view` cast as a `HoldingSpaceItemView`. Note that this performs a
// DCHECK to assert that `view` is in fact a `HoldingSpaceItemView` instance.
static HoldingSpaceItemView* Cast(views::View* view);
// views::InkDropHostView: // views::InkDropHostView:
int GetDragOperations(const gfx::Point& point) override;
SkColor GetInkDropBaseColor() const override; SkColor GetInkDropBaseColor() const override;
void OnGestureEvent(ui::GestureEvent* event) override; void OnGestureEvent(ui::GestureEvent* event) override;
bool OnKeyPressed(const ui::KeyEvent& event) override; bool OnKeyPressed(const ui::KeyEvent& event) override;
bool OnMousePressed(const ui::MouseEvent& event) override; bool OnMousePressed(const ui::MouseEvent& event) override;
void WriteDragData(const gfx::Point& point, ui::OSExchangeData*) override;
const HoldingSpaceItem* item() const { return item_; } const HoldingSpaceItem* item() const { return item_; }
...@@ -41,8 +40,8 @@ class ASH_EXPORT HoldingSpaceItemView : public views::InkDropHostView { ...@@ -41,8 +40,8 @@ class ASH_EXPORT HoldingSpaceItemView : public views::InkDropHostView {
bool selected() const { return selected_; } bool selected() const { return selected_; }
private: private:
HoldingSpaceItemViewDelegate* delegate_;
const HoldingSpaceItem* const item_; const HoldingSpaceItem* const item_;
std::unique_ptr<HoldingSpaceItemContextMenu> const context_menu_;
// Whether or not this view is selected. // Whether or not this view is selected.
bool selected_ = false; bool selected_ = false;
......
...@@ -2,17 +2,19 @@ ...@@ -2,17 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "ash/system/holding_space/holding_space_item_context_menu.h" #include "ash/system/holding_space/holding_space_item_view_delegate.h"
#include "ash/public/cpp/holding_space/holding_space_client.h" #include "ash/public/cpp/holding_space/holding_space_client.h"
#include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_constants.h"
#include "ash/public/cpp/holding_space/holding_space_controller.h" #include "ash/public/cpp/holding_space/holding_space_controller.h"
#include "ash/public/cpp/holding_space/holding_space_item.h"
#include "ash/public/cpp/holding_space/holding_space_model.h" #include "ash/public/cpp/holding_space/holding_space_model.h"
#include "ash/resources/vector_icons/vector_icons.h" #include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h" #include "ash/strings/grit/ash_strings.h"
#include "ash/system/holding_space/holding_space_item_view.h" #include "ash/system/holding_space/holding_space_item_view.h"
#include "base/bind.h" #include "base/bind.h"
#include "net/base/mime_util.h" #include "net/base/mime_util.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/simple_menu_model.h" #include "ui/base/models/simple_menu_model.h"
#include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/menu/menu_runner.h"
...@@ -21,16 +23,79 @@ ...@@ -21,16 +23,79 @@
namespace ash { namespace ash {
HoldingSpaceItemContextMenu::HoldingSpaceItemContextMenu( namespace {
const HoldingSpaceItem* item)
: item_(item) {}
HoldingSpaceItemContextMenu::~HoldingSpaceItemContextMenu() = default; // It is expected that all `HoldingSpaceItemView`s share the same delegate in
// order to support multiple selections. We cache the singleton `instance` in
// order to enforce this requirement.
HoldingSpaceItemViewDelegate* instance = nullptr;
void HoldingSpaceItemContextMenu::ShowContextMenuForViewImpl( // Helpers ---------------------------------------------------------------------
// Attempts to open the specified holding space `item`.
void OpenItem(const HoldingSpaceItem& item) {
HoldingSpaceController::Get()->client()->OpenItem(item, base::DoNothing());
}
} // namespace
// HoldingSpaceItemViewDelegate ------------------------------------------------
HoldingSpaceItemViewDelegate::HoldingSpaceItemViewDelegate() {
DCHECK_EQ(nullptr, instance);
instance = this;
}
HoldingSpaceItemViewDelegate::~HoldingSpaceItemViewDelegate() {
DCHECK_EQ(instance, this);
instance = nullptr;
}
// TODO(dmblack): Implement multiple selection.
void HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewGestureEvent(
HoldingSpaceItemView* view,
const ui::GestureEvent& event) {
if (event.type() == ui::ET_GESTURE_TAP)
OpenItem(*view->item());
}
// TODO(dmblack): Handle multiple selection.
bool HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewKeyPressed(
HoldingSpaceItemView* view,
const ui::KeyEvent& event) {
if (event.key_code() == ui::KeyboardCode::VKEY_RETURN) {
OpenItem(*view->item());
return true;
}
return false;
}
// TODO(dmblack): Handle multiple selection.
bool HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewMousePressed(
HoldingSpaceItemView* view,
const ui::MouseEvent& event) {
if (event.flags() & ui::EF_IS_DOUBLE_CLICK) {
OpenItem(*view->item());
return true;
}
return false;
}
void HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewDestroyed(
HoldingSpaceItemView* view) {
selected_views_by_item_id_.erase(view->item()->id());
}
// TODO(dmblack): Handle multiple selection.
void HoldingSpaceItemViewDelegate::ShowContextMenuForViewImpl(
views::View* source, views::View* source,
const gfx::Point& point, const gfx::Point& point,
ui::MenuSourceType source_type) { ui::MenuSourceType source_type) {
selected_views_by_item_id_.clear();
HoldingSpaceItemView* selected_view = HoldingSpaceItemView::Cast(source);
selected_views_by_item_id_[selected_view->item()->id()] = selected_view;
int run_types = views::MenuRunner::USE_TOUCHABLE_LAYOUT | int run_types = views::MenuRunner::USE_TOUCHABLE_LAYOUT |
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::CONTEXT_MENU |
views::MenuRunner::FIXED_ANCHOR; views::MenuRunner::FIXED_ANCHOR;
...@@ -44,27 +109,65 @@ void HoldingSpaceItemContextMenu::ShowContextMenuForViewImpl( ...@@ -44,27 +109,65 @@ void HoldingSpaceItemContextMenu::ShowContextMenuForViewImpl(
source_type); source_type);
} }
void HoldingSpaceItemContextMenu::ExecuteCommand(int command_id, // TODO(dmblack): Handle multiple selection.
int event_flags) { bool HoldingSpaceItemViewDelegate::CanStartDragForView(
views::View* sender,
const gfx::Point& press_pt,
const gfx::Point& current_pt) {
selected_views_by_item_id_.clear();
HoldingSpaceItemView* selected_view = HoldingSpaceItemView::Cast(sender);
selected_views_by_item_id_[selected_view->item()->id()] = selected_view;
return true;
}
int HoldingSpaceItemViewDelegate::GetDragOperationsForView(
views::View* sender,
const gfx::Point& press_pt) {
return ui::DragDropTypes::DRAG_COPY;
}
// TODO(dmblack): Handle multiple selection.
void HoldingSpaceItemViewDelegate::WriteDragDataForView(
views::View* sender,
const gfx::Point& press_pt,
ui::OSExchangeData* data) {
DCHECK_EQ(1u, selected_views_by_item_id_.size());
auto* selected_view = selected_views_by_item_id_.begin()->second;
data->SetFilename(selected_view->item()->file_path());
}
// TODO(dmblack): Handle multiple selection.
void HoldingSpaceItemViewDelegate::ExecuteCommand(int command_id,
int event_flags) {
DCHECK_EQ(1u, selected_views_by_item_id_.size());
auto* selected_view = selected_views_by_item_id_.begin()->second;
switch (command_id) { switch (command_id) {
case HoldingSpaceCommandId::kCopyImageToClipboard: case HoldingSpaceCommandId::kCopyImageToClipboard:
HoldingSpaceController::Get()->client()->CopyImageToClipboard( HoldingSpaceController::Get()->client()->CopyImageToClipboard(
*item_, base::DoNothing()); *selected_view->item(), base::DoNothing());
break; break;
case HoldingSpaceCommandId::kPinItem: case HoldingSpaceCommandId::kPinItem:
HoldingSpaceController::Get()->client()->PinItem(*item_); HoldingSpaceController::Get()->client()->PinItem(*selected_view->item());
break; break;
case HoldingSpaceCommandId::kShowInFolder: case HoldingSpaceCommandId::kShowInFolder:
HoldingSpaceController::Get()->client()->ShowItemInFolder( HoldingSpaceController::Get()->client()->ShowItemInFolder(
*item_, base::DoNothing()); *selected_view->item(), base::DoNothing());
break; break;
case HoldingSpaceCommandId::kUnpinItem: case HoldingSpaceCommandId::kUnpinItem:
HoldingSpaceController::Get()->client()->UnpinItem(*item_); HoldingSpaceController::Get()->client()->UnpinItem(
*selected_view->item());
break; break;
} }
} }
ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() { // TODO(dmblack): Handle multiple selection.
ui::SimpleMenuModel* HoldingSpaceItemViewDelegate::BuildMenuModel() {
DCHECK_EQ(1u, selected_views_by_item_id_.size());
auto* selected_view = selected_views_by_item_id_.begin()->second;
context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this); context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
context_menu_model_->AddItemWithIcon( context_menu_model_->AddItemWithIcon(
HoldingSpaceCommandId::kShowInFolder, HoldingSpaceCommandId::kShowInFolder,
...@@ -73,9 +176,9 @@ ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() { ...@@ -73,9 +176,9 @@ ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() {
ui::ImageModel::FromVectorIcon(kFolderIcon)); ui::ImageModel::FromVectorIcon(kFolderIcon));
std::string mime_type; std::string mime_type;
const bool is_image = const bool is_image = net::GetMimeTypeFromFile(
net::GetMimeTypeFromFile(item_->file_path(), &mime_type) && selected_view->item()->file_path(), &mime_type) &&
net::MatchesMimeType(kMimeTypeImage, mime_type); net::MatchesMimeType(kMimeTypeImage, mime_type);
if (is_image) { if (is_image) {
context_menu_model_->AddItemWithIcon( context_menu_model_->AddItemWithIcon(
...@@ -86,8 +189,10 @@ ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() { ...@@ -86,8 +189,10 @@ ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() {
} }
const bool is_pinned = HoldingSpaceController::Get()->model()->GetItem( const bool is_pinned = HoldingSpaceController::Get()->model()->GetItem(
HoldingSpaceItem::GetFileBackedItemId(HoldingSpaceItem::Type::kPinnedFile, HoldingSpaceItem::GetFileBackedItemId(
item_->file_path())); HoldingSpaceItem::Type::kPinnedFile,
selected_view->item()->file_path()));
if (!is_pinned) { if (!is_pinned) {
context_menu_model_->AddItemWithIcon( context_menu_model_->AddItemWithIcon(
HoldingSpaceCommandId::kPinItem, HoldingSpaceCommandId::kPinItem,
......
// Copyright 2020 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 ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_
#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_
#include <map>
#include <memory>
#include <string>
#include "ash/ash_export.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/drag_controller.h"
namespace ui {
class GestureEvent;
class KeyEvent;
class MouseEvent;
} // namespace ui
namespace views {
class MenuRunner;
} // namespace views
namespace ash {
class HoldingSpaceItemView;
// TODO(dmblack): Implement multiple selection.
// A delegate for `HoldingSpaceItemView`s which implements context menu,
// drag-and-drop, and selection functionality. In order to support multiple
// selections at a time, all `HoldingSpaceItemView`s must share the same
// `HoldingSpaceItemViewDelegate` instance.
class ASH_EXPORT HoldingSpaceItemViewDelegate
: public views::ContextMenuController,
public views::DragController,
public ui::SimpleMenuModel::Delegate {
public:
HoldingSpaceItemViewDelegate();
HoldingSpaceItemViewDelegate(const HoldingSpaceItemViewDelegate&) = delete;
HoldingSpaceItemViewDelegate& operator=(const HoldingSpaceItemViewDelegate&) =
delete;
~HoldingSpaceItemViewDelegate() override;
// Invoked when `view` receives the specified gesture `event`.
void OnHoldingSpaceItemViewGestureEvent(HoldingSpaceItemView* view,
const ui::GestureEvent& event);
// Invoked when `view` receives the specified key pressed `event`.
bool OnHoldingSpaceItemViewKeyPressed(HoldingSpaceItemView* view,
const ui::KeyEvent& event);
// Invoked when `view` receives the specified mouse pressed `event`.
bool OnHoldingSpaceItemViewMousePressed(HoldingSpaceItemView* view,
const ui::MouseEvent& event);
// Invoked when `view` has been destroyed.
void OnHoldingSpaceItemViewDestroyed(HoldingSpaceItemView* view);
private:
// views::ContextMenuController:
void ShowContextMenuForViewImpl(views::View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) override;
// views::DragController:
bool CanStartDragForView(views::View* sender,
const gfx::Point& press_pt,
const gfx::Point& current_pt) override;
int GetDragOperationsForView(views::View* sender,
const gfx::Point& press_pt) override;
void WriteDragDataForView(views::View* sender,
const gfx::Point& press_pt,
ui::OSExchangeData* data) override;
// SimpleMenuModel::Delegate:
void ExecuteCommand(int command_id, int event_flags) override;
// Builds and returns a raw pointer to `context_menu_model_`.
ui::SimpleMenuModel* BuildMenuModel();
std::unique_ptr<ui::SimpleMenuModel> context_menu_model_;
std::unique_ptr<views::MenuRunner> context_menu_runner_;
std::map<std::string, HoldingSpaceItemView*> selected_views_by_item_id_;
};
} // namespace ash
#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_
...@@ -64,8 +64,11 @@ HoldingSpaceTray::HoldingSpaceTray(Shelf* shelf) : TrayBackgroundView(shelf) { ...@@ -64,8 +64,11 @@ HoldingSpaceTray::HoldingSpaceTray(Shelf* shelf) : TrayBackgroundView(shelf) {
} }
HoldingSpaceTray::~HoldingSpaceTray() { HoldingSpaceTray::~HoldingSpaceTray() {
if (bubble_) if (bubble_) {
// View hierarchy must not outlive `this`.
bubble_->bubble_view()->ResetDelegate(); bubble_->bubble_view()->ResetDelegate();
bubble_->GetBubbleWidget()->CloseNow();
}
} }
bool HoldingSpaceTray::ContainsPointInScreen(const gfx::Point& point) { bool HoldingSpaceTray::ContainsPointInScreen(const gfx::Point& point) {
...@@ -149,8 +152,8 @@ void HoldingSpaceTray::ShowBubble(bool show_by_click) { ...@@ -149,8 +152,8 @@ void HoldingSpaceTray::ShowBubble(bool show_by_click) {
bubble_view->set_margins(GetSecondaryBubbleInsets()); bubble_view->set_margins(GetSecondaryBubbleInsets());
// Add pinned files container. // Add pinned files container.
pinned_files_container_ = pinned_files_container_ = bubble_view->AddChildView(
bubble_view->AddChildView(std::make_unique<PinnedFilesContainer>()); std::make_unique<PinnedFilesContainer>(&delegate_));
SetupChildLayer(pinned_files_container_); SetupChildLayer(pinned_files_container_);
// Separator between the two containers, gives illusion of 2 separate bubbles. // Separator between the two containers, gives illusion of 2 separate bubbles.
...@@ -159,8 +162,8 @@ void HoldingSpaceTray::ShowBubble(bool show_by_click) { ...@@ -159,8 +162,8 @@ void HoldingSpaceTray::ShowBubble(bool show_by_click) {
separator->SetBorder(views::CreateEmptyBorder( separator->SetBorder(views::CreateEmptyBorder(
gfx::Insets(kHoldingSpaceContainerSpacing, 0, 0, 0))); gfx::Insets(kHoldingSpaceContainerSpacing, 0, 0, 0)));
recent_files_container_ = recent_files_container_ = bubble_view->AddChildView(
bubble_view->AddChildView(std::make_unique<RecentFilesContainer>()); std::make_unique<RecentFilesContainer>(&delegate_));
SetupChildLayer(recent_files_container_); SetupChildLayer(recent_files_container_);
// Show the bubble. // Show the bubble.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/system/holding_space/holding_space_item_view_delegate.h"
#include "ash/system/tray/tray_background_view.h" #include "ash/system/tray/tray_background_view.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
...@@ -58,6 +59,10 @@ class ASH_EXPORT HoldingSpaceTray : public TrayBackgroundView { ...@@ -58,6 +59,10 @@ class ASH_EXPORT HoldingSpaceTray : public TrayBackgroundView {
bool ShouldEnableExtraKeyboardAccessibility() override; bool ShouldEnableExtraKeyboardAccessibility() override;
void HideBubble(const TrayBubbleView* bubble_view) override; void HideBubble(const TrayBubbleView* bubble_view) override;
// The singleton delegate for `HoldingSpaceItemView`s that implements support
// for context menu, drag-and-drop, and multiple selection.
HoldingSpaceItemViewDelegate delegate_;
std::unique_ptr<TrayBubbleWrapper> bubble_; std::unique_ptr<TrayBubbleWrapper> bubble_;
PinnedFilesContainer* pinned_files_container_ = nullptr; PinnedFilesContainer* pinned_files_container_ = nullptr;
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
namespace ash { namespace ash {
PinnedFilesContainer::PinnedFilesContainer() { PinnedFilesContainer::PinnedFilesContainer(
HoldingSpaceItemViewDelegate* delegate)
: delegate_(delegate) {
SetID(kHoldingSpacePinnedFilesContainerId); SetID(kHoldingSpacePinnedFilesContainerId);
SetLayoutManager(std::make_unique<views::BoxLayout>( SetLayoutManager(std::make_unique<views::BoxLayout>(
...@@ -52,7 +54,8 @@ void PinnedFilesContainer::AddHoldingSpaceItemView( ...@@ -52,7 +54,8 @@ void PinnedFilesContainer::AddHoldingSpaceItemView(
if (item->type() == HoldingSpaceItem::Type::kPinnedFile) { if (item->type() == HoldingSpaceItem::Type::kPinnedFile) {
views_by_item_id_[item->id()] = item_chips_container_->AddChildViewAt( views_by_item_id_[item->id()] = item_chips_container_->AddChildViewAt(
std::make_unique<HoldingSpaceItemChipView>(item), 0 /*index*/); std::make_unique<HoldingSpaceItemChipView>(delegate_, item),
/*index=*/0);
} }
} }
......
...@@ -12,11 +12,12 @@ ...@@ -12,11 +12,12 @@
namespace ash { namespace ash {
class HoldingSpaceItemChipsContainer; class HoldingSpaceItemChipsContainer;
class HoldingSpaceItemViewDelegate;
// Container for pinned files that the user adds to the holding space bubble. // Container for pinned files that the user adds to the holding space bubble.
class PinnedFilesContainer : public HoldingSpaceItemViewsContainer { class PinnedFilesContainer : public HoldingSpaceItemViewsContainer {
public: public:
PinnedFilesContainer(); explicit PinnedFilesContainer(HoldingSpaceItemViewDelegate* delegate);
PinnedFilesContainer(const PinnedFilesContainer& other) = delete; PinnedFilesContainer(const PinnedFilesContainer& other) = delete;
PinnedFilesContainer& operator=(const PinnedFilesContainer& other) = delete; PinnedFilesContainer& operator=(const PinnedFilesContainer& other) = delete;
~PinnedFilesContainer() override; ~PinnedFilesContainer() override;
...@@ -27,6 +28,7 @@ class PinnedFilesContainer : public HoldingSpaceItemViewsContainer { ...@@ -27,6 +28,7 @@ class PinnedFilesContainer : public HoldingSpaceItemViewsContainer {
void RemoveHoldingSpaceItemView(const HoldingSpaceItem* item) override; void RemoveHoldingSpaceItemView(const HoldingSpaceItem* item) override;
private: private:
HoldingSpaceItemViewDelegate* const delegate_;
HoldingSpaceItemChipsContainer* item_chips_container_ = nullptr; HoldingSpaceItemChipsContainer* item_chips_container_ = nullptr;
std::map<std::string, views::View*> views_by_item_id_; std::map<std::string, views::View*> views_by_item_id_;
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
namespace ash { namespace ash {
RecentFilesContainer::RecentFilesContainer() { RecentFilesContainer::RecentFilesContainer(
HoldingSpaceItemViewDelegate* delegate)
: delegate_(delegate) {
SetID(kHoldingSpaceRecentFilesContainerId); SetID(kHoldingSpaceRecentFilesContainerId);
SetLayoutManager(std::make_unique<views::BoxLayout>( SetLayoutManager(std::make_unique<views::BoxLayout>(
...@@ -66,10 +68,12 @@ void RecentFilesContainer::AddHoldingSpaceItemView( ...@@ -66,10 +68,12 @@ void RecentFilesContainer::AddHoldingSpaceItemView(
DCHECK(!base::Contains(views_by_item_id_, item->id())); DCHECK(!base::Contains(views_by_item_id_, item->id()));
if (item->type() == HoldingSpaceItem::Type::kScreenshot) { if (item->type() == HoldingSpaceItem::Type::kScreenshot) {
views_by_item_id_[item->id()] = screenshots_container_->AddChildViewAt( views_by_item_id_[item->id()] = screenshots_container_->AddChildViewAt(
std::make_unique<HoldingSpaceItemScreenshotView>(item), 0 /*index*/); std::make_unique<HoldingSpaceItemScreenshotView>(delegate_, item),
/*index=*/0);
} else if (item->type() == HoldingSpaceItem::Type::kDownload) { } else if (item->type() == HoldingSpaceItem::Type::kDownload) {
views_by_item_id_[item->id()] = recent_downloads_container_->AddChildViewAt( views_by_item_id_[item->id()] = recent_downloads_container_->AddChildViewAt(
std::make_unique<HoldingSpaceItemChipView>(item), 0 /*index*/); std::make_unique<HoldingSpaceItemChipView>(delegate_, item),
/*index=*/0);
} }
} }
...@@ -84,13 +88,13 @@ void RecentFilesContainer::RemoveHoldingSpaceItemView( ...@@ -84,13 +88,13 @@ void RecentFilesContainer::RemoveHoldingSpaceItemView(
auto it = views_by_item_id_.find(item->id()); auto it = views_by_item_id_.find(item->id());
if (it == views_by_item_id_.end()) if (it == views_by_item_id_.end())
return; return;
views::View* view = it->second;
if (item->type() == HoldingSpaceItem::Type::kScreenshot) { if (item->type() == HoldingSpaceItem::Type::kScreenshot) {
screenshots_container_->RemoveChildViewT(view); screenshots_container_->RemoveChildViewT(it->second);
} else if (item->type() == HoldingSpaceItem::Type::kDownload) { } else if (item->type() == HoldingSpaceItem::Type::kDownload) {
recent_downloads_container_->RemoveChildViewT(view); recent_downloads_container_->RemoveChildViewT(it->second);
} }
views_by_item_id_.erase(it); views_by_item_id_.erase(it);
} }
......
...@@ -12,11 +12,12 @@ ...@@ -12,11 +12,12 @@
namespace ash { namespace ash {
class HoldingSpaceItemChipsContainer; class HoldingSpaceItemChipsContainer;
class HoldingSpaceItemViewDelegate;
// Container for the recent files (Screenshots, downloads etc). // Container for the recent files (Screenshots, downloads etc).
class RecentFilesContainer : public HoldingSpaceItemViewsContainer { class RecentFilesContainer : public HoldingSpaceItemViewsContainer {
public: public:
RecentFilesContainer(); explicit RecentFilesContainer(HoldingSpaceItemViewDelegate* delegate);
RecentFilesContainer(const RecentFilesContainer& other) = delete; RecentFilesContainer(const RecentFilesContainer& other) = delete;
RecentFilesContainer& operator=(const RecentFilesContainer& other) = delete; RecentFilesContainer& operator=(const RecentFilesContainer& other) = delete;
~RecentFilesContainer() override; ~RecentFilesContainer() override;
...@@ -27,6 +28,7 @@ class RecentFilesContainer : public HoldingSpaceItemViewsContainer { ...@@ -27,6 +28,7 @@ class RecentFilesContainer : public HoldingSpaceItemViewsContainer {
void RemoveHoldingSpaceItemView(const HoldingSpaceItem* item) override; void RemoveHoldingSpaceItemView(const HoldingSpaceItem* item) override;
private: private:
HoldingSpaceItemViewDelegate* const delegate_;
views::View* screenshots_container_ = nullptr; views::View* screenshots_container_ = nullptr;
HoldingSpaceItemChipsContainer* recent_downloads_container_ = nullptr; HoldingSpaceItemChipsContainer* recent_downloads_container_ = nullptr;
......
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