]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/ogl/constrnt.cpp
and restored error checking too: this completes sequence of 3 check ins making wx...
[wxWidgets.git] / contrib / src / ogl / constrnt.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: constrnt.cpp
3 // Purpose: OGL Constraint classes
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 "constrnt.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 #if wxUSE_PROLOGIO
28 #include <wx/deprecated/wxexpr.h>
29 #endif
30
31 #include "wx/ogl/ogl.h"
32
33
34 wxList *wxOGLConstraintTypes = NULL;
35
36 /*
37 * Constraint type
38 *
39 */
40
41 IMPLEMENT_DYNAMIC_CLASS(wxOGLConstraintType, wxObject)
42
43 wxOGLConstraintType::wxOGLConstraintType(int theType, const wxString& theName, const wxString& thePhrase)
44 {
45 m_type = theType;
46 m_name = theName;
47 m_phrase = thePhrase;
48 }
49
50 wxOGLConstraintType::~wxOGLConstraintType()
51 {
52 }
53
54 void OGLInitializeConstraintTypes()
55 {
56 if (!wxOGLConstraintTypes)
57 return;
58
59 wxOGLConstraintTypes = new wxList(wxKEY_INTEGER);
60
61 wxOGLConstraintTypes->Append(gyCONSTRAINT_CENTRED_VERTICALLY,
62 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_VERTICALLY, wxT("Centre vertically"), wxT("centred vertically w.r.t.")));
63
64 wxOGLConstraintTypes->Append(gyCONSTRAINT_CENTRED_HORIZONTALLY,
65 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_HORIZONTALLY, wxT("Centre horizontally"), wxT("centred horizontally w.r.t.")));
66
67 wxOGLConstraintTypes->Append(gyCONSTRAINT_CENTRED_BOTH,
68 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_BOTH, wxT("Centre"), wxT("centred w.r.t.")));
69
70 wxOGLConstraintTypes->Append(gyCONSTRAINT_LEFT_OF,
71 new wxOGLConstraintType(gyCONSTRAINT_LEFT_OF, wxT("Left of"), wxT("left of")));
72
73 wxOGLConstraintTypes->Append(gyCONSTRAINT_RIGHT_OF,
74 new wxOGLConstraintType(gyCONSTRAINT_RIGHT_OF, wxT("Right of"), wxT("right of")));
75
76 wxOGLConstraintTypes->Append(gyCONSTRAINT_ABOVE,
77 new wxOGLConstraintType(gyCONSTRAINT_ABOVE, wxT("Above"), wxT("above")));
78
79 wxOGLConstraintTypes->Append(gyCONSTRAINT_BELOW,
80 new wxOGLConstraintType(gyCONSTRAINT_BELOW, wxT("Below"), wxT("below")));
81
82 // Alignment
83 wxOGLConstraintTypes->Append(gyCONSTRAINT_ALIGNED_TOP,
84 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_TOP, wxT("Top-aligned"), wxT("aligned to the top of")));
85
86 wxOGLConstraintTypes->Append(gyCONSTRAINT_ALIGNED_BOTTOM,
87 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_BOTTOM, wxT("Bottom-aligned"), wxT("aligned to the bottom of")));
88
89 wxOGLConstraintTypes->Append(gyCONSTRAINT_ALIGNED_LEFT,
90 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_LEFT, wxT("Left-aligned"), wxT("aligned to the left of")));
91
92 wxOGLConstraintTypes->Append(gyCONSTRAINT_ALIGNED_RIGHT,
93 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_RIGHT, wxT("Right-aligned"), wxT("aligned to the right of")));
94
95 // Mid-alignment
96 wxOGLConstraintTypes->Append(gyCONSTRAINT_MIDALIGNED_TOP,
97 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_TOP, wxT("Top-midaligned"), wxT("centred on the top of")));
98
99 wxOGLConstraintTypes->Append(gyCONSTRAINT_MIDALIGNED_BOTTOM,
100 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_BOTTOM, wxT("Bottom-midaligned"), wxT("centred on the bottom of")));
101
102 wxOGLConstraintTypes->Append(gyCONSTRAINT_MIDALIGNED_LEFT,
103 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_LEFT, wxT("Left-midaligned"), wxT("centred on the left of")));
104
105 wxOGLConstraintTypes->Append(gyCONSTRAINT_MIDALIGNED_RIGHT,
106 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_RIGHT, wxT("Right-midaligned"), wxT("centred on the right of")));
107 }
108
109 void OGLCleanUpConstraintTypes()
110 {
111 if (!wxOGLConstraintTypes)
112 return;
113
114 wxNode* node = wxOGLConstraintTypes->GetFirst();
115 while (node)
116 {
117 wxOGLConstraintType* ct = (wxOGLConstraintType*) node->GetData();
118 delete ct;
119 node = node->GetNext();
120 }
121 delete wxOGLConstraintTypes;
122 wxOGLConstraintTypes = NULL;
123 }
124
125 /*
126 * Constraint Stuff
127 *
128 */
129
130 IMPLEMENT_DYNAMIC_CLASS(wxOGLConstraint, wxObject)
131
132 wxOGLConstraint::wxOGLConstraint(int type, wxShape *constraining, wxList& constrained)
133 {
134 m_xSpacing = 0.0;
135 m_ySpacing = 0.0;
136
137 m_constraintType = type;
138 m_constrainingObject = constraining;
139
140 m_constraintId = 0;
141 m_constraintName = wxT("noname");
142
143 wxNode *node = constrained.GetFirst();
144 while (node)
145 {
146 m_constrainedObjects.Append(node->GetData());
147 node = node->GetNext();
148 }
149 }
150
151 wxOGLConstraint::~wxOGLConstraint()
152 {
153 }
154
155 bool wxOGLConstraint::Equals(double a, double b)
156 {
157 double marg = 0.5;
158
159 bool eq = ((b <= a + marg) && (b >= a - marg));
160 return eq;
161 }
162
163 // Return true if anything changed
164 bool wxOGLConstraint::Evaluate()
165 {
166 double maxWidth, maxHeight, minWidth, minHeight, x, y;
167 m_constrainingObject->GetBoundingBoxMax(&maxWidth, &maxHeight);
168 m_constrainingObject->GetBoundingBoxMin(&minWidth, &minHeight);
169 x = m_constrainingObject->GetX();
170 y = m_constrainingObject->GetY();
171
172 wxClientDC dc(m_constrainingObject->GetCanvas());
173 m_constrainingObject->GetCanvas()->PrepareDC(dc);
174
175 switch (m_constraintType)
176 {
177 case gyCONSTRAINT_CENTRED_VERTICALLY:
178 {
179 int n = m_constrainedObjects.GetCount();
180 double totalObjectHeight = 0.0;
181 wxNode *node = m_constrainedObjects.GetFirst();
182 while (node)
183 {
184 wxShape *constrainedObject = (wxShape *)node->GetData();
185
186 double width2, height2;
187 constrainedObject->GetBoundingBoxMax(&width2, &height2);
188 totalObjectHeight += height2;
189 node = node->GetNext();
190 }
191 double startY;
192 double spacingY;
193 // Check if within the constraining object...
194 if ((totalObjectHeight + (n + 1)*m_ySpacing) <= minHeight)
195 {
196 spacingY = (double)((minHeight - totalObjectHeight)/(n + 1));
197 startY = (double)(y - (minHeight/2.0));
198 }
199 // Otherwise, use default spacing
200 else
201 {
202 spacingY = m_ySpacing;
203 startY = (double)(y - ((totalObjectHeight + (n+1)*spacingY)/2.0));
204 }
205
206 // Now position the objects
207 bool changed = false;
208 node = m_constrainedObjects.GetFirst();
209 while (node)
210 {
211 wxShape *constrainedObject = (wxShape *)node->GetData();
212 double width2, height2;
213 constrainedObject->GetBoundingBoxMax(&width2, &height2);
214 startY += (double)(spacingY + (height2/2.0));
215 if (!Equals(startY, constrainedObject->GetY()))
216 {
217 constrainedObject->Move(dc, constrainedObject->GetX(), startY, false);
218 changed = true;
219 }
220 startY += (double)(height2/2.0);
221 node = node->GetNext();
222 }
223 return changed;
224 }
225 case gyCONSTRAINT_CENTRED_HORIZONTALLY:
226 {
227 int n = m_constrainedObjects.GetCount();
228 double totalObjectWidth = 0.0;
229 wxNode *node = m_constrainedObjects.GetFirst();
230 while (node)
231 {
232 wxShape *constrainedObject = (wxShape *)node->GetData();
233
234 double width2, height2;
235 constrainedObject->GetBoundingBoxMax(&width2, &height2);
236 totalObjectWidth += width2;
237 node = node->GetNext();
238 }
239 double startX;
240 double spacingX;
241 // Check if within the constraining object...
242 if ((totalObjectWidth + (n + 1)*m_xSpacing) <= minWidth)
243 {
244 spacingX = (double)((minWidth - totalObjectWidth)/(n + 1));
245 startX = (double)(x - (minWidth/2.0));
246 }
247 // Otherwise, use default spacing
248 else
249 {
250 spacingX = m_xSpacing;
251 startX = (double)(x - ((totalObjectWidth + (n+1)*spacingX)/2.0));
252 }
253
254 // Now position the objects
255 bool changed = false;
256 node = m_constrainedObjects.GetFirst();
257 while (node)
258 {
259 wxShape *constrainedObject = (wxShape *)node->GetData();
260 double width2, height2;
261 constrainedObject->GetBoundingBoxMax(&width2, &height2);
262 startX += (double)(spacingX + (width2/2.0));
263 if (!Equals(startX, constrainedObject->GetX()))
264 {
265 constrainedObject->Move(dc, startX, constrainedObject->GetY(), false);
266 changed = true;
267 }
268 startX += (double)(width2/2.0);
269 node = node->GetNext();
270 }
271 return changed;
272 }
273 case gyCONSTRAINT_CENTRED_BOTH:
274 {
275 int n = m_constrainedObjects.GetCount();
276 double totalObjectWidth = 0.0;
277 double totalObjectHeight = 0.0;
278 wxNode *node = m_constrainedObjects.GetFirst();
279 while (node)
280 {
281 wxShape *constrainedObject = (wxShape *)node->GetData();
282
283 double width2, height2;
284 constrainedObject->GetBoundingBoxMax(&width2, &height2);
285 totalObjectWidth += width2;
286 totalObjectHeight += height2;
287 node = node->GetNext();
288 }
289 double startX;
290 double spacingX;
291 double startY;
292 double spacingY;
293
294 // Check if within the constraining object...
295 if ((totalObjectWidth + (n + 1)*m_xSpacing) <= minWidth)
296 {
297 spacingX = (double)((minWidth - totalObjectWidth)/(n + 1));
298 startX = (double)(x - (minWidth/2.0));
299 }
300 // Otherwise, use default spacing
301 else
302 {
303 spacingX = m_xSpacing;
304 startX = (double)(x - ((totalObjectWidth + (n+1)*spacingX)/2.0));
305 }
306
307 // Check if within the constraining object...
308 if ((totalObjectHeight + (n + 1)*m_ySpacing) <= minHeight)
309 {
310 spacingY = (double)((minHeight - totalObjectHeight)/(n + 1));
311 startY = (double)(y - (minHeight/2.0));
312 }
313 // Otherwise, use default spacing
314 else
315 {
316 spacingY = m_ySpacing;
317 startY = (double)(y - ((totalObjectHeight + (n+1)*spacingY)/2.0));
318 }
319
320 // Now position the objects
321 bool changed = false;
322 node = m_constrainedObjects.GetFirst();
323 while (node)
324 {
325 wxShape *constrainedObject = (wxShape *)node->GetData();
326 double width2, height2;
327 constrainedObject->GetBoundingBoxMax(&width2, &height2);
328 startX += (double)(spacingX + (width2/2.0));
329 startY += (double)(spacingY + (height2/2.0));
330
331 if ((!Equals(startX, constrainedObject->GetX())) || (!Equals(startY, constrainedObject->GetY())))
332 {
333 constrainedObject->Move(dc, startX, startY, false);
334 changed = true;
335 }
336
337 startX += (double)(width2/2.0);
338 startY += (double)(height2/2.0);
339
340 node = node->GetNext();
341 }
342 return changed;
343 }
344 case gyCONSTRAINT_LEFT_OF:
345 {
346 bool changed = false;
347
348 wxNode *node = m_constrainedObjects.GetFirst();
349 while (node)
350 {
351 wxShape *constrainedObject = (wxShape *)node->GetData();
352
353 double width2, height2;
354 constrainedObject->GetBoundingBoxMax(&width2, &height2);
355
356 double x3 = (double)(x - (minWidth/2.0) - (width2/2.0) - m_xSpacing);
357 if (!Equals(x3, constrainedObject->GetX()))
358 {
359 changed = true;
360 constrainedObject->Move(dc, x3, constrainedObject->GetY(), false);
361 }
362
363 node = node->GetNext();
364 }
365 return changed;
366 }
367 case gyCONSTRAINT_RIGHT_OF:
368 {
369 bool changed = false;
370
371 wxNode *node = m_constrainedObjects.GetFirst();
372 while (node)
373 {
374 wxShape *constrainedObject = (wxShape *)node->GetData();
375
376 double width2, height2;
377 constrainedObject->GetBoundingBoxMax(&width2, &height2);
378
379 double x3 = (double)(x + (minWidth/2.0) + (width2/2.0) + m_xSpacing);
380 if (!Equals(x3, constrainedObject->GetX()))
381 {
382 changed = true;
383 constrainedObject->Move(dc, x3, constrainedObject->GetY(), false);
384 }
385
386 node = node->GetNext();
387 }
388 return changed;
389 }
390 case gyCONSTRAINT_ABOVE:
391 {
392 bool changed = false;
393
394 wxNode *node = m_constrainedObjects.GetFirst();
395 while (node)
396 {
397 wxShape *constrainedObject = (wxShape *)node->GetData();
398
399 double width2, height2;
400 constrainedObject->GetBoundingBoxMax(&width2, &height2);
401
402 double y3 = (double)(y - (minHeight/2.0) - (height2/2.0) - m_ySpacing);
403 if (!Equals(y3, constrainedObject->GetY()))
404 {
405 changed = true;
406 constrainedObject->Move(dc, constrainedObject->GetX(), y3, false);
407 }
408
409 node = node->GetNext();
410 }
411 return changed;
412 }
413 case gyCONSTRAINT_BELOW:
414 {
415 bool changed = false;
416
417 wxNode *node = m_constrainedObjects.GetFirst();
418 while (node)
419 {
420 wxShape *constrainedObject = (wxShape *)node->GetData();
421
422 double width2, height2;
423 constrainedObject->GetBoundingBoxMax(&width2, &height2);
424
425 double y3 = (double)(y + (minHeight/2.0) + (height2/2.0) + m_ySpacing);
426 if (!Equals(y3, constrainedObject->GetY()))
427 {
428 changed = true;
429 constrainedObject->Move(dc, constrainedObject->GetX(), y3, false);
430 }
431
432 node = node->GetNext();
433 }
434 return changed;
435 }
436 case gyCONSTRAINT_ALIGNED_LEFT:
437 {
438 bool changed = false;
439
440 wxNode *node = m_constrainedObjects.GetFirst();
441 while (node)
442 {
443 wxShape *constrainedObject = (wxShape *)node->GetData();
444
445 double width2, height2;
446 constrainedObject->GetBoundingBoxMax(&width2, &height2);
447
448 double x3 = (double)(x - (minWidth/2.0) + (width2/2.0) + m_xSpacing);
449 if (!Equals(x3, constrainedObject->GetX()))
450 {
451 changed = true;
452 constrainedObject->Move(dc, x3, constrainedObject->GetY(), false);
453 }
454
455 node = node->GetNext();
456 }
457 return changed;
458 }
459 case gyCONSTRAINT_ALIGNED_RIGHT:
460 {
461 bool changed = false;
462
463 wxNode *node = m_constrainedObjects.GetFirst();
464 while (node)
465 {
466 wxShape *constrainedObject = (wxShape *)node->GetData();
467
468 double width2, height2;
469 constrainedObject->GetBoundingBoxMax(&width2, &height2);
470
471 double x3 = (double)(x + (minWidth/2.0) - (width2/2.0) - m_xSpacing);
472 if (!Equals(x3, constrainedObject->GetX()))
473 {
474 changed = true;
475 constrainedObject->Move(dc, x3, constrainedObject->GetY(), false);
476 }
477
478 node = node->GetNext();
479 }
480 return changed;
481 #if 0
482 // two returned values ?
483 return false;
484 #endif
485 }
486 case gyCONSTRAINT_ALIGNED_TOP:
487 {
488 bool changed = false;
489
490 wxNode *node = m_constrainedObjects.GetFirst();
491 while (node)
492 {
493 wxShape *constrainedObject = (wxShape *)node->GetData();
494
495 double width2, height2;
496 constrainedObject->GetBoundingBoxMax(&width2, &height2);
497
498 double y3 = (double)(y - (minHeight/2.0) + (height2/2.0) + m_ySpacing);
499 if (!Equals(y3, constrainedObject->GetY()))
500 {
501 changed = true;
502 constrainedObject->Move(dc, constrainedObject->GetX(), y3, false);
503 }
504
505 node = node->GetNext();
506 }
507 return changed;
508 }
509 case gyCONSTRAINT_ALIGNED_BOTTOM:
510 {
511 bool changed = false;
512
513 wxNode *node = m_constrainedObjects.GetFirst();
514 while (node)
515 {
516 wxShape *constrainedObject = (wxShape *)node->GetData();
517
518 double width2, height2;
519 constrainedObject->GetBoundingBoxMax(&width2, &height2);
520
521 double y3 = (double)(y + (minHeight/2.0) - (height2/2.0) - m_ySpacing);
522 if (!Equals(y3, constrainedObject->GetY()))
523 {
524 changed = true;
525 constrainedObject->Move(dc, constrainedObject->GetX(), y3, false);
526 }
527
528 node = node->GetNext();
529 }
530 return changed;
531 }
532 case gyCONSTRAINT_MIDALIGNED_LEFT:
533 {
534 bool changed = false;
535
536 wxNode *node = m_constrainedObjects.GetFirst();
537 while (node)
538 {
539 wxShape *constrainedObject = (wxShape *)node->GetData();
540
541 double x3 = (double)(x - (minWidth/2.0));
542 if (!Equals(x3, constrainedObject->GetX()))
543 {
544 changed = true;
545 constrainedObject->Move(dc, x3, constrainedObject->GetY(), false);
546 }
547
548 node = node->GetNext();
549 }
550 return changed;
551 }
552 case gyCONSTRAINT_MIDALIGNED_RIGHT:
553 {
554 bool changed = false;
555
556 wxNode *node = m_constrainedObjects.GetFirst();
557 while (node)
558 {
559 wxShape *constrainedObject = (wxShape *)node->GetData();
560
561 double x3 = (double)(x + (minWidth/2.0));
562 if (!Equals(x3, constrainedObject->GetX()))
563 {
564 changed = true;
565 constrainedObject->Move(dc, x3, constrainedObject->GetY(), false);
566 }
567
568 node = node->GetNext();
569 }
570 return changed;
571 #if 0
572 // two returned values ?
573 return false;
574 #endif
575 }
576 case gyCONSTRAINT_MIDALIGNED_TOP:
577 {
578 bool changed = false;
579
580 wxNode *node = m_constrainedObjects.GetFirst();
581 while (node)
582 {
583 wxShape *constrainedObject = (wxShape *)node->GetData();
584
585 double y3 = (double)(y - (minHeight/2.0));
586 if (!Equals(y3, constrainedObject->GetY()))
587 {
588 changed = true;
589 constrainedObject->Move(dc, constrainedObject->GetX(), y3, false);
590 }
591
592 node = node->GetNext();
593 }
594 return changed;
595 }
596 case gyCONSTRAINT_MIDALIGNED_BOTTOM:
597 {
598 bool changed = false;
599
600 wxNode *node = m_constrainedObjects.GetFirst();
601 while (node)
602 {
603 wxShape *constrainedObject = (wxShape *)node->GetData();
604
605 double y3 = (double)(y + (minHeight/2.0));
606 if (!Equals(y3, constrainedObject->GetY()))
607 {
608 changed = true;
609 constrainedObject->Move(dc, constrainedObject->GetX(), y3, false);
610 }
611
612 node = node->GetNext();
613 }
614 return changed;
615 }
616 #if 0
617 // default value handled in main function body
618 default:
619 return false;
620 #endif
621 }
622 return false;
623 }
624