summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--src/gui/char_select.cpp58
-rw-r--r--src/gui/widgets/layout.cpp145
-rw-r--r--src/gui/widgets/layout.h56
4 files changed, 163 insertions, 97 deletions
diff --git a/ChangeLog b/ChangeLog
index a6d41da7..7590d646 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,7 @@
* src/gui/login.cpp: Fixed layout of login dialog box when native
language is not English.
* src/gui/playerbox.cpp: Centered sprite inside selection box.
+ * src/gui/char_select.cpp: Reworked layout of dialog box.
2007-10-19 Guillaume Melquiond <guillaume.melquiond@gmail.com>
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index e8381bef..ea04b6bc 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -36,6 +36,8 @@
#include "unregisterdialog.h"
+#include "widgets/layout.h"
+
#include "../game.h"
#include "../localplayer.h"
#include "../main.h"
@@ -100,40 +102,28 @@ CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo,
mMoneyLabel = new gcn::Label(strprintf(_("Money: %d"), 0));
mPlayerBox = new PlayerBox();
- int w = 195;
- int h = 220;
- setContentSize(w, h);
- mPlayerBox->setDimension(gcn::Rectangle(5, 5, w - 10, 90));
- mNameLabel->setDimension(gcn::Rectangle(10, 100, 128, 16));
- mLevelLabel->setDimension(gcn::Rectangle(10, 116, 128, 16));
- mMoneyLabel->setDimension(gcn::Rectangle(10, 148, 128, 16));
- mPreviousButton->setPosition(5, 170);
- mNextButton->setPosition(mPreviousButton->getWidth() + 10, 170);
- mNewCharButton->setPosition(5, h - 5 - mNewCharButton->getHeight());
- mDelCharButton->setPosition(
- 5 + mNewCharButton->getWidth() + 5,
- mNewCharButton->getY());
- mCancelButton->setPosition(
- w - 5 - mCancelButton->getWidth(),
- mNewCharButton->getY());
- mSelectButton->setPosition(
- mCancelButton->getX() - 5 - mSelectButton->getWidth(),
- mNewCharButton->getY());
- mUnRegisterButton->setPosition(
- w - 5 - mUnRegisterButton->getWidth(),
- mCancelButton->getY() - 5 - mUnRegisterButton->getHeight());
-
- add(mPlayerBox);
- add(mSelectButton);
- add(mCancelButton);
- add(mUnRegisterButton);
- add(mNewCharButton);
- add(mDelCharButton);
- add(mPreviousButton);
- add(mNextButton);
- add(mNameLabel);
- add(mLevelLabel);
- add(mMoneyLabel);
+ setPadding(8);
+ Layout &layout = getLayout();
+ place(0, 0, mPlayerBox, 1, 5).setPadding(3);
+ place(1, 0, mNameLabel, 3);
+ place(1, 1, mLevelLabel, 3);
+ place(1, 2, mMoneyLabel, 3);
+ place(1, 3, mPreviousButton);
+ place(2, 3, mNextButton);
+ place(1, 4, mNewCharButton);
+ place(2, 4, mDelCharButton);
+ layout.setWidth(230);
+ layout.setColWidth(0, 80);
+ layout.setColWidth(3, Layout::FILL);
+ layout.matchColWidth(1, 2);
+ layout.setRowHeight(5, 5);
+ layout.flush();
+ place(0, 0, mUnRegisterButton);
+ place(2, 0, mSelectButton);
+ place(3, 0, mCancelButton);
+ layout.setColWidth(1, Layout::FILL);
+ reflowLayout();
+ forgetLayout();
setLocationRelativeTo(getParent());
setVisible(true);
diff --git a/src/gui/widgets/layout.cpp b/src/gui/widgets/layout.cpp
index 8a64acc0..2133b077 100644
--- a/src/gui/widgets/layout.cpp
+++ b/src/gui/widgets/layout.cpp
@@ -25,18 +25,22 @@
void Layout::resizeGrid(int w, int h)
{
- bool extW = w && w > (int)mColWidths.size(),
- extH = h && h > (int)mRowHeights.size();
+ bool extW = w && w > (int)mSizes[0].size(),
+ extH = h && h > (int)mSizes[1].size();
if (!extW && !extH) return;
if (extH)
{
- mRowHeights.resize(h, -1);
+ mSizes[1].resize(h, 0);
mCells.resize(h);
- if (!extW) w = (int)mColWidths.size();
+ if (!extW) w = mSizes[0].size();
+ }
+
+ if (extW)
+ {
+ mSizes[0].resize(w, 0);
}
- mColWidths.resize(w, -1);
for (std::vector< std::vector< Cell > >::iterator
i = mCells.begin(), i_end = mCells.end(); i != i_end; ++i)
{
@@ -47,13 +51,22 @@ void Layout::resizeGrid(int w, int h)
void Layout::setColWidth(int n, int w)
{
resizeGrid(n + 1, 0);
- mColWidths[n] = w;
+ mSizes[0][n] = w;
}
void Layout::setRowHeight(int n, int h)
{
resizeGrid(0, n + 1);
- mRowHeights[n] = h;
+ mSizes[1][n] = h;
+}
+
+void Layout::matchColWidth(int n1, int n2)
+{
+ resizeGrid(std::max(n1, n2) + 1, 0);
+ std::vector< int > widths = compute(0, mW);
+ 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)
@@ -61,40 +74,45 @@ Cell &Layout::place(gcn::Widget *widget, int x, int y, int w, int h)
resizeGrid(x + w, y + h);
Cell &cell = mCells[y][x];
cell.mWidget = widget;
- cell.mColExtent = w;
- cell.mRowExtent = h;
+ cell.mExtent[0] = w;
+ cell.mExtent[1] = h;
cell.mPadding = 0;
- cell.mHAlign = Cell::FILL;
- cell.mVAlign = Cell::FILL;
+ cell.mAlign[0] = Cell::FILL;
+ cell.mAlign[1] = Cell::FILL;
return cell;
}
-static void align(int &pos, int &cur, int upp, Cell::Alignment a)
+void Layout::align(int &pos, int &size, int dim, Cell &cell, int *sizes)
{
- cur = std::min(cur, upp);
- switch (a)
+ int size_max = sizes[0] - cell.mPadding * 2;
+ for (int i = 1; i < cell.mExtent[dim]; ++i)
+ size_max += sizes[i] + mPadding;
+ size = std::min(dim == 0 ? cell.mWidget->getWidth()
+ : cell.mWidget->getHeight(), size_max);
+ pos += cell.mPadding;
+
+ switch (cell.mAlign[dim])
{
case Cell::LEFT:
return;
case Cell::RIGHT:
- pos += upp - cur;
+ pos += size_max - size;
return;
case Cell::CENTER:
- pos += (upp - cur) / 2;
+ pos += (size_max - size) / 2;
return;
case Cell::FILL:
- cur = upp;
+ size = size_max;
return;
}
}
-void Layout::reflow()
+std::vector< int > Layout::compute(int dim, int upp)
{
- int gridW = mColWidths.size(), gridH = mRowHeights.size();
-
- std::vector< int > widths(gridW, 0);
- std::vector< int > heights(gridH, 0);
+ int gridW = mSizes[0].size(), gridH = 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)
@@ -102,58 +120,77 @@ void Layout::reflow()
Cell &cell = mCells[gridY][gridX];
if (!cell.mWidget) continue;
- if (cell.mColExtent == 1)
- {
- int w = cell.mWidget->getWidth() + cell.mPadding * 2;
- if (w > widths[gridX]) widths[gridX] = w;
- }
-
- if (cell.mRowExtent == 1)
+ if (cell.mExtent[dim] == 1)
{
- int h = cell.mWidget->getHeight() + cell.mPadding * 2;
- if (h > heights[gridY]) heights[gridY] = h;
+ int s = dim == 0 ? cell.mWidget->getWidth()
+ : cell.mWidget->getHeight();
+ int n = dim == 0 ? gridX : gridY;
+ s += cell.mPadding * 2;
+ if (s > sizes[n]) sizes[n] = s;
}
}
}
- for (int gridX = 0; gridX < gridW; ++gridX)
+ // Compute the FILL sizes.
+ int nb = sizes.size();
+ int nbFill = 0;
+ for (int i = 0; i < nb; ++i)
{
- int w = mColWidths[gridX];
- if (w != -1) widths[gridX] = w;
+ if (mSizes[dim][i] == FILL) ++nbFill;
+ if (sizes[i] > 0) upp -= sizes[i];
+ upp -= mPadding;
}
+ upp += mPadding;
- for (int gridY = 0; gridY < gridH; ++gridY)
+ if (upp <= 0 || nbFill == 0) return sizes;
+
+ for (int i = 0; i < nb; ++i)
{
- int h = mRowHeights[gridY];
- if (h != -1) heights[gridY] = h;
+ if (mSizes[dim][i] != FILL) continue;
+ int s = (upp + nbFill / 2) / nbFill;
+ sizes[i] += s;
+ upp -= s;
+ --nbFill;
}
- int y = 0;
+ return sizes;
+}
+
+void Layout::reflow()
+{
+ int gridW = mSizes[0].size(), gridH = mSizes[1].size();
+
+ std::vector< int > widths = compute(0, mW);
+ std::vector< int > heights = compute(1, mH);
+
+ int y = mY;
for (int gridY = 0; gridY < gridH; ++gridY)
{
- int h = heights[gridY];
- int x = 0;
+ int x = mX;
for (int gridX = 0; gridX < gridW; ++gridX)
{
- int w = widths[gridX];
Cell &cell = mCells[gridY][gridX];
if (cell.mWidget)
{
- int ew = w - cell.mPadding * 2,
- eh = h - cell.mPadding * 2;
- for (int i = 1; i < cell.mColExtent; ++i)
- ew += widths[gridX + i] + mPadding;
- for (int i = 1; i < cell.mRowExtent; ++i)
- eh += heights[gridY + i] + mPadding;
- int dw = cell.mWidget->getWidth(),
- dh = cell.mWidget->getHeight();
- int dx = x + cell.mPadding, dy = y + cell.mPadding;
- align(dx, dw, ew, cell.mHAlign);
- align(dy, dh, eh, cell.mVAlign);
+ 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));
}
- x += w + mPadding;
+ x += widths[gridX] + mPadding;
+ mNW = x - mX;
}
- y += h + mPadding;
+ y += heights[gridY] + mPadding;
+ mNH = y - mY;
}
}
+
+void Layout::flush()
+{
+ reflow();
+ mY += mNH;
+ mW = mNW - mPadding;
+ mSizes[0].clear();
+ mSizes[1].clear();
+ mCells.clear();
+}
diff --git a/src/gui/widgets/layout.h b/src/gui/widgets/layout.h
index 5be8e84c..09b511f6 100644
--- a/src/gui/widgets/layout.h
+++ b/src/gui/widgets/layout.h
@@ -58,20 +58,20 @@ class Cell
* Sets the horizontal alignment of the cell content.
*/
Cell &setHAlign(Alignment a)
- { mHAlign = a; return *this; }
+ { mAlign[0] = a; return *this; }
/**
* Sets the vertical alignment of the cell content.
*/
Cell &setVAlign(Alignment a)
- { mVAlign = a; return *this; }
+ { mAlign[1] = a; return *this; }
private:
gcn::Widget *mWidget;
- int mColExtent, mRowExtent;
int mPadding;
- Alignment mHAlign, mVAlign;
+ int mExtent[2];
+ Alignment mAlign[2];
};
/**
@@ -85,19 +85,36 @@ class Layout
{
public:
- Layout(): mPadding(4) {}
+ Layout(): mPadding(4), mX(0), mY(0), mW(0), mH(0) {}
/**
- * Sets the width of a column.
+ * Sets the minimum width of a column.
*/
void setColWidth(int n, int w);
/**
- * Sets the height of a row.
+ * Sets the minimum height of a row.
*/
void setRowHeight(int n, int h);
/**
+ * Matchs widths of two columns.
+ */
+ void matchColWidth(int n1, int n2);
+
+ /**
+ * Sets the minimum width of the layout.
+ */
+ void setWidth(int w)
+ { mW = w; }
+
+ /**
+ * Sets the minimum height of the layout.
+ */
+ void setHeight(int h)
+ { mH = h; }
+
+ /**
* Sets the padding between cells.
*/
void setPadding(int p)
@@ -113,18 +130,39 @@ class Layout
*/
void reflow();
+ /**
+ * Reflows the current layout. Then starts a new layout just below with
+ * the same width.
+ */
+ void flush();
+
+ enum
+ {
+ FILL = -1, /**< Expand until the layout as the expected size. */
+ };
+
private:
/**
+ * Gets the position and size of a widget along a given axis
+ */
+ void align(int &pos, int &size, int dim, Cell &cell, int *sizes);
+
+ /**
* Ensures the private vectors are large enough.
*/
void resizeGrid(int w, int h);
- std::vector< int > mColWidths;
- std::vector< int > mRowHeights;
+ /**
+ * Gets the column/row sizes along a given axis.
+ */
+ std::vector< int > compute(int dim, int upp);
+
+ std::vector< int > mSizes[2];
std::vector< std::vector < Cell > > mCells;
int mPadding;
+ int mX, mY, mW, mH, mNW, mNH;
};
#endif