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