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

Side by Side Diff: ui/views/layout/align_layout.cc

Issue 2230913003: Experimental alignment layout manager using a property on the views Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Renamed AlignAttribute and associated types to FillAttribute Created 4 years, 2 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 unified diff | Download patch
« no previous file with comments | « ui/views/layout/align_layout.h ('k') | ui/views/layout/align_layout_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/layout/align_layout.h"
6
7 #include "base/logging.h"
8 #include "ui/views/anchor_attribute.h"
9
10 namespace views {
11
12 // This special value represents the absence of the align attribute.
13 static constexpr Fill Fill_None =
14 static_cast<Fill>(static_cast<int>(Fill::Content) + 1);
15
16 AlignLayout::AlignLayout() {}
17
18 AlignLayout::~AlignLayout() {}
19
20 void AlignLayout::AlignViews(View* host,
21 views::Fill fill,
22 gfx::Rect& contents) {
23 View::Views fill_list;
24 for (int i = 0; i < host->child_count(); ++i) {
25 FillAttribute* fill_attr;
26 View* child = host->child_at(i);
27 if (child->visible() && child->attributes().Find(fill_attr)
28 ? fill_attr->fill() == fill
29 : fill == Fill_None) {
30 View::Views::iterator j = fill_list.begin();
31 while (j < fill_list.end() && !ShouldInsert(child, *j, fill))
32 j++;
33 fill_list.insert(j, child);
34 }
35 }
36 for (View* child : fill_list)
37 PlaceView(child, fill, contents);
38 }
39
40 void AlignLayout::Layout(View* host) {
41 static const Fill fillstyles[] = {
42 views::Fill::Top, views::Fill::Bottom, views::Fill::Left,
43 views::Fill::Right, views::Fill::Content, Fill_None};
44 if (ShouldAlign(host)) {
45 gfx::Rect contents = host->GetContentsBounds();
46 for (std::size_t i = 0; i < sizeof(fillstyles) / sizeof(fillstyles[0]); i++)
47 AlignViews(host, fillstyles[i], contents);
48 }
49 }
50
51 gfx::Size AlignLayout::GetPreferredSize(const View* host) const {
52 return gfx::Size();
53 }
54
55 int AlignLayout::GetPreferredHeightForWidth(const View* host, int width) const {
56 return 0;
57 }
58
59 static int MulDiv(int Number, int Numerator, int Denominator) {
60 return static_cast<int>((static_cast<int64_t>(Number) * Numerator) /
61 Denominator);
62 }
63
64 void AlignLayout::PlaceView(View* view,
65 views::Fill fill,
66 gfx::Rect& contents) {
67 AnchorAttribute* anchor = nullptr;
68 AnchorContent local_content;
69 AnchorContent& content =
70 view->attributes().Find(anchor) ? anchor->GetContent() : local_content;
71 if (fill == Fill_None ||
72 content.anchors() != AnchorContent::AnchorFill(fill)) {
73 if (!content.LastParentSize().IsEmpty()) {
74 int new_left = view->x();
75 int new_top = view->y();
76 int new_width = view->width();
77 int new_height = view->height();
78 Anchors anchors = content.anchors();
79 gfx::Size parent_size = view->parent()->GetContentsBounds().size();
80 if (anchors.Contains(Anchor::Right))
81 if (anchors.Contains(Anchor::Left))
82 new_width = parent_size.width() - (content.LastParentSize().width() -
83 content.anchorBasis().x());
84 else
85 new_left = parent_size.width() - (content.LastParentSize().width() -
86 content.anchorBasis().x());
87 else if (!anchors.Contains(Anchor::Left))
88 new_left = MulDiv(content.anchorBasis().x(), parent_size.width(),
89 content.LastParentSize().width()) -
90 new_width / 2;
91 if (anchors.Contains(Anchor::Bottom))
92 if (anchors.Contains(Anchor::Top))
93 new_height =
94 parent_size.height() -
95 (content.LastParentSize().height() - content.anchorBasis().y());
96 else
97 new_top = parent_size.height() - (content.LastParentSize().height() -
98 content.anchorBasis().y());
99 else if (!anchors.Contains(Anchor::Top))
100 new_top = MulDiv(content.anchorBasis().y(), parent_size.height(),
101 content.LastParentSize().height()) -
102 new_height / 2;
103 view->SetBounds(new_left, new_top, new_width, new_height);
104 }
105 if (fill == Fill_None)
106 return;
107 }
108 int new_width = contents.size().width();
109 if (new_width < 0 || fill == views::Fill::Left ||
110 fill == views::Fill::Right)
111 new_width = view->width();
112 int new_height = contents.size().height();
113 if (new_height < 0 || fill == views::Fill::Top ||
114 fill == views::Fill::Bottom)
115 new_height = view->height();
116 int new_left = contents.x();
117 int new_top = contents.y();
118 switch (fill) {
119 case views::Fill::Top: {
120 contents.Inset(0, new_height, 0, 0);
121 break;
122 }
123 case views::Fill::Bottom: {
124 contents.Inset(0, 0, 0, new_height);
125 new_top = contents.bottom();
126 break;
127 }
128 case views::Fill::Left: {
129 contents.Inset(new_width, 0, 0, 0);
130 break;
131 }
132 case views::Fill::Right: {
133 contents.Inset(0, 0, new_width, 0);
134 new_left = contents.right();
135 // Fall through
136 }
137 default:
138 break;
139 }
140 view->SetBounds(new_left, new_top, new_width, new_height);
141 // If the view's bounds are constrained in some other manner, this
142 // will ensure the content rect is adjusted based on the actual
143 // size of the view.
144 if (view->width() != new_width || view->height() != new_height) {
145 switch (fill) {
146 case views::Fill::Top: {
147 contents.set_y(contents.y() - (new_height - view->height()));
148 break;
149 }
150 case views::Fill::Bottom: {
151 contents.set_height(contents.height() + (new_height - view->height()));
152 break;
153 }
154 case views::Fill::Left: {
155 contents.set_x(contents.x() - (new_width - view->width()));
156 break;
157 }
158 case views::Fill::Right: {
159 contents.set_width(contents.width() + (new_width - view->width()));
160 break;
161 }
162 case views::Fill::Content: {
163 contents.set_width(contents.width() + (new_width - view->width()));
164 contents.set_height(contents.height() + (new_height - view->width()));
165 }
166 }
167 }
168 }
169
170 bool AlignLayout::ShouldAlign(View* host) {
171 for (int i = 0; i < host->child_count(); ++i) {
172 FillAttribute* fill_attr;
173 AnchorAttribute* anchor_attr;
174 View* view = host->child_at(i);
175 if (view->visible() && (view->attributes().Find(fill_attr) ||
176 view->attributes().Find(anchor_attr)))
177 return true;
178 }
179 return false;
180 }
181
182 bool AlignLayout::ShouldInsert(View* child1, View* child2, views::Fill fill) {
183 switch (fill) {
184 case views::Fill::Top:
185 return child1->y() < child2->y();
186 case views::Fill::Bottom:
187 return child1->bounds().bottom() >= child2->bounds().bottom();
188 case views::Fill::Left:
189 return child1->x() < child2->x();
190 case views::Fill::Right:
191 return child1->bounds().right() >= child2->bounds().right();
192 default:
193 return false;
194 }
195 }
196
197 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/layout/align_layout.h ('k') | ui/views/layout/align_layout_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698