1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: OGL Constraint classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
24 #include <wx/deprecated/wxexpr.h>
27 #include "wx/ogl/ogl.h"
30 wxList
*wxOGLConstraintTypes
= NULL
;
37 IMPLEMENT_DYNAMIC_CLASS(wxOGLConstraintType
, wxObject
)
39 wxOGLConstraintType::wxOGLConstraintType(int theType
, const wxString
& theName
, const wxString
& thePhrase
)
46 wxOGLConstraintType::~wxOGLConstraintType()
50 void OGLInitializeConstraintTypes()
52 if (!wxOGLConstraintTypes
)
55 wxOGLConstraintTypes
= new wxList(wxKEY_INTEGER
);
57 wxOGLConstraintTypes
->Append(gyCONSTRAINT_CENTRED_VERTICALLY
,
58 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_VERTICALLY
, wxT("Centre vertically"), wxT("centred vertically w.r.t.")));
60 wxOGLConstraintTypes
->Append(gyCONSTRAINT_CENTRED_HORIZONTALLY
,
61 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_HORIZONTALLY
, wxT("Centre horizontally"), wxT("centred horizontally w.r.t.")));
63 wxOGLConstraintTypes
->Append(gyCONSTRAINT_CENTRED_BOTH
,
64 new wxOGLConstraintType(gyCONSTRAINT_CENTRED_BOTH
, wxT("Centre"), wxT("centred w.r.t.")));
66 wxOGLConstraintTypes
->Append(gyCONSTRAINT_LEFT_OF
,
67 new wxOGLConstraintType(gyCONSTRAINT_LEFT_OF
, wxT("Left of"), wxT("left of")));
69 wxOGLConstraintTypes
->Append(gyCONSTRAINT_RIGHT_OF
,
70 new wxOGLConstraintType(gyCONSTRAINT_RIGHT_OF
, wxT("Right of"), wxT("right of")));
72 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ABOVE
,
73 new wxOGLConstraintType(gyCONSTRAINT_ABOVE
, wxT("Above"), wxT("above")));
75 wxOGLConstraintTypes
->Append(gyCONSTRAINT_BELOW
,
76 new wxOGLConstraintType(gyCONSTRAINT_BELOW
, wxT("Below"), wxT("below")));
79 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ALIGNED_TOP
,
80 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_TOP
, wxT("Top-aligned"), wxT("aligned to the top of")));
82 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ALIGNED_BOTTOM
,
83 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_BOTTOM
, wxT("Bottom-aligned"), wxT("aligned to the bottom of")));
85 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ALIGNED_LEFT
,
86 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_LEFT
, wxT("Left-aligned"), wxT("aligned to the left of")));
88 wxOGLConstraintTypes
->Append(gyCONSTRAINT_ALIGNED_RIGHT
,
89 new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_RIGHT
, wxT("Right-aligned"), wxT("aligned to the right of")));
92 wxOGLConstraintTypes
->Append(gyCONSTRAINT_MIDALIGNED_TOP
,
93 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_TOP
, wxT("Top-midaligned"), wxT("centred on the top of")));
95 wxOGLConstraintTypes
->Append(gyCONSTRAINT_MIDALIGNED_BOTTOM
,
96 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_BOTTOM
, wxT("Bottom-midaligned"), wxT("centred on the bottom of")));
98 wxOGLConstraintTypes
->Append(gyCONSTRAINT_MIDALIGNED_LEFT
,
99 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_LEFT
, wxT("Left-midaligned"), wxT("centred on the left of")));
101 wxOGLConstraintTypes
->Append(gyCONSTRAINT_MIDALIGNED_RIGHT
,
102 new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_RIGHT
, wxT("Right-midaligned"), wxT("centred on the right of")));
105 void OGLCleanUpConstraintTypes()
107 if (!wxOGLConstraintTypes
)
110 wxNode
* node
= wxOGLConstraintTypes
->GetFirst();
113 wxOGLConstraintType
* ct
= (wxOGLConstraintType
*) node
->GetData();
115 node
= node
->GetNext();
117 delete wxOGLConstraintTypes
;
118 wxOGLConstraintTypes
= NULL
;
126 IMPLEMENT_DYNAMIC_CLASS(wxOGLConstraint
, wxObject
)
128 wxOGLConstraint::wxOGLConstraint(int type
, wxShape
*constraining
, wxList
& constrained
)
133 m_constraintType
= type
;
134 m_constrainingObject
= constraining
;
137 m_constraintName
= wxT("noname");
139 wxNode
*node
= constrained
.GetFirst();
142 m_constrainedObjects
.Append(node
->GetData());
143 node
= node
->GetNext();
147 wxOGLConstraint::~wxOGLConstraint()
151 bool wxOGLConstraint::Equals(double a
, double b
)
155 bool eq
= ((b
<= a
+ marg
) && (b
>= a
- marg
));
159 // Return true if anything changed
160 bool wxOGLConstraint::Evaluate()
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();
168 wxClientDC
dc(m_constrainingObject
->GetCanvas());
169 m_constrainingObject
->GetCanvas()->PrepareDC(dc
);
171 switch (m_constraintType
)
173 case gyCONSTRAINT_CENTRED_VERTICALLY
:
175 int n
= m_constrainedObjects
.GetCount();
176 double totalObjectHeight
= 0.0;
177 wxNode
*node
= m_constrainedObjects
.GetFirst();
180 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
182 double width2
, height2
;
183 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
184 totalObjectHeight
+= height2
;
185 node
= node
->GetNext();
189 // Check if within the constraining object...
190 if ((totalObjectHeight
+ (n
+ 1)*m_ySpacing
) <= minHeight
)
192 spacingY
= (double)((minHeight
- totalObjectHeight
)/(n
+ 1));
193 startY
= (double)(y
- (minHeight
/2.0));
195 // Otherwise, use default spacing
198 spacingY
= m_ySpacing
;
199 startY
= (double)(y
- ((totalObjectHeight
+ (n
+1)*spacingY
)/2.0));
202 // Now position the objects
203 bool changed
= false;
204 node
= m_constrainedObjects
.GetFirst();
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()))
213 constrainedObject
->Move(dc
, constrainedObject
->GetX(), startY
, false);
216 startY
+= (double)(height2
/2.0);
217 node
= node
->GetNext();
221 case gyCONSTRAINT_CENTRED_HORIZONTALLY
:
223 int n
= m_constrainedObjects
.GetCount();
224 double totalObjectWidth
= 0.0;
225 wxNode
*node
= m_constrainedObjects
.GetFirst();
228 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
230 double width2
, height2
;
231 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
232 totalObjectWidth
+= width2
;
233 node
= node
->GetNext();
237 // Check if within the constraining object...
238 if ((totalObjectWidth
+ (n
+ 1)*m_xSpacing
) <= minWidth
)
240 spacingX
= (double)((minWidth
- totalObjectWidth
)/(n
+ 1));
241 startX
= (double)(x
- (minWidth
/2.0));
243 // Otherwise, use default spacing
246 spacingX
= m_xSpacing
;
247 startX
= (double)(x
- ((totalObjectWidth
+ (n
+1)*spacingX
)/2.0));
250 // Now position the objects
251 bool changed
= false;
252 node
= m_constrainedObjects
.GetFirst();
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()))
261 constrainedObject
->Move(dc
, startX
, constrainedObject
->GetY(), false);
264 startX
+= (double)(width2
/2.0);
265 node
= node
->GetNext();
269 case gyCONSTRAINT_CENTRED_BOTH
:
271 int n
= m_constrainedObjects
.GetCount();
272 double totalObjectWidth
= 0.0;
273 double totalObjectHeight
= 0.0;
274 wxNode
*node
= m_constrainedObjects
.GetFirst();
277 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
279 double width2
, height2
;
280 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
281 totalObjectWidth
+= width2
;
282 totalObjectHeight
+= height2
;
283 node
= node
->GetNext();
290 // Check if within the constraining object...
291 if ((totalObjectWidth
+ (n
+ 1)*m_xSpacing
) <= minWidth
)
293 spacingX
= (double)((minWidth
- totalObjectWidth
)/(n
+ 1));
294 startX
= (double)(x
- (minWidth
/2.0));
296 // Otherwise, use default spacing
299 spacingX
= m_xSpacing
;
300 startX
= (double)(x
- ((totalObjectWidth
+ (n
+1)*spacingX
)/2.0));
303 // Check if within the constraining object...
304 if ((totalObjectHeight
+ (n
+ 1)*m_ySpacing
) <= minHeight
)
306 spacingY
= (double)((minHeight
- totalObjectHeight
)/(n
+ 1));
307 startY
= (double)(y
- (minHeight
/2.0));
309 // Otherwise, use default spacing
312 spacingY
= m_ySpacing
;
313 startY
= (double)(y
- ((totalObjectHeight
+ (n
+1)*spacingY
)/2.0));
316 // Now position the objects
317 bool changed
= false;
318 node
= m_constrainedObjects
.GetFirst();
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));
327 if ((!Equals(startX
, constrainedObject
->GetX())) || (!Equals(startY
, constrainedObject
->GetY())))
329 constrainedObject
->Move(dc
, startX
, startY
, false);
333 startX
+= (double)(width2
/2.0);
334 startY
+= (double)(height2
/2.0);
336 node
= node
->GetNext();
340 case gyCONSTRAINT_LEFT_OF
:
342 bool changed
= false;
344 wxNode
*node
= m_constrainedObjects
.GetFirst();
347 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
349 double width2
, height2
;
350 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
352 double x3
= (double)(x
- (minWidth
/2.0) - (width2
/2.0) - m_xSpacing
);
353 if (!Equals(x3
, constrainedObject
->GetX()))
356 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), false);
359 node
= node
->GetNext();
363 case gyCONSTRAINT_RIGHT_OF
:
365 bool changed
= false;
367 wxNode
*node
= m_constrainedObjects
.GetFirst();
370 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
372 double width2
, height2
;
373 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
375 double x3
= (double)(x
+ (minWidth
/2.0) + (width2
/2.0) + m_xSpacing
);
376 if (!Equals(x3
, constrainedObject
->GetX()))
379 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), false);
382 node
= node
->GetNext();
386 case gyCONSTRAINT_ABOVE
:
388 bool changed
= false;
390 wxNode
*node
= m_constrainedObjects
.GetFirst();
393 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
395 double width2
, height2
;
396 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
398 double y3
= (double)(y
- (minHeight
/2.0) - (height2
/2.0) - m_ySpacing
);
399 if (!Equals(y3
, constrainedObject
->GetY()))
402 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, false);
405 node
= node
->GetNext();
409 case gyCONSTRAINT_BELOW
:
411 bool changed
= false;
413 wxNode
*node
= m_constrainedObjects
.GetFirst();
416 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
418 double width2
, height2
;
419 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
421 double y3
= (double)(y
+ (minHeight
/2.0) + (height2
/2.0) + m_ySpacing
);
422 if (!Equals(y3
, constrainedObject
->GetY()))
425 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, false);
428 node
= node
->GetNext();
432 case gyCONSTRAINT_ALIGNED_LEFT
:
434 bool changed
= false;
436 wxNode
*node
= m_constrainedObjects
.GetFirst();
439 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
441 double width2
, height2
;
442 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
444 double x3
= (double)(x
- (minWidth
/2.0) + (width2
/2.0) + m_xSpacing
);
445 if (!Equals(x3
, constrainedObject
->GetX()))
448 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), false);
451 node
= node
->GetNext();
455 case gyCONSTRAINT_ALIGNED_RIGHT
:
457 bool changed
= false;
459 wxNode
*node
= m_constrainedObjects
.GetFirst();
462 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
464 double width2
, height2
;
465 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
467 double x3
= (double)(x
+ (minWidth
/2.0) - (width2
/2.0) - m_xSpacing
);
468 if (!Equals(x3
, constrainedObject
->GetX()))
471 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), false);
474 node
= node
->GetNext();
478 // two returned values ?
482 case gyCONSTRAINT_ALIGNED_TOP
:
484 bool changed
= false;
486 wxNode
*node
= m_constrainedObjects
.GetFirst();
489 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
491 double width2
, height2
;
492 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
494 double y3
= (double)(y
- (minHeight
/2.0) + (height2
/2.0) + m_ySpacing
);
495 if (!Equals(y3
, constrainedObject
->GetY()))
498 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, false);
501 node
= node
->GetNext();
505 case gyCONSTRAINT_ALIGNED_BOTTOM
:
507 bool changed
= false;
509 wxNode
*node
= m_constrainedObjects
.GetFirst();
512 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
514 double width2
, height2
;
515 constrainedObject
->GetBoundingBoxMax(&width2
, &height2
);
517 double y3
= (double)(y
+ (minHeight
/2.0) - (height2
/2.0) - m_ySpacing
);
518 if (!Equals(y3
, constrainedObject
->GetY()))
521 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, false);
524 node
= node
->GetNext();
528 case gyCONSTRAINT_MIDALIGNED_LEFT
:
530 bool changed
= false;
532 wxNode
*node
= m_constrainedObjects
.GetFirst();
535 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
537 double x3
= (double)(x
- (minWidth
/2.0));
538 if (!Equals(x3
, constrainedObject
->GetX()))
541 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), false);
544 node
= node
->GetNext();
548 case gyCONSTRAINT_MIDALIGNED_RIGHT
:
550 bool changed
= false;
552 wxNode
*node
= m_constrainedObjects
.GetFirst();
555 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
557 double x3
= (double)(x
+ (minWidth
/2.0));
558 if (!Equals(x3
, constrainedObject
->GetX()))
561 constrainedObject
->Move(dc
, x3
, constrainedObject
->GetY(), false);
564 node
= node
->GetNext();
568 // two returned values ?
572 case gyCONSTRAINT_MIDALIGNED_TOP
:
574 bool changed
= false;
576 wxNode
*node
= m_constrainedObjects
.GetFirst();
579 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
581 double y3
= (double)(y
- (minHeight
/2.0));
582 if (!Equals(y3
, constrainedObject
->GetY()))
585 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, false);
588 node
= node
->GetNext();
592 case gyCONSTRAINT_MIDALIGNED_BOTTOM
:
594 bool changed
= false;
596 wxNode
*node
= m_constrainedObjects
.GetFirst();
599 wxShape
*constrainedObject
= (wxShape
*)node
->GetData();
601 double y3
= (double)(y
+ (minHeight
/2.0));
602 if (!Equals(y3
, constrainedObject
->GetY()))
605 constrainedObject
->Move(dc
, constrainedObject
->GetX(), y3
, false);
608 node
= node
->GetNext();
613 // default value handled in main function body