-//---------------------------------------------------------------------------
-// wxWrapSizer
-//---------------------------------------------------------------------------
-
-#define wxDEFAULT_PROPORTION_LAST 1000000
-
-// User data to hold old proportion for last item on line
-// (which might be extended)
-struct wxPropHolder : public wxObject
-{
- wxPropHolder( ) : m_item(0), m_propOld(0) { }
- void Init( wxSizerItem *item, int propOld ) { m_item=item; m_propOld=propOld; }
-
- wxSizerItem *m_item;
- int m_propOld;
-};
-
-IMPLEMENT_DYNAMIC_CLASS(wxWrapSizer, wxBoxSizer);
-
-wxWrapSizer::wxWrapSizer( int orient, int flags )
- : wxBoxSizer(orient),
- m_prim_size_last( -1 ),
- m_rows(orient^wxBOTH),
- m_flags(flags)
-{
-}
-
-wxWrapSizer::~wxWrapSizer()
-{
- // Have to clear grand child items so that they're not deleted twice
- for( int ix=m_rows.GetChildren().GetCount()-1; ix>=0; ix-- )
- {
- wxSizer *psz = m_rows.GetItem((size_t)ix)->GetSizer();
- wxSizerItemList &sl = psz->GetChildren();
- while( sl.GetLast() )
- sl.Erase( sl.GetLast() );
- }
-}
-
-
-bool wxWrapSizer::InformFirstDirection( int direction, int size, int WXUNUSED(availableOtherDir) )
-{
- if( !direction )
- {
- // Better to keep value, then CalcMin will work better
- //m_prim_size_last = -1;
- return false;
- }
- if( direction==m_orient )
- {
- // The direction is same as our primary, so we can make use of it
- m_prim_size_last = size;
- return true;
- }
- else
- return false;
-}
-
-
-void wxWrapSizer::AdjustPropLastItem(wxSizer *psz, wxSizerItem *itemLast)
-{
- wxSizerItem *psi = m_rows.GetItem(psz);
- wxASSERT(psi);
- wxPropHolder *pph = (wxPropHolder*)psi->GetUserData();
- if ( !pph )
- psi->SetUserData( pph=new wxPropHolder );
-
- pph->Init( itemLast, itemLast->GetProportion() );
- itemLast->SetProportion( wxDEFAULT_PROPORTION_LAST );
-}
-
-void wxWrapSizer::RecalcSizes()
-{
- wxASSERT( m_orient&wxBOTH );
- if (m_children.GetCount() == 0)
- return;
-
- // What we do here is to put our items into child box sizers,
- // as many of them as we have lines.
-
- // Empty all items in all rows in owned sizer.
- // We have to access the list directly, since we don't want to
- // destroy the wxSizerItems.
- for( int ix=m_rows.GetChildren().GetCount()-1; ix>=0; ix-- ){
- wxSizerItem *psi = m_rows.GetItem( (size_t)ix );
-
- // Restore proportion for last item on line (if item has not been deleted)
- wxPropHolder *pph = (wxPropHolder*)psi->GetUserData();
- if( pph && GetChildren().Find(pph->m_item) )
- pph->m_item->SetProportion(pph->m_propOld);
-
- wxSizer *psz = psi->GetSizer();
- wxASSERT( psz );
- wxSizerItemList &sl = psz->GetChildren();
- while( sl.GetLast() )
- sl.Erase( sl.GetLast() );
- }
-
- int lineSumMajor = 0;
- int majorSize = GetSizeInMajorDir(m_size);
-
- // Make sure we have at least one child sizer
- m_n_line = 1;
- if( !m_rows.GetChildren().GetCount() )
- m_rows.Add( new wxBoxSizer(GetOrientation()), 1, wxEXPAND );
-
- // The sizer where to insert items in
- wxSizer *psz = m_rows.GetItem((size_t)0)->GetSizer();
- wxASSERT( psz );
-
- // Now put our child items into child sizers instead
- wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
- wxSizerItem *item = NULL, *itemLast=NULL;
- while (node)
- {
- item = node->GetData();
- if ( item->IsShown() )
- {
- wxSize minSz = item->GetMinSize();
- int minSzMajor = GetSizeInMajorDir(minSz);
-
- // More space on this line?
- if( !lineSumMajor || lineSumMajor+minSzMajor<=majorSize )
- {
- lineSumMajor += minSzMajor;
- }
- else
- {
- lineSumMajor = minSzMajor;
- // Get a new empty sizer to insert into
- if( (int)m_rows.GetChildren().GetCount()<=m_n_line )
- m_rows.Add( new wxBoxSizer(GetOrientation()), 1, wxEXPAND );
-
- // If we have extend-last-on-each-line mode, then do so now
- // Note: We must store old proportion value then.
- if( m_flags&wxEXTEND_LAST_ON_EACH_LINE )
- AdjustPropLastItem(psz,itemLast);
-
- // The sizer where to insert items in
- psz = m_rows.GetItem(m_n_line++)->GetSizer();
- }
- itemLast = item;
- psz->Add( item );
- // If item is a window, it now has a pointer to the child sizer,
- // which is wrong. Set it to point to us.
- if( item->GetWindow() )
- item->GetWindow()->SetContainingSizer( this );
- }
- node = node->GetNext();
- }
-
- // If we have extend-last-on-each-line mode, then do so now
- if( m_flags&wxEXTEND_LAST_ON_EACH_LINE )
- AdjustPropLastItem(psz,itemLast);
-
- // If we have more sizers than lines, remove them
- while( (int)m_rows.GetChildren().GetCount()>m_n_line )
- m_rows.Remove( m_n_line );
-
- // Now do layout on row sizer
- m_rows.SetDimension( m_position.x, m_position.y, m_size.x, m_size.y );
-
- // Remember this to next time (will be overridden by InformFirstDirection if used)
- m_prim_size_last = GetSizeInMajorDir(m_size);
-}
-
-
-wxSize wxWrapSizer::CalcMin()
-{
- if (m_children.GetCount() == 0)
- return wxSize();
-
- // Algorithm for calculating min size: (assuming horizontal orientation)
- // X: Max width of all members
- // Y: Based on last X, calculate how many lines needed
- // First time around, assume all items fits on one line
-
- int maxMajor = 0;
- int minorSum = 0;
- int lineMaxMinor = 0;
- int lineSumMajor = 0;
- m_n_line = 0;
-
- // precalc item minsizes and fit on lines (preliminary)
- wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
- while (node)
- {
- wxSizerItem *item = node->GetData();
- if ( item->IsShown() )
- {
- wxSize minSz = item->CalcMin();
- int szMajor = GetSizeInMajorDir(minSz);
- int szMinor = GetSizeInMinorDir(minSz);
- if( szMajor>maxMajor ) maxMajor = szMajor;
- // More space on this line?
- if( m_prim_size_last<0 || !lineSumMajor ||
- lineSumMajor+szMajor<=m_prim_size_last )
- {
- lineSumMajor += szMajor;
- if( szMinor>lineMaxMinor )
- lineMaxMinor = szMinor;
- }
- else
- {
- minorSum += lineMaxMinor; // Add height of highest item on last line
- m_n_line++;
- lineMaxMinor = szMinor;
- lineSumMajor = szMajor;
- }
- }
- node = node->GetNext();
- }
- minorSum += lineMaxMinor; // Add height of highest item on last line
-
- m_minSize = SizeFromMajorMinor(maxMajor, minorSum);
- return m_minSize;
-}
-