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(wxCompositeShape
& copy
)
365 wxRectangleShape::Copy(copy
);
367 // Associate old and new copies for copying constraints and division geometry
368 wxObjectCopyMapping
.Append((long)this, ©
);
371 wxNode
*node
= m_children
.First();
374 wxShape
*object
= (wxShape
*)node
->Data();
375 wxShape
*newObject
= object
->PrivateCopy();
376 if (newObject
->GetId() == 0)
377 newObject
->SetId(NewId());
379 newObject
->SetParent(©
);
380 copy
.m_children
.Append(newObject
);
382 // Some m_children may be divisions
383 if (m_divisions
.Member(object
))
384 copy
.m_divisions
.Append(newObject
);
386 wxObjectCopyMapping
.Append((long)object
, newObject
);
391 // Copy the constraints
392 node
= m_constraints
.First();
395 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
397 wxShape
*newConstraining
= (wxShape
*)(wxObjectCopyMapping
.Find((long)constraint
->m_constrainingObject
)->Data());
399 wxList newConstrainedList
;
400 wxNode
*node2
= constraint
->m_constrainedObjects
.First();
403 wxShape
*constrainedObject
= (wxShape
*)node2
->Data();
404 wxShape
*newConstrained
= (wxShape
*)(wxObjectCopyMapping
.Find((long)constrainedObject
)->Data());
405 newConstrainedList
.Append(newConstrained
);
406 node2
= node2
->Next();
409 OGLConstraint
*newConstraint
= new OGLConstraint(constraint
->m_constraintType
, newConstraining
,
411 newConstraint
->m_constraintId
= constraint
->m_constraintId
;
412 if (constraint
->m_constraintName
)
414 newConstraint
->m_constraintName
= constraint
->m_constraintName
;
416 newConstraint
->SetSpacing(constraint
->m_xSpacing
, constraint
->m_ySpacing
);
417 copy
.m_constraints
.Append(newConstraint
);
422 // Now copy the division geometry
423 node
= m_divisions
.First();
426 wxDivisionShape
*division
= (wxDivisionShape
*)node
->Data();
427 wxNode
*node1
= wxObjectCopyMapping
.Find((long)division
);
428 wxNode
*leftNode
= NULL
;
429 wxNode
*topNode
= NULL
;
430 wxNode
*rightNode
= NULL
;
431 wxNode
*bottomNode
= NULL
;
432 if (division
->GetLeftSide())
433 leftNode
= wxObjectCopyMapping
.Find((long)division
->GetLeftSide());
434 if (division
->GetTopSide())
435 topNode
= wxObjectCopyMapping
.Find((long)division
->GetTopSide());
436 if (division
->GetRightSide())
437 rightNode
= wxObjectCopyMapping
.Find((long)division
->GetRightSide());
438 if (division
->GetBottomSide())
439 bottomNode
= wxObjectCopyMapping
.Find((long)division
->GetBottomSide());
442 wxDivisionShape
*newDivision
= (wxDivisionShape
*)node1
->Data();
444 newDivision
->SetLeftSide((wxDivisionShape
*)leftNode
->Data());
446 newDivision
->SetTopSide((wxDivisionShape
*)topNode
->Data());
448 newDivision
->SetRightSide((wxDivisionShape
*)rightNode
->Data());
450 newDivision
->SetBottomSide((wxDivisionShape
*)bottomNode
->Data());
456 wxShape
*wxCompositeShape::PrivateCopy()
458 wxCompositeShape
*obj
= new wxCompositeShape
;
463 OGLConstraint
*wxCompositeShape::AddConstraint(OGLConstraint
*constraint
)
465 m_constraints
.Append(constraint
);
466 if (constraint
->m_constraintId
== 0)
467 constraint
->m_constraintId
= NewId();
471 OGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxList
& constrained
)
473 OGLConstraint
*constraint
= new OGLConstraint(type
, constraining
, constrained
);
474 if (constraint
->m_constraintId
== 0)
475 constraint
->m_constraintId
= NewId();
476 m_constraints
.Append(constraint
);
480 OGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxShape
*constrained
)
483 l
.Append(constrained
);
484 OGLConstraint
*constraint
= new OGLConstraint(type
, constraining
, l
);
485 if (constraint
->m_constraintId
== 0)
486 constraint
->m_constraintId
= NewId();
487 m_constraints
.Append(constraint
);
491 OGLConstraint
*wxCompositeShape::FindConstraint(long cId
, wxCompositeShape
**actualComposite
)
493 wxNode
*node
= m_constraints
.First();
496 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
497 if (constraint
->m_constraintId
== cId
)
500 *actualComposite
= this;
505 // If not found, try children.
506 node
= m_children
.First();
509 wxShape
*child
= (wxShape
*)node
->Data();
510 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
512 OGLConstraint
*constraint
= ((wxCompositeShape
*)child
)->FindConstraint(cId
, actualComposite
);
516 *actualComposite
= (wxCompositeShape
*)child
;
525 void wxCompositeShape::DeleteConstraint(OGLConstraint
*constraint
)
527 m_constraints
.DeleteObject(constraint
);
531 void wxCompositeShape::CalculateSize()
533 float maxX
= (float) -999999.9;
534 float maxY
= (float) -999999.9;
535 float minX
= (float) 999999.9;
536 float minY
= (float) 999999.9;
539 wxNode
*node
= m_children
.First();
542 wxShape
*object
= (wxShape
*)node
->Data();
544 // Recalculate size of composite objects because may not conform
545 // to size it was set to - depends on the children.
546 object
->CalculateSize();
548 object
->GetBoundingBoxMax(&w
, &h
);
549 if ((object
->GetX() + (w
/2.0)) > maxX
)
550 maxX
= (float)(object
->GetX() + (w
/2.0));
551 if ((object
->GetX() - (w
/2.0)) < minX
)
552 minX
= (float)(object
->GetX() - (w
/2.0));
553 if ((object
->GetY() + (h
/2.0)) > maxY
)
554 maxY
= (float)(object
->GetY() + (h
/2.0));
555 if ((object
->GetY() - (h
/2.0)) < minY
)
556 minY
= (float)(object
->GetY() - (h
/2.0));
560 m_width
= maxX
- minX
;
561 m_height
= maxY
- minY
;
562 m_xpos
= (float)(m_width
/2.0 + minX
);
563 m_ypos
= (float)(m_height
/2.0 + minY
);
566 bool wxCompositeShape::Recompute()
568 int noIterations
= 0;
570 while (changed
&& (noIterations
< 500))
572 changed
= Constrain();
578 cerr << "Warning: constraint algorithm failed after 500 iterations.\n";
584 bool wxCompositeShape::Constrain()
588 bool changed
= FALSE
;
589 wxNode
*node
= m_children
.First();
592 wxShape
*object
= (wxShape
*)node
->Data();
593 if (object
->Constrain())
598 node
= m_constraints
.First();
601 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
602 if (constraint
->Evaluate()) changed
= TRUE
;
609 void wxCompositeShape::WritePrologAttributes(wxExpr
*clause
)
611 wxRectangleShape::WritePrologAttributes(clause
);
613 // clause->AddAttributeValue("selectable", (long)selectable);
615 // Output constraints as constraint1 = (...), constraint2 = (...), etc.
616 int constraintNo
= 1;
617 char m_constraintNameBuf
[20];
618 wxNode
*node
= m_constraints
.First();
621 OGLConstraint
*constraint
= (OGLConstraint
*)node
->Data();
622 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
624 // Each constraint is stored in the form
625 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
626 wxExpr
*constraintExpr
= new wxExpr(PrologList
);
627 constraintExpr
->Append(new wxExpr((long)constraint
->m_constraintType
));
628 constraintExpr
->Append(new wxExpr(PrologString
, constraint
->m_constraintName
));
629 constraintExpr
->Append(new wxExpr(constraint
->m_constraintId
));
630 constraintExpr
->Append(new wxExpr(constraint
->m_xSpacing
));
631 constraintExpr
->Append(new wxExpr(constraint
->m_ySpacing
));
632 constraintExpr
->Append(new wxExpr(constraint
->m_constrainingObject
->GetId()));
634 wxExpr
*objectList
= new wxExpr(PrologList
);
635 wxNode
*node1
= constraint
->m_constrainedObjects
.First();
638 wxShape
*obj
= (wxShape
*)node1
->Data();
639 objectList
->Append(new wxExpr(obj
->GetId()));
640 node1
= node1
->Next();
642 constraintExpr
->Append(objectList
);
644 clause
->AddAttributeValue(m_constraintNameBuf
, constraintExpr
);
650 // Write the ids of all the child images
651 wxExpr
*childrenExpr
= new wxExpr(PrologList
);
652 node
= m_children
.First();
655 wxShape
*child
= (wxShape
*)node
->Data();
656 childrenExpr
->Append(new wxExpr(child
->GetId()));
659 clause
->AddAttributeValue("children", childrenExpr
);
661 // Write the ids of all the division images
662 if (m_divisions
.Number() > 0)
664 wxExpr
*divisionsExpr
= new wxExpr(PrologList
);
665 node
= m_divisions
.First();
668 wxShape
*child
= (wxShape
*)node
->Data();
669 divisionsExpr
->Append(new wxExpr(child
->GetId()));
672 clause
->AddAttributeValue("divisions", divisionsExpr
);
676 // Problem. Child images are always written AFTER the parent
677 // so as to be able to link up to parent. So we may not be able
678 // to find the constraint participants until we've read everything
679 // in. Need to have another pass for composites.
680 void wxCompositeShape::ReadPrologAttributes(wxExpr
*clause
)
682 wxRectangleShape::ReadPrologAttributes(clause
);
684 // clause->GetAttributeValue("selectable", selectable);
687 void wxCompositeShape::ReadConstraints(wxExpr
*clause
, wxExprDatabase
*database
)
689 // Constraints are output as constraint1 = (...), constraint2 = (...), etc.
690 int constraintNo
= 1;
691 char m_constraintNameBuf
[20];
692 bool haveConstraints
= TRUE
;
694 while (haveConstraints
)
696 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
697 wxExpr
*constraintExpr
= NULL
;
698 clause
->GetAttributeValue(m_constraintNameBuf
, &constraintExpr
);
701 haveConstraints
= FALSE
;
705 float cXSpacing
= 0.0;
706 float cYSpacing
= 0.0;
709 wxShape
*m_constrainingObject
= NULL
;
710 wxList m_constrainedObjects
;
712 // Each constraint is stored in the form
713 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
715 wxExpr
*typeExpr
= constraintExpr
->Nth(0);
716 wxExpr
*nameExpr
= constraintExpr
->Nth(1);
717 wxExpr
*idExpr
= constraintExpr
->Nth(2);
718 wxExpr
*xExpr
= constraintExpr
->Nth(3);
719 wxExpr
*yExpr
= constraintExpr
->Nth(4);
720 wxExpr
*constrainingExpr
= constraintExpr
->Nth(5);
721 wxExpr
*constrainedExpr
= constraintExpr
->Nth(6);
723 cType
= (int)typeExpr
->IntegerValue();
724 cXSpacing
= xExpr
->RealValue();
725 cYSpacing
= yExpr
->RealValue();
726 cName
= nameExpr
->StringValue();
727 cId
= idExpr
->IntegerValue();
729 wxExpr
*objExpr1
= database
->HashFind("node_image", constrainingExpr
->IntegerValue());
730 if (objExpr1
&& objExpr1
->GetClientData())
731 m_constrainingObject
= (wxShape
*)objExpr1
->GetClientData();
733 wxFatalError("Couldn't find constraining image of composite.", "Object graphics error");
736 wxExpr
*currentIdExpr
= constrainedExpr
->Nth(i
);
737 while (currentIdExpr
)
739 long currentId
= currentIdExpr
->IntegerValue();
740 wxExpr
*objExpr2
= database
->HashFind("node_image", currentId
);
741 if (objExpr2
&& objExpr2
->GetClientData())
743 m_constrainedObjects
.Append((wxShape
*)objExpr2
->GetClientData());
747 wxFatalError("Couldn't find constrained image of composite.", "Object graphics error");
751 currentIdExpr
= constrainedExpr
->Nth(i
);
753 OGLConstraint
*newConstraint
= AddConstraint(cType
, m_constrainingObject
, m_constrainedObjects
);
754 newConstraint
->SetSpacing(cXSpacing
, cYSpacing
);
755 newConstraint
->m_constraintId
= cId
;
756 newConstraint
->m_constraintName
= (const char*) cName
;
762 // Make this composite into a container by creating one wxDivisionShape
763 void wxCompositeShape::MakeContainer()
765 wxDivisionShape
*division
= OnCreateDivision();
766 m_divisions
.Append(division
);
769 division
->SetSize(m_width
, m_height
);
771 wxClientDC
dc(GetCanvas());
772 GetCanvas()->PrepareDC(dc
);
774 division
->Move(dc
, GetX(), GetY());
776 division
->Show(TRUE
);
779 wxDivisionShape
*wxCompositeShape::OnCreateDivision()
781 return new wxDivisionShape
;
784 wxShape
*wxCompositeShape::FindContainerImage()
786 wxNode
*node
= m_children
.First();
789 wxShape
*child
= (wxShape
*)node
->Data();
790 if (!m_divisions
.Member(child
))
797 // Returns TRUE if division is a descendant of this container
798 bool wxCompositeShape::ContainsDivision(wxDivisionShape
*division
)
800 if (m_divisions
.Member(division
))
802 wxNode
*node
= m_children
.First();
805 wxShape
*child
= (wxShape
*)node
->Data();
806 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
808 bool ans
= ((wxCompositeShape
*)child
)->ContainsDivision(division
);
822 IMPLEMENT_DYNAMIC_CLASS(wxDivisionShape
, wxCompositeShape
)
824 wxDivisionShape::wxDivisionShape()
826 SetSensitivityFilter(OP_CLICK_LEFT
| OP_CLICK_RIGHT
| OP_DRAG_RIGHT
);
827 SetCentreResize(FALSE
);
828 SetAttachmentMode(TRUE
);
833 m_handleSide
= DIVISION_SIDE_NONE
;
834 m_leftSidePen
= wxBLACK_PEN
;
835 m_topSidePen
= wxBLACK_PEN
;
836 m_leftSideColour
= "BLACK";
837 m_topSideColour
= "BLACK";
838 m_leftSideStyle
= "Solid";
839 m_topSideStyle
= "Solid";
843 wxDivisionShape::~wxDivisionShape()
847 void wxDivisionShape::OnDraw(wxDC
& dc
)
849 dc
.SetBrush(wxTRANSPARENT_BRUSH
);
850 dc
.SetBackgroundMode(wxTRANSPARENT
);
852 float x1
= (float)(GetX() - (GetWidth()/2.0));
853 float y1
= (float)(GetY() - (GetHeight()/2.0));
854 float x2
= (float)(GetX() + (GetWidth()/2.0));
855 float y2
= (float)(GetY() + (GetHeight()/2.0));
857 // Should subtract 1 pixel if drawing under Windows
864 dc
.SetPen(m_leftSidePen
);
865 dc
.DrawLine(x1
, y2
, x1
, y1
);
869 dc
.SetPen(m_topSidePen
);
870 dc
.DrawLine(x1
, y1
, x2
, y1
);
873 // For testing purposes, draw a rectangle so we know
874 // how big the division is.
875 // SetBrush(wxCYAN_BRUSH);
876 // wxRectangleShape::OnDraw(dc);
879 void wxDivisionShape::OnDrawContents(wxDC
& dc
)
881 wxCompositeShape::OnDrawContents(dc
);
884 bool wxDivisionShape::OnMovePre(wxDC
& dc
, float x
, float y
, float oldx
, float oldy
, bool display
)
886 float diffX
= x
- oldx
;
887 float diffY
= y
- oldy
;
888 wxNode
*node
= m_children
.First();
891 wxShape
*object
= (wxShape
*)node
->Data();
893 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
899 void wxDivisionShape::OnDragLeft(bool draw
, float x
, float y
, int keys
, int attachment
)
901 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
907 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
908 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
912 wxShape::OnDragLeft(draw
, x
, y
, keys
, attachment
);
915 void wxDivisionShape::OnBeginDragLeft(float x
, float y
, int keys
, int attachment
)
917 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
923 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
924 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
929 wxShape::OnBeginDragLeft(x
, y
, keys
, attachment
);
932 void wxDivisionShape::OnEndDragLeft(float x
, float y
, int keys
, int attachment
)
934 m_canvas
->ReleaseMouse();
935 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
941 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
942 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
947 wxClientDC
dc(GetCanvas());
948 GetCanvas()->PrepareDC(dc
);
950 dc
.SetLogicalFunction(wxCOPY
);
952 m_canvas
->Snap(&m_xpos
, &m_ypos
);
953 GetEventHandler()->OnMovePre(dc
, x
, y
, m_oldX
, m_oldY
);
955 ResetControlPoints();
958 GetEventHandler()->OnDrawControlPoints(dc
);
960 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
963 void wxDivisionShape::SetSize(float w
, float h
, bool recursive
)
967 wxRectangleShape::SetSize(w
, h
, recursive
);
970 void wxDivisionShape::CalculateSize()
974 void wxDivisionShape::Copy(wxDivisionShape
& copy
)
976 wxCompositeShape::Copy(copy
);
978 copy
.m_leftSideStyle
= m_leftSideStyle
;
979 copy
.m_topSideStyle
= m_topSideStyle
;
980 copy
.m_leftSideColour
= m_leftSideColour
;
981 copy
.m_topSideColour
= m_topSideColour
;
983 copy
.m_leftSidePen
= m_leftSidePen
;
984 copy
.m_topSidePen
= m_topSidePen
;
985 copy
.m_handleSide
= m_handleSide
;
987 // Division geometry copying is handled at the wxCompositeShape level.
990 wxShape
*wxDivisionShape::PrivateCopy()
992 wxDivisionShape
*obj
= new wxDivisionShape
;
998 void wxDivisionShape::WritePrologAttributes(wxExpr
*clause
)
1000 wxCompositeShape::WritePrologAttributes(clause
);
1003 clause
->AddAttributeValue("left_side", (long)m_leftSide
->GetId());
1005 clause
->AddAttributeValue("top_side", (long)m_topSide
->GetId());
1007 clause
->AddAttributeValue("right_side", (long)m_rightSide
->GetId());
1009 clause
->AddAttributeValue("bottom_side", (long)m_bottomSide
->GetId());
1011 clause
->AddAttributeValue("handle_side", (long)m_handleSide
);
1012 clause
->AddAttributeValueString("left_colour", m_leftSideColour
);
1013 clause
->AddAttributeValueString("top_colour", m_topSideColour
);
1014 clause
->AddAttributeValueString("left_style", m_leftSideStyle
);
1015 clause
->AddAttributeValueString("top_style", m_topSideStyle
);
1018 void wxDivisionShape::ReadPrologAttributes(wxExpr
*clause
)
1020 wxCompositeShape::ReadPrologAttributes(clause
);
1022 clause
->GetAttributeValue("handle_side", m_handleSide
);
1023 clause
->GetAttributeValue("left_colour", m_leftSideColour
);
1024 clause
->GetAttributeValue("top_colour", m_topSideColour
);
1025 clause
->GetAttributeValue("left_style", m_leftSideStyle
);
1026 clause
->GetAttributeValue("top_style", m_topSideStyle
);
1031 void wxDivisionShape::OnRightClick(float x
, float y
, int keys
, int attachment
)
1033 if (keys
& KEY_CTRL
)
1038 else if (keys & KEY_SHIFT)
1040 if (m_leftSide || m_topSide || m_rightSide || m_bottomSide)
1045 GetParent()->Draw(dc);
1058 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1059 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1066 // Divide wxHORIZONTALly or wxVERTICALly
1067 bool wxDivisionShape::Divide(int direction
)
1069 // Calculate existing top-left, bottom-right
1070 float x1
= (float)(GetX() - (GetWidth()/2.0));
1071 float y1
= (float)(GetY() - (GetHeight()/2.0));
1072 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1073 float oldWidth
= GetWidth();
1074 float oldHeight
= GetHeight();
1078 wxClientDC
dc(GetCanvas());
1079 GetCanvas()->PrepareDC(dc
);
1081 if (direction
== wxVERTICAL
)
1083 // Dividing vertically means notionally putting a horizontal line through it.
1084 // Break existing piece into two.
1085 float newXPos1
= GetX();
1086 float newYPos1
= (float)(y1
+ (GetHeight()/4.0));
1087 float newXPos2
= GetX();
1088 float newYPos2
= (float)(y1
+ (3.0*GetHeight()/4.0));
1089 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1090 newDivision
->Show(TRUE
);
1094 // Anything adjoining the bottom of this division now adjoins the
1095 // bottom of the new division.
1096 wxNode
*node
= compositeParent
->GetDivisions().First();
1099 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->Data();
1100 if (obj
->GetTopSide() == this)
1101 obj
->SetTopSide(newDivision
);
1102 node
= node
->Next();
1104 newDivision
->SetTopSide(this);
1105 newDivision
->SetBottomSide(m_bottomSide
);
1106 newDivision
->SetLeftSide(m_leftSide
);
1107 newDivision
->SetRightSide(m_rightSide
);
1108 m_bottomSide
= newDivision
;
1110 compositeParent
->GetDivisions().Append(newDivision
);
1112 // CHANGE: Need to insert this division at start of divisions in the object
1113 // list, because e.g.:
1115 // 2) Add contained object
1117 // Division is now receiving mouse events _before_ the contained object,
1118 // because it was added last (on top of all others)
1120 // Add after the image that visualizes the container
1121 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1123 m_handleSide
= DIVISION_SIDE_BOTTOM
;
1124 newDivision
->SetHandleSide(DIVISION_SIDE_TOP
);
1126 SetSize(oldWidth
, (float)(oldHeight
/2.0));
1127 Move(dc
, newXPos1
, newYPos1
);
1129 newDivision
->SetSize(oldWidth
, (float)(oldHeight
/2.0));
1130 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1134 // Dividing horizontally means notionally putting a vertical line through it.
1135 // Break existing piece into two.
1136 float newXPos1
= (float)(x1
+ (GetWidth()/4.0));
1137 float newYPos1
= GetY();
1138 float newXPos2
= (float)(x1
+ (3.0*GetWidth()/4.0));
1139 float newYPos2
= GetY();
1140 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1141 newDivision
->Show(TRUE
);
1145 // Anything adjoining the left of this division now adjoins the
1146 // left of the new division.
1147 wxNode
*node
= compositeParent
->GetDivisions().First();
1150 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->Data();
1151 if (obj
->GetLeftSide() == this)
1152 obj
->SetLeftSide(newDivision
);
1153 node
= node
->Next();
1155 newDivision
->SetTopSide(m_topSide
);
1156 newDivision
->SetBottomSide(m_bottomSide
);
1157 newDivision
->SetLeftSide(this);
1158 newDivision
->SetRightSide(m_rightSide
);
1159 m_rightSide
= newDivision
;
1161 compositeParent
->GetDivisions().Append(newDivision
);
1162 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1164 m_handleSide
= DIVISION_SIDE_RIGHT
;
1165 newDivision
->SetHandleSide(DIVISION_SIDE_LEFT
);
1167 SetSize((float)(oldWidth
/2.0), oldHeight
);
1168 Move(dc
, newXPos1
, newYPos1
);
1170 newDivision
->SetSize((float)(oldWidth
/2.0), oldHeight
);
1171 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1173 if (compositeParent
->Selected())
1175 compositeParent
->DeleteControlPoints(& dc
);
1176 compositeParent
->MakeControlPoints();
1177 compositeParent
->MakeMandatoryControlPoints();
1179 compositeParent
->Draw(dc
);
1183 // Make one control point for every visible line
1184 void wxDivisionShape::MakeControlPoints()
1186 MakeMandatoryControlPoints();
1189 void wxDivisionShape::MakeMandatoryControlPoints()
1193 GetBoundingBoxMax(&maxX
, &maxY
);
1199 x = (float)(-maxX/2.0);
1201 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1202 CONTROL_POINT_HORIZONTAL);
1203 m_canvas->AddShape(control);
1204 m_controlPoints.Append(control);
1209 y = (float)(-maxY/2.0);
1210 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1211 CONTROL_POINT_VERTICAL);
1212 m_canvas->AddShape(control);
1213 m_controlPoints.Append(control);
1216 switch (m_handleSide
)
1218 case DIVISION_SIDE_LEFT
:
1220 x
= (float)(-maxX
/2.0);
1222 direction
= CONTROL_POINT_HORIZONTAL
;
1225 case DIVISION_SIDE_TOP
:
1228 y
= (float)(-maxY
/2.0);
1229 direction
= CONTROL_POINT_VERTICAL
;
1232 case DIVISION_SIDE_RIGHT
:
1234 x
= (float)(maxX
/2.0);
1236 direction
= CONTROL_POINT_HORIZONTAL
;
1239 case DIVISION_SIDE_BOTTOM
:
1242 y
= (float)(maxY
/2.0);
1243 direction
= CONTROL_POINT_VERTICAL
;
1249 if (m_handleSide
!= DIVISION_SIDE_NONE
)
1251 wxDivisionControlPoint
*control
= new wxDivisionControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, x
, y
,
1253 m_canvas
->AddShape(control
);
1254 m_controlPoints
.Append(control
);
1258 void wxDivisionShape::ResetControlPoints()
1260 ResetMandatoryControlPoints();
1263 void wxDivisionShape::ResetMandatoryControlPoints()
1265 if (m_controlPoints
.Number() < 1)
1270 GetBoundingBoxMax(&maxX
, &maxY
);
1272 wxNode *node = m_controlPoints.First();
1275 wxDivisionControlPoint *control = (wxDivisionControlPoint *)node->Data();
1276 if (control->type == CONTROL_POINT_HORIZONTAL)
1278 control->xoffset = (float)(-maxX/2.0); control->m_yoffset = 0.0;
1280 else if (control->type == CONTROL_POINT_VERTICAL)
1282 control->xoffset = 0.0; control->m_yoffset = (float)(-maxY/2.0);
1284 node = node->Next();
1287 wxNode
*node
= m_controlPoints
.First();
1288 if ((m_handleSide
== DIVISION_SIDE_LEFT
) && node
)
1290 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1291 control
->m_xoffset
= (float)(-maxX
/2.0); control
->m_yoffset
= 0.0;
1294 if ((m_handleSide
== DIVISION_SIDE_TOP
) && node
)
1296 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1297 control
->m_xoffset
= 0.0; control
->m_yoffset
= (float)(-maxY
/2.0);
1300 if ((m_handleSide
== DIVISION_SIDE_RIGHT
) && node
)
1302 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1303 control
->m_xoffset
= (float)(maxX
/2.0); control
->m_yoffset
= 0.0;
1306 if ((m_handleSide
== DIVISION_SIDE_BOTTOM
) && node
)
1308 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->Data();
1309 control
->m_xoffset
= 0.0; control
->m_yoffset
= (float)(maxY
/2.0);
1313 // Adjust a side, returning FALSE if it's not physically possible.
1314 bool wxDivisionShape::AdjustLeft(float left
, bool test
)
1316 float x2
= (float)(GetX() + (GetWidth()/2.0));
1323 float newW
= x2
- left
;
1324 float newX
= (float)(left
+ newW
/2.0);
1325 SetSize(newW
, GetHeight());
1327 wxClientDC
dc(GetCanvas());
1328 GetCanvas()->PrepareDC(dc
);
1330 Move(dc
, newX
, GetY());
1335 bool wxDivisionShape::AdjustTop(float top
, bool test
)
1337 float y2
= (float)(GetY() + (GetHeight()/2.0));
1344 float newH
= y2
- top
;
1345 float newY
= (float)(top
+ newH
/2.0);
1346 SetSize(GetWidth(), newH
);
1348 wxClientDC
dc(GetCanvas());
1349 GetCanvas()->PrepareDC(dc
);
1351 Move(dc
, GetX(), newY
);
1356 bool wxDivisionShape::AdjustRight(float right
, bool test
)
1358 float x1
= (float)(GetX() - (GetWidth()/2.0));
1365 float newW
= right
- x1
;
1366 float newX
= (float)(x1
+ newW
/2.0);
1367 SetSize(newW
, GetHeight());
1369 wxClientDC
dc(GetCanvas());
1370 GetCanvas()->PrepareDC(dc
);
1372 Move(dc
, newX
, GetY());
1377 bool wxDivisionShape::AdjustBottom(float bottom
, bool test
)
1379 float y1
= (float)(GetY() - (GetHeight()/2.0));
1386 float newH
= bottom
- y1
;
1387 float newY
= (float)(y1
+ newH
/2.0);
1388 SetSize(GetWidth(), newH
);
1390 wxClientDC
dc(GetCanvas());
1391 GetCanvas()->PrepareDC(dc
);
1393 Move(dc
, GetX(), newY
);
1398 wxDivisionControlPoint::wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, float size
, float the_xoffset
, float the_yoffset
, int the_type
):
1399 wxControlPoint(the_canvas
, object
, size
, the_xoffset
, the_yoffset
, the_type
)
1401 SetEraseObject(FALSE
);
1404 wxDivisionControlPoint::~wxDivisionControlPoint()
1408 static float originalX
= 0.0;
1409 static float originalY
= 0.0;
1410 static float originalW
= 0.0;
1411 static float originalH
= 0.0;
1413 // Implement resizing of canvas object
1414 void wxDivisionControlPoint::OnDragLeft(bool draw
, float x
, float y
, int keys
, int attachment
)
1416 wxControlPoint::OnDragLeft(draw
, x
, y
, keys
, attachment
);
1419 void wxDivisionControlPoint::OnBeginDragLeft(float x
, float y
, int keys
, int attachment
)
1421 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1422 originalX
= division
->GetX();
1423 originalY
= division
->GetY();
1424 originalW
= division
->GetWidth();
1425 originalH
= division
->GetHeight();
1427 wxControlPoint::OnBeginDragLeft(x
, y
, keys
, attachment
);
1430 void wxDivisionControlPoint::OnEndDragLeft(float x
, float y
, int keys
, int attachment
)
1432 wxControlPoint::OnEndDragLeft(x
, y
, keys
, attachment
);
1434 wxClientDC
dc(GetCanvas());
1435 GetCanvas()->PrepareDC(dc
);
1437 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1438 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)division
->GetParent();
1440 // Need to check it's within the bounds of the parent composite.
1441 float x1
= (float)(divisionParent
->GetX() - (divisionParent
->GetWidth()/2.0));
1442 float y1
= (float)(divisionParent
->GetY() - (divisionParent
->GetHeight()/2.0));
1443 float x2
= (float)(divisionParent
->GetX() + (divisionParent
->GetWidth()/2.0));
1444 float y2
= (float)(divisionParent
->GetY() + (divisionParent
->GetHeight()/2.0));
1446 // Need to check it has not made the division zero or negative width/height
1447 float dx1
= (float)(division
->GetX() - (division
->GetWidth()/2.0));
1448 float dy1
= (float)(division
->GetY() - (division
->GetHeight()/2.0));
1449 float dx2
= (float)(division
->GetX() + (division
->GetWidth()/2.0));
1450 float dy2
= (float)(division
->GetY() + (division
->GetHeight()/2.0));
1452 bool success
= TRUE
;
1453 switch (division
->GetHandleSide())
1455 case DIVISION_SIDE_LEFT
:
1457 if ((x
<= x1
) || (x
>= x2
) || (x
>= dx2
))
1459 // Try it out first...
1460 else if (!division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, TRUE
))
1463 division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, FALSE
);
1467 case DIVISION_SIDE_TOP
:
1469 if ((y
<= y1
) || (y
>= y2
) || (y
>= dy2
))
1471 else if (!division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, TRUE
))
1474 division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, FALSE
);
1478 case DIVISION_SIDE_RIGHT
:
1480 if ((x
<= x1
) || (x
>= x2
) || (x
<= dx1
))
1482 else if (!division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, TRUE
))
1485 division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, FALSE
);
1489 case DIVISION_SIDE_BOTTOM
:
1491 if ((y
<= y1
) || (y
>= y2
) || (y
<= dy1
))
1493 else if (!division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, TRUE
))
1496 division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, FALSE
);
1503 division
->SetSize(originalW
, originalH
);
1504 division
->Move(dc
, originalX
, originalY
);
1506 divisionParent
->Draw(dc
);
1507 division
->GetEventHandler()->OnDrawControlPoints(dc
);
1510 /* Resize adjoining divisions.
1512 Behaviour should be as follows:
1513 If right edge moves, find all objects whose left edge
1514 adjoins this object, and move left edge accordingly.
1515 If left..., move ... right.
1516 If top..., move ... bottom.
1517 If bottom..., move top.
1518 If size goes to zero or end position is other side of start position,
1519 resize to original size and return.
1521 bool wxDivisionShape::ResizeAdjoining(int side
, float newPos
, bool test
)
1523 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)GetParent();
1524 wxNode
*node
= divisionParent
->GetDivisions().First();
1527 wxDivisionShape
*division
= (wxDivisionShape
*)node
->Data();
1530 case DIVISION_SIDE_LEFT
:
1532 if (division
->m_rightSide
== this)
1534 bool success
= division
->AdjustRight(newPos
, test
);
1535 if (!success
&& test
)
1540 case DIVISION_SIDE_TOP
:
1542 if (division
->m_bottomSide
== this)
1544 bool success
= division
->AdjustBottom(newPos
, test
);
1545 if (!success
&& test
)
1550 case DIVISION_SIDE_RIGHT
:
1552 if (division
->m_leftSide
== this)
1554 bool success
= division
->AdjustLeft(newPos
, test
);
1555 if (!success
&& test
)
1560 case DIVISION_SIDE_BOTTOM
:
1562 if (division
->m_topSide
== this)
1564 bool success
= division
->AdjustTop(newPos
, test
);
1565 if (!success
&& test
)
1573 node
= node
->Next();
1580 * Popup menu for editing divisions
1584 void oglGraphicsDivisionMenuProc(wxMenu
& menu
, wxCommandEvent
& event
)
1586 wxDivisionShape
*division
= (wxDivisionShape
*)menu
.GetClientData();
1587 switch (event
.GetInt())
1589 case DIVISION_MENU_SPLIT_HORIZONTALLY
:
1591 division
->Divide(wxHORIZONTAL
);
1594 case DIVISION_MENU_SPLIT_VERTICALLY
:
1596 division
->Divide(wxVERTICAL
);
1599 case DIVISION_MENU_EDIT_LEFT_EDGE
:
1601 division
->EditEdge(DIVISION_SIDE_LEFT
);
1604 case DIVISION_MENU_EDIT_TOP_EDGE
:
1606 division
->EditEdge(DIVISION_SIDE_TOP
);
1614 void wxDivisionShape::EditEdge(int side
)
1616 wxMessageBox("EditEdge() not implemented", "OGL", wxOK
);
1619 wxBeginBusyCursor();
1621 wxPen
*currentPen
= NULL
;
1622 char **pColour
= NULL
;
1623 char **pStyle
= NULL
;
1624 if (side
== DIVISION_SIDE_LEFT
)
1626 currentPen
= m_leftSidePen
;
1627 pColour
= &m_leftSideColour
;
1628 pStyle
= &m_leftSideStyle
;
1632 currentPen
= m_topSidePen
;
1633 pColour
= &m_topSideColour
;
1634 pStyle
= &m_topSideStyle
;
1637 GraphicsForm
*form
= new GraphicsForm("Containers");
1638 int lineWidth
= currentPen
->GetWidth();
1640 form
->Add(wxMakeFormShort("Width", &lineWidth
, wxFORM_DEFAULT
, NULL
, NULL
, wxVERTICAL
,
1642 form
->Add(wxMakeFormString("Colour", pColour
, wxFORM_CHOICE
,
1643 new wxList(wxMakeConstraintStrings(
1667 NULL
), NULL
, wxVERTICAL
, 150));
1668 form
->Add(wxMakeFormString("Style", pStyle
, wxFORM_CHOICE
,
1669 new wxList(wxMakeConstraintStrings(
1676 NULL
), NULL
, wxVERTICAL
, 100));
1678 wxDialogBox
*dialog
= new wxDialogBox(m_canvas
->GetParent(), "Division properties", 10, 10, 500, 500);
1679 if (GraphicsLabelFont
)
1680 dialog
->SetLabelFont(GraphicsLabelFont
);
1681 if (GraphicsButtonFont
)
1682 dialog
->SetButtonFont(GraphicsButtonFont
);
1684 form
->AssociatePanel(dialog
);
1685 form
->dialog
= dialog
;
1688 dialog
->Centre(wxBOTH
);
1693 int lineStyle
= wxSOLID
;
1696 if (strcmp(*pStyle
, "Solid") == 0)
1697 lineStyle
= wxSOLID
;
1698 else if (strcmp(*pStyle
, "Dot") == 0)
1700 else if (strcmp(*pStyle
, "Short Dash") == 0)
1701 lineStyle
= wxSHORT_DASH
;
1702 else if (strcmp(*pStyle
, "Long Dash") == 0)
1703 lineStyle
= wxLONG_DASH
;
1704 else if (strcmp(*pStyle
, "Dot Dash") == 0)
1705 lineStyle
= wxDOT_DASH
;
1708 wxPen
*newPen
= wxThePenList
->FindOrCreatePen(*pColour
, lineWidth
, lineStyle
);
1711 if (side
== DIVISION_SIDE_LEFT
)
1712 m_leftSidePen
= newPen
;
1714 m_topSidePen
= newPen
;
1716 // Need to draw whole image again
1717 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1718 compositeParent
->Draw(dc
);
1723 void wxDivisionShape::PopupMenu(float x
, float y
)
1725 oglPopupDivisionMenu
->SetClientData((char *)this);
1727 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, TRUE
);
1729 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, FALSE
);
1731 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, TRUE
);
1733 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, FALSE
);
1736 m_canvas
->ViewStart(&x1
, &y1
);
1739 m_canvas
->GetScrollPixelsPerUnit(&unit_x
, &unit_y
);
1741 wxClientDC
dc(GetCanvas());
1742 GetCanvas()->PrepareDC(dc
);
1744 int mouse_x
= (int)(dc
.LogicalToDeviceX(x
- x1
*unit_x
));
1745 int mouse_y
= (int)(dc
.LogicalToDeviceY(y
- y1
*unit_y
));
1747 m_canvas
->PopupMenu(oglPopupDivisionMenu
, mouse_x
, mouse_y
);
1750 void wxDivisionShape::SetLeftSideColour(const wxString
& colour
)
1752 m_leftSideColour
= colour
;
1755 void wxDivisionShape::SetTopSideColour(const wxString
& colour
)
1757 m_topSideColour
= colour
;
1760 void wxDivisionShape::SetLeftSideStyle(const wxString
& style
)
1762 m_leftSideStyle
= style
;
1765 void wxDivisionShape::SetTopSideStyle(const wxString
& style
)
1767 m_topSideStyle
= style
;