1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        multicell.cpp
3 // Purpose:     provide two new classes for layout, wxMultiCellSizer and wxMultiCellCanvas
4 // Author:      Jonathan Bayer
5 // Modified by:
6 // Created:
7 // RCS-ID:      $Id: multicell.cpp 42046 2006-10-16 09:30:01Z ABX $
8 // Copyright:   (c) Jonathan Bayer
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // This was inspired by the gbsizer class written by Alex Andruschak
13 
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16 
17 #ifdef __BORLANDC__
18     #pragma hdrstop
19 #endif
20 
21 // ----------------------------------------------------------------------------
22 // headers
23 // ----------------------------------------------------------------------------
24 
25 #ifndef WX_PRECOMP
26     #include "wx/wx.h"
27 #endif
28 
29 #include "wx/gizmos/multicell.h"
30 
31 
32 
33 
34 //---------------------------------------------------------------------------
35 
36 IMPLEMENT_ABSTRACT_CLASS(wxMultiCellSizer, wxSizer);
37 IMPLEMENT_ABSTRACT_CLASS(wxMultiCellItemHandle, wxObject);
38 
39 //---------------------------------------------------------------------------
40 // wxMultiCellItemHandle
41 //---------------------------------------------------------------------------
42 /*
43  *Function Name: wxMultiCellItemHandle :: wxMultiCellItemHandle
44  *
45  *Parameters:    int         row
46  *               int         column
47  *               int         height
48  *               int         width
49  *               wxSize      size
50  *               wxResizable Style
51  *               wxSize      weight
52  *               int         align
53  *
54  *Description:   This is the constructor for the class.
55  *
56  */
57 
Initialize(int row,int column,int height,int width,wxSize size,wxResizable Style,wxSize weight,int align)58 void wxMultiCellItemHandle :: Initialize( int row, int column, int height, int width, wxSize size, wxResizable Style, wxSize weight, int align)
59 {
60     m_column = column;
61     m_row = row;
62     m_width = width;
63     m_height = height;
64 
65     m_style = Style;
66     m_fixedSize = size;
67     m_alignment = align;
68     m_weight = weight;
69 }
70 //---------------------------------------------------------------------------
wxMultiCellItemHandle(int row,int column,int height,int width,wxSize size,wxResizable Style,wxSize weight,int align)71 wxMultiCellItemHandle :: wxMultiCellItemHandle( int row, int column, int height, int width, wxSize size, wxResizable Style, wxSize weight, int align)
72 {
73     Initialize(row, column,height, width, size, Style, weight, align);
74 }
75 //---------------------------------------------------------------------------
wxMultiCellItemHandle(int row,int column,wxSize size,wxResizable style,wxSize weight,int align)76 wxMultiCellItemHandle :: wxMultiCellItemHandle( int row, int column, wxSize size, wxResizable style, wxSize weight, int align)
77 {
78     Initialize(row, column,1, 1, size, style, weight, align);
79 }
80 //---------------------------------------------------------------------------
wxMultiCellItemHandle(int row,int column,wxResizable style,wxSize weight,int align)81 wxMultiCellItemHandle :: wxMultiCellItemHandle( int row, int column, wxResizable style, wxSize weight, int align)
82 {
83     Initialize(row, column, 1, 1, wxSize(1, 1), style, weight, align);
84 }
85 //---------------------------------------------------------------------------
GetColumn()86 int wxMultiCellItemHandle::GetColumn()
87 {
88     return m_column;
89 }
90 //---------------------------------------------------------------------------
GetRow()91 int wxMultiCellItemHandle::GetRow()
92 {
93     return m_row;
94 }
95 //---------------------------------------------------------------------------
GetWidth()96 int wxMultiCellItemHandle::GetWidth()
97 {
98     return m_width;
99 }
100 //---------------------------------------------------------------------------
GetHeight()101 int wxMultiCellItemHandle::GetHeight()
102 {
103     return m_height;
104 }
105 //---------------------------------------------------------------------------
GetStyle()106 wxResizable    wxMultiCellItemHandle :: GetStyle()
107 {
108     return m_style;
109 };
110 //---------------------------------------------------------------------------
GetLocalSize()111 wxSize wxMultiCellItemHandle :: GetLocalSize()
112 {
113     return m_fixedSize;
114 };
115 //---------------------------------------------------------------------------
GetAlignment()116 int wxMultiCellItemHandle :: GetAlignment()
117 {
118     return m_alignment;
119 };
120 //---------------------------------------------------------------------------
GetWeight()121 wxSize wxMultiCellItemHandle :: GetWeight()
122 {
123     return m_weight;
124 };
125 
126 
127 
128 //---------------------------------------------------------------------------
129 
130 //---------------------------------------------------------------------------
131 // wxMultiCellSizer
132 //---------------------------------------------------------------------------
133 
134 /*
135  *Function Name: wxMultiCellSizer::Initialize
136  *
137  *Parameters:    wxsize Initial size of sizer
138  *
139  *Description:   This is a common function to initialize all the members of
140  *               this class.  It is only called from the constructors
141  *
142  */
143 
Initialize(wxSize size)144 void wxMultiCellSizer::Initialize( wxSize size )
145 {
146     m_cell_count = size;
147     m_maxHeight = (int *)malloc((1 + m_cell_count.GetHeight()) * sizeof(int));
148     m_maxWidth = (int *)malloc( (1 + m_cell_count.GetWidth()) * sizeof(int));
149     m_rowStretch = (int *)malloc( (1 + m_cell_count.GetHeight()) * sizeof(int));
150     m_colStretch = (int *)malloc((1 + m_cell_count.GetWidth()) * sizeof(int));
151 
152     m_weights = (wxSize **)malloc((1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth())) * sizeof(wxSize *));
153     m_minSizes = (wxSize **)malloc((1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth())) * sizeof(wxSize *));
154     for (int x = 0; x < 1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth()); x++)
155     {
156         m_weights[x] = new wxSize(0,0);
157         m_minSizes[x] = new wxSize(0,0);
158     }
159 
160     m_maxWeights = 1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth());
161     m_defaultCellSize = wxSize(5, 5);
162     m_win = NULL;
163     m_pen = wxRED_PEN;
164 }
165 //---------------------------------------------------------------------------
wxMultiCellSizer(wxSize & size)166 wxMultiCellSizer::wxMultiCellSizer( wxSize & size )
167 {
168     Initialize(size);
169 }
170 //---------------------------------------------------------------------------
wxMultiCellSizer(int rows,int cols)171 wxMultiCellSizer::wxMultiCellSizer( int rows, int cols)
172 {
173     wxSize size(cols, rows);
174     Initialize(size);
175 }
176 //---------------------------------------------------------------------------
~wxMultiCellSizer()177 wxMultiCellSizer::~wxMultiCellSizer()
178 {
179     WX_CLEAR_LIST(wxSizerItemList, m_children);
180 
181     free(m_maxHeight);
182     free(m_maxWidth);
183     free(m_rowStretch);
184     free(m_colStretch);
185 
186     for (int x = 0; x < 1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth()); x++)
187     {
188         delete m_weights[x];
189         delete m_minSizes[x];
190     }
191     free(m_weights);
192     free(m_minSizes);
193 }
194 //---------------------------------------------------------------------------
EnableGridLines(wxWindow * win)195 bool wxMultiCellSizer::EnableGridLines(wxWindow *win)
196 {
197     m_win = win;
198     return true;
199 }
200 //---------------------------------------------------------------------------
SetGridPen(const wxPen * pen)201 bool wxMultiCellSizer::SetGridPen(const wxPen *pen)
202 {
203     m_pen = pen;
204     return true;
205 }
206 
207 //---------------------------------------------------------------------------
SetDefaultCellSize(wxSize size)208 bool wxMultiCellSizer::SetDefaultCellSize(wxSize size)
209 {
210     m_defaultCellSize = size;
211     return true;
212 }
213 //---------------------------------------------------------------------------
SetColumnWidth(int column,int colSize,bool expandable)214 bool wxMultiCellSizer::SetColumnWidth(int column, int colSize, bool expandable)
215 {
216     if (expandable)
217     {
218         m_minSizes[column]->SetWidth(-colSize);
219     }
220     else
221     {
222         m_minSizes[column]->SetWidth(colSize);
223     }
224     return true;
225 }
226 //---------------------------------------------------------------------------
SetRowHeight(int row,int rowSize,bool expandable)227 bool wxMultiCellSizer::SetRowHeight(int row, int rowSize, bool expandable)
228 {
229     if (expandable)
230     {
231         m_minSizes[row]->SetHeight(-rowSize);
232     }
233     else
234     {
235         m_minSizes[row]->SetHeight(rowSize);
236     }
237     return true;
238 }
239 //---------------------------------------------------------------------------
RecalcSizes()240 void wxMultiCellSizer::RecalcSizes()
241 {
242     if (m_children.GetCount() == 0)
243         return;
244     wxSize size = GetSize();
245     wxPoint pos = GetPosition();
246 
247     GetMinimums();
248 
249     // We need to take the unused space and equally give it out to all the rows/columns
250     // which are stretchable
251 
252     int unUsedWidth = size.GetWidth() - Sum(m_maxWidth, m_cell_count.GetWidth());
253     int unUsedHeight = size.GetHeight() - Sum(m_maxHeight, m_cell_count.GetHeight());
254     int totalWidthWeight = 0;
255     int totalHeightWeight = 0;
256     int x;
257 
258     for (x = 0; x < wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth()); x++)
259     {
260         if (m_rowStretch[x])
261         {
262             totalHeightWeight += m_weights[x]->GetHeight();
263         }
264         if (x < m_cell_count.GetWidth() && m_colStretch[x])
265         {
266             totalWidthWeight += m_weights[x]->GetWidth();
267         }
268     }
269     for (x = 0; x < wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth()); x++)
270     {
271         if (x < m_cell_count.GetHeight() && m_rowStretch[x])
272         {
273             m_maxHeight[x] += unUsedHeight * m_weights[x]->GetHeight() / totalHeightWeight;
274         }
275         if (x < m_cell_count.GetWidth() && m_colStretch[x])
276         {
277             m_maxWidth[x] += unUsedWidth * m_weights[x]->GetWidth() / totalWidthWeight;
278         }
279     }
280     // We now have everything we need to figure each cell position and size
281     // The arrays m_maxHeight and m_maxWidth now contain the final widths and height of
282     // each row and column.
283 
284     double cell_width = (double)size.GetWidth() / (double)m_cell_count.GetWidth();
285     double cell_height = (double)size.GetHeight() / (double)m_cell_count.GetHeight();
286     wxPoint c_point;
287     wxSize  c_size;
288 
289     wxSizerItemList::compatibility_iterator current = m_children.GetFirst();
290     while (current)
291     {
292         wxSizerItem *item = current->GetData();
293 
294         wxMultiCellItemHandle *rect;
295         if (item != NULL &&
296             (rect = (wxMultiCellItemHandle *)item->GetUserData()) != NULL)
297         {
298             c_point.x = pos.x + (int)(rect->GetColumn() * cell_width);
299             c_point.y = pos.y + (int)(rect->GetRow() * cell_height);
300 
301             c_point.x = pos.x + Sum(m_maxWidth, rect->GetColumn());
302             c_point.y = pos.y + Sum(m_maxHeight, rect->GetRow());
303 
304 
305             c_size = rect->GetLocalSize();
306             wxSize minSize( item->CalcMin() );
307             if (c_size.GetHeight() != wxDefaultCoord ||
308                 c_size.GetWidth() != wxDefaultCoord)
309             {
310                 minSize.SetHeight(wxMax(minSize.GetHeight(), c_size.GetHeight()));
311                 minSize.SetWidth(wxMax(minSize.GetWidth(), c_size.GetWidth()));
312             }
313             if (rect->GetStyle() & wxHORIZONTAL_RESIZABLE ||
314                 rect->GetWidth() > 1
315                 || m_minSizes[rect->GetColumn()]->GetWidth() < 0)
316             {
317                 int w = 0;
318                 for (int x = 0; x < rect->GetWidth(); x++)
319                 {
320                     w += m_maxWidth[rect->GetColumn() + x];
321                 }
322                 c_size.SetWidth(w);
323             }
324             else
325             {
326                 c_size.SetWidth(minSize.GetWidth() );
327             }
328             if (rect->GetStyle() & wxVERTICAL_RESIZABLE ||
329                 rect->GetHeight() > 1 ||
330                 m_minSizes[rect->GetRow()]->GetHeight() < 0)
331             {
332                 int h = 0;
333                 for (int x = 0; x < rect->GetHeight(); x++)
334                 {
335                     h += m_maxHeight[rect->GetRow() + x];
336                 }
337                 c_size.SetHeight(h);
338             }
339             else
340             {
341                 c_size.SetHeight(minSize.GetHeight());
342             }
343             int extraHeight = (m_maxHeight[rect->GetRow()] - c_size.GetHeight());
344             int extraWidth = (m_maxWidth[rect->GetColumn()] - c_size.GetWidth());
345 
346             if (rect->GetWidth() == 1 && rect->GetAlignment() & wxALIGN_CENTER_HORIZONTAL)
347             {
348                 c_point.x += extraWidth / 2;
349             }
350             if (rect->GetWidth() == 1 && rect->GetAlignment() & wxALIGN_RIGHT)
351             {
352                 c_point.x += extraWidth;
353             }
354             if (rect->GetHeight() == 1 && rect->GetAlignment() & wxALIGN_CENTER_VERTICAL)
355             {
356                 c_point.y += extraHeight / 2;
357             }
358             if (rect->GetHeight() == 1 && rect->GetAlignment() & wxALIGN_BOTTOM)
359             {
360                 c_point.y += extraHeight;
361             }
362             item->SetDimension(c_point, c_size);
363         }
364         current = current->GetNext();
365     }
366 }
367 //---------------------------------------------------------------------------
CalcMin()368 wxSize wxMultiCellSizer::CalcMin()
369 {
370     if (m_children.GetCount() == 0)
371         return wxSize(10,10);
372 
373     GetMinimums();
374     int m_minWidth = Sum(m_maxWidth, m_cell_count.GetWidth());
375     int m_minHeight = Sum(m_maxHeight, m_cell_count.GetHeight());
376     return wxSize( m_minWidth, m_minHeight );
377 }
378 //---------------------------------------------------------------------------
GetMinimums()379 void wxMultiCellSizer :: GetMinimums()
380 {
381     // We first initial all the arrays EXCEPT for the m_minsizes array.
382 
383     memset(m_maxHeight, 0, sizeof(int) * m_cell_count.GetHeight());
384     memset(m_maxWidth, 0, sizeof(int) * m_cell_count.GetWidth());
385     memset(m_rowStretch, 0, sizeof(int) * m_cell_count.GetHeight());
386     memset(m_colStretch, 0, sizeof(int) * m_cell_count.GetWidth());
387     for (int x = 0; x < 1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth()); x++)
388     {
389         m_weights[x]->SetHeight(0);
390         m_weights[x]->SetWidth(0);
391     }
392 
393     wxSizerItemList::compatibility_iterator     node = m_children.GetFirst();
394     while (node)
395     {
396         wxSizerItem     *item = node->GetData();
397         wxMultiCellItemHandle *rect;
398         if (item != NULL &&
399             (rect = (wxMultiCellItemHandle *)item->GetUserData()) != NULL)
400         {
401             int row = rect->GetRow();
402             int col = rect->GetColumn();
403 
404             // First make sure that the control knows about the max rows and columns
405 
406             int changed = false;
407             if (row + 1 > m_cell_count.GetHeight())
408             {
409                 changed++;
410                 m_maxHeight = (int *)realloc(m_maxHeight, (1 + row) * sizeof(int));
411                 m_rowStretch = (int *)realloc(m_rowStretch, (1 + row) * sizeof(int));
412                 for (int x = m_cell_count.GetHeight(); x < row + 1; x++)
413                 {
414                     m_maxHeight[x - 1] = 0;
415                     m_rowStretch[x - 1] = 0;
416                 }
417                 m_cell_count.SetHeight(row + 1);
418             }
419             if (col + 1 > m_cell_count.GetWidth())
420             {
421                 changed++;
422                 m_maxWidth = (int *)realloc(m_maxWidth, (1 + col) * sizeof(int));
423                 m_colStretch = (int *)realloc(m_colStretch, ( 1 + col) * sizeof(int));
424                 for (int x = m_cell_count.GetWidth(); x < col + 1; x++)
425                 {
426                     m_maxWidth[x - 1] = 0;
427                     m_colStretch[x - 1] = 0;
428                 }
429                 m_cell_count.SetWidth(col + 1);
430             }
431             if (changed)
432             {
433                 m_weights = (wxSize **)realloc(m_weights, (1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth())) * sizeof(wxSize *));
434                 m_minSizes = (wxSize **)realloc(m_minSizes, (1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth())) * sizeof(wxSize *));
435                 for (int x = m_maxWeights; x < 1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth()); x++)
436                 {
437                     m_weights[x - 1] = new wxSize(0,0);
438                     m_minSizes[x - 1] = new wxSize(0,0);
439                 }
440                 m_maxWeights = 1 + wxMax(m_cell_count.GetHeight(), m_cell_count.GetWidth());
441             }
442 
443             // Sum the m_weights for each row/column, but only if they are resizable
444 
445             wxSize minSize( item->CalcMin() );
446             wxSize c_size = rect->GetLocalSize();
447             if (c_size.GetHeight() != wxDefaultCoord ||
448                 c_size.GetWidth() != wxDefaultCoord)
449             {
450                 minSize.SetHeight(wxMax(minSize.GetHeight(), c_size.GetHeight()));
451                 minSize.SetWidth(wxMax(minSize.GetWidth(), c_size.GetWidth()));
452             }
453 
454             // For each row, calculate the max height for those fields which are not
455             // resizable in the vertical pane
456 
457             if (!(rect->GetStyle() & wxVERTICAL_RESIZABLE || m_minSizes[row]->GetHeight() < 0))
458             {
459                 m_maxHeight[row] = wxMax(m_maxHeight[row], minSize.GetHeight() / rect->GetHeight());
460             }
461             else
462             {
463                 m_rowStretch[row] = 1;
464                 if (m_minSizes[row]->GetHeight())
465                 {
466                     m_maxHeight[row] = abs(m_minSizes[row]->GetHeight());
467                 }
468                 else
469                 {
470                     m_maxHeight[row] = wxMax(m_maxHeight[row], m_defaultCellSize.GetHeight());
471                 }
472                 m_weights[row]->SetHeight(wxMax(m_weights[row]->GetHeight(), rect->GetWeight().GetHeight()));
473             }
474 
475             // For each column, calculate the max width for those fields which are not
476             // resizable in the horizontal pane
477 
478             if (!(rect->GetStyle() & wxHORIZONTAL_RESIZABLE || m_minSizes[col]->GetWidth() < 0))
479             {
480                 if (m_minSizes[col]->GetWidth())
481                 {
482                     m_maxWidth[col] = abs(m_minSizes[col]->GetWidth());
483                 }
484                 else
485                 {
486                     m_maxWidth[col] = wxMax(m_maxWidth[col], minSize.GetWidth() / rect->GetWidth());
487                 }
488             }
489             else
490             {
491                 m_colStretch[col] = 1;
492                 m_maxWidth[col] = wxMax(m_maxWidth[col], m_defaultCellSize.GetWidth());
493                 m_weights[col]->SetWidth(wxMax(m_weights[col]->GetWidth(), rect->GetWeight().GetWidth()));
494             }
495             node = node->GetNext();
496         }
497     }
498 } // wxMultiCellSizer :: GetMinimums
499 //---------------------------------------------------------------------------
500 /*
501  *Function Name: wxMultiCellSizer :: Sum
502  *
503  *Parameters:    int* pointer to array of ints
504  *               int  Number of cells to sum up
505  *
506  *Description:   This member function sums up all the elements of the array which
507  *               preceed the specified cell.
508  *
509  *Returns:       int Sum
510  *
511  */
512 
Sum(int * array,int x)513 int wxMultiCellSizer :: Sum(int *array, int x)
514 {
515     int sum = 0;
516     while (x--)
517     {
518         sum += array[x];
519     }
520     return sum;
521 }
522 //---------------------------------------------------------------------------
523 /*
524  *Function Name: wxMultiCellSizer :: DrawGridLines
525  *
526  *Parameters:    wxDC Device context
527  *
528  *Description:   This function draws the grid lines in the specified device context.
529  *
530  */
531 
DrawGridLines(wxDC & dc)532 void wxMultiCellSizer :: DrawGridLines(wxDC& dc)
533 {
534     RecalcSizes();
535     int maxW = Sum(m_maxWidth, m_cell_count.GetWidth());
536     int maxH = Sum(m_maxHeight, m_cell_count.GetHeight());
537     int x;
538 
539     // Draw the columns
540     dc.SetPen(* m_pen);
541     for (x = 1; x < m_cell_count.GetWidth(); x++)
542     {
543         int colPos = Sum(m_maxWidth, x) ;
544         dc.DrawLine(colPos, 0, colPos, maxH);
545     }
546 
547     // Draw the rows
548     for (x = 1; x < m_cell_count.GetHeight(); x++)
549     {
550         int rowPos = Sum(m_maxHeight, x);
551         dc.DrawLine(0, rowPos, maxW, rowPos);
552     }
553 }
554 //---------------------------------------------------------------------------
555 // Define the repainting behaviour
556 /*
557  *Function Name: wxMultiCellSizer::OnPaint
558  *
559  *Parameters:    wxDC Device context
560  *
561  *Description:   This function calls the DrawGridLines() member if a window
562  *               has been previously specified.  This functions MUST be called
563  *               from an OnPaint member belonging to the window which the sizer
564  *               is attached to.
565  *
566  */
567 
OnPaint(wxDC & dc)568 void wxMultiCellSizer::OnPaint(wxDC& dc )
569 {
570     if (m_win)
571     {
572         DrawGridLines(dc);
573     }
574 }
575 
576 
577 //---------------------------------------------------------------------------
578 //---------------------------------------------------------------------------
579 
580 
581 
582 
583 #define CELL_LOC(row, col) ((row) * m_maxCols + col)
584 
585 //---------------------------------------------------------------------------
586 // wxCell
587 //---------------------------------------------------------------------------
588 /*
589  *Function Name: wxCell : wxLayoutConstraints
590  *
591  *Description:   This class is used by wxMultiCellCanvas for internal storage
592  *
593  */
594 
595 class wxCell : public wxLayoutConstraints
596 {
597 public:
wxCell(wxWindow * win)598     wxCell(wxWindow *win)
599     {
600         m_window = win;
601     };
602 
603     wxWindow    *m_window;
604 };
605 
606 
607 
608 //---------------------------------------------------------------------------
609 // wxMultiCellCanvas
610 //---------------------------------------------------------------------------
wxMultiCellCanvas(wxWindow * par,int numRows,int numCols)611 wxMultiCellCanvas :: wxMultiCellCanvas(wxWindow *par, int numRows, int numCols)
612    : wxFlexGridSizer(numRows, numCols, 0, 0)
613 {
614     m_cells = (wxCell **)calloc(numRows * numCols, sizeof(wxCell *));
615 
616     m_parent = par;
617     m_maxRows = numRows;
618     m_maxCols = numCols;
619     m_minCellSize = wxSize(5, 5);
620 }
621 //---------------------------------------------------------------------------
Add(wxWindow * win,unsigned int row,unsigned int col)622 void wxMultiCellCanvas :: Add(wxWindow *win, unsigned int row, unsigned int col)
623 {
624   // thanks to unsigned data row and col are always >= 0
625     wxASSERT_MSG( /* row >= 0 && */ row < m_maxRows,
626                  wxString::Format(_T("Row %d out of bounds (0..%d)"), row, m_maxRows) );
627     wxASSERT_MSG( /* col >= 0 && */ col < m_maxCols,
628                  wxString::Format(_T("Column %d out of bounds (0..%d)"), col, m_maxCols) );
629 
630     wxASSERT_MSG(m_cells[CELL_LOC(row, col)] == NULL, wxT("Cell already occupied"));
631 
632     wxCell *newCell = new wxCell(win);
633     m_cells[CELL_LOC(row,col)] = newCell;
634 }
635 //---------------------------------------------------------------------------
CalculateConstraints()636 void wxMultiCellCanvas :: CalculateConstraints()
637 {
638     unsigned int    row, col;
639     for (row = 0; row < m_maxRows; row++)
640     {
641         for (col = 0; col < m_maxCols; col++)
642         {
643             if (!m_cells[CELL_LOC(row, col)])
644             {
645                 // Create an empty static text field as a placeholder
646                 m_cells[CELL_LOC(row, col)] = new wxCell(new wxStaticText(m_parent, wxID_ANY, wxEmptyString));
647             }
648             wxFlexGridSizer::Add(m_cells[CELL_LOC(row, col)]->m_window);
649         }
650     }
651 }
652 
653 /*** End of File ***/
654