diff options
author | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-10-27 20:23:48 +0000 |
---|---|---|
committer | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-10-27 20:23:48 +0000 |
commit | 97bbe57e21a28544646da087e2a522390bf2ce5c (patch) | |
tree | a1899345f3b3928b3b0747b2429a45d08f79ae59 /src/gui/widgets/layout.cpp | |
parent | ee15a808a1e0d36167f80d9f96147103ba5583de (diff) | |
download | mana-97bbe57e21a28544646da087e2a522390bf2ce5c.tar.gz mana-97bbe57e21a28544646da087e2a522390bf2ce5c.tar.bz2 mana-97bbe57e21a28544646da087e2a522390bf2ce5c.tar.xz mana-97bbe57e21a28544646da087e2a522390bf2ce5c.zip |
Improved layout handler to support trees of nested arrays. Needed for converting and fixing the trade window.
Diffstat (limited to 'src/gui/widgets/layout.cpp')
-rw-r--r-- | src/gui/widgets/layout.cpp | 231 |
1 files changed, 172 insertions, 59 deletions
diff --git a/src/gui/widgets/layout.cpp b/src/gui/widgets/layout.cpp index 252cf198..2bcc558d 100644 --- a/src/gui/widgets/layout.cpp +++ b/src/gui/widgets/layout.cpp @@ -21,9 +21,103 @@ * $Id$ */ +#include <cassert> + #include "layout.h" -void Layout::resizeGrid(int w, int h) +ContainerPlacer ContainerPlacer::at(int x, int y) +{ + return ContainerPlacer(mContainer, &mCell->at(x, y)); +} + +LayoutCell &ContainerPlacer::operator() + (int x, int y, gcn::Widget *wg, int w, int h) +{ + mContainer->add(wg); + return mCell->place(wg, x, y, w, h); +} + +LayoutCell::~LayoutCell() +{ + if (mType == ARRAY) delete mArray; +} + +LayoutArray &LayoutCell::getArray() +{ + assert(mType != WIDGET); + if (mType == ARRAY) return *mArray; + mArray = new LayoutArray; + mType = ARRAY; + mExtent[0] = 1; + mExtent[1] = 1; + mPadding = 0; + mAlign[0] = FILL; + mAlign[1] = FILL; + return *mArray; +} + +void LayoutCell::reflow(int nx, int ny, int nw, int nh) +{ + assert(mType != NONE); + nx += mPadding; + ny += mPadding; + nw -= 2 * mPadding; + nh -= 2 * mPadding; + if (mType == ARRAY) + mArray->reflow(nx, ny, nw, nh); + else + mWidget->setDimension(gcn::Rectangle(nx, ny, nw, nh)); +} + +void LayoutCell::computeSizes() +{ + assert(mType == ARRAY); + + for (std::vector< std::vector< LayoutCell * > >::iterator + i = mArray->mCells.begin(), i_end = mArray->mCells.end(); + i != i_end; ++i) + { + for (std::vector< LayoutCell * >::iterator + j = i->begin(), j_end = i->end(); j != j_end; ++j) + { + LayoutCell *cell = *j; + if (cell && cell->mType == ARRAY) cell->computeSizes(); + } + } + + mSize[0] = mArray->getSize(0); + mSize[1] = mArray->getSize(1); +} + +LayoutArray::LayoutArray(): mSpacing(4) +{ +} + +LayoutArray::~LayoutArray() +{ + for (std::vector< std::vector< LayoutCell * > >::iterator + i = mCells.begin(), i_end = mCells.end(); i != i_end; ++i) + { + for (std::vector< LayoutCell * >::iterator + j = i->begin(), j_end = i->end(); j != j_end; ++j) + { + delete *j; + } + } +} + +LayoutCell &LayoutArray::at(int x, int y, int w, int h) +{ + resizeGrid(x + w, y + h); + LayoutCell *&cell = mCells[y][x]; + if (!cell) + { + cell = new LayoutCell; + } + return *cell; +} + +void LayoutArray::resizeGrid(int w, int h) { bool extW = w && w > (int)mSizes[0].size(), extH = h && h > (int)mSizes[1].size(); @@ -31,127 +125,128 @@ void Layout::resizeGrid(int w, int h) if (extH) { - mSizes[1].resize(h, FILL); + mSizes[1].resize(h, Layout::FILL); mCells.resize(h); if (!extW) w = mSizes[0].size(); } if (extW) { - mSizes[0].resize(w, FILL); + mSizes[0].resize(w, Layout::FILL); } - for (std::vector< std::vector< Cell > >::iterator + for (std::vector< std::vector< LayoutCell * > >::iterator i = mCells.begin(), i_end = mCells.end(); i != i_end; ++i) { - i->resize(w); + i->resize(w, NULL); } } -void Layout::setColWidth(int n, int w) +void LayoutArray::setColWidth(int n, int w) { resizeGrid(n + 1, 0); mSizes[0][n] = w; } -void Layout::setRowHeight(int n, int h) +void LayoutArray::setRowHeight(int n, int h) { resizeGrid(0, n + 1); mSizes[1][n] = h; } -void Layout::matchColWidth(int n1, int n2) +void LayoutArray::matchColWidth(int n1, int n2) { resizeGrid(std::max(n1, n2) + 1, 0); - std::vector< int > widths = compute(0, mW); + std::vector< short > widths = getSizes(0, Layout::FILL); int s = std::max(widths[n1], widths[n2]); mSizes[0][n1] = s; mSizes[0][n2] = s; } -Cell &Layout::place(gcn::Widget *widget, int x, int y, int w, int h) +LayoutCell &LayoutArray::place(gcn::Widget *widget, int x, int y, int w, int h) { - resizeGrid(x + w, y + h); - Cell &cell = mCells[y][x]; + LayoutCell &cell = at(x, y, w, h); + assert(cell.mType == LayoutCell::NONE); + cell.mType = LayoutCell::WIDGET; cell.mWidget = widget; + cell.mSize[0] = w == 1 ? widget->getWidth() : 0; + cell.mSize[1] = h == 1 ? widget->getHeight() : 0; cell.mExtent[0] = w; cell.mExtent[1] = h; cell.mPadding = 0; - cell.mAlign[0] = Cell::FILL; - cell.mAlign[1] = Cell::FILL; - int &cs = mSizes[0][x], &rs = mSizes[1][y]; - if (cs == FILL) cs = 0; - if (rs == FILL) rs = 0; + cell.mAlign[0] = LayoutCell::FILL; + cell.mAlign[1] = LayoutCell::FILL; + short &cs = mSizes[0][x], &rs = mSizes[1][y]; + if (cs == Layout::FILL && w == 1) cs = 0; + if (rs == Layout::FILL && h == 1) rs = 0; return cell; } -void Layout::align(int &pos, int &size, int dim, - Cell const &cell, int *sizes) const +void LayoutArray::align(int &pos, int &size, int dim, + LayoutCell const &cell, short *sizes) const { - int size_max = sizes[0] - cell.mPadding * 2; + int size_max = sizes[0]; for (int i = 1; i < cell.mExtent[dim]; ++i) size_max += sizes[i] + mSpacing; - size = std::min(dim == 0 ? cell.mWidget->getWidth() - : cell.mWidget->getHeight(), size_max); - pos += cell.mPadding; + size = std::min<int>(cell.mSize[dim], size_max); switch (cell.mAlign[dim]) { - case Cell::LEFT: + case LayoutCell::LEFT: return; - case Cell::RIGHT: + case LayoutCell::RIGHT: pos += size_max - size; return; - case Cell::CENTER: + case LayoutCell::CENTER: pos += (size_max - size) / 2; return; - case Cell::FILL: + case LayoutCell::FILL: size = size_max; return; } } -std::vector< int > Layout::compute(int dim, int upp) const +std::vector< short > LayoutArray::getSizes(int dim, int upp) const { int gridW = mSizes[0].size(), gridH = mSizes[1].size(); - std::vector< int > sizes = mSizes[dim]; + std::vector< short > sizes = mSizes[dim]; // Compute minimum sizes. for (int gridY = 0; gridY < gridH; ++gridY) { for (int gridX = 0; gridX < gridW; ++gridX) { - Cell const &cell = mCells[gridY][gridX]; - if (!cell.mWidget) continue; + LayoutCell const *cell = mCells[gridY][gridX]; + if (!cell || cell->mType == LayoutCell::NONE) continue; - if (cell.mExtent[dim] == 1) + if (cell->mExtent[dim] == 1) { - int s = dim == 0 ? cell.mWidget->getWidth() - : cell.mWidget->getHeight(); int n = dim == 0 ? gridX : gridY; - s += cell.mPadding * 2; + int s = cell->mSize[dim] + cell->mPadding * 2; if (s > sizes[n]) sizes[n] = s; } } } + if (upp == Layout::FILL) return sizes; + // Compute the FILL sizes. int nb = sizes.size(); int nbFill = 0; for (int i = 0; i < nb; ++i) { - if (mSizes[dim][i] == FILL) ++nbFill; - if (sizes[i] == FILL) sizes[i] = 0; + if (mSizes[dim][i] == Layout::FILL) ++nbFill; + if (sizes[i] == Layout::FILL) sizes[i] = 0; else upp -= sizes[i]; upp -= mSpacing; } - upp = upp + mSpacing - mMargin * 2; + upp = upp + mSpacing; if (nbFill == 0) return sizes; for (int i = 0; i < nb; ++i) { - if (mSizes[dim][i] != FILL) continue; + if (mSizes[dim][i] != Layout::FILL) continue; int s = upp / nbFill; sizes[i] += s; upp -= s; @@ -161,43 +256,61 @@ std::vector< int > Layout::compute(int dim, int upp) const return sizes; } -void Layout::reflow(int &nw, int &nh) +int LayoutArray::getSize(int dim) const +{ + std::vector< short > sizes = getSizes(dim, Layout::FILL); + int size = 0; + int nb = sizes.size(); + for (int i = 0; i < nb; ++i) + { + if (sizes[i] != Layout::FILL) size += sizes[i]; + size += mSpacing; + } + return size - mSpacing; +} + +void LayoutArray::reflow(int nx, int ny, int nw, int nh) { int gridW = mSizes[0].size(), gridH = mSizes[1].size(); - std::vector< int > widths = compute(0, mW); - std::vector< int > heights = compute(1, mH); + std::vector< short > widths = getSizes(0, nw); + std::vector< short > heights = getSizes(1, nh); - int x, y = mY + mMargin; + int y = ny; for (int gridY = 0; gridY < gridH; ++gridY) { - x = mX + mMargin; + int x = nx; for (int gridX = 0; gridX < gridW; ++gridX) { - Cell &cell = mCells[gridY][gridX]; - if (cell.mWidget) + LayoutCell *cell = mCells[gridY][gridX]; + if (cell && cell->mType != LayoutCell::NONE) { int dx = x, dy = y, dw, dh; - align(dx, dw, 0, cell, &widths[gridX]); - align(dy, dh, 1, cell, &heights[gridY]); - cell.mWidget->setDimension(gcn::Rectangle(dx, dy, dw, dh)); + align(dx, dw, 0, *cell, &widths[gridX]); + align(dy, dh, 1, *cell, &heights[gridY]); + cell->reflow(dx, dy, dw, dh); } x += widths[gridX] + mSpacing; } y += heights[gridY] + mSpacing; } +} - nw = x - mX - mSpacing + mMargin; - nh = y - mY - mSpacing + mMargin; +Layout::Layout(): mComputed(false) +{ + getArray(); + setPadding(6); } -void Layout::flush() +void Layout::reflow(int &nw, int &nh) { - int w, h; - reflow(w, h); - mY += h; - mW = w; - mSizes[0].clear(); - mSizes[1].clear(); - mCells.clear(); + if (!mComputed) + { + computeSizes(); + mComputed = true; + } + + nw = nw == 0 ? mSize[0] + 2 * mPadding : nw; + nh = nh == 0 ? mSize[1] + 2 * mPadding : nh; + LayoutCell::reflow(0, 0, nw, nh); } |