1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: OGL Constraint classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "constrnt.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
28 #include <wx/deprecated/wxexpr.h>
31 #include <wx/ogl/basic.h>
32 #include <wx/ogl/constrnt.h>
33 #include <wx/ogl/canvas.h>
35 wxList
*wxOGLConstraintTypes
= NULL
;
42 IMPLEMENT_DYNAMIC_CLASS(wxOGLConstraintType
, wxObject
)
44 wxOGLConstraintType::wxOGLConstraintType(int theType
, const wxString
& theName
, const wxString
& thePhrase
)
51 wxOGLConstraintType::~wxOGLConstraintType()
55 void OGLInitializeConstraintTypes()
57 if (!wxOGLConstraintTypes
)
60 wxOGLConstraintTypes
= new wxList(wxKEY_INTEGER
);
62 wxOGLConstraintTypes
->Append(gyCONSTRAINT_CENTRED_VERTICALLY
,
63 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_VERTICALLY
, wxT("Centre vertically"), wxT("centred vertically w.r.t.")));
65 wxOGLConstraintTypes
->Append(gyCONSTRAINT_CENTRED_HORIZONTALLY
,
66 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_HORIZONTALLY
, wxT("Centre horizontally"), wxT("centred horizontally w.r.t.")));
68 wxOGLConstraintTypes
->Append(gyCONSTRAINT_CENTRED_BOTH
,
69 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_BOTH
, wxT("Centre"), wxT("centred w.r.t.")));
71 wxOGLConstraintTypes
->Append(gyCONSTRAINT_LEFT_OF
,
72 new wxOGLConstraintType(gyCONSTRAINT_LEFT_OF
, wxT("Left of"), wxT("left of")));
74 wxOGLConstraintTypes
->Append(gyCONSTRAINT_RIGHT_OF
,
75 new wxOGLConstraintType(gyCONSTRAINT_RIGHT_OF
, wxT("Right of"), wxT("right of")));
77 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ABOVE
,
78 new wxOGLConstraintType(gyCONSTRAINT_ABOVE
, wxT("Above"), wxT("above")));
80 wxOGLConstraintTypes
->Append(gyCONSTRAINT_BELOW
,
81 new wxOGLConstraintType(gyCONSTRAINT_BELOW
, wxT("Below"), wxT("below")));
84 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ALIGNED_TOP
,
85 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_TOP
, wxT("Top-aligned"), wxT("aligned to the top of")));
87 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ALIGNED_BOTTOM
,
88 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_BOTTOM
, wxT("Bottom-aligned"), wxT("aligned to the bottom of")));
90 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ALIGNED_LEFT
,
91 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_LEFT
, wxT("Left-aligned"), wxT("aligned to the left of")));
93 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ALIGNED_RIGHT
,
94 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_RIGHT
, wxT("Right-aligned"), wxT("aligned to the right of")));
97 wxOGLConstraintTypes
->Append(gyCONSTRAINT_MIDALIGNED_TOP
,
98 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_TOP
, wxT("Top-midaligned"), wxT("centred on the top of")));
100 wxOGLConstraintTypes
->Append(gyCONSTRAINT_MIDALIGNED_BOTTOM
,
101 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_BOTTOM
, wxT("Bottom-midaligned"), wxT("centred on the bottom of")));
103 wxOGLConstraintTypes
->Append(gyCONSTRAINT_MIDALIGNED_LEFT
,
104 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_LEFT
, wxT("Left-midaligned"), wxT("centred on the left of")));
106 wxOGLConstraintTypes
->Append(gyCONSTRAINT_MIDALIGNED_RIGHT
,
107 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_RIGHT
, wxT("Right-midaligned"), wxT("centred on the right of")));
110 void OGLCleanUpConstraintTypes()
112 if (!wxOGLConstraintTypes
)
115 wxNode
* node
= wxOGLConstraintTypes
->GetFirst();
118 wxOGLConstraintType
* ct
= (wxOGLConstraintType
*) node
->GetData();
120 node
= node
->GetNext();
122 delete wxOGLConstraintTypes
;
123 wxOGLConstraintTypes
= NULL
;
131 IMPLEMENT_DYNAMIC_CLASS(wxOGLConstraint
, wxObject
)
133 wxOGLConstraint::wxOGLConstraint(int type
, wxShape
*constraining
, wxList
& constrained
)
138 m_constraintType
= type
;
139 m_constrainingObject
= constraining
;
142 m_constraintName
= wxT("noname");
144 wxNode
*node
= constrained
.GetFirst();
147 m_constrainedObjects
.Append(node
->GetData());
148 node
= node
->GetNext();
152 wxOGLConstraint::~wxOGLConstraint()
156 bool wxOGLConstraint::Equals(double a
, double b
)
160 bool eq
= ((b
<= a
+ marg
) && (b
>= a
- marg
));
164 // Return TRUE if anything changed
165 bool wxOGLConstraint::Evaluate()
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();
173 wxClientDC
dc(m_constrainingObject
->GetCanvas());
174 m_constrainingObject
->GetCanvas()->PrepareDC(dc
);
176 switch (m_constraintType
)
178 case gyCONSTRAINT_CENTRED_VERTICALLY
:
180 int n
= m_constrainedObjects
.GetCount();
181 double totalObjectHeight
= 0.0;
182 wxNode
*node
= m_constrainedObjects
.GetFirst();
185 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
187 double width2
, height2
;
188 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
189 totalObjectHeight
+= height2
;
190 node
= node
->GetNext();
194 // Check if within the constraining object...
195 if ((totalObjectHeight
+ (n
+ 1)*m_ySpacing
) <= minHeight
)
197 spacingY
= (double)((minHeight
- totalObjectHeight
)/(n
+ 1));
198 startY
= (double)(y
- (minHeight
/2.0));
200 // Otherwise, use default spacing
203 spacingY
= m_ySpacing
;
204 startY
= (double)(y
- ((totalObjectHeight
+ (n
+1)*spacingY
)/2.0));
207 // Now position the objects
208 bool changed
= FALSE
;
209 node
= m_constrainedObjects
.GetFirst();
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()))
218 constrainedObject
->Move(dc
, constrainedObject
->GetX(), startY
, FALSE
);
221 startY
+= (double)(height2
/2.0);
222 node
= node
->GetNext();
226 case gyCONSTRAINT_CENTRED_HORIZONTALLY
:
228 int n
= m_constrainedObjects
.GetCount();
229 double totalObjectWidth
= 0.0;
230 wxNode
*node
= m_constrainedObjects
.GetFirst();
233 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
235 double width2
, height2
;
236 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
237 totalObjectWidth
+= width2
;
238 node
= node
->GetNext();
242 // Check if within the constraining object...
243 if ((totalObjectWidth
+ (n
+ 1)*m_xSpacing
) <= minWidth
)
245 spacingX
= (double)((minWidth
- totalObjectWidth
)/(n
+ 1));
246 startX
= (double)(x
- (minWidth
/2.0));
248 // Otherwise, use default spacing
251 spacingX
= m_xSpacing
;
252 startX
= (double)(x
- ((totalObjectWidth
+ (n
+1)*spacingX
)/2.0));
255 // Now position the objects
256 bool changed
= FALSE
;
257 node
= m_constrainedObjects
.GetFirst();
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()))
266 constrainedObject
->Move(dc
, startX
, constrainedObject
->GetY(), FALSE
);
269 startX
+= (double)(width2
/2.0);
270 node
= node
->GetNext();
274 case gyCONSTRAINT_CENTRED_BOTH
:
276 int n
= m_constrainedObjects
.GetCount();
277 double totalObjectWidth
= 0.0;
278 double totalObjectHeight
= 0.0;
279 wxNode
*node
= m_constrainedObjects
.GetFirst();
282 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
284 double width2
, height2
;
285 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
286 totalObjectWidth
+= width2
;
287 totalObjectHeight
+= height2
;
288 node
= node
->GetNext();
295 // Check if within the constraining object...
296 if ((totalObjectWidth
+ (n
+ 1)*m_xSpacing
) <= minWidth
)
298 spacingX
= (double)((minWidth
- totalObjectWidth
)/(n
+ 1));
299 startX
= (double)(x
- (minWidth
/2.0));
301 // Otherwise, use default spacing
304 spacingX
= m_xSpacing
;
305 startX
= (double)(x
- ((totalObjectWidth
+ (n
+1)*spacingX
)/2.0));
308 // Check if within the constraining object...
309 if ((totalObjectHeight
+ (n
+ 1)*m_ySpacing
) <= minHeight
)
311 spacingY
= (double)((minHeight
- totalObjectHeight
)/(n
+ 1));
312 startY
= (double)(y
- (minHeight
/2.0));
314 // Otherwise, use default spacing
317 spacingY
= m_ySpacing
;
318 startY
= (double)(y
- ((totalObjectHeight
+ (n
+1)*spacingY
)/2.0));
321 // Now position the objects
322 bool changed
= FALSE
;
323 node
= m_constrainedObjects
.GetFirst();
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));
332 if ((!Equals(startX
, constrainedObject
->GetX())) || (!Equals(startY
, constrainedObject
->GetY())))
334 constrainedObject
->Move(dc
, startX
, startY
, FALSE
);
338 startX
+= (double)(width2
/2.0);
339 startY
+= (double)(height2
/2.0);
341 node
= node
->GetNext();
345 case gyCONSTRAINT_LEFT_OF
:
347 bool changed
= FALSE
;
349 wxNode
*node
= m_constrainedObjects
.GetFirst();
352 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
354 double width2
, height2
;
355 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
357 double x3
= (double)(x
- (minWidth
/2.0) - (width2
/2.0) - m_xSpacing
);
358 if (!Equals(x3
, constrainedObject
->GetX()))
361 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), FALSE
);
364 node
= node
->GetNext();
368 case gyCONSTRAINT_RIGHT_OF
:
370 bool changed
= FALSE
;
372 wxNode
*node
= m_constrainedObjects
.GetFirst();
375 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
377 double width2
, height2
;
378 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
380 double x3
= (double)(x
+ (minWidth
/2.0) + (width2
/2.0) + m_xSpacing
);
381 if (!Equals(x3
, constrainedObject
->GetX()))
384 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), FALSE
);
387 node
= node
->GetNext();
393 case gyCONSTRAINT_ABOVE
:
395 bool changed
= FALSE
;
397 wxNode
*node
= m_constrainedObjects
.GetFirst();
400 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
402 double width2
, height2
;
403 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
405 double y3
= (double)(y
- (minHeight
/2.0) - (height2
/2.0) - m_ySpacing
);
406 if (!Equals(y3
, constrainedObject
->GetY()))
409 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, FALSE
);
412 node
= node
->GetNext();
416 case gyCONSTRAINT_BELOW
:
418 bool changed
= FALSE
;
420 wxNode
*node
= m_constrainedObjects
.GetFirst();
423 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
425 double width2
, height2
;
426 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
428 double y3
= (double)(y
+ (minHeight
/2.0) + (height2
/2.0) + m_ySpacing
);
429 if (!Equals(y3
, constrainedObject
->GetY()))
432 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, FALSE
);
435 node
= node
->GetNext();
439 case gyCONSTRAINT_ALIGNED_LEFT
:
441 bool changed
= FALSE
;
443 wxNode
*node
= m_constrainedObjects
.GetFirst();
446 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
448 double width2
, height2
;
449 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
451 double x3
= (double)(x
- (minWidth
/2.0) + (width2
/2.0) + m_xSpacing
);
452 if (!Equals(x3
, constrainedObject
->GetX()))
455 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), FALSE
);
458 node
= node
->GetNext();
462 case gyCONSTRAINT_ALIGNED_RIGHT
:
464 bool changed
= FALSE
;
466 wxNode
*node
= m_constrainedObjects
.GetFirst();
469 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
471 double width2
, height2
;
472 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
474 double x3
= (double)(x
+ (minWidth
/2.0) - (width2
/2.0) - m_xSpacing
);
475 if (!Equals(x3
, constrainedObject
->GetX()))
478 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), FALSE
);
481 node
= node
->GetNext();
487 case gyCONSTRAINT_ALIGNED_TOP
:
489 bool changed
= FALSE
;
491 wxNode
*node
= m_constrainedObjects
.GetFirst();
494 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
496 double width2
, height2
;
497 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
499 double y3
= (double)(y
- (minHeight
/2.0) + (height2
/2.0) + m_ySpacing
);
500 if (!Equals(y3
, constrainedObject
->GetY()))
503 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, FALSE
);
506 node
= node
->GetNext();
510 case gyCONSTRAINT_ALIGNED_BOTTOM
:
512 bool changed
= FALSE
;
514 wxNode
*node
= m_constrainedObjects
.GetFirst();
517 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
519 double width2
, height2
;
520 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
522 double y3
= (double)(y
+ (minHeight
/2.0) - (height2
/2.0) - m_ySpacing
);
523 if (!Equals(y3
, constrainedObject
->GetY()))
526 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, FALSE
);
529 node
= node
->GetNext();
533 case gyCONSTRAINT_MIDALIGNED_LEFT
:
535 bool changed
= FALSE
;
537 wxNode
*node
= m_constrainedObjects
.GetFirst();
540 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
542 double x3
= (double)(x
- (minWidth
/2.0));
543 if (!Equals(x3
, constrainedObject
->GetX()))
546 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), FALSE
);
549 node
= node
->GetNext();
553 case gyCONSTRAINT_MIDALIGNED_RIGHT
:
555 bool changed
= FALSE
;
557 wxNode
*node
= m_constrainedObjects
.GetFirst();
560 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
562 double x3
= (double)(x
+ (minWidth
/2.0));
563 if (!Equals(x3
, constrainedObject
->GetX()))
566 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), FALSE
);
569 node
= node
->GetNext();
575 case gyCONSTRAINT_MIDALIGNED_TOP
:
577 bool changed
= FALSE
;
579 wxNode
*node
= m_constrainedObjects
.GetFirst();
582 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
584 double y3
= (double)(y
- (minHeight
/2.0));
585 if (!Equals(y3
, constrainedObject
->GetY()))
588 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, FALSE
);
591 node
= node
->GetNext();
595 case gyCONSTRAINT_MIDALIGNED_BOTTOM
:
597 bool changed
= FALSE
;
599 wxNode
*node
= m_constrainedObjects
.GetFirst();
602 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
604 double y3
= (double)(y
+ (minHeight
/2.0));
605 if (!Equals(y3
, constrainedObject
->GetY()))
608 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, FALSE
);
611 node
= node
->GetNext();