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