]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
fix for temp file creation under Windows
[wxWidgets.git] / src / common / sizer.cpp
CommitLineData
5279a24d
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: sizer.cpp
1044a386 3// Purpose: provide new wxSizer class for layout
5279a24d
RR
4// Author: Robert Roebling and Robin Dunn
5// Modified by:
0c0d686f 6// Created:
5279a24d
RR
7// RCS-ID: $Id$
8// Copyright: (c) Robin Dunn, Dirk Holtwick and Robert Roebling
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
5279a24d 12#ifdef __GNUG__
c62ac5b6 13#pragma implementation "sizer.h"
5279a24d
RR
14#endif
15
77671fd2
VZ
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
5279a24d 23#include "wx/sizer.h"
61d514bb 24#include "wx/utils.h"
27ea1d8a 25#include "wx/statbox.h"
83edc0a5 26#include "wx/notebook.h"
5279a24d 27
0c0d686f
RD
28//---------------------------------------------------------------------------
29
30IMPLEMENT_ABSTRACT_CLASS(wxSizerItem, wxObject);
31IMPLEMENT_ABSTRACT_CLASS(wxSizer, wxObject);
f6bcfd97
BP
32IMPLEMENT_ABSTRACT_CLASS(wxGridSizer, wxSizer);
33IMPLEMENT_ABSTRACT_CLASS(wxFlexGridSizer, wxGridSizer);
0c0d686f 34IMPLEMENT_ABSTRACT_CLASS(wxBoxSizer, wxSizer);
1e6feb95 35#if wxUSE_STATBOX
0c0d686f 36IMPLEMENT_ABSTRACT_CLASS(wxStaticBoxSizer, wxBoxSizer);
1e6feb95 37#endif
60be2f47 38#if wxUSE_NOTEBOOK
83edc0a5 39IMPLEMENT_ABSTRACT_CLASS(wxNotebookSizer, wxSizer);
60be2f47 40#endif
0c0d686f 41
5279a24d 42//---------------------------------------------------------------------------
3417c2cd 43// wxSizerItem
5279a24d
RR
44//---------------------------------------------------------------------------
45
0c0d686f 46wxSizerItem::wxSizerItem( int width, int height, int option, int flag, int border, wxObject* userData )
5279a24d
RR
47{
48 m_window = (wxWindow *) NULL;
3417c2cd 49 m_sizer = (wxSizer *) NULL;
d597fcb7
RR
50 m_option = option;
51 m_border = border;
52 m_flag = flag;
0c0d686f
RD
53 m_userData = userData;
54
d597fcb7 55 // minimal size is the initial size
5279a24d 56 m_minSize.x = width;
c62ac5b6 57 m_minSize.y = height;
0c0d686f 58
be2577e4
RD
59 SetRatio(width, height);
60
d597fcb7
RR
61 // size is set directly
62 m_size = m_minSize;
5279a24d
RR
63}
64
0c0d686f 65wxSizerItem::wxSizerItem( wxWindow *window, int option, int flag, int border, wxObject* userData )
5279a24d
RR
66{
67 m_window = window;
3417c2cd 68 m_sizer = (wxSizer *) NULL;
5279a24d 69 m_option = option;
d597fcb7
RR
70 m_border = border;
71 m_flag = flag;
0c0d686f
RD
72 m_userData = userData;
73
d597fcb7
RR
74 // minimal size is the initial size
75 m_minSize = window->GetSize();
0c0d686f 76
be2577e4
RD
77 // aspect ratio calculated from initial size
78 SetRatio(m_minSize);
79
d597fcb7
RR
80 // size is calculated later
81 // m_size = ...
5279a24d
RR
82}
83
0c0d686f 84wxSizerItem::wxSizerItem( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
5279a24d
RR
85{
86 m_window = (wxWindow *) NULL;
87 m_sizer = sizer;
5279a24d 88 m_option = option;
d597fcb7
RR
89 m_border = border;
90 m_flag = flag;
0c0d686f
RD
91 m_userData = userData;
92
d597fcb7
RR
93 // minimal size is calculated later
94 // m_minSize = ...
be2577e4 95 m_ratio = 0;
0c0d686f 96
d597fcb7
RR
97 // size is calculated later
98 // m_size = ...
5279a24d
RR
99}
100
0c0d686f
RD
101wxSizerItem::~wxSizerItem()
102{
103 if (m_userData)
104 delete m_userData;
105 if (m_sizer)
106 delete m_sizer;
107}
108
109
3417c2cd 110wxSize wxSizerItem::GetSize()
5279a24d 111{
d597fcb7 112 wxSize ret;
3417c2cd 113 if (IsSizer())
d597fcb7
RR
114 ret = m_sizer->GetSize();
115 else
c62ac5b6 116 if (IsWindow())
d597fcb7
RR
117 ret = m_window->GetSize();
118 else ret = m_size;
0c0d686f 119
d597fcb7
RR
120 if (m_flag & wxWEST)
121 ret.x += m_border;
122 if (m_flag & wxEAST)
123 ret.x += m_border;
124 if (m_flag & wxNORTH)
125 ret.y += m_border;
126 if (m_flag & wxSOUTH)
127 ret.y += m_border;
0c0d686f 128
d597fcb7 129 return ret;
5279a24d
RR
130}
131
3417c2cd 132wxSize wxSizerItem::CalcMin()
c62ac5b6 133{
d597fcb7 134 wxSize ret;
3417c2cd 135 if (IsSizer())
be2577e4 136 {
f6bcfd97 137 ret = m_sizer->GetMinSize();
d13d8d4e 138
be2577e4
RD
139 // if we have to preserve aspect ratio _AND_ this is
140 // the first-time calculation, consider ret to be initial size
d13d8d4e
VZ
141 if ((m_flag & wxSHAPED) && !m_ratio)
142 SetRatio(ret);
be2577e4 143 }
d597fcb7 144 else
d13d8d4e
VZ
145 {
146 if ( IsWindow() && (m_flag & wxADJUST_MINSIZE) )
147 {
148 // check if the best (minimal, in fact) window size hadn't changed
149 // by chance: this may happen for, e.g. static text if its label
150 // changed
151 wxSize size = m_window->GetBestSize();
152 if ( size.x > m_minSize.x )
153 m_minSize.x = size.x;
154 if ( size.y > m_minSize.y )
155 m_minSize.y = size.y;
156 }
157
158 ret = m_minSize;
159 }
0c0d686f 160
d597fcb7
RR
161 if (m_flag & wxWEST)
162 ret.x += m_border;
163 if (m_flag & wxEAST)
164 ret.x += m_border;
165 if (m_flag & wxNORTH)
166 ret.y += m_border;
167 if (m_flag & wxSOUTH)
168 ret.y += m_border;
0c0d686f 169
d597fcb7 170 return ret;
c62ac5b6
RR
171}
172
3417c2cd 173void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
c62ac5b6 174{
cdddaeea 175 if (m_flag & wxSHAPED)
d597fcb7 176 {
be2577e4
RD
177 // adjust aspect ratio
178 int rwidth = (int) (size.y * m_ratio);
cdddaeea
VZ
179 if (rwidth > size.x)
180 {
be2577e4
RD
181 // fit horizontally
182 int rheight = (int) (size.x / m_ratio);
183 // add vertical space
184 if (m_flag & wxALIGN_CENTER_VERTICAL)
185 pos.y += (size.y - rheight) / 2;
186 else if (m_flag & wxALIGN_BOTTOM)
187 pos.y += (size.y - rheight);
188 // use reduced dimensions
189 size.y =rheight;
cdddaeea
VZ
190 }
191 else if (rwidth < size.x)
192 {
be2577e4
RD
193 // add horizontal space
194 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
195 pos.x += (size.x - rwidth) / 2;
196 else if (m_flag & wxALIGN_RIGHT)
197 pos.x += (size.x - rwidth);
198 size.x = rwidth;
199 }
200 }
33ac7e6f 201
cdddaeea
VZ
202 // This is what GetPosition() returns. Since we calculate
203 // borders afterwards, GetPosition() will be the left/top
204 // corner of the surrounding border.
205 m_pos = pos;
206
207 if (m_flag & wxWEST)
208 {
209 pos.x += m_border;
210 size.x -= m_border;
211 }
212 if (m_flag & wxEAST)
213 {
214 size.x -= m_border;
215 }
216 if (m_flag & wxNORTH)
217 {
218 pos.y += m_border;
219 size.y -= m_border;
220 }
221 if (m_flag & wxSOUTH)
222 {
223 size.y -= m_border;
224 }
0c0d686f 225
3417c2cd 226 if (IsSizer())
c62ac5b6 227 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
0c0d686f 228
c62ac5b6 229 if (IsWindow())
b919f007 230 m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
d597fcb7
RR
231
232 m_size = size;
c62ac5b6
RR
233}
234
84f7908b
RR
235void wxSizerItem::DeleteWindows()
236{
237 if (m_window)
238 m_window->Destroy();
239
240 if (m_sizer)
241 m_sizer->DeleteWindows();
242}
243
3417c2cd 244bool wxSizerItem::IsWindow()
5279a24d
RR
245{
246 return (m_window != NULL);
247}
248
3417c2cd 249bool wxSizerItem::IsSizer()
5279a24d
RR
250{
251 return (m_sizer != NULL);
252}
253
3417c2cd 254bool wxSizerItem::IsSpacer()
5279a24d
RR
255{
256 return (m_window == NULL) && (m_sizer == NULL);
257}
258
259//---------------------------------------------------------------------------
3417c2cd 260// wxSizer
5279a24d
RR
261//---------------------------------------------------------------------------
262
3417c2cd 263wxSizer::wxSizer()
5279a24d
RR
264{
265 m_children.DeleteContents( TRUE );
f6bcfd97
BP
266 m_minSize.x = 0;
267 m_minSize.y = 0;
5279a24d
RR
268}
269
3417c2cd 270wxSizer::~wxSizer()
5279a24d
RR
271{
272}
0c0d686f
RD
273
274void wxSizer::Add( wxWindow *window, int option, int flag, int border, wxObject* userData )
5279a24d 275{
0c0d686f 276 m_children.Append( new wxSizerItem( window, option, flag, border, userData ) );
5279a24d
RR
277}
278
0c0d686f 279void wxSizer::Add( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
5279a24d 280{
0c0d686f 281 m_children.Append( new wxSizerItem( sizer, option, flag, border, userData ) );
5279a24d
RR
282}
283
0c0d686f 284void wxSizer::Add( int width, int height, int option, int flag, int border, wxObject* userData )
5279a24d 285{
0c0d686f 286 m_children.Append( new wxSizerItem( width, height, option, flag, border, userData ) );
5279a24d
RR
287}
288
0c0d686f 289void wxSizer::Prepend( wxWindow *window, int option, int flag, int border, wxObject* userData )
42b4e99e 290{
0c0d686f 291 m_children.Insert( new wxSizerItem( window, option, flag, border, userData ) );
42b4e99e
RR
292}
293
0c0d686f 294void wxSizer::Prepend( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
42b4e99e 295{
0c0d686f 296 m_children.Insert( new wxSizerItem( sizer, option, flag, border, userData ) );
42b4e99e
RR
297}
298
0c0d686f 299void wxSizer::Prepend( int width, int height, int option, int flag, int border, wxObject* userData )
42b4e99e 300{
0c0d686f 301 m_children.Insert( new wxSizerItem( width, height, option, flag, border, userData ) );
f35aa3da
RR
302}
303
304void wxSizer::Insert( int before, wxWindow *window, int option, int flag, int border, wxObject* userData )
305{
306 m_children.Insert( before, new wxSizerItem( window, option, flag, border, userData ) );
307}
308
309void wxSizer::Insert( int before, wxSizer *sizer, int option, int flag, int border, wxObject* userData )
310{
311 m_children.Insert( before, new wxSizerItem( sizer, option, flag, border, userData ) );
312}
313
314void wxSizer::Insert( int before, int width, int height, int option, int flag, int border, wxObject* userData )
315{
316 m_children.Insert( before, new wxSizerItem( width, height, option, flag, border, userData ) );
42b4e99e
RR
317}
318
319bool wxSizer::Remove( wxWindow *window )
320{
321 wxASSERT( window );
0c0d686f 322
42b4e99e
RR
323 wxNode *node = m_children.First();
324 while (node)
325 {
326 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
327 if (item->GetWindow() == window)
328 {
42b4e99e 329 m_children.DeleteNode( node );
3ca6a5f0
BP
330 return TRUE;
331 }
42b4e99e
RR
332 node = node->Next();
333 }
0c0d686f 334
42b4e99e
RR
335 return FALSE;
336}
337
338bool wxSizer::Remove( wxSizer *sizer )
339{
340 wxASSERT( sizer );
0c0d686f 341
42b4e99e
RR
342 wxNode *node = m_children.First();
343 while (node)
344 {
345 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
346 if (item->GetSizer() == sizer)
347 {
42b4e99e 348 m_children.DeleteNode( node );
3ca6a5f0
BP
349 return TRUE;
350 }
42b4e99e
RR
351 node = node->Next();
352 }
0c0d686f 353
42b4e99e
RR
354 return FALSE;
355}
356
357bool wxSizer::Remove( int pos )
358{
359 wxNode *node = m_children.Nth( pos );
360 if (!node) return FALSE;
0c0d686f 361
42b4e99e 362 m_children.DeleteNode( node );
0c0d686f 363
42b4e99e
RR
364 return TRUE;
365}
0c0d686f 366
84f7908b
RR
367void wxSizer::Clear( bool delete_windows )
368{
369 if (delete_windows)
370 DeleteWindows();
371
372 m_children.Clear();
373}
374
375void wxSizer::DeleteWindows()
376{
377 wxNode *node = m_children.First();
378 while (node)
379 {
380 wxSizerItem *item = (wxSizerItem*)node->Data();
381 item->DeleteWindows();
382 node = node->Next();
383 }
384}
385
3417c2cd 386void wxSizer::Fit( wxWindow *window )
5279a24d 387{
9ef2e675
GT
388 wxSize size;
389 if (window->IsTopLevel())
390 size = FitSize( window );
391 else
392 size = GetMinWindowSize( window );
393
65ba4113 394 window->SetSize( size );
5279a24d
RR
395}
396
3417c2cd 397void wxSizer::Layout()
c62ac5b6 398{
42b4e99e 399 CalcMin();
c62ac5b6
RR
400 RecalcSizes();
401}
402
3417c2cd 403void wxSizer::SetSizeHints( wxWindow *window )
5279a24d 404{
65ba4113 405 wxSize size = FitSize( window );
5279a24d
RR
406 window->SetSizeHints( size.x, size.y );
407}
408
33ac7e6f 409wxSize wxSizer::GetMaxWindowSize( wxWindow *WXUNUSED(window) )
65ba4113 410{
ef397583
GT
411 wxRect rect = wxGetClientDisplayRect();
412 wxSize sizeMax (rect.width,rect.height);
413
e6ba3fd4
JS
414 // Sorry, but this bit is wrong -- it makes a window that should just be
415 // able to fit onto the screen, not fit on the screen. -- JACS
416#if 0
f98de448
RD
417 // Make the max size a bit smaller than the visible portion of
418 // the screen. A window which takes the entire screen doesn't
ef397583 419 // look very nice either
65ba4113
GT
420 sizeMax.x *= 9;
421 sizeMax.x /= 10;
422
423 sizeMax.y *= 9;
424 sizeMax.y /= 10;
e6ba3fd4 425#endif
65ba4113
GT
426
427 return sizeMax;
428}
429
3417c2cd 430wxSize wxSizer::GetMinWindowSize( wxWindow *window )
5279a24d 431{
77671fd2 432 wxSize minSize( GetMinSize() );
5279a24d
RR
433 wxSize size( window->GetSize() );
434 wxSize client_size( window->GetClientSize() );
77671fd2 435 return wxSize( minSize.x+size.x-client_size.x,
0c0d686f 436 minSize.y+size.y-client_size.y );
5279a24d
RR
437}
438
65ba4113
GT
439// Return a window size that will fit within the screens dimensions
440wxSize wxSizer::FitSize( wxWindow *window )
441{
442 wxSize size = GetMinWindowSize( window );
443 wxSize sizeMax = GetMaxWindowSize( window );
444
445 if ( size.x > sizeMax.x )
446 size.x = sizeMax.x;
447 if ( size.y > sizeMax.y )
448 size.y = sizeMax.y;
449
450 return size;
451}
452
3417c2cd 453void wxSizer::SetDimension( int x, int y, int width, int height )
5279a24d
RR
454{
455 m_position.x = x;
456 m_position.y = y;
457 m_size.x = width;
458 m_size.y = height;
42b4e99e 459 CalcMin();
5279a24d
RR
460 RecalcSizes();
461}
462
f6bcfd97 463wxSize wxSizer::GetMinSize()
3ca6a5f0 464{
f6bcfd97
BP
465 wxSize ret( CalcMin() );
466 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
467 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
3ca6a5f0 468 return ret;
f6bcfd97
BP
469}
470
471void wxSizer::DoSetMinSize( int width, int height )
472{
473 m_minSize.x = width;
474 m_minSize.y = height;
475}
476
477bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
478{
479 wxASSERT( window );
480
481 wxNode *node = m_children.First();
482 while (node)
483 {
484 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
485 if (item->GetWindow() == window)
486 {
f6bcfd97 487 item->SetInitSize( width, height );
3ca6a5f0
BP
488 return TRUE;
489 }
f6bcfd97
BP
490 node = node->Next();
491 }
492
493 node = m_children.First();
494 while (node)
495 {
496 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
497 if (item->GetSizer())
498 {
f6bcfd97
BP
499 /* It's a sizer, so lets search recursively. */
500 if (item->GetSizer()->DoSetItemMinSize( window, width, height ))
501 {
502 /* A child sizer found the requested windw, exit. */
3ca6a5f0 503 return TRUE;
f6bcfd97 504 }
3ca6a5f0 505 }
f6bcfd97
BP
506 node = node->Next();
507 }
508
509 return FALSE;
510}
511
512bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
513{
514 wxASSERT( sizer );
515
516 wxNode *node = m_children.First();
517 while (node)
518 {
519 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
520 if (item->GetSizer() == sizer)
521 {
f6bcfd97 522 item->GetSizer()->DoSetMinSize( width, height );
3ca6a5f0
BP
523 return TRUE;
524 }
f6bcfd97
BP
525 node = node->Next();
526 }
527
528 node = m_children.First();
529 while (node)
530 {
531 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
532 if (item->GetSizer())
533 {
f6bcfd97
BP
534 /* It's a sizer, so lets search recursively. */
535 if (item->GetSizer()->DoSetItemMinSize( sizer, width, height ))
536 {
537 /* A child sizer found the requested windw, exit. */
3ca6a5f0 538 return TRUE;
f6bcfd97 539 }
3ca6a5f0 540 }
f6bcfd97
BP
541 node = node->Next();
542 }
543
544 return FALSE;
545}
546
547bool wxSizer::DoSetItemMinSize( int pos, int width, int height )
548{
549 wxNode *node = m_children.Nth( pos );
550 if (!node) return FALSE;
551
552 wxSizerItem *item = (wxSizerItem*) node->Data();
553 if (item->GetSizer())
554 {
555 /* Sizers contains the minimal size in them, if not calculated ... */
556 item->GetSizer()->DoSetMinSize( width, height );
557 }
558 else
559 {
3ca6a5f0 560 /* ... whereas the minimal size of spacers and windows in stored
f6bcfd97
BP
561 in the item */
562 item->SetInitSize( width, height );
563 }
564
565 return TRUE;
566}
567
568//---------------------------------------------------------------------------
569// wxGridSizer
570//---------------------------------------------------------------------------
571
572wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
573{
574 m_rows = rows;
575 m_cols = cols;
576 m_vgap = vgap;
577 m_hgap = hgap;
578}
579
580wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
581{
582 m_rows = 0;
583 m_cols = cols;
584 m_vgap = vgap;
585 m_hgap = hgap;
586}
587
588void wxGridSizer::RecalcSizes()
589{
590 if (m_children.GetCount() == 0)
591 return;
592
593 int nitems = m_children.GetCount();
594 int nrows = m_rows;
595 int ncols = m_cols;
596
597 if (ncols > 0)
598 nrows = (nitems + ncols-1) / ncols;
599 else
600 ncols = (nitems + nrows-1) / nrows;
601
602 wxSize sz( GetSize() );
603 wxPoint pt( GetPosition() );
3ca6a5f0
BP
604
605 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
606 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
f6bcfd97
BP
607
608 int x = pt.x;
609 for (int c = 0; c < ncols; c++)
610 {
611 int y = pt.y;
612 for (int r = 0; r < nrows; r++)
613 {
614 int i = r * ncols + c;
615 if (i < nitems)
616 {
617 wxNode *node = m_children.Nth( i );
618 wxASSERT( node );
3ca6a5f0 619
f6bcfd97
BP
620 SetItemBounds( (wxSizerItem*) node->Data(), x, y, w, h);
621 }
622 y = y + h + m_vgap;
623 }
624 x = x + w + m_hgap;
625 }
626}
627
628wxSize wxGridSizer::CalcMin()
629{
630 if (m_children.GetCount() == 0)
631 return wxSize(10,10);
632
633 int nitems = m_children.GetCount();
634 int nrows = m_rows;
635 int ncols = m_cols;
636
637 if (ncols > 0)
638 nrows = (nitems + ncols-1) / ncols;
639 else
640 ncols = (nitems + nrows-1) / nrows;
641
642 /* Find the max width and height for any component */
643 int w = 0;
644 int h = 0;
3ca6a5f0 645
f6bcfd97
BP
646 wxNode *node = m_children.First();
647 while (node)
648 {
649 wxSizerItem *item = (wxSizerItem*)node->Data();
650 wxSize sz( item->CalcMin() );
651 w = wxMax( w, sz.x );
652 h = wxMax( h, sz.y );
3ca6a5f0 653
f6bcfd97
BP
654 node = node->Next();
655 }
3ca6a5f0 656
f6bcfd97
BP
657 return wxSize(ncols * w + (ncols-1) * m_hgap,
658 nrows * h + (nrows-1) * m_vgap);
659}
660
661void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
662{
663 wxPoint pt( x,y );
664 wxSize sz( item->CalcMin() );
665 int flag = item->GetFlag();
666
667 if ((flag & wxEXPAND) || (flag & wxSHAPED))
668 {
669 sz = wxSize(w, h);
670 }
671 else
672 {
673 if (flag & wxALIGN_CENTER_HORIZONTAL)
674 {
675 pt.x = x + (w - sz.x) / 2;
676 }
677 else if (flag & wxALIGN_RIGHT)
678 {
679 pt.x = x + (w - sz.x);
680 }
3ca6a5f0 681
f6bcfd97
BP
682 if (flag & wxALIGN_CENTER_VERTICAL)
683 {
684 pt.y = y + (h - sz.y) / 2;
685 }
686 else if (flag & wxALIGN_BOTTOM)
687 {
688 pt.y = y + (h - sz.y);
689 }
690 }
3ca6a5f0 691
f6bcfd97
BP
692 item->SetDimension(pt, sz);
693}
694
695//---------------------------------------------------------------------------
696// wxFlexGridSizer
697//---------------------------------------------------------------------------
698
699wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
700 : wxGridSizer( rows, cols, vgap, hgap )
3ca6a5f0 701{
f6bcfd97
BP
702 m_rowHeights = (int*) NULL;
703 m_colWidths = (int*) NULL;
704}
705
706wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
3ca6a5f0
BP
707 : wxGridSizer( cols, vgap, hgap )
708{
f6bcfd97
BP
709 m_rowHeights = (int*) NULL;
710 m_colWidths = (int*) NULL;
711}
3ca6a5f0 712
f6bcfd97
BP
713wxFlexGridSizer::~wxFlexGridSizer()
714{
715 if (m_rowHeights)
716 delete[] m_rowHeights;
717 if (m_colWidths)
718 delete[] m_colWidths;
719}
720
721void wxFlexGridSizer::CreateArrays()
722{
723 if (m_rowHeights)
724 delete[] m_rowHeights;
725 if (m_colWidths)
726 delete[] m_colWidths;
3ca6a5f0 727
f6bcfd97
BP
728 if (m_children.GetCount() == 0)
729 return;
3ca6a5f0 730
f6bcfd97
BP
731 int nitems = m_children.GetCount();
732 int nrows = m_rows;
733 int ncols = m_cols;
734
735 if (ncols > 0)
736 nrows = (nitems + ncols-1) / ncols;
737 else
738 ncols = (nitems + nrows-1) / nrows;
739
740 m_rowHeights = new int[nrows];
741 m_colWidths = new int[ncols];
3ca6a5f0 742
f6bcfd97
BP
743 for (int col = 0; col < ncols; col++)
744 m_colWidths[ col ] = 0;
745 for (int row = 0; row < nrows; row++)
746 m_rowHeights[ row ] = 0;
747}
748
749void wxFlexGridSizer::RecalcSizes()
750{
751 if (m_children.GetCount() == 0)
752 return;
753
754 int nitems = m_children.GetCount();
755 int nrows = m_rows;
756 int ncols = m_cols;
757
758 if (ncols > 0)
759 nrows = (nitems + ncols-1) / ncols;
760 else
761 ncols = (nitems + nrows-1) / nrows;
762
763 wxSize sz( GetSize() );
764 wxSize minsz( CalcMin() );
765 wxPoint pt( GetPosition() );
766 int delta;
767 size_t idx;
768
769 if ((m_growableRows.GetCount() > 0) && (sz.y > minsz.y))
770 {
771 delta = (sz.y - minsz.y) / m_growableRows.GetCount();
772 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
773 m_rowHeights[ m_growableRows[idx] ] += delta;
774 }
3ca6a5f0 775
f6bcfd97
BP
776 if ((m_growableCols.GetCount() > 0) && (sz.x > minsz.x))
777 {
778 delta = (sz.x - minsz.x) / m_growableCols.GetCount();
779 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
780 m_colWidths[ m_growableCols[idx] ] += delta;
781 }
3ca6a5f0 782
f6bcfd97
BP
783 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
784
785 int x = pt.x;
786 for (int c = 0; c < ncols; c++)
787 {
788 int y = pt.y;
789 for (int r = 0; r < nrows; r++)
790 {
791 int i = r * ncols + c;
792 if (i < nitems)
793 {
794 wxNode *node = m_children.Nth( i );
795 wxASSERT( node );
3ca6a5f0 796
f6bcfd97
BP
797 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
798 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
3ca6a5f0 799
f6bcfd97
BP
800 SetItemBounds( (wxSizerItem*) node->Data(), x, y, w, h);
801 }
802 y = y + m_rowHeights[r] + m_vgap;
803 }
804 x = x + m_colWidths[c] + m_hgap;
805 }
806}
807
808wxSize wxFlexGridSizer::CalcMin()
809{
810 if (m_children.GetCount() == 0)
811 return wxSize(10,10);
812
813 int nitems = m_children.GetCount();
814 int nrows = m_rows;
815 int ncols = m_cols;
816
817 if (ncols > 0)
818 nrows = (nitems + ncols-1) / ncols;
819 else
820 ncols = (nitems + nrows-1) / nrows;
821
822 CreateArrays();
3ca6a5f0 823
f6bcfd97
BP
824 int col;
825 int row;
3ca6a5f0 826
f6bcfd97
BP
827 int i = 0;
828 wxNode *node = m_children.First();
829 while (node)
830 {
831 wxSizerItem *item = (wxSizerItem*)node->Data();
832 wxSize sz( item->CalcMin() );
833 row = i / ncols;
834 col = i % ncols;
835 m_rowHeights[ row ] = wxMax( sz.y, m_rowHeights[ row ] );
836 m_colWidths[ col ] = wxMax( sz.x, m_colWidths[ col ] );
3ca6a5f0 837
f6bcfd97
BP
838 node = node->Next();
839 i++;
840 }
3ca6a5f0 841
f6bcfd97
BP
842 int width = 0;
843 for (col = 0; col < ncols; col++)
844 width += m_colWidths[ col ];
3ca6a5f0 845
f6bcfd97
BP
846 int height = 0;
847 for (row = 0; row < nrows; row++)
848 height += m_rowHeights[ row ];
3ca6a5f0 849
f6bcfd97
BP
850 return wxSize( width + (ncols-1) * m_hgap,
851 height + (nrows-1) * m_vgap);
852}
853
854void wxFlexGridSizer::AddGrowableRow( size_t idx )
855{
856 m_growableRows.Add( idx );
857}
858
3ca6a5f0 859void wxFlexGridSizer::RemoveGrowableRow( size_t WXUNUSED(idx) )
f6bcfd97
BP
860{
861}
862
863void wxFlexGridSizer::AddGrowableCol( size_t idx )
864{
865 m_growableCols.Add( idx );
866}
867
3ca6a5f0 868void wxFlexGridSizer::RemoveGrowableCol( size_t WXUNUSED(idx) )
f6bcfd97
BP
869{
870}
871
c62ac5b6 872//---------------------------------------------------------------------------
92afa2b1 873// wxBoxSizer
61d514bb
RR
874//---------------------------------------------------------------------------
875
92afa2b1 876wxBoxSizer::wxBoxSizer( int orient )
61d514bb
RR
877{
878 m_orient = orient;
879}
880
92afa2b1 881void wxBoxSizer::RecalcSizes()
61d514bb
RR
882{
883 if (m_children.GetCount() == 0)
61d514bb 884 return;
0c0d686f 885
61d514bb
RR
886 int delta = 0;
887 int extra = 0;
888 if (m_stretchable)
889 {
890 if (m_orient == wxHORIZONTAL)
891 {
892 delta = (m_size.x - m_fixedWidth) / m_stretchable;
893 extra = (m_size.x - m_fixedWidth) % m_stretchable;
3ca6a5f0
BP
894 }
895 else
896 {
61d514bb
RR
897 delta = (m_size.y - m_fixedHeight) / m_stretchable;
898 extra = (m_size.y - m_fixedHeight) % m_stretchable;
3ca6a5f0 899 }
61d514bb 900 }
0c0d686f 901
61d514bb 902 wxPoint pt( m_position );
0c0d686f 903
61d514bb
RR
904 wxNode *node = m_children.GetFirst();
905 while (node)
906 {
3417c2cd 907 wxSizerItem *item = (wxSizerItem*) node->Data();
61d514bb 908
3ca6a5f0
BP
909 int weight = 1;
910 if (item->GetOption())
911 weight = item->GetOption();
912
913 wxSize size( item->CalcMin() );
914
915 if (m_orient == wxVERTICAL)
916 {
917 wxCoord height = size.y;
918 if (item->GetOption())
919 {
920 height = (delta * weight) + extra;
921 extra = 0; // only the first item will get the remainder as extra size
922 }
923
924 wxPoint child_pos( pt );
925 wxSize child_size( wxSize( size.x, height) );
926
927 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
928 child_size.x = m_size.x;
929 else if (item->GetFlag() & wxALIGN_RIGHT)
930 child_pos.x += m_size.x - size.x;
931 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
932 // XXX wxCENTER is added for backward compatibility;
933 // wxALIGN_CENTER should be used in new code
934 child_pos.x += (m_size.x - size.x) / 2;
935
936 item->SetDimension( child_pos, child_size );
937
938 pt.y += height;
939 }
940 else
941 {
942 wxCoord width = size.x;
943 if (item->GetOption())
944 {
945 width = (delta * weight) + extra;
946 extra = 0; // only the first item will get the remainder as extra size
947 }
948
949 wxPoint child_pos( pt );
950 wxSize child_size( wxSize(width, size.y) );
951
952 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
953 child_size.y = m_size.y;
954 else if (item->GetFlag() & wxALIGN_BOTTOM)
955 child_pos.y += m_size.y - size.y;
956 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
957 // XXX wxCENTER is added for backward compatibility;
958 // wxALIGN_CENTER should be used in new code
959 child_pos.y += (m_size.y - size.y) / 2;
960
961 item->SetDimension( child_pos, child_size );
962
963 pt.x += width;
964 }
965
966 node = node->Next();
61d514bb
RR
967 }
968}
969
92afa2b1 970wxSize wxBoxSizer::CalcMin()
61d514bb
RR
971{
972 if (m_children.GetCount() == 0)
c7a9fa36 973 return wxSize(10,10);
0c0d686f 974
61d514bb
RR
975 m_stretchable = 0;
976 m_minWidth = 0;
977 m_minHeight = 0;
978 m_fixedWidth = 0;
979 m_fixedHeight = 0;
0c0d686f 980
f98de448
RD
981 // Find how long each stretch unit needs to be
982 int stretchSize = 1;
61d514bb
RR
983 wxNode *node = m_children.GetFirst();
984 while (node)
f98de448
RD
985 {
986 wxSizerItem *item = (wxSizerItem*) node->Data();
987 if (item->GetOption() != 0)
988 {
989 int stretch = item->GetOption();
990 wxSize size( item->CalcMin() );
991 int sizePerStretch;
992 // Integer division rounded up is (a + b - 1) / b
993 if (m_orient == wxHORIZONTAL)
994 sizePerStretch = ( size.x + stretch - 1 ) / stretch;
995 else
996 sizePerStretch = ( size.y + stretch - 1 ) / stretch;
997 if (sizePerStretch > stretchSize)
998 stretchSize = sizePerStretch;
999 }
1000 node = node->Next();
1001 }
1002 // Calculate overall minimum size
1003 node = m_children.GetFirst();
1004 while (node)
61d514bb 1005 {
3417c2cd 1006 wxSizerItem *item = (wxSizerItem*) node->Data();
0c0d686f 1007
aa21b509 1008 m_stretchable += item->GetOption();
33ac7e6f 1009
3ca6a5f0 1010 wxSize size( item->CalcMin() );
f98de448
RD
1011 if (item->GetOption() != 0)
1012 {
1013 if (m_orient == wxHORIZONTAL)
1014 size.x = stretchSize * item->GetOption();
1015 else
1016 size.y = stretchSize * item->GetOption();
1017 }
3ca6a5f0
BP
1018
1019 if (m_orient == wxHORIZONTAL)
1020 {
aa21b509 1021 m_minWidth += size.x;
3ca6a5f0
BP
1022 m_minHeight = wxMax( m_minHeight, size.y );
1023 }
1024 else
1025 {
aa21b509 1026 m_minHeight += size.y;
3ca6a5f0
BP
1027 m_minWidth = wxMax( m_minWidth, size.x );
1028 }
1029
aa21b509 1030 if (item->GetOption() == 0)
3ca6a5f0
BP
1031 {
1032 if (m_orient == wxVERTICAL)
1033 {
1034 m_fixedHeight += size.y;
1035 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1036 }
1037 else
33ac7e6f 1038 {
3ca6a5f0
BP
1039 m_fixedWidth += size.x;
1040 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1041 }
1042 }
1043
1044 node = node->Next();
61d514bb 1045 }
0c0d686f 1046
61d514bb
RR
1047 return wxSize( m_minWidth, m_minHeight );
1048}
27ea1d8a
RR
1049
1050//---------------------------------------------------------------------------
1051// wxStaticBoxSizer
1052//---------------------------------------------------------------------------
1053
1e6feb95
VZ
1054#if wxUSE_STATBOX
1055
27ea1d8a 1056wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
84028727 1057 : wxBoxSizer( orient )
27ea1d8a 1058{
223d09f6 1059 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
0c0d686f 1060
27ea1d8a
RR
1061 m_staticBox = box;
1062}
0c0d686f 1063
84028727
VZ
1064static void GetStaticBoxBorders(wxStaticBox *box,
1065 int *borderTop, int *borderOther)
1066{
1067 // this has to be done platform by platform as there is no way to
1068 // guess the thickness of a wxStaticBox border
1069#ifdef __WXGTK__
1070 if ( box->GetLabel().IsEmpty() )
1071 *borderTop = 5;
1072 else
1073#endif // __WXGTK__
1074 *borderTop = 15;
33ac7e6f 1075 (void)box;
84028727
VZ
1076 *borderOther = 5;
1077}
1078
27ea1d8a
RR
1079void wxStaticBoxSizer::RecalcSizes()
1080{
84028727
VZ
1081 int top_border, other_border;
1082 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1083
1084 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1085
27ea1d8a
RR
1086 wxPoint old_pos( m_position );
1087 m_position.x += other_border;
1088 m_position.y += top_border;
1089 wxSize old_size( m_size );
1090 m_size.x -= 2*other_border;
1091 m_size.y -= top_border + other_border;
0c0d686f 1092
27ea1d8a 1093 wxBoxSizer::RecalcSizes();
0c0d686f 1094
27ea1d8a
RR
1095 m_position = old_pos;
1096 m_size = old_size;
1097}
1098
1099wxSize wxStaticBoxSizer::CalcMin()
1100{
84028727
VZ
1101 int top_border, other_border;
1102 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1103
27ea1d8a 1104 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1105 ret.x += 2*other_border;
27ea1d8a 1106 ret.y += other_border + top_border;
0c0d686f 1107
27ea1d8a
RR
1108 return ret;
1109}
83edc0a5 1110
1e6feb95
VZ
1111#endif // wxUSE_STATBOX
1112
83edc0a5
RR
1113//---------------------------------------------------------------------------
1114// wxNotebookSizer
1115//---------------------------------------------------------------------------
1116
60be2f47
VS
1117#if wxUSE_NOTEBOOK
1118
83edc0a5
RR
1119wxNotebookSizer::wxNotebookSizer( wxNotebook *nb )
1120{
1121 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a notebook") );
3ca6a5f0 1122
83edc0a5
RR
1123 m_notebook = nb;
1124}
1125
1126void wxNotebookSizer::RecalcSizes()
1127{
1128 m_notebook->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1129}
1130
1131wxSize wxNotebookSizer::CalcMin()
1132{
1e6feb95
VZ
1133 wxSize sizeBorder = m_notebook->CalcSizeFromPage(wxSize(0, 0));
1134
1135 sizeBorder.x += 5;
1136 sizeBorder.y += 5;
3ca6a5f0 1137
83edc0a5 1138 if (m_notebook->GetChildren().GetCount() == 0)
1e6feb95
VZ
1139 {
1140 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1141 }
83edc0a5
RR
1142
1143 int maxX = 0;
1144 int maxY = 0;
1145
1146 wxWindowList::Node *node = m_notebook->GetChildren().GetFirst();
1147 while (node)
1148 {
1149 wxWindow *item = node->GetData();
3ca6a5f0
BP
1150 wxSizer *itemsizer = item->GetSizer();
1151
1152 if (itemsizer)
1153 {
83edc0a5 1154 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1155
1e6feb95
VZ
1156 if (subsize.x > maxX)
1157 maxX = subsize.x;
1158 if (subsize.y > maxY)
1159 maxY = subsize.y;
3ca6a5f0
BP
1160 }
1161
1162 node = node->GetNext();
83edc0a5
RR
1163 }
1164
1e6feb95 1165 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
1166}
1167
60be2f47 1168#endif // wxUSE_NOTEBOOK