summaryrefslogtreecommitdiff
path: root/chromium/ui/views/layout/flex_layout_types.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 16:23:34 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:37:21 +0000
commit38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch)
treec4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/ui/views/layout/flex_layout_types.cc
parente684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff)
downloadqtwebengine-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.cc203
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