1 /*
2 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7 #include "Wt/WGridLayout.h"
8 #include "Wt/WWidgetItem.h"
9
10 #include "StdGridLayoutImpl2.h"
11
12 #include <algorithm>
13
14 namespace Wt {
15
16 namespace Impl {
17
Section(int stretch)18 Grid::Section::Section(int stretch)
19 : stretch_(stretch),
20 resizable_(false)
21 { }
22
Item(std::unique_ptr<WLayoutItem> item,WFlags<AlignmentFlag> alignment)23 Grid::Item::Item(std::unique_ptr<WLayoutItem> item,
24 WFlags<AlignmentFlag> alignment)
25 : item_(std::move(item)),
26 rowSpan_(1),
27 colSpan_(1),
28 update_(true),
29 alignment_(alignment)
30 { }
31
~Item()32 Grid::Item::~Item()
33 { }
34
Grid()35 Grid::Grid()
36 : horizontalSpacing_(6),
37 verticalSpacing_(6)
38 { }
39
~Grid()40 Grid::~Grid()
41 {
42 }
43
clear()44 void Grid::clear()
45 {
46 rows_.clear();
47 columns_.clear();
48 items_.clear();
49 }
50
51 }
52
WGridLayout()53 WGridLayout::WGridLayout()
54 { }
55
~WGridLayout()56 WGridLayout::~WGridLayout()
57 { }
58
addItem(std::unique_ptr<WLayoutItem> item)59 void WGridLayout::addItem(std::unique_ptr<WLayoutItem> item)
60 {
61 addItem(std::move(item), 0, columnCount());
62 }
63
removeItem(WLayoutItem * item)64 std::unique_ptr<WLayoutItem> WGridLayout::removeItem(WLayoutItem *item)
65 {
66 int index = indexOf(item);
67
68 std::unique_ptr<WLayoutItem> result;
69
70 if (index != -1) {
71 int row = index / columnCount();
72 int col = index % columnCount();
73
74 result = std::move(grid_.items_[row][col].item_);
75 itemRemoved(item);
76 }
77
78 return result;
79 }
80
itemAt(int index)81 WLayoutItem *WGridLayout::itemAt(int index) const
82 {
83 int row = index / columnCount();
84 int col = index % columnCount();
85
86 return grid_.items_[row][col].item_.get();
87 }
88
iterateWidgets(const HandleWidgetMethod & method)89 void WGridLayout::iterateWidgets(const HandleWidgetMethod& method) const
90 {
91 for (unsigned r = 0; r < grid_.rows_.size(); ++r) {
92 for (unsigned c = 0; c < grid_.columns_.size(); ++c) {
93 WLayoutItem *item = grid_.items_[r][c].item_.get();
94 if (item)
95 item->iterateWidgets(method);
96 }
97 }
98 }
99
count()100 int WGridLayout::count() const
101 {
102 return grid_.rows_.size() * grid_.columns_.size();
103 }
104
addItem(std::unique_ptr<WLayoutItem> item,int row,int column,int rowSpan,int columnSpan,WFlags<AlignmentFlag> alignment)105 void WGridLayout::addItem(std::unique_ptr<WLayoutItem> item,
106 int row, int column,
107 int rowSpan, int columnSpan,
108 WFlags<AlignmentFlag> alignment)
109 {
110 columnSpan = std::max(1, columnSpan);
111 rowSpan = std::max(1, rowSpan);
112
113 expand(row, column, rowSpan, columnSpan);
114
115 Impl::Grid::Item& gridItem = grid_.items_[row][column];
116
117 if (gridItem.item_) {
118 auto oldItem = std::move(gridItem.item_);
119 itemRemoved(oldItem.get());
120 }
121
122 gridItem.item_ = std::move(item);
123 gridItem.rowSpan_ = rowSpan;
124 gridItem.colSpan_ = columnSpan;
125 gridItem.alignment_ = alignment;
126
127 itemAdded(gridItem.item_.get());
128 }
129
addLayout(std::unique_ptr<WLayout> layout,int row,int column,WFlags<AlignmentFlag> alignment)130 void WGridLayout::addLayout(std::unique_ptr<WLayout> layout,
131 int row, int column,
132 WFlags<AlignmentFlag> alignment)
133 {
134 addItem(std::move(layout), row, column, 1, 1, alignment);
135 }
136
addLayout(std::unique_ptr<WLayout> layout,int row,int column,int rowSpan,int columnSpan,WFlags<AlignmentFlag> alignment)137 void WGridLayout::addLayout(std::unique_ptr<WLayout> layout,
138 int row, int column,
139 int rowSpan, int columnSpan,
140 WFlags<AlignmentFlag> alignment)
141 {
142 addItem(std::move(layout), row, column, rowSpan, columnSpan, alignment);
143 }
144
addWidget(std::unique_ptr<WWidget> widget,int row,int column,WFlags<AlignmentFlag> alignment)145 void WGridLayout::addWidget(std::unique_ptr<WWidget> widget,
146 int row, int column,
147 WFlags<AlignmentFlag> alignment)
148 {
149 addItem(std::unique_ptr<WLayoutItem>(new WWidgetItem(std::move(widget))),
150 row, column, 1, 1, alignment);
151 }
152
addWidget(std::unique_ptr<WWidget> widget,int row,int column,int rowSpan,int columnSpan,WFlags<AlignmentFlag> alignment)153 void WGridLayout::addWidget(std::unique_ptr<WWidget> widget,
154 int row, int column,
155 int rowSpan, int columnSpan,
156 WFlags<AlignmentFlag> alignment)
157 {
158 addItem(std::unique_ptr<WLayoutItem>(new WWidgetItem(std::move(widget))),
159 row, column, rowSpan, columnSpan, alignment);
160 }
161
setHorizontalSpacing(int size)162 void WGridLayout::setHorizontalSpacing(int size)
163 {
164 grid_.horizontalSpacing_ = size;
165
166 update();
167 }
168
setVerticalSpacing(int size)169 void WGridLayout::setVerticalSpacing(int size)
170 {
171 grid_.verticalSpacing_ = size;
172
173 update();
174 }
175
columnCount()176 int WGridLayout::columnCount() const
177 {
178 return grid_.columns_.size();
179 }
180
rowCount()181 int WGridLayout::rowCount() const
182 {
183 return grid_.rows_.size();
184 }
185
setColumnStretch(int column,int stretch)186 void WGridLayout::setColumnStretch(int column, int stretch)
187 {
188 expand(0, column, 0, 1);
189 grid_.columns_[column].stretch_ = stretch;
190
191 update();
192 }
193
columnStretch(int column)194 int WGridLayout::columnStretch(int column) const
195 {
196 return grid_.columns_[column].stretch_;
197 }
198
setRowStretch(int row,int stretch)199 void WGridLayout::setRowStretch(int row, int stretch)
200 {
201 expand(row, 0, 1, 0);
202 grid_.rows_[row].stretch_ = stretch;
203
204 update();
205 }
206
rowStretch(int row)207 int WGridLayout::rowStretch(int row) const
208 {
209 return grid_.rows_[row].stretch_;
210 }
211
setRowResizable(int row,bool enabled,const WLength & initialSize)212 void WGridLayout::setRowResizable(int row, bool enabled,
213 const WLength& initialSize)
214 {
215 expand(row, 0, 1, 0);
216 grid_.rows_[row].resizable_ = enabled;
217 grid_.rows_[row].initialSize_ = initialSize;
218
219 update();
220 }
221
rowIsResizable(int row)222 bool WGridLayout::rowIsResizable(int row) const
223 {
224 return grid_.rows_[row].resizable_;
225 }
226
setColumnResizable(int column,bool enabled,const WLength & initialSize)227 void WGridLayout::setColumnResizable(int column, bool enabled,
228 const WLength& initialSize)
229 {
230 expand(0, column, 0, 1);
231 grid_.columns_[column].resizable_ = enabled;
232 grid_.columns_[column].initialSize_ = initialSize;
233
234 update();
235 }
236
columnIsResizable(int column)237 bool WGridLayout::columnIsResizable(int column) const
238 {
239 return grid_.columns_[column].resizable_;
240 }
241
expand(int row,int column,int rowSpan,int columnSpan)242 void WGridLayout::expand(int row, int column, int rowSpan, int columnSpan)
243 {
244 int newRowCount = std::max(rowCount(), row + rowSpan);
245 int newColumnCount = std::max(columnCount(), column + columnSpan);
246
247 int extraRows = newRowCount - rowCount();
248 int extraColumns = newColumnCount - columnCount();
249
250 if (extraColumns > 0) {
251 for (int a_row = 0; a_row < rowCount(); ++a_row) {
252 for (int i = 0; i < extraColumns; ++i)
253 grid_.items_[a_row].push_back(Impl::Grid::Item());
254 }
255
256 grid_.columns_.insert(grid_.columns_.end(), extraColumns,
257 Impl::Grid::Section());
258 }
259
260 if (extraRows > 0) {
261 #ifndef WT_TARGET_JAVA
262 for (int i = 0; i < extraRows; ++i) {
263 std::vector<Impl::Grid::Item> row;
264 for (int a_col = 0; a_col < columnCount(); ++a_col)
265 row.push_back(Impl::Grid::Item());
266 grid_.items_.push_back(std::move(row));
267 }
268 #else
269 grid_.items_.insert(grid_.items_.end(), extraRows,
270 std::vector<Impl::Grid::Item>());
271 for (int i = 0; i < extraRows; ++i) {
272 std::vector<Impl::Grid::Item>& items
273 = grid_.items_[grid_.items_.size() - extraRows + i];
274 items.insert(items.end(), newColumnCount, Impl::Grid::Item());
275 }
276 #endif // WT_TARGET_JAVA
277 grid_.rows_.insert(grid_.rows_.end(), extraRows, Impl::Grid::Section());
278 }
279 }
280
setParentWidget(WWidget * parent)281 void WGridLayout::setParentWidget(WWidget *parent)
282 {
283 WLayout::setParentWidget(parent);
284
285 if (parent)
286 setImpl(std::unique_ptr<WLayoutImpl>
287 (new StdGridLayoutImpl2(this, grid_)));
288 }
289
290
291 }
292