]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
Added EVT_COMMAND_TREE_ITEM_MENU
[wxWidgets.git] / src / common / sizer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: sizer.cpp
3 // Purpose: provide new wxSizer class for layout
4 // Author: Robert Roebling and Robin Dunn, contributions by
5 // Dirk Holtwick, Ron Lee
6 // Modified by: Ron Lee
7 // Created:
8 // RCS-ID: $Id$
9 // Copyright: (c) Robin Dunn, Robert Roebling
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma implementation "sizer.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #include "wx/sizer.h"
25 #include "wx/utils.h"
26 #include "wx/statbox.h"
27 #include "wx/settings.h"
28 #include "wx/listimpl.cpp"
29 #if WXWIN_COMPATIBILITY_2_4
30 #include "wx/notebook.h"
31 #endif
32
33 #ifdef __WXMAC__
34 # include "wx/mac/uma.h"
35 #endif
36
37 //---------------------------------------------------------------------------
38
39 IMPLEMENT_CLASS(wxSizerItem, wxObject)
40 IMPLEMENT_CLASS(wxSizer, wxObject)
41 IMPLEMENT_CLASS(wxGridSizer, wxSizer)
42 IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
43 IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
44 #if wxUSE_STATBOX
45 IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
46 #endif
47 IMPLEMENT_CLASS(wxStdDialogButtonSizer, wxBoxSizer)
48
49 WX_DEFINE_EXPORTED_LIST( wxSizerItemList );
50
51 /*
52 TODO PROPERTIES
53 sizeritem
54 object
55 object_ref
56 minsize
57 option
58 flag
59 border
60 spacer
61 option
62 flag
63 borfder
64 boxsizer
65 orient
66 staticboxsizer
67 orient
68 label
69 gridsizer
70 rows
71 cols
72 vgap
73 hgap
74 flexgridsizer
75 rows
76 cols
77 vgap
78 hgap
79 growablerows
80 growablecols
81 minsize
82 */
83
84 //---------------------------------------------------------------------------
85 // wxSizerItem
86 //---------------------------------------------------------------------------
87
88 void wxSizerItem::Init()
89 {
90 m_window = NULL;
91 m_sizer = NULL;
92 m_show = true;
93 m_userData = NULL;
94 m_zoneRect = wxRect( 0, 0, 0, 0 );
95 }
96
97 void wxSizerItem::Init(const wxSizerFlags& flags)
98 {
99 Init();
100
101 m_proportion = flags.GetProportion();
102 m_flag = flags.GetFlags();
103 m_border = flags.GetBorderInPixels();
104 }
105
106 wxSizerItem::wxSizerItem( int width, int height, int proportion, int flag, int border, wxObject* userData )
107 : m_window( NULL )
108 , m_sizer( NULL )
109 , m_size( wxSize( width, height ) ) // size is set directly
110 , m_minSize( m_size ) // minimal size is the initial size
111 , m_proportion( proportion )
112 , m_border( border )
113 , m_flag( flag )
114 , m_zoneRect( 0, 0, 0, 0 )
115 , m_show( true )
116 , m_userData( userData )
117 {
118 SetRatio( m_size );
119 }
120
121 wxSizerItem::wxSizerItem( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
122 : m_window( window )
123 , m_sizer( NULL )
124 , m_proportion( proportion )
125 , m_border( border )
126 , m_flag( flag )
127 , m_zoneRect( 0, 0, 0, 0 )
128 , m_show( true )
129 , m_userData( userData )
130 {
131 if (flag & wxFIXED_MINSIZE)
132 window->SetMinSize(window->GetSize());
133 m_minSize = window->GetSize();
134
135 // aspect ratio calculated from initial size
136 SetRatio( m_minSize );
137
138 // m_size is calculated later
139 }
140
141 wxSizerItem::wxSizerItem( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
142 : m_window( NULL )
143 , m_sizer( sizer )
144 , m_proportion( proportion )
145 , m_border( border )
146 , m_flag( flag )
147 , m_zoneRect( 0, 0, 0, 0 )
148 , m_show( true )
149 , m_ratio( 0.0 )
150 , m_userData( userData )
151 {
152 // m_minSize is calculated later
153 // m_size is calculated later
154 }
155
156 wxSizerItem::wxSizerItem()
157 {
158 Init();
159
160 m_proportion = 0;
161 m_border = 0;
162 m_flag = 0;
163 }
164
165 wxSizerItem::~wxSizerItem()
166 {
167 delete m_userData;
168
169 if ( m_window )
170 {
171 m_window->SetContainingSizer(NULL);
172 }
173 else // we must be a sizer
174 {
175 delete m_sizer;
176 }
177 }
178
179
180 wxSize wxSizerItem::GetSize() const
181 {
182 wxSize ret;
183 if (IsSizer())
184 ret = m_sizer->GetSize();
185 else
186 if (IsWindow())
187 ret = m_window->GetSize();
188 else ret = m_size;
189
190 if (m_flag & wxWEST)
191 ret.x += m_border;
192 if (m_flag & wxEAST)
193 ret.x += m_border;
194 if (m_flag & wxNORTH)
195 ret.y += m_border;
196 if (m_flag & wxSOUTH)
197 ret.y += m_border;
198
199 return ret;
200 }
201
202 wxSize wxSizerItem::CalcMin()
203 {
204 if (IsSizer())
205 {
206 m_minSize = m_sizer->GetMinSize();
207
208 // if we have to preserve aspect ratio _AND_ this is
209 // the first-time calculation, consider ret to be initial size
210 if ((m_flag & wxSHAPED) && !m_ratio)
211 SetRatio(m_minSize);
212 }
213 else if ( IsWindow() )
214 {
215 // Since the size of the window may change during runtime, we
216 // should use the current minimal/best size.
217 m_minSize = m_window->GetBestFittingSize();
218 }
219
220 return GetMinSizeWithBorder();
221 }
222
223 wxSize wxSizerItem::GetMinSizeWithBorder() const
224 {
225 wxSize ret = m_minSize;
226
227 if (m_flag & wxWEST)
228 ret.x += m_border;
229 if (m_flag & wxEAST)
230 ret.x += m_border;
231 if (m_flag & wxNORTH)
232 ret.y += m_border;
233 if (m_flag & wxSOUTH)
234 ret.y += m_border;
235
236 return ret;
237 }
238
239
240 void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
241 {
242 if (m_flag & wxSHAPED)
243 {
244 // adjust aspect ratio
245 int rwidth = (int) (size.y * m_ratio);
246 if (rwidth > size.x)
247 {
248 // fit horizontally
249 int rheight = (int) (size.x / m_ratio);
250 // add vertical space
251 if (m_flag & wxALIGN_CENTER_VERTICAL)
252 pos.y += (size.y - rheight) / 2;
253 else if (m_flag & wxALIGN_BOTTOM)
254 pos.y += (size.y - rheight);
255 // use reduced dimensions
256 size.y =rheight;
257 }
258 else if (rwidth < size.x)
259 {
260 // add horizontal space
261 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
262 pos.x += (size.x - rwidth) / 2;
263 else if (m_flag & wxALIGN_RIGHT)
264 pos.x += (size.x - rwidth);
265 size.x = rwidth;
266 }
267 }
268
269 // This is what GetPosition() returns. Since we calculate
270 // borders afterwards, GetPosition() will be the left/top
271 // corner of the surrounding border.
272 m_pos = pos;
273
274 if (m_flag & wxWEST)
275 {
276 pos.x += m_border;
277 size.x -= m_border;
278 }
279 if (m_flag & wxEAST)
280 {
281 size.x -= m_border;
282 }
283 if (m_flag & wxNORTH)
284 {
285 pos.y += m_border;
286 size.y -= m_border;
287 }
288 if (m_flag & wxSOUTH)
289 {
290 size.y -= m_border;
291 }
292
293 if (IsSizer())
294 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
295
296 m_zoneRect = wxRect(pos, size);
297 if (IsWindow())
298 m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
299
300 m_size = size;
301 }
302
303 void wxSizerItem::DeleteWindows()
304 {
305 if (m_window)
306 {
307 m_window->Destroy();
308 m_window = NULL;
309 }
310
311 if (m_sizer)
312 m_sizer->DeleteWindows();
313 }
314
315 bool wxSizerItem::IsWindow() const
316 {
317 return (m_window != NULL);
318 }
319
320 bool wxSizerItem::IsSizer() const
321 {
322 return (m_sizer != NULL);
323 }
324
325 bool wxSizerItem::IsSpacer() const
326 {
327 return (m_window == NULL) && (m_sizer == NULL);
328 }
329
330 void wxSizerItem::Show( bool show )
331 {
332 m_show = show;
333
334 if( IsWindow() )
335 m_window->Show( show );
336 else if( IsSizer() )
337 m_sizer->ShowItems( show );
338
339 // ... nothing else to do to hide/show spacers
340 }
341
342 void wxSizerItem::SetOption( int option )
343 {
344 SetProportion( option );
345 }
346
347 int wxSizerItem::GetOption() const
348 {
349 return GetProportion();
350 }
351
352
353 //---------------------------------------------------------------------------
354 // wxSizer
355 //---------------------------------------------------------------------------
356
357 wxSizer::wxSizer()
358 : m_minSize( wxSize( 0, 0 ) )
359 {
360 }
361
362 wxSizer::~wxSizer()
363 {
364 WX_CLEAR_LIST(wxSizerItemList, m_children);
365 }
366
367 wxSizerItem* wxSizer::Insert( size_t index, wxSizerItem *item )
368 {
369 m_children.Insert( index, item );
370
371 if( item->GetWindow() )
372 item->GetWindow()->SetContainingSizer( this );
373
374 return item;
375 }
376
377 bool wxSizer::Remove( wxWindow *window )
378 {
379 return Detach( window );
380 }
381
382 bool wxSizer::Remove( wxSizer *sizer )
383 {
384 wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
385
386 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
387 while (node)
388 {
389 wxSizerItem *item = node->GetData();
390
391 if (item->GetSizer() == sizer)
392 {
393 delete item;
394 m_children.Erase( node );
395 return true;
396 }
397
398 node = node->GetNext();
399 }
400
401 return false;
402 }
403
404 bool wxSizer::Remove( int index )
405 {
406 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
407 false,
408 _T("Remove index is out of range") );
409
410 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
411
412 wxCHECK_MSG( node, false, _T("Failed to find child node") );
413
414 wxSizerItem *item = node->GetData();
415
416 if( item->IsWindow() )
417 item->GetWindow()->SetContainingSizer( NULL );
418
419 delete item;
420 m_children.Erase( node );
421 return true;
422 }
423
424 bool wxSizer::Detach( wxSizer *sizer )
425 {
426 wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
427
428 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
429 while (node)
430 {
431 wxSizerItem *item = node->GetData();
432
433 if (item->GetSizer() == sizer)
434 {
435 item->DetachSizer();
436 delete item;
437 m_children.Erase( node );
438 return true;
439 }
440 node = node->GetNext();
441 }
442
443 return false;
444 }
445
446 bool wxSizer::Detach( wxWindow *window )
447 {
448 wxASSERT_MSG( window, _T("Detaching NULL window") );
449
450 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
451 while (node)
452 {
453 wxSizerItem *item = node->GetData();
454
455 if (item->GetWindow() == window)
456 {
457 item->GetWindow()->SetContainingSizer( NULL );
458 delete item;
459 m_children.Erase( node );
460 return true;
461 }
462 node = node->GetNext();
463 }
464
465 return false;
466 }
467
468 bool wxSizer::Detach( int index )
469 {
470 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
471 false,
472 _T("Detach index is out of range") );
473
474 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
475
476 wxCHECK_MSG( node, false, _T("Failed to find child node") );
477
478 wxSizerItem *item = node->GetData();
479
480 if( item->IsSizer() )
481 item->DetachSizer();
482 else if( item->IsWindow() )
483 item->GetWindow()->SetContainingSizer( NULL );
484
485 delete item;
486 m_children.Erase( node );
487 return true;
488 }
489
490 void wxSizer::Clear( bool delete_windows )
491 {
492 // First clear the ContainingSizer pointers
493 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
494 while (node)
495 {
496 wxSizerItem *item = node->GetData();
497
498 if (item->IsWindow())
499 item->GetWindow()->SetContainingSizer( NULL );
500 node = node->GetNext();
501 }
502
503 // Destroy the windows if needed
504 if (delete_windows)
505 DeleteWindows();
506
507 // Now empty the list
508 WX_CLEAR_LIST(wxSizerItemList, m_children);
509 }
510
511 void wxSizer::DeleteWindows()
512 {
513 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
514 while (node)
515 {
516 wxSizerItem *item = node->GetData();
517
518 item->DeleteWindows();
519 node = node->GetNext();
520 }
521 }
522
523 wxSize wxSizer::Fit( wxWindow *window )
524 {
525 wxSize size(window->IsTopLevel() ? FitSize(window)
526 : GetMinWindowSize(window));
527
528 window->SetSize( size );
529
530 return size;
531 }
532
533 void wxSizer::FitInside( wxWindow *window )
534 {
535 wxSize size;
536 if (window->IsTopLevel())
537 size = VirtualFitSize( window );
538 else
539 size = GetMinClientSize( window );
540
541 window->SetVirtualSize( size );
542 }
543
544 void wxSizer::Layout()
545 {
546 // (re)calculates minimums needed for each item and other preparations
547 // for layout
548 CalcMin();
549
550 // Applies the layout and repositions/resizes the items
551 RecalcSizes();
552 }
553
554 void wxSizer::SetSizeHints( wxWindow *window )
555 {
556 // Preserve the window's max size hints, but set the
557 // lower bound according to the sizer calculations.
558
559 wxSize size = Fit( window );
560
561 window->SetSizeHints( size.x,
562 size.y,
563 window->GetMaxWidth(),
564 window->GetMaxHeight() );
565 }
566
567 void wxSizer::SetVirtualSizeHints( wxWindow *window )
568 {
569 // Preserve the window's max size hints, but set the
570 // lower bound according to the sizer calculations.
571
572 FitInside( window );
573 wxSize size( window->GetVirtualSize() );
574 window->SetVirtualSizeHints( size.x,
575 size.y,
576 window->GetMaxWidth(),
577 window->GetMaxHeight() );
578 }
579
580 wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
581 {
582 return window->GetMaxSize();
583 }
584
585 wxSize wxSizer::GetMinWindowSize( wxWindow *window )
586 {
587 wxSize minSize( GetMinSize() );
588 wxSize size( window->GetSize() );
589 wxSize client_size( window->GetClientSize() );
590
591 return wxSize( minSize.x+size.x-client_size.x,
592 minSize.y+size.y-client_size.y );
593 }
594
595 // TODO on mac we need a function that determines how much free space this
596 // min size contains, in order to make sure that we have 20 pixels of free
597 // space around the controls
598
599 // Return a window size that will fit within the screens dimensions
600 wxSize wxSizer::FitSize( wxWindow *window )
601 {
602 wxSize size = GetMinWindowSize( window );
603 wxSize sizeMax = GetMaxWindowSize( window );
604
605 // Limit the size if sizeMax != wxDefaultSize
606
607 if ( size.x > sizeMax.x && sizeMax.x != wxDefaultCoord )
608 size.x = sizeMax.x;
609 if ( size.y > sizeMax.y && sizeMax.y != wxDefaultCoord )
610 size.y = sizeMax.y;
611
612 return size;
613 }
614
615 wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
616 {
617 wxSize maxSize( window->GetMaxSize() );
618
619 if( maxSize != wxDefaultSize )
620 {
621 wxSize size( window->GetSize() );
622 wxSize client_size( window->GetClientSize() );
623
624 return wxSize( maxSize.x + client_size.x - size.x,
625 maxSize.y + client_size.y - size.y );
626 }
627 else
628 return wxDefaultSize;
629 }
630
631 wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
632 {
633 return GetMinSize(); // Already returns client size.
634 }
635
636 wxSize wxSizer::VirtualFitSize( wxWindow *window )
637 {
638 wxSize size = GetMinClientSize( window );
639 wxSize sizeMax = GetMaxClientSize( window );
640
641 // Limit the size if sizeMax != wxDefaultSize
642
643 if ( size.x > sizeMax.x && sizeMax.x != wxDefaultCoord )
644 size.x = sizeMax.x;
645 if ( size.y > sizeMax.y && sizeMax.y != wxDefaultCoord )
646 size.y = sizeMax.y;
647
648 return size;
649 }
650
651 void wxSizer::SetDimension( int x, int y, int width, int height )
652 {
653 m_position.x = x;
654 m_position.y = y;
655 m_size.x = width;
656 m_size.y = height;
657 Layout();
658 }
659
660 wxSize wxSizer::GetMinSize()
661 {
662 wxSize ret( CalcMin() );
663 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
664 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
665 return ret;
666 }
667
668 void wxSizer::DoSetMinSize( int width, int height )
669 {
670 m_minSize.x = width;
671 m_minSize.y = height;
672 }
673
674 bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
675 {
676 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
677
678 // Is it our immediate child?
679
680 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
681 while (node)
682 {
683 wxSizerItem *item = node->GetData();
684
685 if (item->GetWindow() == window)
686 {
687 item->SetMinSize( width, height );
688 return true;
689 }
690 node = node->GetNext();
691 }
692
693 // No? Search any subsizers we own then
694
695 node = m_children.GetFirst();
696 while (node)
697 {
698 wxSizerItem *item = node->GetData();
699
700 if ( item->GetSizer() &&
701 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
702 {
703 // A child sizer found the requested windw, exit.
704 return true;
705 }
706 node = node->GetNext();
707 }
708
709 return false;
710 }
711
712 bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
713 {
714 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
715
716 // Is it our immediate child?
717
718 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
719 while (node)
720 {
721 wxSizerItem *item = node->GetData();
722
723 if (item->GetSizer() == sizer)
724 {
725 item->GetSizer()->DoSetMinSize( width, height );
726 return true;
727 }
728 node = node->GetNext();
729 }
730
731 // No? Search any subsizers we own then
732
733 node = m_children.GetFirst();
734 while (node)
735 {
736 wxSizerItem *item = node->GetData();
737
738 if ( item->GetSizer() &&
739 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
740 {
741 // A child found the requested sizer, exit.
742 return true;
743 }
744 node = node->GetNext();
745 }
746
747 return false;
748 }
749
750 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
751 {
752 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
753
754 wxCHECK_MSG( node, false, _T("Failed to find child node") );
755
756 wxSizerItem *item = node->GetData();
757
758 if (item->GetSizer())
759 {
760 // Sizers contains the minimal size in them, if not calculated ...
761 item->GetSizer()->DoSetMinSize( width, height );
762 }
763 else
764 {
765 // ... but the minimal size of spacers and windows is stored via the item
766 item->SetMinSize( width, height );
767 }
768
769 return true;
770 }
771
772 wxSizerItem* wxSizer::GetItem( wxWindow *window, bool recursive )
773 {
774 wxASSERT_MSG( window, _T("GetItem for NULL window") );
775
776 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
777 while (node)
778 {
779 wxSizerItem *item = node->GetData();
780
781 if (item->GetWindow() == window)
782 {
783 return item;
784 }
785 else if (recursive && item->IsSizer())
786 {
787 wxSizerItem *subitem = item->GetSizer()->GetItem( window, true );
788 if (subitem)
789 return subitem;
790 }
791
792 node = node->GetNext();
793 }
794
795 return NULL;
796 }
797
798 wxSizerItem* wxSizer::GetItem( wxSizer *sizer, bool recursive )
799 {
800 wxASSERT_MSG( sizer, _T("GetItem for NULL sizer") );
801
802 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
803 while (node)
804 {
805 wxSizerItem *item = node->GetData();
806
807 if (item->GetSizer() == sizer)
808 {
809 return item;
810 }
811 else if (recursive && item->IsSizer())
812 {
813 wxSizerItem *subitem = item->GetSizer()->GetItem( sizer, true );
814 if (subitem)
815 return subitem;
816 }
817
818 node = node->GetNext();
819 }
820
821 return NULL;
822 }
823
824 wxSizerItem* wxSizer::GetItem( size_t index )
825 {
826 wxCHECK_MSG( index < m_children.GetCount(),
827 NULL,
828 _T("GetItem index is out of range") );
829
830 return m_children.Item( index )->GetData();
831 }
832
833 bool wxSizer::Show( wxWindow *window, bool show, bool recursive )
834 {
835 wxSizerItem *item = GetItem( window, recursive );
836
837 if ( item )
838 {
839 item->Show( show );
840 return true;
841 }
842
843 return false;
844 }
845
846 bool wxSizer::Show( wxSizer *sizer, bool show, bool recursive )
847 {
848 wxSizerItem *item = GetItem( sizer, recursive );
849
850 if ( item )
851 {
852 item->Show( show );
853 return true;
854 }
855
856 return false;
857 }
858
859 bool wxSizer::Show( size_t index, bool show)
860 {
861 wxSizerItem *item = GetItem( index );
862
863 if ( item )
864 {
865 item->Show( show );
866 return true;
867 }
868
869 return false;
870 }
871
872 void wxSizer::ShowItems( bool show )
873 {
874 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
875 while (node)
876 {
877 node->GetData()->Show( show );
878 node = node->GetNext();
879 }
880 }
881
882 bool wxSizer::IsShown( wxWindow *window ) const
883 {
884 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
885 while (node)
886 {
887 wxSizerItem *item = node->GetData();
888
889 if (item->GetWindow() == window)
890 {
891 return item->IsShown();
892 }
893 node = node->GetNext();
894 }
895
896 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
897
898 return false;
899 }
900
901 bool wxSizer::IsShown( wxSizer *sizer ) const
902 {
903 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
904 while (node)
905 {
906 wxSizerItem *item = node->GetData();
907
908 if (item->GetSizer() == sizer)
909 {
910 return item->IsShown();
911 }
912 node = node->GetNext();
913 }
914
915 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
916
917 return false;
918 }
919
920 bool wxSizer::IsShown( size_t index ) const
921 {
922 wxCHECK_MSG( index < m_children.GetCount(),
923 false,
924 _T("IsShown index is out of range") );
925
926 return m_children.Item( index )->GetData()->IsShown();
927 }
928
929
930 //---------------------------------------------------------------------------
931 // wxGridSizer
932 //---------------------------------------------------------------------------
933
934 wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
935 : m_rows( rows )
936 , m_cols( cols )
937 , m_vgap( vgap )
938 , m_hgap( hgap )
939 {
940 if (m_rows == 0 && m_cols == 0)
941 m_rows = 1;
942 }
943
944 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
945 : m_rows( 0 )
946 , m_cols( cols )
947 , m_vgap( vgap )
948 , m_hgap( hgap )
949 {
950 if (m_rows == 0 && m_cols == 0)
951 m_rows = 1;
952 }
953
954 int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
955 {
956 int nitems = m_children.GetCount();
957 if ( nitems)
958 {
959 if ( m_cols )
960 {
961 ncols = m_cols;
962 nrows = (nitems + m_cols - 1) / m_cols;
963 }
964 else if ( m_rows )
965 {
966 ncols = (nitems + m_rows - 1) / m_rows;
967 nrows = m_rows;
968 }
969 else // 0 columns, 0 rows?
970 {
971 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
972
973 nrows = ncols = 0;
974 }
975 }
976
977 return nitems;
978 }
979
980 void wxGridSizer::RecalcSizes()
981 {
982 int nitems, nrows, ncols;
983 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
984 return;
985
986 wxSize sz( GetSize() );
987 wxPoint pt( GetPosition() );
988
989 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
990 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
991
992 int x = pt.x;
993 for (int c = 0; c < ncols; c++)
994 {
995 int y = pt.y;
996 for (int r = 0; r < nrows; r++)
997 {
998 int i = r * ncols + c;
999 if (i < nitems)
1000 {
1001 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1002
1003 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
1004
1005 SetItemBounds( node->GetData(), x, y, w, h);
1006 }
1007 y = y + h + m_vgap;
1008 }
1009 x = x + w + m_hgap;
1010 }
1011 }
1012
1013 wxSize wxGridSizer::CalcMin()
1014 {
1015 int nrows, ncols;
1016 if ( CalcRowsCols(nrows, ncols) == 0 )
1017 return wxSize(10, 10);
1018
1019 // Find the max width and height for any component
1020 int w = 0;
1021 int h = 0;
1022
1023 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1024 while (node)
1025 {
1026 wxSizerItem *item = node->GetData();
1027 wxSize sz( item->CalcMin() );
1028
1029 w = wxMax( w, sz.x );
1030 h = wxMax( h, sz.y );
1031
1032 node = node->GetNext();
1033 }
1034
1035 return wxSize( ncols * w + (ncols-1) * m_hgap,
1036 nrows * h + (nrows-1) * m_vgap );
1037 }
1038
1039 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1040 {
1041 wxPoint pt( x,y );
1042 wxSize sz( item->GetMinSizeWithBorder() );
1043 int flag = item->GetFlag();
1044
1045 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1046 {
1047 sz = wxSize(w, h);
1048 }
1049 else
1050 {
1051 if (flag & wxALIGN_CENTER_HORIZONTAL)
1052 {
1053 pt.x = x + (w - sz.x) / 2;
1054 }
1055 else if (flag & wxALIGN_RIGHT)
1056 {
1057 pt.x = x + (w - sz.x);
1058 }
1059
1060 if (flag & wxALIGN_CENTER_VERTICAL)
1061 {
1062 pt.y = y + (h - sz.y) / 2;
1063 }
1064 else if (flag & wxALIGN_BOTTOM)
1065 {
1066 pt.y = y + (h - sz.y);
1067 }
1068 }
1069
1070 item->SetDimension(pt, sz);
1071 }
1072
1073 //---------------------------------------------------------------------------
1074 // wxFlexGridSizer
1075 //---------------------------------------------------------------------------
1076
1077 wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
1078 : wxGridSizer( rows, cols, vgap, hgap ),
1079 m_flexDirection(wxBOTH),
1080 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1081 {
1082 }
1083
1084 wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
1085 : wxGridSizer( cols, vgap, hgap ),
1086 m_flexDirection(wxBOTH),
1087 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1088 {
1089 }
1090
1091 wxFlexGridSizer::~wxFlexGridSizer()
1092 {
1093 }
1094
1095 void wxFlexGridSizer::RecalcSizes()
1096 {
1097 int nitems, nrows, ncols;
1098 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1099 return;
1100
1101 wxPoint pt( GetPosition() );
1102 wxSize sz( GetSize() );
1103
1104 AdjustForGrowables(sz, m_calculatedMinSize, nrows, ncols);
1105
1106 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1107
1108 int x = pt.x;
1109 for (int c = 0; c < ncols; c++)
1110 {
1111 int y = pt.y;
1112 for (int r = 0; r < nrows; r++)
1113 {
1114 int i = r * ncols + c;
1115 if (i < nitems)
1116 {
1117 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1118
1119 wxASSERT_MSG( node, _T("Failed to find node") );
1120
1121 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1122 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1123
1124 SetItemBounds( node->GetData(), x, y, w, h);
1125 }
1126 y = y + m_rowHeights[r] + m_vgap;
1127 }
1128 x = x + m_colWidths[c] + m_hgap;
1129 }
1130 }
1131
1132 wxSize wxFlexGridSizer::CalcMin()
1133 {
1134 int nrows,
1135 ncols;
1136 size_t i, s;
1137
1138 // Number of rows/columns can change as items are added or removed.
1139 if ( !CalcRowsCols(nrows, ncols) )
1140 return wxSize(10, 10);
1141
1142 m_rowHeights.SetCount(nrows);
1143 m_colWidths.SetCount(ncols);
1144
1145 // We have to recalcuate the sizes in case the item minimum size has
1146 // changed since the previous layout, or the item has been hidden using
1147 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1148 // dimension of the row/column will be -1, indicating that the column
1149 // itself is hidden.
1150 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1151 m_rowHeights[ i ] = -1;
1152 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1153 m_colWidths[ i ] = -1;
1154
1155 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1156
1157 i = 0;
1158 while (node)
1159 {
1160 wxSizerItem *item = node->GetData();
1161 if ( item->IsShown() )
1162 {
1163 wxSize sz( item->CalcMin() );
1164 int row = i / ncols;
1165 int col = i % ncols;
1166
1167 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1168 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1169 }
1170
1171 node = node->GetNext();
1172 i++;
1173 }
1174
1175 AdjustForFlexDirection();
1176
1177 // Sum total minimum size, including gaps between rows/columns.
1178 // -1 is used as a magic number meaning empty column.
1179 int width = 0;
1180 for (int col = 0; col < ncols; col++)
1181 if ( m_colWidths[ col ] != -1 )
1182 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1183
1184 int height = 0;
1185 for (int row = 0; row < nrows; row++)
1186 if ( m_rowHeights[ row ] != -1 )
1187 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1188
1189 m_calculatedMinSize = wxSize( width, height );
1190 return m_calculatedMinSize;
1191 }
1192
1193 void wxFlexGridSizer::AdjustForFlexDirection()
1194 {
1195 // the logic in CalcMin works when we resize flexibly in both directions
1196 // but maybe this is not the case
1197 if ( m_flexDirection != wxBOTH )
1198 {
1199 // select the array corresponding to the direction in which we do *not*
1200 // resize flexibly
1201 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1202 : m_rowHeights;
1203
1204 const int count = array.GetCount();
1205
1206 // find the largest value in this array
1207 int n, largest = 0;
1208 for ( n = 0; n < count; ++n )
1209 {
1210 if ( array[n] > largest )
1211 largest = array[n];
1212 }
1213
1214 // and now fill it with the largest value
1215 for ( n = 0; n < count; ++n )
1216 {
1217 array[n] = largest;
1218 }
1219 }
1220 }
1221
1222
1223 void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1224 int nrows, int ncols)
1225 {
1226 // what to do with the rows? by default, resize them proportionally
1227 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1228 {
1229 int sum_proportions = 0;
1230 int growable_space = 0;
1231 int num = 0;
1232 size_t idx;
1233 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1234 {
1235 // Since the number of rows/columns can change as items are
1236 // inserted/deleted, we need to verify at runtime that the
1237 // requested growable rows/columns are still valid.
1238 if (m_growableRows[idx] >= nrows)
1239 continue;
1240
1241 // If all items in a row/column are hidden, that row/column will
1242 // have a dimension of -1. This causes the row/column to be
1243 // hidden completely.
1244 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1245 continue;
1246 sum_proportions += m_growableRowsProportions[idx];
1247 growable_space += m_rowHeights[ m_growableRows[idx] ];
1248 num++;
1249 }
1250
1251 if (num > 0)
1252 {
1253 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1254 {
1255 if (m_growableRows[idx] >= nrows )
1256 continue;
1257 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1258 m_rowHeights[ m_growableRows[idx] ] = 0;
1259 else
1260 {
1261 int delta = (sz.y - minsz.y);
1262 if (sum_proportions == 0)
1263 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1264 else
1265 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1266 m_rowHeights[ m_growableRows[idx] ] = delta;
1267 }
1268 }
1269 }
1270 }
1271 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1272 {
1273 // rounding problem?
1274 for ( int row = 0; row < nrows; ++row )
1275 m_rowHeights[ row ] = sz.y / nrows;
1276 }
1277
1278 // the same logic as above but for the columns
1279 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1280 {
1281 int sum_proportions = 0;
1282 int growable_space = 0;
1283 int num = 0;
1284 size_t idx;
1285 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1286 {
1287 // Since the number of rows/columns can change as items are
1288 // inserted/deleted, we need to verify at runtime that the
1289 // requested growable rows/columns are still valid.
1290 if (m_growableCols[idx] >= ncols)
1291 continue;
1292
1293 // If all items in a row/column are hidden, that row/column will
1294 // have a dimension of -1. This causes the column to be hidden
1295 // completely.
1296 if (m_colWidths[ m_growableCols[idx] ] == -1)
1297 continue;
1298 sum_proportions += m_growableColsProportions[idx];
1299 growable_space += m_colWidths[ m_growableCols[idx] ];
1300 num++;
1301 }
1302
1303 if (num > 0)
1304 {
1305 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1306 {
1307 if (m_growableCols[idx] >= ncols )
1308 continue;
1309 if (m_colWidths[ m_growableCols[idx] ] == -1)
1310 m_colWidths[ m_growableCols[idx] ] = 0;
1311 else
1312 {
1313 int delta = (sz.x - minsz.x);
1314 if (sum_proportions == 0)
1315 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1316 else
1317 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1318 m_colWidths[ m_growableCols[idx] ] = delta;
1319 }
1320 }
1321 }
1322 }
1323 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1324 {
1325 for ( int col=0; col < ncols; ++col )
1326 m_colWidths[ col ] = sz.x / ncols;
1327 }
1328 }
1329
1330
1331 void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
1332 {
1333 m_growableRows.Add( idx );
1334 m_growableRowsProportions.Add( proportion );
1335 }
1336
1337 void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
1338 {
1339 m_growableRows.Remove( idx );
1340 }
1341
1342 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
1343 {
1344 m_growableCols.Add( idx );
1345 m_growableColsProportions.Add( proportion );
1346 }
1347
1348 void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
1349 {
1350 m_growableCols.Remove( idx );
1351 }
1352
1353 //---------------------------------------------------------------------------
1354 // wxBoxSizer
1355 //---------------------------------------------------------------------------
1356
1357 wxBoxSizer::wxBoxSizer( int orient )
1358 : m_orient( orient )
1359 {
1360 }
1361
1362 void wxBoxSizer::RecalcSizes()
1363 {
1364 if (m_children.GetCount() == 0)
1365 return;
1366
1367 int delta = 0;
1368 if (m_stretchable)
1369 {
1370 if (m_orient == wxHORIZONTAL)
1371 delta = m_size.x - m_fixedWidth;
1372 else
1373 delta = m_size.y - m_fixedHeight;
1374 }
1375
1376 wxPoint pt( m_position );
1377
1378 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1379 while (node)
1380 {
1381 wxSizerItem *item = node->GetData();
1382
1383 if (item->IsShown())
1384 {
1385 wxSize size( item->GetMinSizeWithBorder() );
1386
1387 if (m_orient == wxVERTICAL)
1388 {
1389 wxCoord height = size.y;
1390 if (item->GetProportion())
1391 {
1392 // Because of at least one visible item has non-zero
1393 // proportion then m_stretchable is not zero
1394 height = (delta * item->GetProportion()) / m_stretchable;
1395 }
1396
1397 wxPoint child_pos( pt );
1398 wxSize child_size( size.x, height );
1399
1400 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1401 child_size.x = m_size.x;
1402 else if (item->GetFlag() & wxALIGN_RIGHT)
1403 child_pos.x += m_size.x - size.x;
1404 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1405 // XXX wxCENTER is added for backward compatibility;
1406 // wxALIGN_CENTER should be used in new code
1407 child_pos.x += (m_size.x - size.x) / 2;
1408
1409 item->SetDimension( child_pos, child_size );
1410
1411 pt.y += height;
1412 }
1413 else
1414 {
1415 wxCoord width = size.x;
1416 if (item->GetProportion())
1417 {
1418 // Because of at least one visible item has non-zero
1419 // proportion then m_stretchable is not zero
1420 width = (delta * item->GetProportion()) / m_stretchable;
1421 }
1422
1423 wxPoint child_pos( pt );
1424 wxSize child_size( width, size.y );
1425
1426 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1427 child_size.y = m_size.y;
1428 else if (item->GetFlag() & wxALIGN_BOTTOM)
1429 child_pos.y += m_size.y - size.y;
1430 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1431 // XXX wxCENTER is added for backward compatibility;
1432 // wxALIGN_CENTER should be used in new code
1433 child_pos.y += (m_size.y - size.y) / 2;
1434
1435 item->SetDimension( child_pos, child_size );
1436
1437 pt.x += width;
1438 }
1439 }
1440
1441 node = node->GetNext();
1442 }
1443 }
1444
1445 wxSize wxBoxSizer::CalcMin()
1446 {
1447 if (m_children.GetCount() == 0)
1448 return wxSize(10,10);
1449
1450 m_stretchable = 0;
1451 m_minWidth = 0;
1452 m_minHeight = 0;
1453 m_fixedWidth = 0;
1454 m_fixedHeight = 0;
1455
1456 // precalc item minsizes and count proportions
1457 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1458 while (node)
1459 {
1460 wxSizerItem *item = node->GetData();
1461
1462 if (item->IsShown())
1463 item->CalcMin(); // result is stored in the item
1464
1465 if (item->IsShown() && item->GetProportion() != 0)
1466 m_stretchable += item->GetProportion();
1467
1468 node = node->GetNext();
1469 }
1470
1471 // Total minimum size (width or height) of sizer
1472 int maxMinSize = 0;
1473
1474 node = m_children.GetFirst();
1475 while (node)
1476 {
1477 wxSizerItem *item = node->GetData();
1478
1479 if (item->IsShown() && item->GetProportion() != 0)
1480 {
1481 int stretch = item->GetProportion();
1482 wxSize size( item->GetMinSizeWithBorder() );
1483 int minSize;
1484
1485 // Integer division rounded up is (a + b - 1) / b
1486 // Round up needed in order to guarantee that all
1487 // all items will have size not less then their min size
1488 if (m_orient == wxHORIZONTAL)
1489 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
1490 else
1491 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1492
1493 if (minSize > maxMinSize)
1494 maxMinSize = minSize;
1495 }
1496 node = node->GetNext();
1497 }
1498
1499 // Calculate overall minimum size
1500 node = m_children.GetFirst();
1501 while (node)
1502 {
1503 wxSizerItem *item = node->GetData();
1504
1505 if (item->IsShown())
1506 {
1507 wxSize size( item->GetMinSizeWithBorder() );
1508 if (item->GetProportion() != 0)
1509 {
1510 if (m_orient == wxHORIZONTAL)
1511 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
1512 else
1513 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
1514 }
1515 else
1516 {
1517 if (m_orient == wxVERTICAL)
1518 {
1519 m_fixedHeight += size.y;
1520 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1521 }
1522 else
1523 {
1524 m_fixedWidth += size.x;
1525 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1526 }
1527 }
1528
1529 if (m_orient == wxHORIZONTAL)
1530 {
1531 m_minWidth += size.x;
1532 m_minHeight = wxMax( m_minHeight, size.y );
1533 }
1534 else
1535 {
1536 m_minHeight += size.y;
1537 m_minWidth = wxMax( m_minWidth, size.x );
1538 }
1539 }
1540 node = node->GetNext();
1541 }
1542
1543 return wxSize( m_minWidth, m_minHeight );
1544 }
1545
1546 //---------------------------------------------------------------------------
1547 // wxStaticBoxSizer
1548 //---------------------------------------------------------------------------
1549
1550 #if wxUSE_STATBOX
1551
1552 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1553 : wxBoxSizer( orient )
1554 , m_staticBox( box )
1555 {
1556 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1557 }
1558
1559 static void GetStaticBoxBorders( wxStaticBox *box,
1560 int *borderTop,
1561 int *borderOther)
1562 {
1563 // this has to be done platform by platform as there is no way to
1564 // guess the thickness of a wxStaticBox border
1565 #ifdef __WXCOCOA__
1566 box->GetBordersForSizer(borderTop,borderOther);
1567 #elif defined(__WXMAC__)
1568
1569 static int extraTop = -1; // Uninitted
1570 static int other = 5;
1571
1572 if ( extraTop == -1 )
1573 {
1574 // The minimal border used for the top. Later on the staticbox'
1575 // font height is added to this.
1576 extraTop = 0;
1577
1578 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
1579 {
1580 // As indicated by the HIG, Panther needs an extra border of 11
1581 // pixels (otherwise overlapping occurs at the top). The "other"
1582 // border has to be 11.
1583 extraTop = 11;
1584 other = 11;
1585 }
1586
1587 }
1588
1589 *borderTop = extraTop + box->GetCharHeight();
1590 *borderOther = other;
1591
1592 #else
1593 #ifdef __WXGTK__
1594 if ( box->GetLabel().empty() )
1595 *borderTop = 5;
1596 else
1597 #endif // __WXGTK__
1598 *borderTop = box->GetCharHeight();
1599
1600 *borderOther = 5;
1601 #endif // __WXCOCOA__
1602 }
1603
1604 void wxStaticBoxSizer::RecalcSizes()
1605 {
1606 int top_border, other_border;
1607 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1608
1609 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1610
1611 wxPoint old_pos( m_position );
1612 m_position.x += other_border;
1613 m_position.y += top_border;
1614 wxSize old_size( m_size );
1615 m_size.x -= 2*other_border;
1616 m_size.y -= top_border + other_border;
1617
1618 wxBoxSizer::RecalcSizes();
1619
1620 m_position = old_pos;
1621 m_size = old_size;
1622 }
1623
1624 wxSize wxStaticBoxSizer::CalcMin()
1625 {
1626 int top_border, other_border;
1627 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1628
1629 wxSize ret( wxBoxSizer::CalcMin() );
1630 ret.x += 2*other_border;
1631 ret.y += other_border + top_border;
1632
1633 return ret;
1634 }
1635
1636 void wxStaticBoxSizer::ShowItems( bool show )
1637 {
1638 m_staticBox->Show( show );
1639 wxBoxSizer::ShowItems( show );
1640 }
1641
1642 #endif // wxUSE_STATBOX
1643
1644 wxStdDialogButtonSizer::wxStdDialogButtonSizer()
1645 : wxBoxSizer(wxHORIZONTAL)
1646 {
1647 bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
1648
1649 // If we have a PDA screen, put yes/no button over
1650 // all other buttons, otherwise on the left side.
1651 if (is_pda)
1652 m_orient = wxVERTICAL;
1653
1654 m_buttonAffirmative = NULL;
1655 m_buttonApply = NULL;
1656 m_buttonNegative = NULL;
1657 m_buttonCancel = NULL;
1658 m_buttonHelp = NULL;
1659 }
1660
1661 void wxStdDialogButtonSizer::AddButton(wxButton *mybutton)
1662 {
1663 switch (mybutton->GetId())
1664 {
1665 case wxID_OK:
1666 case wxID_YES:
1667 case wxID_SAVE:
1668 m_buttonAffirmative = mybutton;
1669 break;
1670 case wxID_APPLY:
1671 m_buttonApply = mybutton;
1672 break;
1673 case wxID_NO:
1674 m_buttonNegative = mybutton;
1675 break;
1676 case wxID_CANCEL:
1677 m_buttonCancel = mybutton;
1678 break;
1679 case wxID_HELP:
1680 m_buttonHelp = mybutton;
1681 break;
1682 default:
1683 break;
1684 }
1685 }
1686
1687 void wxStdDialogButtonSizer::Finalise()
1688 {
1689 #ifdef __WXMAC__
1690 Add(0, 0, 0, wxLEFT, 6);
1691 if (m_buttonHelp)
1692 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1693
1694 if (m_buttonNegative){
1695 // HIG POLICE BULLETIN - destructive buttons need extra padding
1696 // 24 pixels on either side
1697 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 12);
1698 }
1699
1700 // extra whitespace between help/negative and cancel/ok buttons
1701 Add(0, 0, 1, wxEXPAND, 0);
1702
1703 if (m_buttonCancel){
1704 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1705 // Cancel or help should be default
1706 // m_buttonCancel->SetDefaultButton();
1707 }
1708
1709 // Ugh, Mac doesn't really have apply dialogs, so I'll just
1710 // figure the best place is between Cancel and OK
1711 if (m_buttonApply)
1712 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1713
1714 if (m_buttonAffirmative){
1715 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
1716
1717 if (m_buttonAffirmative->GetId() == wxID_SAVE){
1718 // these buttons have set labels under Mac so we should use them
1719 m_buttonAffirmative->SetLabel(_("Save"));
1720 m_buttonNegative->SetLabel(_("Don't Save"));
1721 }
1722 }
1723
1724 // Extra space around and at the right
1725 Add(12, 24);
1726 #elif defined(__WXGTK20__)
1727 Add(0, 0, 0, wxLEFT, 9);
1728 if (m_buttonHelp)
1729 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1730
1731 // extra whitespace between help and cancel/ok buttons
1732 Add(0, 0, 1, wxEXPAND, 0);
1733
1734 if (m_buttonNegative){
1735 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1736 }
1737
1738 if (m_buttonCancel){
1739 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1740 // Cancel or help should be default
1741 // m_buttonCancel->SetDefaultButton();
1742 }
1743
1744 if (m_buttonApply)
1745 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1746
1747 if (m_buttonAffirmative)
1748 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
1749 #else
1750 // do the same thing for GTK1 and Windows platforms
1751 // and assume any platform not accounted for here will use
1752 // Windows style
1753 Add(0, 0, 0, wxLEFT, 9);
1754 if (m_buttonHelp)
1755 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(4, 0)).x);
1756
1757 // extra whitespace between help and cancel/ok buttons
1758 Add(0, 0, 1, wxEXPAND, 0);
1759
1760 if (m_buttonApply)
1761 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(4, 0)).x);
1762
1763 if (m_buttonAffirmative){
1764 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(4, 0)).x);
1765 }
1766
1767 if (m_buttonNegative){
1768 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(4, 0)).x);
1769 }
1770
1771 if (m_buttonCancel){
1772 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT, m_buttonCancel->ConvertDialogToPixels(wxSize(4, 0)).x);
1773 // Cancel or help should be default
1774 // m_buttonCancel->SetDefaultButton();
1775 }
1776
1777 #endif
1778 }
1779
1780 #if WXWIN_COMPATIBILITY_2_4
1781
1782 // ----------------------------------------------------------------------------
1783 // wxNotebookSizer
1784 // ----------------------------------------------------------------------------
1785
1786 #if wxUSE_BOOKCTRL
1787 IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
1788 #if wxUSE_NOTEBOOK
1789 IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
1790 #endif // wxUSE_NOTEBOOK
1791 #endif // wxUSE_BOOKCTRL
1792
1793 #if wxUSE_BOOKCTRL
1794
1795 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrlBase *bookctrl)
1796 : m_bookctrl(bookctrl)
1797 {
1798 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1799 }
1800
1801 void wxBookCtrlSizer::RecalcSizes()
1802 {
1803 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1804 }
1805
1806 wxSize wxBookCtrlSizer::CalcMin()
1807 {
1808 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1809
1810 sizeBorder.x += 5;
1811 sizeBorder.y += 5;
1812
1813 if ( m_bookctrl->GetPageCount() == 0 )
1814 {
1815 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1816 }
1817
1818 int maxX = 0;
1819 int maxY = 0;
1820
1821 wxWindowList::compatibility_iterator
1822 node = m_bookctrl->GetChildren().GetFirst();
1823 while (node)
1824 {
1825 wxWindow *item = node->GetData();
1826 wxSizer *itemsizer = item->GetSizer();
1827
1828 if (itemsizer)
1829 {
1830 wxSize subsize( itemsizer->CalcMin() );
1831
1832 if (subsize.x > maxX)
1833 maxX = subsize.x;
1834 if (subsize.y > maxY)
1835 maxY = subsize.y;
1836 }
1837
1838 node = node->GetNext();
1839 }
1840
1841 return wxSize( maxX, maxY ) + sizeBorder;
1842 }
1843
1844 #if wxUSE_NOTEBOOK
1845
1846 wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1847 {
1848 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
1849 m_bookctrl = nb;
1850 }
1851
1852 #endif // wxUSE_NOTEBOOOK
1853 #endif // wxUSE_BOOKCTRL
1854
1855 #endif // WXWIN_COMPATIBILITY_2_4