]>
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 | ||
f9032263 RR |
20 | #include "wx/canvas/canvas.h" |
21 | #include "wx/canvas/polygon.h" | |
22 | #include "wx/canvas/liner.h" | |
6a2c1874 RR |
23 | |
24 | #ifdef __WXGTK__ | |
25 | #include <gtk/gtk.h> | |
26 | #include <gdk/gdkrgb.h> | |
27 | #include "wx/gtk/win_gtk.h" | |
28 | #endif | |
29 | ||
1e1af41e | 30 | #ifndef wxUSE_FREETYPE |
84fba40b | 31 | #define wxUSE_FREETYPE 0 |
1e1af41e | 32 | #endif |
d1f9b206 | 33 | |
1e1af41e RR |
34 | #if wxUSE_FREETYPE |
35 | #include <freetype/freetype.h> | |
d1f9b206 RR |
36 | #endif |
37 | ||
84fba40b RR |
38 | //#define CANVASDEBUG |
39 | ||
d1f9b206 RR |
40 | //---------------------------------------------------------------------------- |
41 | // globals | |
42 | //---------------------------------------------------------------------------- | |
43 | ||
2a66db28 | 44 | static const double pi = 3.1415926535; |
84fba40b | 45 | |
1e1af41e | 46 | #if wxUSE_FREETYPE |
d1f9b206 RR |
47 | FT_Library g_freetypeLibrary; |
48 | #endif | |
6a2c1874 RR |
49 | |
50 | //---------------------------------------------------------------------------- | |
51 | // wxCanvasObject | |
52 | //---------------------------------------------------------------------------- | |
f03b31e8 | 53 | |
a977709b JS |
54 | IMPLEMENT_CLASS(wxCanvasObject, wxEvtHandler) |
55 | ||
4dbd4ee6 | 56 | wxCanvasObject::wxCanvasObject() |
6a2c1874 | 57 | { |
84fba40b RR |
58 | // the default event handler is just this object |
59 | m_eventHandler=this; | |
60 | m_admin = NULL; | |
4dbd4ee6 RR |
61 | m_isControl = FALSE; |
62 | m_isVector = FALSE; | |
63 | m_isImage = FALSE; | |
84fba40b | 64 | m_visible = TRUE; |
b5789150 | 65 | m_dragmode = wxDRAG_ONTOP; |
84fba40b | 66 | // handy when debugging |
b5789150 | 67 | // m_dragmode = wxDRAG_RECTANGLE; |
84fba40b RR |
68 | m_dragable = TRUE; |
69 | } | |
70 | ||
71 | bool wxCanvasObject::ProcessCanvasObjectEvent(wxEvent& event) | |
72 | { | |
73 | return m_eventHandler->ProcessEvent(event); | |
74 | } | |
75 | ||
76 | void wxCanvasObject::PushEventHandler(wxEvtHandler *handler) | |
77 | { | |
78 | handler->SetNextHandler(GetEventHandler()); | |
79 | m_eventHandler=handler; | |
80 | } | |
81 | ||
82 | wxEvtHandler *wxCanvasObject::PopEventHandler(bool deleteHandler) | |
83 | { | |
84 | wxEvtHandler *handlerA = m_eventHandler; | |
85 | if ( handlerA ) | |
86 | { | |
87 | wxEvtHandler *handlerB = handlerA->GetNextHandler(); | |
88 | handlerA->SetNextHandler((wxEvtHandler *)NULL); | |
89 | m_eventHandler=handlerB; | |
90 | if ( deleteHandler ) | |
91 | { | |
92 | delete handlerA; | |
93 | handlerA = (wxEvtHandler *)NULL; | |
94 | } | |
95 | } | |
96 | ||
97 | return handlerA; | |
98 | } | |
99 | ||
100 | void wxCanvasObject::AppendEventHandler(wxEvtHandler *handler) | |
101 | { | |
102 | GetEventHandler()->SetNextHandler(handler); | |
103 | } | |
104 | ||
105 | wxEvtHandler *wxCanvasObject::RemoveLastEventHandler(bool deleteHandler) | |
106 | { | |
107 | //always the first in the row | |
108 | wxEvtHandler *handlerA = m_eventHandler; | |
109 | wxEvtHandler *handlerB=handlerA; | |
110 | //goto the end | |
111 | while ( handlerA->GetNextHandler() ) | |
112 | { | |
113 | handlerB = handlerA; | |
114 | handlerA = handlerA->GetNextHandler(); | |
115 | } | |
116 | ||
117 | handlerB->SetNextHandler((wxEvtHandler *)NULL); | |
118 | if ( deleteHandler ) | |
119 | { | |
120 | delete handlerA; | |
121 | } | |
122 | ||
123 | return GetEventHandler(); | |
124 | } | |
125 | ||
126 | wxRect wxCanvasObject::GetAbsoluteArea(const wxTransformMatrix& cworld) | |
127 | { | |
84fba40b RR |
128 | wxBoundingBox tmp=m_bbox; |
129 | tmp.MapBbox(cworld); | |
130 | ||
84fba40b RR |
131 | int x1 = m_admin->LogicalToDeviceX( tmp.GetMinX() ); |
132 | int y1 = m_admin->LogicalToDeviceY( tmp.GetMinY() ); | |
133 | int x2 = m_admin->LogicalToDeviceX( tmp.GetMaxX() ); | |
134 | int y2 = m_admin->LogicalToDeviceY( tmp.GetMaxY() ); | |
135 | ||
136 | if (x1 > x2) | |
137 | { | |
138 | int tmp = x1; | |
139 | x1 = x2; | |
140 | x2 = tmp; | |
141 | } | |
142 | if (y1 > y2) | |
143 | { | |
144 | int tmp = y1; | |
145 | y1 = y2; | |
146 | y2 = tmp; | |
147 | } | |
148 | ||
149 | wxRect tmparea; | |
150 | tmparea.x = x1; | |
151 | tmparea.y = y1; | |
8636c073 RR |
152 | tmparea.width = x2-x1; // FIXME +1 ? |
153 | tmparea.height = y2-y1; // FIXME +1 ? | |
84fba40b RR |
154 | |
155 | return tmparea; | |
156 | } | |
157 | ||
158 | void wxCanvasObject::MoveAbsolute( double x, double y ) | |
159 | { | |
160 | //save old position of boundingbox | |
161 | double oldx = GetXMin(); | |
162 | double oldy = GetYMin(); | |
163 | double w = m_bbox.GetWidth(); | |
164 | double h = m_bbox.GetHeight(); | |
165 | ||
166 | SetPosXY(x,y); | |
167 | ||
168 | double newx=GetXMin(); | |
169 | double newy=GetYMin(); | |
170 | ||
171 | double leftu,rightu,bottomu,topu ; | |
172 | leftu = wxMin (oldx, newx ) ; | |
173 | rightu = wxMax (oldx + w, newx + w) ; | |
174 | topu = wxMin (oldy, newy) ; | |
175 | bottomu = wxMax (oldy + h, newy + h) ; | |
176 | ||
177 | if ( rightu - leftu < 2*w && bottomu - topu < 2*h ) | |
178 | { | |
179 | m_admin->Update( this,leftu, topu, rightu - leftu, bottomu - topu); | |
180 | } | |
181 | else | |
182 | { | |
183 | m_admin->Update( this, oldx, oldy, w, h ); | |
184 | m_admin->Update( this, newx, newy, w, h ); | |
185 | } | |
4dbd4ee6 RR |
186 | } |
187 | ||
84fba40b | 188 | void wxCanvasObject::MoveRelative( double x, double y ) |
4dbd4ee6 | 189 | { |
84fba40b RR |
190 | //save old position of boundingbox |
191 | double oldx = GetXMin(); | |
192 | double oldy = GetYMin(); | |
193 | double w = m_bbox.GetWidth(); | |
194 | double h = m_bbox.GetHeight(); | |
195 | ||
196 | TransLate(x,y); | |
197 | ||
198 | double newx=GetXMin(); | |
199 | double newy=GetYMin(); | |
200 | ||
201 | double leftu,rightu,bottomu,topu ; | |
202 | leftu = wxMin (oldx, newx ) ; | |
203 | rightu = wxMax (oldx + w, newx + w) ; | |
204 | topu = wxMin (oldy, newy) ; | |
205 | bottomu = wxMax (oldy + h, newy + h) ; | |
206 | ||
207 | if ( rightu - leftu < 2*w && bottomu - topu < 2*h ) | |
208 | { | |
209 | m_admin->Update( this,leftu, topu, rightu - leftu, bottomu - topu); | |
210 | } | |
211 | else | |
212 | { | |
213 | m_admin->Update( this, oldx, oldy, w, h ); | |
214 | m_admin->Update( this, newx, newy, w, h ); | |
215 | } | |
4dbd4ee6 RR |
216 | } |
217 | ||
84fba40b RR |
218 | |
219 | void wxCanvasObject::DragStart() | |
4dbd4ee6 | 220 | { |
b5789150 | 221 | if (m_dragmode == wxDRAG_RECTANGLE) |
84fba40b RR |
222 | { |
223 | this->SetVisible(FALSE); | |
224 | wxTransformMatrix help; | |
225 | double x = GetXMin(); | |
226 | double y = GetYMin(); | |
227 | double w = m_bbox.GetWidth(); | |
228 | double h = m_bbox.GetHeight(); | |
229 | m_admin->Update( this, x, y, w, h ); | |
230 | m_admin->UpdateNow(); | |
231 | ||
232 | wxRect recold=GetAbsoluteArea(help); | |
233 | wxClientDC dc(m_admin->GetActive()); | |
234 | dc.SetPen(*wxBLACK_PEN); | |
235 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | |
236 | dc.SetLogicalFunction(wxINVERT); | |
237 | dc.DrawRectangle(recold); | |
238 | dc.SetBrush(wxNullBrush); | |
239 | dc.SetPen(wxNullPen); | |
240 | } | |
b5789150 | 241 | else if (m_dragmode != wxDRAG_REDRAW) |
84fba40b RR |
242 | { |
243 | this->SetVisible(FALSE); | |
244 | wxTransformMatrix help; | |
245 | double x = GetXMin(); | |
246 | double y = GetYMin(); | |
247 | double w = m_bbox.GetWidth(); | |
248 | double h = m_bbox.GetHeight(); | |
249 | ||
250 | wxRect recnew=GetAbsoluteArea(help); | |
251 | ||
252 | //redraw in buffer what should be there without this object | |
253 | m_admin->Update( this, x, y, w, h ); | |
254 | m_admin->GetActive()->Freeze(); | |
255 | ||
256 | //save the drawing (without the object itself to a bitmap) | |
257 | m_atnewpos = wxBitmap(recnew.width,recnew.height); | |
258 | wxMemoryDC dcm; | |
259 | dcm.SelectObject(*m_admin->GetActive()->GetBuffer()); | |
260 | wxMemoryDC tmp; | |
261 | tmp.SelectObject(m_atnewpos); | |
262 | tmp.Blit(0,0,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE); | |
263 | tmp.SelectObject(wxNullBitmap); | |
264 | dcm.SelectObject(wxNullBitmap); | |
265 | } | |
6a2c1874 RR |
266 | } |
267 | ||
84fba40b RR |
268 | |
269 | void wxCanvasObject::DragRelative( double x, double y) | |
6a2c1874 | 270 | { |
b5789150 | 271 | if (m_dragmode == wxDRAG_RECTANGLE) |
84fba40b RR |
272 | { |
273 | wxTransformMatrix help; | |
5143c96b | 274 | |
84fba40b | 275 | wxRect recold=GetAbsoluteArea(help); |
dc16900b | 276 | |
84fba40b RR |
277 | TransLate(x,y); |
278 | ||
279 | wxRect recnew=GetAbsoluteArea(help); | |
280 | ||
281 | wxClientDC dc(m_admin->GetActive()); | |
282 | dc.SetPen(*wxBLACK_PEN); | |
283 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | |
284 | dc.SetLogicalFunction(wxINVERT); | |
285 | dc.DrawRectangle(recold); | |
286 | dc.DrawRectangle(recnew); | |
287 | dc.SetBrush(wxNullBrush); | |
288 | dc.SetPen(wxNullPen); | |
289 | } | |
b5789150 | 290 | else if (m_dragmode != wxDRAG_REDRAW) |
6a2c1874 | 291 | { |
84fba40b RR |
292 | wxClientDC dc(m_admin->GetActive()); |
293 | wxMemoryDC tmp; | |
294 | ||
295 | wxTransformMatrix help; | |
296 | wxRect recold=GetAbsoluteArea(help); | |
297 | ||
298 | //restore what was there (without the object itself) | |
299 | wxMemoryDC dcm; | |
300 | dcm.SelectObject(*m_admin->GetActive()->GetBuffer()); | |
301 | tmp.SelectObject(m_atnewpos); | |
302 | dcm.Blit(recold.x,recold.y,recold.width,recold.height,&tmp,0,0,wxCOPY,FALSE); | |
303 | ||
304 | TransLate(x,y); | |
305 | ||
306 | wxRect recnew=GetAbsoluteArea(help); | |
307 | ||
308 | //save the contents of the buffer at the new position | |
309 | tmp.Blit(0,0,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE); | |
310 | tmp.SelectObject(wxNullBitmap); | |
311 | ||
312 | //m_atnewpos = m_admin->GetActive()->GetBuffer()->GetSubBitmap( recnew ); | |
313 | ||
314 | this->SetVisible(TRUE); | |
315 | //redraw object into the buffer | |
316 | m_admin->GetActive()->SetDC(&dcm); | |
317 | Render(&help,recnew.x,recnew.y,recnew.width,recnew.height); | |
318 | ||
319 | //draw the union or seperate to the canvas | |
320 | double leftu,rightu,bottomu,topu ; | |
321 | leftu = wxMin (recold.x, recnew.x ) ; | |
322 | rightu = wxMax (recold.x + recold.width, recnew.x + recnew.width ) ; | |
323 | topu = wxMin (recold.y, recnew.y) ; | |
324 | bottomu = wxMax (recold.y + recold.height, recnew.y + recnew.height) ; | |
325 | ||
326 | if ( rightu - leftu < 2*recold.width && bottomu - topu < 2*recold.height) | |
327 | { | |
328 | dc.Blit(leftu,topu,rightu - leftu,bottomu - topu,&dcm,leftu,topu,wxCOPY,FALSE); | |
329 | } | |
330 | else | |
331 | { | |
332 | //do them seperate | |
333 | //first redraw what should be at the old position in the canvas | |
334 | dc.Blit(recold.x,recold.y,recold.width,recold.height,&dcm,recold.x,recold.y,wxCOPY,FALSE); | |
335 | //blit the new position of the object to the canvas | |
336 | dc.Blit(recnew.x,recnew.y,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE); | |
337 | } | |
338 | dcm.SelectObject(wxNullBitmap); | |
339 | this->SetVisible(FALSE); | |
6a2c1874 | 340 | } |
b5789150 RR |
341 | else |
342 | MoveRelative(x,y); | |
84fba40b RR |
343 | } |
344 | ||
345 | ||
346 | void wxCanvasObject::DragEnd() | |
347 | { | |
84fba40b RR |
348 | m_atnewpos = wxBitmap(0,0); |
349 | m_admin->GetActive()->Thaw(); | |
350 | this->SetVisible(TRUE); | |
351 | double x = GetXMin(); | |
352 | double y = GetYMin(); | |
353 | double w = m_bbox.GetWidth(); | |
354 | double h = m_bbox.GetHeight(); | |
355 | m_admin->Update( this, x, y, w, h ); | |
356 | m_admin->UpdateNow(); | |
84fba40b RR |
357 | } |
358 | ||
359 | wxCanvasObject* wxCanvasObject::IsHitWorld( double x, double y, double margin ) | |
360 | { | |
361 | if ((x >= m_bbox.GetMinX()-margin) && | |
362 | (x <= m_bbox.GetMaxX()+margin) && | |
363 | (y >= m_bbox.GetMinY()-margin) && | |
f03b31e8 RR |
364 | (y <= m_bbox.GetMaxY()+margin)) |
365 | { | |
84fba40b | 366 | return this; |
f03b31e8 RR |
367 | } |
368 | ||
84fba40b | 369 | return (wxCanvasObject*) NULL; |
6a2c1874 RR |
370 | } |
371 | ||
84fba40b | 372 | wxCanvasObject* wxCanvasObject::Contains( wxCanvasObject* obj ) |
239c1f50 | 373 | { |
84fba40b RR |
374 | if (obj == this) |
375 | return this; | |
f03b31e8 | 376 | |
84fba40b | 377 | return (wxCanvasObject*) NULL; |
239c1f50 RR |
378 | } |
379 | ||
dc16900b KH |
380 | void wxCanvasObject::CaptureMouse() |
381 | { | |
84fba40b | 382 | m_admin->GetActive()->SetCaptureMouse( this ); |
dc16900b KH |
383 | } |
384 | ||
385 | void wxCanvasObject::ReleaseMouse() | |
386 | { | |
84fba40b | 387 | m_admin->GetActive()->SetCaptureMouse( NULL ); |
dc16900b KH |
388 | } |
389 | ||
390 | bool wxCanvasObject::IsCapturedMouse() | |
391 | { | |
f03b31e8 | 392 | return (m_admin->GetActive()->GetCaptured() == this); |
dc16900b KH |
393 | } |
394 | ||
395 | ||
84fba40b | 396 | void wxCanvasObject::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height ) |
6a2c1874 RR |
397 | { |
398 | } | |
399 | ||
84fba40b | 400 | void wxCanvasObject::CalcBoundingBox() |
1e1af41e RR |
401 | { |
402 | } | |
403 | ||
404 | void wxCanvasObject::WriteSVG( wxTextOutputStream &stream ) | |
6a2c1874 RR |
405 | { |
406 | } | |
407 | ||
fcbb6b37 KH |
408 | //---------------------------------------------------------------------------- |
409 | // wxCanvasObjectGroup | |
410 | //---------------------------------------------------------------------------- | |
411 | ||
a977709b JS |
412 | IMPLEMENT_CLASS(wxCanvasObjectGroup, wxCanvasObject) |
413 | ||
84fba40b | 414 | wxCanvasObjectGroup::wxCanvasObjectGroup(double x, double y) |
fcbb6b37 | 415 | { |
84fba40b RR |
416 | lworld.Translate(x,y); |
417 | //no objects make the bounding box the x,y and take care of it later | |
418 | m_bbox.Expand(x,y); | |
21840a6c RR |
419 | } |
420 | ||
421 | wxCanvasObjectGroup::~wxCanvasObjectGroup() | |
422 | { | |
fcbb6b37 KH |
423 | } |
424 | ||
84fba40b | 425 | void wxCanvasObjectGroup::PushEventHandler(wxEvtHandler *handler) |
fcbb6b37 | 426 | { |
84fba40b | 427 | wxCanvasObject::PushEventHandler(handler); |
fcbb6b37 KH |
428 | wxNode *node = m_objects.First(); |
429 | while (node) | |
430 | { | |
431 | wxCanvasObject *obj = (wxCanvasObject*) node->Data(); | |
432 | ||
84fba40b | 433 | obj->PushEventHandler(handler); |
fcbb6b37 KH |
434 | |
435 | node = node->Next(); | |
436 | } | |
437 | } | |
438 | ||
84fba40b | 439 | wxEvtHandler *wxCanvasObjectGroup::PopEventHandler(bool deleteHandler) |
fcbb6b37 | 440 | { |
84fba40b RR |
441 | wxNode *node = m_objects.First(); |
442 | while (node) | |
21840a6c | 443 | { |
84fba40b RR |
444 | wxCanvasObject *obj = (wxCanvasObject*) node->Data(); |
445 | ||
446 | obj->PopEventHandler(deleteHandler); | |
447 | ||
448 | node = node->Next(); | |
21840a6c | 449 | } |
84fba40b RR |
450 | return wxCanvasObject::PopEventHandler(deleteHandler); |
451 | } | |
452 | ||
453 | void wxCanvasObjectGroup::AppendEventHandler(wxEvtHandler *handler) | |
454 | { | |
455 | wxCanvasObject::AppendEventHandler(handler); | |
456 | wxNode *node = m_objects.First(); | |
457 | while (node) | |
458 | { | |
459 | wxCanvasObject *obj = (wxCanvasObject*) node->Data(); | |
460 | ||
461 | obj->AppendEventHandler(handler); | |
462 | ||
463 | node = node->Next(); | |
464 | } | |
465 | } | |
466 | ||
467 | wxEvtHandler *wxCanvasObjectGroup::RemoveLastEventHandler(bool deleteHandler) | |
468 | { | |
469 | wxNode *node = m_objects.First(); | |
470 | while (node) | |
471 | { | |
472 | wxCanvasObject *obj = (wxCanvasObject*) node->Data(); | |
473 | ||
474 | obj->RemoveLastEventHandler(deleteHandler); | |
475 | ||
476 | node = node->Next(); | |
477 | } | |
478 | return wxCanvasObject::RemoveLastEventHandler(deleteHandler); | |
479 | } | |
480 | ||
481 | void wxCanvasObjectGroup::TransLate( double x, double y ) | |
482 | { | |
483 | lworld.Translate(x,y); | |
484 | CalcBoundingBox(); | |
485 | } | |
486 | ||
487 | void wxCanvasObjectGroup::SetAdmin(wxCanvasAdmin* admin) | |
488 | { | |
489 | m_admin=admin; | |
490 | wxNode *node = m_objects.First(); | |
491 | while (node) | |
21840a6c | 492 | { |
84fba40b RR |
493 | wxCanvasObject *obj = (wxCanvasObject*) node->Data(); |
494 | ||
495 | obj->SetAdmin(admin); | |
fcbb6b37 | 496 | |
84fba40b | 497 | node = node->Next(); |
21840a6c | 498 | } |
fcbb6b37 KH |
499 | } |
500 | ||
fcbb6b37 KH |
501 | void wxCanvasObjectGroup::DeleteContents( bool flag) |
502 | { | |
503 | m_objects.DeleteContents( flag ); | |
84fba40b RR |
504 | m_bbox.SetValid(FALSE); |
505 | CalcBoundingBox(); | |
fcbb6b37 KH |
506 | } |
507 | ||
fcbb6b37 KH |
508 | void wxCanvasObjectGroup::Prepend( wxCanvasObject* obj ) |
509 | { | |
510 | m_objects.Insert( obj ); | |
84fba40b | 511 | if (m_objects.First()) |
f03b31e8 | 512 | { |
84fba40b | 513 | m_bbox.Expand(obj->GetBbox()); |
f03b31e8 | 514 | } |
84fba40b RR |
515 | else |
516 | { | |
517 | m_bbox.SetValid(FALSE); | |
518 | CalcBoundingBox(); | |
519 | } | |
fcbb6b37 KH |
520 | } |
521 | ||
522 | void wxCanvasObjectGroup::Append( wxCanvasObject* obj ) | |
523 | { | |
524 | m_objects.Append( obj ); | |
84fba40b | 525 | if (m_objects.First()) |
f03b31e8 | 526 | { |
84fba40b | 527 | m_bbox.Expand(obj->GetBbox()); |
f03b31e8 | 528 | } |
84fba40b RR |
529 | else |
530 | { | |
531 | m_bbox.SetValid(FALSE); | |
532 | CalcBoundingBox(); | |
533 | } | |
fcbb6b37 KH |
534 | } |
535 | ||
536 | void wxCanvasObjectGroup::Insert( size_t before, wxCanvasObject* obj ) | |
537 | { | |
538 | m_objects.Insert( before, obj ); | |
84fba40b RR |
539 | m_bbox.SetValid(FALSE); |
540 | if (m_objects.First()) | |
f03b31e8 | 541 | { |
84fba40b | 542 | m_bbox.Expand(obj->GetBbox()); |
f03b31e8 | 543 | } |
84fba40b RR |
544 | else |
545 | { | |
546 | m_bbox.SetValid(FALSE); | |
547 | CalcBoundingBox(); | |
548 | } | |
fcbb6b37 KH |
549 | } |
550 | ||
551 | void wxCanvasObjectGroup::Remove( wxCanvasObject* obj ) | |
552 | { | |
553 | m_objects.DeleteObject( obj ); | |
84fba40b RR |
554 | m_bbox.SetValid(FALSE); |
555 | CalcBoundingBox(); | |
fcbb6b37 KH |
556 | } |
557 | ||
84fba40b | 558 | void wxCanvasObjectGroup::CalcBoundingBox() |
fcbb6b37 | 559 | { |
84fba40b | 560 | m_bbox.SetValid(FALSE); |
fcbb6b37 KH |
561 | wxNode *node = m_objects.First(); |
562 | while (node) | |
563 | { | |
564 | wxCanvasObject *obj = (wxCanvasObject*) node->Data(); | |
565 | ||
fcbb6b37 | 566 | |
84fba40b RR |
567 | obj->CalcBoundingBox(); |
568 | wxBoundingBox tmp; | |
569 | tmp=obj->GetBbox(); | |
570 | tmp.MapBbox(lworld); | |
571 | ||
572 | m_bbox.Expand( tmp ); | |
fcbb6b37 KH |
573 | node = node->Next(); |
574 | } | |
575 | } | |
576 | ||
84fba40b | 577 | void wxCanvasObjectGroup::Render(wxTransformMatrix* cworld, int x, int y, int width, int height ) |
fcbb6b37 | 578 | { |
84fba40b RR |
579 | if (!m_visible) return; |
580 | ||
581 | wxTransformMatrix backup = *cworld; | |
582 | *cworld *= lworld; | |
583 | ||
fcbb6b37 | 584 | wxNode *node = m_objects.First(); |
84fba40b RR |
585 | |
586 | if (!node) return; | |
587 | ||
588 | ||
589 | #ifdef CANVASDEBUG | |
590 | wxRect absarea=GetAbsoluteArea(*cworld); | |
591 | wxDC *dc = m_admin->GetActive()->GetDC(); | |
592 | dc->SetPen(*wxBLACK_PEN); | |
593 | dc->SetBrush(*wxTRANSPARENT_BRUSH); | |
594 | dc->DrawRectangle( absarea.x , absarea.y , absarea.width , absarea.height ); | |
595 | dc->SetBrush(wxNullBrush); | |
596 | dc->SetPen(wxNullPen); | |
597 | #endif | |
598 | //TODO the next will only work if all boundingboxes stay up to date (problem when mowing currently | |
599 | /* | |
600 | if (! ( wxMax(absarea.x, x) < wxMin(absarea.x + absarea.width , x + width ) && | |
601 | wxMax(absarea.y, y) < wxMin(absarea.y + absarea.height , y + height ) | |
602 | ) | |
603 | ) | |
604 | return; | |
605 | */ | |
606 | ||
607 | // cycle through all objects | |
fcbb6b37 KH |
608 | while (node) |
609 | { | |
610 | wxCanvasObject *obj = (wxCanvasObject*) node->Data(); | |
611 | ||
84fba40b | 612 | if (!obj->IsControl() && obj->GetVisible()) |
fcbb6b37 | 613 | { |
84fba40b RR |
614 | |
615 | //get area at the absolute position | |
8636c073 RR |
616 | wxRect absareaobject = obj->GetAbsoluteArea(*cworld); |
617 | ||
fcbb6b37 KH |
618 | // If we have 10.000 objects, we will go through |
619 | // this 10.000 times for each update, so we have | |
620 | // to optimise carefully. | |
84fba40b RR |
621 | int clip_x = absareaobject.x; |
622 | int clip_width = absareaobject.width; | |
fcbb6b37 KH |
623 | if (clip_x < x) |
624 | { | |
625 | clip_width -= x-clip_x; | |
626 | clip_x = x; | |
627 | } | |
628 | if (clip_width > 0) | |
629 | { | |
630 | if (clip_x + clip_width > x + width) | |
631 | clip_width = x+width-clip_x; | |
632 | ||
633 | if (clip_width > 0) | |
634 | { | |
84fba40b RR |
635 | int clip_y = absareaobject.y; |
636 | int clip_height = absareaobject.height; | |
fcbb6b37 KH |
637 | if (clip_y < y) |
638 | { | |
639 | clip_height -= y-clip_y; | |
640 | clip_y = y; | |
641 | } | |
642 | if (clip_height > 0) | |
643 | { | |
644 | if (clip_y + clip_height > y + height) | |
645 | clip_height = y+height-clip_y; | |
646 | ||
647 | if (clip_height > 0) | |
84fba40b RR |
648 | { |
649 | obj->Render(cworld, clip_x, clip_y, clip_width, clip_height ); | |
650 | } | |
fcbb6b37 KH |
651 | } |
652 | } | |
653 | } | |
654 | } | |
655 | ||
656 | node = node->Next(); | |
657 | } | |
84fba40b | 658 | *cworld = backup; |
fcbb6b37 KH |
659 | } |
660 | ||
661 | void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream &stream ) | |
662 | { | |
663 | } | |
664 | ||
f03b31e8 | 665 | wxCanvasObject* wxCanvasObjectGroup::IsHitWorld( double x, double y, double margin ) |
fcbb6b37 | 666 | { |
84fba40b RR |
667 | //KKKfirst check if within bbox |
668 | //will only work if they are always uptodate | |
669 | //if (!m_bbox.PointInBox(x,y,margin)) | |
670 | // return (wxCanvasObject*) NULL; | |
671 | ||
672 | wxTransformMatrix inverse = lworld; | |
673 | double xh,yh; | |
674 | inverse.Invert(); | |
675 | inverse.TransformPoint(x,y,xh,yh); | |
676 | ||
677 | wxCanvasObject *obj=0; | |
fcbb6b37 KH |
678 | wxNode *node = m_objects.Last(); |
679 | while (node) | |
680 | { | |
84fba40b | 681 | obj=(wxCanvasObject*) node->Data(); |
fcbb6b37 | 682 | |
84fba40b | 683 | if (!obj->IsControl() ) |
fcbb6b37 | 684 | { |
880d870e | 685 | if (obj->IsHitWorld(xh,yh,margin)) |
fcbb6b37 | 686 | { |
84fba40b | 687 | return obj; |
fcbb6b37 KH |
688 | } |
689 | } | |
690 | node = node->Previous(); | |
691 | } | |
84fba40b RR |
692 | |
693 | return (wxCanvasObject*) NULL; | |
fcbb6b37 KH |
694 | } |
695 | ||
84fba40b | 696 | wxCanvasObject* wxCanvasObjectGroup::Contains( wxCanvasObject* obj ) |
fcbb6b37 | 697 | { |
84fba40b RR |
698 | wxCanvasObject* cobj; |
699 | wxNode *node = m_objects.First(); | |
fcbb6b37 KH |
700 | while (node) |
701 | { | |
84fba40b | 702 | cobj=(wxCanvasObject*) node->Data(); |
fcbb6b37 | 703 | |
84fba40b | 704 | if (cobj->Contains(obj)) |
fcbb6b37 | 705 | { |
84fba40b | 706 | return obj; |
fcbb6b37 | 707 | } |
84fba40b | 708 | node = node->Next(); |
fcbb6b37 | 709 | } |
5143c96b | 710 | |
21840a6c | 711 | return (wxCanvasObject*) NULL; |
fcbb6b37 KH |
712 | } |
713 | ||
84fba40b RR |
714 | int wxCanvasObjectGroup::IndexOf( wxCanvasObject* obj ) |
715 | { | |
716 | return m_objects.IndexOf( obj ); | |
717 | } | |
718 | ||
fcbb6b37 | 719 | //---------------------------------------------------------------------------- |
84fba40b | 720 | // wxCanvasObjectRef |
fcbb6b37 KH |
721 | //---------------------------------------------------------------------------- |
722 | ||
a977709b JS |
723 | IMPLEMENT_CLASS(wxCanvasObjectRef, wxCanvasObject) |
724 | ||
84fba40b | 725 | wxCanvasObjectRef::wxCanvasObjectRef(double x, double y, wxCanvasObject* obj) |
fcbb6b37 KH |
726 | : wxCanvasObject() |
727 | { | |
f03b31e8 | 728 | lworld.Translate(x,y); |
84fba40b RR |
729 | m_obj = obj; |
730 | ||
731 | m_bbox.SetValid(FALSE); | |
732 | wxBoundingBox tmp; | |
733 | tmp=obj->GetBbox(); | |
734 | tmp.MapBbox(lworld); | |
735 | m_bbox.Expand( tmp ); | |
fcbb6b37 KH |
736 | } |
737 | ||
84fba40b | 738 | void wxCanvasObjectRef::PushEventHandler(wxEvtHandler *handler) |
fcbb6b37 | 739 | { |
84fba40b RR |
740 | wxCanvasObject::PushEventHandler(handler); |
741 | m_obj->PushEventHandler(handler); | |
fcbb6b37 KH |
742 | } |
743 | ||
84fba40b | 744 | wxEvtHandler *wxCanvasObjectRef::PopEventHandler(bool deleteHandler) |
fcbb6b37 | 745 | { |
84fba40b RR |
746 | m_obj->PopEventHandler(deleteHandler); |
747 | return wxCanvasObject::PopEventHandler(deleteHandler); | |
748 | } | |
fcbb6b37 | 749 | |
84fba40b RR |
750 | void wxCanvasObjectRef::AppendEventHandler(wxEvtHandler *handler) |
751 | { | |
752 | wxCanvasObject::AppendEventHandler(handler); | |
753 | m_obj->AppendEventHandler(handler); | |
754 | } | |
755 | ||
756 | wxEvtHandler *wxCanvasObjectRef::RemoveLastEventHandler(bool deleteHandler) | |
757 | { | |
758 | m_obj->RemoveLastEventHandler(deleteHandler); | |
759 | return wxCanvasObject::RemoveLastEventHandler(deleteHandler); | |
760 | } | |
761 | ||
762 | void wxCanvasObjectRef::TransLate( double x, double y ) | |
763 | { | |
764 | lworld.Translate(x,y); | |
765 | CalcBoundingBox(); | |
766 | } | |
767 | ||
768 | wxCanvasObject* wxCanvasObjectRef::Contains( wxCanvasObject* obj ) | |
769 | { | |
770 | if (obj == this || m_obj->Contains(obj)) | |
771 | return this; | |
772 | ||
773 | return (wxCanvasObject*) NULL; | |
774 | } | |
775 | ||
776 | ||
777 | void wxCanvasObjectRef::SetRotation(double rotation) | |
778 | { | |
779 | lworld.SetRotation(rotation); | |
780 | CalcBoundingBox(); | |
781 | } | |
782 | ||
783 | void wxCanvasObjectRef::SetScale(double scalex,double scaley) | |
784 | { | |
785 | lworld.Scale(scalex,scaley,lworld.GetValue(2,0),lworld.GetValue(2,1)); | |
786 | CalcBoundingBox(); | |
fcbb6b37 KH |
787 | } |
788 | ||
84fba40b | 789 | void wxCanvasObjectRef::SetAdmin(wxCanvasAdmin* admin) |
fcbb6b37 | 790 | { |
84fba40b RR |
791 | m_admin = admin; |
792 | m_obj->SetAdmin(admin); | |
793 | } | |
794 | ||
795 | void wxCanvasObjectRef::CalcBoundingBox() | |
796 | { | |
797 | m_bbox.SetValid(FALSE); | |
798 | m_obj->CalcBoundingBox(); | |
fcbb6b37 | 799 | |
84fba40b RR |
800 | wxBoundingBox tmp; |
801 | tmp=m_obj->GetBbox(); | |
802 | tmp.MapBbox(lworld); | |
803 | m_bbox.Expand( tmp ); | |
fcbb6b37 KH |
804 | } |
805 | ||
84fba40b | 806 | void wxCanvasObjectRef::Render(wxTransformMatrix* cworld, int x, int y, int width, int height ) |
fcbb6b37 | 807 | { |
84fba40b RR |
808 | if (!m_visible) return; |
809 | ||
810 | //get the absolute area (without the local matrix included) | |
811 | //the boundingbox is relative to the parent. | |
812 | wxRect absarea=GetAbsoluteArea(*cworld); | |
fcbb6b37 | 813 | |
84fba40b RR |
814 | wxTransformMatrix backup = *cworld; |
815 | *cworld *= lworld; | |
816 | ||
817 | #ifdef CANVASDEBUG | |
818 | wxDC *dc = m_admin->GetActive()->GetDC(); | |
819 | dc->SetPen(*wxBLACK_PEN); | |
820 | dc->SetBrush(*wxTRANSPARENT_BRUSH); | |
821 | dc->DrawRectangle( absarea.x , absarea.y , absarea.width , absarea.height ); | |
822 | dc->SetBrush(wxNullBrush); | |
823 | dc->SetPen(wxNullPen); | |
824 | #endif | |
825 | ||
826 | int clip_x = absarea.x; | |
827 | int clip_width = absarea.width; | |
fcbb6b37 KH |
828 | if (clip_x < x) |
829 | { | |
830 | clip_width -= x-clip_x; | |
831 | clip_x = x; | |
832 | } | |
833 | if (clip_width > 0) | |
834 | { | |
835 | if (clip_x + clip_width > x + width) | |
836 | clip_width = x+width-clip_x; | |
837 | ||
838 | if (clip_width > 0) | |
839 | { | |
84fba40b RR |
840 | int clip_y = absarea.y; |
841 | int clip_height = absarea.height; | |
fcbb6b37 KH |
842 | if (clip_y < y) |
843 | { | |
844 | clip_height -= y-clip_y; | |
845 | clip_y = y; | |
846 | } | |
847 | if (clip_height > 0) | |
848 | { | |
849 | if (clip_y + clip_height > y + height) | |
850 | clip_height = y+height-clip_y; | |
851 | ||
852 | if (clip_height > 0) | |
84fba40b | 853 | m_obj->Render(cworld, clip_x, clip_y, clip_width, clip_height ); |
fcbb6b37 KH |
854 | } |
855 | } | |
856 | } | |
fcbb6b37 | 857 | |
84fba40b | 858 | *cworld = backup; |
fcbb6b37 KH |
859 | } |
860 | ||
84fba40b | 861 | void wxCanvasObjectRef::WriteSVG( wxTextOutputStream &stream ) |
fcbb6b37 | 862 | { |
fcbb6b37 KH |
863 | } |
864 | ||
84fba40b | 865 | wxCanvasObject* wxCanvasObjectRef::IsHitWorld( double x, double y, double margin ) |
fcbb6b37 | 866 | { |
84fba40b RR |
867 | //KKKfirst check if within bbox |
868 | //will only work if they are always uptodate | |
869 | //if (!m_bbox.PointInBox(x,y,margin)) | |
870 | // return (wxCanvasObject*) NULL; | |
fcbb6b37 | 871 | |
84fba40b RR |
872 | wxTransformMatrix inverse = lworld; |
873 | double xh,yh; | |
874 | inverse.Invert(); | |
875 | inverse.TransformPoint(x,y,xh,yh); | |
fcbb6b37 | 876 | |
84fba40b RR |
877 | if (m_obj->IsHitWorld(xh,yh,margin)) |
878 | return this; | |
5143c96b | 879 | |
84fba40b RR |
880 | return (wxCanvasObject*) NULL; |
881 | } | |
5143c96b | 882 | |
5143c96b | 883 | |
fcbb6b37 | 884 | |
5143c96b | 885 | //---------------------------------------------------------------------------- |
84fba40b | 886 | // wxCanvasRect |
5143c96b KH |
887 | //---------------------------------------------------------------------------- |
888 | ||
a977709b JS |
889 | IMPLEMENT_CLASS(wxCanvasRect, wxCanvasObject) |
890 | ||
84fba40b | 891 | wxCanvasRect::wxCanvasRect( double x, double y, double w, double h , double radius ) |
5143c96b KH |
892 | : wxCanvasObject() |
893 | { | |
84fba40b RR |
894 | m_x = x; |
895 | m_y = y; | |
896 | m_width = w; | |
897 | m_height = h; | |
898 | m_radius = radius; | |
899 | ||
900 | m_brush = *wxBLACK_BRUSH; | |
901 | m_pen = *wxTRANSPARENT_PEN; | |
902 | CalcBoundingBox(); | |
5143c96b KH |
903 | } |
904 | ||
84fba40b | 905 | void wxCanvasRect::TransLate( double x, double y ) |
5143c96b | 906 | { |
84fba40b RR |
907 | m_x += x; |
908 | m_y += y; | |
909 | CalcBoundingBox(); | |
5143c96b KH |
910 | } |
911 | ||
84fba40b | 912 | void wxCanvasRect::CalcBoundingBox() |
5143c96b | 913 | { |
84fba40b RR |
914 | m_bbox.SetMin( m_x , m_y); |
915 | m_bbox.SetMax( m_x + m_width ,m_y + m_height ); | |
5143c96b KH |
916 | |
917 | //include the pen width also | |
84fba40b RR |
918 | //KKK m_bbox.EnLarge(m_pen.GetWidth()+m_radius); |
919 | m_bbox.EnLarge(m_pen.GetWidth()/2); | |
5143c96b KH |
920 | } |
921 | ||
84fba40b | 922 | void wxCanvasRect::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height ) |
5143c96b | 923 | { |
84fba40b RR |
924 | if (!m_visible) return; |
925 | ||
84fba40b | 926 | if (cworld->GetRotation()) |
5143c96b | 927 | { |
84fba40b RR |
928 | wxPoint *cpoints = new wxPoint[4]; |
929 | double x; | |
930 | double y; | |
931 | cworld->TransformPoint( m_x, m_y, x, y ); | |
932 | cpoints[0].x = m_admin->LogicalToDeviceX(x); | |
933 | cpoints[0].y = m_admin->LogicalToDeviceY(y); | |
934 | cworld->TransformPoint( m_x , m_y + m_height, x, y ); | |
935 | cpoints[1].x = m_admin->LogicalToDeviceX(x); | |
936 | cpoints[1].y = m_admin->LogicalToDeviceY(y); | |
937 | cworld->TransformPoint( m_x + m_width, m_y + m_height, x, y ); | |
938 | cpoints[2].x = m_admin->LogicalToDeviceX(x); | |
939 | cpoints[2].y = m_admin->LogicalToDeviceY(y); | |
940 | cworld->TransformPoint( m_x + m_width, m_y , x, y ); | |
941 | cpoints[3].x = m_admin->LogicalToDeviceX(x); | |
942 | cpoints[3].y = m_admin->LogicalToDeviceY(y); | |
943 | ||
944 | wxDC *dc = m_admin->GetActive()->GetDC(); | |
945 | dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height); | |
946 | dc->SetBrush(m_brush); | |
947 | int pw=m_pen.GetWidth(); | |
948 | m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw)); | |
949 | dc->SetPen(m_pen); | |
950 | dc->DrawPolygon(4, cpoints, 0,0,wxWINDING_RULE); | |
951 | delete [] cpoints; | |
952 | dc->SetBrush(wxNullBrush); | |
953 | dc->SetPen(wxNullPen); | |
954 | dc->DestroyClippingRegion(); | |
955 | m_pen.SetWidth(pw); | |
956 | } | |
957 | else | |
958 | { | |
959 | wxDC *dc = m_admin->GetActive()->GetDC(); | |
960 | dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height); | |
961 | dc->SetBrush(m_brush); | |
962 | int pw=m_pen.GetWidth(); | |
963 | m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw)); | |
964 | dc->SetPen(m_pen); | |
965 | //yes the whole not only the clipping region, because we have a pen also | |
966 | int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x ); | |
967 | int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y ); | |
968 | int w = m_admin->LogicalToDeviceXRel( m_width ); | |
969 | int h = m_admin->LogicalToDeviceYRel( m_height ); | |
970 | int r = m_admin->LogicalToDeviceYRel( m_radius ); | |
971 | if (w > 0 && w < 1) w=1; | |
972 | if (w < 0 && w > -1) w=-1; | |
973 | if (h > 0 && h < 1) h=1; | |
974 | if (h < 0 && h > -1) h=-1; | |
975 | if (m_radius) | |
976 | dc->DrawRoundedRectangle( x,y,w,h,r); | |
977 | else | |
978 | dc->DrawRectangle( x,y,w,h); | |
979 | dc->SetBrush(wxNullBrush); | |
980 | dc->SetPen(wxNullPen); | |
981 | dc->DestroyClippingRegion(); | |
982 | m_pen.SetWidth(pw); | |
5143c96b | 983 | } |
5143c96b KH |
984 | } |
985 | ||
84fba40b | 986 | void wxCanvasRect::WriteSVG( wxTextOutputStream &stream ) |
5143c96b KH |
987 | { |
988 | } | |
989 | ||
990 | //---------------------------------------------------------------------------- | |
84fba40b | 991 | // wxCanvasCircle |
5143c96b KH |
992 | //---------------------------------------------------------------------------- |
993 | ||
84fba40b | 994 | wxCanvasCircle::wxCanvasCircle( double x, double y, double radius ) |
5143c96b KH |
995 | : wxCanvasObject() |
996 | { | |
84fba40b RR |
997 | m_x = x; |
998 | m_y = y; | |
999 | m_radius = radius; | |
1000 | ||
27d1065d RR |
1001 | m_brush = *wxBLACK_BRUSH; |
1002 | m_pen = *wxTRANSPARENT_PEN; | |
84fba40b | 1003 | CalcBoundingBox(); |
5143c96b KH |
1004 | } |
1005 | ||
84fba40b | 1006 | void wxCanvasCircle::TransLate( double x, double y ) |
5143c96b | 1007 | { |
84fba40b RR |
1008 | m_x += x; |
1009 | m_y += y; | |
1010 | CalcBoundingBox(); | |
5143c96b KH |
1011 | } |
1012 | ||
84fba40b | 1013 | void wxCanvasCircle::CalcBoundingBox() |
5143c96b | 1014 | { |
84fba40b RR |
1015 | m_bbox.SetMin( m_x-m_radius , m_y-m_radius ); |
1016 | m_bbox.SetMax( m_x+m_radius , m_y+m_radius ); | |
5143c96b | 1017 | |
84fba40b RR |
1018 | //include the pen width also |
1019 | m_bbox.EnLarge(m_pen.GetWidth()/2); | |
1020 | } | |
1021 | ||
1022 | void wxCanvasCircle::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height ) | |
1023 | { | |
1024 | if (!m_visible) return; | |
1025 | ||
84fba40b RR |
1026 | wxDC *dc = m_admin->GetActive()->GetDC(); |
1027 | dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height); | |
1028 | dc->SetBrush(m_brush); | |
1029 | int pw=m_pen.GetWidth(); | |
1030 | m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw)); | |
1031 | dc->SetPen(m_pen); | |
1032 | //yes the whole not only the clipping region, because we have a pen also | |
1033 | //and rotation on a circle is not important so only a shift with cworld | |
1034 | int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x ); | |
1035 | int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y ); | |
1036 | int radius = m_admin->LogicalToDeviceXRel( m_radius ); | |
1037 | if (radius < 1) radius=1; | |
1038 | dc->DrawCircle( x,y,radius); | |
1039 | dc->SetBrush(wxNullBrush); | |
1040 | dc->SetPen(wxNullPen); | |
1041 | dc->DestroyClippingRegion(); | |
1042 | m_pen.SetWidth(pw); | |
5143c96b KH |
1043 | } |
1044 | ||
84fba40b | 1045 | void wxCanvasCircle::WriteSVG( wxTextOutputStream &stream ) |
5143c96b | 1046 | { |
84fba40b | 1047 | } |
5143c96b | 1048 | |
84fba40b RR |
1049 | wxCanvasObject* wxCanvasCircle::IsHitWorld( double x, double y, double margin ) |
1050 | { | |
1051 | if ((x >= m_bbox.GetMinX()-margin) && | |
1052 | (x <= m_bbox.GetMaxX()+margin) && | |
1053 | (y >= m_bbox.GetMinY()-margin) && | |
1054 | (y <= m_bbox.GetMaxY()+margin) | |
1055 | ) | |
5143c96b | 1056 | { |
84fba40b RR |
1057 | if (m_radius+m_pen.GetWidth()/2+margin > sqrt(pow(m_x-x,2)+pow(m_y-y,2))) |
1058 | return this; | |
1059 | else | |
1060 | return (wxCanvasObject*) NULL; | |
5143c96b | 1061 | } |
84fba40b RR |
1062 | return (wxCanvasObject*) NULL; |
1063 | } | |
5143c96b | 1064 | |
84fba40b RR |
1065 | //---------------------------------------------------------------------------- |
1066 | // wxCanvasEllipse | |
1067 | //---------------------------------------------------------------------------- | |
1068 | ||
1069 | wxCanvasEllipse::wxCanvasEllipse( double x, double y, double width, double height ) | |
1070 | : wxCanvasObject() | |
1071 | { | |
1072 | m_x = x; | |
1073 | m_y = y; | |
1074 | m_width = width; | |
1075 | m_height = height; | |
1076 | ||
1077 | m_brush = *wxBLACK_BRUSH; | |
1078 | m_pen = *wxTRANSPARENT_PEN; | |
1079 | CalcBoundingBox(); | |
1080 | } | |
5143c96b | 1081 | |
84fba40b RR |
1082 | void wxCanvasEllipse::TransLate( double x, double y ) |
1083 | { | |
1084 | m_x += x; | |
1085 | m_y += y; | |
1086 | CalcBoundingBox(); | |
5143c96b KH |
1087 | } |
1088 | ||
84fba40b | 1089 | void wxCanvasEllipse::CalcBoundingBox() |
5143c96b | 1090 | { |
84fba40b RR |
1091 | m_bbox.SetMin( m_x, m_y ); |
1092 | m_bbox.SetMax( m_x+m_width , m_y+m_height ); | |
5143c96b | 1093 | |
84fba40b RR |
1094 | //include the pen width also |
1095 | m_bbox.EnLarge(m_pen.GetWidth()/2); | |
1096 | } | |
5143c96b | 1097 | |
84fba40b RR |
1098 | void wxCanvasEllipse::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height ) |
1099 | { | |
1100 | if (!m_visible) return; | |
5143c96b | 1101 | |
84fba40b RR |
1102 | wxDC *dc = m_admin->GetActive()->GetDC(); |
1103 | dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height); | |
5143c96b | 1104 | dc->SetBrush(m_brush); |
84fba40b RR |
1105 | int pw=m_pen.GetWidth(); |
1106 | m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw)); | |
5143c96b | 1107 | dc->SetPen(m_pen); |
84fba40b RR |
1108 | int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x ); |
1109 | int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y ); | |
1110 | int w = m_admin->LogicalToDeviceXRel( m_width ); | |
1111 | int h = m_admin->LogicalToDeviceYRel( m_height ); | |
1112 | if (w > 0 && w < 1) w=1; | |
1113 | if (w < 0 && w > -1) w=-1; | |
1114 | if (h > 0 && h < 1) h=1; | |
1115 | if (h < 0 && h > -1) h=-1; | |
1116 | dc->DrawEllipse( x,y,w,h); | |
5143c96b KH |
1117 | dc->SetBrush(wxNullBrush); |
1118 | dc->SetPen(wxNullPen); | |
1119 | dc->DestroyClippingRegion(); | |
84fba40b | 1120 | m_pen.SetWidth(pw); |
5143c96b KH |
1121 | } |
1122 | ||
84fba40b | 1123 | void wxCanvasEllipse::WriteSVG( wxTextOutputStream &stream ) |
5143c96b KH |
1124 | { |
1125 | } | |
1126 | ||
84fba40b RR |
1127 | wxCanvasObject* wxCanvasEllipse::IsHitWorld( double x, double y, double margin ) |
1128 | { | |
1129 | if ((x >= m_bbox.GetMinX()-margin) && | |
1130 | (x <= m_bbox.GetMaxX()+margin) && | |
1131 | (y >= m_bbox.GetMinY()-margin) && | |
1132 | (y <= m_bbox.GetMaxY()+margin) | |
1133 | ) | |
1134 | { | |
1135 | double a=(m_width+m_pen.GetWidth())/2+margin ; | |
1136 | double b=(m_height+m_pen.GetWidth())/2+margin; | |
1137 | double c=pow((m_x+m_width/2-x)/a,2)+pow((m_y+m_height/2-y)/b,2); | |
1138 | if ( 1 > c) | |
1139 | return this; | |
1140 | else | |
1141 | return (wxCanvasObject*) NULL; | |
1142 | } | |
1143 | return (wxCanvasObject*) NULL; | |
1144 | } | |
fcbb6b37 | 1145 | |
21544859 | 1146 | //---------------------------------------------------------------------------- |
84fba40b | 1147 | // wxCanvasEllipticArc |
21544859 RR |
1148 | //---------------------------------------------------------------------------- |
1149 | ||
84fba40b | 1150 | wxCanvasEllipticArc::wxCanvasEllipticArc( double x, double y, double width, double height, double start, double end ) |
4dbd4ee6 | 1151 | : wxCanvasObject() |
21544859 | 1152 | { |
4dbd4ee6 RR |
1153 | m_x = x; |
1154 | m_y = y; | |
84fba40b RR |
1155 | m_width = width; |
1156 | m_height = height; | |
1157 | m_start = start; | |
1158 | m_end = end; | |
dc16900b | 1159 | |
27d1065d RR |
1160 | m_brush = *wxBLACK_BRUSH; |
1161 | m_pen = *wxTRANSPARENT_PEN; | |
84fba40b | 1162 | CalcBoundingBox(); |
21544859 RR |
1163 | } |
1164 | ||
84fba40b | 1165 | void wxCanvasEllipticArc::TransLate( double x, double y ) |
4dbd4ee6 | 1166 | { |
84fba40b RR |
1167 | m_x += x; |
1168 | m_y += y; | |
1169 | CalcBoundingBox(); | |
4dbd4ee6 RR |
1170 | } |
1171 | ||
84fba40b | 1172 | void wxCanvasEllipticArc::CalcBoundingBox() |
21544859 | 1173 | { |
84fba40b RR |
1174 | m_bbox.SetMin( m_x, m_y ); |
1175 | m_bbox.SetMax( m_x+m_width , m_y+m_height ); | |
fcbb6b37 | 1176 | |
84fba40b RR |
1177 | //include the pen width also |
1178 | m_bbox.EnLarge(m_pen.GetWidth()/2); | |
1179 | } | |
fcbb6b37 | 1180 | |
84fba40b RR |
1181 | void wxCanvasEllipticArc::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height ) |
1182 | { | |
1183 | if (!m_visible) return; | |
fcbb6b37 | 1184 | |
84fba40b RR |
1185 | wxDC *dc = m_admin->GetActive()->GetDC(); |
1186 | dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height); | |
1187 | dc->SetBrush(m_brush); | |
1188 | int pw=m_pen.GetWidth(); | |
1189 | m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw)); | |
1190 | dc->SetPen(m_pen); | |
1191 | int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x ); | |
1192 | int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y ); | |
1193 | int w = m_admin->LogicalToDeviceXRel( m_width ); | |
1194 | int h = m_admin->LogicalToDeviceYRel( m_height ); | |
1195 | if (w > 0 && w < 1) w=1; | |
1196 | if (w < 0 && w > -1) w=-1; | |
1197 | if (h > 0 && h < 1) h=1; | |
1198 | if (h < 0 && h > -1) h=-1; | |
1199 | if (m_admin->GetActive()->GetYaxis()) | |
1200 | dc->DrawEllipticArc( x,y,w,h,-m_end,-m_start); | |
1201 | else | |
1202 | dc->DrawEllipticArc( x,y,w,h,m_start,m_end); | |
1203 | dc->SetBrush(wxNullBrush); | |
1204 | dc->SetPen(wxNullPen); | |
1205 | dc->DestroyClippingRegion(); | |
1206 | m_pen.SetWidth(pw); | |
21544859 RR |
1207 | } |
1208 | ||
84fba40b RR |
1209 | void wxCanvasEllipticArc::WriteSVG( wxTextOutputStream &stream ) |
1210 | { | |
1211 | } | |
1212 | ||
1213 | wxCanvasObject* wxCanvasEllipticArc::IsHitWorld( double x, double y, double margin ) | |
21544859 | 1214 | { |
84fba40b RR |
1215 | if ((x >= m_bbox.GetMinX()-margin) && |
1216 | (x <= m_bbox.GetMaxX()+margin) && | |
1217 | (y >= m_bbox.GetMinY()-margin) && | |
1218 | (y <= m_bbox.GetMaxY()+margin) | |
1219 | ) | |
1220 | { | |
1221 | double a=(m_width+m_pen.GetWidth())/2+margin ; | |
1222 | double b=(m_height+m_pen.GetWidth())/2+margin; | |
1223 | double c=pow((m_x+m_width/2-x)/a,2)+pow((m_y+m_height/2-y)/b,2); | |
1224 | if ( 1 > c) | |
1225 | return this; | |
1226 | else | |
1227 | return (wxCanvasObject*) NULL; | |
1228 | } | |
1229 | return (wxCanvasObject*) NULL; | |
21544859 RR |
1230 | } |
1231 | ||
239c1f50 RR |
1232 | //---------------------------------------------------------------------------- |
1233 | // wxCanvasLine | |
1234 | //---------------------------------------------------------------------------- | |
1235 | ||
27d1065d | 1236 | wxCanvasLine::wxCanvasLine( double x1, double y1, double x2, double y2 ) |
4dbd4ee6 | 1237 | : wxCanvasObject() |
239c1f50 | 1238 | { |
4dbd4ee6 RR |
1239 | m_x1 = x1; |
1240 | m_y1 = y1; | |
1241 | m_x2 = x2; | |
1242 | m_y2 = y2; | |
1243 | ||
27d1065d | 1244 | m_pen = *wxBLACK_PEN; |
84fba40b | 1245 | CalcBoundingBox(); |
239c1f50 RR |
1246 | } |
1247 | ||
84fba40b | 1248 | void wxCanvasLine::TransLate( double x, double y ) |
4dbd4ee6 | 1249 | { |
84fba40b RR |
1250 | m_x1 += x; |
1251 | m_y1 += y; | |
1252 | m_x2 += x; | |
1253 | m_y2 += y; | |
1254 | CalcBoundingBox(); | |
1255 | } | |
1256 | ||
1257 | void wxCanvasLine::CalcBoundingBox() | |
1258 | { | |
1259 | m_bbox.SetMin( m_x1 , m_y1); | |
1260 | m_bbox.SetMax( m_x2 , m_y2); | |
1261 | ||
1262 | //include the pen width also | |
1263 | m_bbox.EnLarge(m_pen.GetWidth()/2); | |
4dbd4ee6 RR |
1264 | } |
1265 | ||
84fba40b | 1266 | void wxCanvasLine::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height ) |
239c1f50 | 1267 | { |
84fba40b | 1268 | if (!m_visible) return; |
fcbb6b37 | 1269 | |
84fba40b RR |
1270 | double x1,y1,x2,y2; |
1271 | cworld->TransformPoint( m_x1, m_y1, x1, y1 ); | |
1272 | cworld->TransformPoint( m_x2, m_y2, x2, y2 ); | |
1273 | x1 = m_admin->LogicalToDeviceX( x1 ); | |
1274 | y1 = m_admin->LogicalToDeviceY( y1 ); | |
1275 | x2 = m_admin->LogicalToDeviceX( x2 ); | |
1276 | y2 = m_admin->LogicalToDeviceY( y2 ); | |
5143c96b | 1277 | |
84fba40b RR |
1278 | wxDC *dc = m_admin->GetActive()->GetDC(); |
1279 | dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height ); | |
1280 | int pw=m_pen.GetWidth(); | |
1281 | m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw)); | |
27d1065d | 1282 | dc->SetPen( m_pen ); |
84fba40b | 1283 | dc->DrawLine( x1, y1, x2, y2 ); |
5143c96b | 1284 | |
33ebcd80 | 1285 | dc->DestroyClippingRegion(); |
84fba40b | 1286 | m_pen.SetWidth(pw); |
239c1f50 RR |
1287 | } |
1288 | ||
1289 | void wxCanvasLine::WriteSVG( wxTextOutputStream &stream ) | |
1290 | { | |
1e1af41e | 1291 | // no idea |
239c1f50 RR |
1292 | } |
1293 | ||
84fba40b RR |
1294 | wxCanvasObject* wxCanvasLine::IsHitWorld( double x, double y, double margin ) |
1295 | { | |
1296 | if ((x >= m_bbox.GetMinX()-margin) && | |
1297 | (x <= m_bbox.GetMaxX()+margin) && | |
1298 | (y >= m_bbox.GetMinY()-margin) && | |
1299 | (y <= m_bbox.GetMaxY()+margin) | |
1300 | ) | |
1301 | { | |
1302 | wxLine line1(m_x1,m_y1,m_x2,m_y2); | |
1303 | wxPoint2DDouble P=wxPoint2DDouble(x,y); | |
1304 | double distance; | |
1305 | if (line1.PointInLine(P,distance,m_pen.GetWidth()/2+margin) == R_IN_AREA) | |
1306 | return this; | |
1307 | else | |
1308 | return (wxCanvasObject*) NULL; | |
1309 | } | |
1310 | return (wxCanvasObject*) NULL; | |
1311 | } | |
1312 | ||
6a2c1874 RR |
1313 | //---------------------------------------------------------------------------- |
1314 | // wxCanvasImage | |
1315 | //---------------------------------------------------------------------------- | |
1316 | ||
4dbd4ee6 RR |
1317 | wxCanvasImage::wxCanvasImage( const wxImage &image, double x, double y, double w, double h ) |
1318 | : wxCanvasObject() | |
6a2c1874 | 1319 | { |
4dbd4ee6 RR |
1320 | m_x = x; |
1321 | m_y = y; | |
1322 | m_width = w; | |
1323 | m_height = h; | |
dc16900b | 1324 | |
6a2c1874 | 1325 | m_image = image; |
84fba40b | 1326 | |
f03b31e8 RR |
1327 | m_orgw = m_image.GetWidth(); |
1328 | m_orgh = m_image.GetHeight(); | |
84fba40b | 1329 | |
6a2c1874 | 1330 | m_isImage = TRUE; |
84fba40b | 1331 | CalcBoundingBox(); |
6a2c1874 RR |
1332 | } |
1333 | ||
880d870e RR |
1334 | void wxCanvasImage::SetPosXY( double x, double y) |
1335 | { | |
1336 | m_x = x; | |
1337 | m_y = y; | |
1338 | CalcBoundingBox(); | |
1339 | } | |
1340 | ||
84fba40b | 1341 | void wxCanvasImage::TransLate( double x, double y ) |
4dbd4ee6 | 1342 | { |
84fba40b RR |
1343 | m_x += x; |
1344 | m_y += y; | |
1345 | CalcBoundingBox(); | |
1346 | } | |
1347 | ||
1348 | void wxCanvasImage::CalcBoundingBox() | |
1349 | { | |
f03b31e8 RR |
1350 | m_bbox.SetMin( m_x, m_y ); |
1351 | m_bbox.SetMax( m_x + m_width, m_y + m_height ); | |
84fba40b RR |
1352 | } |
1353 | ||
1354 | void wxCanvasImage::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height ) | |
1355 | { | |
1356 | if (!m_visible) return; | |
880d870e | 1357 | |
84fba40b RR |
1358 | wxRect tmparea; |
1359 | ||
1360 | tmparea.x = m_admin->LogicalToDeviceXRel( m_bbox.GetMinX()); | |
1361 | tmparea.y = m_admin->LogicalToDeviceYRel( m_bbox.GetMinY()); | |
1362 | tmparea.width = m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ); | |
1363 | tmparea.height = m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ); | |
1364 | ||
1365 | double x; | |
1366 | double y; | |
1367 | cworld->TransformPoint( m_x, m_y, x, y ); | |
1368 | x = m_admin->LogicalToDeviceX(x); | |
1369 | y = m_admin->LogicalToDeviceY(y); | |
1370 | ||
dc16900b | 1371 | |
880d870e | 1372 | // What is this??? |
84fba40b RR |
1373 | if ( m_orgw*5 < m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) || |
1374 | m_orgw/5 > m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) || | |
1375 | m_orgh*5 < m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) || | |
1376 | m_orgh/5 > m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) | |
1377 | ) | |
1378 | { | |
1379 | wxDC *dc = m_admin->GetActive()->GetDC(); | |
1380 | dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height); | |
1381 | dc->SetBrush(*wxTRANSPARENT_BRUSH); | |
1382 | dc->SetPen(*wxBLACK_PEN); | |
1383 | //yes the whole not only the clipping region, because we have a pen also | |
1384 | int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x ); | |
1385 | int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y ); | |
1386 | int w = m_admin->LogicalToDeviceXRel( m_width ); | |
1387 | int h = m_admin->LogicalToDeviceYRel( m_height ); | |
1388 | if (w < 1) w=1; | |
1389 | if (h < 1) h=1; | |
1390 | dc->DrawRectangle( x,y,w,h); | |
1391 | dc->SetBrush(wxNullBrush); | |
1392 | dc->SetPen(wxNullPen); | |
1393 | dc->DestroyClippingRegion(); | |
1394 | return; | |
1395 | } | |
880d870e RR |
1396 | |
1397 | wxImage tmp; | |
1398 | bool is_cashed = FALSE; | |
84fba40b | 1399 | |
880d870e | 1400 | if (m_cImage.Ok() && (m_cW == m_bbox.GetWidth()) && (m_cH == m_bbox.GetHeight())) |
33ebcd80 | 1401 | { |
880d870e RR |
1402 | // use cached image |
1403 | tmp = m_cImage; | |
1404 | is_cashed = TRUE; | |
33ebcd80 RR |
1405 | } |
1406 | else | |
1407 | { | |
880d870e RR |
1408 | if ((m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) == m_image.GetWidth()) && |
1409 | (m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) == m_image.GetHeight())) | |
1410 | { | |
1411 | tmp = m_image; | |
1412 | } | |
1413 | else | |
1414 | { | |
1415 | tmp = m_image.Scale( m_admin->LogicalToDeviceXRel( m_bbox.GetWidth()), | |
1416 | m_admin->LogicalToDeviceYRel( m_bbox.GetHeight()) ); | |
1417 | } | |
1418 | ||
1419 | // create cached image | |
1420 | m_cImage = tmp; | |
1421 | m_cW = tmp.GetWidth(); | |
1422 | m_cH = tmp.GetHeight(); | |
33ebcd80 | 1423 | } |
4dbd4ee6 | 1424 | |
84fba40b RR |
1425 | // wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y)); |
1426 | wxPoint centr(0,0); | |
fcbb6b37 | 1427 | |
880d870e RR |
1428 | wxBitmap bmp; |
1429 | ||
1430 | if (m_cBitmap.Ok() && is_cashed && (m_cR == cworld->GetRotation())) | |
d1f9b206 | 1431 | { |
880d870e | 1432 | bmp = m_cBitmap; |
d1f9b206 RR |
1433 | } |
1434 | else | |
1435 | { | |
880d870e RR |
1436 | if (cworld->GetRotation()) |
1437 | tmp = tmp.Rotate(-cworld->GetRotation()/180.0 * pi, centr, TRUE, NULL ); | |
1438 | ||
12d1ab44 | 1439 | bmp = wxBitmap(tmp); |
880d870e RR |
1440 | |
1441 | // create cached bitmap | |
1442 | m_cBitmap = bmp; | |
1443 | m_cR = cworld->GetRotation(); | |
d1f9b206 | 1444 | } |
5143c96b | 1445 | |
84fba40b RR |
1446 | wxDC *dc = m_admin->GetActive()->GetDC(); |
1447 | ||
1448 | wxPoint centr2; | |
1449 | if (cworld->GetRotation()> 0) | |
33ebcd80 | 1450 | { |
84fba40b RR |
1451 | centr2.x= (int) (x+m_height*sin(-cworld->GetRotation()/180.0 * pi)); |
1452 | centr2.y= (int) y; | |
33ebcd80 RR |
1453 | } |
1454 | else | |
1455 | { | |
84fba40b RR |
1456 | centr2.x= (int) x; |
1457 | centr2.y= (int) (y-m_width*sin(-cworld->GetRotation()/180.0 * pi)); | |
1458 | } | |
5143c96b | 1459 | |
84fba40b RR |
1460 | if (cworld->GetRotation() != 0) |
1461 | { | |
1462 | //TODO clipping not right | |
1463 | dc->DrawBitmap(bmp,centr2,TRUE ); | |
1464 | // dc->DrawPoint(centr2); | |
1465 | // dc->DrawPoint(x,y); | |
1466 | } | |
1467 | else | |
1468 | { | |
880d870e RR |
1469 | dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height ); |
1470 | dc->DrawBitmap( bmp, x, y, TRUE ); | |
1471 | dc->DestroyClippingRegion(); | |
33ebcd80 | 1472 | } |
6a2c1874 RR |
1473 | } |
1474 | ||
1475 | void wxCanvasImage::WriteSVG( wxTextOutputStream &stream ) | |
1476 | { | |
1477 | // no idea | |
1478 | } | |
1479 | ||
3b111dbe RR |
1480 | //---------------------------------------------------------------------------- |
1481 | // wxCanvasCtrl | |
1482 | //---------------------------------------------------------------------------- | |
1483 | ||
1484 | wxCanvasControl::wxCanvasControl( wxWindow *control ) | |
4dbd4ee6 | 1485 | : wxCanvasObject() |
3b111dbe | 1486 | { |
21544859 | 1487 | m_isControl = TRUE; |
3b111dbe | 1488 | m_control = control; |
84fba40b RR |
1489 | CalcBoundingBox(); |
1490 | } | |
1491 | ||
1492 | double wxCanvasControl::GetPosX() | |
1493 | { | |
1494 | int x,y ; | |
1495 | m_control->GetPosition( &x, &y ); | |
1496 | return m_admin->DeviceToLogicalX(x); | |
1497 | } | |
1498 | ||
1499 | double wxCanvasControl::GetPosY() | |
1500 | { | |
1501 | int x,y ; | |
1502 | m_control->GetPosition( &x, &y ); | |
1503 | return m_admin->DeviceToLogicalY(y); | |
1504 | } | |
1505 | ||
1506 | void wxCanvasControl::SetPosXY( double x, double y) | |
1507 | { | |
1508 | int xd = m_admin->LogicalToDeviceX(x); | |
1509 | int yd = m_admin->LogicalToDeviceY(y); | |
1510 | m_control->Move(xd,yd); | |
1511 | } | |
1512 | ||
1513 | ||
1514 | void wxCanvasControl::TransLate( double x, double y ) | |
1515 | { | |
1516 | int xdo,ydo; | |
1517 | m_control->GetPosition( &xdo, &ydo ); | |
1518 | int xd = m_admin->LogicalToDeviceX(x)-xdo; | |
1519 | int yd = m_admin->LogicalToDeviceY(y)-ydo; | |
1520 | m_control->Move(xd,yd); | |
1521 | CalcBoundingBox(); | |
3b111dbe RR |
1522 | } |
1523 | ||
1524 | wxCanvasControl::~wxCanvasControl() | |
1525 | { | |
1526 | m_control->Destroy(); | |
1527 | } | |
1528 | ||
84fba40b | 1529 | void wxCanvasControl::CalcBoundingBox() |
3b111dbe | 1530 | { |
84fba40b RR |
1531 | wxRect tmparea; |
1532 | ||
1533 | m_control->GetSize( &tmparea.width, &tmparea.height ); | |
1534 | m_control->GetPosition( &tmparea.x, &tmparea.y ); | |
1535 | ||
1536 | m_bbox.SetMin( tmparea.x , tmparea.y); | |
1537 | m_bbox.SetMax( tmparea.x + tmparea.width , tmparea.y + tmparea.height); | |
1538 | ||
3b111dbe RR |
1539 | } |
1540 | ||
84fba40b | 1541 | void wxCanvasControl::MoveRelative( double x, double y ) |
3b111dbe | 1542 | { |
84fba40b | 1543 | m_control->Move( m_admin->LogicalToDeviceX(x), m_admin->LogicalToDeviceX(y) ); |
3b111dbe RR |
1544 | } |
1545 | ||
d1f9b206 RR |
1546 | //---------------------------------------------------------------------------- |
1547 | // wxCanvasText | |
1548 | //---------------------------------------------------------------------------- | |
1549 | ||
1550 | class wxFaceData | |
1551 | { | |
1552 | public: | |
1e1af41e | 1553 | #if wxUSE_FREETYPE |
d1f9b206 RR |
1554 | FT_Face m_face; |
1555 | #else | |
1556 | void *m_dummy; | |
dc16900b | 1557 | #endif |
d1f9b206 RR |
1558 | }; |
1559 | ||
4dbd4ee6 RR |
1560 | wxCanvasText::wxCanvasText( const wxString &text, double x, double y, const wxString &fontFile, int size ) |
1561 | : wxCanvasObject() | |
d1f9b206 RR |
1562 | { |
1563 | m_text = text; | |
cb281cfc RR |
1564 | m_fontFileName = fontFile; |
1565 | m_size = size; | |
dc16900b | 1566 | |
cb281cfc | 1567 | m_red = 0; |
d1f9b206 RR |
1568 | m_green = 0; |
1569 | m_blue = 0; | |
dc16900b | 1570 | |
4dbd4ee6 | 1571 | m_alpha = NULL; |
dc16900b | 1572 | |
4dbd4ee6 RR |
1573 | m_x = x; |
1574 | m_y = y; | |
dc16900b KH |
1575 | |
1576 | #if wxUSE_FREETYPE | |
d1f9b206 RR |
1577 | wxFaceData *data = new wxFaceData; |
1578 | m_faceData = data; | |
dc16900b | 1579 | |
d1f9b206 | 1580 | int error = FT_New_Face( g_freetypeLibrary, |
cb281cfc | 1581 | m_fontFileName, |
d1f9b206 RR |
1582 | 0, |
1583 | &(data->m_face) ); | |
5143c96b | 1584 | |
d1f9b206 RR |
1585 | error = FT_Set_Char_Size( data->m_face, |
1586 | 0, | |
cb281cfc RR |
1587 | m_size*64, |
1588 | 96, // screen dpi | |
d1f9b206 RR |
1589 | 96 ); |
1590 | #endif | |
84fba40b | 1591 | CalcBoundingBox(); |
d1f9b206 RR |
1592 | } |
1593 | ||
1594 | wxCanvasText::~wxCanvasText() | |
1595 | { | |
fcbb6b37 | 1596 | #if wxUSE_FREETYPE |
d1f9b206 RR |
1597 | wxFaceData *data = (wxFaceData*) m_faceData; |
1598 | delete data; | |
1599 | #endif | |
1600 | ||
1601 | if (m_alpha) delete [] m_alpha; | |
1602 | } | |
1603 | ||
1604 | void wxCanvasText::SetRGB( unsigned char red, unsigned char green, unsigned char blue ) | |
1605 | { | |
1606 | m_red = red; | |
1607 | m_green = green; | |
1608 | m_blue = blue; | |
1609 | } | |
1610 | ||
1611 | void wxCanvasText::SetFlag( int flag ) | |
1612 | { | |
1613 | m_flag = flag; | |
1614 | } | |
1615 | ||
84fba40b | 1616 | void wxCanvasText::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height ) |
d1f9b206 | 1617 | { |
84fba40b RR |
1618 | if (!m_visible) return; |
1619 | ||
1620 | wxRect tmparea; | |
1621 | tmparea.x = m_admin->LogicalToDeviceX( m_bbox.GetMinX()); | |
1622 | tmparea.y = m_admin->LogicalToDeviceY( m_bbox.GetMinY()); | |
1623 | tmparea.width = m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ); | |
1624 | tmparea.height = m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ); | |
1625 | ||
1626 | m_alpha = new unsigned char[tmparea.width*tmparea.height]; | |
1627 | memset( m_alpha, 0, tmparea.width*tmparea.height ); | |
1628 | ||
d1f9b206 | 1629 | if (!m_alpha) return; |
fcbb6b37 | 1630 | |
84fba40b RR |
1631 | #if wxUSE_FREETYPE |
1632 | FT_Face face = ((wxFaceData*)m_faceData)->m_face; | |
1633 | FT_GlyphSlot slot = face->glyph; | |
1634 | int pen_x = 0; | |
1635 | int pen_y = m_size; | |
1636 | ||
1637 | for (int n = 0; n < (int)m_text.Len(); n++) | |
1638 | { | |
1639 | FT_UInt index = FT_Get_Char_Index( face, m_text[(unsigned int)n] ); | |
1640 | ||
1641 | int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); | |
1642 | if (error) continue; | |
1643 | ||
1644 | error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); | |
1645 | if (error) continue; | |
1646 | ||
1647 | FT_Bitmap *bitmap = &slot->bitmap; | |
1648 | unsigned char* buffer = bitmap->buffer; | |
1649 | for (int y = 0; y < bitmap->rows; y++) | |
1650 | for (int x = 0; x < bitmap->width; x++) | |
1651 | { | |
1652 | unsigned char alpha = buffer[ y*bitmap->pitch + x ]; | |
1653 | if (alpha == 0) continue; | |
1654 | ||
1655 | int xx = pen_x + slot->bitmap_left + x; | |
1656 | int yy = pen_y - slot->bitmap_top + y; | |
1657 | m_alpha[ yy * tmparea.width + xx ] = alpha; | |
1658 | } | |
1659 | ||
1660 | pen_x += slot->advance.x >> 6; | |
1661 | pen_y += slot->advance.y >> 6; | |
1662 | } | |
1663 | #endif | |
1664 | ||
84fba40b RR |
1665 | wxBitmap *bitmap = m_admin->GetActive()->GetBuffer(); |
1666 | wxRect sub_rect( clip_x, clip_y, clip_width, clip_height ); | |
96f5fca9 | 1667 | wxBitmap sub_bitmap( bitmap->GetSubBitmap( sub_rect ) ); |
84fba40b | 1668 | |
12d1ab44 | 1669 | wxImage image( sub_bitmap.ConvertToImage() ); |
96f5fca9 RR |
1670 | |
1671 | // local coordinates | |
84fba40b | 1672 | int start_x = clip_x - tmparea.x; |
96f5fca9 | 1673 | int end_x = clip_width + start_x; |
84fba40b | 1674 | int start_y = clip_y - tmparea.y; |
96f5fca9 RR |
1675 | int end_y = clip_height + start_y; |
1676 | ||
1677 | for (int y = start_y; y < end_y; y++) | |
1678 | for (int x = start_x; x < end_x; x++) | |
1679 | { | |
84fba40b | 1680 | int alpha = m_alpha[y*tmparea.width + x]; |
96f5fca9 RR |
1681 | if (alpha) |
1682 | { | |
1683 | int image_x = x - start_x; | |
1684 | int image_y = y - start_y; | |
1685 | if (alpha == 255) | |
1686 | { | |
1687 | image.SetRGB( image_x, image_y, m_red, m_green, m_blue ); | |
1688 | continue; | |
1689 | } | |
1690 | int red1 = (m_red * alpha) / 255; | |
1691 | int green1 = (m_green * alpha) / 255; | |
1692 | int blue1 = (m_blue * alpha) / 255; | |
1693 | ||
1694 | alpha = 255-alpha; | |
1695 | int red2 = image.GetRed( image_x, image_y ); | |
1696 | int green2 = image.GetGreen( image_x, image_y ); | |
1697 | int blue2 = image.GetBlue( image_x, image_y ); | |
1698 | red2 = (red2 * alpha) / 255; | |
1699 | green2 = (green2 * alpha) / 255; | |
1700 | blue2 = (blue2 * alpha) / 255; | |
1701 | ||
1702 | image.SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 ); | |
1703 | } | |
1704 | } | |
84fba40b | 1705 | |
12d1ab44 | 1706 | sub_bitmap = wxBitmap(image); |
84fba40b RR |
1707 | |
1708 | wxDC *dc = m_admin->GetActive()->GetDC(); | |
1709 | dc->DrawBitmap( sub_bitmap, clip_x, clip_y ); | |
d1f9b206 RR |
1710 | } |
1711 | ||
1712 | void wxCanvasText::WriteSVG( wxTextOutputStream &stream ) | |
1713 | { | |
1714 | } | |
1715 | ||
84fba40b | 1716 | void wxCanvasText::TransLate( double x, double y ) |
d1f9b206 | 1717 | { |
84fba40b RR |
1718 | m_x += x; |
1719 | m_y += y; | |
1720 | CalcBoundingBox(); | |
1721 | } | |
dc16900b | 1722 | |
84fba40b RR |
1723 | void wxCanvasText::CalcBoundingBox() |
1724 | { | |
1725 | if (m_alpha) delete [] m_alpha; | |
dc16900b | 1726 | |
84fba40b RR |
1727 | m_bbox.SetMin( m_x , m_y); |
1728 | m_bbox.SetMax( m_x + 100 , m_y + m_size + (m_size/2)); | |
fcbb6b37 | 1729 | |
fcbb6b37 | 1730 | |
84fba40b | 1731 | } |
dc16900b | 1732 | |
84fba40b RR |
1733 | //---------------------------------------------------------------------------- |
1734 | // wxCanvas | |
1735 | //---------------------------------------------------------------------------- | |
fcbb6b37 | 1736 | |
8636c073 | 1737 | IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow) |
fcbb6b37 | 1738 | |
8636c073 | 1739 | BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow) |
6a2c1874 | 1740 | EVT_PAINT( wxCanvas::OnPaint ) |
6a2c1874 | 1741 | EVT_IDLE( wxCanvas::OnIdle ) |
8636c073 | 1742 | EVT_SIZE( wxCanvas::OnSize ) |
6a2c1874 RR |
1743 | EVT_MOUSE_EVENTS( wxCanvas::OnMouse ) |
1744 | EVT_SET_FOCUS( wxCanvas::OnSetFocus ) | |
1745 | EVT_KILL_FOCUS( wxCanvas::OnKillFocus ) | |
61b64bd9 | 1746 | EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground ) |
6a2c1874 RR |
1747 | END_EVENT_TABLE() |
1748 | ||
84fba40b | 1749 | wxCanvas::wxCanvas( wxCanvasAdmin* admin, wxWindow *parent, wxWindowID id, |
6a2c1874 | 1750 | const wxPoint &position, const wxSize& size, long style ) : |
8636c073 | 1751 | wxScrolledWindow( parent, id, position, size, style ) |
6a2c1874 | 1752 | { |
8636c073 RR |
1753 | // These are unused in wxVectorCanvas |
1754 | m_bufferX = 0; | |
1755 | m_bufferY = 0; | |
1756 | ||
84fba40b | 1757 | m_admin = admin; |
8636c073 RR |
1758 | m_admin->Append( this ); |
1759 | ||
6a2c1874 | 1760 | m_needUpdate = FALSE; |
84fba40b | 1761 | m_background = *wxWHITE; |
239c1f50 | 1762 | m_lastMouse = (wxCanvasObject*)NULL; |
4dbd4ee6 | 1763 | m_captureMouse = (wxCanvasObject*)NULL; |
f03b31e8 | 1764 | m_frozen = FALSE; |
27d1065d RR |
1765 | m_oldDeviceX = 0; |
1766 | m_oldDeviceY = 0; | |
8636c073 | 1767 | m_root = (wxCanvasObjectGroup*)NULL; |
6a2c1874 RR |
1768 | } |
1769 | ||
1770 | wxCanvas::~wxCanvas() | |
1771 | { | |
1772 | wxNode *node = m_updateRects.First(); | |
1773 | while (node) | |
1774 | { | |
1775 | wxRect *rect = (wxRect*) node->Data(); | |
1776 | delete rect; | |
1777 | m_updateRects.DeleteNode( node ); | |
1778 | node = m_updateRects.First(); | |
1779 | } | |
1780 | } | |
1781 | ||
8636c073 RR |
1782 | double wxCanvas::GetMinX() const |
1783 | { | |
1784 | return 0.0; | |
1785 | } | |
1786 | ||
1787 | double wxCanvas::GetMinY() const | |
1788 | { | |
1789 | return 0.0; | |
1790 | } | |
1791 | ||
1792 | double wxCanvas::GetMaxX() const | |
1793 | { | |
1794 | int width; | |
1795 | GetVirtualSize( &width, NULL ); | |
1796 | return width; | |
1797 | } | |
1798 | ||
1799 | double wxCanvas::GetMaxY() const | |
1800 | { | |
1801 | int height; | |
1802 | GetVirtualSize( NULL, &height ); | |
1803 | return height; | |
1804 | } | |
1805 | ||
84fba40b | 1806 | void wxCanvas::SetColour( const wxColour& background ) |
cb281cfc | 1807 | { |
8636c073 | 1808 | m_background = background; |
84fba40b | 1809 | SetBackgroundColour( m_background ); |
61b64bd9 | 1810 | |
239c1f50 | 1811 | if (m_frozen) return; |
dc16900b | 1812 | |
33ebcd80 RR |
1813 | wxMemoryDC dc; |
1814 | dc.SelectObject( m_buffer ); | |
1815 | dc.SetPen( *wxTRANSPARENT_PEN ); | |
84fba40b | 1816 | wxBrush brush( m_background, wxSOLID ); |
33ebcd80 RR |
1817 | dc.SetBrush( brush ); |
1818 | dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() ); | |
1819 | dc.SelectObject( wxNullBitmap ); | |
cb281cfc RR |
1820 | } |
1821 | ||
dc16900b | 1822 | void wxCanvas::SetCaptureMouse( wxCanvasObject *obj ) |
4dbd4ee6 | 1823 | { |
dc16900b KH |
1824 | if (obj) |
1825 | { | |
1826 | wxWindow::CaptureMouse(); | |
1827 | m_captureMouse = obj; | |
1828 | } | |
1829 | else | |
1830 | { | |
1831 | wxWindow::ReleaseMouse(); | |
1832 | m_captureMouse = NULL; | |
1833 | } | |
4dbd4ee6 RR |
1834 | } |
1835 | ||
239c1f50 RR |
1836 | void wxCanvas::Freeze() |
1837 | { | |
1838 | m_frozen = TRUE; | |
1839 | } | |
1840 | ||
1841 | void wxCanvas::Thaw() | |
1842 | { | |
1843 | wxNode *node = m_updateRects.First(); | |
1844 | while (node) | |
1845 | { | |
1846 | wxRect *rect = (wxRect*) node->Data(); | |
1847 | delete rect; | |
1848 | m_updateRects.DeleteNode( node ); | |
1849 | node = m_updateRects.First(); | |
1850 | } | |
dc16900b | 1851 | |
239c1f50 | 1852 | m_frozen = FALSE; |
dc16900b | 1853 | |
41328253 | 1854 | if (m_buffer.Ok()) |
8636c073 | 1855 | Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight() ); |
239c1f50 RR |
1856 | } |
1857 | ||
41328253 | 1858 | void wxCanvas::Update( int x, int y, int width, int height, bool blit ) |
6a2c1874 | 1859 | { |
8636c073 RR |
1860 | CalcScrolledPosition( 0, 0, &m_oldDeviceX, &m_oldDeviceY ); |
1861 | ||
84fba40b RR |
1862 | m_admin->SetActive(this); |
1863 | ||
1864 | if (!m_root) return; | |
1865 | ||
239c1f50 | 1866 | if (m_frozen) return; |
fcbb6b37 | 1867 | |
21544859 | 1868 | // clip to buffer |
8636c073 | 1869 | if (x < m_bufferX) |
21544859 | 1870 | { |
8636c073 RR |
1871 | width -= m_bufferX-x; |
1872 | x = m_bufferX; | |
21544859 | 1873 | } |
33ebcd80 | 1874 | if (width <= 0) return; |
dc16900b | 1875 | |
8636c073 | 1876 | if (y < m_bufferY) |
21544859 | 1877 | { |
8636c073 RR |
1878 | height -= m_bufferY-y; |
1879 | y = m_bufferY; | |
21544859 | 1880 | } |
33ebcd80 | 1881 | if (height <= 0) return; |
dc16900b | 1882 | |
8636c073 | 1883 | if (x+width > m_bufferX+m_buffer.GetWidth()) |
21544859 | 1884 | { |
8636c073 | 1885 | width = m_bufferX+m_buffer.GetWidth() - x; |
21544859 | 1886 | } |
33ebcd80 | 1887 | if (width <= 0) return; |
dc16900b | 1888 | |
8636c073 | 1889 | if (y+height > m_bufferY+m_buffer.GetHeight()) |
21544859 | 1890 | { |
8636c073 | 1891 | height = m_bufferY+m_buffer.GetHeight() - y; |
21544859 | 1892 | } |
33ebcd80 | 1893 | if (height <= 0) return; |
dc16900b | 1894 | |
21544859 | 1895 | // update is within the buffer |
6a2c1874 | 1896 | m_needUpdate = TRUE; |
dc16900b | 1897 | |
21544859 | 1898 | // has to be blitted to screen later |
41328253 RR |
1899 | if (blit) |
1900 | { | |
1901 | m_updateRects.Append( | |
1902 | (wxObject*) new wxRect( x,y,width,height ) ); | |
1903 | } | |
dc16900b | 1904 | |
84fba40b RR |
1905 | wxTransformMatrix cworld; |
1906 | ||
33ebcd80 RR |
1907 | wxMemoryDC dc; |
1908 | dc.SelectObject( m_buffer ); | |
84fba40b | 1909 | |
33ebcd80 | 1910 | dc.SetPen( *wxTRANSPARENT_PEN ); |
8636c073 | 1911 | wxBrush brush( m_background, wxSOLID ); |
33ebcd80 | 1912 | dc.SetBrush( brush ); |
8636c073 | 1913 | dc.SetLogicalFunction(wxCOPY); |
33ebcd80 | 1914 | |
8636c073 | 1915 | #if 0 |
84fba40b RR |
1916 | if (width != m_buffer.GetWidth() && height != m_buffer.GetHeight()) |
1917 | { | |
84fba40b RR |
1918 | dc.SetClippingRegion(x,y,width,height); |
1919 | dc.DrawRectangle(x-2,y-2,width+4,height+4); | |
1920 | dc.DestroyClippingRegion(); | |
1921 | } | |
1922 | else | |
1923 | { | |
1924 | dc.Clear(); | |
84fba40b RR |
1925 | dc.DrawRectangle(0,0,m_buffer.GetWidth(),m_buffer.GetHeight()); |
1926 | } | |
8636c073 RR |
1927 | #else |
1928 | // No idea, what the code up there does. | |
1929 | dc.DrawRectangle( x-m_bufferX, y-m_bufferY, width, height ); | |
1930 | #endif | |
1931 | ||
84fba40b RR |
1932 | dc.SetBrush(wxNullBrush); |
1933 | dc.SetPen(wxNullPen); | |
1934 | ||
8636c073 RR |
1935 | dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY ); |
1936 | m_renderDC = &dc; | |
84fba40b | 1937 | |
8636c073 | 1938 | m_root->Render( &cworld, x, y, width, height ); |
5143c96b | 1939 | |
8636c073 | 1940 | m_renderDC = NULL; |
33ebcd80 | 1941 | dc.SelectObject( wxNullBitmap ); |
6a2c1874 RR |
1942 | } |
1943 | ||
3b111dbe | 1944 | void wxCanvas::BlitBuffer( wxDC &dc ) |
6a2c1874 | 1945 | { |
6a2c1874 RR |
1946 | wxNode *node = m_updateRects.First(); |
1947 | while (node) | |
1948 | { | |
1949 | wxRect *rect = (wxRect*) node->Data(); | |
8636c073 | 1950 | |
84fba40b RR |
1951 | wxMemoryDC mdc; |
1952 | mdc.SelectObject( m_buffer ); | |
8636c073 RR |
1953 | dc.Blit( rect->x, |
1954 | rect->y, | |
1955 | rect->width, | |
1956 | rect->height, | |
1957 | &mdc, | |
1958 | rect->x - m_bufferX, | |
1959 | rect->y - m_bufferY ); | |
84fba40b | 1960 | mdc.SelectObject( wxNullBitmap ); |
5143c96b | 1961 | |
6a2c1874 RR |
1962 | delete rect; |
1963 | m_updateRects.DeleteNode( node ); | |
1964 | node = m_updateRects.First(); | |
1965 | } | |
dc16900b | 1966 | |
3b111dbe RR |
1967 | m_needUpdate = FALSE; |
1968 | } | |
1969 | ||
1970 | void wxCanvas::UpdateNow() | |
1971 | { | |
61b64bd9 RR |
1972 | if (m_frozen) return; |
1973 | ||
3b111dbe | 1974 | if (!m_needUpdate) return; |
dc16900b | 1975 | |
3b111dbe RR |
1976 | wxClientDC dc( this ); |
1977 | PrepareDC( dc ); | |
dc16900b | 1978 | |
3b111dbe | 1979 | BlitBuffer( dc ); |
6a2c1874 RR |
1980 | } |
1981 | ||
8636c073 RR |
1982 | void wxCanvas::OnSize(wxSizeEvent &event) |
1983 | { | |
1984 | int w,h; | |
1985 | GetClientSize( &w, &h ); | |
1986 | m_buffer = wxBitmap( w, h ); | |
1987 | ||
1988 | CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY ); | |
1989 | ||
1990 | wxNode *node = m_updateRects.First(); | |
1991 | while (node) | |
1992 | { | |
1993 | wxRect *rect = (wxRect*) node->Data(); | |
1994 | delete rect; | |
1995 | m_updateRects.DeleteNode( node ); | |
1996 | node = m_updateRects.First(); | |
1997 | } | |
1998 | ||
1999 | m_frozen = FALSE; | |
2000 | ||
2001 | Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE ); | |
2002 | ||
2003 | event.Skip(); | |
2004 | } | |
2005 | ||
6a2c1874 RR |
2006 | void wxCanvas::OnPaint(wxPaintEvent &event) |
2007 | { | |
6a2c1874 | 2008 | wxPaintDC dc(this); |
3b111dbe | 2009 | PrepareDC( dc ); |
dc16900b | 2010 | |
41328253 | 2011 | if (!m_buffer.Ok()) return; |
fcbb6b37 | 2012 | |
b85cfb6f | 2013 | if (m_frozen) return; |
41328253 | 2014 | |
6a2c1874 RR |
2015 | m_needUpdate = TRUE; |
2016 | ||
2017 | wxRegionIterator it( GetUpdateRegion() ); | |
2018 | while (it) | |
2019 | { | |
2020 | int x = it.GetX(); | |
2021 | int y = it.GetY(); | |
dc16900b | 2022 | |
6a2c1874 RR |
2023 | int w = it.GetWidth(); |
2024 | int h = it.GetHeight(); | |
dc16900b | 2025 | |
21544859 RR |
2026 | if (x+w > m_buffer.GetWidth()) |
2027 | w = m_buffer.GetWidth() - x; | |
2028 | if (y+h > m_buffer.GetHeight()) | |
2029 | h = m_buffer.GetHeight() - y; | |
dc16900b | 2030 | |
21544859 | 2031 | if ((w > 0) && (h > 0)) |
41328253 | 2032 | { |
8636c073 RR |
2033 | x += m_bufferX; |
2034 | y += m_bufferY; | |
21544859 | 2035 | m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) ); |
41328253 | 2036 | } |
dc16900b | 2037 | |
6a2c1874 RR |
2038 | it++; |
2039 | } | |
dc16900b | 2040 | |
3b111dbe | 2041 | BlitBuffer( dc ); |
6a2c1874 RR |
2042 | } |
2043 | ||
41328253 RR |
2044 | void wxCanvas::ScrollWindow( int dx, int dy, const wxRect* rect ) |
2045 | { | |
61b64bd9 | 2046 | // If any updates are pending, do them now since they will |
27d1065d | 2047 | // expect the previous m_bufferX and m_bufferY as well as |
84fba40b | 2048 | // the previous device origin values. |
27d1065d RR |
2049 | wxClientDC dc( this ); |
2050 | dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY ); | |
2051 | BlitBuffer( dc ); | |
41328253 | 2052 | |
8636c073 RR |
2053 | // The buffer always starts at the top left corner of the |
2054 | // client area. Indeed, it is the client area. | |
2055 | CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY ); | |
2056 | ||
2057 | // Update everything. | |
2058 | Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE ); | |
2059 | ||
2060 | // Scroll, actually. | |
2061 | wxWindow::ScrollWindow( dx, dy, rect ); | |
2062 | } | |
2063 | ||
2064 | void wxCanvas::OnMouse(wxMouseEvent &event) | |
2065 | { | |
2066 | m_admin->SetActive(this); | |
2067 | if (!m_root) | |
84fba40b | 2068 | { |
8636c073 RR |
2069 | event.Skip(); |
2070 | return; | |
84fba40b RR |
2071 | } |
2072 | ||
8636c073 RR |
2073 | int x = event.GetX(); |
2074 | int y = event.GetY(); | |
41328253 | 2075 | |
8636c073 RR |
2076 | //to world coordinates to do hit test in world coordinates |
2077 | double xw = DeviceToLogicalX( x ); | |
2078 | double yw = DeviceToLogicalY( y ); | |
fcbb6b37 | 2079 | |
8636c073 RR |
2080 | //make a select margin of 2 pixels, so also zero line thickness will be hit |
2081 | double margin = DeviceToLogicalXRel( 2 ); | |
fcbb6b37 | 2082 | |
8636c073 | 2083 | if (event.GetEventType() == wxEVT_MOTION) |
41328253 | 2084 | { |
8636c073 | 2085 | if (m_captureMouse) //no matter what go to this one |
61b64bd9 | 2086 | { |
8636c073 RR |
2087 | wxMouseEvent child_event( wxEVT_MOTION ); |
2088 | child_event.SetEventObject(m_captureMouse); | |
2089 | child_event.m_x = x; | |
2090 | child_event.m_y = y; | |
2091 | child_event.m_leftDown = event.m_leftDown; | |
2092 | child_event.m_rightDown = event.m_rightDown; | |
2093 | child_event.m_middleDown = event.m_middleDown; | |
2094 | child_event.m_controlDown = event.m_controlDown; | |
2095 | child_event.m_shiftDown = event.m_shiftDown; | |
2096 | child_event.m_altDown = event.m_altDown; | |
2097 | child_event.m_metaDown = event.m_metaDown; | |
fcbb6b37 | 2098 | |
8636c073 RR |
2099 | m_captureMouse->ProcessCanvasObjectEvent( child_event ); |
2100 | return; | |
61b64bd9 RR |
2101 | } |
2102 | else | |
2103 | { | |
8636c073 | 2104 | wxCanvasObject *obj = m_root->IsHitWorld(xw,yw,margin); |
fcbb6b37 | 2105 | |
8636c073 RR |
2106 | if (obj && !obj->IsControl()) |
2107 | { | |
2108 | wxMouseEvent child_event( wxEVT_MOTION ); | |
2109 | child_event.SetEventObject( obj ); | |
2110 | child_event.m_x = x; | |
2111 | child_event.m_y = y; | |
2112 | child_event.m_leftDown = event.m_leftDown; | |
2113 | child_event.m_rightDown = event.m_rightDown; | |
2114 | child_event.m_middleDown = event.m_middleDown; | |
2115 | child_event.m_controlDown = event.m_controlDown; | |
2116 | child_event.m_shiftDown = event.m_shiftDown; | |
2117 | child_event.m_altDown = event.m_altDown; | |
2118 | child_event.m_metaDown = event.m_metaDown; | |
41328253 | 2119 | |
8636c073 RR |
2120 | if ((obj != m_lastMouse) && (m_lastMouse != NULL)) |
2121 | { | |
2122 | child_event.SetEventType( wxEVT_LEAVE_WINDOW ); | |
2123 | child_event.SetEventObject( m_lastMouse ); | |
2124 | child_event.m_x = x; | |
2125 | child_event.m_y = y; | |
2126 | m_lastMouse->ProcessCanvasObjectEvent( child_event ); | |
fcbb6b37 KH |
2127 | |
2128 | m_lastMouse = obj; | |
2129 | child_event.SetEventType( wxEVT_ENTER_WINDOW ); | |
2130 | child_event.SetEventObject( m_lastMouse ); | |
84fba40b RR |
2131 | child_event.m_x = x; |
2132 | child_event.m_y = y; | |
2133 | m_lastMouse->ProcessCanvasObjectEvent( child_event ); | |
fcbb6b37 KH |
2134 | |
2135 | child_event.SetEventType( wxEVT_MOTION ); | |
2136 | child_event.SetEventObject( obj ); | |
239c1f50 | 2137 | } |
84fba40b RR |
2138 | |
2139 | obj->ProcessCanvasObjectEvent( child_event ); | |
fcbb6b37 | 2140 | return; |
239c1f50 | 2141 | } |
239c1f50 RR |
2142 | } |
2143 | if (m_lastMouse) | |
2144 | { | |
2145 | wxMouseEvent child_event( wxEVT_LEAVE_WINDOW ); | |
2146 | child_event.SetEventObject( m_lastMouse ); | |
84fba40b RR |
2147 | child_event.m_x = x; |
2148 | child_event.m_y = y; | |
239c1f50 RR |
2149 | child_event.m_leftDown = event.m_leftDown; |
2150 | child_event.m_rightDown = event.m_rightDown; | |
2151 | child_event.m_middleDown = event.m_middleDown; | |
2152 | child_event.m_controlDown = event.m_controlDown; | |
2153 | child_event.m_shiftDown = event.m_shiftDown; | |
2154 | child_event.m_altDown = event.m_altDown; | |
2155 | child_event.m_metaDown = event.m_metaDown; | |
84fba40b | 2156 | m_lastMouse->ProcessCanvasObjectEvent( child_event ); |
dc16900b | 2157 | |
239c1f50 RR |
2158 | m_lastMouse = (wxCanvasObject*) NULL; |
2159 | return; | |
2160 | } | |
2161 | } | |
872f1044 RR |
2162 | else |
2163 | { | |
2164 | if (m_captureMouse) //no matter what go to this one | |
2165 | { | |
2166 | wxMouseEvent child_event( event.GetEventType() ); | |
2167 | child_event.SetEventObject(m_captureMouse); | |
84fba40b RR |
2168 | child_event.m_x = x; |
2169 | child_event.m_y = y; | |
872f1044 RR |
2170 | child_event.m_leftDown = event.m_leftDown; |
2171 | child_event.m_rightDown = event.m_rightDown; | |
2172 | child_event.m_middleDown = event.m_middleDown; | |
2173 | child_event.m_controlDown = event.m_controlDown; | |
2174 | child_event.m_shiftDown = event.m_shiftDown; | |
2175 | child_event.m_altDown = event.m_altDown; | |
2176 | child_event.m_metaDown = event.m_metaDown; | |
84fba40b | 2177 | m_captureMouse->ProcessCanvasObjectEvent( child_event ); |
872f1044 RR |
2178 | } |
2179 | else | |
2180 | { | |
84fba40b | 2181 | wxCanvasObject *obj = m_root->IsHitWorld(xw,yw,margin); |
872f1044 RR |
2182 | |
2183 | if (obj && !obj->IsControl()) | |
2184 | { | |
2185 | wxMouseEvent child_event( event.GetEventType() ); | |
2186 | child_event.SetEventObject( obj ); | |
84fba40b RR |
2187 | child_event.m_x = x; |
2188 | child_event.m_y = y; | |
872f1044 RR |
2189 | child_event.m_leftDown = event.m_leftDown; |
2190 | child_event.m_rightDown = event.m_rightDown; | |
2191 | child_event.m_middleDown = event.m_middleDown; | |
2192 | child_event.m_controlDown = event.m_controlDown; | |
2193 | child_event.m_shiftDown = event.m_shiftDown; | |
2194 | child_event.m_altDown = event.m_altDown; | |
2195 | child_event.m_metaDown = event.m_metaDown; | |
84fba40b RR |
2196 | |
2197 | obj->ProcessCanvasObjectEvent( child_event ); | |
872f1044 RR |
2198 | return; |
2199 | } | |
2200 | } | |
2201 | } | |
fcbb6b37 | 2202 | |
239c1f50 | 2203 | event.Skip(); |
6a2c1874 RR |
2204 | } |
2205 | ||
8636c073 RR |
2206 | void wxCanvas::OnIdle(wxIdleEvent &event) |
2207 | { | |
2208 | m_admin->SetActive(this); | |
2209 | UpdateNow(); | |
2210 | event.Skip(); | |
2211 | } | |
2212 | ||
2213 | void wxCanvas::OnSetFocus(wxFocusEvent &event) | |
2214 | { | |
2215 | m_admin->SetActive(this); | |
2216 | } | |
2217 | ||
2218 | void wxCanvas::OnKillFocus(wxFocusEvent &event) | |
2219 | { | |
2220 | } | |
2221 | ||
2222 | ||
2223 | void wxCanvas::OnEraseBackground(wxEraseEvent &event) | |
2224 | { | |
2225 | } | |
2226 | ||
2227 | // coordinates conversions | |
2228 | // ----------------------- | |
2229 | double wxCanvas::DeviceToLogicalX(int x) const | |
2230 | { | |
2231 | return (double)(x); | |
2232 | } | |
2233 | ||
2234 | double wxCanvas::DeviceToLogicalY(int y) const | |
2235 | { | |
2236 | return (double)(y); | |
2237 | } | |
2238 | ||
2239 | double wxCanvas::DeviceToLogicalXRel(int x) const | |
2240 | { | |
2241 | return (double)x; | |
2242 | } | |
2243 | ||
2244 | double wxCanvas::DeviceToLogicalYRel(int y) const | |
2245 | { | |
2246 | return (double)y; | |
2247 | } | |
2248 | ||
2249 | int wxCanvas::LogicalToDeviceX(double x) const | |
2250 | { | |
2251 | return (int)(x + 0.5); | |
2252 | } | |
2253 | ||
2254 | int wxCanvas::LogicalToDeviceY(double y) const | |
2255 | { | |
2256 | return (int)(y + 0.5); | |
2257 | } | |
2258 | ||
2259 | int wxCanvas::LogicalToDeviceXRel(double x) const | |
2260 | { | |
2261 | return (int)(x + 0.5); | |
2262 | } | |
2263 | ||
2264 | int wxCanvas::LogicalToDeviceYRel(double y) const | |
2265 | { | |
2266 | return (int)(y + 0.5); | |
2267 | } | |
2268 | ||
2269 | //---------------------------------------------------------------------------- | |
2270 | // wxVectorCanvas | |
2271 | //---------------------------------------------------------------------------- | |
2272 | ||
2273 | IMPLEMENT_CLASS(wxVectorCanvas,wxCanvas) | |
2274 | ||
2275 | BEGIN_EVENT_TABLE(wxVectorCanvas,wxCanvas) | |
2276 | EVT_SCROLLWIN( wxVectorCanvas::OnScroll ) | |
2277 | EVT_CHAR( wxVectorCanvas::OnChar ) | |
2278 | EVT_SIZE( wxVectorCanvas::OnSize ) | |
2279 | END_EVENT_TABLE() | |
2280 | ||
2281 | wxVectorCanvas::wxVectorCanvas( wxCanvasAdmin* admin, wxWindow *parent, wxWindowID id, | |
2282 | const wxPoint &position, const wxSize& size, long style ) : | |
2283 | wxCanvas( admin, parent, id, position, size, style ) | |
2284 | { | |
2285 | m_scrolled = FALSE; | |
2286 | m_yaxis = FALSE; | |
2287 | } | |
2288 | ||
2289 | double wxVectorCanvas::GetMinX() const | |
2290 | { | |
2291 | return m_virt_minX; | |
2292 | } | |
2293 | ||
2294 | double wxVectorCanvas::GetMinY() const | |
2295 | { | |
2296 | return m_virt_minY; | |
2297 | } | |
2298 | ||
2299 | double wxVectorCanvas::GetMaxX() const | |
2300 | { | |
2301 | return m_virt_maxX; | |
2302 | } | |
2303 | ||
2304 | double wxVectorCanvas::GetMaxY() const | |
2305 | { | |
2306 | return m_virt_maxY; | |
2307 | } | |
2308 | ||
2309 | void wxVectorCanvas::ScrollWindow( int dx, int dy, const wxRect* rect ) | |
2310 | { | |
2311 | // If any updates are pending, do them now since they will | |
2312 | // expect the previous m_bufferX and m_bufferY as well as | |
2313 | // the previous device origin values. | |
2314 | wxClientDC dc( this ); | |
2315 | dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY ); | |
2316 | BlitBuffer( dc ); | |
2317 | ||
2318 | if (dy != 0) | |
2319 | { | |
2320 | double dyv=DeviceToLogicalYRel(dy); | |
2321 | m_virt_minY=m_virt_minY-dyv; | |
2322 | m_virt_maxY=m_virt_maxY-dyv; | |
2323 | } | |
2324 | if (dx != 0) | |
2325 | { | |
2326 | double dxv=DeviceToLogicalXRel(dx); | |
2327 | m_virt_minX=m_virt_minX-dxv; | |
2328 | m_virt_maxX=m_virt_maxX-dxv; | |
2329 | } | |
2330 | ||
2331 | m_admin->SetActive(this); | |
2332 | SetMappingScroll(m_virt_minX,m_virt_minY,m_virt_maxX,m_virt_maxY,FALSE); | |
2333 | ||
2334 | ||
2335 | if (dy != 0) | |
2336 | { | |
2337 | if (dy > 0 && dy < m_buffer.GetHeight()) | |
2338 | { | |
2339 | wxRect rect( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight()-dy); | |
2340 | wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) ); | |
2341 | wxMemoryDC dcm; | |
2342 | dcm.SelectObject( m_buffer ); | |
2343 | dcm.DrawBitmap( sub_bitmap, 0, dy, TRUE ); | |
2344 | dcm.SelectObject( wxNullBitmap ); | |
2345 | ||
2346 | Update( 0, 0, m_buffer.GetWidth(), dy, TRUE ); | |
2347 | } | |
2348 | else if (dy < 0 && dy > -m_buffer.GetHeight()) | |
2349 | { | |
2350 | wxRect rect( 0, -dy, m_buffer.GetWidth(), m_buffer.GetHeight()+dy); | |
2351 | wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) ); | |
2352 | wxMemoryDC dcm; | |
2353 | dcm.SelectObject( m_buffer ); | |
2354 | dcm.DrawBitmap( sub_bitmap, 0, 0, TRUE ); | |
2355 | dcm.SelectObject( wxNullBitmap ); | |
2356 | ||
2357 | Update( 0, m_buffer.GetHeight()+dy, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE ); | |
2358 | } | |
2359 | else | |
2360 | Update( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE ); | |
2361 | } | |
2362 | ||
2363 | if (dx != 0) | |
2364 | { | |
2365 | if (dx > 0 && dx < m_buffer.GetWidth()) | |
2366 | { | |
2367 | wxRect rect( 0, 0, m_buffer.GetWidth()-dx, m_buffer.GetHeight()); | |
2368 | wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) ); | |
2369 | wxMemoryDC dcm; | |
2370 | dcm.SelectObject( m_buffer ); | |
2371 | dcm.DrawBitmap( sub_bitmap, dx, 0, TRUE ); | |
2372 | dcm.SelectObject( wxNullBitmap ); | |
2373 | ||
2374 | Update( 0, 0, dx, m_buffer.GetHeight(), TRUE ); | |
2375 | } | |
2376 | else if (dx < 0 && dx > -m_buffer.GetWidth()) | |
2377 | { | |
2378 | wxRect rect( -dx, 0, m_buffer.GetWidth()+dx, m_buffer.GetHeight()); | |
2379 | wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) ); | |
2380 | wxMemoryDC dcm; | |
2381 | dcm.SelectObject( m_buffer ); | |
2382 | dcm.DrawBitmap( sub_bitmap, 0, 0, TRUE ); | |
2383 | dcm.SelectObject( wxNullBitmap ); | |
2384 | ||
2385 | Update( m_buffer.GetWidth()+dx, 0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE ); | |
2386 | } | |
2387 | else | |
2388 | Update( 0,0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE ); | |
2389 | } | |
2390 | ||
2391 | wxWindow::ScrollWindow( dx, dy, rect ); | |
2392 | ||
2393 | //must be done now because quick repeated scrolling will prevent wxPaint | |
2394 | //from doing it properly | |
2395 | UpdateNow(); | |
2396 | } | |
2397 | ||
2398 | void wxVectorCanvas::OnSize(wxSizeEvent &event) | |
6a2c1874 | 2399 | { |
b85cfb6f | 2400 | int w,h; |
84fba40b | 2401 | |
b85cfb6f | 2402 | GetClientSize( &w, &h ); |
84fba40b | 2403 | |
84fba40b | 2404 | wxMemoryDC dc; |
33ebcd80 | 2405 | m_buffer = wxBitmap( w, h ); |
84fba40b RR |
2406 | dc.SelectObject( m_buffer ); |
2407 | dc.SetPen( *wxTRANSPARENT_PEN ); | |
2408 | wxBrush brush( m_background , wxSOLID ); | |
2409 | dc.SetBrush( brush ); | |
2410 | dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() ); | |
2411 | dc.SelectObject( wxNullBitmap ); | |
fcbb6b37 | 2412 | |
b85cfb6f RR |
2413 | wxNode *node = m_updateRects.First(); |
2414 | while (node) | |
2415 | { | |
2416 | wxRect *rect = (wxRect*) node->Data(); | |
2417 | delete rect; | |
2418 | m_updateRects.DeleteNode( node ); | |
2419 | node = m_updateRects.First(); | |
2420 | } | |
2421 | ||
2422 | m_frozen = FALSE; | |
2423 | ||
84fba40b RR |
2424 | m_admin->SetActive(this); |
2425 | SetMappingScroll(m_virt_minX,m_virt_minY,m_virt_maxX,m_virt_maxY,FALSE); | |
2426 | ||
2427 | Update( 0,0, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE ); | |
41328253 | 2428 | |
8636c073 | 2429 | // event.Skip(); |
6a2c1874 RR |
2430 | } |
2431 | ||
84fba40b RR |
2432 | // maps the virtual window (Real drawing to the window coordinates |
2433 | // also used for zooming | |
8636c073 | 2434 | void wxVectorCanvas::SetMappingScroll( double vx1, double vy1, double vx2, double vy2, bool border) |
84fba40b RR |
2435 | { |
2436 | int dwxi,dwyi; | |
2437 | GetClientSize(&dwxi,&dwyi); | |
2438 | ||
2439 | if (vx2==vx1) vx2=vx1+100000; | |
2440 | if (vy2==vy1) vy2=vy1+100000; | |
2441 | m_virt_minX=vx1; | |
2442 | m_virt_minY=vy1; | |
2443 | m_virt_maxX=vx2; | |
2444 | m_virt_maxY=vy2; | |
2445 | ||
2446 | double dwx=dwxi; | |
2447 | double dwy=dwyi; | |
2448 | if (dwx==0) dwx=1; | |
2449 | if (dwy==0) dwy=1; | |
2450 | ||
2451 | double dvx = m_virt_maxX - m_virt_minX; | |
2452 | double dvy = m_virt_maxY - m_virt_minY; | |
2453 | ||
2454 | // calculate the scaling factor for the virtual window | |
2455 | double temp_x=0; | |
2456 | double temp_y=0; | |
2457 | if ((dvy / dvx) < (dwy / dwx)) | |
2458 | { | |
2459 | dvy = dvx * (dwy / dwx); | |
2460 | // calculate the change in the coordinates | |
2461 | temp_y = (dvy - (m_virt_maxY - m_virt_minY) )/ 2.0; | |
2462 | } | |
2463 | else | |
2464 | { | |
2465 | dvx = dvy * (dwx / dwy); | |
2466 | // calculate the change in the coordinates | |
2467 | temp_x = (dvx - (m_virt_maxX - m_virt_minX) )/ 2.0; | |
2468 | } | |
2469 | ||
2470 | // add or substract the change from the original coordinates | |
2471 | m_virt_minX=m_virt_minX-temp_x; | |
2472 | m_virt_minY=m_virt_minY-temp_y; | |
2473 | ||
2474 | m_virt_maxX=m_virt_maxX+temp_x; | |
2475 | m_virt_maxY=m_virt_maxY+temp_y; | |
2476 | ||
2477 | // initialize the mapping_matrix used for mapping the | |
2478 | // virtual windows to the drawing window | |
2479 | ||
2480 | // make mappingmatrix | |
2481 | m_mapping_matrix.Identity(); | |
2482 | if (!border) | |
f03b31e8 | 2483 | { |
84fba40b RR |
2484 | // translate the drawing to 0,0 |
2485 | if (m_yaxis) | |
2486 | m_mapping_matrix.Translate(-m_virt_minX,-m_virt_maxY); | |
2487 | else | |
2488 | m_mapping_matrix.Translate(-m_virt_minX,-m_virt_minY); | |
f03b31e8 | 2489 | } |
84fba40b RR |
2490 | else |
2491 | { | |
2492 | // make a small white border around the drawing | |
2493 | m_virt_minX=m_virt_minX- 0.05 * dvx; | |
2494 | m_virt_minY=m_virt_minY- 0.05 * dvy; | |
2495 | ||
2496 | m_virt_maxX=m_virt_maxX+ 0.05 * dvx; | |
2497 | m_virt_maxY=m_virt_maxY+ 0.05 * dvy; | |
2498 | ||
2499 | // translate the drawing to 0,0 | |
2500 | if (m_yaxis) | |
2501 | m_mapping_matrix.Translate(-m_virt_minX,-m_virt_maxY); | |
2502 | else | |
2503 | m_mapping_matrix.Translate(-m_virt_minX,-m_virt_minY); | |
2504 | } | |
2505 | ||
2506 | double scalefactor_x = dwx; | |
2507 | scalefactor_x /= (m_virt_maxX - m_virt_minX); | |
2508 | ||
2509 | double scalefactor_y = dwy; | |
2510 | scalefactor_y /= (m_virt_maxY - m_virt_minY); | |
2511 | ||
2512 | // scale the drawing so it fit's in the window | |
2513 | m_mapping_matrix.Scale(scalefactor_x, scalefactor_y, 0, 0); | |
2514 | ||
2515 | // because of coordinate change mirror over X | |
2516 | // 0,0 in graphic computerscreens: upperleft corner | |
2517 | // 0,0 in cartesian: lowerleft corner | |
2518 | if (m_yaxis) | |
2519 | { | |
2520 | m_mapping_matrix.Mirror(); | |
2521 | } | |
2522 | // make inverse of mapping matrix | |
2523 | // this is to set coordinates in the statusbar | |
2524 | // and the calculate screencoordinates to world coordinates used | |
2525 | // in zooming | |
2526 | m_inverse_mapping=m_mapping_matrix; | |
2527 | m_inverse_mapping.Invert(); | |
2528 | ||
2529 | if (m_scrolled) | |
2530 | SetScroll(m_virtm_minX,m_virtm_minY,m_virtm_maxX,m_virtm_maxY); | |
2531 | ||
2532 | int dx2,dy2; | |
2533 | GetClientSize(&dx2,&dy2); | |
2534 | if ( dwxi != dx2 || dwyi != dy2) //scrollbar is/became empty | |
2535 | SetScroll(m_virtm_minX,m_virtm_minY,m_virtm_maxX,m_virtm_maxY); | |
2536 | } | |
2537 | ||
2538 | ||
8636c073 | 2539 | void wxVectorCanvas::SetScroll(double vx1,double vy1,double vx2,double vy2) |
84fba40b RR |
2540 | { |
2541 | m_virtm_minX=vx1; | |
2542 | m_virtm_minY=vy1; | |
2543 | m_virtm_maxX=vx2; | |
2544 | m_virtm_maxY=vy2; | |
2545 | ||
2546 | double dvx = m_virt_maxX - m_virt_minX; | |
2547 | double dvy = m_virt_maxY - m_virt_minY; | |
2548 | double dmvx = m_virtm_maxX - m_virtm_minX; | |
2549 | double dmvy = m_virtm_maxY - m_virtm_minY; | |
2550 | ||
f03b31e8 | 2551 | SetScrollbar(wxHORIZONTAL,(m_virt_minX-m_virtm_minX)/dmvx *1000,dvx/dmvx *1000,1000,FALSE); |
84fba40b RR |
2552 | if (m_yaxis) |
2553 | { | |
f03b31e8 | 2554 | SetScrollbar(wxVERTICAL,(m_virtm_maxY-m_virt_maxY)/dmvy *1000,dvy/dmvy *1000,1000,FALSE); |
84fba40b RR |
2555 | } |
2556 | else | |
2557 | { | |
f03b31e8 | 2558 | SetScrollbar(wxVERTICAL,(m_virt_minY-m_virtm_minY)/dmvy *1000,dvy/dmvy *1000,1000,FALSE); |
84fba40b RR |
2559 | } |
2560 | ||
f03b31e8 | 2561 | m_scrolled=TRUE; |
84fba40b RR |
2562 | } |
2563 | ||
2564 | // coordinates conversions | |
2565 | // ----------------------- | |
8636c073 | 2566 | double wxVectorCanvas::DeviceToLogicalX(int x) const |
61b64bd9 | 2567 | { |
84fba40b | 2568 | return m_inverse_mapping.GetValue(0,0) * x + m_inverse_mapping.GetValue(2,0); |
61b64bd9 RR |
2569 | } |
2570 | ||
8636c073 | 2571 | double wxVectorCanvas::DeviceToLogicalY(int y) const |
84fba40b RR |
2572 | { |
2573 | return m_inverse_mapping.GetValue(1,1) * y + m_inverse_mapping.GetValue(2,1); | |
2574 | } | |
2575 | ||
8636c073 | 2576 | double wxVectorCanvas::DeviceToLogicalXRel(int x) const |
84fba40b RR |
2577 | { |
2578 | return x*m_inverse_mapping.GetValue(0,0); | |
2579 | } | |
2580 | ||
8636c073 | 2581 | double wxVectorCanvas::DeviceToLogicalYRel(int y) const |
84fba40b RR |
2582 | { |
2583 | return y*m_inverse_mapping.GetValue(1,1); | |
2584 | } | |
2585 | ||
8636c073 | 2586 | int wxVectorCanvas::LogicalToDeviceX(double x) const |
84fba40b RR |
2587 | { |
2588 | return (int) (m_mapping_matrix.GetValue(0,0) * x + m_mapping_matrix.GetValue(2,0) + 0.5); | |
2589 | } | |
2590 | ||
8636c073 | 2591 | int wxVectorCanvas::LogicalToDeviceY(double y) const |
84fba40b RR |
2592 | { |
2593 | return (int) (m_mapping_matrix.GetValue(1,1) * y + m_mapping_matrix.GetValue(2,1) + 0.5); | |
2594 | } | |
2595 | ||
8636c073 | 2596 | int wxVectorCanvas::LogicalToDeviceXRel(double x) const |
84fba40b RR |
2597 | { |
2598 | return (int) (x*m_mapping_matrix.GetValue(0,0) + 0.5); | |
2599 | } | |
2600 | ||
8636c073 | 2601 | int wxVectorCanvas::LogicalToDeviceYRel(double y) const |
84fba40b RR |
2602 | { |
2603 | return (int) (y*m_mapping_matrix.GetValue(1,1) + 0.5); | |
2604 | } | |
2605 | ||
2606 | ||
84fba40b | 2607 | // return the inverse mapping matrix for zooming or coordinates |
8636c073 | 2608 | wxTransformMatrix wxVectorCanvas::GetInverseMappingMatrix() |
84fba40b RR |
2609 | { |
2610 | return m_inverse_mapping; | |
2611 | } | |
2612 | ||
8636c073 | 2613 | wxTransformMatrix wxVectorCanvas::GetMappingMatrix() |
84fba40b RR |
2614 | { |
2615 | return m_mapping_matrix; | |
2616 | } | |
2617 | ||
2618 | ||
2619 | // ---------------------------------------------------------------------------- | |
2620 | // scrolling behaviour | |
2621 | // ---------------------------------------------------------------------------- | |
2622 | ||
8636c073 | 2623 | void wxVectorCanvas::OnScroll(wxScrollWinEvent& event) |
84fba40b RR |
2624 | { |
2625 | if (event.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE) | |
2626 | { | |
2627 | if (event.GetOrientation()==wxHORIZONTAL) | |
2628 | { | |
2629 | double x=m_virtm_minX+event.GetPosition()/1000.0*(m_virtm_maxX-m_virtm_minX); | |
2630 | x=LogicalToDeviceXRel(x-m_virt_minX); | |
2631 | ScrollWindow(-x, 0, (const wxRect *) NULL); | |
2632 | } | |
2633 | else | |
2634 | { | |
2635 | double y=m_virtm_minY+event.GetPosition()/1000.0*(m_virtm_maxY-m_virtm_minY); | |
2636 | y=LogicalToDeviceYRel(y-m_virt_minY); | |
2637 | ScrollWindow(0, -y, (const wxRect *) NULL); | |
2638 | } | |
2639 | } | |
2640 | else if (event.GetEventType()==wxEVT_SCROLLWIN_PAGEUP) | |
2641 | { | |
2642 | if (event.GetOrientation()==wxHORIZONTAL) | |
2643 | { | |
2644 | double x=GetBufferWidth(); | |
2645 | ScrollWindow(x, 0, (const wxRect *) NULL); | |
2646 | } | |
2647 | else | |
2648 | { | |
2649 | double y=GetBufferHeight(); | |
2650 | ScrollWindow(0, y, (const wxRect *) NULL); | |
2651 | } | |
2652 | } | |
2653 | else if (event.GetEventType()==wxEVT_SCROLLWIN_PAGEDOWN) | |
2654 | { | |
2655 | if (event.GetOrientation()==wxHORIZONTAL) | |
2656 | { | |
2657 | double x=-GetBufferWidth(); | |
2658 | ScrollWindow(x, 0, (const wxRect *) NULL); | |
2659 | } | |
2660 | else | |
2661 | { | |
2662 | double y=-GetBufferHeight(); | |
2663 | ScrollWindow(0, y, (const wxRect *) NULL); | |
2664 | } | |
2665 | } | |
2666 | else if (event.GetEventType()==wxEVT_SCROLLWIN_LINEUP) | |
2667 | { | |
2668 | if (event.GetOrientation()==wxHORIZONTAL) | |
2669 | { | |
2670 | int x=GetBufferWidth()/10; | |
2671 | ScrollWindow(x, 0, (const wxRect *) NULL); | |
2672 | } | |
2673 | else | |
2674 | { | |
2675 | int y=GetBufferHeight()/10; | |
2676 | ScrollWindow(0, y, (const wxRect *) NULL); | |
2677 | } | |
2678 | } | |
2679 | else if (event.GetEventType()==wxEVT_SCROLLWIN_LINEDOWN) | |
2680 | { | |
2681 | if (event.GetOrientation()==wxHORIZONTAL) | |
2682 | { | |
2683 | int x=-GetBufferWidth()/10; | |
2684 | ScrollWindow(x, 0, (const wxRect *) NULL); | |
2685 | } | |
2686 | else | |
2687 | { | |
2688 | int y=-GetBufferHeight()/10; | |
2689 | ScrollWindow(0, y, (const wxRect *) NULL); | |
2690 | } | |
2691 | } | |
2692 | ||
2693 | } | |
2694 | ||
8636c073 | 2695 | void wxVectorCanvas::OnChar(wxKeyEvent& event) |
84fba40b RR |
2696 | { |
2697 | switch ( event.KeyCode() ) | |
2698 | { | |
2699 | case WXK_PAGEUP: | |
2700 | case WXK_PRIOR: | |
2701 | { | |
2702 | double y=GetBufferHeight(); | |
2703 | ScrollWindow(0, y, (const wxRect *) NULL); | |
2704 | } | |
2705 | break; | |
2706 | case WXK_PAGEDOWN: | |
2707 | case WXK_NEXT: | |
2708 | { | |
2709 | double y=-GetBufferHeight(); | |
2710 | ScrollWindow(0, y, (const wxRect *) NULL); | |
2711 | } | |
2712 | break; | |
2713 | case WXK_HOME: | |
2714 | { | |
2715 | double y=m_virtm_minY; | |
2716 | y=LogicalToDeviceYRel(y-m_virt_minY); | |
2717 | ScrollWindow(0, -y, (const wxRect *) NULL); | |
2718 | } | |
2719 | break; | |
2720 | case WXK_END: | |
2721 | { | |
2722 | double y=m_virtm_minY+(m_virtm_maxY-m_virtm_minY); | |
2723 | y=LogicalToDeviceYRel(y-m_virt_minY); | |
2724 | ScrollWindow(0, -y, (const wxRect *) NULL); | |
2725 | } | |
2726 | break; | |
2727 | case WXK_UP: | |
2728 | { | |
2729 | int y; | |
2730 | if (!event.ControlDown()) | |
2731 | y=GetBufferHeight()/10; | |
2732 | else | |
2733 | y=GetBufferHeight(); | |
2734 | ScrollWindow(0, y, (const wxRect *) NULL); | |
2735 | } | |
2736 | break; | |
2737 | ||
2738 | case WXK_DOWN: | |
2739 | { | |
2740 | int y; | |
2741 | if (!event.ControlDown()) | |
2742 | y=-GetBufferHeight()/10; | |
2743 | else | |
2744 | y=-GetBufferHeight(); | |
2745 | ScrollWindow(0, y, (const wxRect *) NULL); | |
2746 | } | |
2747 | break; | |
2748 | ||
2749 | case WXK_LEFT: | |
2750 | { | |
2751 | int x; | |
2752 | if (!event.ControlDown()) | |
2753 | x=GetBufferWidth()/10; | |
2754 | else | |
2755 | x=GetBufferWidth(); | |
2756 | ScrollWindow(x, 0, (const wxRect *) NULL); | |
2757 | } | |
2758 | break; | |
2759 | case WXK_RIGHT: | |
2760 | { | |
2761 | int x; | |
2762 | if (!event.ControlDown()) | |
2763 | x=-GetBufferWidth()/10; | |
2764 | else | |
2765 | x=-GetBufferWidth(); | |
2766 | ScrollWindow(x, 0, (const wxRect *) NULL); | |
2767 | } | |
2768 | break; | |
2769 | default: | |
2770 | // not for us | |
2771 | event.Skip(); | |
2772 | } | |
2773 | } | |
2774 | ||
2775 | ||
8636c073 RR |
2776 | //---------------------------------------------------------------------------- |
2777 | // wxCanvasAdmin | |
2778 | //---------------------------------------------------------------------------- | |
84fba40b RR |
2779 | |
2780 | wxCanvasAdmin::wxCanvasAdmin() | |
2781 | { | |
2782 | ||
2783 | } | |
2784 | ||
2785 | wxCanvasAdmin::~wxCanvasAdmin() | |
2786 | { | |
84fba40b RR |
2787 | } |
2788 | ||
2789 | ||
2790 | void wxCanvasAdmin::Append( wxCanvas* canvas ) | |
2791 | { | |
2792 | m_canvaslist.Append( canvas ); | |
2793 | } | |
2794 | ||
2795 | void wxCanvasAdmin::Remove( wxCanvas* canvas ) | |
2796 | { | |
2797 | m_canvaslist.DeleteObject( canvas ); | |
2798 | } | |
2799 | ||
2800 | void wxCanvasAdmin::Update(wxCanvasObject* obj, double x, double y, double width, double height) | |
2801 | { | |
2802 | wxNode *node = m_canvaslist.First(); | |
2803 | while (node) | |
2804 | { | |
2805 | ||
2806 | wxCanvas *canvas = (wxCanvas*) node->Data(); | |
2807 | ||
2808 | if (m_active == canvas) | |
2809 | { | |
2810 | int xi = canvas->LogicalToDeviceX( x); | |
2811 | int yi = canvas->LogicalToDeviceY( y); | |
2812 | int wi = canvas->LogicalToDeviceXRel( width ); | |
2813 | int hi = canvas->LogicalToDeviceYRel( height); | |
2814 | //update a little more then is strictly needed, | |
2815 | //to get rid of the 1 bit bugs | |
2816 | if (canvas->GetYaxis()) | |
2817 | canvas->Update( xi-2, yi+hi-2, wi+4, -hi+4); | |
2818 | else | |
2819 | canvas->Update( xi-2, yi-2, wi+4, hi+4); | |
2820 | } | |
2821 | else | |
2822 | { wxCanvasObject* topobj=canvas->GetRoot()->Contains(obj); | |
2823 | if (topobj) | |
2824 | { | |
2825 | wxCanvas* tcanvas = m_active; | |
2826 | SetActive(canvas); | |
2827 | ||
2828 | /* | |
2829 | //KKK TODO somehow the next does not work for update i do not know why | |
2830 | canvas->GetRoot()->CalcBoundingBox(); | |
2831 | int xi = topobj->GetX(); | |
2832 | int yi = topobj->GetY(); | |
2833 | int wi = topobj->GetWidth(); | |
2834 | int hi = topobj->GetHeight(); | |
2835 | */ | |
2836 | canvas->Update( 0,0, canvas->GetBufferWidth(),canvas->GetBufferHeight()); | |
2837 | SetActive(tcanvas); | |
2838 | } | |
2839 | } | |
2840 | ||
2841 | node = node->Next(); | |
2842 | } | |
2843 | } | |
2844 | ||
2845 | void wxCanvasAdmin::UpdateNow() | |
2846 | { | |
2847 | wxNode *node = m_canvaslist.First(); | |
2848 | while (node) | |
2849 | { | |
2850 | wxCanvas *canvas = (wxCanvas*) node->Data(); | |
2851 | ||
2852 | canvas->UpdateNow(); | |
2853 | node = node->Next(); | |
2854 | } | |
2855 | } | |
2856 | ||
2857 | // coordinates conversions | |
2858 | // ----------------------- | |
2859 | double wxCanvasAdmin::DeviceToLogicalX(int x) const | |
2860 | { | |
2861 | return m_active->DeviceToLogicalX(x); | |
2862 | } | |
2863 | ||
2864 | double wxCanvasAdmin::DeviceToLogicalY(int y) const | |
2865 | { | |
2866 | return m_active->DeviceToLogicalY(y); | |
2867 | } | |
2868 | ||
2869 | double wxCanvasAdmin::DeviceToLogicalXRel(int x) const | |
2870 | { | |
2871 | return m_active->DeviceToLogicalXRel(x); | |
2872 | } | |
2873 | ||
2874 | double wxCanvasAdmin::DeviceToLogicalYRel(int y) const | |
2875 | { | |
2876 | return m_active->DeviceToLogicalYRel(y); | |
2877 | } | |
2878 | ||
2879 | int wxCanvasAdmin::LogicalToDeviceX(double x) const | |
2880 | { | |
2881 | return m_active->LogicalToDeviceX(x); | |
2882 | } | |
2883 | ||
2884 | int wxCanvasAdmin::LogicalToDeviceY(double y) const | |
2885 | { | |
2886 | return m_active->LogicalToDeviceY(y); | |
2887 | } | |
2888 | ||
2889 | int wxCanvasAdmin::LogicalToDeviceXRel(double x) const | |
2890 | { | |
2891 | return m_active->LogicalToDeviceXRel(x); | |
2892 | } | |
2893 | ||
2894 | int wxCanvasAdmin::LogicalToDeviceYRel(double y) const | |
2895 | { | |
2896 | return m_active->LogicalToDeviceYRel(y); | |
2897 | } | |
2898 | ||
2899 | void wxCanvasAdmin::SetActive(wxCanvas* activate) | |
2900 | { | |
2901 | wxNode *node = m_canvaslist.First(); | |
2902 | while (node) | |
2903 | { | |
2904 | wxCanvas *canvas = (wxCanvas*) node->Data(); | |
2905 | ||
2906 | if (activate == canvas) | |
2907 | { | |
2908 | m_active=canvas; | |
2909 | break; | |
2910 | } | |
2911 | node = node->Next(); | |
2912 | } | |
2913 | } | |
8636c073 RR |
2914 | //-------------------------------------------------------------------- |
2915 | // wxCanvasModule | |
2916 | //-------------------------------------------------------------------- | |
2917 | ||
2918 | class wxCanvasModule : public wxModule | |
2919 | { | |
2920 | public: | |
2921 | virtual bool OnInit(); | |
2922 | virtual void OnExit(); | |
2923 | ||
2924 | private: | |
2925 | DECLARE_DYNAMIC_CLASS(wxCanvasModule) | |
2926 | }; | |
2927 | ||
2928 | IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule, wxModule) | |
2929 | ||
2930 | bool wxCanvasModule::OnInit() | |
2931 | { | |
2932 | #if wxUSE_FREETYPE | |
2933 | int error = FT_Init_FreeType( &g_freetypeLibrary ); | |
2934 | if (error) return FALSE; | |
2935 | #endif | |
2936 | ||
2937 | return TRUE; | |
2938 | } | |
2939 | ||
2940 | void wxCanvasModule::OnExit() | |
2941 | { | |
2942 | #if wxUSE_FREETYPE | |
2943 | FT_Done_FreeType( g_freetypeLibrary ); | |
2944 | #endif | |
2945 | } | |
2946 | ||
2947 | ||
84fba40b RR |
2948 | |
2949 |