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