1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Composite OGL class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "composit.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include <wx/wxprec.h>
28 #include <wx/wxexpr.h>
38 // Sometimes, objects need to access the whole database to
39 // construct themselves.
40 wxExprDatabase
*GlobalwxExprDatabase
= NULL
;
42 // Popup menu for editing divisions
43 wxMenu
*oglPopupDivisionMenu
= NULL
;
46 * Division control point
49 class wxDivisionControlPoint
: public wxControlPoint
51 DECLARE_DYNAMIC_CLASS(wxDivisionControlPoint
)
53 wxDivisionControlPoint() {}
54 wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, float size
, float the_xoffset
, float the_yoffset
, int the_type
);
55 ~wxDivisionControlPoint();
57 void OnDragLeft(bool draw
, float x
, float y
, int keys
=0, int attachment
= 0);
58 void OnBeginDragLeft(float x
, float y
, int keys
=0, int attachment
= 0);
59 void OnEndDragLeft(float x
, float y
, int keys
=0, int attachment
= 0);
62 IMPLEMENT_DYNAMIC_CLASS(wxDivisionControlPoint
, wxControlPoint
)
69 IMPLEMENT_DYNAMIC_CLASS(wxCompositeShape
, wxRectangleShape
)
71 wxCompositeShape::wxCompositeShape(): wxRectangleShape(10.0, 10.0)
73 // selectable = FALSE;
78 wxCompositeShape::~wxCompositeShape()
80 wxNode
*node
= m_constraints
.First();
83 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
87 node
= m_children
.First();
90 wxShape
*object
= (wxShape
*)node
->Data();
91 wxNode
*next
= node
->Next();
98 void wxCompositeShape::OnDraw(wxDC
& dc
)
100 float x1
= (float)(m_xpos
- m_width
/2.0);
101 float y1
= (float)(m_ypos
- m_height
/2.0);
103 if (m_shadowMode
!= SHADOW_NONE
)
106 dc
.SetBrush(m_shadowBrush
);
107 dc
.SetPen(transparent_pen
);
109 if (m_cornerRadius
!= 0.0)
110 dc
.DrawRoundedRectangle(x1
+ m_shadowOffsetX
, y1
+ m_shadowOffsetY
,
111 m_width
, m_height
, m_cornerRadius
);
113 dc
.DrawRectangle(x1
+ m_shadowOffsetX
, y1
+ m_shadowOffsetY
, m_width
, m_height
);
117 void wxCompositeShape::OnDrawContents(wxDC
& dc
)
119 wxNode
*node
= m_children
.First();
122 wxShape
*object
= (wxShape
*)node
->Data();
124 object
->DrawLinks(dc
);
127 wxShape::OnDrawContents(dc
);
130 bool wxCompositeShape::OnMovePre(wxDC
& dc
, float x
, float y
, float oldx
, float oldy
, bool display
)
132 float diffX
= x
- oldx
;
133 float diffY
= y
- oldy
;
134 wxNode
*node
= m_children
.First();
137 wxShape
*object
= (wxShape
*)node
->Data();
140 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
147 void wxCompositeShape::OnErase(wxDC
& dc
)
149 wxRectangleShape::OnErase(dc
);
150 wxNode
*node
= m_children
.First();
153 wxShape
*object
= (wxShape
*)node
->Data();
159 static float objectStartX
= 0.0;
160 static float objectStartY
= 0.0;
162 void wxCompositeShape::OnDragLeft(bool draw
, float x
, float y
, int keys
, int attachment
)
166 m_canvas
->Snap(&xx
, &yy
);
167 float offsetX
= xx
- objectStartX
;
168 float offsetY
= yy
- objectStartY
;
170 wxClientDC
dc(GetCanvas());
171 GetCanvas()->PrepareDC(dc
);
173 dc
.SetLogicalFunction(wxXOR
);
174 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
175 dc
.SetPen(dottedPen
);
176 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
178 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
179 // wxShape::OnDragLeft(draw, x, y, keys, attachment);
182 void wxCompositeShape::OnBeginDragLeft(float x
, float y
, int keys
, int attachment
)
187 wxClientDC
dc(GetCanvas());
188 GetCanvas()->PrepareDC(dc
);
192 dc
.SetLogicalFunction(wxXOR
);
194 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
195 dc
.SetPen(dottedPen
);
196 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
197 m_canvas
->CaptureMouse();
201 m_canvas
->Snap(&xx
, &yy
);
202 float offsetX
= xx
- objectStartX
;
203 float offsetY
= yy
- objectStartY
;
205 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
207 // wxShape::OnBeginDragLeft(x, y, keys, attachment);
210 void wxCompositeShape::OnEndDragLeft(float x
, float y
, int keys
, int attachment
)
212 // wxShape::OnEndDragLeft(x, y, keys, attachment);
214 wxClientDC
dc(GetCanvas());
215 GetCanvas()->PrepareDC(dc
);
217 m_canvas
->ReleaseMouse();
221 if (m_parent
) m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, 0);
225 dc
.SetLogicalFunction(wxCOPY
);
228 m_canvas
->Snap(&xx
, &yy
);
229 float offsetX
= xx
- objectStartX
;
230 float offsetY
= yy
- objectStartY
;
232 Move(dc
, GetX() + offsetX
, GetY() + offsetY
);
234 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
237 void wxCompositeShape::OnRightClick(float x
, float y
, int keys
, int attachment
)
239 // If we get a ctrl-right click, this means send the message to
240 // the division, so we can invoke a user interface for dealing with regions.
243 wxNode
*node
= m_divisions
.First();
246 wxDivisionShape
*division
= (wxDivisionShape
*)node
->Data();
247 wxNode
*next
= node
->Next();
250 if (division
->HitTest(x
, y
, &attach
, &dist
))
252 division
->GetEventHandler()->OnRightClick(x
, y
, keys
, attach
);
261 void wxCompositeShape::SetSize(float w
, float h
, bool recursive
)
263 SetAttachmentSize(w
, h
);
265 float xScale
= (float)(w
/(wxMax(1.0, GetWidth())));
266 float yScale
= (float)(h
/(wxMax(1.0, GetHeight())));
271 if (!recursive
) return;
273 wxNode
*node
= m_children
.First();
275 wxClientDC
dc(GetCanvas());
276 GetCanvas()->PrepareDC(dc
);
278 float xBound
, yBound
;
281 wxShape
*object
= (wxShape
*)node
->Data();
283 // Scale the position first
284 float newX
= (float)(((object
->GetX() - GetX())*xScale
) + GetX());
285 float newY
= (float)(((object
->GetY() - GetY())*yScale
) + GetY());
287 object
->Move(dc
, newX
, newY
);
290 // Now set the scaled size
291 object
->GetBoundingBoxMin(&xBound
, &yBound
);
292 object
->SetSize(object
->GetFixedWidth() ? xBound
: xScale
*xBound
,
293 object
->GetFixedHeight() ? yBound
: yScale
*yBound
);
297 SetDefaultRegionSize();
300 void wxCompositeShape::AddChild(wxShape
*child
, wxShape
*addAfter
)
302 m_children
.Append(child
);
303 child
->SetParent(this);
306 // Ensure we add at the right position
308 child
->RemoveFromCanvas(m_canvas
);
309 child
->AddToCanvas(m_canvas
, addAfter
);
313 void wxCompositeShape::RemoveChild(wxShape
*child
)
315 m_children
.DeleteObject(child
);
316 m_divisions
.DeleteObject(child
);
317 RemoveChildFromConstraints(child
);
318 child
->SetParent(NULL
);
321 void wxCompositeShape::DeleteConstraintsInvolvingChild(wxShape
*child
)
323 wxNode
*node
= m_constraints
.First();
326 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
327 wxNode
*nextNode
= node
->Next();
329 if ((constraint
->m_constrainingObject
== child
) ||
330 constraint
->m_constrainedObjects
.Member(child
))
339 void wxCompositeShape::RemoveChildFromConstraints(wxShape
*child
)
341 wxNode
*node
= m_constraints
.First();
344 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
345 wxNode
*nextNode
= node
->Next();
347 if (constraint
->m_constrainedObjects
.Member(child
))
348 constraint
->m_constrainedObjects
.DeleteObject(child
);
349 if (constraint
->m_constrainingObject
== child
)
350 constraint
->m_constrainingObject
= NULL
;
352 // Delete the constraint if no participants left
353 if (!constraint
->m_constrainingObject
)
363 void wxCompositeShape::Copy(wxShape
& copy
)
365 wxRectangleShape::Copy(copy
);
367 wxASSERT( copy
.IsKindOf(CLASSINFO(wxCompositeShape
)) ) ;
369 wxCompositeShape
& compositeCopy
= (wxCompositeShape
&) copy
;
371 // Associate old and new copies for compositeCopying constraints and division geometry
372 wxObjectCopyMapping
.Append((long)this, &compositeCopy
);
375 wxNode
*node
= m_children
.First();
378 wxShape
*object
= (wxShape
*)node
->Data();
379 wxShape
*newObject
= object
->CreateNewCopy(FALSE
, FALSE
);
380 if (newObject
->GetId() == 0)
381 newObject
->SetId(NewId());
383 newObject
->SetParent(&compositeCopy
);
384 compositeCopy
.m_children
.Append(newObject
);
386 // Some m_children may be divisions
387 if (m_divisions
.Member(object
))
388 compositeCopy
.m_divisions
.Append(newObject
);
390 wxObjectCopyMapping
.Append((long)object
, newObject
);
395 // Copy the constraints
396 node
= m_constraints
.First();
399 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
401 wxShape
*newConstraining
= (wxShape
*)(wxObjectCopyMapping
.Find((long)constraint
->m_constrainingObject
)->Data());
403 wxList newConstrainedList
;
404 wxNode
*node2
= constraint
->m_constrainedObjects
.First();
407 wxShape
*constrainedObject
= (wxShape
*)node2
->Data();
408 wxShape
*newConstrained
= (wxShape
*)(wxObjectCopyMapping
.Find((long)constrainedObject
)->Data());
409 newConstrainedList
.Append(newConstrained
);
410 node2
= node2
->Next();
413 OGLConstraint
*newConstraint
= new OGLConstraint(constraint
->m_constraintType
, newConstraining
,
415 newConstraint
->m_constraintId
= constraint
->m_constraintId
;
416 if (constraint
->m_constraintName
)
418 newConstraint
->m_constraintName
= constraint
->m_constraintName
;
420 newConstraint
->SetSpacing(constraint
->m_xSpacing
, constraint
->m_ySpacing
);
421 compositeCopy
.m_constraints
.Append(newConstraint
);
426 // Now compositeCopy the division geometry
427 node
= m_divisions
.First();
430 wxDivisionShape
*division
= (wxDivisionShape
*)node
->Data();
431 wxNode
*node1
= wxObjectCopyMapping
.Find((long)division
);
432 wxNode
*leftNode
= NULL
;
433 wxNode
*topNode
= NULL
;
434 wxNode
*rightNode
= NULL
;
435 wxNode
*bottomNode
= NULL
;
436 if (division
->GetLeftSide())
437 leftNode
= wxObjectCopyMapping
.Find((long)division
->GetLeftSide());
438 if (division
->GetTopSide())
439 topNode
= wxObjectCopyMapping
.Find((long)division
->GetTopSide());
440 if (division
->GetRightSide())
441 rightNode
= wxObjectCopyMapping
.Find((long)division
->GetRightSide());
442 if (division
->GetBottomSide())
443 bottomNode
= wxObjectCopyMapping
.Find((long)division
->GetBottomSide());
446 wxDivisionShape
*newDivision
= (wxDivisionShape
*)node1
->Data();
448 newDivision
->SetLeftSide((wxDivisionShape
*)leftNode
->Data());
450 newDivision
->SetTopSide((wxDivisionShape
*)topNode
->Data());
452 newDivision
->SetRightSide((wxDivisionShape
*)rightNode
->Data());
454 newDivision
->SetBottomSide((wxDivisionShape
*)bottomNode
->Data());
460 OGLConstraint
*wxCompositeShape::AddConstraint(OGLConstraint
*constraint
)
462 m_constraints
.Append(constraint
);
463 if (constraint
->m_constraintId
== 0)
464 constraint
->m_constraintId
= NewId();
468 OGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxList
& constrained
)
470 OGLConstraint
*constraint
= new OGLConstraint(type
, constraining
, constrained
);
471 if (constraint
->m_constraintId
== 0)
472 constraint
->m_constraintId
= NewId();
473 m_constraints
.Append(constraint
);
477 OGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxShape
*constrained
)
480 l
.Append(constrained
);
481 OGLConstraint
*constraint
= new OGLConstraint(type
, constraining
, l
);
482 if (constraint
->m_constraintId
== 0)
483 constraint
->m_constraintId
= NewId();
484 m_constraints
.Append(constraint
);
488 OGLConstraint
*wxCompositeShape::FindConstraint(long cId
, wxCompositeShape
**actualComposite
)
490 wxNode
*node
= m_constraints
.First();
493 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
494 if (constraint
->m_constraintId
== cId
)
497 *actualComposite
= this;
502 // If not found, try children.
503 node
= m_children
.First();
506 wxShape
*child
= (wxShape
*)node
->Data();
507 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
509 OGLConstraint
*constraint
= ((wxCompositeShape
*)child
)->FindConstraint(cId
, actualComposite
);
513 *actualComposite
= (wxCompositeShape
*)child
;
522 void wxCompositeShape::DeleteConstraint(OGLConstraint
*constraint
)
524 m_constraints
.DeleteObject(constraint
);
528 void wxCompositeShape::CalculateSize()
530 float maxX
= (float) -999999.9;
531 float maxY
= (float) -999999.9;
532 float minX
= (float) 999999.9;
533 float minY
= (float) 999999.9;
536 wxNode
*node
= m_children
.First();
539 wxShape
*object
= (wxShape
*)node
->Data();
541 // Recalculate size of composite objects because may not conform
542 // to size it was set to - depends on the children.
543 object
->CalculateSize();
545 object
->GetBoundingBoxMax(&w
, &h
);
546 if ((object
->GetX() + (w
/2.0)) > maxX
)
547 maxX
= (float)(object
->GetX() + (w
/2.0));
548 if ((object
->GetX() - (w
/2.0)) < minX
)
549 minX
= (float)(object
->GetX() - (w
/2.0));
550 if ((object
->GetY() + (h
/2.0)) > maxY
)
551 maxY
= (float)(object
->GetY() + (h
/2.0));
552 if ((object
->GetY() - (h
/2.0)) < minY
)
553 minY
= (float)(object
->GetY() - (h
/2.0));
557 m_width
= maxX
- minX
;
558 m_height
= maxY
- minY
;
559 m_xpos
= (float)(m_width
/2.0 + minX
);
560 m_ypos
= (float)(m_height
/2.0 + minY
);
563 bool wxCompositeShape::Recompute()
565 int noIterations
= 0;
567 while (changed
&& (noIterations
< 500))
569 changed
= Constrain();
575 cerr << "Warning: constraint algorithm failed after 500 iterations.\n";
581 bool wxCompositeShape::Constrain()
585 bool changed
= FALSE
;
586 wxNode
*node
= m_children
.First();
589 wxShape
*object
= (wxShape
*)node
->Data();
590 if (object
->Constrain())
595 node
= m_constraints
.First();
598 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
599 if (constraint
->Evaluate()) changed
= TRUE
;
606 void wxCompositeShape::WritePrologAttributes(wxExpr
*clause
)
608 wxRectangleShape::WritePrologAttributes(clause
);
610 // clause->AddAttributeValue("selectable", (long)selectable);
612 // Output constraints as constraint1 = (...), constraint2 = (...), etc.
613 int constraintNo
= 1;
614 char m_constraintNameBuf
[20];
615 wxNode
*node
= m_constraints
.First();
618 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
619 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
621 // Each constraint is stored in the form
622 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
623 wxExpr
*constraintExpr
= new wxExpr(PrologList
);
624 constraintExpr
->Append(new wxExpr((long)constraint
->m_constraintType
));
625 constraintExpr
->Append(new wxExpr(PrologString
, constraint
->m_constraintName
));
626 constraintExpr
->Append(new wxExpr(constraint
->m_constraintId
));
627 constraintExpr
->Append(new wxExpr(constraint
->m_xSpacing
));
628 constraintExpr
->Append(new wxExpr(constraint
->m_ySpacing
));
629 constraintExpr
->Append(new wxExpr(constraint
->m_constrainingObject
->GetId()));
631 wxExpr
*objectList
= new wxExpr(PrologList
);
632 wxNode
*node1
= constraint
->m_constrainedObjects
.First();
635 wxShape
*obj
= (wxShape
*)node1
->Data();
636 objectList
->Append(new wxExpr(obj
->GetId()));
637 node1
= node1
->Next();
639 constraintExpr
->Append(objectList
);
641 clause
->AddAttributeValue(m_constraintNameBuf
, constraintExpr
);
647 // Write the ids of all the child images
648 wxExpr
*childrenExpr
= new wxExpr(PrologList
);
649 node
= m_children
.First();
652 wxShape
*child
= (wxShape
*)node
->Data();
653 childrenExpr
->Append(new wxExpr(child
->GetId()));
656 clause
->AddAttributeValue("children", childrenExpr
);
658 // Write the ids of all the division images
659 if (m_divisions
.Number() > 0)
661 wxExpr
*divisionsExpr
= new wxExpr(PrologList
);
662 node
= m_divisions
.First();
665 wxShape
*child
= (wxShape
*)node
->Data();
666 divisionsExpr
->Append(new wxExpr(child
->GetId()));
669 clause
->AddAttributeValue("divisions", divisionsExpr
);
673 // Problem. Child images are always written AFTER the parent
674 // so as to be able to link up to parent. So we may not be able
675 // to find the constraint participants until we've read everything
676 // in. Need to have another pass for composites.
677 void wxCompositeShape::ReadPrologAttributes(wxExpr
*clause
)
679 wxRectangleShape::ReadPrologAttributes(clause
);
681 // clause->GetAttributeValue("selectable", selectable);
684 void wxCompositeShape::ReadConstraints(wxExpr
*clause
, wxExprDatabase
*database
)
686 // Constraints are output as constraint1 = (...), constraint2 = (...), etc.
687 int constraintNo
= 1;
688 char m_constraintNameBuf
[20];
689 bool haveConstraints
= TRUE
;
691 while (haveConstraints
)
693 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
694 wxExpr
*constraintExpr
= NULL
;
695 clause
->GetAttributeValue(m_constraintNameBuf
, &constraintExpr
);
698 haveConstraints
= FALSE
;
702 float cXSpacing
= 0.0;
703 float cYSpacing
= 0.0;
706 wxShape
*m_constrainingObject
= NULL
;
707 wxList m_constrainedObjects
;
709 // Each constraint is stored in the form
710 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
712 wxExpr
*typeExpr
= constraintExpr
->Nth(0);
713 wxExpr
*nameExpr
= constraintExpr
->Nth(1);
714 wxExpr
*idExpr
= constraintExpr
->Nth(2);
715 wxExpr
*xExpr
= constraintExpr
->Nth(3);
716 wxExpr
*yExpr
= constraintExpr
->Nth(4);
717 wxExpr
*constrainingExpr
= constraintExpr
->Nth(5);
718 wxExpr
*constrainedExpr
= constraintExpr
->Nth(6);
720 cType
= (int)typeExpr
->IntegerValue();
721 cXSpacing
= xExpr
->RealValue();
722 cYSpacing
= yExpr
->RealValue();
723 cName
= nameExpr
->StringValue();
724 cId
= idExpr
->IntegerValue();
726 wxExpr
*objExpr1
= database
->HashFind("node_image", constrainingExpr
->IntegerValue());
727 if (objExpr1
&& objExpr1
->GetClientData())
728 m_constrainingObject
= (wxShape
*)objExpr1
->GetClientData();
730 wxFatalError("Couldn't find constraining image of composite.", "Object graphics error");
733 wxExpr
*currentIdExpr
= constrainedExpr
->Nth(i
);
734 while (currentIdExpr
)
736 long currentId
= currentIdExpr
->IntegerValue();
737 wxExpr
*objExpr2
= database
->HashFind("node_image", currentId
);
738 if (objExpr2
&& objExpr2
->GetClientData())
740 m_constrainedObjects
.Append((wxShape
*)objExpr2
->GetClientData());
744 wxFatalError("Couldn't find constrained image of composite.", "Object graphics error");
748 currentIdExpr
= constrainedExpr
->Nth(i
);
750 OGLConstraint
*newConstraint
= AddConstraint(cType
, m_constrainingObject
, m_constrainedObjects
);
751 newConstraint
->SetSpacing(cXSpacing
, cYSpacing
);
752 newConstraint
->m_constraintId
= cId
;
753 newConstraint
->m_constraintName
= (const char*) cName
;
759 // Make this composite into a container by creating one wxDivisionShape
760 void wxCompositeShape::MakeContainer()
762 wxDivisionShape
*division
= OnCreateDivision();
763 m_divisions
.Append(division
);
766 division
->SetSize(m_width
, m_height
);
768 wxClientDC
dc(GetCanvas());
769 GetCanvas()->PrepareDC(dc
);
771 division
->Move(dc
, GetX(), GetY());
773 division
->Show(TRUE
);
776 wxDivisionShape
*wxCompositeShape::OnCreateDivision()
778 return new wxDivisionShape
;
781 wxShape
*wxCompositeShape::FindContainerImage()
783 wxNode
*node
= m_children
.First();
786 wxShape
*child
= (wxShape
*)node
->Data();
787 if (!m_divisions
.Member(child
))
794 // Returns TRUE if division is a descendant of this container
795 bool wxCompositeShape::ContainsDivision(wxDivisionShape
*division
)
797 if (m_divisions
.Member(division
))
799 wxNode
*node
= m_children
.First();
802 wxShape
*child
= (wxShape
*)node
->Data();
803 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
805 bool ans
= ((wxCompositeShape
*)child
)->ContainsDivision(division
);
819 IMPLEMENT_DYNAMIC_CLASS(wxDivisionShape
, wxCompositeShape
)
821 wxDivisionShape::wxDivisionShape()
823 SetSensitivityFilter(OP_CLICK_LEFT
| OP_CLICK_RIGHT
| OP_DRAG_RIGHT
);
824 SetCentreResize(FALSE
);
825 SetAttachmentMode(TRUE
);
830 m_handleSide
= DIVISION_SIDE_NONE
;
831 m_leftSidePen
= wxBLACK_PEN
;
832 m_topSidePen
= wxBLACK_PEN
;
833 m_leftSideColour
= "BLACK";
834 m_topSideColour
= "BLACK";
835 m_leftSideStyle
= "Solid";
836 m_topSideStyle
= "Solid";
840 wxDivisionShape::~wxDivisionShape()
844 void wxDivisionShape::OnDraw(wxDC
& dc
)
846 dc
.SetBrush(wxTRANSPARENT_BRUSH
);
847 dc
.SetBackgroundMode(wxTRANSPARENT
);
849 float x1
= (float)(GetX() - (GetWidth()/2.0));
850 float y1
= (float)(GetY() - (GetHeight()/2.0));
851 float x2
= (float)(GetX() + (GetWidth()/2.0));
852 float y2
= (float)(GetY() + (GetHeight()/2.0));
854 // Should subtract 1 pixel if drawing under Windows
861 dc
.SetPen(m_leftSidePen
);
862 dc
.DrawLine(x1
, y2
, x1
, y1
);
866 dc
.SetPen(m_topSidePen
);
867 dc
.DrawLine(x1
, y1
, x2
, y1
);
870 // For testing purposes, draw a rectangle so we know
871 // how big the division is.
872 // SetBrush(wxCYAN_BRUSH);
873 // wxRectangleShape::OnDraw(dc);
876 void wxDivisionShape::OnDrawContents(wxDC
& dc
)
878 wxCompositeShape::OnDrawContents(dc
);
881 bool wxDivisionShape::OnMovePre(wxDC
& dc
, float x
, float y
, float oldx
, float oldy
, bool display
)
883 float diffX
= x
- oldx
;
884 float diffY
= y
- oldy
;
885 wxNode
*node
= m_children
.First();
888 wxShape
*object
= (wxShape
*)node
->Data();
890 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
896 void wxDivisionShape::OnDragLeft(bool draw
, float x
, float y
, int keys
, int attachment
)
898 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
904 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
905 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
909 wxShape::OnDragLeft(draw
, x
, y
, keys
, attachment
);
912 void wxDivisionShape::OnBeginDragLeft(float x
, float y
, int keys
, int attachment
)
914 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
920 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
921 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
926 wxShape::OnBeginDragLeft(x
, y
, keys
, attachment
);
929 void wxDivisionShape::OnEndDragLeft(float x
, float y
, int keys
, int attachment
)
931 m_canvas
->ReleaseMouse();
932 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
938 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
939 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
944 wxClientDC
dc(GetCanvas());
945 GetCanvas()->PrepareDC(dc
);
947 dc
.SetLogicalFunction(wxCOPY
);
949 m_canvas
->Snap(&m_xpos
, &m_ypos
);
950 GetEventHandler()->OnMovePre(dc
, x
, y
, m_oldX
, m_oldY
);
952 ResetControlPoints();
955 GetEventHandler()->OnDrawControlPoints(dc
);
957 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
960 void wxDivisionShape::SetSize(float w
, float h
, bool recursive
)
964 wxRectangleShape::SetSize(w
, h
, recursive
);
967 void wxDivisionShape::CalculateSize()
971 void wxDivisionShape::Copy(wxShape
& copy
)
973 wxCompositeShape::Copy(copy
);
975 wxASSERT( copy
.IsKindOf(CLASSINFO(wxDivisionShape
)) ) ;
977 wxDivisionShape
& divisionCopy
= (wxDivisionShape
&) copy
;
979 divisionCopy
.m_leftSideStyle
= m_leftSideStyle
;
980 divisionCopy
.m_topSideStyle
= m_topSideStyle
;
981 divisionCopy
.m_leftSideColour
= m_leftSideColour
;
982 divisionCopy
.m_topSideColour
= m_topSideColour
;
984 divisionCopy
.m_leftSidePen
= m_leftSidePen
;
985 divisionCopy
.m_topSidePen
= m_topSidePen
;
986 divisionCopy
.m_handleSide
= m_handleSide
;
988 // Division geometry copying is handled at the wxCompositeShape level.
992 void wxDivisionShape::WritePrologAttributes(wxExpr
*clause
)
994 wxCompositeShape::WritePrologAttributes(clause
);
997 clause
->AddAttributeValue("left_side", (long)m_leftSide
->GetId());
999 clause
->AddAttributeValue("top_side", (long)m_topSide
->GetId());
1001 clause
->AddAttributeValue("right_side", (long)m_rightSide
->GetId());
1003 clause
->AddAttributeValue("bottom_side", (long)m_bottomSide
->GetId());
1005 clause
->AddAttributeValue("handle_side", (long)m_handleSide
);
1006 clause
->AddAttributeValueString("left_colour", m_leftSideColour
);
1007 clause
->AddAttributeValueString("top_colour", m_topSideColour
);
1008 clause
->AddAttributeValueString("left_style", m_leftSideStyle
);
1009 clause
->AddAttributeValueString("top_style", m_topSideStyle
);
1012 void wxDivisionShape::ReadPrologAttributes(wxExpr
*clause
)
1014 wxCompositeShape::ReadPrologAttributes(clause
);
1016 clause
->GetAttributeValue("handle_side", m_handleSide
);
1017 clause
->GetAttributeValue("left_colour", m_leftSideColour
);
1018 clause
->GetAttributeValue("top_colour", m_topSideColour
);
1019 clause
->GetAttributeValue("left_style", m_leftSideStyle
);
1020 clause
->GetAttributeValue("top_style", m_topSideStyle
);
1025 void wxDivisionShape::OnRightClick(float x
, float y
, int keys
, int attachment
)
1027 if (keys
& KEY_CTRL
)
1032 else if (keys & KEY_SHIFT)
1034 if (m_leftSide || m_topSide || m_rightSide || m_bottomSide)
1039 GetParent()->Draw(dc);
1052 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1053 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1060 // Divide wxHORIZONTALly or wxVERTICALly
1061 bool wxDivisionShape::Divide(int direction
)
1063 // Calculate existing top-left, bottom-right
1064 float x1
= (float)(GetX() - (GetWidth()/2.0));
1065 float y1
= (float)(GetY() - (GetHeight()/2.0));
1066 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1067 float oldWidth
= GetWidth();
1068 float oldHeight
= GetHeight();
1072 wxClientDC
dc(GetCanvas());
1073 GetCanvas()->PrepareDC(dc
);
1075 if (direction
== wxVERTICAL
)
1077 // Dividing vertically means notionally putting a horizontal line through it.
1078 // Break existing piece into two.
1079 float newXPos1
= GetX();
1080 float newYPos1
= (float)(y1
+ (GetHeight()/4.0));
1081 float newXPos2
= GetX();
1082 float newYPos2
= (float)(y1
+ (3.0*GetHeight()/4.0));
1083 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1084 newDivision
->Show(TRUE
);
1088 // Anything adjoining the bottom of this division now adjoins the
1089 // bottom of the new division.
1090 wxNode
*node
= compositeParent
->GetDivisions().First();
1093 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->Data();
1094 if (obj
->GetTopSide() == this)
1095 obj
->SetTopSide(newDivision
);
1096 node
= node
->Next();
1098 newDivision
->SetTopSide(this);
1099 newDivision
->SetBottomSide(m_bottomSide
);
1100 newDivision
->SetLeftSide(m_leftSide
);
1101 newDivision
->SetRightSide(m_rightSide
);
1102 m_bottomSide
= newDivision
;
1104 compositeParent
->GetDivisions().Append(newDivision
);
1106 // CHANGE: Need to insert this division at start of divisions in the object
1107 // list, because e.g.:
1109 // 2) Add contained object
1111 // Division is now receiving mouse events _before_ the contained object,
1112 // because it was added last (on top of all others)
1114 // Add after the image that visualizes the container
1115 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1117 m_handleSide
= DIVISION_SIDE_BOTTOM
;
1118 newDivision
->SetHandleSide(DIVISION_SIDE_TOP
);
1120 SetSize(oldWidth
, (float)(oldHeight
/2.0));
1121 Move(dc
, newXPos1
, newYPos1
);
1123 newDivision
->SetSize(oldWidth
, (float)(oldHeight
/2.0));
1124 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1128 // Dividing horizontally means notionally putting a vertical line through it.
1129 // Break existing piece into two.
1130 float newXPos1
= (float)(x1
+ (GetWidth()/4.0));
1131 float newYPos1
= GetY();
1132 float newXPos2
= (float)(x1
+ (3.0*GetWidth()/4.0));
1133 float newYPos2
= GetY();
1134 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1135 newDivision
->Show(TRUE
);
1139 // Anything adjoining the left of this division now adjoins the
1140 // left of the new division.
1141 wxNode
*node
= compositeParent
->GetDivisions().First();
1144 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->Data();
1145 if (obj
->GetLeftSide() == this)
1146 obj
->SetLeftSide(newDivision
);
1147 node
= node
->Next();
1149 newDivision
->SetTopSide(m_topSide
);
1150 newDivision
->SetBottomSide(m_bottomSide
);
1151 newDivision
->SetLeftSide(this);
1152 newDivision
->SetRightSide(m_rightSide
);
1153 m_rightSide
= newDivision
;
1155 compositeParent
->GetDivisions().Append(newDivision
);
1156 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1158 m_handleSide
= DIVISION_SIDE_RIGHT
;
1159 newDivision
->SetHandleSide(DIVISION_SIDE_LEFT
);
1161 SetSize((float)(oldWidth
/2.0), oldHeight
);
1162 Move(dc
, newXPos1
, newYPos1
);
1164 newDivision
->SetSize((float)(oldWidth
/2.0), oldHeight
);
1165 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1167 if (compositeParent
->Selected())
1169 compositeParent
->DeleteControlPoints(& dc
);
1170 compositeParent
->MakeControlPoints();
1171 compositeParent
->MakeMandatoryControlPoints();
1173 compositeParent
->Draw(dc
);
1177 // Make one control point for every visible line
1178 void wxDivisionShape::MakeControlPoints()
1180 MakeMandatoryControlPoints();
1183 void wxDivisionShape::MakeMandatoryControlPoints()
1187 GetBoundingBoxMax(&maxX
, &maxY
);
1193 x = (float)(-maxX/2.0);
1195 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1196 CONTROL_POINT_HORIZONTAL);
1197 m_canvas->AddShape(control);
1198 m_controlPoints.Append(control);
1203 y = (float)(-maxY/2.0);
1204 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1205 CONTROL_POINT_VERTICAL);
1206 m_canvas->AddShape(control);
1207 m_controlPoints.Append(control);
1210 switch (m_handleSide
)
1212 case DIVISION_SIDE_LEFT
:
1214 x
= (float)(-maxX
/2.0);
1216 direction
= CONTROL_POINT_HORIZONTAL
;
1219 case DIVISION_SIDE_TOP
:
1222 y
= (float)(-maxY
/2.0);
1223 direction
= CONTROL_POINT_VERTICAL
;
1226 case DIVISION_SIDE_RIGHT
:
1228 x
= (float)(maxX
/2.0);
1230 direction
= CONTROL_POINT_HORIZONTAL
;
1233 case DIVISION_SIDE_BOTTOM
:
1236 y
= (float)(maxY
/2.0);
1237 direction
= CONTROL_POINT_VERTICAL
;
1243 if (m_handleSide
!= DIVISION_SIDE_NONE
)
1245 wxDivisionControlPoint
*control
= new wxDivisionControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, x
, y
,
1247 m_canvas
->AddShape(control
);
1248 m_controlPoints
.Append(control
);
1252 void wxDivisionShape::ResetControlPoints()
1254 ResetMandatoryControlPoints();
1257 void wxDivisionShape::ResetMandatoryControlPoints()
1259 if (m_controlPoints
.Number() < 1)
1264 GetBoundingBoxMax(&maxX
, &maxY
);
1266 wxNode *node = m_controlPoints.First();
1269 wxDivisionControlPoint *control = (wxDivisionControlPoint *)node->Data();
1270 if (control->type == CONTROL_POINT_HORIZONTAL)
1272 control->xoffset = (float)(-maxX/2.0); control->m_yoffset = 0.0;
1274 else if (control->type == CONTROL_POINT_VERTICAL)
1276 control->xoffset = 0.0; control->m_yoffset = (float)(-maxY/2.0);
1278 node = node->Next();
1281 wxNode
*node
= m_controlPoints
.First();
1282 if ((m_handleSide
== DIVISION_SIDE_LEFT
) && node
)
1284 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1285 control
->m_xoffset
= (float)(-maxX
/2.0); control
->m_yoffset
= 0.0;
1288 if ((m_handleSide
== DIVISION_SIDE_TOP
) && node
)
1290 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1291 control
->m_xoffset
= 0.0; control
->m_yoffset
= (float)(-maxY
/2.0);
1294 if ((m_handleSide
== DIVISION_SIDE_RIGHT
) && node
)
1296 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1297 control
->m_xoffset
= (float)(maxX
/2.0); control
->m_yoffset
= 0.0;
1300 if ((m_handleSide
== DIVISION_SIDE_BOTTOM
) && node
)
1302 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1303 control
->m_xoffset
= 0.0; control
->m_yoffset
= (float)(maxY
/2.0);
1307 // Adjust a side, returning FALSE if it's not physically possible.
1308 bool wxDivisionShape::AdjustLeft(float left
, bool test
)
1310 float x2
= (float)(GetX() + (GetWidth()/2.0));
1317 float newW
= x2
- left
;
1318 float newX
= (float)(left
+ newW
/2.0);
1319 SetSize(newW
, GetHeight());
1321 wxClientDC
dc(GetCanvas());
1322 GetCanvas()->PrepareDC(dc
);
1324 Move(dc
, newX
, GetY());
1329 bool wxDivisionShape::AdjustTop(float top
, bool test
)
1331 float y2
= (float)(GetY() + (GetHeight()/2.0));
1338 float newH
= y2
- top
;
1339 float newY
= (float)(top
+ newH
/2.0);
1340 SetSize(GetWidth(), newH
);
1342 wxClientDC
dc(GetCanvas());
1343 GetCanvas()->PrepareDC(dc
);
1345 Move(dc
, GetX(), newY
);
1350 bool wxDivisionShape::AdjustRight(float right
, bool test
)
1352 float x1
= (float)(GetX() - (GetWidth()/2.0));
1359 float newW
= right
- x1
;
1360 float newX
= (float)(x1
+ newW
/2.0);
1361 SetSize(newW
, GetHeight());
1363 wxClientDC
dc(GetCanvas());
1364 GetCanvas()->PrepareDC(dc
);
1366 Move(dc
, newX
, GetY());
1371 bool wxDivisionShape::AdjustBottom(float bottom
, bool test
)
1373 float y1
= (float)(GetY() - (GetHeight()/2.0));
1380 float newH
= bottom
- y1
;
1381 float newY
= (float)(y1
+ newH
/2.0);
1382 SetSize(GetWidth(), newH
);
1384 wxClientDC
dc(GetCanvas());
1385 GetCanvas()->PrepareDC(dc
);
1387 Move(dc
, GetX(), newY
);
1392 wxDivisionControlPoint::wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, float size
, float the_xoffset
, float the_yoffset
, int the_type
):
1393 wxControlPoint(the_canvas
, object
, size
, the_xoffset
, the_yoffset
, the_type
)
1395 SetEraseObject(FALSE
);
1398 wxDivisionControlPoint::~wxDivisionControlPoint()
1402 static float originalX
= 0.0;
1403 static float originalY
= 0.0;
1404 static float originalW
= 0.0;
1405 static float originalH
= 0.0;
1407 // Implement resizing of canvas object
1408 void wxDivisionControlPoint::OnDragLeft(bool draw
, float x
, float y
, int keys
, int attachment
)
1410 wxControlPoint::OnDragLeft(draw
, x
, y
, keys
, attachment
);
1413 void wxDivisionControlPoint::OnBeginDragLeft(float x
, float y
, int keys
, int attachment
)
1415 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1416 originalX
= division
->GetX();
1417 originalY
= division
->GetY();
1418 originalW
= division
->GetWidth();
1419 originalH
= division
->GetHeight();
1421 wxControlPoint::OnBeginDragLeft(x
, y
, keys
, attachment
);
1424 void wxDivisionControlPoint::OnEndDragLeft(float x
, float y
, int keys
, int attachment
)
1426 wxControlPoint::OnEndDragLeft(x
, y
, keys
, attachment
);
1428 wxClientDC
dc(GetCanvas());
1429 GetCanvas()->PrepareDC(dc
);
1431 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1432 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)division
->GetParent();
1434 // Need to check it's within the bounds of the parent composite.
1435 float x1
= (float)(divisionParent
->GetX() - (divisionParent
->GetWidth()/2.0));
1436 float y1
= (float)(divisionParent
->GetY() - (divisionParent
->GetHeight()/2.0));
1437 float x2
= (float)(divisionParent
->GetX() + (divisionParent
->GetWidth()/2.0));
1438 float y2
= (float)(divisionParent
->GetY() + (divisionParent
->GetHeight()/2.0));
1440 // Need to check it has not made the division zero or negative width/height
1441 float dx1
= (float)(division
->GetX() - (division
->GetWidth()/2.0));
1442 float dy1
= (float)(division
->GetY() - (division
->GetHeight()/2.0));
1443 float dx2
= (float)(division
->GetX() + (division
->GetWidth()/2.0));
1444 float dy2
= (float)(division
->GetY() + (division
->GetHeight()/2.0));
1446 bool success
= TRUE
;
1447 switch (division
->GetHandleSide())
1449 case DIVISION_SIDE_LEFT
:
1451 if ((x
<= x1
) || (x
>= x2
) || (x
>= dx2
))
1453 // Try it out first...
1454 else if (!division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, TRUE
))
1457 division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, FALSE
);
1461 case DIVISION_SIDE_TOP
:
1463 if ((y
<= y1
) || (y
>= y2
) || (y
>= dy2
))
1465 else if (!division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, TRUE
))
1468 division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, FALSE
);
1472 case DIVISION_SIDE_RIGHT
:
1474 if ((x
<= x1
) || (x
>= x2
) || (x
<= dx1
))
1476 else if (!division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, TRUE
))
1479 division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, FALSE
);
1483 case DIVISION_SIDE_BOTTOM
:
1485 if ((y
<= y1
) || (y
>= y2
) || (y
<= dy1
))
1487 else if (!division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, TRUE
))
1490 division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, FALSE
);
1497 division
->SetSize(originalW
, originalH
);
1498 division
->Move(dc
, originalX
, originalY
);
1500 divisionParent
->Draw(dc
);
1501 division
->GetEventHandler()->OnDrawControlPoints(dc
);
1504 /* Resize adjoining divisions.
1506 Behaviour should be as follows:
1507 If right edge moves, find all objects whose left edge
1508 adjoins this object, and move left edge accordingly.
1509 If left..., move ... right.
1510 If top..., move ... bottom.
1511 If bottom..., move top.
1512 If size goes to zero or end position is other side of start position,
1513 resize to original size and return.
1515 bool wxDivisionShape::ResizeAdjoining(int side
, float newPos
, bool test
)
1517 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)GetParent();
1518 wxNode
*node
= divisionParent
->GetDivisions().First();
1521 wxDivisionShape
*division
= (wxDivisionShape
*)node
->Data();
1524 case DIVISION_SIDE_LEFT
:
1526 if (division
->m_rightSide
== this)
1528 bool success
= division
->AdjustRight(newPos
, test
);
1529 if (!success
&& test
)
1534 case DIVISION_SIDE_TOP
:
1536 if (division
->m_bottomSide
== this)
1538 bool success
= division
->AdjustBottom(newPos
, test
);
1539 if (!success
&& test
)
1544 case DIVISION_SIDE_RIGHT
:
1546 if (division
->m_leftSide
== this)
1548 bool success
= division
->AdjustLeft(newPos
, test
);
1549 if (!success
&& test
)
1554 case DIVISION_SIDE_BOTTOM
:
1556 if (division
->m_topSide
== this)
1558 bool success
= division
->AdjustTop(newPos
, test
);
1559 if (!success
&& test
)
1567 node
= node
->Next();
1574 * Popup menu for editing divisions
1578 void oglGraphicsDivisionMenuProc(wxMenu
& menu
, wxCommandEvent
& event
)
1580 wxDivisionShape
*division
= (wxDivisionShape
*)menu
.GetClientData();
1581 switch (event
.GetInt())
1583 case DIVISION_MENU_SPLIT_HORIZONTALLY
:
1585 division
->Divide(wxHORIZONTAL
);
1588 case DIVISION_MENU_SPLIT_VERTICALLY
:
1590 division
->Divide(wxVERTICAL
);
1593 case DIVISION_MENU_EDIT_LEFT_EDGE
:
1595 division
->EditEdge(DIVISION_SIDE_LEFT
);
1598 case DIVISION_MENU_EDIT_TOP_EDGE
:
1600 division
->EditEdge(DIVISION_SIDE_TOP
);
1608 void wxDivisionShape::EditEdge(int side
)
1610 wxMessageBox("EditEdge() not implemented", "OGL", wxOK
);
1613 wxBeginBusyCursor();
1615 wxPen
*currentPen
= NULL
;
1616 char **pColour
= NULL
;
1617 char **pStyle
= NULL
;
1618 if (side
== DIVISION_SIDE_LEFT
)
1620 currentPen
= m_leftSidePen
;
1621 pColour
= &m_leftSideColour
;
1622 pStyle
= &m_leftSideStyle
;
1626 currentPen
= m_topSidePen
;
1627 pColour
= &m_topSideColour
;
1628 pStyle
= &m_topSideStyle
;
1631 GraphicsForm
*form
= new GraphicsForm("Containers");
1632 int lineWidth
= currentPen
->GetWidth();
1634 form
->Add(wxMakeFormShort("Width", &lineWidth
, wxFORM_DEFAULT
, NULL
, NULL
, wxVERTICAL
,
1636 form
->Add(wxMakeFormString("Colour", pColour
, wxFORM_CHOICE
,
1637 new wxList(wxMakeConstraintStrings(
1661 NULL
), NULL
, wxVERTICAL
, 150));
1662 form
->Add(wxMakeFormString("Style", pStyle
, wxFORM_CHOICE
,
1663 new wxList(wxMakeConstraintStrings(
1670 NULL
), NULL
, wxVERTICAL
, 100));
1672 wxDialogBox
*dialog
= new wxDialogBox(m_canvas
->GetParent(), "Division properties", 10, 10, 500, 500);
1673 if (GraphicsLabelFont
)
1674 dialog
->SetLabelFont(GraphicsLabelFont
);
1675 if (GraphicsButtonFont
)
1676 dialog
->SetButtonFont(GraphicsButtonFont
);
1678 form
->AssociatePanel(dialog
);
1679 form
->dialog
= dialog
;
1682 dialog
->Centre(wxBOTH
);
1687 int lineStyle
= wxSOLID
;
1690 if (strcmp(*pStyle
, "Solid") == 0)
1691 lineStyle
= wxSOLID
;
1692 else if (strcmp(*pStyle
, "Dot") == 0)
1694 else if (strcmp(*pStyle
, "Short Dash") == 0)
1695 lineStyle
= wxSHORT_DASH
;
1696 else if (strcmp(*pStyle
, "Long Dash") == 0)
1697 lineStyle
= wxLONG_DASH
;
1698 else if (strcmp(*pStyle
, "Dot Dash") == 0)
1699 lineStyle
= wxDOT_DASH
;
1702 wxPen
*newPen
= wxThePenList
->FindOrCreatePen(*pColour
, lineWidth
, lineStyle
);
1705 if (side
== DIVISION_SIDE_LEFT
)
1706 m_leftSidePen
= newPen
;
1708 m_topSidePen
= newPen
;
1710 // Need to draw whole image again
1711 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1712 compositeParent
->Draw(dc
);
1717 void wxDivisionShape::PopupMenu(float x
, float y
)
1719 oglPopupDivisionMenu
->SetClientData((char *)this);
1721 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, TRUE
);
1723 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, FALSE
);
1725 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, TRUE
);
1727 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, FALSE
);
1730 m_canvas
->ViewStart(&x1
, &y1
);
1733 m_canvas
->GetScrollPixelsPerUnit(&unit_x
, &unit_y
);
1735 wxClientDC
dc(GetCanvas());
1736 GetCanvas()->PrepareDC(dc
);
1738 int mouse_x
= (int)(dc
.LogicalToDeviceX(x
- x1
*unit_x
));
1739 int mouse_y
= (int)(dc
.LogicalToDeviceY(y
- y1
*unit_y
));
1741 m_canvas
->PopupMenu(oglPopupDivisionMenu
, mouse_x
, mouse_y
);
1744 void wxDivisionShape::SetLeftSideColour(const wxString
& colour
)
1746 m_leftSideColour
= colour
;
1749 void wxDivisionShape::SetTopSideColour(const wxString
& colour
)
1751 m_topSideColour
= colour
;
1754 void wxDivisionShape::SetLeftSideStyle(const wxString
& style
)
1756 m_leftSideStyle
= style
;
1759 void wxDivisionShape::SetTopSideStyle(const wxString
& style
)
1761 m_topSideStyle
= style
;