]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/ogl/ogldiag.cpp
Compilation fix for non-PCH compilers.
[wxWidgets.git] / contrib / src / ogl / ogldiag.cpp
CommitLineData
1fc25a89
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: ogldiag.cpp
3// Purpose: wxDiagram
4// Author: Julian Smart
5// Modified by:
6// Created: 12/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "ogldiag.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
92a19c2e 17#include "wx/wxprec.h"
1fc25a89
JS
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include <wx/wx.h>
25#endif
26
27#include <wx/wxexpr.h>
28
3f1802b5
JS
29#ifdef new
30#undef new
31#endif
32
1fc25a89
JS
33#include <ctype.h>
34#include <math.h>
35#include <stdlib.h>
36
37#include <wx/ogl/basic.h>
38#include <wx/ogl/basicp.h>
39#include <wx/ogl/canvas.h>
40#include <wx/ogl/ogldiag.h>
41#include <wx/ogl/lines.h>
42#include <wx/ogl/composit.h>
43#include <wx/ogl/misc.h>
44
45IMPLEMENT_DYNAMIC_CLASS(wxDiagram, wxObject)
46
47// Object canvas
48wxDiagram::wxDiagram()
49{
50 m_diagramCanvas = NULL;
51 m_quickEditMode = FALSE;
52 m_snapToGrid = TRUE;
53 m_gridSpacing = 5.0;
54 m_shapeList = new wxList;
55 m_mouseTolerance = DEFAULT_MOUSE_TOLERANCE;
56}
57
58wxDiagram::~wxDiagram()
59{
60 if (m_shapeList)
61 delete m_shapeList;
62}
63
64void wxDiagram::SetSnapToGrid(bool snap)
65{
66 m_snapToGrid = snap;
67}
68
69void wxDiagram::SetGridSpacing(double spacing)
70{
71 m_gridSpacing = spacing;
72}
73
74void wxDiagram::Snap(double *x, double *y)
75{
76 if (m_snapToGrid)
77 {
78 *x = m_gridSpacing * ((int)(*x/m_gridSpacing + 0.5));
79 *y = m_gridSpacing * ((int)(*y/m_gridSpacing + 0.5));
80 }
81}
82
83
84void wxDiagram::Redraw(wxDC& dc)
85{
86 if (m_shapeList)
87 {
88 if (GetCanvas())
89 GetCanvas()->SetCursor(* wxHOURGLASS_CURSOR);
b9ac87bc 90 wxNode *current = m_shapeList->GetFirst();
1fc25a89
JS
91
92 while (current)
93 {
b9ac87bc 94 wxShape *object = (wxShape *)current->GetData();
1fc25a89
JS
95 if (!object->GetParent())
96 object->Draw(dc);
97
b9ac87bc 98 current = current->GetNext();
1fc25a89
JS
99 }
100 if (GetCanvas())
101 GetCanvas()->SetCursor(* wxSTANDARD_CURSOR);
102 }
103}
104
105void wxDiagram::Clear(wxDC& dc)
106{
107 dc.Clear();
108}
109
110// Insert object after addAfter, or at end of list.
111void wxDiagram::AddShape(wxShape *object, wxShape *addAfter)
112{
113 wxNode *nodeAfter = NULL;
114 if (addAfter)
115 nodeAfter = m_shapeList->Member(addAfter);
116
117 if (!m_shapeList->Member(object))
118 {
119 if (nodeAfter)
120 {
b9ac87bc
RD
121 if (nodeAfter->GetNext())
122 m_shapeList->Insert(nodeAfter->GetNext(), object);
1fc25a89
JS
123 else
124 m_shapeList->Append(object);
125 }
126 else
127 m_shapeList->Append(object);
128 object->SetCanvas(GetCanvas());
129 }
130}
131
132void wxDiagram::InsertShape(wxShape *object)
133{
134 m_shapeList->Insert(object);
135 object->SetCanvas(GetCanvas());
136}
137
138void wxDiagram::RemoveShape(wxShape *object)
139{
140 m_shapeList->DeleteObject(object);
141}
142
143// Should this delete the actual objects too? I think not.
144void wxDiagram::RemoveAllShapes()
145{
146 m_shapeList->Clear();
147}
148
149void wxDiagram::DeleteAllShapes()
150{
b9ac87bc 151 wxNode *node = m_shapeList->GetFirst();
1fc25a89
JS
152 while (node)
153 {
b9ac87bc 154 wxShape *shape = (wxShape *)node->GetData();
1fc25a89
JS
155 if (!shape->GetParent())
156 {
157 RemoveShape(shape);
158 delete shape;
b9ac87bc 159 node = m_shapeList->GetFirst();
1fc25a89
JS
160 }
161 else
b9ac87bc 162 node = node->GetNext();
1fc25a89
JS
163 }
164}
165
166void wxDiagram::ShowAll(bool show)
167{
b9ac87bc 168 wxNode *current = m_shapeList->GetFirst();
1fc25a89
JS
169
170 while (current)
171 {
b9ac87bc 172 wxShape *object = (wxShape *)current->GetData();
1fc25a89
JS
173 object->Show(show);
174
b9ac87bc 175 current = current->GetNext();
1fc25a89
JS
176 }
177}
178
179void wxDiagram::DrawOutline(wxDC& dc, double x1, double y1, double x2, double y2)
180{
181 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
182 dc.SetPen(dottedPen);
183 dc.SetBrush((* wxTRANSPARENT_BRUSH));
184
185 wxPoint points[5];
186
187 points[0].x = (int) x1;
188 points[0].y = (int) y1;
189
190 points[1].x = (int) x2;
191 points[1].y = (int) y1;
192
193 points[2].x = (int) x2;
194 points[2].y = (int) y2;
195
196 points[3].x = (int) x1;
197 points[3].y = (int) y2;
198
199 points[4].x = (int) x1;
200 points[4].y = (int) y1;
201 dc.DrawLines(5, points);
202}
203
204// Make sure all text that should be centred, is centred.
205void wxDiagram::RecentreAll(wxDC& dc)
206{
b9ac87bc 207 wxNode *object_node = m_shapeList->GetFirst();
1fc25a89
JS
208 while (object_node)
209 {
b9ac87bc 210 wxShape *obj = (wxShape *)object_node->GetData();
1fc25a89 211 obj->Recentre(dc);
b9ac87bc 212 object_node = object_node->GetNext();
1fc25a89
JS
213 }
214}
215
216// Input/output
2b5f62a0 217#if wxUSE_PROLOGIO
1fc25a89
JS
218bool wxDiagram::SaveFile(const wxString& filename)
219{
220 wxBeginBusyCursor();
221
222 wxExprDatabase *database = new wxExprDatabase;
223
224 // First write the diagram type
225 wxExpr *header = new wxExpr("diagram");
226 OnHeaderSave(*database, *header);
227
228 database->Append(header);
229
b9ac87bc 230 wxNode *node = m_shapeList->GetFirst();
1fc25a89
JS
231 while (node)
232 {
b9ac87bc 233 wxShape *shape = (wxShape *)node->GetData();
1fc25a89
JS
234
235 if (!shape->IsKindOf(CLASSINFO(wxControlPoint)))
236 {
237 wxExpr *expr = NULL;
238 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
239 expr = new wxExpr("line");
240 else
241 expr = new wxExpr("shape");
242
243 OnShapeSave(*database, *shape, *expr);
244 }
245 node = node->Next();
246 }
247 OnDatabaseSave(*database);
248
c1fa2fda
RD
249 wxString tempFile;
250 wxGetTempFileName(wxT("diag"), tempFile);
251 FILE* file = fopen(tempFile.mb_str(wxConvFile), "w");
1fc25a89
JS
252 if (! file)
253 {
254 wxEndBusyCursor();
255 delete database;
256 return FALSE;
257 }
258
259 database->Write(file);
260 fclose(file);
261 delete database;
262
263/*
264 // Save backup
265 if (FileExists(filename))
266 {
267 char buf[400];
268#ifdef __X__
269 sprintf(buf, "%s.bak", filename);
270#endif
271#ifdef __WXMSW__
272 sprintf(buf, "_diagram.bak");
273#endif
274 if (FileExists(buf)) wxRemoveFile(buf);
275 if (!wxRenameFile(filename, buf))
276 {
277 wxCopyFile(filename, buf);
278 wxRemoveFile(filename);
279 }
280 }
281*/
282
283 // Copy the temporary file to the correct filename
284 if (!wxRenameFile(tempFile, filename))
285 {
286 wxCopyFile(tempFile, filename);
287 wxRemoveFile(tempFile);
288 }
289
290 wxEndBusyCursor();
291 return TRUE;
292}
293
294bool wxDiagram::LoadFile(const wxString& filename)
295{
296 wxBeginBusyCursor();
297
298 wxExprDatabase database(wxExprInteger, "id");
299 if (!database.Read(filename))
300 {
301 wxEndBusyCursor();
302 return FALSE;
303 }
304
305 DeleteAllShapes();
306
307 database.BeginFind();
308 wxExpr *header = database.FindClauseByFunctor("diagram");
309
310 if (header)
311 OnHeaderLoad(database, *header);
312
313 // Scan through all clauses and register the ids
314 wxNode *node = database.First();
315 while (node)
316 {
b9ac87bc 317 wxExpr *clause = (wxExpr *)node->GetData();
1fc25a89
JS
318 long id = -1;
319 clause->GetAttributeValue("id", id);
320 wxRegisterId(id);
321 node = node->Next();
322 }
323
324 ReadNodes(database);
325 ReadContainerGeometry(database);
326 ReadLines(database);
327
328 OnDatabaseLoad(database);
329
330 wxEndBusyCursor();
331
332 return TRUE;
333}
334
335void wxDiagram::ReadNodes(wxExprDatabase& database)
336{
337 // Find and create the node images
338 database.BeginFind();
339 wxExpr *clause = database.FindClauseByFunctor("shape");
340 while (clause)
341 {
c1fa2fda 342 wxChar *type = NULL;
1fc25a89
JS
343 long parentId = -1;
344
c1fa2fda
RD
345 clause->AssignAttributeValue(wxT("type"), &type);
346 clause->AssignAttributeValue(wxT("parent"), &parentId);
1fc25a89
JS
347 wxClassInfo *classInfo = wxClassInfo::FindClass(type);
348 if (classInfo)
349 {
350 wxShape *shape = (wxShape *)classInfo->CreateObject();
351 OnShapeLoad(database, *shape, *clause);
352
353 shape->SetCanvas(GetCanvas());
354 shape->Show(TRUE);
355
356 m_shapeList->Append(shape);
357
358 // If child of composite, link up
359 if (parentId > -1)
360 {
361 wxExpr *parentExpr = database.HashFind("shape", parentId);
362 if (parentExpr && parentExpr->GetClientData())
363 {
364 wxShape *parent = (wxShape *)parentExpr->GetClientData();
365 shape->SetParent(parent);
366 parent->GetChildren().Append(shape);
367 }
368 }
369
370 clause->SetClientData(shape);
371 }
372 if (type)
373 delete[] type;
374
375 clause = database.FindClauseByFunctor("shape");
376 }
377 return;
378}
379
380void wxDiagram::ReadLines(wxExprDatabase& database)
381{
382 database.BeginFind();
383 wxExpr *clause = database.FindClauseByFunctor("line");
384 while (clause)
385 {
c1fa2fda 386 wxString type;
1fc25a89
JS
387 long parentId = -1;
388
389 clause->GetAttributeValue("type", type);
390 clause->GetAttributeValue("parent", parentId);
c1fa2fda 391 wxClassInfo *classInfo = wxClassInfo::FindClass(type);
1fc25a89
JS
392 if (classInfo)
393 {
394 wxLineShape *shape = (wxLineShape *)classInfo->CreateObject();
395 shape->Show(TRUE);
396
397 OnShapeLoad(database, *shape, *clause);
398 shape->SetCanvas(GetCanvas());
399
400 long image_to = -1; long image_from = -1;
401 clause->GetAttributeValue("to", image_to);
402 clause->GetAttributeValue("from", image_from);
403
404 wxExpr *image_to_expr = database.HashFind("shape", image_to);
405
406 if (!image_to_expr)
407 {
408 // Error
409 }
410 wxExpr *image_from_expr = database.HashFind("shape", image_from);
411
412 if (!image_from_expr)
413 {
414 // Error
415 }
416
417 if (image_to_expr && image_from_expr)
418 {
419 wxShape *image_to_object = (wxShape *)image_to_expr->GetClientData();
420 wxShape *image_from_object = (wxShape *)image_from_expr->GetClientData();
421
422 if (image_to_object && image_from_object)
423 {
424 image_from_object->AddLine(shape, image_to_object, shape->GetAttachmentFrom(), shape->GetAttachmentTo());
425 }
426 }
427 clause->SetClientData(shape);
428
429 m_shapeList->Append(shape);
430 }
431
432 clause = database.FindClauseByFunctor("line");
433 }
434}
435
436// Containers have divisions that reference adjoining divisions,
437// so we need a separate pass to link everything up.
438// Also used by Symbol Library.
439void wxDiagram::ReadContainerGeometry(wxExprDatabase& database)
440{
441 database.BeginFind();
442 wxExpr *clause = database.FindClauseByFunctor("shape");
443 while (clause)
444 {
445 wxShape *image = (wxShape *)clause->GetClientData();
446 if (image && image->IsKindOf(CLASSINFO(wxCompositeShape)))
447 {
448 wxCompositeShape *composite = (wxCompositeShape *)image;
449 wxExpr *divisionExpr = NULL;
450
451 // Find the list of divisions in the composite
452 clause->GetAttributeValue("divisions", &divisionExpr);
453 if (divisionExpr)
454 {
455 int i = 0;
b9ac87bc 456 wxExpr *idExpr = divisionExpr->Item(i);
1fc25a89
JS
457 while (idExpr)
458 {
459 long divisionId = idExpr->IntegerValue();
460 wxExpr *childExpr = database.HashFind("shape", divisionId);
461 if (childExpr && childExpr->GetClientData())
462 {
463 wxDivisionShape *child = (wxDivisionShape *)childExpr->GetClientData();
464 composite->GetDivisions().Append(child);
465
466 // Find the adjoining shapes
467 long leftSideId = -1;
468 long topSideId = -1;
469 long rightSideId = -1;
470 long bottomSideId = -1;
471 childExpr->GetAttributeValue("left_side", leftSideId);
472 childExpr->GetAttributeValue("top_side", topSideId);
473 childExpr->GetAttributeValue("right_side", rightSideId);
474 childExpr->GetAttributeValue("bottom_side", bottomSideId);
475 if (leftSideId > -1)
476 {
477 wxExpr *leftExpr = database.HashFind("shape", leftSideId);
478 if (leftExpr && leftExpr->GetClientData())
479 {
480 wxDivisionShape *leftSide = (wxDivisionShape *)leftExpr->GetClientData();
481 child->SetLeftSide(leftSide);
482 }
483 }
484 if (topSideId > -1)
485 {
486 wxExpr *topExpr = database.HashFind("shape", topSideId);
487 if (topExpr && topExpr->GetClientData())
488 {
489 wxDivisionShape *topSide = (wxDivisionShape *)topExpr->GetClientData();
490 child->SetTopSide(topSide);
491 }
492 }
493 if (rightSideId > -1)
494 {
495 wxExpr *rightExpr = database.HashFind("shape", rightSideId);
496 if (rightExpr && rightExpr->GetClientData())
497 {
498 wxDivisionShape *rightSide = (wxDivisionShape *)rightExpr->GetClientData();
499 child->SetRightSide(rightSide);
500 }
501 }
502 if (bottomSideId > -1)
503 {
504 wxExpr *bottomExpr = database.HashFind("shape", bottomSideId);
505 if (bottomExpr && bottomExpr->GetClientData())
506 {
507 wxDivisionShape *bottomSide = (wxDivisionShape *)bottomExpr->GetClientData();
508 child->SetBottomSide(bottomSide);
509 }
510 }
511 }
512 i ++;
b9ac87bc 513 idExpr = divisionExpr->Item(i);
1fc25a89
JS
514 }
515 }
516 }
517
518 clause = database.FindClauseByFunctor("shape");
519 }
520}
521
522// Allow for modifying file
523bool wxDiagram::OnDatabaseLoad(wxExprDatabase& db)
524{
525 return TRUE;
526}
527
528bool wxDiagram::OnDatabaseSave(wxExprDatabase& db)
529{
530 return TRUE;
531}
532
533bool wxDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
534{
535 shape.WriteAttributes(&expr);
536 db.Append(&expr);
537
538 if (shape.IsKindOf(CLASSINFO(wxCompositeShape)))
539 {
540 wxNode *node = shape.GetChildren().First();
541 while (node)
542 {
b9ac87bc 543 wxShape *childShape = (wxShape *)node->GetData();
1fc25a89
JS
544 wxExpr *childExpr = new wxExpr("shape");
545 OnShapeSave(db, *childShape, *childExpr);
546 node = node->Next();
547 }
548 }
549
550 return TRUE;
551}
552
553bool wxDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
554{
555 shape.ReadAttributes(&expr);
556 return TRUE;
557}
558
559bool wxDiagram::OnHeaderSave(wxExprDatabase& db, wxExpr& expr)
560{
561 return TRUE;
562}
563
564bool wxDiagram::OnHeaderLoad(wxExprDatabase& db, wxExpr& expr)
565{
566 return TRUE;
567}
568
569#endif
570
571void wxDiagram::SetCanvas(wxShapeCanvas *can)
572{
573 m_diagramCanvas = can;
574}
575
576// Find a shape by its id
577wxShape* wxDiagram::FindShape(long id) const
578{
b9ac87bc 579 wxNode* node = GetShapeList()->GetFirst();
1fc25a89
JS
580 while (node)
581 {
b9ac87bc 582 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
583 if (shape->GetId() == id)
584 return shape;
b9ac87bc 585 node = node->GetNext();
1fc25a89
JS
586 }
587 return NULL;
588}
589
590
591//// Crossings classes
592
593wxLineCrossings::wxLineCrossings()
594{
595}
596
597wxLineCrossings::~wxLineCrossings()
598{
599 ClearCrossings();
600}
601
602void wxLineCrossings::FindCrossings(wxDiagram& diagram)
603{
604 ClearCrossings();
b9ac87bc 605 wxNode* node1 = diagram.GetShapeList()->GetFirst();
1fc25a89
JS
606 while (node1)
607 {
b9ac87bc 608 wxShape* shape1 = (wxShape*) node1->GetData();
1fc25a89
JS
609 if (shape1->IsKindOf(CLASSINFO(wxLineShape)))
610 {
611 wxLineShape* lineShape1 = (wxLineShape*) shape1;
612 // Iterate through the segments
613 wxList* pts1 = lineShape1->GetLineControlPoints();
614 int i;
b9ac87bc 615 for (i = 0; i < (pts1->GetCount() - 1); i++)
1fc25a89 616 {
b9ac87bc
RD
617 wxRealPoint* pt1_a = (wxRealPoint*) (pts1->Item(i)->GetData());
618 wxRealPoint* pt1_b = (wxRealPoint*) (pts1->Item(i+1)->GetData());
1fc25a89
JS
619
620 // Now we iterate through the segments again
621
b9ac87bc 622 wxNode* node2 = diagram.GetShapeList()->GetFirst();
1fc25a89
JS
623 while (node2)
624 {
b9ac87bc 625 wxShape* shape2 = (wxShape*) node2->GetData();
1fc25a89
JS
626
627 // Assume that the same line doesn't cross itself
628 if (shape2->IsKindOf(CLASSINFO(wxLineShape)) && (shape1 != shape2))
629 {
630 wxLineShape* lineShape2 = (wxLineShape*) shape2;
631 // Iterate through the segments
632 wxList* pts2 = lineShape2->GetLineControlPoints();
633 int j;
b9ac87bc 634 for (j = 0; j < (pts2->GetCount() - 1); j++)
1fc25a89 635 {
b9ac87bc
RD
636 wxRealPoint* pt2_a = (wxRealPoint*) (pts2->Item(j)->GetData());
637 wxRealPoint* pt2_b = (wxRealPoint*) (pts2->Item(j+1)->GetData());
1fc25a89
JS
638
639 // Now let's see if these two segments cross.
640 double ratio1, ratio2;
641 oglCheckLineIntersection(pt1_a->x, pt1_a->y, pt1_b->x, pt1_b->y,
642 pt2_a->x, pt2_a->y, pt2_b->x, pt2_b->y,
643 & ratio1, & ratio2);
644
645 if ((ratio1 < 1.0) && (ratio1 > -1.0))
646 {
647 // Intersection!
648 wxLineCrossing* crossing = new wxLineCrossing;
649 crossing->m_intersect.x = (pt1_a->x + (pt1_b->x - pt1_a->x)*ratio1);
650 crossing->m_intersect.y = (pt1_a->y + (pt1_b->y - pt1_a->y)*ratio1);
651
652 crossing->m_pt1 = * pt1_a;
653 crossing->m_pt2 = * pt1_b;
654 crossing->m_pt3 = * pt2_a;
655 crossing->m_pt4 = * pt2_b;
656
657 crossing->m_lineShape1 = lineShape1;
658 crossing->m_lineShape2 = lineShape2;
659
660 m_crossings.Append(crossing);
661 }
662 }
663 }
b9ac87bc 664 node2 = node2->GetNext();
1fc25a89
JS
665 }
666 }
667 }
668
b9ac87bc 669 node1 = node1->GetNext();
1fc25a89
JS
670 }
671}
672
673void wxLineCrossings::DrawCrossings(wxDiagram& diagram, wxDC& dc)
674{
675 dc.SetBrush(*wxTRANSPARENT_BRUSH);
676
677 long arcWidth = 8;
678
b9ac87bc 679 wxNode* node = m_crossings.GetFirst();
1fc25a89
JS
680 while (node)
681 {
b9ac87bc 682 wxLineCrossing* crossing = (wxLineCrossing*) node->GetData();
1fc25a89
JS
683// dc.DrawEllipse((long) (crossing->m_intersect.x - (arcWidth/2.0) + 0.5), (long) (crossing->m_intersect.y - (arcWidth/2.0) + 0.5),
684// arcWidth, arcWidth);
685
686
687 // Let's do some geometry to find the points on either end of the arc.
688/*
689
690(x1, y1)
691 |\
692 | \
693 | \
694 | \
695 | \
696 | |\ c c1
697 | a | \
698 | \
699 | - x <-- centre of arc
700 a1 | b |\
701 | | \ c2
702 | a2 | \
703 | - \
704 | b2 \
705 | \
706 |_______________\ (x2, y2)
707 b1
708
709*/
710
711 double a1 = wxMax(crossing->m_pt1.y, crossing->m_pt2.y) - wxMin(crossing->m_pt1.y, crossing->m_pt2.y) ;
712 double b1 = wxMax(crossing->m_pt1.x, crossing->m_pt2.x) - wxMin(crossing->m_pt1.x, crossing->m_pt2.x) ;
713 double c1 = sqrt( (a1*a1) + (b1*b1) );
714
715 double c = arcWidth / 2.0;
716 double a = c * a1/c1 ;
717 double b = c * b1/c1 ;
718
719 // I'm not sure this is right, since we don't know which direction we should be going in - need
720 // to know which way the line slopes and choose the sign appropriately.
721 double arcX1 = crossing->m_intersect.x - b;
722 double arcY1 = crossing->m_intersect.y - a;
723
724 double arcX2 = crossing->m_intersect.x + b;
725 double arcY2 = crossing->m_intersect.y + a;
726
727 dc.SetPen(*wxBLACK_PEN);
728 dc.DrawArc( (long) arcX1, (long) arcY1, (long) arcX2, (long) arcY2,
729 (long) crossing->m_intersect.x, (long) crossing->m_intersect.y);
730
731 dc.SetPen(*wxWHITE_PEN);
732 dc.DrawLine( (long) arcX1, (long) arcY1, (long) arcX2, (long) arcY2 );
733
b9ac87bc 734 node = node->GetNext();
1fc25a89
JS
735 }
736}
737
738void wxLineCrossings::ClearCrossings()
739{
b9ac87bc 740 wxNode* node = m_crossings.GetFirst();
1fc25a89
JS
741 while (node)
742 {
b9ac87bc 743 wxLineCrossing* crossing = (wxLineCrossing*) node->GetData();
1fc25a89 744 delete crossing;
b9ac87bc 745 node = node->GetNext();
1fc25a89
JS
746 }
747 m_crossings.Clear();
748}
749