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>
27 #include <wx/wxexpr.h>
36 // Sometimes, objects need to access the whole database to
37 // construct themselves.
38 wxExprDatabase
*GlobalwxExprDatabase
= NULL
;
40 // Popup menu for editing divisions
41 wxMenu
*oglPopupDivisionMenu
= NULL
;
44 * Division control point
47 class wxDivisionControlPoint
: public wxControlPoint
49 DECLARE_DYNAMIC_CLASS(wxDivisionControlPoint
)
51 wxDivisionControlPoint() {}
52 wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, double size
, double the_xoffset
, double the_yoffset
, int the_type
);
53 ~wxDivisionControlPoint();
55 void OnDragLeft(bool draw
, double x
, double y
, int keys
=0, int attachment
= 0);
56 void OnBeginDragLeft(double x
, double y
, int keys
=0, int attachment
= 0);
57 void OnEndDragLeft(double x
, double y
, int keys
=0, int attachment
= 0);
60 IMPLEMENT_DYNAMIC_CLASS(wxDivisionControlPoint
, wxControlPoint
)
67 IMPLEMENT_DYNAMIC_CLASS(wxCompositeShape
, wxRectangleShape
)
69 wxCompositeShape::wxCompositeShape(): wxRectangleShape(10.0, 10.0)
71 // selectable = FALSE;
76 wxCompositeShape::~wxCompositeShape()
78 wxNode
*node
= m_constraints
.First();
81 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->Data();
85 node
= m_children
.First();
88 wxShape
*object
= (wxShape
*)node
->Data();
89 wxNode
*next
= node
->Next();
96 void wxCompositeShape::OnDraw(wxDC
& dc
)
98 double x1
= (double)(m_xpos
- m_width
/2.0);
99 double y1
= (double)(m_ypos
- m_height
/2.0);
101 if (m_shadowMode
!= SHADOW_NONE
)
104 dc
.SetBrush(* m_shadowBrush
);
105 dc
.SetPen(* g_oglTransparentPen
);
107 if (m_cornerRadius
!= 0.0)
108 dc
.DrawRoundedRectangle(WXROUND(x1
+ m_shadowOffsetX
), WXROUND(y1
+ m_shadowOffsetY
),
109 WXROUND(m_width
), WXROUND(m_height
), m_cornerRadius
);
111 dc
.DrawRectangle(WXROUND(x1
+ m_shadowOffsetX
), WXROUND(y1
+ m_shadowOffsetY
), WXROUND(m_width
), WXROUND(m_height
));
115 void wxCompositeShape::OnDrawContents(wxDC
& dc
)
117 wxNode
*node
= m_children
.First();
120 wxShape
*object
= (wxShape
*)node
->Data();
122 object
->DrawLinks(dc
);
125 wxShape::OnDrawContents(dc
);
128 bool wxCompositeShape::OnMovePre(wxDC
& dc
, double x
, double y
, double oldx
, double oldy
, bool display
)
130 double diffX
= x
- oldx
;
131 double diffY
= y
- oldy
;
132 wxNode
*node
= m_children
.First();
135 wxShape
*object
= (wxShape
*)node
->Data();
138 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
145 void wxCompositeShape::OnErase(wxDC
& dc
)
147 wxRectangleShape::OnErase(dc
);
148 wxNode
*node
= m_children
.First();
151 wxShape
*object
= (wxShape
*)node
->Data();
157 static double objectStartX
= 0.0;
158 static double objectStartY
= 0.0;
160 void wxCompositeShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
164 m_canvas
->Snap(&xx
, &yy
);
165 double offsetX
= xx
- objectStartX
;
166 double offsetY
= yy
- objectStartY
;
168 wxClientDC
dc(GetCanvas());
169 GetCanvas()->PrepareDC(dc
);
171 dc
.SetLogicalFunction(OGLRBLF
);
172 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
173 dc
.SetPen(dottedPen
);
174 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
176 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
177 // wxShape::OnDragLeft(draw, x, y, keys, attachment);
180 void wxCompositeShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
185 wxClientDC
dc(GetCanvas());
186 GetCanvas()->PrepareDC(dc
);
190 dc
.SetLogicalFunction(OGLRBLF
);
192 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
193 dc
.SetPen(dottedPen
);
194 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
195 m_canvas
->CaptureMouse();
199 m_canvas
->Snap(&xx
, &yy
);
200 double offsetX
= xx
- objectStartX
;
201 double offsetY
= yy
- objectStartY
;
203 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
205 // wxShape::OnBeginDragLeft(x, y, keys, attachment);
208 void wxCompositeShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
210 // wxShape::OnEndDragLeft(x, y, keys, attachment);
212 wxClientDC
dc(GetCanvas());
213 GetCanvas()->PrepareDC(dc
);
215 m_canvas
->ReleaseMouse();
219 if (m_parent
) m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, 0);
223 dc
.SetLogicalFunction(wxCOPY
);
226 m_canvas
->Snap(&xx
, &yy
);
227 double offsetX
= xx
- objectStartX
;
228 double offsetY
= yy
- objectStartY
;
230 Move(dc
, GetX() + offsetX
, GetY() + offsetY
);
232 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
235 void wxCompositeShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
237 // If we get a ctrl-right click, this means send the message to
238 // the division, so we can invoke a user interface for dealing with regions.
241 wxNode
*node
= m_divisions
.First();
244 wxDivisionShape
*division
= (wxDivisionShape
*)node
->Data();
245 wxNode
*next
= node
->Next();
248 if (division
->HitTest(x
, y
, &attach
, &dist
))
250 division
->GetEventHandler()->OnRightClick(x
, y
, keys
, attach
);
259 void wxCompositeShape::SetSize(double w
, double h
, bool recursive
)
261 SetAttachmentSize(w
, h
);
263 double xScale
= (double)(w
/(wxMax(1.0, GetWidth())));
264 double yScale
= (double)(h
/(wxMax(1.0, GetHeight())));
269 if (!recursive
) return;
271 wxNode
*node
= m_children
.First();
273 wxClientDC
dc(GetCanvas());
274 GetCanvas()->PrepareDC(dc
);
276 double xBound
, yBound
;
279 wxShape
*object
= (wxShape
*)node
->Data();
281 // Scale the position first
282 double newX
= (double)(((object
->GetX() - GetX())*xScale
) + GetX());
283 double newY
= (double)(((object
->GetY() - GetY())*yScale
) + GetY());
285 object
->Move(dc
, newX
, newY
);
288 // Now set the scaled size
289 object
->GetBoundingBoxMin(&xBound
, &yBound
);
290 object
->SetSize(object
->GetFixedWidth() ? xBound
: xScale
*xBound
,
291 object
->GetFixedHeight() ? yBound
: yScale
*yBound
);
295 SetDefaultRegionSize();
298 void wxCompositeShape::AddChild(wxShape
*child
, wxShape
*addAfter
)
300 m_children
.Append(child
);
301 child
->SetParent(this);
304 // Ensure we add at the right position
306 child
->RemoveFromCanvas(m_canvas
);
307 child
->AddToCanvas(m_canvas
, addAfter
);
311 void wxCompositeShape::RemoveChild(wxShape
*child
)
313 m_children
.DeleteObject(child
);
314 m_divisions
.DeleteObject(child
);
315 RemoveChildFromConstraints(child
);
316 child
->SetParent(NULL
);
319 void wxCompositeShape::DeleteConstraintsInvolvingChild(wxShape
*child
)
321 wxNode
*node
= m_constraints
.First();
324 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->Data();
325 wxNode
*nextNode
= node
->Next();
327 if ((constraint
->m_constrainingObject
== child
) ||
328 constraint
->m_constrainedObjects
.Member(child
))
337 void wxCompositeShape::RemoveChildFromConstraints(wxShape
*child
)
339 wxNode
*node
= m_constraints
.First();
342 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->Data();
343 wxNode
*nextNode
= node
->Next();
345 if (constraint
->m_constrainedObjects
.Member(child
))
346 constraint
->m_constrainedObjects
.DeleteObject(child
);
347 if (constraint
->m_constrainingObject
== child
)
348 constraint
->m_constrainingObject
= NULL
;
350 // Delete the constraint if no participants left
351 if (!constraint
->m_constrainingObject
)
361 void wxCompositeShape::Copy(wxShape
& copy
)
363 wxRectangleShape::Copy(copy
);
365 wxASSERT( copy
.IsKindOf(CLASSINFO(wxCompositeShape
)) ) ;
367 wxCompositeShape
& compositeCopy
= (wxCompositeShape
&) copy
;
369 // Associate old and new copies for compositeCopying constraints and division geometry
370 oglObjectCopyMapping
.Append((long)this, &compositeCopy
);
373 wxNode
*node
= m_children
.First();
376 wxShape
*object
= (wxShape
*)node
->Data();
377 wxShape
*newObject
= object
->CreateNewCopy(FALSE
, FALSE
);
378 if (newObject
->GetId() == 0)
379 newObject
->SetId(NewId());
381 newObject
->SetParent(&compositeCopy
);
382 compositeCopy
.m_children
.Append(newObject
);
384 // Some m_children may be divisions
385 if (m_divisions
.Member(object
))
386 compositeCopy
.m_divisions
.Append(newObject
);
388 oglObjectCopyMapping
.Append((long)object
, newObject
);
393 // Copy the constraints
394 node
= m_constraints
.First();
397 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->Data();
399 wxShape
*newConstraining
= (wxShape
*)(oglObjectCopyMapping
.Find((long)constraint
->m_constrainingObject
)->Data());
401 wxList newConstrainedList
;
402 wxNode
*node2
= constraint
->m_constrainedObjects
.First();
405 wxShape
*constrainedObject
= (wxShape
*)node2
->Data();
406 wxShape
*newConstrained
= (wxShape
*)(oglObjectCopyMapping
.Find((long)constrainedObject
)->Data());
407 newConstrainedList
.Append(newConstrained
);
408 node2
= node2
->Next();
411 wxOGLConstraint
*newConstraint
= new wxOGLConstraint(constraint
->m_constraintType
, newConstraining
,
413 newConstraint
->m_constraintId
= constraint
->m_constraintId
;
414 if (constraint
->m_constraintName
)
416 newConstraint
->m_constraintName
= constraint
->m_constraintName
;
418 newConstraint
->SetSpacing(constraint
->m_xSpacing
, constraint
->m_ySpacing
);
419 compositeCopy
.m_constraints
.Append(newConstraint
);
424 // Now compositeCopy the division geometry
425 node
= m_divisions
.First();
428 wxDivisionShape
*division
= (wxDivisionShape
*)node
->Data();
429 wxNode
*node1
= oglObjectCopyMapping
.Find((long)division
);
430 wxNode
*leftNode
= NULL
;
431 wxNode
*topNode
= NULL
;
432 wxNode
*rightNode
= NULL
;
433 wxNode
*bottomNode
= NULL
;
434 if (division
->GetLeftSide())
435 leftNode
= oglObjectCopyMapping
.Find((long)division
->GetLeftSide());
436 if (division
->GetTopSide())
437 topNode
= oglObjectCopyMapping
.Find((long)division
->GetTopSide());
438 if (division
->GetRightSide())
439 rightNode
= oglObjectCopyMapping
.Find((long)division
->GetRightSide());
440 if (division
->GetBottomSide())
441 bottomNode
= oglObjectCopyMapping
.Find((long)division
->GetBottomSide());
444 wxDivisionShape
*newDivision
= (wxDivisionShape
*)node1
->Data();
446 newDivision
->SetLeftSide((wxDivisionShape
*)leftNode
->Data());
448 newDivision
->SetTopSide((wxDivisionShape
*)topNode
->Data());
450 newDivision
->SetRightSide((wxDivisionShape
*)rightNode
->Data());
452 newDivision
->SetBottomSide((wxDivisionShape
*)bottomNode
->Data());
458 wxOGLConstraint
*wxCompositeShape::AddConstraint(wxOGLConstraint
*constraint
)
460 m_constraints
.Append(constraint
);
461 if (constraint
->m_constraintId
== 0)
462 constraint
->m_constraintId
= NewId();
466 wxOGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxList
& constrained
)
468 wxOGLConstraint
*constraint
= new wxOGLConstraint(type
, constraining
, constrained
);
469 if (constraint
->m_constraintId
== 0)
470 constraint
->m_constraintId
= NewId();
471 m_constraints
.Append(constraint
);
475 wxOGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxShape
*constrained
)
478 l
.Append(constrained
);
479 wxOGLConstraint
*constraint
= new wxOGLConstraint(type
, constraining
, l
);
480 if (constraint
->m_constraintId
== 0)
481 constraint
->m_constraintId
= NewId();
482 m_constraints
.Append(constraint
);
486 wxOGLConstraint
*wxCompositeShape::FindConstraint(long cId
, wxCompositeShape
**actualComposite
)
488 wxNode
*node
= m_constraints
.First();
491 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->Data();
492 if (constraint
->m_constraintId
== cId
)
495 *actualComposite
= this;
500 // If not found, try children.
501 node
= m_children
.First();
504 wxShape
*child
= (wxShape
*)node
->Data();
505 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
507 wxOGLConstraint
*constraint
= ((wxCompositeShape
*)child
)->FindConstraint(cId
, actualComposite
);
511 *actualComposite
= (wxCompositeShape
*)child
;
520 void wxCompositeShape::DeleteConstraint(wxOGLConstraint
*constraint
)
522 m_constraints
.DeleteObject(constraint
);
526 void wxCompositeShape::CalculateSize()
528 double maxX
= (double) -999999.9;
529 double maxY
= (double) -999999.9;
530 double minX
= (double) 999999.9;
531 double minY
= (double) 999999.9;
534 wxNode
*node
= m_children
.First();
537 wxShape
*object
= (wxShape
*)node
->Data();
539 // Recalculate size of composite objects because may not conform
540 // to size it was set to - depends on the children.
541 object
->CalculateSize();
543 object
->GetBoundingBoxMax(&w
, &h
);
544 if ((object
->GetX() + (w
/2.0)) > maxX
)
545 maxX
= (double)(object
->GetX() + (w
/2.0));
546 if ((object
->GetX() - (w
/2.0)) < minX
)
547 minX
= (double)(object
->GetX() - (w
/2.0));
548 if ((object
->GetY() + (h
/2.0)) > maxY
)
549 maxY
= (double)(object
->GetY() + (h
/2.0));
550 if ((object
->GetY() - (h
/2.0)) < minY
)
551 minY
= (double)(object
->GetY() - (h
/2.0));
555 m_width
= maxX
- minX
;
556 m_height
= maxY
- minY
;
557 m_xpos
= (double)(m_width
/2.0 + minX
);
558 m_ypos
= (double)(m_height
/2.0 + minY
);
561 bool wxCompositeShape::Recompute()
563 int noIterations
= 0;
565 while (changed
&& (noIterations
< 500))
567 changed
= Constrain();
573 cerr << "Warning: constraint algorithm failed after 500 iterations.\n";
579 bool wxCompositeShape::Constrain()
583 bool changed
= FALSE
;
584 wxNode
*node
= m_children
.First();
587 wxShape
*object
= (wxShape
*)node
->Data();
588 if (object
->Constrain())
593 node
= m_constraints
.First();
596 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->Data();
597 if (constraint
->Evaluate()) changed
= TRUE
;
604 void wxCompositeShape::WriteAttributes(wxExpr
*clause
)
606 wxRectangleShape::WriteAttributes(clause
);
608 // clause->AddAttributeValue("selectable", (long)selectable);
610 // Output constraints as constraint1 = (...), constraint2 = (...), etc.
611 int constraintNo
= 1;
612 char m_constraintNameBuf
[20];
613 wxNode
*node
= m_constraints
.First();
616 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->Data();
617 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
619 // Each constraint is stored in the form
620 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
621 wxExpr
*constraintExpr
= new wxExpr(wxExprList
);
622 constraintExpr
->Append(new wxExpr((long)constraint
->m_constraintType
));
623 constraintExpr
->Append(new wxExpr(wxExprString
, constraint
->m_constraintName
));
624 constraintExpr
->Append(new wxExpr(constraint
->m_constraintId
));
625 constraintExpr
->Append(new wxExpr(constraint
->m_xSpacing
));
626 constraintExpr
->Append(new wxExpr(constraint
->m_ySpacing
));
627 constraintExpr
->Append(new wxExpr(constraint
->m_constrainingObject
->GetId()));
629 wxExpr
*objectList
= new wxExpr(wxExprList
);
630 wxNode
*node1
= constraint
->m_constrainedObjects
.First();
633 wxShape
*obj
= (wxShape
*)node1
->Data();
634 objectList
->Append(new wxExpr(obj
->GetId()));
635 node1
= node1
->Next();
637 constraintExpr
->Append(objectList
);
639 clause
->AddAttributeValue(m_constraintNameBuf
, constraintExpr
);
645 // Write the ids of all the child images
646 wxExpr
*childrenExpr
= new wxExpr(wxExprList
);
647 node
= m_children
.First();
650 wxShape
*child
= (wxShape
*)node
->Data();
651 childrenExpr
->Append(new wxExpr(child
->GetId()));
654 clause
->AddAttributeValue("children", childrenExpr
);
656 // Write the ids of all the division images
657 if (m_divisions
.Number() > 0)
659 wxExpr
*divisionsExpr
= new wxExpr(wxExprList
);
660 node
= m_divisions
.First();
663 wxShape
*child
= (wxShape
*)node
->Data();
664 divisionsExpr
->Append(new wxExpr(child
->GetId()));
667 clause
->AddAttributeValue("divisions", divisionsExpr
);
671 // Problem. Child images are always written AFTER the parent
672 // so as to be able to link up to parent. So we may not be able
673 // to find the constraint participants until we've read everything
674 // in. Need to have another pass for composites.
675 void wxCompositeShape::ReadAttributes(wxExpr
*clause
)
677 wxRectangleShape::ReadAttributes(clause
);
679 // clause->GetAttributeValue("selectable", selectable);
682 void wxCompositeShape::ReadConstraints(wxExpr
*clause
, wxExprDatabase
*database
)
684 // Constraints are output as constraint1 = (...), constraint2 = (...), etc.
685 int constraintNo
= 1;
686 char m_constraintNameBuf
[20];
687 bool haveConstraints
= TRUE
;
689 while (haveConstraints
)
691 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
692 wxExpr
*constraintExpr
= NULL
;
693 clause
->GetAttributeValue(m_constraintNameBuf
, &constraintExpr
);
696 haveConstraints
= FALSE
;
700 double cXSpacing
= 0.0;
701 double cYSpacing
= 0.0;
704 wxShape
*m_constrainingObject
= NULL
;
705 wxList m_constrainedObjects
;
707 // Each constraint is stored in the form
708 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
710 wxExpr
*typeExpr
= constraintExpr
->Nth(0);
711 wxExpr
*nameExpr
= constraintExpr
->Nth(1);
712 wxExpr
*idExpr
= constraintExpr
->Nth(2);
713 wxExpr
*xExpr
= constraintExpr
->Nth(3);
714 wxExpr
*yExpr
= constraintExpr
->Nth(4);
715 wxExpr
*constrainingExpr
= constraintExpr
->Nth(5);
716 wxExpr
*constrainedExpr
= constraintExpr
->Nth(6);
718 cType
= (int)typeExpr
->IntegerValue();
719 cXSpacing
= xExpr
->RealValue();
720 cYSpacing
= yExpr
->RealValue();
721 cName
= nameExpr
->StringValue();
722 cId
= idExpr
->IntegerValue();
724 wxExpr
*objExpr1
= database
->HashFind("node_image", constrainingExpr
->IntegerValue());
725 if (objExpr1
&& objExpr1
->GetClientData())
726 m_constrainingObject
= (wxShape
*)objExpr1
->GetClientData();
728 wxFatalError("Couldn't find constraining image of composite.", "Object graphics error");
731 wxExpr
*currentIdExpr
= constrainedExpr
->Nth(i
);
732 while (currentIdExpr
)
734 long currentId
= currentIdExpr
->IntegerValue();
735 wxExpr
*objExpr2
= database
->HashFind("node_image", currentId
);
736 if (objExpr2
&& objExpr2
->GetClientData())
738 m_constrainedObjects
.Append((wxShape
*)objExpr2
->GetClientData());
742 wxFatalError("Couldn't find constrained image of composite.", "Object graphics error");
746 currentIdExpr
= constrainedExpr
->Nth(i
);
748 wxOGLConstraint
*newConstraint
= AddConstraint(cType
, m_constrainingObject
, m_constrainedObjects
);
749 newConstraint
->SetSpacing(cXSpacing
, cYSpacing
);
750 newConstraint
->m_constraintId
= cId
;
751 newConstraint
->m_constraintName
= (const char*) cName
;
757 // Make this composite into a container by creating one wxDivisionShape
758 void wxCompositeShape::MakeContainer()
760 wxDivisionShape
*division
= OnCreateDivision();
761 m_divisions
.Append(division
);
764 division
->SetSize(m_width
, m_height
);
766 wxClientDC
dc(GetCanvas());
767 GetCanvas()->PrepareDC(dc
);
769 division
->Move(dc
, GetX(), GetY());
771 division
->Show(TRUE
);
774 wxDivisionShape
*wxCompositeShape::OnCreateDivision()
776 return new wxDivisionShape
;
779 wxShape
*wxCompositeShape::FindContainerImage()
781 wxNode
*node
= m_children
.First();
784 wxShape
*child
= (wxShape
*)node
->Data();
785 if (!m_divisions
.Member(child
))
792 // Returns TRUE if division is a descendant of this container
793 bool wxCompositeShape::ContainsDivision(wxDivisionShape
*division
)
795 if (m_divisions
.Member(division
))
797 wxNode
*node
= m_children
.First();
800 wxShape
*child
= (wxShape
*)node
->Data();
801 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
803 bool ans
= ((wxCompositeShape
*)child
)->ContainsDivision(division
);
817 IMPLEMENT_DYNAMIC_CLASS(wxDivisionShape
, wxCompositeShape
)
819 wxDivisionShape::wxDivisionShape()
821 SetSensitivityFilter(OP_CLICK_LEFT
| OP_CLICK_RIGHT
| OP_DRAG_RIGHT
);
822 SetCentreResize(FALSE
);
823 SetAttachmentMode(TRUE
);
828 m_handleSide
= DIVISION_SIDE_NONE
;
829 m_leftSidePen
= wxBLACK_PEN
;
830 m_topSidePen
= wxBLACK_PEN
;
831 m_leftSideColour
= "BLACK";
832 m_topSideColour
= "BLACK";
833 m_leftSideStyle
= "Solid";
834 m_topSideStyle
= "Solid";
838 wxDivisionShape::~wxDivisionShape()
842 void wxDivisionShape::OnDraw(wxDC
& dc
)
844 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
845 dc
.SetBackgroundMode(wxTRANSPARENT
);
847 double x1
= (double)(GetX() - (GetWidth()/2.0));
848 double y1
= (double)(GetY() - (GetHeight()/2.0));
849 double x2
= (double)(GetX() + (GetWidth()/2.0));
850 double y2
= (double)(GetY() + (GetHeight()/2.0));
852 // Should subtract 1 pixel if drawing under Windows
859 dc
.SetPen(* m_leftSidePen
);
860 dc
.DrawLine(WXROUND(x1
), WXROUND(y2
), WXROUND(x1
), WXROUND(y1
));
864 dc
.SetPen(* m_topSidePen
);
865 dc
.DrawLine(WXROUND(x1
), WXROUND(y1
), WXROUND(x2
), WXROUND(y1
));
868 // For testing purposes, draw a rectangle so we know
869 // how big the division is.
870 // SetBrush(* wxCYAN_BRUSH);
871 // wxRectangleShape::OnDraw(dc);
874 void wxDivisionShape::OnDrawContents(wxDC
& dc
)
876 wxCompositeShape::OnDrawContents(dc
);
879 bool wxDivisionShape::OnMovePre(wxDC
& dc
, double x
, double y
, double oldx
, double oldy
, bool display
)
881 double diffX
= x
- oldx
;
882 double diffY
= y
- oldy
;
883 wxNode
*node
= m_children
.First();
886 wxShape
*object
= (wxShape
*)node
->Data();
888 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
894 void wxDivisionShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
896 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
902 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
903 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
907 wxShape::OnDragLeft(draw
, x
, y
, keys
, attachment
);
910 void wxDivisionShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
912 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
918 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
919 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
924 wxShape::OnBeginDragLeft(x
, y
, keys
, attachment
);
927 void wxDivisionShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
929 m_canvas
->ReleaseMouse();
930 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
936 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
937 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
942 wxClientDC
dc(GetCanvas());
943 GetCanvas()->PrepareDC(dc
);
945 dc
.SetLogicalFunction(wxCOPY
);
947 m_canvas
->Snap(&m_xpos
, &m_ypos
);
948 GetEventHandler()->OnMovePre(dc
, x
, y
, m_oldX
, m_oldY
);
950 ResetControlPoints();
953 GetEventHandler()->OnDrawControlPoints(dc
);
955 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
958 void wxDivisionShape::SetSize(double w
, double h
, bool recursive
)
962 wxRectangleShape::SetSize(w
, h
, recursive
);
965 void wxDivisionShape::CalculateSize()
969 void wxDivisionShape::Copy(wxShape
& copy
)
971 wxCompositeShape::Copy(copy
);
973 wxASSERT( copy
.IsKindOf(CLASSINFO(wxDivisionShape
)) ) ;
975 wxDivisionShape
& divisionCopy
= (wxDivisionShape
&) copy
;
977 divisionCopy
.m_leftSideStyle
= m_leftSideStyle
;
978 divisionCopy
.m_topSideStyle
= m_topSideStyle
;
979 divisionCopy
.m_leftSideColour
= m_leftSideColour
;
980 divisionCopy
.m_topSideColour
= m_topSideColour
;
982 divisionCopy
.m_leftSidePen
= m_leftSidePen
;
983 divisionCopy
.m_topSidePen
= m_topSidePen
;
984 divisionCopy
.m_handleSide
= m_handleSide
;
986 // Division geometry copying is handled at the wxCompositeShape level.
990 void wxDivisionShape::WriteAttributes(wxExpr
*clause
)
992 wxCompositeShape::WriteAttributes(clause
);
995 clause
->AddAttributeValue("left_side", (long)m_leftSide
->GetId());
997 clause
->AddAttributeValue("top_side", (long)m_topSide
->GetId());
999 clause
->AddAttributeValue("right_side", (long)m_rightSide
->GetId());
1001 clause
->AddAttributeValue("bottom_side", (long)m_bottomSide
->GetId());
1003 clause
->AddAttributeValue("handle_side", (long)m_handleSide
);
1004 clause
->AddAttributeValueString("left_colour", m_leftSideColour
);
1005 clause
->AddAttributeValueString("top_colour", m_topSideColour
);
1006 clause
->AddAttributeValueString("left_style", m_leftSideStyle
);
1007 clause
->AddAttributeValueString("top_style", m_topSideStyle
);
1010 void wxDivisionShape::ReadAttributes(wxExpr
*clause
)
1012 wxCompositeShape::ReadAttributes(clause
);
1014 clause
->GetAttributeValue("handle_side", m_handleSide
);
1015 clause
->GetAttributeValue("left_colour", m_leftSideColour
);
1016 clause
->GetAttributeValue("top_colour", m_topSideColour
);
1017 clause
->GetAttributeValue("left_style", m_leftSideStyle
);
1018 clause
->GetAttributeValue("top_style", m_topSideStyle
);
1023 void wxDivisionShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
1025 if (keys
& KEY_CTRL
)
1030 else if (keys & KEY_SHIFT)
1032 if (m_leftSide || m_topSide || m_rightSide || m_bottomSide)
1037 GetParent()->Draw(dc);
1050 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1051 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1058 // Divide wxHORIZONTALly or wxVERTICALly
1059 bool wxDivisionShape::Divide(int direction
)
1061 // Calculate existing top-left, bottom-right
1062 double x1
= (double)(GetX() - (GetWidth()/2.0));
1063 double y1
= (double)(GetY() - (GetHeight()/2.0));
1064 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1065 double oldWidth
= GetWidth();
1066 double oldHeight
= GetHeight();
1070 wxClientDC
dc(GetCanvas());
1071 GetCanvas()->PrepareDC(dc
);
1073 if (direction
== wxVERTICAL
)
1075 // Dividing vertically means notionally putting a horizontal line through it.
1076 // Break existing piece into two.
1077 double newXPos1
= GetX();
1078 double newYPos1
= (double)(y1
+ (GetHeight()/4.0));
1079 double newXPos2
= GetX();
1080 double newYPos2
= (double)(y1
+ (3.0*GetHeight()/4.0));
1081 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1082 newDivision
->Show(TRUE
);
1086 // Anything adjoining the bottom of this division now adjoins the
1087 // bottom of the new division.
1088 wxNode
*node
= compositeParent
->GetDivisions().First();
1091 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->Data();
1092 if (obj
->GetTopSide() == this)
1093 obj
->SetTopSide(newDivision
);
1094 node
= node
->Next();
1096 newDivision
->SetTopSide(this);
1097 newDivision
->SetBottomSide(m_bottomSide
);
1098 newDivision
->SetLeftSide(m_leftSide
);
1099 newDivision
->SetRightSide(m_rightSide
);
1100 m_bottomSide
= newDivision
;
1102 compositeParent
->GetDivisions().Append(newDivision
);
1104 // CHANGE: Need to insert this division at start of divisions in the object
1105 // list, because e.g.:
1107 // 2) Add contained object
1109 // Division is now receiving mouse events _before_ the contained object,
1110 // because it was added last (on top of all others)
1112 // Add after the image that visualizes the container
1113 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1115 m_handleSide
= DIVISION_SIDE_BOTTOM
;
1116 newDivision
->SetHandleSide(DIVISION_SIDE_TOP
);
1118 SetSize(oldWidth
, (double)(oldHeight
/2.0));
1119 Move(dc
, newXPos1
, newYPos1
);
1121 newDivision
->SetSize(oldWidth
, (double)(oldHeight
/2.0));
1122 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1126 // Dividing horizontally means notionally putting a vertical line through it.
1127 // Break existing piece into two.
1128 double newXPos1
= (double)(x1
+ (GetWidth()/4.0));
1129 double newYPos1
= GetY();
1130 double newXPos2
= (double)(x1
+ (3.0*GetWidth()/4.0));
1131 double newYPos2
= GetY();
1132 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1133 newDivision
->Show(TRUE
);
1137 // Anything adjoining the left of this division now adjoins the
1138 // left of the new division.
1139 wxNode
*node
= compositeParent
->GetDivisions().First();
1142 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->Data();
1143 if (obj
->GetLeftSide() == this)
1144 obj
->SetLeftSide(newDivision
);
1145 node
= node
->Next();
1147 newDivision
->SetTopSide(m_topSide
);
1148 newDivision
->SetBottomSide(m_bottomSide
);
1149 newDivision
->SetLeftSide(this);
1150 newDivision
->SetRightSide(m_rightSide
);
1151 m_rightSide
= newDivision
;
1153 compositeParent
->GetDivisions().Append(newDivision
);
1154 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1156 m_handleSide
= DIVISION_SIDE_RIGHT
;
1157 newDivision
->SetHandleSide(DIVISION_SIDE_LEFT
);
1159 SetSize((double)(oldWidth
/2.0), oldHeight
);
1160 Move(dc
, newXPos1
, newYPos1
);
1162 newDivision
->SetSize((double)(oldWidth
/2.0), oldHeight
);
1163 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1165 if (compositeParent
->Selected())
1167 compositeParent
->DeleteControlPoints(& dc
);
1168 compositeParent
->MakeControlPoints();
1169 compositeParent
->MakeMandatoryControlPoints();
1171 compositeParent
->Draw(dc
);
1175 // Make one control point for every visible line
1176 void wxDivisionShape::MakeControlPoints()
1178 MakeMandatoryControlPoints();
1181 void wxDivisionShape::MakeMandatoryControlPoints()
1185 GetBoundingBoxMax(&maxX
, &maxY
);
1191 x = (double)(-maxX/2.0);
1193 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1194 CONTROL_POINT_HORIZONTAL);
1195 m_canvas->AddShape(control);
1196 m_controlPoints.Append(control);
1201 y = (double)(-maxY/2.0);
1202 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1203 CONTROL_POINT_VERTICAL);
1204 m_canvas->AddShape(control);
1205 m_controlPoints.Append(control);
1208 switch (m_handleSide
)
1210 case DIVISION_SIDE_LEFT
:
1212 x
= (double)(-maxX
/2.0);
1214 direction
= CONTROL_POINT_HORIZONTAL
;
1217 case DIVISION_SIDE_TOP
:
1220 y
= (double)(-maxY
/2.0);
1221 direction
= CONTROL_POINT_VERTICAL
;
1224 case DIVISION_SIDE_RIGHT
:
1226 x
= (double)(maxX
/2.0);
1228 direction
= CONTROL_POINT_HORIZONTAL
;
1231 case DIVISION_SIDE_BOTTOM
:
1234 y
= (double)(maxY
/2.0);
1235 direction
= CONTROL_POINT_VERTICAL
;
1241 if (m_handleSide
!= DIVISION_SIDE_NONE
)
1243 wxDivisionControlPoint
*control
= new wxDivisionControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, x
, y
,
1245 m_canvas
->AddShape(control
);
1246 m_controlPoints
.Append(control
);
1250 void wxDivisionShape::ResetControlPoints()
1252 ResetMandatoryControlPoints();
1255 void wxDivisionShape::ResetMandatoryControlPoints()
1257 if (m_controlPoints
.Number() < 1)
1262 GetBoundingBoxMax(&maxX
, &maxY
);
1264 wxNode *node = m_controlPoints.First();
1267 wxDivisionControlPoint *control = (wxDivisionControlPoint *)node->Data();
1268 if (control->type == CONTROL_POINT_HORIZONTAL)
1270 control->xoffset = (double)(-maxX/2.0); control->m_yoffset = 0.0;
1272 else if (control->type == CONTROL_POINT_VERTICAL)
1274 control->xoffset = 0.0; control->m_yoffset = (double)(-maxY/2.0);
1276 node = node->Next();
1279 wxNode
*node
= m_controlPoints
.First();
1280 if ((m_handleSide
== DIVISION_SIDE_LEFT
) && node
)
1282 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1283 control
->m_xoffset
= (double)(-maxX
/2.0); control
->m_yoffset
= 0.0;
1286 if ((m_handleSide
== DIVISION_SIDE_TOP
) && node
)
1288 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1289 control
->m_xoffset
= 0.0; control
->m_yoffset
= (double)(-maxY
/2.0);
1292 if ((m_handleSide
== DIVISION_SIDE_RIGHT
) && node
)
1294 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1295 control
->m_xoffset
= (double)(maxX
/2.0); control
->m_yoffset
= 0.0;
1298 if ((m_handleSide
== DIVISION_SIDE_BOTTOM
) && node
)
1300 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1301 control
->m_xoffset
= 0.0; control
->m_yoffset
= (double)(maxY
/2.0);
1305 // Adjust a side, returning FALSE if it's not physically possible.
1306 bool wxDivisionShape::AdjustLeft(double left
, bool test
)
1308 double x2
= (double)(GetX() + (GetWidth()/2.0));
1315 double newW
= x2
- left
;
1316 double newX
= (double)(left
+ newW
/2.0);
1317 SetSize(newW
, GetHeight());
1319 wxClientDC
dc(GetCanvas());
1320 GetCanvas()->PrepareDC(dc
);
1322 Move(dc
, newX
, GetY());
1327 bool wxDivisionShape::AdjustTop(double top
, bool test
)
1329 double y2
= (double)(GetY() + (GetHeight()/2.0));
1336 double newH
= y2
- top
;
1337 double newY
= (double)(top
+ newH
/2.0);
1338 SetSize(GetWidth(), newH
);
1340 wxClientDC
dc(GetCanvas());
1341 GetCanvas()->PrepareDC(dc
);
1343 Move(dc
, GetX(), newY
);
1348 bool wxDivisionShape::AdjustRight(double right
, bool test
)
1350 double x1
= (double)(GetX() - (GetWidth()/2.0));
1357 double newW
= right
- x1
;
1358 double newX
= (double)(x1
+ newW
/2.0);
1359 SetSize(newW
, GetHeight());
1361 wxClientDC
dc(GetCanvas());
1362 GetCanvas()->PrepareDC(dc
);
1364 Move(dc
, newX
, GetY());
1369 bool wxDivisionShape::AdjustBottom(double bottom
, bool test
)
1371 double y1
= (double)(GetY() - (GetHeight()/2.0));
1378 double newH
= bottom
- y1
;
1379 double newY
= (double)(y1
+ newH
/2.0);
1380 SetSize(GetWidth(), newH
);
1382 wxClientDC
dc(GetCanvas());
1383 GetCanvas()->PrepareDC(dc
);
1385 Move(dc
, GetX(), newY
);
1390 wxDivisionControlPoint::wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, double size
, double the_xoffset
, double the_yoffset
, int the_type
):
1391 wxControlPoint(the_canvas
, object
, size
, the_xoffset
, the_yoffset
, the_type
)
1393 SetEraseObject(FALSE
);
1396 wxDivisionControlPoint::~wxDivisionControlPoint()
1400 static double originalX
= 0.0;
1401 static double originalY
= 0.0;
1402 static double originalW
= 0.0;
1403 static double originalH
= 0.0;
1405 // Implement resizing of canvas object
1406 void wxDivisionControlPoint::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
1408 wxControlPoint::OnDragLeft(draw
, x
, y
, keys
, attachment
);
1411 void wxDivisionControlPoint::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
1413 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1414 originalX
= division
->GetX();
1415 originalY
= division
->GetY();
1416 originalW
= division
->GetWidth();
1417 originalH
= division
->GetHeight();
1419 wxControlPoint::OnBeginDragLeft(x
, y
, keys
, attachment
);
1422 void wxDivisionControlPoint::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
1424 wxControlPoint::OnEndDragLeft(x
, y
, keys
, attachment
);
1426 wxClientDC
dc(GetCanvas());
1427 GetCanvas()->PrepareDC(dc
);
1429 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1430 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)division
->GetParent();
1432 // Need to check it's within the bounds of the parent composite.
1433 double x1
= (double)(divisionParent
->GetX() - (divisionParent
->GetWidth()/2.0));
1434 double y1
= (double)(divisionParent
->GetY() - (divisionParent
->GetHeight()/2.0));
1435 double x2
= (double)(divisionParent
->GetX() + (divisionParent
->GetWidth()/2.0));
1436 double y2
= (double)(divisionParent
->GetY() + (divisionParent
->GetHeight()/2.0));
1438 // Need to check it has not made the division zero or negative width/height
1439 double dx1
= (double)(division
->GetX() - (division
->GetWidth()/2.0));
1440 double dy1
= (double)(division
->GetY() - (division
->GetHeight()/2.0));
1441 double dx2
= (double)(division
->GetX() + (division
->GetWidth()/2.0));
1442 double dy2
= (double)(division
->GetY() + (division
->GetHeight()/2.0));
1444 bool success
= TRUE
;
1445 switch (division
->GetHandleSide())
1447 case DIVISION_SIDE_LEFT
:
1449 if ((x
<= x1
) || (x
>= x2
) || (x
>= dx2
))
1451 // Try it out first...
1452 else if (!division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, TRUE
))
1455 division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, FALSE
);
1459 case DIVISION_SIDE_TOP
:
1461 if ((y
<= y1
) || (y
>= y2
) || (y
>= dy2
))
1463 else if (!division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, TRUE
))
1466 division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, FALSE
);
1470 case DIVISION_SIDE_RIGHT
:
1472 if ((x
<= x1
) || (x
>= x2
) || (x
<= dx1
))
1474 else if (!division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, TRUE
))
1477 division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, FALSE
);
1481 case DIVISION_SIDE_BOTTOM
:
1483 if ((y
<= y1
) || (y
>= y2
) || (y
<= dy1
))
1485 else if (!division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, TRUE
))
1488 division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, FALSE
);
1495 division
->SetSize(originalW
, originalH
);
1496 division
->Move(dc
, originalX
, originalY
);
1498 divisionParent
->Draw(dc
);
1499 division
->GetEventHandler()->OnDrawControlPoints(dc
);
1502 /* Resize adjoining divisions.
1504 Behaviour should be as follows:
1505 If right edge moves, find all objects whose left edge
1506 adjoins this object, and move left edge accordingly.
1507 If left..., move ... right.
1508 If top..., move ... bottom.
1509 If bottom..., move top.
1510 If size goes to zero or end position is other side of start position,
1511 resize to original size and return.
1513 bool wxDivisionShape::ResizeAdjoining(int side
, double newPos
, bool test
)
1515 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)GetParent();
1516 wxNode
*node
= divisionParent
->GetDivisions().First();
1519 wxDivisionShape
*division
= (wxDivisionShape
*)node
->Data();
1522 case DIVISION_SIDE_LEFT
:
1524 if (division
->m_rightSide
== this)
1526 bool success
= division
->AdjustRight(newPos
, test
);
1527 if (!success
&& test
)
1532 case DIVISION_SIDE_TOP
:
1534 if (division
->m_bottomSide
== this)
1536 bool success
= division
->AdjustBottom(newPos
, test
);
1537 if (!success
&& test
)
1542 case DIVISION_SIDE_RIGHT
:
1544 if (division
->m_leftSide
== this)
1546 bool success
= division
->AdjustLeft(newPos
, test
);
1547 if (!success
&& test
)
1552 case DIVISION_SIDE_BOTTOM
:
1554 if (division
->m_topSide
== this)
1556 bool success
= division
->AdjustTop(newPos
, test
);
1557 if (!success
&& test
)
1565 node
= node
->Next();
1572 * Popup menu for editing divisions
1576 void oglGraphicsDivisionMenuProc(wxMenu
& menu
, wxCommandEvent
& event
)
1578 wxDivisionShape
*division
= (wxDivisionShape
*)menu
.GetClientData();
1579 switch (event
.GetInt())
1581 case DIVISION_MENU_SPLIT_HORIZONTALLY
:
1583 division
->Divide(wxHORIZONTAL
);
1586 case DIVISION_MENU_SPLIT_VERTICALLY
:
1588 division
->Divide(wxVERTICAL
);
1591 case DIVISION_MENU_EDIT_LEFT_EDGE
:
1593 division
->EditEdge(DIVISION_SIDE_LEFT
);
1596 case DIVISION_MENU_EDIT_TOP_EDGE
:
1598 division
->EditEdge(DIVISION_SIDE_TOP
);
1606 void wxDivisionShape::EditEdge(int side
)
1608 wxMessageBox("EditEdge() not implemented", "OGL", wxOK
);
1611 wxBeginBusyCursor();
1613 wxPen
*currentPen
= NULL
;
1614 char **pColour
= NULL
;
1615 char **pStyle
= NULL
;
1616 if (side
== DIVISION_SIDE_LEFT
)
1618 currentPen
= m_leftSidePen
;
1619 pColour
= &m_leftSideColour
;
1620 pStyle
= &m_leftSideStyle
;
1624 currentPen
= m_topSidePen
;
1625 pColour
= &m_topSideColour
;
1626 pStyle
= &m_topSideStyle
;
1629 GraphicsForm
*form
= new GraphicsForm("Containers");
1630 int lineWidth
= currentPen
->GetWidth();
1632 form
->Add(wxMakeFormShort("Width", &lineWidth
, wxFORM_DEFAULT
, NULL
, NULL
, wxVERTICAL
,
1634 form
->Add(wxMakeFormString("Colour", pColour
, wxFORM_CHOICE
,
1635 new wxList(wxMakeConstraintStrings(
1659 NULL
), NULL
, wxVERTICAL
, 150));
1660 form
->Add(wxMakeFormString("Style", pStyle
, wxFORM_CHOICE
,
1661 new wxList(wxMakeConstraintStrings(
1668 NULL
), NULL
, wxVERTICAL
, 100));
1670 wxDialogBox
*dialog
= new wxDialogBox(m_canvas
->GetParent(), "Division properties", 10, 10, 500, 500);
1671 if (GraphicsLabelFont
)
1672 dialog
->SetLabelFont(GraphicsLabelFont
);
1673 if (GraphicsButtonFont
)
1674 dialog
->SetButtonFont(GraphicsButtonFont
);
1676 form
->AssociatePanel(dialog
);
1677 form
->dialog
= dialog
;
1680 dialog
->Centre(wxBOTH
);
1685 int lineStyle
= wxSOLID
;
1688 if (strcmp(*pStyle
, "Solid") == 0)
1689 lineStyle
= wxSOLID
;
1690 else if (strcmp(*pStyle
, "Dot") == 0)
1692 else if (strcmp(*pStyle
, "Short Dash") == 0)
1693 lineStyle
= wxSHORT_DASH
;
1694 else if (strcmp(*pStyle
, "Long Dash") == 0)
1695 lineStyle
= wxLONG_DASH
;
1696 else if (strcmp(*pStyle
, "Dot Dash") == 0)
1697 lineStyle
= wxDOT_DASH
;
1700 wxPen
*newPen
= wxThePenList
->FindOrCreatePen(*pColour
, lineWidth
, lineStyle
);
1703 if (side
== DIVISION_SIDE_LEFT
)
1704 m_leftSidePen
= newPen
;
1706 m_topSidePen
= newPen
;
1708 // Need to draw whole image again
1709 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1710 compositeParent
->Draw(dc
);
1715 void wxDivisionShape::PopupMenu(double x
, double y
)
1717 oglPopupDivisionMenu
->SetClientData((void *)this);
1719 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, TRUE
);
1721 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, FALSE
);
1723 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, TRUE
);
1725 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, FALSE
);
1728 m_canvas
->ViewStart(&x1
, &y1
);
1731 m_canvas
->GetScrollPixelsPerUnit(&unit_x
, &unit_y
);
1733 wxClientDC
dc(GetCanvas());
1734 GetCanvas()->PrepareDC(dc
);
1736 int mouse_x
= (int)(dc
.LogicalToDeviceX((long)(x
- x1
*unit_x
)));
1737 int mouse_y
= (int)(dc
.LogicalToDeviceY((long)(y
- y1
*unit_y
)));
1739 m_canvas
->PopupMenu(oglPopupDivisionMenu
, mouse_x
, mouse_y
);
1742 void wxDivisionShape::SetLeftSideColour(const wxString
& colour
)
1744 m_leftSideColour
= colour
;
1747 void wxDivisionShape::SetTopSideColour(const wxString
& colour
)
1749 m_topSideColour
= colour
;
1752 void wxDivisionShape::SetLeftSideStyle(const wxString
& style
)
1754 m_leftSideStyle
= style
;
1757 void wxDivisionShape::SetTopSideStyle(const wxString
& style
)
1759 m_topSideStyle
= style
;