910e62b5创建于 1月15日历史提交
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/quick_insert/views/quick_insert_main_container_view.h"

#include <memory>
#include <utility>

#include "ash/public/cpp/style/color_provider.h"
#include "ash/quick_insert/views/quick_insert_contents_view.h"
#include "ash/quick_insert/views/quick_insert_page_view.h"
#include "ash/quick_insert/views/quick_insert_pseudo_focus.h"
#include "ash/quick_insert/views/quick_insert_search_field_view.h"
#include "ash/quick_insert/views/quick_insert_style.h"
#include "ash/style/system_shadow.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/views/background.h"
#include "ui/views/controls/separator.h"
#include "ui/views/highlight_border.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"

namespace ash {
namespace {

constexpr int kMainContainerMaxHeight = 300;

std::unique_ptr<views::Separator> CreateSeparator() {
  return views::Builder<views::Separator>()
      .SetOrientation(views::Separator::Orientation::kHorizontal)
      .SetColorId(cros_tokens::kCrosSysSeparator)
      .Build();
}

}  // namespace

QuickInsertMainContainerView::QuickInsertMainContainerView() {
  SetPaintToLayer();
  layer()->SetRoundedCornerRadius(
      gfx::RoundedCornersF{kQuickInsertContainerBorderRadius});
  layer()->SetFillsBoundsOpaquely(false);
  layer()->SetIsFastRoundedCorner(true);
  // We set background blur even though the main container background is opaque,
  // to avoid a flickering issue related to the container's scroll view
  // gradient. See b/351051291.
  layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma);
  layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality);

  SetBackground(views::CreateRoundedRectBackground(
      kQuickInsertContainerBackgroundColor, kQuickInsertContainerBorderRadius));
  SetBorder(std::make_unique<views::HighlightBorder>(
      kQuickInsertContainerBorderRadius,
      views::HighlightBorder::Type::kHighlightBorderOnShadow));
  shadow_ = SystemShadow::CreateShadowOnNinePatchLayerForView(
      this, kQuickInsertContainerShadowType);
  shadow_->SetRoundedCornerRadius(kQuickInsertContainerBorderRadius);

  SetLayoutManager(std::make_unique<views::BoxLayout>())
      ->SetOrientation(views::LayoutOrientation::kVertical);
}

QuickInsertMainContainerView::~QuickInsertMainContainerView() = default;

gfx::Size QuickInsertMainContainerView::CalculatePreferredSize(
    const views::SizeBounds& available_size) const {
  const int preferred_height =
      views::View::CalculatePreferredSize(available_size).height();
  return gfx::Size(kQuickInsertViewWidth,
                   std::min(preferred_height, kMainContainerMaxHeight));
}

views::View* QuickInsertMainContainerView::GetTopItem() {
  return active_page_->GetTopItem();
}

views::View* QuickInsertMainContainerView::GetBottomItem() {
  return active_page_->GetBottomItem();
}

views::View* QuickInsertMainContainerView::GetItemAbove(views::View* item) {
  if (search_field_view_->Contains(item)) {
    views::View* prev_item = GetNextQuickInsertPseudoFocusableView(
        item, QuickInsertPseudoFocusDirection::kBackward,
        /*should_loop=*/false);
    return Contains(prev_item) ? prev_item : nullptr;
  }
  // Try to get an item above `item`, skipping items outside of the active page
  // (such as search field buttons).
  return active_page_->GetItemAbove(item);
}

views::View* QuickInsertMainContainerView::GetItemBelow(views::View* item) {
  if (search_field_view_->Contains(item)) {
    views::View* next_item = GetNextQuickInsertPseudoFocusableView(
        item, QuickInsertPseudoFocusDirection::kForward, /*should_loop=*/false);
    return Contains(next_item) ? next_item : nullptr;
  }
  // Try to get an item below `item`, skipping items outside of the active page
  // (such as search field buttons).
  return active_page_->GetItemBelow(item);
}

views::View* QuickInsertMainContainerView::GetItemLeftOf(views::View* item) {
  return active_page_->GetItemLeftOf(item);
}

views::View* QuickInsertMainContainerView::GetItemRightOf(views::View* item) {
  return active_page_->GetItemRightOf(item);
}

bool QuickInsertMainContainerView::ContainsItem(views::View* item) {
  return Contains(item);
}

QuickInsertSearchFieldView* QuickInsertMainContainerView::AddSearchFieldView(
    std::unique_ptr<QuickInsertSearchFieldView> search_field_view) {
  search_field_view_ = AddChildView(std::move(search_field_view));
  return search_field_view_;
}

QuickInsertContentsView* QuickInsertMainContainerView::AddContentsView(
    QuickInsertLayoutType layout_type) {
  switch (layout_type) {
    case QuickInsertLayoutType::kMainResultsBelowSearchField:
      AddChildView(CreateSeparator());
      contents_view_ =
          AddChildView(std::make_unique<QuickInsertContentsView>(layout_type));
      break;
    case QuickInsertLayoutType::kMainResultsAboveSearchField:
      contents_view_ = AddChildViewAt(
          std::make_unique<QuickInsertContentsView>(layout_type), 0);
      AddChildViewAt(CreateSeparator(), 1);
      break;
  }

  contents_view_->SetProperty(
      views::kBoxLayoutFlexKey,
      views::BoxLayoutFlexSpecification().WithWeight(1));

  return contents_view_;
}

void QuickInsertMainContainerView::SetActivePage(
    QuickInsertPageView* page_view) {
  contents_view_->SetActivePage(page_view);
  active_page_ = page_view;
}

BEGIN_METADATA(QuickInsertMainContainerView)
END_METADATA

}  // namespace ash