// 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. #ifndef UI_VIEWS_LAYOUT_FLEX_LAYOUT_TYPES_H_ #define UI_VIEWS_LAYOUT_FLEX_LAYOUT_TYPES_H_ #include <algorithm> #include <memory> #include <string> #include "base/functional/callback.h" #include "ui/views/layout/layout_types.h" #include "ui/views/views_export.h" namespace gfx { class Size; } namespace views { class View; // Specifies whether flex space is allocated in the same order as the children // in the host view, or in reverse order. Reverse order is useful when you want // child views to drop out from left to right instead of right to left if there // isn't enough space to display them. enum class FlexAllocationOrder { … }; // Callback used to specify the size of a child view based on its size bounds. // Create your own custom rules, or use the Minimum|MaximumFlexSizeRule // constants below for common behaviors. // // This callback takes two parameters: a child view, and a set of size bounds // representing the available space for that child view to occupy. The function // returns the preferred size of the view within those bounds, which may exceed // them if the child is not capable of shrinking to the specified size. The // callback may also return an empty size, which means the child view can drop // out of the layout. Not specifying either bound means there is an unlimited // amount of room for the child view in that dimension (and the child view // should probably use its preferred size). // // We provide the ability to use an arbitrary function here because some views // have complex sizing behavior; for example, they may shrink stepwise as their // internal elements drop out due to lack of space. FlexRule; // Describes a simple rule for how a child view should shrink in a layout when // the available size for that view decreases. enum class MinimumFlexSizeRule { … }; // Describes a simple rule for how a child view should grow in a layout when // there is extra size available for that view to occupy. enum class MaximumFlexSizeRule { … }; // Specifies how a view should flex (i.e. grow or shrink) within its parent as // the available space changes. Flex specifications have three components: // - A |rule| which tells the layout manager how the child view resizes with // available space. // - A |weight| which specifies how much each individual child will deviate // from its preferred size; larger weights will deviate more either when // shrinking or growing. The deviation is proportional to the weight divided // by the total weight of all views at this |order|. // - An |order| which specifies the priority with which available space is // allocated (lower numbers -> higher priority). // // Space allocation works as follows: // 1. All views are given the smallest possible size that |rule| allows (which // might be zero.) // 2. Going by |order|, we attempt to allocate the preferred size of each view. // 3. If there is insufficient size, the deficit is allocated across all views // at this |order| whose |rule| allows them to shrink, proportional to // |weight|. // 4. Once all orders have been allocated this way, repeat the process by // |order| allocating any excess space among views whose |rule| allows them // to exceed their preferred size. // // For example, say there are three child views in a horizontal layout, each // of which has a flex rule that allows it to be between 10 and 40 DIP with a // preferred width of 20 DIP. Child A is at order 2 with weight 2, child B is at // order 1 with weight 1, and child C is at order 2 with weight 1. // // At 30 DIP (the parent's minimum size): // [10][10][10] // // At 40 DIP: // [10][20][10] (B hits its preferred size) // // At 48 DIP: // [12][20][16] (deficit is spread across A and C by weight) // // At 57 DIP: // [18][20][19] // // At 60 DIP: // [20][20][20] (all views at preferred size) // // At 80 DIP: // [20][40][20] (B hits its maximum size) // // At 110 DIP: // [40][40][30] (A scales faster than C) // // At 120 DIP (the parent's maximum size): // [40][40][40] // // NOTE(dfried): the behavior of |weight| may seem backwards when views shrink // below their preferred size, but it works the way it does because: // (a) It's consistent with BoxLayout, making upgrading to FlexLayout easier. // (b) It allows smooth scaling across a view's preferred size. // If this gets too confusing we could add an option to make weights reciprocal // when allocating deficit. class VIEWS_EXPORT FlexSpecification { … }; // Represents insets in a single dimension. class VIEWS_EXPORT Inset1D { … }; // Represents a line segment in one dimension with a starting point and length. class VIEWS_EXPORT Span { … }; // These are declared here for use in gtest-based unit tests but is defined in // the views_test_support target. Depend on that to use this in your unit test. // This should not be used in production code - call ToString() instead. void PrintTo(MinimumFlexSizeRule minimum_flex_size_rule, ::std::ostream* os); void PrintTo(MaximumFlexSizeRule maximum_flex_size_rule, ::std::ostream* os); } // namespace views #endif // UI_VIEWS_LAYOUT_FLEX_LAYOUT_TYPES_H_