1/////////////////////////////////////////////////////////////////////////////
2// Name:        updatesmgr.cpp
3// Purpose:     cbSimpleUpdatesMgr implementation.
4// Author:      Aleksandras Gluchovas
5// Modified by:
6// Created:     19/10/98
7// RCS-ID:      $Id: updatesmgr.cpp 35650 2005-09-23 12:56:45Z MR $
8// Copyright:   (c) Aleksandras Gluchovas
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20#include "wx/wx.h"
21#endif
22
23#include "wx/fl/updatesmgr.h"
24
25// helper function
26
27static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
28{
29    if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
30         ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
31
32        if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
33             ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
34
35            return 1;
36
37    return 0;
38}
39
40/***** Implementation for class cbSimpleUpdatesMgr *****/
41
42IMPLEMENT_DYNAMIC_CLASS( cbSimpleUpdatesMgr, cbUpdatesManagerBase )
43
44cbSimpleUpdatesMgr::cbSimpleUpdatesMgr( wxFrameLayout* pPanel )
45    : cbUpdatesManagerBase( pPanel )
46{}
47
48bool cbSimpleUpdatesMgr::WasChanged( cbUpdateMgrData& data, wxRect& currentBounds )
49{
50    return (   data.IsDirty() ||
51
52             ( data.mPrevBounds.x      != currentBounds.x     ||
53               data.mPrevBounds.y      != currentBounds.y     ||
54               data.mPrevBounds.width  != currentBounds.width ||
55               data.mPrevBounds.height != currentBounds.height  )
56           );
57}
58
59void cbSimpleUpdatesMgr::OnStartChanges()
60{
61    // memorize states of ALL items in the layout -
62    // this is quite excessive, but OK for the simple
63    // implementation of updates manager
64
65    mpLayout->GetPrevClientRect() = mpLayout->GetClientRect();
66
67    cbDockPane** panes = mpLayout->GetPanesArray();
68
69    for( int n = 0; n != MAX_PANES; ++n )
70    {
71        cbDockPane& pane = *panes[n];
72        // store pane state
73        pane.mUMgrData.StoreItemState( pane.mBoundsInParent );
74        pane.mUMgrData.SetDirty( false );
75
76        for( size_t i = 0; i != pane.GetRowList().Count(); ++i )
77        {
78            cbRowInfo& row = *pane.GetRowList()[ i ];
79
80            // store row state
81            row.mUMgrData.StoreItemState( row.mBoundsInParent );
82            row.mUMgrData.SetDirty( false );
83
84            for( size_t k = 0; k != row.mBars.Count(); ++k )
85            {
86                cbBarInfo& bar = *row.mBars[ k ];
87
88                // store bar state
89                bar.mUMgrData.StoreItemState( bar.mBoundsInParent );
90                bar.mUMgrData.SetDirty( false );
91            }
92        }
93    }
94}
95
96void cbSimpleUpdatesMgr::OnFinishChanges()
97{
98    // nothing here, could be overriden by more sophisticated updates-managers
99}
100
101void cbSimpleUpdatesMgr::OnRowWillChange( cbRowInfo* WXUNUSED(pRow), cbDockPane* WXUNUSED(pInPane) )
102{
103    // -/-
104}
105
106void cbSimpleUpdatesMgr::OnBarWillChange( cbBarInfo* WXUNUSED(pBar),
107                                          cbRowInfo* WXUNUSED(pInRow), cbDockPane* WXUNUSED(pInPane) )
108{
109    // -/-
110}
111
112void cbSimpleUpdatesMgr::OnPaneMarginsWillChange( cbDockPane* WXUNUSED(pPane) )
113{
114    // -/-
115}
116
117void cbSimpleUpdatesMgr::OnPaneWillChange( cbDockPane* WXUNUSED(pPane) )
118{
119    // -/-
120}
121
122void cbSimpleUpdatesMgr::UpdateNow()
123{
124    cbDockPane** panes = mpLayout->GetPanesArray();
125
126    wxRect& r1 = mpLayout->GetClientRect();
127    wxRect& r2 = mpLayout->GetPrevClientRect();
128
129    // detect changes in client window's area
130
131    bool clientWindowChanged = ( r1.x      != r2.x     ||
132                                 r1.y      != r2.y     ||
133                                 r1.width  != r2.width ||
134                                 r1.height != r2.height );
135
136    // step #1 - detect changes in each row of each pane,
137    //           and repaint decorations around changed windows
138
139    wxList mBarsToRefresh;
140    wxList mPanesList;
141
142    for( int n = 0; n != MAX_PANES; ++n )
143    {
144        cbDockPane& pane = *(panes[n]);
145
146        bool paneChanged = WasChanged( pane.mUMgrData, pane.mBoundsInParent );
147
148        if ( paneChanged )
149        {
150            wxClientDC dc( &mpLayout->GetParentFrame() );
151            pane.PaintPaneBackground( dc );
152        }
153
154        wxRect realBounds;
155
156        for( size_t i = 0; i != pane.GetRowList().Count(); ++i )
157        {
158            cbRowInfo& row = *pane.GetRowList()[ i ];
159
160            wxDC* pDc = NULL;
161
162            bool rowChanged = false;
163
164            // FIXME:: the below should not be fixed
165            cbBarInfo* barsToRepaint[256];
166
167            // number of bars, that were changed in the current row
168            int nBars = 0;
169
170            if ( WasChanged( row.mUMgrData, row.mBoundsInParent ) )
171
172                rowChanged = true;
173            else
174                for( size_t k = 0; k != row.mBars.Count(); ++k )
175
176                    if ( WasChanged( row.mBars[k]->mUMgrData,
177                         row.mBars[k]->mBoundsInParent )
178                       )
179
180                        barsToRepaint[nBars++] = row.mBars[k];
181
182            if ( nBars || rowChanged )
183            {
184                realBounds = row.mBoundsInParent;
185
186                // include 1-pixel thick shades around the row
187                realBounds.x -= 1;
188                realBounds.y -= 1;
189                realBounds.width  += 2;
190                realBounds.height += 2;
191
192                pDc = pane.StartDrawInArea( realBounds );
193            }
194
195            if ( rowChanged )
196            {
197                // postphone the resizing and refreshing the changed
198                // bar windows
199
200                for( size_t k = 0; k != row.mBars.Count(); ++k )
201                {
202                    mBarsToRefresh.Append( (wxObject*)row.mBars[k] );
203                    mPanesList.Append( &pane );
204                }
205
206                // draw only their decorations now
207
208                pane.PaintRow( &row, *pDc );
209            }
210            else
211            if ( nBars != 0 )
212            {
213                for( int i = 0; i != nBars; ++i )
214                {
215                    // postphone the resizement and refreshing the changed
216                    // bar windows
217
218                    mBarsToRefresh.Append( (wxObject*)barsToRepaint[i] );
219                    mPanesList.Append( &pane );
220                }
221
222                // redraw decorations of entire row, regardless of how much
223                // of the bars were changed
224                pane.PaintRow( &row, *pDc );
225            }
226
227            if ( pDc )
228
229                pane.FinishDrawInArea( realBounds );
230        } // end of while
231
232        if ( paneChanged )
233        {
234            wxClientDC dc( &mpLayout->GetParentFrame() );
235            pane.PaintPaneDecorations( dc );
236        }
237
238    } // end of for
239
240    if ( clientWindowChanged )
241    {
242        mpLayout->PositionClientWindow();
243        // ptr to client-window object is "marked" as 0
244    }
245
246    // step #2 - do ordered refreshing and resizing of bar window objects now
247
248    wxNode* pNode     = mBarsToRefresh.GetFirst();
249    wxNode* pPaneNode = mPanesList.GetFirst();
250
251    while( pNode )
252    {
253        cbBarInfo*  pBar  = (cbBarInfo*) pNode->GetData();
254        cbDockPane* pPane = (cbDockPane*)pPaneNode->GetData();
255
256        pPane->SizeBar( pBar );
257
258        pNode     = pNode->GetNext();
259        pPaneNode = pPaneNode->GetNext();
260    }
261
262    pNode = mBarsToRefresh.GetFirst();
263
264    while( pNode )
265    {
266        cbBarInfo* pBar = (cbBarInfo*)pNode->GetData();
267
268        if ( pBar->mpBarWnd )
269        {
270            pBar->mpBarWnd->Refresh();
271
272            // FIXME::
273            //info.mpBarWnd->Show(false);
274            //info.mpBarWnd->Show(true);
275        }
276
277        pNode  = pNode->GetNext();
278    }
279
280    if ( clientWindowChanged )
281    {
282        // FIXME:: excessive?
283
284        mpLayout->GetFrameClient()->Refresh();
285    }
286}
287
288
289