Skip to content

Commit

Permalink
Add basic layout for Editor Menu view
Browse files Browse the repository at this point in the history
This cl adds the basic layout and title for the editor menu view.
Other parts will be added as follow ups.

Bug: b/296081497
Test: Added new tests
Change-Id: Id39351f27adc1105baf09743d560e20575f8eaf4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4781767
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Tao Wu <wutao@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1184537}
  • Loading branch information
Tao Wu authored and Chromium LUCI CQ committed Aug 17, 2023
1 parent 73c44c4 commit 950e8b0
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 3 deletions.
16 changes: 16 additions & 0 deletions chrome/browser/ui/views/editor_menu/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,25 @@ source_set("editor_menu") {
]

deps = [
":views",
"//base",
"//chromeos/components/editor_menu/public/cpp",
"//ui/gfx",
"//ui/views",
]
}

source_set("views") {
sources = [
"editor_menu_view.cc",
"editor_menu_view.h",
]

deps = [
"//base",
"//ui/aura",
"//ui/chromeos/styles:cros_tokens_color_mappings_generator",
"//ui/gfx",
"//ui/views",
]
}
59 changes: 57 additions & 2 deletions chrome/browser/ui/views/editor_menu/editor_menu_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,38 @@
#include "chromeos/constants/chromeos_features.h"
#include "content/public/test/browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/views/view.h"

namespace {

constexpr int kMarginDip = 8;
constexpr gfx::Rect kAnchorBounds =
gfx::Rect(gfx::Point(500, 250), gfx::Size(80, 160));
constexpr gfx::Rect kAnchorBoundsTop =
gfx::Rect(gfx::Point(500, 0), gfx::Size(80, 160));

} // namespace

class EditorMenuBrowserTest : public InProcessBrowserTest {
public:
EditorMenuBrowserTest() = default;
~EditorMenuBrowserTest() override = default;

protected:
using EditorMenuController = chromeos::editor_menu::EditorMenuController;
using EditorMenuControllerImpl =
chromeos::editor_menu::EditorMenuControllerImpl;

EditorMenuControllerImpl* GetControllerImpl() {
return static_cast<EditorMenuControllerImpl*>(EditorMenuController::Get());
}

views::View* GetEditorMenuView() {
return GetControllerImpl()
->editor_menu_widget_for_testing()
->GetContentsView();
}

base::test::ScopedFeatureList feature_list_;
};

