diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-13 16:23:34 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-14 10:37:21 +0000 |
commit | 38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch) | |
tree | c4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/ui/views/layout/flex_layout_types.cc | |
parent | e684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff) | |
download | qtwebengine-chromium-38a9a29f4f9436cace7f0e7abf9c586057df8a4e.tar.gz |
BASELINE: Update Chromium to 73.0.3683.37
Change-Id: I08c9af2948b645f671e5d933aca1f7a90ea372f2
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/ui/views/layout/flex_layout_types.cc')
-rw-r--r-- | chromium/ui/views/layout/flex_layout_types.cc | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/chromium/ui/views/layout/flex_layout_types.cc b/chromium/ui/views/layout/flex_layout_types.cc new file mode 100644 index 00000000000..692e7262758 --- /dev/null +++ b/chromium/ui/views/layout/flex_layout_types.cc @@ -0,0 +1,203 @@ +// Copyright 2018 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. + +#include "ui/views/layout/flex_layout_types.h" + +#include <algorithm> +#include <tuple> + +#include "base/strings/stringprintf.h" +#include "ui/gfx/geometry/size.h" +#include "ui/views/view.h" + +namespace views { + +namespace { + +std::string OptionalToString(const base::Optional<int>& opt) { + if (!opt.has_value()) + return "_"; + return base::StringPrintf("%d", opt.value()); +} + +// Default Flex Rules ---------------------------------------------------------- + +// Interpolates a size between minimum, preferred size, and upper bound based on +// sizing rules, returning the resulting ideal size. +int InterpolateSize(MinimumFlexSizeRule minimum_size_rule, + MaximumFlexSizeRule maximum_size_rule, + int minimum_size, + int preferred_size, + int available_size) { + if (available_size < minimum_size) { + switch (minimum_size_rule) { + case MinimumFlexSizeRule::kScaleToZero: + return available_size; + case MinimumFlexSizeRule::kPreferred: + return preferred_size; + case MinimumFlexSizeRule::kScaleToMinimum: + case MinimumFlexSizeRule::kPreferredSnapToMinimum: + return minimum_size; + case MinimumFlexSizeRule::kScaleToMinimumSnapToZero: + case MinimumFlexSizeRule::kPreferredSnapToZero: + return 0; + } + } else if (available_size < preferred_size) { + switch (minimum_size_rule) { + case MinimumFlexSizeRule::kPreferred: + return preferred_size; + case MinimumFlexSizeRule::kScaleToZero: + case MinimumFlexSizeRule::kScaleToMinimum: + case MinimumFlexSizeRule::kScaleToMinimumSnapToZero: + return available_size; + case MinimumFlexSizeRule::kPreferredSnapToMinimum: + return minimum_size; + case MinimumFlexSizeRule::kPreferredSnapToZero: + return 0; + } + } else { + switch (maximum_size_rule) { + case MaximumFlexSizeRule::kPreferred: + return preferred_size; + case MaximumFlexSizeRule::kUnbounded: + return available_size; + } + } +} + +gfx::Size GetPreferredSize(MinimumFlexSizeRule minimum_size_rule, + MaximumFlexSizeRule maximum_size_rule, + const views::View* view, + const views::SizeBounds& maximum_size) { + gfx::Size min = view->GetMinimumSize(); + gfx::Size preferred = view->GetPreferredSize(); + + int width, height; + + if (!maximum_size.width()) { + // Not having a maximum size is different from having a large available + // size; a view can't grow infinitely, so we go with its preferred size. + width = preferred.width(); + } else { + width = InterpolateSize(minimum_size_rule, maximum_size_rule, min.width(), + preferred.width(), *maximum_size.width()); + } + + // Allow views that need to grow vertically when they're compressed + // horizontally to do so. + // + // If we just went with GetHeightForWidth() we would have situations where an + // empty text control wanted no (or very little) height which could cause a + // layout to shrink vertically; we will always try to allocate at least the + // view's reported preferred height. + // + // Note that this is an adjustment made for practical considerations, and may + // not be "correct" in some absolute sense. Let's revisit at some point. + const int preferred_height = + std::max(preferred.height(), view->GetHeightForWidth(width)); + + if (!maximum_size.height()) { + // Not having a maximum size is different from having a large available + // size; a view can't grow infinitely, so we go with its preferred size. + height = preferred_height; + } else { + height = InterpolateSize(minimum_size_rule, maximum_size_rule, min.height(), + preferred_height, *maximum_size.height()); + } + + return gfx::Size(width, height); +} + +FlexRule GetDefaultFlexRule( + MinimumFlexSizeRule minimum_size_rule = MinimumFlexSizeRule::kPreferred, + MaximumFlexSizeRule maximum_size_rule = MaximumFlexSizeRule::kPreferred) { + return base::BindRepeating(&GetPreferredSize, minimum_size_rule, + maximum_size_rule); +} + +} // namespace + +// SizeBounds ------------------------------------------------------------------ + +SizeBounds::SizeBounds() = default; + +SizeBounds::SizeBounds(const base::Optional<int>& width, + const base::Optional<int>& height) + : width_(width), height_(height) {} + +SizeBounds::SizeBounds(const SizeBounds& other) + : width_(other.width()), height_(other.height()) {} + +SizeBounds::SizeBounds(const gfx::Size& other) + : width_(other.width()), height_(other.height()) {} + +void SizeBounds::Enlarge(int width, int height) { + if (width_) + width_ = std::max(0, *width_ + width); + if (height_) + height_ = std::max(0, *height_ + height); +} + +bool SizeBounds::operator==(const SizeBounds& other) const { + return width_ == other.width_ && height_ == other.height_; +} + +bool SizeBounds::operator!=(const SizeBounds& other) const { + return !(*this == other); +} + +bool SizeBounds::operator<(const SizeBounds& other) const { + return std::tie(height_, width_) < std::tie(other.height_, other.width_); +} + +std::string SizeBounds::ToString() const { + return base::StringPrintf("%s x %s", OptionalToString(width()).c_str(), + OptionalToString(height()).c_str()); +} + +// FlexSpecification ----------------------------------------------------------- + +FlexSpecification::FlexSpecification() + : rule_(GetDefaultFlexRule()), order_(1), weight_(0) {} + +FlexSpecification FlexSpecification::ForCustomRule(const FlexRule& rule) { + return FlexSpecification(rule, 1, 1); +} + +FlexSpecification FlexSpecification::ForSizeRule( + MinimumFlexSizeRule minimum_size_rule, + MaximumFlexSizeRule maximum_size_rule) { + return FlexSpecification( + GetDefaultFlexRule(minimum_size_rule, maximum_size_rule), 1, 1); +} + +FlexSpecification::FlexSpecification(const FlexRule& rule, + int order, + int weight) + : rule_(rule), order_(order), weight_(weight) {} + +FlexSpecification::FlexSpecification(const FlexSpecification& other) + : rule_(other.rule_), order_(other.order_), weight_(other.weight_) {} + +FlexSpecification& FlexSpecification::operator=( + const FlexSpecification& other) { + rule_ = other.rule_; + order_ = other.order_; + weight_ = other.weight_; + return *this; +} + +FlexSpecification::~FlexSpecification() = default; + +FlexSpecification FlexSpecification::WithWeight(int weight) const { + DCHECK_GE(weight, 0); + return FlexSpecification(rule_, order_, weight); +} + +FlexSpecification FlexSpecification::WithOrder(int order) const { + DCHECK_GE(order, 1); + return FlexSpecification(rule_, order, weight_); +} + +} // namespace views |