summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2014-05-14 22:15:54 +0300
committerAndrei Karas <akaras@inbox.ru>2014-05-14 22:15:54 +0300
commit4e7b98accb8f6fa927711174e4ee82a731317c74 (patch)
tree0d024c46b41771aa178771ec57eafe2f5f39f819
parentffee866c7eea91d38f6a27fbd4ecf38b573d32ee (diff)
downloadmanaplus-4e7b98accb8f6fa927711174e4ee82a731317c74.tar.gz
manaplus-4e7b98accb8f6fa927711174e4ee82a731317c74.tar.bz2
manaplus-4e7b98accb8f6fa927711174e4ee82a731317c74.tar.xz
manaplus-4e7b98accb8f6fa927711174e4ee82a731317c74.zip
Move layoutarray into separate file.
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/gui/widgets/layout.cpp270
-rw-r--r--src/gui/widgets/layout.h89
-rw-r--r--src/gui/widgets/layoutarray.cpp304
-rw-r--r--src/gui/widgets/layoutarray.h124
-rw-r--r--src/gui/widgets/layoutcell.cpp1
7 files changed, 433 insertions, 359 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f831a6190..baf729677 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -181,6 +181,8 @@ SET(SRCS
gui/widgets/tabs/langtab.h
gui/widgets/layout.cpp
gui/widgets/layout.h
+ gui/widgets/layoutarray.cpp
+ gui/widgets/layoutarray.h
gui/widgets/layoutcell.cpp
gui/widgets/layoutcell.h
gui/widgets/layouthelper.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 9d3449ed7..ee08b6c4a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -273,6 +273,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \
gui/widgets/tabs/langtab.h \
gui/widgets/layout.cpp \
gui/widgets/layout.h \
+ gui/widgets/layoutarray.cpp \
+ gui/widgets/layoutarray.h \
gui/widgets/layoutcell.cpp \
gui/widgets/layoutcell.h \
gui/widgets/layouthelper.cpp \
diff --git a/src/gui/widgets/layout.cpp b/src/gui/widgets/layout.cpp
index eb61bd4d5..1f67da953 100644
--- a/src/gui/widgets/layout.cpp
+++ b/src/gui/widgets/layout.cpp
@@ -32,276 +32,6 @@
#include "debug.h"
-LayoutArray::LayoutArray():
- mCells(),
- mSpacing(4)
-{
-}
-
-LayoutArray::~LayoutArray()
-{
- std::vector <std::vector <LayoutCell *> >::iterator
- i = mCells.begin();
- const std::vector <std::vector <LayoutCell *> >::iterator
- i_end = mCells.end();
- while (i != i_end)
- {
- std::vector< LayoutCell * >::iterator j = i->begin();
- const std::vector< LayoutCell * >::iterator j_end = i->end();
- while (j != j_end)
- {
- delete *j;
- ++j;
- }
- ++i;
- }
-}
-
-LayoutCell &LayoutArray::at(const int x, const int y,
- const int w, const int h)
-{
- resizeGrid(x + w, y + h);
- LayoutCell *&cell = mCells[y][x];
- if (!cell)
- cell = new LayoutCell;
- return *cell;
-}
-
-void LayoutArray::resizeGrid(int w, const int h)
-{
- const bool extW = w && w > static_cast<int>(mSizes[0].size());
- const bool extH = h && h > static_cast<int>(mSizes[1].size());
-
- if (!extW && !extH)
- return;
-
- if (extH)
- {
- mSizes[1].resize(h, Layout::AUTO_DEF);
- mCells.resize(h);
- if (!extW)
- w = static_cast<int>(mSizes[0].size());
- }
-
- if (extW)
- mSizes[0].resize(w, Layout::AUTO_DEF);
-
- std::vector <std::vector <LayoutCell *> >::iterator
- i = mCells.begin();
- const std::vector <std::vector <LayoutCell *> >::iterator
- i_end = mCells.end();
- while (i != i_end)
- {
- i->resize(w, nullptr);
- ++i;
- }
-}
-
-void LayoutArray::setColWidth(const int n, const int w)
-{
- resizeGrid(n + 1, 0);
- mSizes[0][n] = w;
-}
-
-void LayoutArray::setRowHeight(const int n, const int h)
-{
- resizeGrid(0, n + 1);
- mSizes[1][n] = h;
-}
-
-void LayoutArray::matchColWidth(const int n1, const int n2)
-{
- resizeGrid(std::max(n1, n2) + 1, 0);
- const std::vector<int> widths = getSizes(0, Layout::AUTO_DEF);
- const int s = std::max(widths[n1], widths[n2]);
- mSizes[0][n1] = s;
- mSizes[0][n2] = s;
-}
-
-void LayoutArray::extend(const int x, const int y, const int w, const int h)
-{
- LayoutCell &cell = at(x, y, w, h);
- cell.mExtent[0] = w;
- cell.mExtent[1] = h;
-}
-
-LayoutCell &LayoutArray::place(Widget *const widget, const int x,
- const int y, const int w, const int h)
-{
- LayoutCell &cell = at(x, y, w, h);
- assert(cell.mType == LayoutCell::NONE);
- cell.mType = LayoutCell::WIDGET;
- cell.mWidget = widget;
- if (widget)
- {
- cell.mSize[0] = w == 1 ? widget->getWidth() : 0;
- cell.mSize[1] = h == 1 ? widget->getHeight() : 0;
- }
- else
- {
- cell.mSize[0] = 1;
- cell.mSize[1] = 1;
- }
- cell.mExtent[0] = w;
- cell.mExtent[1] = h;
- cell.mHPadding = 0;
- cell.mVPadding = 0;
- cell.mAlign[0] = LayoutCell::FILL;
- cell.mAlign[1] = LayoutCell::FILL;
- int &cs = mSizes[0][x], &rs = mSizes[1][y];
- if (cs == Layout::AUTO_DEF && w == 1)
- cs = 0;
- if (rs == Layout::AUTO_DEF && h == 1)
- rs = 0;
- return cell;
-}
-
-void LayoutArray::align(int &restrict pos, int &restrict size, const int dim,
- LayoutCell const &restrict cell,
- const int *restrict const sizes,
- const int sizeCount) const
-{
- if (dim < 0 || dim >= 2)
- return;
- int size_max = sizes[0];
- int cnt = cell.mExtent[dim];
- if (sizeCount && cell.mExtent[dim] > sizeCount)
- cnt = sizeCount;
-
- for (int i = 1; i < cnt; ++i)
- size_max += sizes[i] + mSpacing;
- size = std::min<int>(cell.mSize[dim], size_max);
-
- switch (cell.mAlign[dim])
- {
- case LayoutCell::LEFT:
- return;
- case LayoutCell::RIGHT:
- pos += size_max - size;
- return;
- case LayoutCell::CENTER:
- pos += (size_max - size) / 2;
- return;
- case LayoutCell::FILL:
- size = size_max;
- return;
- default:
- logger->log1("LayoutArray::align unknown layout");
- return;
- }
-}
-
-std::vector<int> LayoutArray::getSizes(const int dim, int upp) const
-{
- if (dim < 0 || dim >= 2)
- return mSizes[1];
-
- const int gridW = static_cast<int>(mSizes[0].size());
- const int gridH = static_cast<int>(mSizes[1].size());
- std::vector<int> sizes = mSizes[dim];
-
- // Compute minimum sizes.
- for (int gridY = 0; gridY < gridH; ++gridY)
- {
- for (int gridX = 0; gridX < gridW; ++gridX)
- {
- const LayoutCell *const cell = mCells[gridY][gridX];
- if (!cell || cell->mType == LayoutCell::NONE)
- continue;
-
- if (cell->mExtent[dim] == 1)
- {
- const int n = (dim == 0 ? gridX : gridY);
- const int s = cell->mSize[dim] + cell->mVPadding * 2;
- if (s > sizes[n])
- sizes[n] = s;
- }
- }
- }
-
- if (upp == Layout::AUTO_DEF)
- return sizes;
-
- // Compute the FILL sizes.
- const int nb = static_cast<int>(sizes.size());
- int nbFill = 0;
- for (int i = 0; i < nb; ++i)
- {
- if (mSizes[dim][i] <= Layout::AUTO_DEF)
- {
- ++nbFill;
- if (mSizes[dim][i] == Layout::AUTO_SET ||
- sizes[i] <= Layout::AUTO_DEF)
- {
- sizes[i] = 0;
- }
- }
- upp -= sizes[i] + mSpacing;
- }
- upp = upp + mSpacing;
-
- if (nbFill == 0)
- return sizes;
-
- for (int i = 0; i < nb; ++i)
- {
- if (mSizes[dim][i] > Layout::AUTO_DEF)
- continue;
-
- const int s = upp / nbFill;
- sizes[i] += s;
- upp -= s;
- --nbFill;
- }
-
- return sizes;
-}
-
-int LayoutArray::getSize(const int dim) const
-{
- std::vector<int> sizes = getSizes(dim, Layout::AUTO_DEF);
- int size = 0;
- const int nb = static_cast<int>(sizes.size());
- for (int i = 0; i < nb; ++i)
- {
- if (sizes[i] > Layout::AUTO_DEF)
- size += sizes[i];
- size += mSpacing;
- }
- return size - mSpacing;
-}
-
-void LayoutArray::reflow(const int nx, const int ny,
- const int nw, const int nh)
-{
- const int gridW = static_cast<int>(mSizes[0].size());
- const int gridH = static_cast<int>(mSizes[1].size());
-
- std::vector<int> widths = getSizes(0, nw);
- std::vector<int> heights = getSizes(1, nh);
-
- const int szW = static_cast<int>(widths.size());
- const int szH = static_cast<int>(heights.size());
- int y = ny;
- for (int gridY = 0; gridY < gridH; ++gridY)
- {
- int x = nx;
- for (int gridX = 0; gridX < gridW; ++gridX)
- {
- LayoutCell *const cell = mCells[gridY][gridX];
- if (cell && cell->mType != LayoutCell::NONE)
- {
- int dx = x, dy = y, dw = 0, dh = 0;
- align(dx, dw, 0, *cell, &widths[gridX], szW - gridX);
- align(dy, dh, 1, *cell, &heights[gridY], szH - gridY);
- cell->reflow(dx, dy, dw, dh);
- }
- x += widths[gridX] + mSpacing;
- }
- y += heights[gridY] + mSpacing;
- }
-}
-
Layout::Layout() :
LayoutCell(),
mComputed(false)
diff --git a/src/gui/widgets/layout.h b/src/gui/widgets/layout.h
index c41c6570f..9e2cbb698 100644
--- a/src/gui/widgets/layout.h
+++ b/src/gui/widgets/layout.h
@@ -33,95 +33,6 @@ class BasicContainer2;
class Widget;
/**
- * This class contains a rectangular array of cells.
- */
-class LayoutArray final
-{
- friend class LayoutCell;
-
- public:
- LayoutArray();
-
- ~LayoutArray();
-
- /**
- * Returns a reference on the cell at given position.
- */
- LayoutCell &at(const int x, const int y,
- const int w = 1, const int h = 1) A_WARN_UNUSED;
-
- /**
- * Places a widget in a given cell.
- * @param w number of columns the widget spawns.
- * @param h number of rows the widget spawns.
- * @note When @a w is 1, the width of column @a x is reset to zero if
- * it was AUTO_DEF. Similarly for @a h.
- */
- LayoutCell &place(Widget *const widget, const int x, const int y,
- const int w = 1, const int h = 1);
-
- /**
- * Sets the minimum width of a column.
- */
- void setColWidth(const int n, const int w);
-
- /**
- * Sets the minimum height of a row.
- */
- void setRowHeight(const int n, const int h);
-
- /**
- * Sets the widths of two columns to the maximum of their widths.
- */
- void matchColWidth(const int n1, const int n2);
-
- /**
- * Spawns a cell over several columns/rows.
- */
- void extend(const int x, const int y, const int w, const int h);
-
- /**
- * Computes and sets the positions of all the widgets.
- * @param nW width of the array, used to resize the AUTO_ columns.
- * @param nH height of the array, used to resize the AUTO_ rows.
- */
- void reflow(const int nX, const int nY, const int nW, const int nH);
-
- private:
- // Copy not allowed, as the array owns all its cells.
- explicit LayoutArray(LayoutArray const &);
- LayoutArray &operator=(LayoutArray const &);
-
- /**
- * Gets the position and size of a widget along a given axis
- */
- void align(int &restrict pos, int &restrict size, const int dim,
- LayoutCell const &restrict cell,
- const int *restrict const sizes, const int sizeCount) const;
-
- /**
- * Ensures the private vectors are large enough.
- */
- void resizeGrid(int w, const int h);
-
- /**
- * Gets the column/row sizes along a given axis.
- * @param upp target size for the array. Ignored if AUTO_DEF.
- */
- std::vector<int> getSizes(const int dim, int upp) const A_WARN_UNUSED;
-
- /**
- * Gets the total size along a given axis.
- */
- int getSize(const int dim) const A_WARN_UNUSED;
-
- std::vector<int> mSizes[2];
- std::vector< std::vector < LayoutCell * > > mCells;
-
- int mSpacing;
-};
-
-/**
* This class is an helper for setting the position of widgets. They are
* positioned along the cells of some rectangular tables. The layout may either
* be a single table or a tree of nested tables.
diff --git a/src/gui/widgets/layoutarray.cpp b/src/gui/widgets/layoutarray.cpp
new file mode 100644
index 000000000..b0d534f00
--- /dev/null
+++ b/src/gui/widgets/layoutarray.cpp
@@ -0,0 +1,304 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/layoutarray.h"
+
+#include "logger.h"
+
+#include "gui/widgets/basiccontainer2.h"
+#include "gui/widgets/layout.h"
+
+#include "utils/delete2.h"
+
+#include <cassert>
+
+#include "debug.h"
+
+LayoutArray::LayoutArray():
+ mCells(),
+ mSpacing(4)
+{
+}
+
+LayoutArray::~LayoutArray()
+{
+ std::vector <std::vector <LayoutCell *> >::iterator
+ i = mCells.begin();
+ const std::vector <std::vector <LayoutCell *> >::iterator
+ i_end = mCells.end();
+ while (i != i_end)
+ {
+ std::vector< LayoutCell * >::iterator j = i->begin();
+ const std::vector< LayoutCell * >::iterator j_end = i->end();
+ while (j != j_end)
+ {
+ delete *j;
+ ++j;
+ }
+ ++i;
+ }
+}
+
+LayoutCell &LayoutArray::at(const int x, const int y,
+ const int w, const int h)
+{
+ resizeGrid(x + w, y + h);
+ LayoutCell *&cell = mCells[y][x];
+ if (!cell)
+ cell = new LayoutCell;
+ return *cell;
+}
+
+void LayoutArray::resizeGrid(int w, const int h)
+{
+ const bool extW = w && w > static_cast<int>(mSizes[0].size());
+ const bool extH = h && h > static_cast<int>(mSizes[1].size());
+
+ if (!extW && !extH)
+ return;
+
+ if (extH)
+ {
+ mSizes[1].resize(h, Layout::AUTO_DEF);
+ mCells.resize(h);
+ if (!extW)
+ w = static_cast<int>(mSizes[0].size());
+ }
+
+ if (extW)
+ mSizes[0].resize(w, Layout::AUTO_DEF);
+
+ std::vector <std::vector <LayoutCell *> >::iterator
+ i = mCells.begin();
+ const std::vector <std::vector <LayoutCell *> >::iterator
+ i_end = mCells.end();
+ while (i != i_end)
+ {
+ i->resize(w, nullptr);
+ ++i;
+ }
+}
+
+void LayoutArray::setColWidth(const int n, const int w)
+{
+ resizeGrid(n + 1, 0);
+ mSizes[0][n] = w;
+}
+
+void LayoutArray::setRowHeight(const int n, const int h)
+{
+ resizeGrid(0, n + 1);
+ mSizes[1][n] = h;
+}
+
+void LayoutArray::matchColWidth(const int n1, const int n2)
+{
+ resizeGrid(std::max(n1, n2) + 1, 0);
+ const std::vector<int> widths = getSizes(0, Layout::AUTO_DEF);
+ const int s = std::max(widths[n1], widths[n2]);
+ mSizes[0][n1] = s;
+ mSizes[0][n2] = s;
+}
+
+void LayoutArray::extend(const int x, const int y, const int w, const int h)
+{
+ LayoutCell &cell = at(x, y, w, h);
+ cell.mExtent[0] = w;
+ cell.mExtent[1] = h;
+}
+
+LayoutCell &LayoutArray::place(Widget *const widget, const int x,
+ const int y, const int w, const int h)
+{
+ LayoutCell &cell = at(x, y, w, h);
+ assert(cell.mType == LayoutCell::NONE);
+ cell.mType = LayoutCell::WIDGET;
+ cell.mWidget = widget;
+ if (widget)
+ {
+ cell.mSize[0] = w == 1 ? widget->getWidth() : 0;
+ cell.mSize[1] = h == 1 ? widget->getHeight() : 0;
+ }
+ else
+ {
+ cell.mSize[0] = 1;
+ cell.mSize[1] = 1;
+ }
+ cell.mExtent[0] = w;
+ cell.mExtent[1] = h;
+ cell.mHPadding = 0;
+ cell.mVPadding = 0;
+ cell.mAlign[0] = LayoutCell::FILL;
+ cell.mAlign[1] = LayoutCell::FILL;
+ int &cs = mSizes[0][x], &rs = mSizes[1][y];
+ if (cs == Layout::AUTO_DEF && w == 1)
+ cs = 0;
+ if (rs == Layout::AUTO_DEF && h == 1)
+ rs = 0;
+ return cell;
+}
+
+void LayoutArray::align(int &restrict pos, int &restrict size, const int dim,
+ LayoutCell const &restrict cell,
+ const int *restrict const sizes,
+ const int sizeCount) const
+{
+ if (dim < 0 || dim >= 2)
+ return;
+ int size_max = sizes[0];
+ int cnt = cell.mExtent[dim];
+ if (sizeCount && cell.mExtent[dim] > sizeCount)
+ cnt = sizeCount;
+
+ for (int i = 1; i < cnt; ++i)
+ size_max += sizes[i] + mSpacing;
+ size = std::min<int>(cell.mSize[dim], size_max);
+
+ switch (cell.mAlign[dim])
+ {
+ case LayoutCell::LEFT:
+ return;
+ case LayoutCell::RIGHT:
+ pos += size_max - size;
+ return;
+ case LayoutCell::CENTER:
+ pos += (size_max - size) / 2;
+ return;
+ case LayoutCell::FILL:
+ size = size_max;
+ return;
+ default:
+ logger->log1("LayoutArray::align unknown layout");
+ return;
+ }
+}
+
+std::vector<int> LayoutArray::getSizes(const int dim, int upp) const
+{
+ if (dim < 0 || dim >= 2)
+ return mSizes[1];
+
+ const int gridW = static_cast<int>(mSizes[0].size());
+ const int gridH = static_cast<int>(mSizes[1].size());
+ std::vector<int> sizes = mSizes[dim];
+
+ // Compute minimum sizes.
+ for (int gridY = 0; gridY < gridH; ++gridY)
+ {
+ for (int gridX = 0; gridX < gridW; ++gridX)
+ {
+ const LayoutCell *const cell = mCells[gridY][gridX];
+ if (!cell || cell->mType == LayoutCell::NONE)
+ continue;
+
+ if (cell->mExtent[dim] == 1)
+ {
+ const int n = (dim == 0 ? gridX : gridY);
+ const int s = cell->mSize[dim] + cell->mVPadding * 2;
+ if (s > sizes[n])
+ sizes[n] = s;
+ }
+ }
+ }
+
+ if (upp == Layout::AUTO_DEF)
+ return sizes;
+
+ // Compute the FILL sizes.
+ const int nb = static_cast<int>(sizes.size());
+ int nbFill = 0;
+ for (int i = 0; i < nb; ++i)
+ {
+ if (mSizes[dim][i] <= Layout::AUTO_DEF)
+ {
+ ++nbFill;
+ if (mSizes[dim][i] == Layout::AUTO_SET ||
+ sizes[i] <= Layout::AUTO_DEF)
+ {
+ sizes[i] = 0;
+ }
+ }
+ upp -= sizes[i] + mSpacing;
+ }
+ upp = upp + mSpacing;
+
+ if (nbFill == 0)
+ return sizes;
+
+ for (int i = 0; i < nb; ++i)
+ {
+ if (mSizes[dim][i] > Layout::AUTO_DEF)
+ continue;
+
+ const int s = upp / nbFill;
+ sizes[i] += s;
+ upp -= s;
+ --nbFill;
+ }
+
+ return sizes;
+}
+
+int LayoutArray::getSize(const int dim) const
+{
+ std::vector<int> sizes = getSizes(dim, Layout::AUTO_DEF);
+ int size = 0;
+ const int nb = static_cast<int>(sizes.size());
+ for (int i = 0; i < nb; ++i)
+ {
+ if (sizes[i] > Layout::AUTO_DEF)
+ size += sizes[i];
+ size += mSpacing;
+ }
+ return size - mSpacing;
+}
+
+void LayoutArray::reflow(const int nx, const int ny,
+ const int nw, const int nh)
+{
+ const int gridW = static_cast<int>(mSizes[0].size());
+ const int gridH = static_cast<int>(mSizes[1].size());
+
+ std::vector<int> widths = getSizes(0, nw);
+ std::vector<int> heights = getSizes(1, nh);
+
+ const int szW = static_cast<int>(widths.size());
+ const int szH = static_cast<int>(heights.size());
+ int y = ny;
+ for (int gridY = 0; gridY < gridH; ++gridY)
+ {
+ int x = nx;
+ for (int gridX = 0; gridX < gridW; ++gridX)
+ {
+ LayoutCell *const cell = mCells[gridY][gridX];
+ if (cell && cell->mType != LayoutCell::NONE)
+ {
+ int dx = x, dy = y, dw = 0, dh = 0;
+ align(dx, dw, 0, *cell, &widths[gridX], szW - gridX);
+ align(dy, dh, 1, *cell, &heights[gridY], szH - gridY);
+ cell->reflow(dx, dy, dw, dh);
+ }
+ x += widths[gridX] + mSpacing;
+ }
+ y += heights[gridY] + mSpacing;
+ }
+}
diff --git a/src/gui/widgets/layoutarray.h b/src/gui/widgets/layoutarray.h
new file mode 100644
index 000000000..f6fffde18
--- /dev/null
+++ b/src/gui/widgets/layoutarray.h
@@ -0,0 +1,124 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_LAYOUTARRAY_H
+#define GUI_WIDGETS_LAYOUTARRAY_H
+
+#include "gui/widgets/layoutcell.h"
+
+#include <vector>
+
+#include "localconsts.h"
+
+class BasicContainer2;
+class Widget;
+
+/**
+ * This class contains a rectangular array of cells.
+ */
+class LayoutArray final
+{
+ friend class LayoutCell;
+
+ public:
+ LayoutArray();
+
+ ~LayoutArray();
+
+ /**
+ * Returns a reference on the cell at given position.
+ */
+ LayoutCell &at(const int x, const int y,
+ const int w = 1, const int h = 1) A_WARN_UNUSED;
+
+ /**
+ * Places a widget in a given cell.
+ * @param w number of columns the widget spawns.
+ * @param h number of rows the widget spawns.
+ * @note When @a w is 1, the width of column @a x is reset to zero if
+ * it was AUTO_DEF. Similarly for @a h.
+ */
+ LayoutCell &place(Widget *const widget, const int x, const int y,
+ const int w = 1, const int h = 1);
+
+ /**
+ * Sets the minimum width of a column.
+ */
+ void setColWidth(const int n, const int w);
+
+ /**
+ * Sets the minimum height of a row.
+ */
+ void setRowHeight(const int n, const int h);
+
+ /**
+ * Sets the widths of two columns to the maximum of their widths.
+ */
+ void matchColWidth(const int n1, const int n2);
+
+ /**
+ * Spawns a cell over several columns/rows.
+ */
+ void extend(const int x, const int y, const int w, const int h);
+
+ /**
+ * Computes and sets the positions of all the widgets.
+ * @param nW width of the array, used to resize the AUTO_ columns.
+ * @param nH height of the array, used to resize the AUTO_ rows.
+ */
+ void reflow(const int nX, const int nY, const int nW, const int nH);
+
+ private:
+ // Copy not allowed, as the array owns all its cells.
+ explicit LayoutArray(LayoutArray const &);
+ LayoutArray &operator=(LayoutArray const &);
+
+ /**
+ * Gets the position and size of a widget along a given axis
+ */
+ void align(int &restrict pos, int &restrict size, const int dim,
+ LayoutCell const &restrict cell,
+ const int *restrict const sizes, const int sizeCount) const;
+
+ /**
+ * Ensures the private vectors are large enough.
+ */
+ void resizeGrid(int w, const int h);
+
+ /**
+ * Gets the column/row sizes along a given axis.
+ * @param upp target size for the array. Ignored if AUTO_DEF.
+ */
+ std::vector<int> getSizes(const int dim, int upp) const A_WARN_UNUSED;
+
+ /**
+ * Gets the total size along a given axis.
+ */
+ int getSize(const int dim) const A_WARN_UNUSED;
+
+ std::vector<int> mSizes[2];
+ std::vector< std::vector < LayoutCell * > > mCells;
+
+ int mSpacing;
+};
+
+#endif // GUI_WIDGETS_LAYOUTARRAY_H
diff --git a/src/gui/widgets/layoutcell.cpp b/src/gui/widgets/layoutcell.cpp
index 58ba6976e..9f5996284 100644
--- a/src/gui/widgets/layoutcell.cpp
+++ b/src/gui/widgets/layoutcell.cpp
@@ -23,6 +23,7 @@
#include "gui/widgets/layoutcell.h"
#include "gui/widgets/layout.h"
+#include "gui/widgets/layoutarray.h"
#include "gui/widgets/widget.h"
#include "utils/delete2.h"