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

#include "ui/views/examples/flex_layout_example.h"

#include <memory>
#include <string>

#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/models/combobox_model.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/combobox/combobox.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/examples/example_combobox_model.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"

namespace views::examples {

FlexLayoutExample::FlexLayoutExample() : LayoutExampleBase("Flex Layout") {}

FlexLayoutExample::~FlexLayoutExample() {
  interior_margin_.ResetControllers();
  default_child_margins_.ResetControllers();
}

void FlexLayoutExample::ContentsChanged(Textfield* sender,
                                        const std::u16string& new_contents) {
  layout_->SetInteriorMargin(
      LayoutExampleBase::TextfieldsToInsets(interior_margin_));
  layout_->SetDefault(views::kMarginsKey, LayoutExampleBase::TextfieldsToInsets(
                                              default_child_margins_));
  RefreshLayoutPanel(false);
}

void FlexLayoutExample::CreateAdditionalControls() {
  constexpr auto kOrientationValues =
      std::to_array<const char* const>({"Horizontal", "Vertical"});
  orientation_ = CreateAndAddCombobox(
      u"Orientation", kOrientationValues,
      base::BindRepeating(&FlexLayoutExample::OrientationChanged,
                          base::Unretained(this)));

  constexpr auto kMainAxisValues =
      std::to_array<const char* const>({"Start", "Center", "End"});
  main_axis_alignment_ = CreateAndAddCombobox(
      u"Main axis", kMainAxisValues,
      base::BindRepeating(&FlexLayoutExample::MainAxisAlignmentChanged,
                          base::Unretained(this)));

  constexpr auto kCrossAxisValues =
      std::to_array<const char* const>({"Stretch", "Start", "Center", "End"});
  cross_axis_alignment_ = CreateAndAddCombobox(
      u"Cross axis", kCrossAxisValues,
      base::BindRepeating(&FlexLayoutExample::CrossAxisAlignmentChanged,
                          base::Unretained(this)));

  CreateMarginsTextFields(u"Interior margin", &interior_margin_);

  CreateMarginsTextFields(u"Default margins", &default_child_margins_);

  collapse_margins_ = CreateAndAddCheckbox(
      u"Collapse margins", base::BindRepeating(
                               [](FlexLayoutExample* example) {
                                 example->layout_->SetCollapseMargins(
                                     example->collapse_margins_->GetChecked());
                                 example->RefreshLayoutPanel(false);
                               },
                               base::Unretained(this)));

  ignore_default_main_axis_margins_ = CreateAndAddCheckbox(
      u"Ignore main axis margins",
      base::BindRepeating(
          [](FlexLayoutExample* example) {
            example->layout_->SetIgnoreDefaultMainAxisMargins(
                example->ignore_default_main_axis_margins_->GetChecked());
            example->RefreshLayoutPanel(false);
          },
          base::Unretained(this)));

  layout_ = layout_panel()->SetLayoutManager(std::make_unique<FlexLayout>());
}

void FlexLayoutExample::UpdateLayoutManager() {
  for (View* child : layout_panel()->children()) {
    const int flex = static_cast<ChildPanel*>(child)->GetFlex();
    if (flex < 0) {
      child->ClearProperty(views::kFlexBehaviorKey);
    } else {
      child->SetProperty(views::kFlexBehaviorKey, GetFlexSpecification(flex));
    }
  }
}

FlexSpecification FlexLayoutExample::GetFlexSpecification(int weight) const {
  return weight > 0
             ? FlexSpecification(MinimumFlexSizeRule::kScaleToZero,
                                 MaximumFlexSizeRule::kUnbounded)
                   .WithWeight(weight)
             : FlexSpecification(MinimumFlexSizeRule::kPreferredSnapToZero,
                                 MaximumFlexSizeRule::kPreferred)
                   .WithWeight(0);
}

void FlexLayoutExample::OrientationChanged() {
  constexpr auto kOrientations = std::to_array<LayoutOrientation>(
      {LayoutOrientation::kHorizontal, LayoutOrientation::kVertical});
  layout_->SetOrientation(
      kOrientations[orientation_->GetSelectedIndex().value()]);
  RefreshLayoutPanel(false);
}

void FlexLayoutExample::MainAxisAlignmentChanged() {
  constexpr auto kMainAxisAlignments = std::to_array<LayoutAlignment>(
      {LayoutAlignment::kStart, LayoutAlignment::kCenter,
       LayoutAlignment::kEnd});
  layout_->SetMainAxisAlignment(
      kMainAxisAlignments[main_axis_alignment_->GetSelectedIndex().value()]);
  RefreshLayoutPanel(false);
}

void FlexLayoutExample::CrossAxisAlignmentChanged() {
  constexpr auto kCrossAxisAlignments = std::to_array<LayoutAlignment>(
      {LayoutAlignment::kStretch, LayoutAlignment::kStart,
       LayoutAlignment::kCenter, LayoutAlignment::kEnd});
  layout_->SetCrossAxisAlignment(
      kCrossAxisAlignments[cross_axis_alignment_->GetSelectedIndex().value()]);
  RefreshLayoutPanel(false);
}

}  // namespace views::examples