]>
Commit | Line | Data |
---|---|---|
6a2c1874 RR |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: canvas.cpp | |
3 | // Author: Robert Roebling | |
4 | // Created: XX/XX/XX | |
5 | // Copyright: 2000 (c) Robert Roebling | |
6 | // Licence: wxWindows Licence | |
7 | ///////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | #ifdef __GNUG__ | |
10 | #pragma implementation "canvas.cpp" | |
11 | #endif | |
12 | ||
13 | // For compilers that support precompilation, includes "wx/wx.h". | |
14 | #include "wx/wxprec.h" | |
15 | ||
16 | #ifdef __BORLANDC__ | |
17 | #pragma hdrstop | |
18 | #endif | |
19 | ||
20 | #include "wx/canvas/canvas.h" | |
21 | ||
22 | #ifdef __WXGTK__ | |
23 | #include <gtk/gtk.h> | |
24 | #include <gdk/gdkrgb.h> | |
25 | #include "wx/gtk/win_gtk.h" | |
26 | #endif | |
27 | ||
28 | // WDR: class implementations | |
29 | ||
30 | //---------------------------------------------------------------------------- | |
31 | // wxCanvasObject | |
32 | //---------------------------------------------------------------------------- | |
33 | ||
34 | wxCanvasObject::wxCanvasObject( int x, int y, int width, int height ) | |
35 | { | |
36 | m_owner = NULL; | |
37 | m_area.x = x; | |
38 | m_area.y = y; | |
39 | m_area.width = width; | |
40 | m_area.height = height; | |
41 | m_isControl = FALSE; | |
42 | m_isVector = FALSE; | |
43 | m_isImage = FALSE; | |
44 | } | |
45 | ||
46 | void wxCanvasObject::Move( int x, int y ) | |
47 | { | |
48 | int old_x = m_area.x; | |
49 | int old_y = m_area.y; | |
50 | ||
51 | m_area.x = x; | |
52 | m_area.y = y; | |
53 | ||
54 | if (!m_isControl) | |
55 | { | |
56 | // TODO: sometimes faster to merge into 1 Update or | |
57 | // to break up into four | |
58 | m_owner->Update( old_x, old_y, m_area.width, m_area.height ); | |
59 | m_owner->Update( x, y, m_area.width, m_area.height ); | |
60 | } | |
61 | } | |
62 | ||
63 | void wxCanvasObject::WriteSVG( wxTextOutputStream &stream ) | |
64 | { | |
65 | } | |
66 | ||
67 | void wxCanvasObject::Render( int clip_x, int clip_y, int clip_width, int clip_height ) | |
68 | { | |
69 | } | |
70 | ||
71 | //---------------------------------------------------------------------------- | |
72 | // wxCanvasImage | |
73 | //---------------------------------------------------------------------------- | |
74 | ||
75 | wxCanvasImage::wxCanvasImage( const wxImage &image, int x, int y ) | |
76 | : wxCanvasObject( x, y, image.GetWidth(), image.GetHeight() ) | |
77 | { | |
78 | m_image = image; | |
79 | m_isImage = TRUE; | |
80 | } | |
81 | ||
82 | void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_height ) | |
83 | { | |
84 | m_owner->GetBuffer()->Paste( m_image, m_area.x, m_area.y ); | |
85 | } | |
86 | ||
87 | void wxCanvasImage::WriteSVG( wxTextOutputStream &stream ) | |
88 | { | |
89 | // no idea | |
90 | } | |
91 | ||
3b111dbe RR |
92 | //---------------------------------------------------------------------------- |
93 | // wxCanvasCtrl | |
94 | //---------------------------------------------------------------------------- | |
95 | ||
96 | wxCanvasControl::wxCanvasControl( wxWindow *control ) | |
97 | : wxCanvasObject( -1, -1, -1, -1 ) | |
98 | { | |
99 | m_control = control; | |
100 | UpdateSize(); | |
101 | } | |
102 | ||
103 | wxCanvasControl::~wxCanvasControl() | |
104 | { | |
105 | m_control->Destroy(); | |
106 | } | |
107 | ||
108 | void wxCanvasControl::Move( int x, int y ) | |
109 | { | |
110 | m_control->Move( x, y ); | |
111 | } | |
112 | ||
113 | void wxCanvasControl::UpdateSize() | |
114 | { | |
115 | m_control->GetSize( &m_area.width, &m_area.height ); | |
116 | m_control->GetPosition( &m_area.x, &m_area.y ); | |
117 | } | |
118 | ||
6a2c1874 RR |
119 | //---------------------------------------------------------------------------- |
120 | // wxCanvas | |
121 | //---------------------------------------------------------------------------- | |
122 | ||
123 | IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow) | |
124 | ||
125 | BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow) | |
126 | EVT_CHAR( wxCanvas::OnChar ) | |
127 | EVT_PAINT( wxCanvas::OnPaint ) | |
128 | EVT_SIZE( wxCanvas::OnSize ) | |
129 | EVT_IDLE( wxCanvas::OnIdle ) | |
130 | EVT_MOUSE_EVENTS( wxCanvas::OnMouse ) | |
131 | EVT_SET_FOCUS( wxCanvas::OnSetFocus ) | |
132 | EVT_KILL_FOCUS( wxCanvas::OnKillFocus ) | |
133 | END_EVENT_TABLE() | |
134 | ||
135 | wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id, | |
136 | const wxPoint &position, const wxSize& size, long style ) : | |
137 | wxScrolledWindow( parent, id, position, size, style ) | |
138 | { | |
139 | m_needUpdate = FALSE; | |
140 | m_objects.DeleteContents( TRUE ); | |
141 | } | |
142 | ||
143 | wxCanvas::~wxCanvas() | |
144 | { | |
145 | wxNode *node = m_updateRects.First(); | |
146 | while (node) | |
147 | { | |
148 | wxRect *rect = (wxRect*) node->Data(); | |
149 | delete rect; | |
150 | m_updateRects.DeleteNode( node ); | |
151 | node = m_updateRects.First(); | |
152 | } | |
153 | } | |
154 | ||
155 | void wxCanvas::SetArea( int width, int height ) | |
156 | { | |
157 | m_buffer = wxImage( width, height ); | |
158 | SetScrollbars( 10, 10, width/10, height/10 ); | |
159 | } | |
160 | ||
161 | void wxCanvas::Update( int x, int y, int width, int height ) | |
162 | { | |
163 | m_needUpdate = TRUE; | |
164 | ||
165 | m_updateRects.Append( | |
166 | (wxObject*) new wxRect( x,y,width,height ) ); | |
167 | ||
168 | // speed up with direct access | |
169 | int xx,yy,ww,hh; | |
170 | for (yy = y; yy < y+height; yy++) | |
171 | for (xx = x; xx < x+width; xx++) | |
172 | m_buffer.SetRGB( xx, yy, 0, 0, 0 ); | |
173 | ||
174 | wxNode *node = m_objects.First(); | |
175 | while (node) | |
176 | { | |
177 | wxCanvasObject *obj = (wxCanvasObject*) node->Data(); | |
178 | xx = obj->GetX(); | |
179 | yy = obj->GetY(); | |
180 | ww = obj->GetWidth(); | |
181 | hh = obj->GetHeight(); | |
182 | ||
3b111dbe | 183 | if (!obj->IsControl()) |
6a2c1874 RR |
184 | { |
185 | obj->Render( x, y, width, height ); | |
186 | } | |
187 | ||
188 | node = node->Next(); | |
189 | } | |
190 | } | |
191 | ||
3b111dbe | 192 | void wxCanvas::BlitBuffer( wxDC &dc ) |
6a2c1874 | 193 | { |
6a2c1874 RR |
194 | wxNode *node = m_updateRects.First(); |
195 | while (node) | |
196 | { | |
197 | wxRect *rect = (wxRect*) node->Data(); | |
198 | wxImage sub_image( m_buffer.GetSubImage( *rect ) ); | |
199 | ||
200 | // DirectDraw here, please | |
201 | ||
202 | #ifdef __WXGTK__ | |
203 | int bpp = wxDisplayDepth(); | |
204 | if (bpp > 8) | |
205 | { | |
206 | // the init code is doubled in wxImage | |
207 | static bool s_hasInitialized = FALSE; | |
208 | ||
209 | if (!s_hasInitialized) | |
210 | { | |
211 | gdk_rgb_init(); | |
212 | s_hasInitialized = TRUE; | |
213 | } | |
214 | ||
215 | int x = rect->x; | |
216 | int y = rect->y; | |
217 | CalcScrolledPosition( x, y, &x, &y ); | |
218 | ||
219 | gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow)->bin_window, | |
220 | m_wxwindow->style->black_gc, | |
221 | x, y, | |
222 | sub_image.GetWidth(), sub_image.GetHeight(), | |
223 | GDK_RGB_DITHER_NONE, | |
224 | sub_image.GetData(), | |
225 | sub_image.GetWidth()*3 ); | |
226 | } | |
227 | else | |
228 | { | |
229 | wxBitmap bitmap( sub_image.ConvertToBitmap() ); | |
230 | dc.DrawBitmap( bitmap, rect->x, rect->y ); | |
231 | } | |
232 | #endif | |
233 | ||
234 | #ifndef __WXGTK__ | |
235 | wxBitmap bitmap( sub_image.ConvertToBitmap() ); | |
236 | dc.DrawBitmap( bitmap, rect->x, rect->y ); | |
237 | #endif | |
238 | ||
239 | delete rect; | |
240 | m_updateRects.DeleteNode( node ); | |
241 | node = m_updateRects.First(); | |
242 | } | |
3b111dbe RR |
243 | |
244 | m_needUpdate = FALSE; | |
245 | } | |
246 | ||
247 | void wxCanvas::UpdateNow() | |
248 | { | |
249 | if (!m_needUpdate) return; | |
250 | ||
251 | wxClientDC dc( this ); | |
252 | PrepareDC( dc ); | |
253 | ||
254 | BlitBuffer( dc ); | |
6a2c1874 RR |
255 | } |
256 | ||
257 | void wxCanvas::Prepend( wxCanvasObject* obj ) | |
258 | { | |
259 | m_objects.Insert( obj ); | |
260 | ||
261 | obj->SetOwner( this ); | |
262 | ||
263 | if (!obj->IsControl()) | |
264 | Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); | |
265 | } | |
266 | ||
267 | void wxCanvas::Append( wxCanvasObject* obj ) | |
268 | { | |
269 | m_objects.Append( obj ); | |
270 | ||
271 | obj->SetOwner( this ); | |
272 | ||
273 | if (!obj->IsControl()) | |
274 | Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); | |
275 | } | |
276 | ||
277 | void wxCanvas::Insert( size_t before, wxCanvasObject* obj ) | |
278 | { | |
279 | m_objects.Insert( before, obj ); | |
280 | ||
281 | obj->SetOwner( this ); | |
282 | ||
283 | if (!obj->IsControl()) | |
284 | Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); | |
285 | } | |
286 | ||
287 | void wxCanvas::Remove( wxCanvasObject* obj ) | |
288 | { | |
289 | int x = obj->GetX(); | |
290 | int y = obj->GetY(); | |
291 | int w = obj->GetWidth(); | |
292 | int h = obj->GetHeight(); | |
293 | bool ic = obj->IsControl(); | |
294 | ||
295 | m_objects.DeleteObject( obj ); | |
296 | ||
297 | if (!ic) | |
298 | Update( x, y, w, h ); | |
299 | } | |
300 | ||
301 | void wxCanvas::OnPaint(wxPaintEvent &event) | |
302 | { | |
6a2c1874 | 303 | wxPaintDC dc(this); |
3b111dbe | 304 | PrepareDC( dc ); |
6a2c1874 RR |
305 | |
306 | m_needUpdate = TRUE; | |
307 | ||
308 | wxRegionIterator it( GetUpdateRegion() ); | |
309 | while (it) | |
310 | { | |
311 | int x = it.GetX(); | |
312 | int y = it.GetY(); | |
313 | CalcUnscrolledPosition( x, y, &x, &y ); | |
314 | ||
315 | int w = it.GetWidth(); | |
316 | int h = it.GetHeight(); | |
317 | if (x + w > m_buffer.GetWidth()) | |
318 | w = m_buffer.GetWidth()-x; | |
319 | if (y + h > m_buffer.GetHeight()) | |
320 | h = m_buffer.GetHeight()-y; | |
321 | ||
322 | m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) ); | |
323 | ||
324 | it++; | |
325 | } | |
3b111dbe RR |
326 | |
327 | BlitBuffer( dc ); | |
6a2c1874 RR |
328 | } |
329 | ||
330 | void wxCanvas::OnMouse(wxMouseEvent &event) | |
331 | { | |
332 | // Propagate to objects here | |
333 | } | |
334 | ||
335 | void wxCanvas::OnSize(wxSizeEvent &event) | |
336 | { | |
337 | event.Skip(); | |
338 | } | |
339 | ||
340 | void wxCanvas::OnIdle(wxIdleEvent &event) | |
341 | { | |
342 | UpdateNow(); | |
343 | event.Skip(); | |
344 | } | |
345 | ||
346 | void wxCanvas::OnSetFocus(wxFocusEvent &event) | |
347 | { | |
348 | } | |
349 | ||
350 | void wxCanvas::OnKillFocus(wxFocusEvent &event) | |
351 | { | |
352 | } | |
353 | ||
354 | void wxCanvas::OnChar(wxKeyEvent &event) | |
355 | { | |
356 | event.Skip(); | |
357 | } | |
358 | ||
359 |