Expand All @@ -31,11 +56,41 @@ class EditorMenuBrowserFeatureEnabledTest : public EditorMenuBrowserTest {
IN_PROC_BROWSER_TEST_F(EditorMenuBrowserTest,
ShouldNotCreateWhenFeatureNotEnabled) {
EXPECT_FALSE(chromeos::features::IsOrcaEnabled());
EXPECT_EQ(nullptr, chromeos::editor_menu::EditorMenuController::Get());
EXPECT_EQ(nullptr, EditorMenuController::Get());
};

IN_PROC_BROWSER_TEST_F(EditorMenuBrowserFeatureEnabledTest,
ShouldCreateWhenFeatureEnabled) {
EXPECT_TRUE(chromeos::features::IsOrcaEnabled());
EXPECT_NE(nullptr, chromeos::editor_menu::EditorMenuController::Get());
EXPECT_NE(nullptr, EditorMenuController::Get());
}

IN_PROC_BROWSER_TEST_F(EditorMenuBrowserFeatureEnabledTest,
ShowEditorMenuAboveAnchor) {
EXPECT_TRUE(chromeos::features::IsOrcaEnabled());
EXPECT_NE(nullptr, EditorMenuController::Get());

EditorMenuController::Get()->MaybeShowEditorMenu(kAnchorBounds);
const gfx::Rect& bounds = GetEditorMenuView()->GetBoundsInScreen();

// View is vertically left aligned with anchor.
EXPECT_EQ(bounds.x(), kAnchorBounds.x());

// View is positioned above the anchor.
EXPECT_EQ(bounds.bottom() + kMarginDip, kAnchorBounds.y());
}

IN_PROC_BROWSER_TEST_F(EditorMenuBrowserFeatureEnabledTest,
ShowEditorMenuBelowAnchor) {
EXPECT_TRUE(chromeos::features::IsOrcaEnabled());
EXPECT_NE(nullptr, EditorMenuController::Get());

EditorMenuController::Get()->MaybeShowEditorMenu(kAnchorBoundsTop);
const gfx::Rect& bounds = GetEditorMenuView()->GetBoundsInScreen();

// View is vertically left aligned with anchor.
EXPECT_EQ(bounds.x(), kAnchorBoundsTop.x());

// View is positioned below the anchor.
EXPECT_EQ(bounds.y() - kMarginDip, kAnchorBoundsTop.bottom());
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "chrome/browser/ui/views/editor_menu/editor_menu_controller_impl.h"

#include "chrome/browser/ui/views/editor_menu/editor_menu_view.h"
#include "ui/gfx/geometry/rect.h"

namespace chromeos::editor_menu {
Expand Down Expand Up @@ -35,8 +36,9 @@ void EditorMenuControllerImpl::MaybeShowEditorMenu(
return;
}

// TODO(b/295060733): Create the main view.
// TODO(b/295059934): Call EditorMediator API to get the parameters.
editor_menu_widget_ = EditorMenuView::CreateWidget(anchor_bounds);
editor_menu_widget_->ShowInactive();
}

void EditorMenuControllerImpl::DismissEditorMenu() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class EditorMenuControllerImpl : public EditorMenuController {
void DismissEditorMenu() override;
void UpdateAnchorBounds(const gfx::Rect& anchor_bounds) override;

views::Widget* editor_menu_widget_for_testing() {
return editor_menu_widget_.get();
}

private:
views::UniqueWidgetPtr editor_menu_widget_;

Expand Down
129 changes: 129 additions & 0 deletions chrome/browser/ui/views/editor_menu/editor_menu_view.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/editor_menu/editor_menu_view.h"

#include "base/memory/raw_ptr.h"
#include "ui/aura/window.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_owner.h"
#include "ui/display/screen.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/layout_manager.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"

namespace chromeos::editor_menu {

namespace {

constexpr char kWidgetName[] = "EditorMenuViewWidget";
constexpr char16_t kContainerTitle[] = u"Editor Menu";

constexpr int kContainerMinWidthDip = 368;
constexpr int kRadiusDip = 4;

constexpr gfx::Insets kTitleContainerInsets = gfx::Insets::TLBR(10, 16, 10, 10);

// Spacing between this view and the anchor view (context menu).
constexpr int kMarginDip = 8;

} // namespace

EditorMenuView::EditorMenuView(const gfx::Rect& anchor_view_bounds) {
InitLayout();
}

EditorMenuView::~EditorMenuView() = default;

// static
views::UniqueWidgetPtr EditorMenuView::CreateWidget(
const gfx::Rect& anchor_view_bounds) {
views::Widget::InitParams params;
params.activatable = views::Widget::InitParams::Activatable::kYes;
params.shadow_elevation = 2;
params.shadow_type = views::Widget::InitParams::ShadowType::kDrop;
params.type = views::Widget::InitParams::TYPE_POPUP;
params.z_order = ui::ZOrderLevel::kFloatingUIElement;
params.name = kWidgetName;

views::UniqueWidgetPtr widget =
std::make_unique<views::Widget>(std::move(params));
EditorMenuView* editor_menu_view = widget->SetContentsView(
std::make_unique<EditorMenuView>(anchor_view_bounds));
editor_menu_view->UpdateBounds(anchor_view_bounds);

return widget;
}

void EditorMenuView::UpdateBounds(const gfx::Rect& anchor_view_bounds) {
int height = GetHeightForWidth(anchor_view_bounds.width());
int y = anchor_view_bounds.y() - kMarginDip - height;

// The Editor Menu view will be off screen if showing above the anchor.
// Show below the anchor instead.
if (y < display::Screen::GetScreen()
->GetDisplayMatching(anchor_view_bounds)
.work_area()
.y()) {
y = anchor_view_bounds.bottom() + kMarginDip;
}

gfx::Rect bounds = {{anchor_view_bounds.x(), y},
{kContainerMinWidthDip, height}};
GetWidget()->SetBounds(bounds);
}

void EditorMenuView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ax::mojom::Role::kDialog;
node_data->SetName(kContainerTitle);
}

void EditorMenuView::InitLayout() {
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
layer()->SetMasksToBounds(true);

SetBackground(views::CreateThemedRoundedRectBackground(
cros_tokens::kCrosSysAppBase, kRadiusDip));

auto* layout = SetLayoutManager(std::make_unique<views::FlexLayout>());
layout->SetOrientation(views::LayoutOrientation::kVertical)
.SetCrossAxisAlignment(views::LayoutAlignment::kStart);

AddTitleContainer();
}

void EditorMenuView::AddTitleContainer() {
title_container_ = AddChildView(std::make_unique<views::View>());
views::BoxLayout* layout =
title_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal));
layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);

auto* title = title_container_->AddChildView(
std::make_unique<views::Label>(kContainerTitle));

// TODO(b/295078199): Add Settings icon.

title_container_->SetProperty(views::kMarginsKey, kTitleContainerInsets);
title_container_->SetPreferredSize(
gfx::Size(kContainerMinWidthDip - kTitleContainerInsets.width(),
title->GetPreferredSize().height()));
}

BEGIN_METADATA(EditorMenuView, views::View)
END_METADATA

} // namespace chromeos::editor_menu
43 changes: 43 additions & 0 deletions chrome/browser/ui/views/editor_menu/editor_menu_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_VIEWS_EDITOR_MENU_EDITOR_MENU_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_EDITOR_MENU_EDITOR_MENU_VIEW_H_

#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/widget/unique_widget_ptr.h"

namespace chromeos::editor_menu {

// A bubble style view to show Editor Menu.
class EditorMenuView : public views::View {
public:
METADATA_HEADER(EditorMenuView);

explicit EditorMenuView(const gfx::Rect& anchor_view_bounds);

EditorMenuView(const EditorMenuView&) = delete;
EditorMenuView& operator=(const EditorMenuView&) = delete;

~EditorMenuView() override;

static views::UniqueWidgetPtr CreateWidget(
const gfx::Rect& anchor_view_bounds);

// views::View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;

void UpdateBounds(const gfx::Rect& anchor_view_bounds);

private:
void InitLayout();
void AddTitleContainer();

// Containing title, badge, and icons.
raw_ptr<views::View> title_container_ = nullptr;
};

} // namespace chromeos::editor_menu

#endif // CHROME_BROWSER_UI_VIEWS_EDITOR_MENU_EDITOR_MENU_VIEW_H_

0 comments on commit 950e8b0

Please sign in to comment.