General makefiles to be added later. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1876 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
409 lines
8.8 KiB
C++
409 lines
8.8 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: No names yet.
|
|
// Purpose: Contrib. demo
|
|
// Author: Aleksandras Gluchovas
|
|
// Modified by:
|
|
// Created: 19/10/98
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) Aleksandras Gluchovas
|
|
// Licence: wxWindows license
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "updatesmgr.h"
|
|
// #pragma interface
|
|
#endif
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/wx.h"
|
|
#endif
|
|
|
|
#include "gcupdatesmgr.h"
|
|
|
|
// helper function
|
|
|
|
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.y >= r1.y && r2.y <= r1.y + r1.height ) ||
|
|
( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// helper structure
|
|
|
|
struct cbRectInfo
|
|
{
|
|
cbBarInfo* mpBar;
|
|
cbDockPane* mpPane;
|
|
wxRect* mpCurBounds;
|
|
wxRect* mpPrevBounds;
|
|
};
|
|
|
|
static inline cbRectInfo& node_to_rect_info( wxNode* pNode )
|
|
{
|
|
return *( (cbRectInfo*) (pNode->Data()) );
|
|
}
|
|
|
|
/***** Implementation for class cbSimpleUpdatesMgr *****/
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS( cbGCUpdatesMgr, cbSimpleUpdatesMgr )
|
|
|
|
cbGCUpdatesMgr::cbGCUpdatesMgr( wxFrameLayout* pPanel )
|
|
: cbSimpleUpdatesMgr( pPanel )
|
|
{}
|
|
|
|
void cbGCUpdatesMgr::AddItem( wxList& itemList,
|
|
cbBarInfo* pBar,
|
|
cbDockPane* pPane,
|
|
wxRect& curBounds,
|
|
wxRect& prevBounds )
|
|
{
|
|
cbRectInfo* pInfo = new cbRectInfo();
|
|
|
|
pInfo->mpBar = pBar;
|
|
pInfo->mpPane = pPane;
|
|
pInfo->mpCurBounds = &curBounds;
|
|
pInfo->mpPrevBounds = &prevBounds;
|
|
|
|
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
|
|
|
|
mpLayout->GetPrevClientRect() = mpLayout->GetClientRect();
|
|
|
|
cbDockPane** panes = mpLayout->GetPanesArray();
|
|
|
|
for( int n = 0; n != MAX_PANES; ++n )
|
|
{
|
|
cbDockPane& pane = *(panes[n]);
|
|
|
|
// store pane state
|
|
pane.mUMgrData.StoreItemState( pane.mBoundsInParent );
|
|
pane.mUMgrData.SetDirty( FALSE );
|
|
|
|
cbRowInfo* pRow = pane.GetFirstRow();
|
|
|
|
while ( pRow )
|
|
{
|
|
cbBarInfo* pBar = pRow->GetFirstBar();
|
|
|
|
// 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 );
|
|
|
|
pBar = pBar->mpNext;
|
|
}
|
|
|
|
pRow = pRow->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cbGCUpdatesMgr::UpdateNow()
|
|
{
|
|
cbDockPane** panes = mpLayout->GetPanesArray();
|
|
|
|
wxRect& r1 = mpLayout->GetClientRect();
|
|
wxRect& r2 = mpLayout->GetPrevClientRect();
|
|
|
|
// 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 );
|
|
|
|
// step #1 - detect changes in each row of each pane,
|
|
// and repaint decorations around changed windows
|
|
|
|
wxList mBarsToResize;
|
|
|
|
for( int n = 0; n != MAX_PANES; ++n )
|
|
{
|
|
cbDockPane& pane = *(panes[n]);
|
|
|
|
bool paneChanged = WasChanged( pane.mUMgrData, pane.mBoundsInParent );
|
|
|
|
if ( paneChanged )
|
|
{
|
|
wxClientDC dc( &mpLayout->GetParentFrame() );
|
|
pane.PaintPaneBackground( dc );
|
|
}
|
|
|
|
wxRect realBounds;
|
|
|
|
cbRowInfo* pRow = pane.GetFirstRow();
|
|
|
|
while ( pRow )
|
|
{
|
|
wxDC* pDc = 0;
|
|
|
|
cbBarInfo* pBar = pRow->GetFirstBar();
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
pBar = pBar->mpNext;
|
|
}
|
|
|
|
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;
|
|
|
|
pDc = pane.StartDrawInArea( realBounds );
|
|
}
|
|
|
|
if ( rowChanged )
|
|
{
|
|
// postphone the resizement and refreshing the changed
|
|
// bar windows
|
|
|
|
cbBarInfo* pCurBar = pRow->GetFirstBar();
|
|
|
|
while( pCurBar )
|
|
{
|
|
if ( WasChanged( pCurBar->mUMgrData,
|
|
pCurBar->mBoundsInParent ) )
|
|
|
|
AddItem( mBarsToResize, pCurBar, &pane,
|
|
pCurBar->mBoundsInParent,
|
|
pCurBar->mUMgrData.mPrevBounds );
|
|
|
|
pCurBar = pCurBar->mpNext;
|
|
}
|
|
|
|
// draw only their decorations now
|
|
|
|
pane.PaintRow( pRow, *pDc );
|
|
}
|
|
else
|
|
if ( nBars != 0 )
|
|
{
|
|
for( int i = 0; i != nBars; ++i )
|
|
|
|
// postphone the resizement and refreshing the changed
|
|
// bar windows
|
|
|
|
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
|
|
|
|
pane.PaintRow( pRow, *pDc );
|
|
}
|
|
|
|
if ( pDc )
|
|
|
|
pane.FinishDrawInArea( realBounds );
|
|
|
|
pRow = pRow->mpNext;
|
|
|
|
} // end of while
|
|
|
|
if ( paneChanged )
|
|
{
|
|
wxClientDC dc( &mpLayout->GetParentFrame() );
|
|
pane.PaintPaneDecorations( dc );
|
|
}
|
|
|
|
} // end of for
|
|
|
|
if ( clientWindowChanged && !mpLayout->mClientWndRefreshPending )
|
|
{
|
|
// ptr to client-window object is "marked" as NULL
|
|
|
|
AddItem( mBarsToResize, NULL, NULL,
|
|
mpLayout->GetClientRect(),
|
|
mpLayout->GetPrevClientRect() );
|
|
}
|
|
|
|
// step #2 - do ordered refreshing and resizing of bar window objects now
|
|
|
|
DoRepositionItems( mBarsToResize );
|
|
}
|
|
|
|
void cbGCUpdatesMgr::DoRepositionItems( wxList& items )
|
|
{
|
|
wxNode* pNode1 = items.First();
|
|
|
|
while( pNode1 )
|
|
{
|
|
cbRectInfo& info = node_to_rect_info( pNode1 );
|
|
|
|
wxNode* pNode2 = items.First();
|
|
|
|
// and node itself
|
|
|
|
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
|
|
|
|
cbRectInfo& otherInfo = node_to_rect_info( pNode2 );
|
|
|
|
if ( rect_hits_rect( *info.mpCurBounds, *otherInfo.mpPrevBounds ) )
|
|
|
|
// the node depends on node
|
|
mGC.AddDependency( &info, &otherInfo );
|
|
}
|
|
|
|
pNode2 = pNode2->Next();
|
|
}
|
|
|
|
pNode1 = pNode1->Next();
|
|
}
|
|
|
|
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)
|
|
|
|
wxNode* pNode = mGC.GetRegularObjects().First();
|
|
|
|
while ( pNode )
|
|
{
|
|
cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
|
|
|
|
if ( info.mpBar == NULL )
|
|
|
|
mpLayout->PositionClientWindow();
|
|
else
|
|
info.mpPane->SizeBar( info.mpBar );
|
|
|
|
pNode = pNode->Next();
|
|
}
|
|
|
|
// cycled item nodes, need to be both resized and repainted
|
|
|
|
pNode = mGC.GetCycledObjects().First();
|
|
|
|
while ( pNode )
|
|
{
|
|
cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
|
|
|
|
if ( info.mpBar == NULL )
|
|
{
|
|
wxWindow* pClntWnd = mpLayout->GetFrameClient();
|
|
|
|
mpLayout->PositionClientWindow();
|
|
|
|
// FIXME FIXME:: excessive!
|
|
|
|
pClntWnd->Show( FALSE );
|
|
pClntWnd->Show( TRUE );
|
|
|
|
// OLD STUFF:: mpLayout->PositionClientWindow();
|
|
}
|
|
else
|
|
if ( info.mpBar->mpBarWnd )
|
|
{
|
|
wxWindow* pWnd = info.mpBar->mpBarWnd;
|
|
|
|
// resize
|
|
info.mpPane->SizeBar( info.mpBar );
|
|
|
|
// repaint
|
|
|
|
/* OLD STUFF:: bool isChoice = info.mpBar->IsKindOf( CLASSINFO( wxChoice ) );
|
|
|
|
//#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"
|
|
|
|
pWnd->Show(FALSE);
|
|
pWnd->Show(TRUE);
|
|
|
|
pWnd->Refresh();
|
|
}
|
|
|
|
pNode = pNode->Next();
|
|
}
|
|
|
|
// release data prepared for GC alg.
|
|
|
|
pNode = items.First();
|
|
|
|
while( pNode )
|
|
{
|
|
cbRectInfo* pInfo = (cbRectInfo*)(pNode->Data());
|
|
|
|
delete pInfo;
|
|
|
|
pNode = pNode->Next();
|
|
}
|
|
|
|
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
|
|
|
|
if ( mpLayout->mClientWndRefreshPending )
|
|
{
|
|
mpLayout->PositionClientWindow();
|
|
mpLayout->GetFrameClient()->Refresh();
|
|
}
|
|
} |