1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/gbsizer.cpp
3 // Purpose:     wxGridBagSizer:  A sizer that can lay out items in a grid,
4 //              with items at specified cells, and with the option of row
5 //              and/or column spanning
6 //
7 // Author:      Robin Dunn
8 // Created:     03-Nov-2003
9 // Copyright:   (c) Robin Dunn
10 // Licence:     wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12 
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
15 
16 
17 #include "wx/gbsizer.h"
18 
19 //---------------------------------------------------------------------------
20 
21 wxIMPLEMENT_DYNAMIC_CLASS(wxGBSizerItem, wxSizerItem);
22 wxIMPLEMENT_CLASS(wxGridBagSizer, wxFlexGridSizer);
23 
24 const wxGBSpan wxDefaultSpan;
25 
26 //---------------------------------------------------------------------------
27 // wxGBSizerItem
28 //---------------------------------------------------------------------------
29 
wxGBSizerItem(int width,int height,const wxGBPosition & pos,const wxGBSpan & span,int flag,int border,wxObject * userData)30 wxGBSizerItem::wxGBSizerItem( int width,
31                               int height,
32                               const wxGBPosition& pos,
33                               const wxGBSpan& span,
34                               int flag,
35                               int border,
36                               wxObject* userData)
37     : wxSizerItem(width, height, 0, flag, border, userData),
38       m_pos(pos),
39       m_span(span),
40       m_gbsizer(NULL)
41 {
42 }
43 
44 
wxGBSizerItem(wxWindow * window,const wxGBPosition & pos,const wxGBSpan & span,int flag,int border,wxObject * userData)45 wxGBSizerItem::wxGBSizerItem( wxWindow *window,
46                               const wxGBPosition& pos,
47                               const wxGBSpan& span,
48                               int flag,
49                               int border,
50                               wxObject* userData )
51     : wxSizerItem(window, 0, flag, border, userData),
52       m_pos(pos),
53       m_span(span),
54       m_gbsizer(NULL)
55 {
56 }
57 
58 
wxGBSizerItem(wxSizer * sizer,const wxGBPosition & pos,const wxGBSpan & span,int flag,int border,wxObject * userData)59 wxGBSizerItem::wxGBSizerItem( wxSizer *sizer,
60                               const wxGBPosition& pos,
61                               const wxGBSpan& span,
62                               int flag,
63                               int border,
64                               wxObject* userData )
65     : wxSizerItem(sizer, 0, flag, border, userData),
66       m_pos(pos),
67       m_span(span),
68       m_gbsizer(NULL)
69 {
70 }
71 
wxGBSizerItem()72 wxGBSizerItem::wxGBSizerItem()
73     : wxSizerItem(),
74       m_pos(-1,-1),
75       m_gbsizer(NULL)
76 {
77 }
78 
79 //---------------------------------------------------------------------------
80 
81 
GetPos(int & row,int & col) const82 void wxGBSizerItem::GetPos(int& row, int& col) const
83 {
84     row = m_pos.GetRow();
85     col = m_pos.GetCol();
86 }
87 
GetSpan(int & rowspan,int & colspan) const88 void wxGBSizerItem::GetSpan(int& rowspan, int& colspan) const
89 {
90     rowspan = m_span.GetRowspan();
91     colspan = m_span.GetColspan();
92 }
93 
94 
SetPos(const wxGBPosition & pos)95 bool wxGBSizerItem::SetPos( const wxGBPosition& pos )
96 {
97     if (m_gbsizer)
98     {
99         wxCHECK_MSG( !m_gbsizer->CheckForIntersection(pos, m_span, this), false,
100                  wxT("An item is already at that position") );
101     }
102     m_pos = pos;
103     return true;
104 }
105 
SetSpan(const wxGBSpan & span)106 bool wxGBSizerItem::SetSpan( const wxGBSpan& span )
107 {
108     if (m_gbsizer)
109     {
110         wxCHECK_MSG( !m_gbsizer->CheckForIntersection(m_pos, span, this), false,
111                  wxT("An item is already at that position") );
112     }
113     m_span = span;
114     return true;
115 }
116 
117 
InRange(int val,int min,int max)118 inline bool InRange(int val, int min, int max)
119 {
120     return (val >= min && val <= max);
121 }
122 
Intersects(const wxGBSizerItem & other)123 bool wxGBSizerItem::Intersects(const wxGBSizerItem& other)
124 {
125     return Intersects(other.GetPos(), other.GetSpan());
126 }
127 
Intersects(const wxGBPosition & pos,const wxGBSpan & span)128 bool wxGBSizerItem::Intersects(const wxGBPosition& pos, const wxGBSpan& span)
129 {
130 
131     int row, col, endrow, endcol;
132     int otherrow, othercol, otherendrow, otherendcol;
133 
134     GetPos(row, col);
135     GetEndPos(endrow, endcol);
136 
137     otherrow = pos.GetRow();
138     othercol = pos.GetCol();
139     otherendrow = otherrow + span.GetRowspan() - 1;
140     otherendcol = othercol + span.GetColspan() - 1;
141 
142     // is the other item's start or end in the range of this one?
143     if (( InRange(otherrow, row, endrow) && InRange(othercol, col, endcol) ) ||
144         ( InRange(otherendrow, row, endrow) && InRange(otherendcol, col, endcol) ))
145         return true;
146 
147     // is this item's start or end in the range of the other one?
148     if (( InRange(row, otherrow, otherendrow) && InRange(col, othercol, otherendcol) ) ||
149         ( InRange(endrow, otherrow, otherendrow) && InRange(endcol, othercol, otherendcol) ))
150         return true;
151 
152     return false;
153 }
154 
155 
GetEndPos(int & row,int & col)156 void wxGBSizerItem::GetEndPos(int& row, int& col)
157 {
158     row = m_pos.GetRow() + m_span.GetRowspan() - 1;
159     col = m_pos.GetCol() + m_span.GetColspan() - 1;
160 }
161 
162 
163 //---------------------------------------------------------------------------
164 // wxGridBagSizer
165 //---------------------------------------------------------------------------
166 
wxGridBagSizer(int vgap,int hgap)167 wxGridBagSizer::wxGridBagSizer(int vgap, int hgap )
168     : wxFlexGridSizer(1, vgap, hgap),
169       m_emptyCellSize(10,20)
170 
171 {
172 }
173 
174 
Add(wxWindow * window,const wxGBPosition & pos,const wxGBSpan & span,int flag,int border,wxObject * userData)175 wxSizerItem* wxGridBagSizer::Add( wxWindow *window,
176                                   const wxGBPosition& pos, const wxGBSpan& span,
177                                   int flag, int border,  wxObject* userData )
178 {
179     wxGBSizerItem* item = new wxGBSizerItem(window, pos, span, flag, border, userData);
180     if ( Add(item) )
181         return item;
182 
183     delete item;
184     return NULL;
185 }
186 
Add(wxSizer * sizer,const wxGBPosition & pos,const wxGBSpan & span,int flag,int border,wxObject * userData)187 wxSizerItem* wxGridBagSizer::Add( wxSizer *sizer,
188                           const wxGBPosition& pos, const wxGBSpan& span,
189                           int flag, int border,  wxObject* userData )
190 {
191     wxGBSizerItem* item = new wxGBSizerItem(sizer, pos, span, flag, border, userData);
192     if ( Add(item) )
193         return item;
194 
195     delete item;
196     return NULL;
197 }
198 
Add(int width,int height,const wxGBPosition & pos,const wxGBSpan & span,int flag,int border,wxObject * userData)199 wxSizerItem* wxGridBagSizer::Add( int width, int height,
200                           const wxGBPosition& pos, const wxGBSpan& span,
201                           int flag, int border,  wxObject* userData )
202 {
203     wxGBSizerItem* item = new wxGBSizerItem(width, height, pos, span, flag, border, userData);
204     if ( Add(item) )
205         return item;
206 
207     delete item;
208     return NULL;
209 }
210 
Add(wxGBSizerItem * item)211 wxSizerItem* wxGridBagSizer::Add( wxGBSizerItem *item )
212 {
213     wxCHECK_MSG( !CheckForIntersection(item), NULL,
214                  wxT("An item is already at that position") );
215     m_children.Append(item);
216     item->SetGBSizer(this);
217     if ( item->GetWindow() )
218         item->GetWindow()->SetContainingSizer( this );
219 
220     // extend the number of rows/columns of the underlying wxFlexGridSizer if
221     // necessary
222     int row, col;
223     item->GetEndPos(row, col);
224     row++;
225     col++;
226 
227     if ( row > GetRows() )
228         SetRows(row);
229     if ( col > GetCols() )
230         SetCols(col);
231 
232     return item;
233 }
234 
235 
236 
237 //---------------------------------------------------------------------------
238 
GetCellSize(int row,int col) const239 wxSize wxGridBagSizer::GetCellSize(int row, int col) const
240 {
241     wxCHECK_MSG( (row < m_rows) && (col < m_cols),
242                  wxDefaultSize,
243                  wxT("Invalid cell."));
244     return wxSize( m_colWidths[col], m_rowHeights[row] );
245 }
246 
247 
GetItemPosition(wxWindow * window)248 wxGBPosition wxGridBagSizer::GetItemPosition(wxWindow *window)
249 {
250     wxGBPosition badpos(-1,-1);
251     wxGBSizerItem* item = FindItem(window);
252     wxCHECK_MSG(item, badpos, wxT("Failed to find item."));
253     return item->GetPos();
254 }
255 
256 
GetItemPosition(wxSizer * sizer)257 wxGBPosition wxGridBagSizer::GetItemPosition(wxSizer *sizer)
258 {
259     wxGBPosition badpos(-1,-1);
260     wxGBSizerItem* item = FindItem(sizer);
261     wxCHECK_MSG(item, badpos, wxT("Failed to find item."));
262     return item->GetPos();
263 }
264 
265 
GetItemPosition(size_t index)266 wxGBPosition wxGridBagSizer::GetItemPosition(size_t index)
267 {
268     wxGBPosition badpos(-1,-1);
269     wxSizerItemList::compatibility_iterator node = m_children.Item( index );
270     wxCHECK_MSG( node, badpos, wxT("Failed to find item.") );
271     wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
272     return item->GetPos();
273 }
274 
275 
276 
SetItemPosition(wxWindow * window,const wxGBPosition & pos)277 bool wxGridBagSizer::SetItemPosition(wxWindow *window, const wxGBPosition& pos)
278 {
279     wxGBSizerItem* item = FindItem(window);
280     wxCHECK_MSG(item, false, wxT("Failed to find item."));
281     return item->SetPos(pos);
282 }
283 
284 
SetItemPosition(wxSizer * sizer,const wxGBPosition & pos)285 bool wxGridBagSizer::SetItemPosition(wxSizer *sizer, const wxGBPosition& pos)
286 {
287     wxGBSizerItem* item = FindItem(sizer);
288     wxCHECK_MSG(item, false, wxT("Failed to find item."));
289     return item->SetPos(pos);
290 }
291 
292 
SetItemPosition(size_t index,const wxGBPosition & pos)293 bool wxGridBagSizer::SetItemPosition(size_t index, const wxGBPosition& pos)
294 {
295     wxSizerItemList::compatibility_iterator node = m_children.Item( index );
296     wxCHECK_MSG( node, false, wxT("Failed to find item.") );
297     wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
298     return item->SetPos(pos);
299 }
300 
301 
302 
GetItemSpan(wxWindow * window)303 wxGBSpan wxGridBagSizer::GetItemSpan(wxWindow *window)
304 {
305     wxGBSizerItem* item = FindItem(window);
306     wxCHECK_MSG( item, wxGBSpan::Invalid(), wxT("Failed to find item.") );
307     return item->GetSpan();
308 }
309 
310 
GetItemSpan(wxSizer * sizer)311 wxGBSpan wxGridBagSizer::GetItemSpan(wxSizer *sizer)
312 {
313     wxGBSizerItem* item = FindItem(sizer);
314     wxCHECK_MSG( item, wxGBSpan::Invalid(), wxT("Failed to find item.") );
315     return item->GetSpan();
316 }
317 
318 
GetItemSpan(size_t index)319 wxGBSpan wxGridBagSizer::GetItemSpan(size_t index)
320 {
321     wxSizerItemList::compatibility_iterator node = m_children.Item( index );
322     wxCHECK_MSG( node, wxGBSpan::Invalid(), wxT("Failed to find item.") );
323     wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
324     return item->GetSpan();
325 }
326 
327 
328 
SetItemSpan(wxWindow * window,const wxGBSpan & span)329 bool wxGridBagSizer::SetItemSpan(wxWindow *window, const wxGBSpan& span)
330 {
331     wxGBSizerItem* item = FindItem(window);
332     wxCHECK_MSG(item, false, wxT("Failed to find item."));
333     return item->SetSpan(span);
334 }
335 
336 
SetItemSpan(wxSizer * sizer,const wxGBSpan & span)337 bool wxGridBagSizer::SetItemSpan(wxSizer *sizer, const wxGBSpan& span)
338 {
339     wxGBSizerItem* item = FindItem(sizer);
340     wxCHECK_MSG(item, false, wxT("Failed to find item."));
341     return item->SetSpan(span);
342 }
343 
344 
SetItemSpan(size_t index,const wxGBSpan & span)345 bool wxGridBagSizer::SetItemSpan(size_t index, const wxGBSpan& span)
346 {
347     wxSizerItemList::compatibility_iterator node = m_children.Item( index );
348     wxCHECK_MSG( node, false, wxT("Failed to find item.") );
349     wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
350     return item->SetSpan(span);
351 }
352 
353 
354 
355 
FindItem(wxWindow * window)356 wxGBSizerItem* wxGridBagSizer::FindItem(wxWindow* window)
357 {
358     wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
359     while (node)
360     {
361         wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
362         if ( item->GetWindow() == window )
363             return item;
364         node = node->GetNext();
365     }
366     return NULL;
367 }
368 
369 
FindItem(wxSizer * sizer)370 wxGBSizerItem* wxGridBagSizer::FindItem(wxSizer* sizer)
371 {
372     wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
373     while (node)
374     {
375         wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
376         if ( item->GetSizer() == sizer )
377             return item;
378         node = node->GetNext();
379     }
380     return NULL;
381 }
382 
383 
384 
385 
FindItemAtPosition(const wxGBPosition & pos)386 wxGBSizerItem* wxGridBagSizer::FindItemAtPosition(const wxGBPosition& pos)
387 {
388     wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
389     while (node)
390     {
391         wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
392         if ( item->Intersects(pos, wxDefaultSpan) )
393             return item;
394         node = node->GetNext();
395     }
396     return NULL;
397 }
398 
399 
400 
401 
FindItemAtPoint(const wxPoint & pt)402 wxGBSizerItem* wxGridBagSizer::FindItemAtPoint(const wxPoint& pt)
403 {
404     wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
405     while (node)
406     {
407         wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
408         wxRect rect(item->GetPosition(), item->GetSize());
409         rect.Inflate(m_hgap, m_vgap);
410         if ( rect.Contains(pt) )
411             return item;
412         node = node->GetNext();
413     }
414     return NULL;
415 }
416 
417 
418 
419 
FindItemWithData(const wxObject * userData)420 wxGBSizerItem* wxGridBagSizer::FindItemWithData(const wxObject* userData)
421 {
422     wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
423     while (node)
424     {
425         wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
426         if ( item->GetUserData() == userData )
427             return item;
428         node = node->GetNext();
429     }
430     return NULL;
431 }
432 
433 
434 
435 
436 //---------------------------------------------------------------------------
437 
438 // Figure out what all the min row heights and col widths are, and calculate
439 // min size from that.
CalcMin()440 wxSize wxGridBagSizer::CalcMin()
441 {
442     int idx;
443 
444     if (m_children.GetCount() == 0)
445         return m_emptyCellSize;
446 
447     m_rowHeights.Empty();
448     m_colWidths.Empty();
449 
450     wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
451     while (node)
452     {
453         wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
454         if ( item->IsShown() )
455         {
456             int row, col, endrow, endcol;
457 
458             item->GetPos(row, col);
459             item->GetEndPos(endrow, endcol);
460 
461             // fill heights and widths up to this item if needed
462             while ( (int)m_rowHeights.GetCount() <= endrow )
463                 m_rowHeights.Add(m_emptyCellSize.GetHeight());
464             while ( (int)m_colWidths.GetCount() <= endcol )
465                 m_colWidths.Add(m_emptyCellSize.GetWidth());
466 
467             // See if this item increases the size of its row(s) or col(s)
468             wxSize size(item->CalcMin());
469             for (idx=row; idx <= endrow; idx++)
470                 m_rowHeights[idx] = wxMax(m_rowHeights[idx], size.GetHeight() / (endrow-row+1));
471             for (idx=col; idx <= endcol; idx++)
472                 m_colWidths[idx] = wxMax(m_colWidths[idx], size.GetWidth() / (endcol-col+1));
473         }
474         node = node->GetNext();
475     }
476 
477     AdjustForOverflow();
478     AdjustForFlexDirection();
479 
480     // Now traverse the heights and widths arrays calcing the totals, including gaps
481     int width = 0;
482     m_cols = m_colWidths.GetCount();
483     for (idx=0; idx < m_cols; idx++)
484         width += m_colWidths[idx] + ( idx == m_cols-1 ? 0 : m_hgap );
485 
486     int height = 0;
487     m_rows = m_rowHeights.GetCount();
488     for (idx=0; idx < m_rows; idx++)
489         height += m_rowHeights[idx] + ( idx == m_rows-1 ? 0 : m_vgap );
490 
491     return wxSize(width, height);
492 }
493 
494 
495 
RepositionChildren(const wxSize & minSize)496 void wxGridBagSizer::RepositionChildren(const wxSize& minSize)
497 {
498     // We can't lay out our elements if we don't have at least a single row and
499     // a single column. Notice that this may happen even if we have some
500     // children but all of them are hidden, so checking for m_children being
501     // non-empty is not enough, see #15475.
502     if ( m_rowHeights.empty() || m_colWidths.empty() )
503         return;
504 
505     wxPoint pt( GetPosition() );
506     wxSize  sz( GetSize() );
507 
508     m_rows = m_rowHeights.GetCount();
509     m_cols = m_colWidths.GetCount();
510     int idx, width, height;
511 
512     AdjustForGrowables(sz, minSize);
513 
514     // Find the start positions on the window of the rows and columns
515     wxArrayInt rowpos;
516     rowpos.Add(0, m_rows);
517     int y = pt.y;
518     for (idx=0; idx < m_rows; idx++)
519     {
520         height = m_rowHeights[idx] + m_vgap;
521         rowpos[idx] = y;
522         y += height;
523     }
524 
525     wxArrayInt colpos;
526     colpos.Add(0, m_cols);
527     int x = pt.x;
528     for (idx=0; idx < m_cols; idx++)
529     {
530         width = m_colWidths[idx] + m_hgap;
531         colpos[idx] = x;
532         x += width;
533     }
534 
535 
536     // Now iterate the children, setting each child's dimensions
537     wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
538     while (node)
539     {
540         wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
541 
542         if ( item->IsShown() )
543         {
544             int row, col, endrow, endcol;
545             item->GetPos(row, col);
546             item->GetEndPos(endrow, endcol);
547 
548             height = 0;
549             for(idx=row; idx <= endrow; idx++)
550                 height += m_rowHeights[idx];
551             height += (endrow - row) * m_vgap; // add a vgap for every row spanned
552 
553             width = 0;
554             for (idx=col; idx <= endcol; idx++)
555                 width += m_colWidths[idx];
556             width += (endcol - col) * m_hgap; // add a hgap for every col spanned
557 
558             SetItemBounds(item, colpos[col], rowpos[row], width, height);
559         }
560 
561         node = node->GetNext();
562     }
563 }
564 
565 
566 // Sometimes CalcMin can result in some rows or cols having too much space in
567 // them because as it traverses the items it makes some assumptions when
568 // items span to other cells.  But those assumptions can become invalid later
569 // on when other items are fitted into the same rows or columns that the
570 // spanning item occupies. This method tries to find those situations and
571 // fixes them.
AdjustForOverflow()572 void wxGridBagSizer::AdjustForOverflow()
573 {
574     int row, col;
575 
576     for (row=0; row<(int)m_rowHeights.GetCount(); row++)
577     {
578         int rowExtra=INT_MAX;
579         int rowHeight = m_rowHeights[row];
580         for (col=0; col<(int)m_colWidths.GetCount(); col++)
581         {
582             wxGBPosition pos(row,col);
583             wxGBSizerItem* item = FindItemAtPosition(pos);
584             if ( !item || !item->IsShown() )
585                 continue;
586 
587             int endrow, endcol;
588             item->GetEndPos(endrow, endcol);
589 
590             // If the item starts in this position and doesn't span rows, then
591             // just look at the whole item height
592             if ( item->GetPos() == pos && endrow == row )
593             {
594                 int itemHeight = item->CalcMin().GetHeight();
595                 rowExtra = wxMin(rowExtra, rowHeight - itemHeight);
596                 continue;
597             }
598 
599             // Otherwise, only look at spanning items if they end on this row
600             if ( endrow == row )
601             {
602                 // first deduct the portions of the item that are on prior rows
603                 int itemHeight = item->CalcMin().GetHeight();
604                 for (int r=item->GetPos().GetRow(); r<row; r++)
605                     itemHeight -= (m_rowHeights[r] + GetHGap());
606 
607                 if ( itemHeight < 0 )
608                     itemHeight = 0;
609 
610                 // and check how much is left
611                 rowExtra = wxMin(rowExtra, rowHeight - itemHeight);
612             }
613         }
614         if ( rowExtra && rowExtra != INT_MAX )
615             m_rowHeights[row] -= rowExtra;
616     }
617 
618     // Now do the same thing for columns
619     for (col=0; col<(int)m_colWidths.GetCount(); col++)
620     {
621         int colExtra=INT_MAX;
622         int colWidth = m_colWidths[col];
623         for (row=0; row<(int)m_rowHeights.GetCount(); row++)
624         {
625             wxGBPosition pos(row,col);
626             wxGBSizerItem* item = FindItemAtPosition(pos);
627             if ( !item || !item->IsShown() )
628                 continue;
629 
630             int endrow, endcol;
631             item->GetEndPos(endrow, endcol);
632 
633             if ( item->GetPos() == pos && endcol == col )
634             {
635                 int itemWidth = item->CalcMin().GetWidth();
636                 colExtra = wxMin(colExtra, colWidth - itemWidth);
637                 continue;
638             }
639 
640             if ( endcol == col )
641             {
642                 int itemWidth = item->CalcMin().GetWidth();
643                 for (int c=item->GetPos().GetCol(); c<col; c++)
644                     itemWidth -= (m_colWidths[c] + GetVGap());
645 
646                 if ( itemWidth < 0 )
647                     itemWidth = 0;
648 
649                 colExtra = wxMin(colExtra, colWidth - itemWidth);
650             }
651         }
652         if ( colExtra && colExtra != INT_MAX )
653             m_colWidths[col] -= colExtra;
654     }
655 
656 
657 }
658 
659 //---------------------------------------------------------------------------
660 
CheckForIntersection(wxGBSizerItem * item,wxGBSizerItem * excludeItem)661 bool wxGridBagSizer::CheckForIntersection(wxGBSizerItem* item, wxGBSizerItem* excludeItem)
662 {
663     return CheckForIntersection(item->GetPos(), item->GetSpan(), excludeItem);
664 }
665 
CheckForIntersection(const wxGBPosition & pos,const wxGBSpan & span,wxGBSizerItem * excludeItem)666 bool wxGridBagSizer::CheckForIntersection(const wxGBPosition& pos, const wxGBSpan& span, wxGBSizerItem* excludeItem)
667 {
668     wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
669     while (node)
670     {
671         wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
672         node = node->GetNext();
673 
674         if ( excludeItem && item == excludeItem )
675             continue;
676 
677         if ( item->Intersects(pos, span) )
678             return true;
679 
680     }
681     return false;
682 }
683 
684 
685 // Assumes a 10x10 grid, and returns the first empty cell found.  This is
686 // really stupid but it is only used by the Add methods that match the base
687 // class virtuals, which should normally not be used anyway...
FindEmptyCell()688 wxGBPosition wxGridBagSizer::FindEmptyCell()
689 {
690     int row, col;
691 
692     for (row=0; row<10; row++)
693         for (col=0; col<10; col++)
694         {
695             wxGBPosition pos(row, col);
696             if ( !CheckForIntersection(pos, wxDefaultSpan) )
697                 return pos;
698         }
699     return wxGBPosition(-1, -1);
700 }
701 
702 
703 //---------------------------------------------------------------------------
704 
705 // The Add base class virtuals should not be used with this class, but
706 // we'll try to make them automatically select a location for the item
707 // anyway.
708 
Add(wxWindow * window,int,int flag,int border,wxObject * userData)709 wxSizerItem* wxGridBagSizer::Add( wxWindow *window, int, int flag, int border, wxObject* userData )
710 {
711     return Add(window, FindEmptyCell(), wxDefaultSpan, flag, border, userData);
712 }
713 
Add(wxSizer * sizer,int,int flag,int border,wxObject * userData)714 wxSizerItem* wxGridBagSizer::Add( wxSizer *sizer, int, int flag, int border, wxObject* userData )
715 {
716     return Add(sizer, FindEmptyCell(), wxDefaultSpan, flag, border, userData);
717 }
718 
Add(int width,int height,int,int flag,int border,wxObject * userData)719 wxSizerItem* wxGridBagSizer::Add( int width, int height, int, int flag, int border, wxObject* userData )
720 {
721     return Add(width, height, FindEmptyCell(), wxDefaultSpan, flag, border, userData);
722 }
723 
724 
725 
726 // The Insert nad Prepend base class virtuals that are not appropriate for
727 // this class and should not be used.  Their implementation in this class
728 // simply fails.
729 
Add(wxSizerItem *)730 wxSizerItem* wxGridBagSizer::Add( wxSizerItem * )
731 {
732     wxFAIL_MSG(wxT("Invalid Add form called."));
733     return NULL;
734 }
735 
Prepend(wxWindow *,int,int,int,wxObject *)736 wxSizerItem* wxGridBagSizer::Prepend( wxWindow *, int, int, int, wxObject*  )
737 {
738     wxFAIL_MSG(wxT("Prepend should not be used with wxGridBagSizer."));
739     return NULL;
740 }
741 
Prepend(wxSizer *,int,int,int,wxObject *)742 wxSizerItem* wxGridBagSizer::Prepend( wxSizer *, int, int, int, wxObject*  )
743 {
744     wxFAIL_MSG(wxT("Prepend should not be used with wxGridBagSizer."));
745     return NULL;
746 }
747 
Prepend(int,int,int,int,int,wxObject *)748 wxSizerItem* wxGridBagSizer::Prepend( int, int, int, int, int, wxObject*  )
749 {
750     wxFAIL_MSG(wxT("Prepend should not be used with wxGridBagSizer."));
751     return NULL;
752 }
753 
Prepend(wxSizerItem *)754 wxSizerItem* wxGridBagSizer::Prepend( wxSizerItem * )
755 {
756     wxFAIL_MSG(wxT("Prepend should not be used with wxGridBagSizer."));
757     return NULL;
758 }
759 
760 
Insert(size_t,wxWindow *,int,int,int,wxObject *)761 wxSizerItem* wxGridBagSizer::Insert( size_t, wxWindow *, int, int, int, wxObject*  )
762 {
763     wxFAIL_MSG(wxT("Insert should not be used with wxGridBagSizer."));
764     return NULL;
765 }
766 
Insert(size_t,wxSizer *,int,int,int,wxObject *)767 wxSizerItem* wxGridBagSizer::Insert( size_t, wxSizer *, int, int, int, wxObject*  )
768 {
769     wxFAIL_MSG(wxT("Insert should not be used with wxGridBagSizer."));
770     return NULL;
771 }
772 
Insert(size_t,int,int,int,int,int,wxObject *)773 wxSizerItem* wxGridBagSizer::Insert( size_t, int, int, int, int, int, wxObject*  )
774 {
775     wxFAIL_MSG(wxT("Insert should not be used with wxGridBagSizer."));
776     return NULL;
777 }
778 
Insert(size_t,wxSizerItem *)779 wxSizerItem* wxGridBagSizer::Insert( size_t, wxSizerItem * )
780 {
781     wxFAIL_MSG(wxT("Insert should not be used with wxGridBagSizer."));
782     return NULL;
783 }
784 
785 
786 //---------------------------------------------------------------------------
787 //---------------------------------------------------------------------------
788