/////////////////////////////////////////////////////////////////////////////
-// Name: No names yet.
-// Purpose: Contrib. demo
+// Name: gcupdatesmgr.cpp
+// Purpose: cbGCUpdatesMgr class, optimizing refresh using GarbageCollector
// Author: Aleksandras Gluchovas
// Modified by:
// Created: 19/10/98
// RCS-ID: $Id$
// Copyright: (c) Aleksandras Gluchovas
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
{
- if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
- ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
+ if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
+ ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
- if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
- ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
-
- return 1;
+ if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
+ ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
+
+ return 1;
- return 0;
+ return 0;
}
// helper structure
struct cbRectInfo
{
- cbBarInfo* mpBar;
- cbDockPane* mpPane;
- wxRect* mpCurBounds;
- wxRect* mpPrevBounds;
+ cbBarInfo* mpBar;
+ cbDockPane* mpPane;
+ wxRect* mpCurBounds;
+ wxRect* mpPrevBounds;
};
static inline cbRectInfo& node_to_rect_info( wxNode* pNode )
{
- return *( (cbRectInfo*) (pNode->Data()) );
+ return *( (cbRectInfo*) (pNode->Data()) );
}
/***** Implementation for class cbSimpleUpdatesMgr *****/
IMPLEMENT_DYNAMIC_CLASS( cbGCUpdatesMgr, cbSimpleUpdatesMgr )
cbGCUpdatesMgr::cbGCUpdatesMgr( wxFrameLayout* pPanel )
- : cbSimpleUpdatesMgr( pPanel )
+ : cbSimpleUpdatesMgr( pPanel )
{}
void cbGCUpdatesMgr::AddItem( wxList& itemList,
- cbBarInfo* pBar,
- cbDockPane* pPane,
- wxRect& curBounds,
- wxRect& prevBounds )
+ cbBarInfo* pBar,
+ cbDockPane* pPane,
+ wxRect& curBounds,
+ wxRect& prevBounds )
{
- cbRectInfo* pInfo = new cbRectInfo();
+ cbRectInfo* pInfo = new cbRectInfo();
- pInfo->mpBar = pBar;
- pInfo->mpPane = pPane;
- pInfo->mpCurBounds = &curBounds;
- pInfo->mpPrevBounds = &prevBounds;
+ pInfo->mpBar = pBar;
+ pInfo->mpPane = pPane;
+ pInfo->mpCurBounds = &curBounds;
+ pInfo->mpPrevBounds = &prevBounds;
- itemList.Append( (wxObject*) pInfo );
+ itemList.Append( (wxObject*) pInfo );
}
void cbGCUpdatesMgr::OnStartChanges()
{
- // memorize states of ALL items in the layout -
- // this is quite excessive, but OK for the decent
- // implementation of updates manager
+ // memorize states of ALL items in the layout -
+ // this is quite excessive, but OK for the decent
+ // implementation of updates manager
- mpLayout->GetPrevClientRect() = mpLayout->GetClientRect();
+ mpLayout->GetPrevClientRect() = mpLayout->GetClientRect();
- cbDockPane** panes = mpLayout->GetPanesArray();
+ cbDockPane** panes = mpLayout->GetPanesArray();
- for( int n = 0; n != MAX_PANES; ++n )
- {
- cbDockPane& pane = *(panes[n]);
+ for( int n = 0; n != MAX_PANES; ++n )
+ {
+ cbDockPane& pane = *(panes[n]);
- // store pane state
- pane.mUMgrData.StoreItemState( pane.mBoundsInParent );
- pane.mUMgrData.SetDirty( FALSE );
+ // store pane state
+ pane.mUMgrData.StoreItemState( pane.mBoundsInParent );
+ pane.mUMgrData.SetDirty( FALSE );
- cbRowInfo* pRow = pane.GetFirstRow();
+ cbRowInfo* pRow = pane.GetFirstRow();
- while ( pRow )
- {
- cbBarInfo* pBar = pRow->GetFirstBar();
+ while ( pRow )
+ {
+ cbBarInfo* pBar = pRow->GetFirstBar();
- // store row state
- pRow->mUMgrData.StoreItemState( pRow->mBoundsInParent );
- pRow->mUMgrData.SetDirty( FALSE );
+ // store row state
+ pRow->mUMgrData.StoreItemState( pRow->mBoundsInParent );
+ pRow->mUMgrData.SetDirty( FALSE );
- while( pBar )
- {
- // store bar state
- pBar->mUMgrData.StoreItemState( pBar->mBoundsInParent );
- pBar->mUMgrData.SetDirty( FALSE );
+ while( pBar )
+ {
+ // store bar state
+ pBar->mUMgrData.StoreItemState( pBar->mBoundsInParent );
+ pBar->mUMgrData.SetDirty( FALSE );
- pBar = pBar->mpNext;
- }
+ pBar = pBar->mpNext;
+ }
- pRow = pRow->mpNext;
- }
- }
+ pRow = pRow->mpNext;
+ }
+ }
}
void cbGCUpdatesMgr::UpdateNow()
{
- cbDockPane** panes = mpLayout->GetPanesArray();
+ cbDockPane** panes = mpLayout->GetPanesArray();
- wxRect& r1 = mpLayout->GetClientRect();
- wxRect& r2 = mpLayout->GetPrevClientRect();
+ wxRect& r1 = mpLayout->GetClientRect();
+ wxRect& r2 = mpLayout->GetPrevClientRect();
- // detect changes in client window's area
+ // detect changes in client window's area
- bool clientWindowChanged = ( r1.x != r2.x ||
- r1.y != r2.y ||
- r1.width != r2.width ||
- r1.height != r2.height );
+ bool clientWindowChanged = ( r1.x != r2.x ||
+ r1.y != r2.y ||
+ r1.width != r2.width ||
+ r1.height != r2.height );
- // step #1 - detect changes in each row of each pane,
- // and repaint decorations around changed windows
+ // step #1 - detect changes in each row of each pane,
+ // and repaint decorations around changed windows
- wxList mBarsToResize;
+ wxList mBarsToResize;
- for( int n = 0; n != MAX_PANES; ++n )
- {
- cbDockPane& pane = *(panes[n]);
+ int n;
+ for ( n = 0; n != MAX_PANES; ++n )
+ {
+ cbDockPane& pane = *(panes[n]);
- bool paneChanged = WasChanged( pane.mUMgrData, pane.mBoundsInParent );
+ bool paneChanged = WasChanged( pane.mUMgrData, pane.mBoundsInParent );
- if ( paneChanged )
- {
- wxClientDC dc( &mpLayout->GetParentFrame() );
- pane.PaintPaneBackground( dc );
- }
+ if ( paneChanged )
+ {
+ wxClientDC dc( &mpLayout->GetParentFrame() );
+ pane.PaintPaneBackground( dc );
+ }
- wxRect realBounds;
+ wxRect realBounds;
- cbRowInfo* pRow = pane.GetFirstRow();
+ cbRowInfo* pRow = pane.GetFirstRow();
- while ( pRow )
- {
- wxDC* pDc = 0;
+ while ( pRow )
+ {
+ wxDC* pDc = 0;
- cbBarInfo* pBar = pRow->GetFirstBar();
+ cbBarInfo* pBar = pRow->GetFirstBar();
- bool rowChanged = FALSE;
- bool rowBkPainted = FALSE;
+ bool rowChanged = FALSE;
+// bool rowBkPainted = FALSE;
- // FIXME:: the below should not be fixed
- cbBarInfo* barsToRepaint[128];
- // number of bars, that were changed in the current row
- int nBars = 0;
+ // FIXME:: the below should not be fixed
+ cbBarInfo* barsToRepaint[128];
+ // number of bars, that were changed in the current row
+ int nBars = 0;
- wxRect r1 = pRow->mUMgrData.mPrevBounds;
- wxRect r2 = pRow->mBoundsInParent;
+ //wxRect r1 = pRow->mUMgrData.mPrevBounds;
+ //wxRect r2 = pRow->mBoundsInParent;
- if ( WasChanged( pRow->mUMgrData, pRow->mBoundsInParent ) )
-
- rowChanged = TRUE;
- else
- while( pBar )
- {
- if ( WasChanged( pBar->mUMgrData, pBar->mBoundsInParent ) )
-
- barsToRepaint[nBars++] = pBar;
+ if ( WasChanged( pRow->mUMgrData, pRow->mBoundsInParent ) )
+
+ rowChanged = TRUE;
+ else
+ while( pBar )
+ {
+ if ( WasChanged( pBar->mUMgrData, pBar->mBoundsInParent ) )
+
+ barsToRepaint[nBars++] = pBar;
- pBar = pBar->mpNext;
- }
+ pBar = pBar->mpNext;
+ }
- if ( nBars || rowChanged )
- {
- realBounds = pRow->mBoundsInParent;
+ if ( nBars || rowChanged )
+ {
+ realBounds = pRow->mBoundsInParent;
- // include 1-pixel thick shades around the row
- realBounds.x -= 1;
- realBounds.y -= 1;
- realBounds.width += 2;
- realBounds.height += 2;
+ // include 1-pixel thick shades around the row
+ realBounds.x -= 1;
+ realBounds.y -= 1;
+ realBounds.width += 2;
+ realBounds.height += 2;
- pDc = pane.StartDrawInArea( realBounds );
- }
+ pDc = pane.StartDrawInArea( realBounds );
+ }
- if ( rowChanged )
- {
- // postphone the resizement and refreshing the changed
- // bar windows
+ if ( rowChanged )
+ {
+ // postphone the resizement and refreshing the changed
+ // bar windows
- cbBarInfo* pCurBar = pRow->GetFirstBar();
+ cbBarInfo* pCurBar = pRow->GetFirstBar();
- while( pCurBar )
- {
- if ( WasChanged( pCurBar->mUMgrData,
- pCurBar->mBoundsInParent ) )
+ while ( pCurBar )
+ {
+ if ( WasChanged( pCurBar->mUMgrData,
+ pCurBar->mBoundsInParent ) )
- AddItem( mBarsToResize, pCurBar, &pane,
- pCurBar->mBoundsInParent,
- pCurBar->mUMgrData.mPrevBounds );
+ AddItem( mBarsToResize, pCurBar, &pane,
+ pCurBar->mBoundsInParent,
+ pCurBar->mUMgrData.mPrevBounds );
- pCurBar = pCurBar->mpNext;
- }
+ pCurBar = pCurBar->mpNext;
+ }
- // draw only their decorations now
+ // draw only their decorations now
- pane.PaintRow( pRow, *pDc );
- }
- else
- if ( nBars != 0 )
- {
- for( int i = 0; i != nBars; ++i )
+ pane.PaintRow( pRow, *pDc );
+ }
+ else
+ if ( nBars != 0 )
+ {
+ for ( int i = 0; i != nBars; ++i )
- // postphone the resizement and refreshing the changed
- // bar windows
+ // postphone the resizement and refreshing the changed
+ // bar windows
- AddItem( mBarsToResize,
- barsToRepaint[i],
- &pane,
- barsToRepaint[i]->mBoundsInParent,
- barsToRepaint[i]->mUMgrData.mPrevBounds );
+ AddItem( mBarsToResize,
+ barsToRepaint[i],
+ &pane,
+ barsToRepaint[i]->mBoundsInParent,
+ barsToRepaint[i]->mUMgrData.mPrevBounds );
- // redraw decorations of entire row, regardless of how much
- // of the bars were changed
+ // redraw decorations of entire row, regardless of how much
+ // of the bars were changed
- pane.PaintRow( pRow, *pDc );
- }
+ pane.PaintRow( pRow, *pDc );
+ }
- if ( pDc )
-
- pane.FinishDrawInArea( realBounds );
+ if ( pDc )
+
+ pane.FinishDrawInArea( realBounds );
- pRow = pRow->mpNext;
+ pRow = pRow->mpNext;
- } // end of while
+ } // end of while
- if ( paneChanged )
- {
- wxClientDC dc( &mpLayout->GetParentFrame() );
- pane.PaintPaneDecorations( dc );
- }
+ if ( paneChanged )
+ {
+ wxClientDC dc( &mpLayout->GetParentFrame() );
+ pane.PaintPaneDecorations( dc );
+ }
- } // end of for
+ } // end of for
- if ( clientWindowChanged && !mpLayout->mClientWndRefreshPending )
- {
- // ptr to client-window object is "marked" as NULL
+ if ( clientWindowChanged && !mpLayout->mClientWndRefreshPending )
+ {
+ // ptr to client-window object is "marked" as NULL
- AddItem( mBarsToResize, NULL, NULL,
- mpLayout->GetClientRect(),
- mpLayout->GetPrevClientRect() );
- }
+ AddItem( mBarsToResize, NULL, NULL,
+ mpLayout->GetClientRect(),
+ mpLayout->GetPrevClientRect() );
+ }
- // step #2 - do ordered refreshing and resizing of bar window objects now
+ // step #2 - do ordered refreshing and resizing of bar window objects now
- DoRepositionItems( mBarsToResize );
+ DoRepositionItems( mBarsToResize );
}
void cbGCUpdatesMgr::DoRepositionItems( wxList& items )
{
- wxNode* pNode1 = items.First();
+ wxNode* pNode1 = items.First();
- while( pNode1 )
- {
- cbRectInfo& info = node_to_rect_info( pNode1 );
+ while( pNode1 )
+ {
+ cbRectInfo& info = node_to_rect_info( pNode1 );
- wxNode* pNode2 = items.First();
+ wxNode* pNode2 = items.First();
- // and node itself
+ // and node itself
- mGC.AddObject( &info );
+ mGC.AddObject( &info );
- while( pNode2 )
- {
- if ( pNode2 != pNode1 ) // node should not depend on itself
- {
- // add references to objects, on which this object
- // depends. Dependecy here indicates intersection of current
- // bounds of this object with the initial bounds of the
- // other object
+ while( pNode2 )
+ {
+ if ( pNode2 != pNode1 ) // node should not depend on itself
+ {
+ // Add references to objects on which this object
+ // depends. Dependency here indicates intersection of current
+ // bounds of this object with the initial bounds of the
+ // other object.
- cbRectInfo& otherInfo = node_to_rect_info( pNode2 );
+ cbRectInfo& otherInfo = node_to_rect_info( pNode2 );
- if ( rect_hits_rect( *info.mpCurBounds, *otherInfo.mpPrevBounds ) )
-
- // the node depends on node
- mGC.AddDependency( &info, &otherInfo );
- }
+ if ( rect_hits_rect( *info.mpCurBounds, *otherInfo.mpPrevBounds ) )
+
+ // the node depends on node
+ mGC.AddDependency( &info, &otherInfo );
+ }
- pNode2 = pNode2->Next();
- }
+ pNode2 = pNode2->Next();
+ }
- pNode1 = pNode1->Next();
- }
+ pNode1 = pNode1->Next();
+ }
- mGC.ArrangeCollection(); // order nodes according "least-dependency" rule,
- // and find out cycled chains
+ mGC.ArrangeCollection(); // order nodes according "least-dependency" rule,
+ // and find out cycled chains
- // regular item nodes need to be resized, but not repainted (since
- // they stand in linear (not cyclic) dependency with other
- // regular nodes)
+ // Regular item nodes need to be resized, but not repainted (since
+ // they stand in linear (not cyclic) dependency with other
+ // regular nodes).
- wxNode* pNode = mGC.GetRegularObjects().First();
+ wxNode* pNode = mGC.GetRegularObjects().First();
- while ( pNode )
- {
- cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
+ while ( pNode )
+ {
+ cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
- if ( info.mpBar == NULL )
-
- mpLayout->PositionClientWindow();
- else
- info.mpPane->SizeBar( info.mpBar );
+ if ( info.mpBar == NULL )
+
+ mpLayout->PositionClientWindow();
+ else
+ info.mpPane->SizeBar( info.mpBar );
- pNode = pNode->Next();
- }
+ pNode = pNode->Next();
+ }
- // cycled item nodes, need to be both resized and repainted
+ // cycled item nodes, need to be both resized and repainted
- pNode = mGC.GetCycledObjects().First();
+ pNode = mGC.GetCycledObjects().First();
- while ( pNode )
- {
- cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
+ while ( pNode )
+ {
+ cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
- if ( info.mpBar == NULL )
- {
- wxWindow* pClntWnd = mpLayout->GetFrameClient();
+ if ( info.mpBar == NULL )
+ {
+ wxWindow* pClntWnd = mpLayout->GetFrameClient();
- mpLayout->PositionClientWindow();
+ mpLayout->PositionClientWindow();
- // FIXME FIXME:: excessive!
+ // FIXME FIXME:: excessive!
- pClntWnd->Show( FALSE );
- pClntWnd->Show( TRUE );
+ pClntWnd->Show( FALSE );
+ pClntWnd->Show( TRUE );
- // OLD STUFF:: mpLayout->PositionClientWindow();
- }
- else
- if ( info.mpBar->mpBarWnd )
- {
- wxWindow* pWnd = info.mpBar->mpBarWnd;
+ // OLD STUFF:: mpLayout->PositionClientWindow();
+ }
+ else
+ if ( info.mpBar->mpBarWnd )
+ {
+ wxWindow* pWnd = info.mpBar->mpBarWnd;
- // resize
- info.mpPane->SizeBar( info.mpBar );
+ // resize
+ info.mpPane->SizeBar( info.mpBar );
- // repaint
+ // repaint
- /* OLD STUFF:: bool isChoice = info.mpBar->IsKindOf( CLASSINFO( wxChoice ) );
+ /* OLD STUFF:: bool isChoice = info.mpBar->IsKindOf( CLASSINFO( wxChoice ) );
- //#ifdef __WINDOWS__
- //int result = ::SendMessage( (HWND)pWnd->m_hWnd, WM_NCPAINT, 0, 0 );
- //#endif
- */
+ //#ifdef __WINDOWS__
+ //int result = ::SendMessage( (HWND)pWnd->m_hWnd, WM_NCPAINT, 0, 0 );
+ //#endif
+ */
- // FIXME FIXME:: there's no other way to repaint non-client area of the wxWindow!!
- // so we do *excessive* "hide 'n show"
+ // FIXME FIXME:: there's no other way to repaint non-client area of the wxWindow!!
+ // so we do *excessive* "hide 'n show"
- pWnd->Show(FALSE);
- pWnd->Show(TRUE);
-
- pWnd->Refresh();
- }
+ pWnd->Show(FALSE);
+ pWnd->Show(TRUE);
+
+ pWnd->Refresh();
+ }
- pNode = pNode->Next();
- }
+ pNode = pNode->Next();
+ }
- // release data prepared for GC alg.
+ // release data prepared for GC alg.
- pNode = items.First();
+ pNode = items.First();
- while( pNode )
- {
- cbRectInfo* pInfo = (cbRectInfo*)(pNode->Data());
+ while( pNode )
+ {
+ cbRectInfo* pInfo = (cbRectInfo*)(pNode->Data());
- delete pInfo;
+ delete pInfo;
- pNode = pNode->Next();
- }
+ pNode = pNode->Next();
+ }
- mGC.Reset(); // reinit GC
+ mGC.Reset(); // reinit GC
- // FIXME:: this is a dirty-workaround for messy client-area,
- // as a result of docking bar out of floated-container window
+ // FIXME:: this is a dirty-workaround for messy client-area,
+ // as a result of docking bar out of floated-container window
- if ( mpLayout->mClientWndRefreshPending )
- {
- mpLayout->PositionClientWindow();
- mpLayout->GetFrameClient()->Refresh();
- }
+ if ( mpLayout->mClientWndRefreshPending )
+ {
+ mpLayout->PositionClientWindow();
+ mpLayout->GetFrameClient()->Refresh();
+ }
}