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