diff options
Diffstat (limited to 'src/gui/widgets/layout.h')
-rw-r--r-- | src/gui/widgets/layout.h | 276 |
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 |