Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Unified Diff: ui/views/layout/box_layout.h

Issue 2836313002: BoxLayout now suports per-view margins. (Closed)
Patch Set: Fixed comment describing the BoxLayout behavior. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/views/layout/box_layout.h
diff --git a/ui/views/layout/box_layout.h b/ui/views/layout/box_layout.h
index 9a87984d51f77cec0caa488860fa6dc1986f9e28..8198496f1e003ee2675f9e5e1cbb0e5035a7ab7d 100644
--- a/ui/views/layout/box_layout.h
+++ b/ui/views/layout/box_layout.h
@@ -58,11 +58,60 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
// Use |inside_border_horizontal_spacing| and
// |inside_border_vertical_spacing| to add additional space between the child
// view area and the host view border. |between_child_spacing| controls the
- // space in between child views.
+ // space in between child views. Use view->SetProperty(kMarginsKey,
+ // new gfx::Insets(xxx)) to add additional margins on a per-view basis. The
+ // |collapse_margins_spacing| parameter controls whether or not adjacent
+ // spacing/margins are collapsed based on the max of the two values. For the
+ // cross axis, |collapse_margins_spacing| will collapse to the max of
+ // inside_border_xxxxx_spacing and the corresponding margin edge from each
+ // view.
+ //
+ // Given the following views where V = view bounds, M = Margins property,
+ // B = between child spacing, S = inside border spacing and
+ // <space> = added margins for alignment
+ //
+ // MMMMM MMVVVVMM MMMM
+ // VVVVM MMMM
+ // VVVVM MMMM
+ // VVVVM VVVV
+ // MMMMM
+ //
+ // With collapse_margins_spacing = false, orientation = kHorizontal,
+ // inside_border_spacing_horizontal = 2, inside_border_spacing_vertical = 2
+ // and between_child_spacing = 1:
+ //
+ // -----------------------
+ // SSSSSSSSSSSSSSSSSSSSSSS
+ // SSSSSSSSSSSSSSSSSSSSSSS
+ // SS MBMM MMBMMMMSS
+ // SS MBMM MMBMMMMSS
+ // SSMMMMMBMM MMBMMMMSS
+ // SSVVVVMBMMVVVVMMBVVVVSS
+ // SSVVVVMBMMVVVVMMBVVVVSS
+ // SSVVVVMBMMVVVVMMBVVVVSS
+ // SSMMMMMBMMVVVVMMBVVVVSS
+ // SSSSSSSSSSSSSSSSSSSSSSS
+ // SSSSSSSSSSSSSSSSSSSSSSS
+ // -----------------------
+ //
+ // Same as above except, collapse_margins_spacing = true.
+ //
+ // --------------------
+ // SS MMMMMMSS
+ // SS MMMMMMSS
+ // SSMMMMMM MMMMMMSS
+ // SSVVVVMMVVVVMMVVVVSS
+ // SSVVVVMMVVVVMMVVVVSS
+ // SSVVVVMMVVVVMMVVVVSS
+ // SSSSSSSSSSSSSSSSSSSS
+ // SSSSSSSSSSSSSSSSSSSS
+ // --------------------
+ //
BoxLayout(Orientation orientation,
int inside_border_horizontal_spacing,
int inside_border_vertical_spacing,
- int between_child_spacing);
+ int between_child_spacing,
+ bool collapse_margins_spacing = false);
~BoxLayout() override;
void set_main_axis_alignment(MainAxisAlignment main_axis_alignment) {
@@ -105,6 +154,43 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
int GetPreferredHeightForWidth(const View* host, int width) const override;
private:
+ // This struct is used internally to "wrap" a child view in order to obviate
+ // the need for the main layout logic to be fully aware of the per-view
+ // margins when |collapse_margin_spacing_| is false. Since each view is a
+ // rectangle of a certain size, this wrapper, coupled with any margins set
+ // will increase the apparent size of the view along the main axis. All
+ // necessary view size/position methods required for the layout logic add or
+ // subtract the margins where appropriate to ensure the actual visible size of
+ // the view doesn't include the margins. For the cross axis, the margins are
+ // NOT included in the size/position calculations. BoxLayout will adjust the
+ // bounding rectangle of the space used for layout using the maximum margin
+ // for all views along the appropriate edge.
+ // When |collapse_margin_spacing_| is true, this wrapper provides quick access
+ // to the view's margins for use by the layout to collapse adjacent spacing
+ // to the largest of the several values.
+ class ViewWrapper {
+ public:
+ ViewWrapper();
+ ViewWrapper(const BoxLayout* layout, View* view);
+ ~ViewWrapper();
+ int GetHeightForWidth(int width) const;
sky 2017/06/05 21:04:10 optional: Generally we have newline after destruct
kylix_rd 2017/06/06 18:22:35 Done.
+ const gfx::Insets& margins() const { return margins_; }
+ gfx::Size GetPreferredSize() const;
+ void SetBoundsRect(const gfx::Rect& bounds);
+ View* view() const { return view_; }
+ bool visible() const;
+
+ private:
+ View* view_;
+ const BoxLayout* layout_;
+ const Orientation orientation_;
sky 2017/06/05 21:04:11 Why do you need to cache both the layout and orien
kylix_rd 2017/06/06 18:22:35 In previous iterations, it was accessed more frequ
+ gfx::Insets margins_;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewWrapper);
+ };
+
+ using FlexMap = std::map<const View*, int>;
+
// Returns the flex for the specified |view|.
int GetFlexForView(const View* view) const;
@@ -126,10 +212,64 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
// Returns the main axis size for the given view. |child_area_width| is needed
// to calculate the height of the view when the orientation is vertical.
- int MainAxisSizeForView(const View* view, int child_area_width) const;
+ int MainAxisSizeForView(const ViewWrapper& view, int child_area_width) const;
+
+ // Returns the |left| or |top| edge of the given inset based on the value of
+ // |orientation_|.
+ int MainAxisLeadingInset(const gfx::Insets& insets) const;
+
+ // Returns the |right| or |bottom| edge of the given inset based on the value
+ // of |orientation_|.
+ int MainAxisTrailingInset(const gfx::Insets& insets) const;
+
+ // Returns the left (|x|) or top (|y|) edge of the given rect based on the
+ // value of |orientation_|.
+ int CrossAxisLeadingEdge(const gfx::Rect& rect) const;
+
+ // Returns the |left| or |top| edge of the given inset based on the value of
+ // |orientation_|.
+ int CrossAxisLeadingInset(const gfx::Insets& insets) const;
+
+ // Returns the |right| or |bottom| edge of the given inset based on the value
+ // of |orientation_|.
+ int CrossAxisTrailingInset(const gfx::Insets& insets) const;
+
+ // Returns the main axis margin spacing between the two views which is the max
+ // of the right margin from the |left| view, the left margin of the |right|
+ // view and |between_child_spacing_|.
+ int MainAxisMarginBetweenViews(const ViewWrapper& left,
+ const ViewWrapper& right) const;
+
+ // Returns the outer margin along the main axis as insets.
+ gfx::Insets MainAxisOuterMargin() const;
+
+ // Returns the maximum margin along the cross axis from all views as insets.
+ gfx::Insets CrossAxisMaxViewMargin() const;
+
+ // Adjusts the main axis for |rect| by collapsing the left or top margin of
+ // the first view with corresponding side of |inside_border_insets_| and the
+ // right or bottom margin of the last view with the corresponding side of
+ // |inside_border_insets_|.
+ void AdjustMainAxisForMargin(gfx::Rect* rect) const;
+
+ // Adjust the cross axis for |rect| using the appropriate sides of
+ // |inside_border_insets_|.
+ void AdjustCrossAxisForInsets(gfx::Rect* rect) const;
// Returns the cross axis size for the given view.
- int CrossAxisSizeForView(const View* view) const;
+ int CrossAxisSizeForView(const ViewWrapper& view) const;
+
+ // Returns the total margin width for the given view or 0 when
+ // collapse_margins_spacing_ is true.
+ int CrossAxisMarginSizeForView(const ViewWrapper& view) const;
+
+ // Returns the Top or Left size of the margin for the given view or 0 when
+ // collapse_margins_spacing_ is true.
+ int CrossAxisLeadingMarginForView(const ViewWrapper& view) const;
+
+ // Adjust the cross axis for |rect| using the given leading and trailing
+ // values.
+ void InsetCrossAxis(gfx::Rect* rect, int leading, int trailing) const;
// The preferred size for the dialog given the width of the child area.
gfx::Size GetPreferredSizeForChildWidth(const View* host,
@@ -139,6 +279,16 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
// child views.
gfx::Size NonChildSize(const View* host) const;
+ // The next visible view at > index. If no other views are visible, return
+ // nullptr.
+ View* NextVisibleView(int index) const;
+
+ // Return the first visible view in the host or nullptr if none are visible.
+ View* FirstVisibleView() const;
+
+ // Return the last visible view in the host or nullptr if none are visible.
+ View* LastVisibleView() const;
+
const Orientation orientation_;
// Spacing between child views and host view border.
@@ -156,7 +306,7 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
CrossAxisAlignment cross_axis_alignment_;
// A map of views to their flex weights.
- std::map<const View*, int> flex_map_;
+ FlexMap flex_map_;
// The flex weight for views if none is set. Defaults to 0.
int default_flex_;
@@ -164,6 +314,9 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
// The minimum cross axis size for the layout.
int minimum_cross_axis_size_;
+ // Adjacent view margins and spacing should be collapsed.
+ const bool collapse_margins_spacing_;
+
// The view that this BoxLayout is managing the layout for.
views::View* host_;

Powered by Google App Engine
This is Rietveld 408576698