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