summaryrefslogtreecommitdiff
path: root/src/gui/widgets/layout.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/widgets/layout.h')
-rw-r--r--src/gui/widgets/layout.h276
1 files changed, 192 insertions, 84 deletions
diff --git a/src/gui/widgets/layout.h b/src/gui/widgets/layout.h
index ae03ed9d..a6e630c2 100644
--- a/src/gui/widgets/layout.h
+++ b/src/gui/widgets/layout.h
@@ -26,172 +26,280 @@
#include <vector>
-#include <guichan/widget.hpp>
+#include <guichan/widgets/container.hpp>
+
+class LayoutCell;
/**
- * This class describes the formatting of a widget in the cell of a layout
- * table. Horizontally, a widget can either fill the width of the cell (minus
- * the cell padding), or it can retain its size and be flushed left, or flush
- * right, or centered in the cell. The process is similar for the vertical
- * alignment, except that top is represented by LEFT and bottom by RIGHT.
+ * This class is a helper for adding widgets to nested tables in a window.
*/
-class Cell
+class ContainerPlacer
{
- friend class Layout;
-
public:
- enum Alignment
- {
- LEFT, RIGHT, CENTER, FILL
- };
-
- Cell(): mWidget(0) {}
+ ContainerPlacer(gcn::Container *c = NULL, LayoutCell *l = NULL):
+ mContainer(c), mCell(l)
+ {}
/**
- * Sets the padding around the cell content.
+ * Gets the pointed cell.
*/
- Cell &setPadding(int p)
- { mPadding = p; return *this; }
+ LayoutCell &getCell()
+ { return *mCell; }
/**
- * Sets the horizontal alignment of the cell content.
+ * Returns a placer for the same container but to an inner cell.
*/
- Cell &setHAlign(Alignment a)
- { mAlign[0] = a; return *this; }
+ ContainerPlacer at(int x, int y);
/**
- * Sets the vertical alignment of the cell content.
+ * Adds the given widget to the container and places it in the layout.
+ * @see LayoutArray::place
*/
- Cell &setVAlign(Alignment a)
- { mAlign[1] = a; return *this; }
+ LayoutCell &operator()
+ (int x, int y, gcn::Widget *, int w = 1, int h = 1);
private:
- gcn::Widget *mWidget;
- int mPadding;
- int mExtent[2];
- Alignment mAlign[2];
+ gcn::Container *mContainer;
+ LayoutCell *mCell;
};
/**
- * This class is an helper for setting the position of widgets. They are
- * positioned along the cells of a rectangular table.
- *
- * The size of a given table column can either be set manually or be chosen
- * from the widest widget of the column. An empty column has a FILL width,
- * which means it will be extended so that the layout fits its minimum width.
- *
- * The process is similar for table rows. By default, there is a spacing of 4
- * pixels between rows and between columns, and a margin of 6 pixels around the
- * whole layout.
+ * This class contains a rectangular array of cells.
*/
-class Layout
+class LayoutArray
{
+ friend class LayoutCell;
+
public:
- Layout(): mSpacing(4), mMargin(6), mX(0), mY(0), mW(0), mH(0) {}
+ LayoutArray();
+
+ ~LayoutArray();
/**
- * Gets the x-coordinate of the top left point of the layout.
+ * Returns a reference on the cell at given position.
*/
- int getX() const
- { return mX; }
+ LayoutCell &at(int x, int y, int w = 1, int h = 1);
/**
- * Gets the y-coordinate of the top left point of the layout.
+ * 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 FILL.
*/
- int getY() const
- { return mY; }
+ LayoutCell &place(gcn::Widget *, int x, int y, int w = 1, int h = 1);
/**
* Sets the minimum width of a column.
- * @note Setting the width to FILL and then placing a widget in the
- * column will reset the width to zero.
*/
void setColWidth(int n, int w);
/**
* Sets the minimum height of a row.
- * @note Setting the height to FILL and then placing a widget in the
- * row will reset the height to zero.
*/
void setRowHeight(int n, int h);
/**
- * Matchs widths of two columns.
+ * Sets the widths of two columns to the maximum of their widths.
*/
void matchColWidth(int n1, int n2);
/**
- * Sets the minimum width of the layout.
+ * Computes and sets the positions of all the widgets.
+ * @param nW width of the array, used to resize the FILL columns.
+ * @param nH height of the array, used to resize the FILL rows.
*/
- void setWidth(int w)
- { mW = w; }
+ void reflow(int nX, int nY, int nW, int nH);
+
+ private:
+
+ // Copy not allowed, as the array owns all its cells.
+ LayoutArray(LayoutArray const &);
+ LayoutArray &operator=(LayoutArray const &);
/**
- * Sets the minimum height of the layout.
+ * Gets the position and size of a widget along a given axis
*/
- void setHeight(int h)
- { mH = h; }
+ void align(int &pos, int &size, int dim,
+ LayoutCell const &cell, short *sizes) const;
/**
- * Sets the spacing between cells.
+ * Ensures the private vectors are large enough.
*/
- void setSpacing(int p)
- { mSpacing = p; }
+ void resizeGrid(int w, int h);
/**
- * Sets the margin around the layout.
+ * Gets the column/row sizes along a given axis.
+ * @param upp target size for the array. Ignored if FILL.
*/
- void setMargin(int m)
- { mMargin = m; }
+ std::vector< short > getSizes(int dim, int upp) const;
/**
- * Places a widget in a given cell.
+ * Gets the total size along a given axis.
*/
- Cell &place(gcn::Widget *, int x, int y, int w, int h);
+ int getSize(int dim) const;
+
+ std::vector< short > mSizes[2];
+ std::vector< std::vector < LayoutCell * > > mCells;
+
+ char mSpacing;
+};
+
+/**
+ * This class describes the formatting of a widget in the cell of a layout
+ * table. Horizontally, a widget can either fill the width of the cell (minus
+ * the cell padding), or it can retain its size and be flushed left, or flush
+ * right, or centered in the cell. The process is similar for the vertical
+ * alignment, except that top is represented by LEFT and bottom by RIGHT.
+ */
+class LayoutCell
+{
+ friend class Layout;
+ friend class LayoutArray;
+
+ public:
+
+ enum Alignment
+ {
+ LEFT, RIGHT, CENTER, FILL
+ };
+
+ LayoutCell(): mType(NONE) {}
+
+ ~LayoutCell();
/**
- * Computes the positions of all the widgets. Returns the size of the
- * layout.
+ * Sets the padding around the cell content.
*/
- void reflow(int &nW, int &nH);
+ LayoutCell &setPadding(int p)
+ { mPadding = p; return *this; }
+
+ /**
+ * Sets the horizontal alignment of the cell content.
+ */
+ LayoutCell &setHAlign(Alignment a)
+ { mAlign[0] = a; return *this; }
+
+ /**
+ * Sets the vertical alignment of the cell content.
+ */
+ LayoutCell &setVAlign(Alignment a)
+ { mAlign[1] = a; return *this; }
+
+ /**
+ * @see LayoutArray::at
+ */
+ LayoutCell &at(int x, int y)
+ { return getArray().at(x, y); }
+
+ /**
+ * @see LayoutArray::place
+ */
+ LayoutCell &place(gcn::Widget *wg, int x, int y, int w = 1, int h = 1)
+ { return getArray().place(wg, x, y, w, h); }
/**
- * Reflows the current layout. Then starts a new layout just below with
- * the same width.
+ * @see LayoutArray::matchColWidth
*/
- void flush();
+ void matchColWidth(int n1, int n2)
+ { getArray().matchColWidth(n1, n2); }
+
+ /**
+ * @see LayoutArray::setColWidth
+ */
+ void setColWidth(int n, int w)
+ { getArray().setColWidth(n, w); }
+
+ /**
+ * @see LayoutArray::setRowHeight
+ */
+ void setRowHeight(int n, int h)
+ { getArray().setRowHeight(n, h); }
+
+ /**
+ * Sets the minimum widths and heights of this cell and of all the
+ * inner cells.
+ */
+ void computeSizes();
+
+ private:
+
+ // Copy not allowed, as the cell may own an array.
+ LayoutCell(LayoutCell const &);
+ LayoutCell &operator=(LayoutCell const &);
+
+ union
+ {
+ gcn::Widget *mWidget;
+ LayoutArray *mArray;
+ };
enum
{
- FILL = -42, /**< Expand until the layout as the expected size. */
+ NONE, WIDGET, ARRAY
};
- private:
+ /**
+ * Returns the embedded array. Creates it if the cell does not contain
+ * anything yet. Aborts if it contains a widget.
+ */
+ LayoutArray &getArray();
/**
- * Gets the position and size of a widget along a given axis
+ * @see LayoutArray::reflow
*/
- void align(int &pos, int &size, int dim,
- Cell const &cell, int *sizes) const;
+ void reflow(int nx, int ny, int nw, int nh);
+
+ short mSize[2];
+ char mPadding;
+ char mExtent[2];
+ char mAlign[2];
+ char mNbFill[2];
+ char mType;
+};
+
+/**
+ * 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.
+ *
+ * The size of a given table column can either be set manually or be chosen
+ * from the widest widget of the column. An empty column has a FILL width,
+ * which means it will be extended so that the layout fits its minimum width.
+ *
+ * The process is similar for table rows. By default, there is a spacing of 4
+ * pixels between rows and between columns, and a margin of 6 pixels around the
+ * whole layout.
+ */
+class Layout: public LayoutCell
+{
+ public:
+
+ Layout();
/**
- * Ensures the private vectors are large enough.
+ * Sets the margin around the layout.
*/
- void resizeGrid(int w, int h);
+ void setMargin(int m)
+ { setPadding(m); }
/**
- * Gets the column/row sizes along a given axis.
+ * Sets the positions of all the widgets.
+ * @see LayoutArray::reflow
*/
- std::vector< int > compute(int dim, int upp) const;
+ void reflow(int &nW, int &nH);
+
+ enum
+ {
+ FILL = -42, /**< Expand until the layout as the expected size. */
+ };
- std::vector< int > mSizes[2];
- std::vector< std::vector < Cell > > mCells;
+ private:
- int mSpacing, mMargin;
- int mX, mY, mW, mH, mNW, mNH;
+ bool mComputed;
};
#endif