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") {
"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.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.h",
"system/holding_space/holding_space_item_view.cc",
"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.h",
"system/holding_space/holding_space_tray.cc",
......
......@@ -30,8 +30,10 @@
namespace ash {
HoldingSpaceItemChipView::HoldingSpaceItemChipView(const HoldingSpaceItem* item)
: HoldingSpaceItemView(item) {
HoldingSpaceItemChipView::HoldingSpaceItemChipView(
HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item)
: HoldingSpaceItemView(delegate, item) {
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal,
gfx::Insets(kHoldingSpaceChipPadding), kHoldingSpaceChipChildSpacing));
......
......@@ -21,6 +21,7 @@ class ToggleImageButton;
namespace ash {
class HoldingSpaceItem;
class HoldingSpaceItemViewDelegate;
namespace tray {
class RoundedImageView;
......@@ -33,7 +34,8 @@ class ASH_EXPORT HoldingSpaceItemChipView : public HoldingSpaceItemView,
public:
METADATA_HEADER(HoldingSpaceItemChipView);
explicit HoldingSpaceItemChipView(const HoldingSpaceItem* item);
HoldingSpaceItemChipView(HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item);
HoldingSpaceItemChipView(const HoldingSpaceItemChipView&) = delete;
HoldingSpaceItemChipView& operator=(const HoldingSpaceItemChipView&) = delete;
~HoldingSpaceItemChipView() override;
......
......@@ -5,9 +5,6 @@
#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_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/proposed_layout.h"
......
......@@ -10,8 +10,7 @@
namespace ash {
// A container view which automatically arranges item chips into a 2 column
// grid.
// A container view which arranges item chips into a 2 column grid.
class HoldingSpaceItemChipsContainer : public views::View {
public:
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 @@
namespace ash {
HoldingSpaceItemScreenshotView::HoldingSpaceItemScreenshotView(
HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item)
: HoldingSpaceItemView(item) {
: HoldingSpaceItemView(delegate, item) {
SetLayoutManager(std::make_unique<views::FillLayout>());
image_ = AddChildView(
......
......@@ -13,6 +13,7 @@
namespace ash {
class HoldingSpaceItem;
class HoldingSpaceItemViewDelegate;
namespace tray {
class RoundedImageView;
......@@ -22,7 +23,8 @@ class ASH_EXPORT HoldingSpaceItemScreenshotView : public HoldingSpaceItemView {
public:
METADATA_HEADER(HoldingSpaceItemScreenshotView);
explicit HoldingSpaceItemScreenshotView(const HoldingSpaceItem* item);
HoldingSpaceItemScreenshotView(HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item);
HoldingSpaceItemScreenshotView(const HoldingSpaceItemScreenshotView&) =
delete;
HoldingSpaceItemScreenshotView& operator=(
......
......@@ -4,43 +4,38 @@
#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_controller.h"
#include "ash/public/cpp/holding_space/holding_space_item.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/holding_space/holding_space_item_context_menu.h"
#include "base/bind_helpers.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/l10n/l10n_util.h"
#include "ash/system/holding_space/holding_space_item_view_delegate.h"
#include "ui/base/class_property.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/focus_ring.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"
namespace ash {
namespace {
// Helpers ---------------------------------------------------------------------
// Attempts to open the specified holding space `item`.
void OpenItem(const HoldingSpaceItem& item) {
HoldingSpaceController::Get()->client()->OpenItem(item, base::DoNothing());
}
// 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
// overridden by subclasses.
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsHoldingSpaceItemViewProperty, false)
} // namespace
// HoldingSpaceItemView --------------------------------------------------------
HoldingSpaceItemView::HoldingSpaceItemView(const HoldingSpaceItem* item)
: item_(item),
context_menu_(std::make_unique<HoldingSpaceItemContextMenu>(item_)) {
set_context_menu_controller(context_menu_.get());
HoldingSpaceItemView::HoldingSpaceItemView(
HoldingSpaceItemViewDelegate* delegate,
const HoldingSpaceItem* item)
: delegate_(delegate), item_(item) {
SetProperty(kIsHoldingSpaceItemViewProperty, true);
set_context_menu_controller(delegate_);
set_drag_controller(delegate_);
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
......@@ -64,10 +59,14 @@ HoldingSpaceItemView::HoldingSpaceItemView(const HoldingSpaceItem* item)
kHoldingSpaceCornerRadius);
}
HoldingSpaceItemView::~HoldingSpaceItemView() = default;
HoldingSpaceItemView::~HoldingSpaceItemView() {
delegate_->OnHoldingSpaceItemViewDestroyed(this);
}
int HoldingSpaceItemView::GetDragOperations(const gfx::Point& point) {
return ui::DragDropTypes::DRAG_COPY;
// static
HoldingSpaceItemView* HoldingSpaceItemView::Cast(views::View* view) {
DCHECK(view->GetProperty(kIsHoldingSpaceItemViewProperty));
return static_cast<HoldingSpaceItemView*>(view);
}
SkColor HoldingSpaceItemView::GetInkDropBaseColor() const {
......@@ -75,29 +74,15 @@ SkColor HoldingSpaceItemView::GetInkDropBaseColor() const {
}
void HoldingSpaceItemView::OnGestureEvent(ui::GestureEvent* event) {
if (event->type() == ui::ET_GESTURE_TAP)
OpenItem(*item());
delegate_->OnHoldingSpaceItemViewGestureEvent(this, *event);
}
bool HoldingSpaceItemView::OnKeyPressed(const ui::KeyEvent& event) {
if (event.key_code() == ui::KeyboardCode::VKEY_RETURN) {
OpenItem(*item());
return true;
}
return false;
return delegate_->OnHoldingSpaceItemViewKeyPressed(this, event);
}
bool HoldingSpaceItemView::OnMousePressed(const ui::MouseEvent& event) {
if (event.flags() & ui::EF_IS_DOUBLE_CLICK) {
OpenItem(*item());
return true;
}
return false;
}
void HoldingSpaceItemView::WriteDragData(const gfx::Point& point,
ui::OSExchangeData* data) {
data->SetFilename(item_->file_path());
return delegate_->OnHoldingSpaceItemViewMousePressed(this, event);
}
void HoldingSpaceItemView::SetSelected(bool selected) {
......
......@@ -5,35 +5,34 @@
#ifndef 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 "ui/base/dragdrop/drag_drop_types.h"
#include "ui/views/animation/ink_drop_host_view.h"
#include "ui/views/metadata/metadata_header_macros.h"
namespace ash {
class HoldingSpaceItem;
class HoldingSpaceItemContextMenu;
class HoldingSpaceItemViewDelegate;
// Base class for HoldingSpaceItemChipView and HoldingSpaceItemScreenshotView.
class ASH_EXPORT HoldingSpaceItemView : public views::InkDropHostView {
public:
METADATA_HEADER(HoldingSpaceItemView);
explicit HoldingSpaceItemView(const HoldingSpaceItem* item);
HoldingSpaceItemView(HoldingSpaceItemViewDelegate*, const HoldingSpaceItem*);
HoldingSpaceItemView(const HoldingSpaceItemView&) = delete;
HoldingSpaceItemView& operator=(const HoldingSpaceItemView&) = delete;
~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:
int GetDragOperations(const gfx::Point& point) override;
SkColor GetInkDropBaseColor() const override;
void OnGestureEvent(ui::GestureEvent* event) override;
bool OnKeyPressed(const ui::KeyEvent& event) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
void WriteDragData(const gfx::Point& point, ui::OSExchangeData*) override;
const HoldingSpaceItem* item() const { return item_; }
......@@ -41,8 +40,8 @@ class ASH_EXPORT HoldingSpaceItemView : public views::InkDropHostView {
bool selected() const { return selected_; }
private:
HoldingSpaceItemViewDelegate* delegate_;
const HoldingSpaceItem* const item_;
std::unique_ptr<HoldingSpaceItemContextMenu> const context_menu_;
// Whether or not this view is selected.
bool selected_ = false;
......
......@@ -2,17 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// 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_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_model.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/holding_space/holding_space_item_view.h"
#include "base/bind.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/models/simple_menu_model.h"
#include "ui/views/controls/menu/menu_runner.h"
......@@ -21,16 +23,79 @@
namespace ash {
HoldingSpaceItemContextMenu::HoldingSpaceItemContextMenu(
const HoldingSpaceItem* item)
: item_(item) {}
namespace {
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,
const gfx::Point& point,
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 |
views::MenuRunner::CONTEXT_MENU |
views::MenuRunner::FIXED_ANCHOR;
......@@ -44,27 +109,65 @@ void HoldingSpaceItemContextMenu::ShowContextMenuForViewImpl(
source_type);
}
void HoldingSpaceItemContextMenu::ExecuteCommand(int command_id,
int event_flags) {
// TODO(dmblack): Handle multiple selection.
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) {
case HoldingSpaceCommandId::kCopyImageToClipboard:
HoldingSpaceController::Get()->client()->CopyImageToClipboard(
*item_, base::DoNothing());
*selected_view->item(), base::DoNothing());
break;
case HoldingSpaceCommandId::kPinItem:
HoldingSpaceController::Get()->client()->PinItem(*item_);
HoldingSpaceController::Get()->client()->PinItem(*selected_view->item());
break;
case HoldingSpaceCommandId::kShowInFolder:
HoldingSpaceController::Get()->client()->ShowItemInFolder(
*item_, base::DoNothing());
*selected_view->item(), base::DoNothing());
break;
case HoldingSpaceCommandId::kUnpinItem:
HoldingSpaceController::Get()->client()->UnpinItem(*item_);
HoldingSpaceController::Get()->client()->UnpinItem(
*selected_view->item());
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_->AddItemWithIcon(
HoldingSpaceCommandId::kShowInFolder,
......@@ -73,9 +176,9 @@ ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() {
ui::ImageModel::FromVectorIcon(kFolderIcon));
std::string mime_type;
const bool is_image =
net::GetMimeTypeFromFile(item_->file_path(), &mime_type) &&
net::MatchesMimeType(kMimeTypeImage, mime_type);
const bool is_image = net::GetMimeTypeFromFile(
selected_view->item()->file_path(), &mime_type) &&
net::MatchesMimeType(kMimeTypeImage, mime_type);
if (is_image) {
context_menu_model_->AddItemWithIcon(
......@@ -86,8 +189,10 @@ ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() {
}
const bool is_pinned = HoldingSpaceController::Get()->model()->GetItem(
HoldingSpaceItem::GetFileBackedItemId(HoldingSpaceItem::Type::kPinnedFile,
item_->file_path()));
HoldingSpaceItem::GetFileBackedItemId(
HoldingSpaceItem::Type::kPinnedFile,
selected_view->item()->file_path()));
if (!is_pinned) {
context_menu_model_->AddItemWithIcon(
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) {
}
HoldingSpaceTray::~HoldingSpaceTray() {
if (bubble_)
if (bubble_) {
// View hierarchy must not outlive `this`.
bubble_->bubble_view()->ResetDelegate();
bubble_->GetBubbleWidget()->CloseNow();
}
}
bool HoldingSpaceTray::ContainsPointInScreen(const gfx::Point& point) {
......@@ -149,8 +152,8 @@ void HoldingSpaceTray::ShowBubble(bool show_by_click) {
bubble_view->set_margins(GetSecondaryBubbleInsets());
// Add pinned files container.
pinned_files_container_ =
bubble_view->AddChildView(std::make_unique<PinnedFilesContainer>());
pinned_files_container_ = bubble_view->AddChildView(
std::make_unique<PinnedFilesContainer>(&delegate_));
SetupChildLayer(pinned_files_container_);
// Separator between the two containers, gives illusion of 2 separate bubbles.
......@@ -159,8 +162,8 @@ void HoldingSpaceTray::ShowBubble(bool show_by_click) {
separator->SetBorder(views::CreateEmptyBorder(
gfx::Insets(kHoldingSpaceContainerSpacing, 0, 0, 0)));
recent_files_container_ =
bubble_view->AddChildView(std::make_unique<RecentFilesContainer>());
recent_files_container_ = bubble_view->AddChildView(
std::make_unique<RecentFilesContainer>(&delegate_));
SetupChildLayer(recent_files_container_);
// Show the bubble.
......
......@@ -8,6 +8,7 @@
#include <memory>
#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 "base/memory/weak_ptr.h"
......@@ -58,6 +59,10 @@ class ASH_EXPORT HoldingSpaceTray : public TrayBackgroundView {
bool ShouldEnableExtraKeyboardAccessibility() 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_;
PinnedFilesContainer* pinned_files_container_ = nullptr;
......
......@@ -22,7 +22,9 @@
namespace ash {
PinnedFilesContainer::PinnedFilesContainer() {
PinnedFilesContainer::PinnedFilesContainer(
HoldingSpaceItemViewDelegate* delegate)
: delegate_(delegate) {
SetID(kHoldingSpacePinnedFilesContainerId);
SetLayoutManager(std::make_unique<views::BoxLayout>(
......@@ -52,7 +54,8 @@ void PinnedFilesContainer::AddHoldingSpaceItemView(
if (item->type() == HoldingSpaceItem::Type::kPinnedFile) {
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 @@
namespace ash {
class HoldingSpaceItemChipsContainer;
class HoldingSpaceItemViewDelegate;
// Container for pinned files that the user adds to the holding space bubble.
class PinnedFilesContainer : public HoldingSpaceItemViewsContainer {
public:
PinnedFilesContainer();
explicit PinnedFilesContainer(HoldingSpaceItemViewDelegate* delegate);
PinnedFilesContainer(const PinnedFilesContainer& other) = delete;
PinnedFilesContainer& operator=(const PinnedFilesContainer& other) = delete;
~PinnedFilesContainer() override;
......@@ -27,6 +28,7 @@ class PinnedFilesContainer : public HoldingSpaceItemViewsContainer {
void RemoveHoldingSpaceItemView(const HoldingSpaceItem* item) override;
private:
HoldingSpaceItemViewDelegate* const delegate_;
HoldingSpaceItemChipsContainer* item_chips_container_ = nullptr;
std::map<std::string, views::View*> views_by_item_id_;
......
......@@ -22,7 +22,9 @@
namespace ash {
RecentFilesContainer::RecentFilesContainer() {
RecentFilesContainer::RecentFilesContainer(
HoldingSpaceItemViewDelegate* delegate)
: delegate_(delegate) {
SetID(kHoldingSpaceRecentFilesContainerId);
SetLayoutManager(std::make_unique<views::BoxLayout>(
......@@ -66,10 +68,12 @@ void RecentFilesContainer::AddHoldingSpaceItemView(
DCHECK(!base::Contains(views_by_item_id_, item->id()));
if (item->type() == HoldingSpaceItem::Type::kScreenshot) {
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) {
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(
auto it = views_by_item_id_.find(item->id());
if (it == views_by_item_id_.end())
return;
views::View* view = it->second;
if (item->type() == HoldingSpaceItem::Type::kScreenshot) {
screenshots_container_->RemoveChildViewT(view);
screenshots_container_->RemoveChildViewT(it->second);
} else if (item->type() == HoldingSpaceItem::Type::kDownload) {
recent_downloads_container_->RemoveChildViewT(view);
recent_downloads_container_->RemoveChildViewT(it->second);
}
views_by_item_id_.erase(it);
}
......
......@@ -12,11 +12,12 @@
namespace ash {
class HoldingSpaceItemChipsContainer;
class HoldingSpaceItemViewDelegate;
// Container for the recent files (Screenshots, downloads etc).
class RecentFilesContainer : public HoldingSpaceItemViewsContainer {
public:
RecentFilesContainer();
explicit RecentFilesContainer(HoldingSpaceItemViewDelegate* delegate);
RecentFilesContainer(const RecentFilesContainer& other) = delete;
RecentFilesContainer& operator=(const RecentFilesContainer& other) = delete;
~RecentFilesContainer() override;
......@@ -27,6 +28,7 @@ class RecentFilesContainer : public HoldingSpaceItemViewsContainer {
void RemoveHoldingSpaceItemView(const HoldingSpaceItem* item) override;
private:
HoldingSpaceItemViewDelegate* const delegate_;
views::View* screenshots_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