Sizer
 All Classes Files Functions Variables Enumerations Enumerator Pages
Sizer.h
Go to the documentation of this file.
1 #ifndef SIZER_H
2 #define SIZER_H
3 
30 #include <vector>
31 
35 struct SizerPoint
36 {
38  SizerPoint(int px = 0, int py = 0) : x(px), y(py) {}
39 
43  void Set(int px, int py) { x = px; y = py; }
44 
45  int x;
46  int y;
47 };
48 
52 struct SizerSize
53 {
55  SizerSize(int width = 0, int height = 0) : w(width), h(height) {}
56 
60  void Set(int width, int height) { w = width; h = height; }
61 
62  int w;
63  int h;
64 };
65 
69 struct SizerRect
70 {
72  SizerRect(int x = 0, int y = 0, int width = 0, int height = 0) : p(x, y), s(width, height) {}
74  SizerRect(const SizerPoint& topLeft, const SizerSize& size) : p(topLeft), s(size) {}
75 
79  void Set(int x, int y, int w, int h) { p.Set(x, y); s.Set(w, h); }
80 
83 };
84 
92 class ISizer
93 {
94 public:
95  ISizer()
96  {
97  dirty = true;
98  }
99 
100  virtual ~ISizer() {}
101 
106  virtual void OnCalcSizes() = 0;
112  virtual void OnRectChanged(int x, int y, int w, int h) = 0;
116  virtual size_t GetItemCount() { return 0; }
120  virtual ISizer* GetItem(size_t i) { return NULL; }
121 
126  void CalcSizes();
136  void Move(int x, int y, int w, int h);
140  void Move(const SizerPoint& p, const SizerSize& s) { return Move(p.x, p.y, s.w, s.h); }
144  void Move(const SizerRect& r) { return Move(r.p.x, r.p.y, r.s.w, r.s.h); }
149  SizerRect GetRect() const;
150 
154  void WmSize(UINT type, int cx, int cy)
155  {
156  Move(0, 0, cx, cy);
157  }
158 
162  void WmGetMinMaxInfo(HWND window, MINMAXINFO* mmi)
163  {
164  RECT r;
165  SetRect(&r, 0, 0, GetMinSize().w, GetMinSize().h);
166  DWORD style = GetWindowLong(window, GWL_STYLE);
167  AdjustWindowRectEx(&r,
168  style,
169  (style & WS_CHILD) == 0 && GetMenu(window) != NULL, // with menu?
170  GetWindowLong(window, GWL_EXSTYLE));
171 
172  mmi->ptMinTrackSize.x = r.right - r.left;
173  mmi->ptMinTrackSize.y = r.bottom - r.top;
174  }
175 protected:
181  bool dirty;
192 private:
193  // disable copy constructor for all subclasses
194  ISizer(const ISizer& other) {}
195  // disable assignment operator for all subclasses
196  ISizer& operator= (const ISizer& other) { return *this; }
197 };
198 
205 class EmptySizer : public ISizer
206 {
207 public:
212  EmptySizer(int minW = 0, int minH = 0)
213  {
214  minimumSize.w = minW;
215  minimumSize.h = minH;
216  }
217 
218  virtual void OnCalcSizes() {}
219  virtual void OnRectChanged(int x, int y, int w, int h) {}
220 };
221 
229 class WindowSizer : public ISizer
230 {
231 public:
235  WindowSizer(HWND pWindow);
236 
237  virtual void OnCalcSizes() {}
238  virtual void OnRectChanged(int x, int y, int w, int h) { MoveWindow(window, x, y, w, h, TRUE); }
239 private:
240  HWND window;
241 };
242 
249 class GroupboxSizer : public ISizer
250 {
251 public:
256  GroupboxSizer(HWND pGroupbox, ISizer* pItem);
257  ~GroupboxSizer();
258 
262  void SetOuterPadding(int pad);
263 
264  virtual void OnCalcSizes();
265  virtual void OnRectChanged(int x, int y, int w, int h);
266  virtual size_t GetItemCount() { return 1; }
267  virtual ISizer* GetItem(size_t i) { return item; }
268 private:
269  int GetHPadding() { return leftPadding+rightPadding; }
270  int GetVPadding() { return topPadding+bottomPadding; }
271 
272  HWND groupbox;
273  ISizer* item;
274  int leftPadding;
275  int rightPadding;
276  int topPadding;
277  int bottomPadding;
278  int outerPadding;
279 };
280 
286 class OverlapSizer : public ISizer
287 {
288 public:
289  OverlapSizer();
290  ~OverlapSizer();
291 
292  virtual void OnCalcSizes();
293  virtual void OnRectChanged(int x, int y, int w, int h);
294  virtual size_t GetItemCount() { return items.size(); }
295  virtual ISizer* GetItem(size_t i) { return items[i]; }
296 
300  void SetOuterPadding(int pad);
304  void Add(ISizer* item);
308  void Add(HWND window) { return Add(new WindowSizer(window)); }
312  void RemoveAll();
313 private:
314  std::vector<ISizer*> items;
315  int outerPadding;
316 };
317 
321 class BoxSizer : public ISizer
322 {
323 public:
327  BoxSizer(bool pHorizontal);
328  ~BoxSizer();
329 
330  virtual void OnCalcSizes();
331  virtual void OnRectChanged(int x, int y, int w, int h);
332  virtual size_t GetItemCount() { return items.size(); }
333  virtual ISizer* GetItem(size_t i) { return items[i].sizer; }
334 
339  BoxSizer* SetPadding(int pad);
344  BoxSizer* SetOuterPadding(int pad);
349  BoxSizer* Add(ISizer* sizer, int proportion = 0);
353  BoxSizer* Add(HWND window, int proportion = 0) { return Add(new WindowSizer(window), proportion); }
357  BoxSizer* AddStretchSpace(int proportion) { return Add((ISizer*)NULL, proportion); }
361  void RemoveAll();
366  BoxSizer* StretchItemInMinorDirection(bool stretch);
367 private:
368  int GetTotalPadding() { return items.empty() ? 0 : ((int)items.size()-1)*padding; }
369 
370  // a BoxSizer works 1-dimensional, so there is a major and a minor coordinate
371  // major minor
372  // horizontal x y
373  // vertical y x
374  int GetMajorCoord(const SizerPoint& p) const { return horizontal ? p.x : p.y; }
375  int GetMinorCoord(const SizerPoint& p) const { return horizontal ? p.y : p.x; }
376  int& MajorCoord(SizerPoint& p) const { return horizontal ? p.x : p.y; }
377  int& MinorCoord(SizerPoint& p) const { return horizontal ? p.y : p.x; }
378  SizerPoint PosFromMajorMinor(int major, int minor) const { return horizontal ? SizerPoint(major, minor) : SizerPoint(minor, major); }
379  int GetMajorCoord(const SizerSize& s) const { return horizontal ? s.w : s.h; }
380  int GetMinorCoord(const SizerSize& s) const { return horizontal ? s.h : s.w; }
381  int& MajorCoord(SizerSize& s) const { return horizontal ? s.w : s.h; }
382  int& MinorCoord(SizerSize& s) const { return horizontal ? s.h : s.w; }
383  SizerSize SizeFromMajorMinor(int major, int minor) const { return horizontal ? SizerSize(major, minor) : SizerSize(minor, major); }
384 
385  struct Item
386  {
387  Item(ISizer* s, int prop)
388  {
389  sizer = s;
390  proportion = prop;
391  }
392 
393  ISizer* sizer;
394  int proportion;
395  };
396 
397  std::vector<Item> items;
398  int padding;
399  bool horizontal;
400  int outerPadding;
401  bool stretchInMinorDir;
402 
403  // this data is generated from CalcSizes()
404  std::vector<SizerSize> calcedSizes;
405 };
406 
410 class HBoxSizer : public BoxSizer
411 {
412 public:
413  HBoxSizer() : BoxSizer(true) {}
414 
428  static HBoxSizer* New() { return new HBoxSizer(); }
429 };
430 
434 class VBoxSizer : public BoxSizer
435 {
436 public:
437  VBoxSizer() : BoxSizer(false) {}
438 
444  static VBoxSizer* New() { return new VBoxSizer(); }
445 };
446 
451 {
455 };
456 
460 class HAlignSizer : public ISizer
461 {
462 public:
466  HAlignSizer();
470  HAlignSizer(ISizer* pItem, SIZER_HALIGN pAlign);
474  HAlignSizer(HWND window, SIZER_HALIGN pAlign);
475  ~HAlignSizer();
476 
477  virtual void OnCalcSizes() { minimumSize = item->GetMinSize(); }
478  virtual void OnRectChanged(int x, int y, int w, int h);
479  virtual size_t GetItemCount() { return 1; }
480  virtual ISizer* GetItem(size_t i) { return item; }
481 
485  void SetItem(ISizer* pItem, SIZER_HALIGN pAlign) { Init(pItem, pAlign); }
489  void SetItem(HWND window, SIZER_HALIGN pAlign) { Init(new WindowSizer(window), pAlign); }
490 
494  void RemoveAll() { Init(NULL, SIZER_LEFT); }
495 private:
496  void Init(ISizer* pItem, SIZER_HALIGN pAlign);
497 
498  ISizer* item;
499  SIZER_HALIGN align;
500 };
501 
506 {
510 };
511 
515 class VAlignSizer : public ISizer
516 {
517 public:
521  VAlignSizer();
525  VAlignSizer(ISizer* pItem, SIZER_VALIGN pAlign);
529  VAlignSizer(HWND window, SIZER_VALIGN pAlign);
530  ~VAlignSizer();
531 
532  virtual void OnCalcSizes() { minimumSize = item->GetMinSize(); }
533  virtual void OnRectChanged(int x, int y, int w, int h);
534  virtual size_t GetItemCount() { return 1; }
535  virtual ISizer* GetItem(size_t i) { return item; }
536 
540  void SetItem(ISizer* pItem, SIZER_VALIGN pAlign) { Init(pItem, pAlign); }
544  void SetItem(HWND window, SIZER_VALIGN pAlign) { Init(new WindowSizer(window), pAlign); }
545 
549  void RemoveAll() { Init(NULL, SIZER_TOP); }
550 private:
551  void Init(ISizer* pItem, SIZER_VALIGN pAlign);
552 
553  ISizer* item;
554  SIZER_VALIGN align;
555 };
556 
560 class GridSizer : public ISizer
561 {
562 public:
563  GridSizer();
564  ~GridSizer();
565 
566  virtual void OnCalcSizes();
567  virtual void OnRectChanged(int x, int y, int w, int h);
568  virtual size_t GetItemCount() { return items.size(); }
569  virtual ISizer* GetItem(size_t i) { return items[i]->sizer; }
570 
574  void SetPadding(int padX, int padY);
578  void SetOuterPadding(int pad);
586  void Add(ISizer* sizer, size_t row, size_t column, size_t spannedRows = 1, size_t spannedColumns = 1);
591  void Add(HWND window, size_t row, size_t column, size_t spannedRows = 1, size_t spannedColumns = 1) { return Add(new WindowSizer(window), row, column, spannedRows, spannedColumns); }
596  void Remove(size_t row, size_t column);
600  void RemoveAll();
604  void SetColumnProportion(size_t column, int proportion);
609  void SetColumnItemsSameWidth(size_t column, bool set);
613  void SetRowProportion(size_t row, int proportion);
618  void SetRowItemsSameHeight(size_t row, bool set);
622  size_t GetNumRows() { return grid.totalRows; }
626  size_t GetNumColumns() { return grid.totalColumns; }
627 private:
628  void EnsureCellExists(size_t row, size_t column);
629  int GetTotalPaddingX() { return grid.totalColumns == 0 ? 0 : ((int)grid.totalColumns-1)*paddingX; }
630  int GetTotalPaddingY() { return grid.totalRows == 0 ? 0 : ((int)grid.totalRows-1)*paddingY; }
631 
632  // specialization of a vector to support 2 dimensions
633  template<typename T>
634  class Grid : public std::vector<T>
635  {
636  public:
637  Grid();
638  void SetSize(size_t rows, size_t columns, T defaultValue);
639  T& Get(size_t row, size_t column);
640  void Set(size_t row, size_t column, const T& value);
641 
642  size_t totalRows;
643  size_t totalColumns;
644  };
645 
646  // holds a sizer and extra information for it, like spanned rows and columns
647  class Item
648  {
649  public:
650  Item(ISizer* pSizer, size_t row, size_t column, size_t spannedRows, size_t spannedColumns)
651  {
652  sizer = pSizer;
653 
654  startRow = row;
655  startColumn = column;
656  // span must not be less than 1
657  spanRows = spannedRows < 1 ? 1 : spannedRows;
658  spanColumns = spannedRows < 1 ? 1 : spannedColumns;
659  }
660 
661  ~Item() { delete sizer; }
662 
663  bool IsColumnSpan() { return spanColumns > 1; }
664  bool IsRowSpan() { return spanRows > 1; }
665  bool IsSpan() { return IsColumnSpan() || IsRowSpan(); }
666 
667  ISizer* sizer;
668  size_t startRow;
669  size_t startColumn;
670  size_t spanRows;
671  size_t spanColumns;
672  };
673 
674  // holds information about a row or column.
675  class RowOrColumn
676  {
677  public:
678  RowOrColumn() : proportion(0), allItemsSameSize(false) {}
679 
680  int proportion;
681  bool allItemsSameSize;
682  };
683 
684  std::vector<RowOrColumn> rows;
685  std::vector<RowOrColumn> columns;
686 
687  // unique list of sizer items
688  std::vector<Item*> items;
689  // grid of sizer items, if a sizer shows up in multiple grid cells, than it is spanned.
690  Grid<Item*> grid;
691  int paddingX;
692  int paddingY;
693  int outerPadding;
694 
695  // this data is generated from CalcSizes()
696  std::vector<int> rowHeights;
697  std::vector<int> columnWidths;
698  Grid<SizerSize> calcedCellSizes;
699 };
700 
704 class FlowSizer : public ISizer
705 {
706 public:
707  FlowSizer();
708  ~FlowSizer();
709 
713  void SetPadding(int pad);
717  void SetOuterPadding(int pad);
721  void Add(ISizer* item);
725  void Add(HWND window) { return Add(new WindowSizer(window)); }
729  void RemoveAll();
730 
731  virtual void OnCalcSizes();
732  virtual void OnRectChanged(int x, int y, int w, int h);
733  virtual size_t GetItemCount() { return items.size(); }
734  virtual ISizer* GetItem(size_t i) { return items[i]; }
735 private:
736  std::vector<ISizer*> items;
737  int padding;
738  int outerPadding;
739 };
740 
741 #endif