]> git.saurik.com Git - wxWidgets.git/blame - utils/ogl/src/ogldiag.cpp
Added wxWindow::Center
[wxWidgets.git] / utils / ogl / src / ogldiag.cpp
CommitLineData
0fc1a713
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".
17#include <wx/wxprec.h>
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include <wx/wx.h>
25#endif
26
27#ifdef PROLOGIO
28#include <wx/wxexpr.h>
29#endif
30
31#if USE_IOSTREAMH
32#include <iostream.h>
33#else
34#include <iostream>
35#endif
36
37#include <fstream.h>
38#include <ctype.h>
39#include <math.h>
40#include <stdlib.h>
41
42#include "basic.h"
43#include "basicp.h"
44#include "canvas.h"
45#include "ogldiag.h"
46#include "lines.h"
47#include "composit.h"
48#include "misc.h"
49
50IMPLEMENT_DYNAMIC_CLASS(wxDiagram, wxObject)
51
52// Object canvas
53wxDiagram::wxDiagram()
54{
55 m_diagramCanvas = NULL;
56 m_quickEditMode = FALSE;
57 m_snapToGrid = TRUE;
58 m_gridSpacing = 5.0;
59 m_shapeList = new wxList;
60 m_mouseTolerance = DEFAULT_MOUSE_TOLERANCE;
61}
62
63wxDiagram::~wxDiagram()
64{
65 if (m_shapeList)
66 delete m_shapeList;
67}
68
69void wxDiagram::SetSnapToGrid(bool snap)
70{
71 m_snapToGrid = snap;
72}
73
74void wxDiagram::SetGridSpacing(float spacing)
75{
76 m_gridSpacing = spacing;
77}
78
79void wxDiagram::Snap(float *x, float *y)
80{
81 if (m_snapToGrid)
82 {
83 *x = m_gridSpacing * ((int)(*x/m_gridSpacing + 0.5));
84 *y = m_gridSpacing * ((int)(*y/m_gridSpacing + 0.5));
85 }
86}
87
88
89void wxDiagram::Redraw(wxDC& dc)
90{
91 if (m_shapeList)
92 {
93 if (GetCanvas())
94 GetCanvas()->SetCursor(wxHOURGLASS_CURSOR);
95 wxNode *current = m_shapeList->First();
96
97 while (current)
98 {
99 wxShape *object = (wxShape *)current->Data();
100 if (!object->GetParent())
101 object->Draw(dc);
102
103 current = current->Next();
104 }
105 if (GetCanvas())
106 GetCanvas()->SetCursor(wxSTANDARD_CURSOR);
107 }
108}
109
110void wxDiagram::Clear(wxDC& dc)
111{
112 dc.Clear();
113}
114
115// Insert object after addAfter, or at end of list.
116void wxDiagram::AddShape(wxShape *object, wxShape *addAfter)
117{
118 wxNode *nodeAfter = NULL;
119 if (addAfter)
120 nodeAfter = m_shapeList->Member(addAfter);
121
122 if (!m_shapeList->Member(object))
123 {
124 if (nodeAfter)
125 {
126 if (nodeAfter->Next())
127 m_shapeList->Insert(nodeAfter->Next(), object);
128 else
129 m_shapeList->Append(object);
130 }
131 else
132 m_shapeList->Append(object);
133 object->SetCanvas(GetCanvas());
134 }
135}
136
137void wxDiagram::InsertShape(wxShape *object)
138{
139 m_shapeList->Insert(object);
140 object->SetCanvas(GetCanvas());
141}
142
143void wxDiagram::RemoveShape(wxShape *object)
144{
145 m_shapeList->DeleteObject(object);
146}
147
148// Should this delete the actual objects too? I think not.
149void wxDiagram::RemoveAllShapes()
150{
151 m_shapeList->Clear();
152}
153
154void wxDiagram::DeleteAllShapes()
155{
156 wxNode *node = m_shapeList->First();
157 while (node)
158 {
159 wxShape *shape = (wxShape *)node->Data();
160 if (!shape->GetParent())
161 {
162 RemoveShape(shape);
163 delete shape;
164 node = m_shapeList->First();
165 }
166 else
167 node = node->Next();
168 }
169}
170
171void wxDiagram::ShowAll(bool show)
172{
173 wxNode *current = m_shapeList->First();
174
175 while (current)
176 {
177 wxShape *object = (wxShape *)current->Data();
178 object->Show(show);
179
180 current = current->Next();
181 }
182}
183
184void wxDiagram::DrawOutline(wxDC& dc, float x1, float y1, float x2, float y2)
185{
186 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
187 dc.SetPen(dottedPen);
188 dc.SetBrush((* wxTRANSPARENT_BRUSH));
189
190 wxPoint points[5];
191
192 points[0].x = x1;
193 points[0].y = y1;
194
195 points[1].x = x2;
196 points[1].y = y1;
197
198 points[2].x = x2;
199 points[2].y = y2;
200
201 points[3].x = x1;
202 points[3].y = y2;
203
204 points[4].x = x1;
205 points[4].y = y1;
206 dc.DrawLines(5, points);
207}
208
209// Make sure all text that should be centred, is centred.
210void wxDiagram::RecentreAll(wxDC& dc)
211{
212 wxNode *object_node = m_shapeList->First();
213 while (object_node)
214 {
215 wxShape *obj = (wxShape *)object_node->Data();
216 obj->Recentre(dc);
217 object_node = object_node->Next();
218 }
219}
220
221// Input/output
222#ifdef PROLOGIO
223bool wxDiagram::SaveFile(const wxString& filename)
224{
225 wxBeginBusyCursor();
226
227 wxExprDatabase *database = new wxExprDatabase;
228
229 // First write the diagram type
230 wxExpr *header = new wxExpr("diagram");
231 OnHeaderSave(*database, *header);
232
233 database->Append(header);
234
235 wxNode *node = m_shapeList->First();
236 while (node)
237 {
238 wxShape *shape = (wxShape *)node->Data();
239
240 if (!shape->IsKindOf(CLASSINFO(wxControlPoint)))
241 {
242 wxExpr *expr = NULL;
243 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
244 expr = new wxExpr("line");
245 else
246 expr = new wxExpr("shape");
247
248 OnShapeSave(*database, *shape, *expr);
249 }
250 node = node->Next();
251 }
252 OnDatabaseSave(*database);
253
254 char tempFile[400];
255 wxGetTempFileName("diag", tempFile);
256 ofstream stream(tempFile);
257 if (stream.bad())
258 {
259 wxEndBusyCursor();
260 delete database;
261 return FALSE;
262 }
263
264 database->Write(stream);
265 stream.close();
266 delete database;
267
268/*
269 // Save backup
270 if (FileExists(filename))
271 {
272 char buf[400];
273#ifdef __X__
274 sprintf(buf, "%s.bak", filename);
275#endif
276#ifdef __WXMSW__
277 sprintf(buf, "_diagram.bak");
278#endif
279 if (FileExists(buf)) wxRemoveFile(buf);
280 if (!wxRenameFile(filename, buf))
281 {
282 wxCopyFile(filename, buf);
283 wxRemoveFile(filename);
284 }
285 }
286*/
287
288 // Copy the temporary file to the correct filename
289 if (!wxRenameFile(tempFile, filename))
290 {
291 wxCopyFile(tempFile, filename);
292 wxRemoveFile(tempFile);
293 }
294
295 wxEndBusyCursor();
296 return TRUE;
297}
298
299bool wxDiagram::LoadFile(const wxString& filename)
300{
301 wxBeginBusyCursor();
302
303 wxExprDatabase database(PrologInteger, "id");
304 if (!database.Read(filename))
305 {
306 wxEndBusyCursor();
307 return FALSE;
308 }
309
310 DeleteAllShapes();
311
312 database.BeginFind();
313 wxExpr *header = database.FindClauseByFunctor("diagram");
314
315 if (header)
316 OnHeaderLoad(database, *header);
317
318 // Scan through all clauses and register the ids
319 wxNode *node = database.First();
320 while (node)
321 {
322 wxExpr *clause = (wxExpr *)node->Data();
323 long id = -1;
324 clause->GetAttributeValue("id", id);
325 RegisterId(id);
326 node = node->Next();
327 }
328
329 ReadNodes(database);
330 ReadContainerGeometry(database);
331 ReadLines(database);
332
333 OnDatabaseLoad(database);
334
335 wxEndBusyCursor();
336
337 return TRUE;
338}
339
340void wxDiagram::ReadNodes(wxExprDatabase& database)
341{
342 // Find and create the node images
343 database.BeginFind();
344 wxExpr *clause = database.FindClauseByFunctor("shape");
345 while (clause)
346 {
347 char *type = NULL;
348 long parentId = -1;
349
350 clause->AssignAttributeValue("type", &type);
351 clause->AssignAttributeValue("parent", &parentId);
352 wxClassInfo *classInfo = wxClassInfo::FindClass(type);
353 if (classInfo)
354 {
355 wxShape *shape = (wxShape *)classInfo->CreateObject();
356 OnShapeLoad(database, *shape, *clause);
357
358 shape->SetCanvas(GetCanvas());
359 shape->Show(TRUE);
360
361 m_shapeList->Append(shape);
362
363 // If child of composite, link up
364 if (parentId > -1)
365 {
366 wxExpr *parentExpr = database.HashFind("shape", parentId);
367 if (parentExpr && parentExpr->GetClientData())
368 {
369 wxShape *parent = (wxShape *)parentExpr->GetClientData();
370 shape->SetParent(parent);
371 parent->GetChildren().Append(shape);
372 }
373 }
374
375 clause->SetClientData(shape);
376 }
377 if (type)
378 delete[] type;
379
380 clause = database.FindClauseByFunctor("shape");
381 }
382 return;
383}
384
385void wxDiagram::ReadLines(wxExprDatabase& database)
386{
387 database.BeginFind();
388 wxExpr *clause = database.FindClauseByFunctor("line");
389 while (clause)
390 {
391 wxString type("");
392 long parentId = -1;
393
394 clause->GetAttributeValue("type", type);
395 clause->GetAttributeValue("parent", parentId);
396 wxClassInfo *classInfo = wxClassInfo::FindClass((char*) (const char*) type);
397 if (classInfo)
398 {
399 wxLineShape *shape = (wxLineShape *)classInfo->CreateObject();
400 shape->Show(TRUE);
401
402 OnShapeLoad(database, *shape, *clause);
403
404 long image_to = -1; long image_from = -1;
405 clause->GetAttributeValue("to", image_to);
406 clause->GetAttributeValue("from", image_from);
407
408 wxExpr *image_to_expr = database.HashFind("shape", image_to);
409
410 if (!image_to_expr)
411 {
412 // Error
413 }
414 wxExpr *image_from_expr = database.HashFind("shape", image_from);
415
416 if (!image_from_expr)
417 {
418 // Error
419 }
420
421 if (image_to_expr && image_from_expr)
422 {
423 wxShape *image_to_object = (wxShape *)image_to_expr->GetClientData();
424 wxShape *image_from_object = (wxShape *)image_from_expr->GetClientData();
425
426 if (image_to_object && image_from_object)
427 {
428 image_from_object->AddLine(shape, image_to_object, shape->GetAttachmentFrom(), shape->GetAttachmentTo());
429 }
430 }
431 clause->SetClientData(shape);
432
433 m_shapeList->Append(shape);
434 }
435
436 clause = database.FindClauseByFunctor("line");
437 }
438}
439
440// Containers have divisions that reference adjoining divisions,
441// so we need a separate pass to link everything up.
442// Also used by Symbol Library.
443void wxDiagram::ReadContainerGeometry(wxExprDatabase& database)
444{
445 database.BeginFind();
446 wxExpr *clause = database.FindClauseByFunctor("shape");
447 while (clause)
448 {
449 wxShape *image = (wxShape *)clause->GetClientData();
450 if (image && image->IsKindOf(CLASSINFO(wxCompositeShape)))
451 {
452 wxCompositeShape *composite = (wxCompositeShape *)image;
453 wxExpr *divisionExpr = NULL;
454
455 // Find the list of divisions in the composite
456 clause->GetAttributeValue("divisions", &divisionExpr);
457 if (divisionExpr)
458 {
459 int i = 0;
460 wxExpr *idExpr = divisionExpr->Nth(i);
461 while (idExpr)
462 {
463 long divisionId = idExpr->IntegerValue();
464 wxExpr *childExpr = database.HashFind("shape", divisionId);
465 if (childExpr && childExpr->GetClientData())
466 {
467 wxDivisionShape *child = (wxDivisionShape *)childExpr->GetClientData();
468 composite->GetDivisions().Append(child);
469
470 // Find the adjoining shapes
471 long leftSideId = -1;
472 long topSideId = -1;
473 long rightSideId = -1;
474 long bottomSideId = -1;
475 childExpr->GetAttributeValue("left_side", leftSideId);
476 childExpr->GetAttributeValue("top_side", topSideId);
477 childExpr->GetAttributeValue("right_side", rightSideId);
478 childExpr->GetAttributeValue("bottom_side", bottomSideId);
479 if (leftSideId > -1)
480 {
481 wxExpr *leftExpr = database.HashFind("shape", leftSideId);
482 if (leftExpr && leftExpr->GetClientData())
483 {
484 wxDivisionShape *leftSide = (wxDivisionShape *)leftExpr->GetClientData();
485 child->SetLeftSide(leftSide);
486 }
487 }
488 if (topSideId > -1)
489 {
490 wxExpr *topExpr = database.HashFind("shape", topSideId);
491 if (topExpr && topExpr->GetClientData())
492 {
493 wxDivisionShape *topSide = (wxDivisionShape *)topExpr->GetClientData();
494 child->SetTopSide(topSide);
495 }
496 }
497 if (rightSideId > -1)
498 {
499 wxExpr *rightExpr = database.HashFind("shape", rightSideId);
500 if (rightExpr && rightExpr->GetClientData())
501 {
502 wxDivisionShape *rightSide = (wxDivisionShape *)rightExpr->GetClientData();
503 child->SetRightSide(rightSide);
504 }
505 }
506 if (bottomSideId > -1)
507 {
508 wxExpr *bottomExpr = database.HashFind("shape", bottomSideId);
509 if (bottomExpr && bottomExpr->GetClientData())
510 {
511 wxDivisionShape *bottomSide = (wxDivisionShape *)bottomExpr->GetClientData();
512 child->SetBottomSide(bottomSide);
513 }
514 }
515 }
516 i ++;
517 idExpr = divisionExpr->Nth(i);
518 }
519 }
520 }
521
522 clause = database.FindClauseByFunctor("shape");
523 }
524}
525
526// Allow for modifying file
527bool wxDiagram::OnDatabaseLoad(wxExprDatabase& db)
528{
529 return TRUE;
530}
531
532bool wxDiagram::OnDatabaseSave(wxExprDatabase& db)
533{
534 return TRUE;
535}
536
537bool wxDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
538{
539 shape.WritePrologAttributes(&expr);
540 db.Append(&expr);
541
542 if (shape.IsKindOf(CLASSINFO(wxCompositeShape)))
543 {
544 wxNode *node = shape.GetChildren().First();
545 while (node)
546 {
547 wxShape *childShape = (wxShape *)node->Data();
548 wxExpr *childExpr = new wxExpr("shape");
549 OnShapeSave(db, *childShape, *childExpr);
550 node = node->Next();
551 }
552 }
553
554 return TRUE;
555}
556
557bool wxDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
558{
559 shape.ReadPrologAttributes(&expr);
560 return TRUE;
561}
562
563bool wxDiagram::OnHeaderSave(wxExprDatabase& db, wxExpr& expr)
564{
565 return TRUE;
566}
567
568bool wxDiagram::OnHeaderLoad(wxExprDatabase& db, wxExpr& expr)
569{
570 return TRUE;
571}
572
573#endif
574
575void wxDiagram::SetCanvas(wxShapeCanvas *can)
576{
577 m_diagramCanvas = can;
578}
579
580