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/deprecated/wxexpr.h>
31 #include "wx/ogl/ogl.h"
35 // Sometimes, objects need to access the whole database to
36 // construct themselves.
37 wxExprDatabase
*GlobalwxExprDatabase
= NULL
;
41 * Division control point
44 class wxDivisionControlPoint
: public wxControlPoint
46 DECLARE_DYNAMIC_CLASS(wxDivisionControlPoint
)
48 wxDivisionControlPoint() {}
49 wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, double size
, double the_xoffset
, double the_yoffset
, int the_type
);
50 ~wxDivisionControlPoint();
52 void OnDragLeft(bool draw
, double x
, double y
, int keys
=0, int attachment
= 0);
53 void OnBeginDragLeft(double x
, double y
, int keys
=0, int attachment
= 0);
54 void OnEndDragLeft(double x
, double y
, int keys
=0, int attachment
= 0);
57 IMPLEMENT_DYNAMIC_CLASS(wxDivisionControlPoint
, wxControlPoint
)
64 IMPLEMENT_DYNAMIC_CLASS(wxCompositeShape
, wxRectangleShape
)
66 wxCompositeShape::wxCompositeShape(): wxRectangleShape(10.0, 10.0)
68 // selectable = FALSE;
73 wxCompositeShape::~wxCompositeShape()
75 wxNode
*node
= m_constraints
.GetFirst();
78 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
80 node
= node
->GetNext();
82 node
= m_children
.GetFirst();
85 wxShape
*object
= (wxShape
*)node
->GetData();
86 wxNode
*next
= node
->GetNext();
93 void wxCompositeShape::OnDraw(wxDC
& dc
)
95 double x1
= (double)(m_xpos
- m_width
/2.0);
96 double y1
= (double)(m_ypos
- m_height
/2.0);
98 if (m_shadowMode
!= SHADOW_NONE
)
101 dc
.SetBrush(* m_shadowBrush
);
102 dc
.SetPen(* g_oglTransparentPen
);
104 if (m_cornerRadius
!= 0.0)
105 dc
.DrawRoundedRectangle(WXROUND(x1
+ m_shadowOffsetX
), WXROUND(y1
+ m_shadowOffsetY
),
106 WXROUND(m_width
), WXROUND(m_height
), m_cornerRadius
);
108 dc
.DrawRectangle(WXROUND(x1
+ m_shadowOffsetX
), WXROUND(y1
+ m_shadowOffsetY
), WXROUND(m_width
), WXROUND(m_height
));
112 void wxCompositeShape::OnDrawContents(wxDC
& dc
)
114 wxNode
*node
= m_children
.GetFirst();
117 wxShape
*object
= (wxShape
*)node
->GetData();
119 object
->DrawLinks(dc
);
120 node
= node
->GetNext();
122 wxShape::OnDrawContents(dc
);
125 bool wxCompositeShape::OnMovePre(wxDC
& dc
, double x
, double y
, double oldx
, double oldy
, bool display
)
127 double diffX
= x
- oldx
;
128 double diffY
= y
- oldy
;
129 wxNode
*node
= m_children
.GetFirst();
132 wxShape
*object
= (wxShape
*)node
->GetData();
135 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
137 node
= node
->GetNext();
142 void wxCompositeShape::OnErase(wxDC
& dc
)
144 wxRectangleShape::OnErase(dc
);
145 wxNode
*node
= m_children
.GetFirst();
148 wxShape
*object
= (wxShape
*)node
->GetData();
150 node
= node
->GetNext();
154 static double objectStartX
= 0.0;
155 static double objectStartY
= 0.0;
157 void wxCompositeShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
161 m_canvas
->Snap(&xx
, &yy
);
162 double offsetX
= xx
- objectStartX
;
163 double offsetY
= yy
- objectStartY
;
165 wxClientDC
dc(GetCanvas());
166 GetCanvas()->PrepareDC(dc
);
168 dc
.SetLogicalFunction(OGLRBLF
);
169 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
170 dc
.SetPen(dottedPen
);
171 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
173 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
174 // wxShape::OnDragLeft(draw, x, y, keys, attachment);
177 void wxCompositeShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
182 wxClientDC
dc(GetCanvas());
183 GetCanvas()->PrepareDC(dc
);
187 dc
.SetLogicalFunction(OGLRBLF
);
189 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
190 dc
.SetPen(dottedPen
);
191 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
192 m_canvas
->CaptureMouse();
196 m_canvas
->Snap(&xx
, &yy
);
197 double offsetX
= xx
- objectStartX
;
198 double offsetY
= yy
- objectStartY
;
200 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
202 // wxShape::OnBeginDragLeft(x, y, keys, attachment);
205 void wxCompositeShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
207 // wxShape::OnEndDragLeft(x, y, keys, attachment);
209 wxClientDC
dc(GetCanvas());
210 GetCanvas()->PrepareDC(dc
);
212 m_canvas
->ReleaseMouse();
216 if (m_parent
) m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, 0);
220 dc
.SetLogicalFunction(wxCOPY
);
223 m_canvas
->Snap(&xx
, &yy
);
224 double offsetX
= xx
- objectStartX
;
225 double offsetY
= yy
- objectStartY
;
227 Move(dc
, GetX() + offsetX
, GetY() + offsetY
);
229 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
232 void wxCompositeShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
234 // If we get a ctrl-right click, this means send the message to
235 // the division, so we can invoke a user interface for dealing with regions.
238 wxNode
*node
= m_divisions
.GetFirst();
241 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
242 wxNode
*next
= node
->GetNext();
245 if (division
->HitTest(x
, y
, &attach
, &dist
))
247 division
->GetEventHandler()->OnRightClick(x
, y
, keys
, attach
);
256 void wxCompositeShape::SetSize(double w
, double h
, bool recursive
)
258 SetAttachmentSize(w
, h
);
260 double xScale
= (double)(w
/(wxMax(1.0, GetWidth())));
261 double yScale
= (double)(h
/(wxMax(1.0, GetHeight())));
266 if (!recursive
) return;
268 wxNode
*node
= m_children
.GetFirst();
270 wxClientDC
dc(GetCanvas());
271 GetCanvas()->PrepareDC(dc
);
273 double xBound
, yBound
;
276 wxShape
*object
= (wxShape
*)node
->GetData();
278 // Scale the position first
279 double newX
= (double)(((object
->GetX() - GetX())*xScale
) + GetX());
280 double newY
= (double)(((object
->GetY() - GetY())*yScale
) + GetY());
282 object
->Move(dc
, newX
, newY
);
285 // Now set the scaled size
286 object
->GetBoundingBoxMin(&xBound
, &yBound
);
287 object
->SetSize(object
->GetFixedWidth() ? xBound
: xScale
*xBound
,
288 object
->GetFixedHeight() ? yBound
: yScale
*yBound
);
290 node
= node
->GetNext();
292 SetDefaultRegionSize();
295 void wxCompositeShape::AddChild(wxShape
*child
, wxShape
*addAfter
)
297 m_children
.Append(child
);
298 child
->SetParent(this);
301 // Ensure we add at the right position
303 child
->RemoveFromCanvas(m_canvas
);
304 child
->AddToCanvas(m_canvas
, addAfter
);
308 void wxCompositeShape::RemoveChild(wxShape
*child
)
310 m_children
.DeleteObject(child
);
311 m_divisions
.DeleteObject(child
);
312 RemoveChildFromConstraints(child
);
313 child
->SetParent(NULL
);
316 void wxCompositeShape::DeleteConstraintsInvolvingChild(wxShape
*child
)
318 wxNode
*node
= m_constraints
.GetFirst();
321 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
322 wxNode
*nextNode
= node
->GetNext();
324 if ((constraint
->m_constrainingObject
== child
) ||
325 constraint
->m_constrainedObjects
.Member(child
))
334 void wxCompositeShape::RemoveChildFromConstraints(wxShape
*child
)
336 wxNode
*node
= m_constraints
.GetFirst();
339 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
340 wxNode
*nextNode
= node
->GetNext();
342 if (constraint
->m_constrainedObjects
.Member(child
))
343 constraint
->m_constrainedObjects
.DeleteObject(child
);
344 if (constraint
->m_constrainingObject
== child
)
345 constraint
->m_constrainingObject
= NULL
;
347 // Delete the constraint if no participants left
348 if (!constraint
->m_constrainingObject
)
358 void wxCompositeShape::Copy(wxShape
& copy
)
360 wxRectangleShape::Copy(copy
);
362 wxASSERT( copy
.IsKindOf(CLASSINFO(wxCompositeShape
)) ) ;
364 wxCompositeShape
& compositeCopy
= (wxCompositeShape
&) copy
;
366 // Associate old and new copies for compositeCopying constraints and division geometry
367 oglObjectCopyMapping
.Append((long)this, &compositeCopy
);
370 wxNode
*node
= m_children
.GetFirst();
373 wxShape
*object
= (wxShape
*)node
->GetData();
374 wxShape
*newObject
= object
->CreateNewCopy(FALSE
, FALSE
);
375 if (newObject
->GetId() == 0)
376 newObject
->SetId(wxNewId());
378 newObject
->SetParent(&compositeCopy
);
379 compositeCopy
.m_children
.Append(newObject
);
381 // Some m_children may be divisions
382 if (m_divisions
.Member(object
))
383 compositeCopy
.m_divisions
.Append(newObject
);
385 oglObjectCopyMapping
.Append((long)object
, newObject
);
387 node
= node
->GetNext();
390 // Copy the constraints
391 node
= m_constraints
.GetFirst();
394 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
396 wxShape
*newConstraining
= (wxShape
*)(oglObjectCopyMapping
.Find((long)constraint
->m_constrainingObject
)->GetData());
398 wxList newConstrainedList
;
399 wxNode
*node2
= constraint
->m_constrainedObjects
.GetFirst();
402 wxShape
*constrainedObject
= (wxShape
*)node2
->GetData();
403 wxShape
*newConstrained
= (wxShape
*)(oglObjectCopyMapping
.Find((long)constrainedObject
)->GetData());
404 newConstrainedList
.Append(newConstrained
);
405 node2
= node2
->GetNext();
408 wxOGLConstraint
*newConstraint
= new wxOGLConstraint(constraint
->m_constraintType
, newConstraining
,
410 newConstraint
->m_constraintId
= constraint
->m_constraintId
;
411 if (constraint
->m_constraintName
)
413 newConstraint
->m_constraintName
= constraint
->m_constraintName
;
415 newConstraint
->SetSpacing(constraint
->m_xSpacing
, constraint
->m_ySpacing
);
416 compositeCopy
.m_constraints
.Append(newConstraint
);
418 node
= node
->GetNext();
421 // Now compositeCopy the division geometry
422 node
= m_divisions
.GetFirst();
425 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
426 wxNode
*node1
= oglObjectCopyMapping
.Find((long)division
);
427 wxNode
*leftNode
= NULL
;
428 wxNode
*topNode
= NULL
;
429 wxNode
*rightNode
= NULL
;
430 wxNode
*bottomNode
= NULL
;
431 if (division
->GetLeftSide())
432 leftNode
= oglObjectCopyMapping
.Find((long)division
->GetLeftSide());
433 if (division
->GetTopSide())
434 topNode
= oglObjectCopyMapping
.Find((long)division
->GetTopSide());
435 if (division
->GetRightSide())
436 rightNode
= oglObjectCopyMapping
.Find((long)division
->GetRightSide());
437 if (division
->GetBottomSide())
438 bottomNode
= oglObjectCopyMapping
.Find((long)division
->GetBottomSide());
441 wxDivisionShape
*newDivision
= (wxDivisionShape
*)node1
->GetData();
443 newDivision
->SetLeftSide((wxDivisionShape
*)leftNode
->GetData());
445 newDivision
->SetTopSide((wxDivisionShape
*)topNode
->GetData());
447 newDivision
->SetRightSide((wxDivisionShape
*)rightNode
->GetData());
449 newDivision
->SetBottomSide((wxDivisionShape
*)bottomNode
->GetData());
451 node
= node
->GetNext();
455 wxOGLConstraint
*wxCompositeShape::AddConstraint(wxOGLConstraint
*constraint
)
457 m_constraints
.Append(constraint
);
458 if (constraint
->m_constraintId
== 0)
459 constraint
->m_constraintId
= wxNewId();
463 wxOGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxList
& constrained
)
465 wxOGLConstraint
*constraint
= new wxOGLConstraint(type
, constraining
, constrained
);
466 if (constraint
->m_constraintId
== 0)
467 constraint
->m_constraintId
= wxNewId();
468 m_constraints
.Append(constraint
);
472 wxOGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxShape
*constrained
)
475 l
.Append(constrained
);
476 wxOGLConstraint
*constraint
= new wxOGLConstraint(type
, constraining
, l
);
477 if (constraint
->m_constraintId
== 0)
478 constraint
->m_constraintId
= wxNewId();
479 m_constraints
.Append(constraint
);
483 wxOGLConstraint
*wxCompositeShape::FindConstraint(long cId
, wxCompositeShape
**actualComposite
)
485 wxNode
*node
= m_constraints
.GetFirst();
488 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
489 if (constraint
->m_constraintId
== cId
)
492 *actualComposite
= this;
495 node
= node
->GetNext();
497 // If not found, try children.
498 node
= m_children
.GetFirst();
501 wxShape
*child
= (wxShape
*)node
->GetData();
502 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
504 wxOGLConstraint
*constraint
= ((wxCompositeShape
*)child
)->FindConstraint(cId
, actualComposite
);
508 *actualComposite
= (wxCompositeShape
*)child
;
512 node
= node
->GetNext();
517 void wxCompositeShape::DeleteConstraint(wxOGLConstraint
*constraint
)
519 m_constraints
.DeleteObject(constraint
);
523 void wxCompositeShape::CalculateSize()
525 double maxX
= (double) -999999.9;
526 double maxY
= (double) -999999.9;
527 double minX
= (double) 999999.9;
528 double minY
= (double) 999999.9;
531 wxNode
*node
= m_children
.GetFirst();
534 wxShape
*object
= (wxShape
*)node
->GetData();
536 // Recalculate size of composite objects because may not conform
537 // to size it was set to - depends on the children.
538 object
->CalculateSize();
540 object
->GetBoundingBoxMax(&w
, &h
);
541 if ((object
->GetX() + (w
/2.0)) > maxX
)
542 maxX
= (double)(object
->GetX() + (w
/2.0));
543 if ((object
->GetX() - (w
/2.0)) < minX
)
544 minX
= (double)(object
->GetX() - (w
/2.0));
545 if ((object
->GetY() + (h
/2.0)) > maxY
)
546 maxY
= (double)(object
->GetY() + (h
/2.0));
547 if ((object
->GetY() - (h
/2.0)) < minY
)
548 minY
= (double)(object
->GetY() - (h
/2.0));
550 node
= node
->GetNext();
552 m_width
= maxX
- minX
;
553 m_height
= maxY
- minY
;
554 m_xpos
= (double)(m_width
/2.0 + minX
);
555 m_ypos
= (double)(m_height
/2.0 + minY
);
558 bool wxCompositeShape::Recompute()
560 int noIterations
= 0;
562 while (changed
&& (noIterations
< 500))
564 changed
= Constrain();
570 cerr << "Warning: constraint algorithm failed after 500 iterations.\n";
576 bool wxCompositeShape::Constrain()
580 bool changed
= FALSE
;
581 wxNode
*node
= m_children
.GetFirst();
584 wxShape
*object
= (wxShape
*)node
->GetData();
585 if (object
->Constrain())
587 node
= node
->GetNext();
590 node
= m_constraints
.GetFirst();
593 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
594 if (constraint
->Evaluate()) changed
= TRUE
;
595 node
= node
->GetNext();
601 void wxCompositeShape::WriteAttributes(wxExpr
*clause
)
603 wxRectangleShape::WriteAttributes(clause
);
605 // clause->AddAttributeValue("selectable", (long)selectable);
607 // Output constraints as constraint1 = (...), constraint2 = (...), etc.
608 int constraintNo
= 1;
609 char m_constraintNameBuf
[20];
610 wxNode
*node
= m_constraints
.GetFirst();
613 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
614 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
616 // Each constraint is stored in the form
617 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
618 wxExpr
*constraintExpr
= new wxExpr(wxExprList
);
619 constraintExpr
->Append(new wxExpr((long)constraint
->m_constraintType
));
620 constraintExpr
->Append(new wxExpr(wxExprString
, constraint
->m_constraintName
));
621 constraintExpr
->Append(new wxExpr(constraint
->m_constraintId
));
622 constraintExpr
->Append(new wxExpr(constraint
->m_xSpacing
));
623 constraintExpr
->Append(new wxExpr(constraint
->m_ySpacing
));
624 constraintExpr
->Append(new wxExpr(constraint
->m_constrainingObject
->GetId()));
626 wxExpr
*objectList
= new wxExpr(wxExprList
);
627 wxNode
*node1
= constraint
->m_constrainedObjects
.GetFirst();
630 wxShape
*obj
= (wxShape
*)node1
->GetData();
631 objectList
->Append(new wxExpr(obj
->GetId()));
632 node1
= node1
->GetNext();
634 constraintExpr
->Append(objectList
);
636 clause
->AddAttributeValue(m_constraintNameBuf
, constraintExpr
);
638 node
= node
->GetNext();
642 // Write the ids of all the child images
643 wxExpr
*childrenExpr
= new wxExpr(wxExprList
);
644 node
= m_children
.GetFirst();
647 wxShape
*child
= (wxShape
*)node
->GetData();
648 childrenExpr
->Append(new wxExpr(child
->GetId()));
649 node
= node
->GetNext();
651 clause
->AddAttributeValue("children", childrenExpr
);
653 // Write the ids of all the division images
654 if (m_divisions
.GetCount() > 0)
656 wxExpr
*divisionsExpr
= new wxExpr(wxExprList
);
657 node
= m_divisions
.GetFirst();
660 wxShape
*child
= (wxShape
*)node
->GetData();
661 divisionsExpr
->Append(new wxExpr(child
->GetId()));
662 node
= node
->GetNext();
664 clause
->AddAttributeValue("divisions", divisionsExpr
);
668 // Problem. Child images are always written AFTER the parent
669 // so as to be able to link up to parent. So we may not be able
670 // to find the constraint participants until we've read everything
671 // in. Need to have another pass for composites.
672 void wxCompositeShape::ReadAttributes(wxExpr
*clause
)
674 wxRectangleShape::ReadAttributes(clause
);
676 // clause->GetAttributeValue("selectable", selectable);
679 void wxCompositeShape::ReadConstraints(wxExpr
*clause
, wxExprDatabase
*database
)
681 // Constraints are output as constraint1 = (...), constraint2 = (...), etc.
682 int constraintNo
= 1;
683 char m_constraintNameBuf
[20];
684 bool haveConstraints
= TRUE
;
686 while (haveConstraints
)
688 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
689 wxExpr
*constraintExpr
= NULL
;
690 clause
->GetAttributeValue(m_constraintNameBuf
, &constraintExpr
);
693 haveConstraints
= FALSE
;
697 double cXSpacing
= 0.0;
698 double cYSpacing
= 0.0;
701 wxShape
*m_constrainingObject
= NULL
;
702 wxList m_constrainedObjects
;
704 // Each constraint is stored in the form
705 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
707 wxExpr
*typeExpr
= constraintExpr
->Nth(0);
708 wxExpr
*nameExpr
= constraintExpr
->Nth(1);
709 wxExpr
*idExpr
= constraintExpr
->Nth(2);
710 wxExpr
*xExpr
= constraintExpr
->Nth(3);
711 wxExpr
*yExpr
= constraintExpr
->Nth(4);
712 wxExpr
*constrainingExpr
= constraintExpr
->Nth(5);
713 wxExpr
*constrainedExpr
= constraintExpr
->Nth(6);
715 cType
= (int)typeExpr
->IntegerValue();
716 cXSpacing
= xExpr
->RealValue();
717 cYSpacing
= yExpr
->RealValue();
718 cName
= nameExpr
->StringValue();
719 cId
= idExpr
->IntegerValue();
721 wxExpr
*objExpr1
= database
->HashFind("node_image", constrainingExpr
->IntegerValue());
722 if (objExpr1
&& objExpr1
->GetClientData())
723 m_constrainingObject
= (wxShape
*)objExpr1
->GetClientData();
725 wxLogFatalError(wxT("Object graphics error: Couldn't find constraining image of composite."));
728 wxExpr
*currentIdExpr
= constrainedExpr
->Nth(i
);
729 while (currentIdExpr
)
731 long currentId
= currentIdExpr
->IntegerValue();
732 wxExpr
*objExpr2
= database
->HashFind("node_image", currentId
);
733 if (objExpr2
&& objExpr2
->GetClientData())
735 m_constrainedObjects
.Append((wxShape
*)objExpr2
->GetClientData());
739 wxLogFatalError(wxT("Object graphics error: Couldn't find constrained image of composite."));
743 currentIdExpr
= constrainedExpr
->Nth(i
);
745 wxOGLConstraint
*newConstraint
= AddConstraint(cType
, m_constrainingObject
, m_constrainedObjects
);
746 newConstraint
->SetSpacing(cXSpacing
, cYSpacing
);
747 newConstraint
->m_constraintId
= cId
;
748 newConstraint
->m_constraintName
= cName
;
754 // Make this composite into a container by creating one wxDivisionShape
755 void wxCompositeShape::MakeContainer()
757 wxDivisionShape
*division
= OnCreateDivision();
758 m_divisions
.Append(division
);
761 division
->SetSize(m_width
, m_height
);
763 wxClientDC
dc(GetCanvas());
764 GetCanvas()->PrepareDC(dc
);
766 division
->Move(dc
, GetX(), GetY());
768 division
->Show(TRUE
);
771 wxDivisionShape
*wxCompositeShape::OnCreateDivision()
773 return new wxDivisionShape
;
776 wxShape
*wxCompositeShape::FindContainerImage()
778 wxNode
*node
= m_children
.GetFirst();
781 wxShape
*child
= (wxShape
*)node
->GetData();
782 if (!m_divisions
.Member(child
))
784 node
= node
->GetNext();
789 // Returns TRUE if division is a descendant of this container
790 bool wxCompositeShape::ContainsDivision(wxDivisionShape
*division
)
792 if (m_divisions
.Member(division
))
794 wxNode
*node
= m_children
.GetFirst();
797 wxShape
*child
= (wxShape
*)node
->GetData();
798 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
800 bool ans
= ((wxCompositeShape
*)child
)->ContainsDivision(division
);
804 node
= node
->GetNext();
814 IMPLEMENT_DYNAMIC_CLASS(wxDivisionShape
, wxCompositeShape
)
816 wxDivisionShape::wxDivisionShape()
818 SetSensitivityFilter(OP_CLICK_LEFT
| OP_CLICK_RIGHT
| OP_DRAG_RIGHT
);
819 SetCentreResize(FALSE
);
820 SetAttachmentMode(TRUE
);
825 m_handleSide
= DIVISION_SIDE_NONE
;
826 m_leftSidePen
= wxBLACK_PEN
;
827 m_topSidePen
= wxBLACK_PEN
;
828 m_leftSideColour
= wxT("BLACK");
829 m_topSideColour
= wxT("BLACK");
830 m_leftSideStyle
= wxT("Solid");
831 m_topSideStyle
= wxT("Solid");
835 wxDivisionShape::~wxDivisionShape()
839 void wxDivisionShape::OnDraw(wxDC
& dc
)
841 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
842 dc
.SetBackgroundMode(wxTRANSPARENT
);
844 double x1
= (double)(GetX() - (GetWidth()/2.0));
845 double y1
= (double)(GetY() - (GetHeight()/2.0));
846 double x2
= (double)(GetX() + (GetWidth()/2.0));
847 double y2
= (double)(GetY() + (GetHeight()/2.0));
849 // Should subtract 1 pixel if drawing under Windows
856 dc
.SetPen(* m_leftSidePen
);
857 dc
.DrawLine(WXROUND(x1
), WXROUND(y2
), WXROUND(x1
), WXROUND(y1
));
861 dc
.SetPen(* m_topSidePen
);
862 dc
.DrawLine(WXROUND(x1
), WXROUND(y1
), WXROUND(x2
), WXROUND(y1
));
865 // For testing purposes, draw a rectangle so we know
866 // how big the division is.
867 // SetBrush(* wxCYAN_BRUSH);
868 // wxRectangleShape::OnDraw(dc);
871 void wxDivisionShape::OnDrawContents(wxDC
& dc
)
873 wxCompositeShape::OnDrawContents(dc
);
876 bool wxDivisionShape::OnMovePre(wxDC
& dc
, double x
, double y
, double oldx
, double oldy
, bool display
)
878 double diffX
= x
- oldx
;
879 double diffY
= y
- oldy
;
880 wxNode
*node
= m_children
.GetFirst();
883 wxShape
*object
= (wxShape
*)node
->GetData();
885 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
886 node
= node
->GetNext();
891 void wxDivisionShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
893 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
899 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
900 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
904 wxShape::OnDragLeft(draw
, x
, y
, keys
, attachment
);
907 void wxDivisionShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
909 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
915 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
916 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
921 wxShape::OnBeginDragLeft(x
, y
, keys
, attachment
);
924 void wxDivisionShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
926 m_canvas
->ReleaseMouse();
927 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
933 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
934 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
939 wxClientDC
dc(GetCanvas());
940 GetCanvas()->PrepareDC(dc
);
942 dc
.SetLogicalFunction(wxCOPY
);
944 m_canvas
->Snap(&m_xpos
, &m_ypos
);
945 GetEventHandler()->OnMovePre(dc
, x
, y
, m_oldX
, m_oldY
);
947 ResetControlPoints();
950 GetEventHandler()->OnDrawControlPoints(dc
);
952 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
955 void wxDivisionShape::SetSize(double w
, double h
, bool recursive
)
959 wxRectangleShape::SetSize(w
, h
, recursive
);
962 void wxDivisionShape::CalculateSize()
966 void wxDivisionShape::Copy(wxShape
& copy
)
968 wxCompositeShape::Copy(copy
);
970 wxASSERT( copy
.IsKindOf(CLASSINFO(wxDivisionShape
)) ) ;
972 wxDivisionShape
& divisionCopy
= (wxDivisionShape
&) copy
;
974 divisionCopy
.m_leftSideStyle
= m_leftSideStyle
;
975 divisionCopy
.m_topSideStyle
= m_topSideStyle
;
976 divisionCopy
.m_leftSideColour
= m_leftSideColour
;
977 divisionCopy
.m_topSideColour
= m_topSideColour
;
979 divisionCopy
.m_leftSidePen
= m_leftSidePen
;
980 divisionCopy
.m_topSidePen
= m_topSidePen
;
981 divisionCopy
.m_handleSide
= m_handleSide
;
983 // Division geometry copying is handled at the wxCompositeShape level.
987 void wxDivisionShape::WriteAttributes(wxExpr
*clause
)
989 wxCompositeShape::WriteAttributes(clause
);
992 clause
->AddAttributeValue("left_side", (long)m_leftSide
->GetId());
994 clause
->AddAttributeValue("top_side", (long)m_topSide
->GetId());
996 clause
->AddAttributeValue("right_side", (long)m_rightSide
->GetId());
998 clause
->AddAttributeValue("bottom_side", (long)m_bottomSide
->GetId());
1000 clause
->AddAttributeValue("handle_side", (long)m_handleSide
);
1001 clause
->AddAttributeValueString("left_colour", m_leftSideColour
);
1002 clause
->AddAttributeValueString("top_colour", m_topSideColour
);
1003 clause
->AddAttributeValueString("left_style", m_leftSideStyle
);
1004 clause
->AddAttributeValueString("top_style", m_topSideStyle
);
1007 void wxDivisionShape::ReadAttributes(wxExpr
*clause
)
1009 wxCompositeShape::ReadAttributes(clause
);
1011 clause
->GetAttributeValue("handle_side", m_handleSide
);
1012 clause
->GetAttributeValue("left_colour", m_leftSideColour
);
1013 clause
->GetAttributeValue("top_colour", m_topSideColour
);
1014 clause
->GetAttributeValue("left_style", m_leftSideStyle
);
1015 clause
->GetAttributeValue("top_style", m_topSideStyle
);
1020 void wxDivisionShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
1022 if (keys
& KEY_CTRL
)
1027 else if (keys & KEY_SHIFT)
1029 if (m_leftSide || m_topSide || m_rightSide || m_bottomSide)
1034 GetParent()->Draw(dc);
1047 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1048 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1055 // Divide wxHORIZONTALly or wxVERTICALly
1056 bool wxDivisionShape::Divide(int direction
)
1058 // Calculate existing top-left, bottom-right
1059 double x1
= (double)(GetX() - (GetWidth()/2.0));
1060 double y1
= (double)(GetY() - (GetHeight()/2.0));
1061 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1062 double oldWidth
= GetWidth();
1063 double oldHeight
= GetHeight();
1067 wxClientDC
dc(GetCanvas());
1068 GetCanvas()->PrepareDC(dc
);
1070 if (direction
== wxVERTICAL
)
1072 // Dividing vertically means notionally putting a horizontal line through it.
1073 // Break existing piece into two.
1074 double newXPos1
= GetX();
1075 double newYPos1
= (double)(y1
+ (GetHeight()/4.0));
1076 double newXPos2
= GetX();
1077 double newYPos2
= (double)(y1
+ (3.0*GetHeight()/4.0));
1078 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1079 newDivision
->Show(TRUE
);
1083 // Anything adjoining the bottom of this division now adjoins the
1084 // bottom of the new division.
1085 wxNode
*node
= compositeParent
->GetDivisions().GetFirst();
1088 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->GetData();
1089 if (obj
->GetTopSide() == this)
1090 obj
->SetTopSide(newDivision
);
1091 node
= node
->GetNext();
1093 newDivision
->SetTopSide(this);
1094 newDivision
->SetBottomSide(m_bottomSide
);
1095 newDivision
->SetLeftSide(m_leftSide
);
1096 newDivision
->SetRightSide(m_rightSide
);
1097 m_bottomSide
= newDivision
;
1099 compositeParent
->GetDivisions().Append(newDivision
);
1101 // CHANGE: Need to insert this division at start of divisions in the object
1102 // list, because e.g.:
1104 // 2) Add contained object
1106 // Division is now receiving mouse events _before_ the contained object,
1107 // because it was added last (on top of all others)
1109 // Add after the image that visualizes the container
1110 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1112 m_handleSide
= DIVISION_SIDE_BOTTOM
;
1113 newDivision
->SetHandleSide(DIVISION_SIDE_TOP
);
1115 SetSize(oldWidth
, (double)(oldHeight
/2.0));
1116 Move(dc
, newXPos1
, newYPos1
);
1118 newDivision
->SetSize(oldWidth
, (double)(oldHeight
/2.0));
1119 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1123 // Dividing horizontally means notionally putting a vertical line through it.
1124 // Break existing piece into two.
1125 double newXPos1
= (double)(x1
+ (GetWidth()/4.0));
1126 double newYPos1
= GetY();
1127 double newXPos2
= (double)(x1
+ (3.0*GetWidth()/4.0));
1128 double newYPos2
= GetY();
1129 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1130 newDivision
->Show(TRUE
);
1134 // Anything adjoining the left of this division now adjoins the
1135 // left of the new division.
1136 wxNode
*node
= compositeParent
->GetDivisions().GetFirst();
1139 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->GetData();
1140 if (obj
->GetLeftSide() == this)
1141 obj
->SetLeftSide(newDivision
);
1142 node
= node
->GetNext();
1144 newDivision
->SetTopSide(m_topSide
);
1145 newDivision
->SetBottomSide(m_bottomSide
);
1146 newDivision
->SetLeftSide(this);
1147 newDivision
->SetRightSide(m_rightSide
);
1148 m_rightSide
= newDivision
;
1150 compositeParent
->GetDivisions().Append(newDivision
);
1151 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1153 m_handleSide
= DIVISION_SIDE_RIGHT
;
1154 newDivision
->SetHandleSide(DIVISION_SIDE_LEFT
);
1156 SetSize((double)(oldWidth
/2.0), oldHeight
);
1157 Move(dc
, newXPos1
, newYPos1
);
1159 newDivision
->SetSize((double)(oldWidth
/2.0), oldHeight
);
1160 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1162 if (compositeParent
->Selected())
1164 compositeParent
->DeleteControlPoints(& dc
);
1165 compositeParent
->MakeControlPoints();
1166 compositeParent
->MakeMandatoryControlPoints();
1168 compositeParent
->Draw(dc
);
1172 // Make one control point for every visible line
1173 void wxDivisionShape::MakeControlPoints()
1175 MakeMandatoryControlPoints();
1178 void wxDivisionShape::MakeMandatoryControlPoints()
1182 GetBoundingBoxMax(&maxX
, &maxY
);
1188 x = (double)(-maxX/2.0);
1190 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1191 CONTROL_POINT_HORIZONTAL);
1192 m_canvas->AddShape(control);
1193 m_controlPoints.Append(control);
1198 y = (double)(-maxY/2.0);
1199 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1200 CONTROL_POINT_VERTICAL);
1201 m_canvas->AddShape(control);
1202 m_controlPoints.Append(control);
1205 switch (m_handleSide
)
1207 case DIVISION_SIDE_LEFT
:
1209 x
= (double)(-maxX
/2.0);
1211 direction
= CONTROL_POINT_HORIZONTAL
;
1214 case DIVISION_SIDE_TOP
:
1217 y
= (double)(-maxY
/2.0);
1218 direction
= CONTROL_POINT_VERTICAL
;
1221 case DIVISION_SIDE_RIGHT
:
1223 x
= (double)(maxX
/2.0);
1225 direction
= CONTROL_POINT_HORIZONTAL
;
1228 case DIVISION_SIDE_BOTTOM
:
1231 y
= (double)(maxY
/2.0);
1232 direction
= CONTROL_POINT_VERTICAL
;
1238 if (m_handleSide
!= DIVISION_SIDE_NONE
)
1240 wxDivisionControlPoint
*control
= new wxDivisionControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, x
, y
,
1242 m_canvas
->AddShape(control
);
1243 m_controlPoints
.Append(control
);
1247 void wxDivisionShape::ResetControlPoints()
1249 ResetMandatoryControlPoints();
1252 void wxDivisionShape::ResetMandatoryControlPoints()
1254 if (m_controlPoints
.GetCount() < 1)
1259 GetBoundingBoxMax(&maxX
, &maxY
);
1261 wxNode *node = m_controlPoints.GetFirst();
1264 wxDivisionControlPoint *control = (wxDivisionControlPoint *)node->GetData();
1265 if (control->type == CONTROL_POINT_HORIZONTAL)
1267 control->xoffset = (double)(-maxX/2.0); control->m_yoffset = 0.0;
1269 else if (control->type == CONTROL_POINT_VERTICAL)
1271 control->xoffset = 0.0; control->m_yoffset = (double)(-maxY/2.0);
1273 node = node->GetNext();
1276 wxNode
*node
= m_controlPoints
.GetFirst();
1277 if ((m_handleSide
== DIVISION_SIDE_LEFT
) && node
)
1279 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1280 control
->m_xoffset
= (double)(-maxX
/2.0); control
->m_yoffset
= 0.0;
1283 if ((m_handleSide
== DIVISION_SIDE_TOP
) && node
)
1285 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1286 control
->m_xoffset
= 0.0; control
->m_yoffset
= (double)(-maxY
/2.0);
1289 if ((m_handleSide
== DIVISION_SIDE_RIGHT
) && node
)
1291 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1292 control
->m_xoffset
= (double)(maxX
/2.0); control
->m_yoffset
= 0.0;
1295 if ((m_handleSide
== DIVISION_SIDE_BOTTOM
) && node
)
1297 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1298 control
->m_xoffset
= 0.0; control
->m_yoffset
= (double)(maxY
/2.0);
1302 // Adjust a side, returning FALSE if it's not physically possible.
1303 bool wxDivisionShape::AdjustLeft(double left
, bool test
)
1305 double x2
= (double)(GetX() + (GetWidth()/2.0));
1312 double newW
= x2
- left
;
1313 double newX
= (double)(left
+ newW
/2.0);
1314 SetSize(newW
, GetHeight());
1316 wxClientDC
dc(GetCanvas());
1317 GetCanvas()->PrepareDC(dc
);
1319 Move(dc
, newX
, GetY());
1324 bool wxDivisionShape::AdjustTop(double top
, bool test
)
1326 double y2
= (double)(GetY() + (GetHeight()/2.0));
1333 double newH
= y2
- top
;
1334 double newY
= (double)(top
+ newH
/2.0);
1335 SetSize(GetWidth(), newH
);
1337 wxClientDC
dc(GetCanvas());
1338 GetCanvas()->PrepareDC(dc
);
1340 Move(dc
, GetX(), newY
);
1345 bool wxDivisionShape::AdjustRight(double right
, bool test
)
1347 double x1
= (double)(GetX() - (GetWidth()/2.0));
1354 double newW
= right
- x1
;
1355 double newX
= (double)(x1
+ newW
/2.0);
1356 SetSize(newW
, GetHeight());
1358 wxClientDC
dc(GetCanvas());
1359 GetCanvas()->PrepareDC(dc
);
1361 Move(dc
, newX
, GetY());
1366 bool wxDivisionShape::AdjustBottom(double bottom
, bool test
)
1368 double y1
= (double)(GetY() - (GetHeight()/2.0));
1375 double newH
= bottom
- y1
;
1376 double newY
= (double)(y1
+ newH
/2.0);
1377 SetSize(GetWidth(), newH
);
1379 wxClientDC
dc(GetCanvas());
1380 GetCanvas()->PrepareDC(dc
);
1382 Move(dc
, GetX(), newY
);
1387 wxDivisionControlPoint::wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, double size
, double the_xoffset
, double the_yoffset
, int the_type
):
1388 wxControlPoint(the_canvas
, object
, size
, the_xoffset
, the_yoffset
, the_type
)
1390 SetEraseObject(FALSE
);
1393 wxDivisionControlPoint::~wxDivisionControlPoint()
1397 static double originalX
= 0.0;
1398 static double originalY
= 0.0;
1399 static double originalW
= 0.0;
1400 static double originalH
= 0.0;
1402 // Implement resizing of canvas object
1403 void wxDivisionControlPoint::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
1405 wxControlPoint::OnDragLeft(draw
, x
, y
, keys
, attachment
);
1408 void wxDivisionControlPoint::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
1410 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1411 originalX
= division
->GetX();
1412 originalY
= division
->GetY();
1413 originalW
= division
->GetWidth();
1414 originalH
= division
->GetHeight();
1416 wxControlPoint::OnBeginDragLeft(x
, y
, keys
, attachment
);
1419 void wxDivisionControlPoint::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
1421 wxControlPoint::OnEndDragLeft(x
, y
, keys
, attachment
);
1423 wxClientDC
dc(GetCanvas());
1424 GetCanvas()->PrepareDC(dc
);
1426 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1427 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)division
->GetParent();
1429 // Need to check it's within the bounds of the parent composite.
1430 double x1
= (double)(divisionParent
->GetX() - (divisionParent
->GetWidth()/2.0));
1431 double y1
= (double)(divisionParent
->GetY() - (divisionParent
->GetHeight()/2.0));
1432 double x2
= (double)(divisionParent
->GetX() + (divisionParent
->GetWidth()/2.0));
1433 double y2
= (double)(divisionParent
->GetY() + (divisionParent
->GetHeight()/2.0));
1435 // Need to check it has not made the division zero or negative width/height
1436 double dx1
= (double)(division
->GetX() - (division
->GetWidth()/2.0));
1437 double dy1
= (double)(division
->GetY() - (division
->GetHeight()/2.0));
1438 double dx2
= (double)(division
->GetX() + (division
->GetWidth()/2.0));
1439 double dy2
= (double)(division
->GetY() + (division
->GetHeight()/2.0));
1441 bool success
= TRUE
;
1442 switch (division
->GetHandleSide())
1444 case DIVISION_SIDE_LEFT
:
1446 if ((x
<= x1
) || (x
>= x2
) || (x
>= dx2
))
1448 // Try it out first...
1449 else if (!division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, TRUE
))
1452 division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, FALSE
);
1456 case DIVISION_SIDE_TOP
:
1458 if ((y
<= y1
) || (y
>= y2
) || (y
>= dy2
))
1460 else if (!division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, TRUE
))
1463 division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, FALSE
);
1467 case DIVISION_SIDE_RIGHT
:
1469 if ((x
<= x1
) || (x
>= x2
) || (x
<= dx1
))
1471 else if (!division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, TRUE
))
1474 division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, FALSE
);
1478 case DIVISION_SIDE_BOTTOM
:
1480 if ((y
<= y1
) || (y
>= y2
) || (y
<= dy1
))
1482 else if (!division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, TRUE
))
1485 division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, FALSE
);
1492 division
->SetSize(originalW
, originalH
);
1493 division
->Move(dc
, originalX
, originalY
);
1495 divisionParent
->Draw(dc
);
1496 division
->GetEventHandler()->OnDrawControlPoints(dc
);
1499 /* Resize adjoining divisions.
1501 Behaviour should be as follows:
1502 If right edge moves, find all objects whose left edge
1503 adjoins this object, and move left edge accordingly.
1504 If left..., move ... right.
1505 If top..., move ... bottom.
1506 If bottom..., move top.
1507 If size goes to zero or end position is other side of start position,
1508 resize to original size and return.
1510 bool wxDivisionShape::ResizeAdjoining(int side
, double newPos
, bool test
)
1512 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)GetParent();
1513 wxNode
*node
= divisionParent
->GetDivisions().GetFirst();
1516 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
1519 case DIVISION_SIDE_LEFT
:
1521 if (division
->m_rightSide
== this)
1523 bool success
= division
->AdjustRight(newPos
, test
);
1524 if (!success
&& test
)
1529 case DIVISION_SIDE_TOP
:
1531 if (division
->m_bottomSide
== this)
1533 bool success
= division
->AdjustBottom(newPos
, test
);
1534 if (!success
&& test
)
1539 case DIVISION_SIDE_RIGHT
:
1541 if (division
->m_leftSide
== this)
1543 bool success
= division
->AdjustLeft(newPos
, test
);
1544 if (!success
&& test
)
1549 case DIVISION_SIDE_BOTTOM
:
1551 if (division
->m_topSide
== this)
1553 bool success
= division
->AdjustTop(newPos
, test
);
1554 if (!success
&& test
)
1562 node
= node
->GetNext();
1569 * Popup menu for editing divisions
1572 class OGLPopupDivisionMenu
: public wxMenu
{
1574 OGLPopupDivisionMenu() : wxMenu() {
1575 Append(DIVISION_MENU_SPLIT_HORIZONTALLY
, wxT("Split horizontally"));
1576 Append(DIVISION_MENU_SPLIT_VERTICALLY
, wxT("Split vertically"));
1578 Append(DIVISION_MENU_EDIT_LEFT_EDGE
, wxT("Edit left edge"));
1579 Append(DIVISION_MENU_EDIT_TOP_EDGE
, wxT("Edit top edge"));
1582 void OnMenu(wxCommandEvent
& event
);
1584 DECLARE_EVENT_TABLE()
1587 BEGIN_EVENT_TABLE(OGLPopupDivisionMenu
, wxMenu
)
1588 EVT_CUSTOM_RANGE(wxEVT_COMMAND_MENU_SELECTED
,
1589 DIVISION_MENU_SPLIT_HORIZONTALLY
,
1590 DIVISION_MENU_EDIT_BOTTOM_EDGE
,
1591 OGLPopupDivisionMenu::OnMenu
)
1595 void OGLPopupDivisionMenu::OnMenu(wxCommandEvent
& event
)
1597 wxDivisionShape
*division
= (wxDivisionShape
*)GetClientData();
1598 switch (event
.GetInt())
1600 case DIVISION_MENU_SPLIT_HORIZONTALLY
:
1602 division
->Divide(wxHORIZONTAL
);
1605 case DIVISION_MENU_SPLIT_VERTICALLY
:
1607 division
->Divide(wxVERTICAL
);
1610 case DIVISION_MENU_EDIT_LEFT_EDGE
:
1612 division
->EditEdge(DIVISION_SIDE_LEFT
);
1615 case DIVISION_MENU_EDIT_TOP_EDGE
:
1617 division
->EditEdge(DIVISION_SIDE_TOP
);
1625 void wxDivisionShape::EditEdge(int side
)
1627 wxMessageBox(wxT("EditEdge() not implemented"), wxT("OGL"), wxOK
);
1630 wxBeginBusyCursor();
1632 wxPen
*currentPen
= NULL
;
1633 char **pColour
= NULL
;
1634 char **pStyle
= NULL
;
1635 if (side
== DIVISION_SIDE_LEFT
)
1637 currentPen
= m_leftSidePen
;
1638 pColour
= &m_leftSideColour
;
1639 pStyle
= &m_leftSideStyle
;
1643 currentPen
= m_topSidePen
;
1644 pColour
= &m_topSideColour
;
1645 pStyle
= &m_topSideStyle
;
1648 GraphicsForm
*form
= new GraphicsForm("Containers");
1649 int lineWidth
= currentPen
->GetWidth();
1651 form
->Add(wxMakeFormShort("Width", &lineWidth
, wxFORM_DEFAULT
, NULL
, NULL
, wxVERTICAL
,
1653 form
->Add(wxMakeFormString("Colour", pColour
, wxFORM_CHOICE
,
1654 new wxList(wxMakeConstraintStrings(
1678 NULL
), NULL
, wxVERTICAL
, 150));
1679 form
->Add(wxMakeFormString("Style", pStyle
, wxFORM_CHOICE
,
1680 new wxList(wxMakeConstraintStrings(
1687 NULL
), NULL
, wxVERTICAL
, 100));
1689 wxDialogBox
*dialog
= new wxDialogBox(m_canvas
->GetParent(), "Division properties", 10, 10, 500, 500);
1690 if (GraphicsLabelFont
)
1691 dialog
->SetLabelFont(GraphicsLabelFont
);
1692 if (GraphicsButtonFont
)
1693 dialog
->SetButtonFont(GraphicsButtonFont
);
1695 form
->AssociatePanel(dialog
);
1696 form
->dialog
= dialog
;
1699 dialog
->Centre(wxBOTH
);
1704 int lineStyle
= wxSOLID
;
1707 if (strcmp(*pStyle
, "Solid") == 0)
1708 lineStyle
= wxSOLID
;
1709 else if (strcmp(*pStyle
, "Dot") == 0)
1711 else if (strcmp(*pStyle
, "Short Dash") == 0)
1712 lineStyle
= wxSHORT_DASH
;
1713 else if (strcmp(*pStyle
, "Long Dash") == 0)
1714 lineStyle
= wxLONG_DASH
;
1715 else if (strcmp(*pStyle
, "Dot Dash") == 0)
1716 lineStyle
= wxDOT_DASH
;
1719 wxPen
*newPen
= wxThePenList
->FindOrCreatePen(*pColour
, lineWidth
, lineStyle
);
1722 if (side
== DIVISION_SIDE_LEFT
)
1723 m_leftSidePen
= newPen
;
1725 m_topSidePen
= newPen
;
1727 // Need to draw whole image again
1728 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1729 compositeParent
->Draw(dc
);
1734 void wxDivisionShape::PopupMenu(double x
, double y
)
1736 wxMenu
* oglPopupDivisionMenu
= new OGLPopupDivisionMenu
;
1738 oglPopupDivisionMenu
->SetClientData((void *)this);
1740 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, TRUE
);
1742 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, FALSE
);
1744 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, TRUE
);
1746 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, FALSE
);
1749 m_canvas
->GetViewStart(&x1
, &y1
);
1752 m_canvas
->GetScrollPixelsPerUnit(&unit_x
, &unit_y
);
1754 wxClientDC
dc(GetCanvas());
1755 GetCanvas()->PrepareDC(dc
);
1757 int mouse_x
= (int)(dc
.LogicalToDeviceX((long)(x
- x1
*unit_x
)));
1758 int mouse_y
= (int)(dc
.LogicalToDeviceY((long)(y
- y1
*unit_y
)));
1760 m_canvas
->PopupMenu(oglPopupDivisionMenu
, mouse_x
, mouse_y
);
1761 delete oglPopupDivisionMenu
;
1764 void wxDivisionShape::SetLeftSideColour(const wxString
& colour
)
1766 m_leftSideColour
= colour
;
1769 void wxDivisionShape::SetTopSideColour(const wxString
& colour
)
1771 m_topSideColour
= colour
;
1774 void wxDivisionShape::SetLeftSideStyle(const wxString
& style
)
1776 m_leftSideStyle
= style
;
1779 void wxDivisionShape::SetTopSideStyle(const wxString
& style
)
1781 m_topSideStyle
= style
;