]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/antiflickpl.cpp
unihde base class virtual functions
[wxWidgets.git] / contrib / src / fl / antiflickpl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: antiflickpl.cpp
3 // Purpose: Double-buffering plugin class for reducing flickering.
4 // Author: Aleksandras Gluchovas (@Lithuania)
5 // Modified by:
6 // Created: 23/10/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "antiflickpl.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include "wx/fl/antiflickpl.h"
28
29 /***** Implementation for class cbAntiflickerPlugin *****/
30
31 IMPLEMENT_DYNAMIC_CLASS( cbAntiflickerPlugin, cbPluginBase )
32
33 BEGIN_EVENT_TABLE( cbAntiflickerPlugin, cbPluginBase )
34
35 EVT_PL_START_DRAW_IN_AREA ( cbAntiflickerPlugin::OnStartDrawInArea )
36 EVT_PL_FINISH_DRAW_IN_AREA ( cbAntiflickerPlugin::OnFinishDrawInArea )
37
38 END_EVENT_TABLE()
39
40 // initialization of static members
41
42 int cbAntiflickerPlugin::mRefCount = 0;
43
44 wxBitmap* cbAntiflickerPlugin::mpVertBuf = 0;
45 wxBitmap* cbAntiflickerPlugin::mpHorizBuf = 0;
46 wxMemoryDC* cbAntiflickerPlugin::mpVertBufDc = 0;
47 wxMemoryDC* cbAntiflickerPlugin::mpHorizBufDc = 0;
48
49 // constructors
50
51 cbAntiflickerPlugin::cbAntiflickerPlugin(void)
52 : mpLRUBufDc ( NULL ),
53 mLRUArea ( -1,-1, -1,-1 )
54 {
55 ++mRefCount;
56 }
57
58 cbAntiflickerPlugin::cbAntiflickerPlugin( wxFrameLayout* pPanel, int paneMask )
59
60 : cbPluginBase( pPanel, paneMask ),
61 mpLRUBufDc ( NULL ),
62 mLRUArea ( -1,-1, -1,-1 )
63 {
64 ++mRefCount;
65 }
66
67 cbAntiflickerPlugin::~cbAntiflickerPlugin()
68 {
69 if ( --mRefCount == 0 )
70 {
71 if ( mpHorizBuf )
72 {
73 mpHorizBufDc->SelectObject( wxNullBitmap );
74 delete mpHorizBuf;
75 delete mpHorizBufDc;
76 mpHorizBuf = 0;
77 mpHorizBufDc = 0;
78 }
79
80 if ( mpVertBuf )
81 {
82 mpVertBufDc->SelectObject( wxNullBitmap );
83 delete mpVertBuf;
84 delete mpVertBufDc;
85 mpVertBuf = 0;
86 mpVertBufDc = 0;
87 }
88 }
89 }
90
91 wxDC* cbAntiflickerPlugin::FindSuitableBuffer( const wxRect& forArea )
92 {
93 if ( mpVertBuf )
94 {
95 if ( mpVertBuf->GetHeight() >= forArea.height &&
96 mpVertBuf->GetWidth() >= forArea.width )
97 return mpVertBufDc;
98 }
99 else
100 if ( mpHorizBuf )
101 {
102 if ( mpHorizBuf->GetHeight() >= forArea.height &&
103 mpHorizBuf->GetWidth() >= forArea.width )
104 return mpHorizBufDc;
105 }
106
107 return 0;
108 }
109
110 wxDC* cbAntiflickerPlugin::AllocNewBuffer( const wxRect& forArea )
111 {
112 // TBD:: preallocate bit larger bitmap at once, to avoid
113 // excessive realocations later
114
115 // check whether the given area is oriented horizontally
116 // or vertically and choose corresponding bitmap to create or
117 // recreate
118
119 if ( forArea.height > forArea.width )
120 {
121 wxSize prevDim( 0,0 );
122
123 if ( mpVertBuf )
124 {
125 prevDim.x = mpVertBuf->GetWidth();
126 prevDim.y = mpVertBuf->GetHeight();
127
128 mpVertBufDc->SelectObject( wxNullBitmap );
129 delete mpVertBuf;
130 }
131 else
132 mpVertBufDc = new wxMemoryDC();
133
134 mpVertBuf = new wxBitmap( int( wxMax(forArea.width, prevDim.x ) ),
135 int( wxMax(forArea.height, prevDim.y ) )
136 );
137
138 mpVertBufDc->SelectObject( *mpVertBuf );
139
140 return mpVertBufDc;
141 }
142 else
143 {
144 wxSize prevDim( 0,0 );
145
146 if ( mpHorizBuf )
147 {
148 prevDim.x = mpHorizBuf->GetWidth();
149 prevDim.y = mpHorizBuf->GetHeight();
150
151 mpHorizBufDc->SelectObject( wxNullBitmap );
152 delete mpHorizBuf;
153 }
154 else
155 mpHorizBufDc = new wxMemoryDC();
156
157 mpHorizBuf = new wxBitmap( int( wxMax(forArea.width, prevDim.x ) ),
158 int( wxMax(forArea.height, prevDim.y ) )
159 );
160
161 mpHorizBufDc->SelectObject( *mpHorizBuf );
162
163 return mpHorizBufDc;
164 }
165 }
166
167 void cbAntiflickerPlugin::OnStartDrawInArea( cbStartDrawInAreaEvent& event )
168 {
169 wxASSERT( mpLRUBufDc == NULL ); // DBG:: see comments in OnFinishDrawInArea(..) method
170
171 // short-cut
172 wxRect& area = event.mArea;
173
174 if ( event.mArea.width < 0 ||
175 event.mArea.height < 0 ) return;
176
177 // memorize given area
178 mLRUArea.x = area.x;
179 mLRUArea.y = area.y;
180 mLRUArea.width = area.width;
181 mLRUArea.height = area.height;
182
183 wxDC* pBufDc = FindSuitableBuffer( area );
184
185 if ( !pBufDc )
186 pBufDc = AllocNewBuffer( area );
187
188 pBufDc->SetDeviceOrigin( -area.x, -area.y );
189
190 pBufDc->SetClippingRegion( area.x, area.y,
191 area.width, area.height );
192
193 wxClientDC clntDc( &mpLayout->GetParentFrame() );
194
195 (*event.mppDc) = pBufDc;
196
197 mpLRUBufDc = pBufDc; // memorize buffer, which will be flushed to screen
198 // upon "commiting" the drawing
199
200 /*
201 // OLD STUFF::
202 mpLRUBufDc->Blit( pos.x, pos.y, size.x, size.y,
203 &clntDc, pos.x, pos.y, wxCOPY );
204 */
205 }
206
207 void cbAntiflickerPlugin::OnFinishDrawInArea( cbFinishDrawInAreaEvent& event )
208 {
209 wxRect& area = event.mArea;
210
211 if ( event.mArea.width < 0 ||
212 event.mArea.height < 0 ) return;
213
214 wxASSERT( mpLRUBufDc ); // DBG:: OnStartDrawInArea should be called first
215
216 // FOR NOW:: OnStartDrawInArea(..) should be immediately followed
217 // by OnFinishDrawInArea(..) for the same area
218
219 wxASSERT( mLRUArea.x == area.x );
220 wxASSERT( mLRUArea.y == area.y );
221 wxASSERT( mLRUArea.width == area.width );
222 wxASSERT( mLRUArea.height == area.height );
223
224 wxClientDC clntDc( &mpLayout->GetParentFrame() );
225
226 // "commit" drawings in one-shot
227 clntDc.Blit( area.x, area.y, area.width, area.height,
228 mpLRUBufDc, area.x, area.y, wxCOPY );
229
230 mpLRUBufDc->DestroyClippingRegion();
231 mpLRUBufDc = 0;
232 }
233