1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Composite OGL class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
24 #include "wx/deprecated/wxexpr.h"
27 #include "wx/ogl/ogl.h"
31 // Sometimes, objects need to access the whole database to
32 // construct themselves.
33 wxExprDatabase
*GlobalwxExprDatabase
= NULL
;
37 * Division control point
40 class wxDivisionControlPoint
: public wxControlPoint
42 DECLARE_DYNAMIC_CLASS(wxDivisionControlPoint
)
44 wxDivisionControlPoint() {}
45 wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, double size
, double the_xoffset
, double the_yoffset
, int the_type
);
46 ~wxDivisionControlPoint();
48 void OnDragLeft(bool draw
, double x
, double y
, int keys
=0, int attachment
= 0);
49 void OnBeginDragLeft(double x
, double y
, int keys
=0, int attachment
= 0);
50 void OnEndDragLeft(double x
, double y
, int keys
=0, int attachment
= 0);
53 IMPLEMENT_DYNAMIC_CLASS(wxDivisionControlPoint
, wxControlPoint
)
60 IMPLEMENT_DYNAMIC_CLASS(wxCompositeShape
, wxRectangleShape
)
62 wxCompositeShape::wxCompositeShape(): wxRectangleShape(10.0, 10.0)
64 // selectable = false;
69 wxCompositeShape::~wxCompositeShape()
71 wxNode
*node
= m_constraints
.GetFirst();
74 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
76 node
= node
->GetNext();
78 node
= m_children
.GetFirst();
81 wxShape
*object
= (wxShape
*)node
->GetData();
82 wxNode
*next
= node
->GetNext();
89 void wxCompositeShape::OnDraw(wxDC
& dc
)
91 double x1
= (double)(m_xpos
- m_width
/2.0);
92 double y1
= (double)(m_ypos
- m_height
/2.0);
94 if (m_shadowMode
!= SHADOW_NONE
)
97 dc
.SetBrush(* m_shadowBrush
);
98 dc
.SetPen(* g_oglTransparentPen
);
100 if (m_cornerRadius
!= 0.0)
101 dc
.DrawRoundedRectangle(WXROUND(x1
+ m_shadowOffsetX
), WXROUND(y1
+ m_shadowOffsetY
),
102 WXROUND(m_width
), WXROUND(m_height
), m_cornerRadius
);
104 dc
.DrawRectangle(WXROUND(x1
+ m_shadowOffsetX
), WXROUND(y1
+ m_shadowOffsetY
), WXROUND(m_width
), WXROUND(m_height
));
108 void wxCompositeShape::OnDrawContents(wxDC
& dc
)
110 wxNode
*node
= m_children
.GetFirst();
113 wxShape
*object
= (wxShape
*)node
->GetData();
115 object
->DrawLinks(dc
);
116 node
= node
->GetNext();
118 wxShape::OnDrawContents(dc
);
121 bool wxCompositeShape::OnMovePre(wxDC
& dc
, double x
, double y
, double oldx
, double oldy
, bool display
)
123 double diffX
= x
- oldx
;
124 double diffY
= y
- oldy
;
125 wxNode
*node
= m_children
.GetFirst();
128 wxShape
*object
= (wxShape
*)node
->GetData();
131 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
133 node
= node
->GetNext();
138 void wxCompositeShape::OnErase(wxDC
& dc
)
140 wxRectangleShape::OnErase(dc
);
141 wxNode
*node
= m_children
.GetFirst();
144 wxShape
*object
= (wxShape
*)node
->GetData();
146 node
= node
->GetNext();
150 static double objectStartX
= 0.0;
151 static double objectStartY
= 0.0;
153 void wxCompositeShape::OnDragLeft(bool WXUNUSED(draw
), double x
, double y
, int WXUNUSED(keys
), int WXUNUSED(attachment
))
157 m_canvas
->Snap(&xx
, &yy
);
158 double offsetX
= xx
- objectStartX
;
159 double offsetY
= yy
- objectStartY
;
161 wxClientDC
dc(GetCanvas());
162 GetCanvas()->PrepareDC(dc
);
164 dc
.SetLogicalFunction(OGLRBLF
);
165 wxPen
dottedPen(*wxBLACK
, 1, wxDOT
);
166 dc
.SetPen(dottedPen
);
167 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
169 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
170 // wxShape::OnDragLeft(draw, x, y, keys, attachment);
173 void wxCompositeShape::OnBeginDragLeft(double x
, double y
, int WXUNUSED(keys
), int WXUNUSED(attachment
))
178 wxClientDC
dc(GetCanvas());
179 GetCanvas()->PrepareDC(dc
);
183 dc
.SetLogicalFunction(OGLRBLF
);
185 wxPen
dottedPen(*wxBLACK
, 1, wxDOT
);
186 dc
.SetPen(dottedPen
);
187 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
188 m_canvas
->CaptureMouse();
192 m_canvas
->Snap(&xx
, &yy
);
193 double offsetX
= xx
- objectStartX
;
194 double offsetY
= yy
- objectStartY
;
196 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
198 // wxShape::OnBeginDragLeft(x, y, keys, attachment);
201 void wxCompositeShape::OnEndDragLeft(double x
, double y
, int keys
, int WXUNUSED(attachment
))
203 // wxShape::OnEndDragLeft(x, y, keys, attachment);
205 wxClientDC
dc(GetCanvas());
206 GetCanvas()->PrepareDC(dc
);
208 m_canvas
->ReleaseMouse();
212 if (m_parent
) m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, 0);
216 dc
.SetLogicalFunction(wxCOPY
);
219 m_canvas
->Snap(&xx
, &yy
);
220 double offsetX
= xx
- objectStartX
;
221 double offsetY
= yy
- objectStartY
;
223 Move(dc
, GetX() + offsetX
, GetY() + offsetY
);
225 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
228 void wxCompositeShape::OnRightClick(double x
, double y
, int keys
, int WXUNUSED(attachment
))
230 // If we get a ctrl-right click, this means send the message to
231 // the division, so we can invoke a user interface for dealing with regions.
234 wxNode
*node
= m_divisions
.GetFirst();
237 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
238 wxNode
*next
= node
->GetNext();
241 if (division
->HitTest(x
, y
, &attach
, &dist
))
243 division
->GetEventHandler()->OnRightClick(x
, y
, keys
, attach
);
252 void wxCompositeShape::SetSize(double w
, double h
, bool recursive
)
254 SetAttachmentSize(w
, h
);
256 double xScale
= (double)(w
/(wxMax(1.0, GetWidth())));
257 double yScale
= (double)(h
/(wxMax(1.0, GetHeight())));
262 if (!recursive
) return;
264 wxNode
*node
= m_children
.GetFirst();
266 wxClientDC
dc(GetCanvas());
267 GetCanvas()->PrepareDC(dc
);
269 double xBound
, yBound
;
272 wxShape
*object
= (wxShape
*)node
->GetData();
274 // Scale the position first
275 double newX
= (double)(((object
->GetX() - GetX())*xScale
) + GetX());
276 double newY
= (double)(((object
->GetY() - GetY())*yScale
) + GetY());
278 object
->Move(dc
, newX
, newY
);
281 // Now set the scaled size
282 object
->GetBoundingBoxMin(&xBound
, &yBound
);
283 object
->SetSize(object
->GetFixedWidth() ? xBound
: xScale
*xBound
,
284 object
->GetFixedHeight() ? yBound
: yScale
*yBound
);
286 node
= node
->GetNext();
288 SetDefaultRegionSize();
291 void wxCompositeShape::AddChild(wxShape
*child
, wxShape
*addAfter
)
293 m_children
.Append(child
);
294 child
->SetParent(this);
297 // Ensure we add at the right position
299 child
->RemoveFromCanvas(m_canvas
);
300 child
->AddToCanvas(m_canvas
, addAfter
);
304 void wxCompositeShape::RemoveChild(wxShape
*child
)
306 m_children
.DeleteObject(child
);
307 m_divisions
.DeleteObject(child
);
308 RemoveChildFromConstraints(child
);
309 child
->SetParent(NULL
);
312 void wxCompositeShape::DeleteConstraintsInvolvingChild(wxShape
*child
)
314 wxNode
*node
= m_constraints
.GetFirst();
317 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
318 wxNode
*nextNode
= node
->GetNext();
320 if ((constraint
->m_constrainingObject
== child
) ||
321 constraint
->m_constrainedObjects
.Member(child
))
330 void wxCompositeShape::RemoveChildFromConstraints(wxShape
*child
)
332 wxNode
*node
= m_constraints
.GetFirst();
335 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
336 wxNode
*nextNode
= node
->GetNext();
338 if (constraint
->m_constrainedObjects
.Member(child
))
339 constraint
->m_constrainedObjects
.DeleteObject(child
);
340 if (constraint
->m_constrainingObject
== child
)
341 constraint
->m_constrainingObject
= NULL
;
343 // Delete the constraint if no participants left
344 if (!constraint
->m_constrainingObject
)
354 void wxCompositeShape::Copy(wxShape
& copy
)
356 wxRectangleShape::Copy(copy
);
358 wxASSERT( copy
.IsKindOf(CLASSINFO(wxCompositeShape
)) ) ;
360 wxCompositeShape
& compositeCopy
= (wxCompositeShape
&) copy
;
362 // Associate old and new copies for compositeCopying constraints and division geometry
363 oglObjectCopyMapping
.Append((long)this, &compositeCopy
);
366 wxNode
*node
= m_children
.GetFirst();
369 wxShape
*object
= (wxShape
*)node
->GetData();
370 wxShape
*newObject
= object
->CreateNewCopy(false, false);
371 if (newObject
->GetId() == 0)
372 newObject
->SetId(wxNewId());
374 newObject
->SetParent(&compositeCopy
);
375 compositeCopy
.m_children
.Append(newObject
);
377 // Some m_children may be divisions
378 if (m_divisions
.Member(object
))
379 compositeCopy
.m_divisions
.Append(newObject
);
381 oglObjectCopyMapping
.Append((long)object
, newObject
);
383 node
= node
->GetNext();
386 // Copy the constraints
387 node
= m_constraints
.GetFirst();
390 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
392 wxShape
*newConstraining
= (wxShape
*)(oglObjectCopyMapping
.Find((long)constraint
->m_constrainingObject
)->GetData());
394 wxList newConstrainedList
;
395 wxNode
*node2
= constraint
->m_constrainedObjects
.GetFirst();
398 wxShape
*constrainedObject
= (wxShape
*)node2
->GetData();
399 wxShape
*newConstrained
= (wxShape
*)(oglObjectCopyMapping
.Find((long)constrainedObject
)->GetData());
400 newConstrainedList
.Append(newConstrained
);
401 node2
= node2
->GetNext();
404 wxOGLConstraint
*newConstraint
= new wxOGLConstraint(constraint
->m_constraintType
, newConstraining
,
406 newConstraint
->m_constraintId
= constraint
->m_constraintId
;
407 if (constraint
->m_constraintName
)
409 newConstraint
->m_constraintName
= constraint
->m_constraintName
;
411 newConstraint
->SetSpacing(constraint
->m_xSpacing
, constraint
->m_ySpacing
);
412 compositeCopy
.m_constraints
.Append(newConstraint
);
414 node
= node
->GetNext();
417 // Now compositeCopy the division geometry
418 node
= m_divisions
.GetFirst();
421 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
422 wxNode
*node1
= oglObjectCopyMapping
.Find((long)division
);
423 wxNode
*leftNode
= NULL
;
424 wxNode
*topNode
= NULL
;
425 wxNode
*rightNode
= NULL
;
426 wxNode
*bottomNode
= NULL
;
427 if (division
->GetLeftSide())
428 leftNode
= oglObjectCopyMapping
.Find((long)division
->GetLeftSide());
429 if (division
->GetTopSide())
430 topNode
= oglObjectCopyMapping
.Find((long)division
->GetTopSide());
431 if (division
->GetRightSide())
432 rightNode
= oglObjectCopyMapping
.Find((long)division
->GetRightSide());
433 if (division
->GetBottomSide())
434 bottomNode
= oglObjectCopyMapping
.Find((long)division
->GetBottomSide());
437 wxDivisionShape
*newDivision
= (wxDivisionShape
*)node1
->GetData();
439 newDivision
->SetLeftSide((wxDivisionShape
*)leftNode
->GetData());
441 newDivision
->SetTopSide((wxDivisionShape
*)topNode
->GetData());
443 newDivision
->SetRightSide((wxDivisionShape
*)rightNode
->GetData());
445 newDivision
->SetBottomSide((wxDivisionShape
*)bottomNode
->GetData());
447 node
= node
->GetNext();
451 wxOGLConstraint
*wxCompositeShape::AddConstraint(wxOGLConstraint
*constraint
)
453 m_constraints
.Append(constraint
);
454 if (constraint
->m_constraintId
== 0)
455 constraint
->m_constraintId
= wxNewId();
459 wxOGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxList
& constrained
)
461 wxOGLConstraint
*constraint
= new wxOGLConstraint(type
, constraining
, constrained
);
462 if (constraint
->m_constraintId
== 0)
463 constraint
->m_constraintId
= wxNewId();
464 m_constraints
.Append(constraint
);
468 wxOGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxShape
*constrained
)
471 l
.Append(constrained
);
472 wxOGLConstraint
*constraint
= new wxOGLConstraint(type
, constraining
, l
);
473 if (constraint
->m_constraintId
== 0)
474 constraint
->m_constraintId
= wxNewId();
475 m_constraints
.Append(constraint
);
479 wxOGLConstraint
*wxCompositeShape::FindConstraint(long cId
, wxCompositeShape
**actualComposite
)
481 wxNode
*node
= m_constraints
.GetFirst();
484 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
485 if (constraint
->m_constraintId
== cId
)
488 *actualComposite
= this;
491 node
= node
->GetNext();
493 // If not found, try children.
494 node
= m_children
.GetFirst();
497 wxShape
*child
= (wxShape
*)node
->GetData();
498 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
500 wxOGLConstraint
*constraint
= ((wxCompositeShape
*)child
)->FindConstraint(cId
, actualComposite
);
504 *actualComposite
= (wxCompositeShape
*)child
;
508 node
= node
->GetNext();
513 void wxCompositeShape::DeleteConstraint(wxOGLConstraint
*constraint
)
515 m_constraints
.DeleteObject(constraint
);
519 void wxCompositeShape::CalculateSize()
521 double maxX
= (double) -999999.9;
522 double maxY
= (double) -999999.9;
523 double minX
= (double) 999999.9;
524 double minY
= (double) 999999.9;
527 wxNode
*node
= m_children
.GetFirst();
530 wxShape
*object
= (wxShape
*)node
->GetData();
532 // Recalculate size of composite objects because may not conform
533 // to size it was set to - depends on the children.
534 object
->CalculateSize();
536 object
->GetBoundingBoxMax(&w
, &h
);
537 if ((object
->GetX() + (w
/2.0)) > maxX
)
538 maxX
= (double)(object
->GetX() + (w
/2.0));
539 if ((object
->GetX() - (w
/2.0)) < minX
)
540 minX
= (double)(object
->GetX() - (w
/2.0));
541 if ((object
->GetY() + (h
/2.0)) > maxY
)
542 maxY
= (double)(object
->GetY() + (h
/2.0));
543 if ((object
->GetY() - (h
/2.0)) < minY
)
544 minY
= (double)(object
->GetY() - (h
/2.0));
546 node
= node
->GetNext();
548 m_width
= maxX
- minX
;
549 m_height
= maxY
- minY
;
550 m_xpos
= (double)(m_width
/2.0 + minX
);
551 m_ypos
= (double)(m_height
/2.0 + minY
);
554 bool wxCompositeShape::Recompute()
556 int noIterations
= 0;
558 while (changed
&& (noIterations
< 500))
560 changed
= Constrain();
566 cerr << "Warning: constraint algorithm failed after 500 iterations.\n";
572 bool wxCompositeShape::Constrain()
576 bool changed
= false;
577 wxNode
*node
= m_children
.GetFirst();
580 wxShape
*object
= (wxShape
*)node
->GetData();
581 if (object
->Constrain())
583 node
= node
->GetNext();
586 node
= m_constraints
.GetFirst();
589 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
590 if (constraint
->Evaluate()) changed
= true;
591 node
= node
->GetNext();
597 void wxCompositeShape::WriteAttributes(wxExpr
*clause
)
599 wxRectangleShape::WriteAttributes(clause
);
601 // clause->AddAttributeValue("selectable", (long)selectable);
603 // Output constraints as constraint1 = (...), constraint2 = (...), etc.
604 int constraintNo
= 1;
605 wxChar m_constraintNameBuf
[20];
606 wxNode
*node
= m_constraints
.GetFirst();
609 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
610 wxSprintf(m_constraintNameBuf
, _T("constraint%d"), constraintNo
);
612 // Each constraint is stored in the form
613 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
614 wxExpr
*constraintExpr
= new wxExpr(wxExprList
);
615 constraintExpr
->Append(new wxExpr((long)constraint
->m_constraintType
));
616 constraintExpr
->Append(new wxExpr(wxExprString
, constraint
->m_constraintName
));
617 constraintExpr
->Append(new wxExpr(constraint
->m_constraintId
));
618 constraintExpr
->Append(new wxExpr(constraint
->m_xSpacing
));
619 constraintExpr
->Append(new wxExpr(constraint
->m_ySpacing
));
620 constraintExpr
->Append(new wxExpr(constraint
->m_constrainingObject
->GetId()));
622 wxExpr
*objectList
= new wxExpr(wxExprList
);
623 wxNode
*node1
= constraint
->m_constrainedObjects
.GetFirst();
626 wxShape
*obj
= (wxShape
*)node1
->GetData();
627 objectList
->Append(new wxExpr(obj
->GetId()));
628 node1
= node1
->GetNext();
630 constraintExpr
->Append(objectList
);
632 clause
->AddAttributeValue(m_constraintNameBuf
, constraintExpr
);
634 node
= node
->GetNext();
638 // Write the ids of all the child images
639 wxExpr
*childrenExpr
= new wxExpr(wxExprList
);
640 node
= m_children
.GetFirst();
643 wxShape
*child
= (wxShape
*)node
->GetData();
644 childrenExpr
->Append(new wxExpr(child
->GetId()));
645 node
= node
->GetNext();
647 clause
->AddAttributeValue(_T("children"), childrenExpr
);
649 // Write the ids of all the division images
650 if (m_divisions
.GetCount() > 0)
652 wxExpr
*divisionsExpr
= new wxExpr(wxExprList
);
653 node
= m_divisions
.GetFirst();
656 wxShape
*child
= (wxShape
*)node
->GetData();
657 divisionsExpr
->Append(new wxExpr(child
->GetId()));
658 node
= node
->GetNext();
660 clause
->AddAttributeValue(_T("divisions"), divisionsExpr
);
664 // Problem. Child images are always written AFTER the parent
665 // so as to be able to link up to parent. So we may not be able
666 // to find the constraint participants until we've read everything
667 // in. Need to have another pass for composites.
668 void wxCompositeShape::ReadAttributes(wxExpr
*clause
)
670 wxRectangleShape::ReadAttributes(clause
);
672 // clause->GetAttributeValue("selectable", selectable);
675 void wxCompositeShape::ReadConstraints(wxExpr
*clause
, wxExprDatabase
*database
)
677 // Constraints are output as constraint1 = (...), constraint2 = (...), etc.
678 int constraintNo
= 1;
679 wxChar m_constraintNameBuf
[20];
680 bool haveConstraints
= true;
682 while (haveConstraints
)
684 wxSprintf(m_constraintNameBuf
, _T("constraint%d"), constraintNo
);
685 wxExpr
*constraintExpr
= NULL
;
686 clause
->GetAttributeValue(m_constraintNameBuf
, &constraintExpr
);
689 haveConstraints
= false;
692 wxString cName
= wxEmptyString
;
693 wxShape
*m_constrainingObject
= NULL
;
694 wxList m_constrainedObjects
;
696 // Each constraint is stored in the form
697 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
699 wxExpr
*typeExpr
= constraintExpr
->Nth(0);
700 wxExpr
*nameExpr
= constraintExpr
->Nth(1);
701 wxExpr
*idExpr
= constraintExpr
->Nth(2);
702 wxExpr
*xExpr
= constraintExpr
->Nth(3);
703 wxExpr
*yExpr
= constraintExpr
->Nth(4);
704 wxExpr
*constrainingExpr
= constraintExpr
->Nth(5);
705 wxExpr
*constrainedExpr
= constraintExpr
->Nth(6);
707 int cType
= (int)typeExpr
->IntegerValue();
708 double cXSpacing
= xExpr
->RealValue();
709 double cYSpacing
= yExpr
->RealValue();
710 cName
= nameExpr
->StringValue();
711 long cId
= idExpr
->IntegerValue();
713 wxExpr
*objExpr1
= database
->HashFind(_T("node_image"), constrainingExpr
->IntegerValue());
714 if (objExpr1
&& objExpr1
->GetClientData())
715 m_constrainingObject
= (wxShape
*)objExpr1
->GetClientData();
717 wxLogFatalError(wxT("Object graphics error: Couldn't find constraining image of composite."));
720 wxExpr
*currentIdExpr
= constrainedExpr
->Nth(i
);
721 while (currentIdExpr
)
723 long currentId
= currentIdExpr
->IntegerValue();
724 wxExpr
*objExpr2
= database
->HashFind(_T("node_image"), currentId
);
725 if (objExpr2
&& objExpr2
->GetClientData())
727 m_constrainedObjects
.Append((wxShape
*)objExpr2
->GetClientData());
731 wxLogFatalError(wxT("Object graphics error: Couldn't find constrained image of composite."));
735 currentIdExpr
= constrainedExpr
->Nth(i
);
737 wxOGLConstraint
*newConstraint
= AddConstraint(cType
, m_constrainingObject
, m_constrainedObjects
);
738 newConstraint
->SetSpacing(cXSpacing
, cYSpacing
);
739 newConstraint
->m_constraintId
= cId
;
740 newConstraint
->m_constraintName
= cName
;
746 // Make this composite into a container by creating one wxDivisionShape
747 void wxCompositeShape::MakeContainer()
749 wxDivisionShape
*division
= OnCreateDivision();
750 m_divisions
.Append(division
);
753 division
->SetSize(m_width
, m_height
);
755 wxClientDC
dc(GetCanvas());
756 GetCanvas()->PrepareDC(dc
);
758 division
->Move(dc
, GetX(), GetY());
760 division
->Show(true);
763 wxDivisionShape
*wxCompositeShape::OnCreateDivision()
765 return new wxDivisionShape
;
768 wxShape
*wxCompositeShape::FindContainerImage()
770 wxNode
*node
= m_children
.GetFirst();
773 wxShape
*child
= (wxShape
*)node
->GetData();
774 if (!m_divisions
.Member(child
))
776 node
= node
->GetNext();
781 // Returns true if division is a descendant of this container
782 bool wxCompositeShape::ContainsDivision(wxDivisionShape
*division
)
784 if (m_divisions
.Member(division
))
786 wxNode
*node
= m_children
.GetFirst();
789 wxShape
*child
= (wxShape
*)node
->GetData();
790 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
792 bool ans
= ((wxCompositeShape
*)child
)->ContainsDivision(division
);
796 node
= node
->GetNext();
806 IMPLEMENT_DYNAMIC_CLASS(wxDivisionShape
, wxCompositeShape
)
808 wxDivisionShape::wxDivisionShape()
810 SetSensitivityFilter(OP_CLICK_LEFT
| OP_CLICK_RIGHT
| OP_DRAG_RIGHT
);
811 SetCentreResize(false);
812 SetAttachmentMode(true);
817 m_handleSide
= DIVISION_SIDE_NONE
;
818 m_leftSidePen
= wxBLACK_PEN
;
819 m_topSidePen
= wxBLACK_PEN
;
820 m_leftSideColour
= wxT("BLACK");
821 m_topSideColour
= wxT("BLACK");
822 m_leftSideStyle
= wxT("Solid");
823 m_topSideStyle
= wxT("Solid");
827 wxDivisionShape::~wxDivisionShape()
831 void wxDivisionShape::OnDraw(wxDC
& dc
)
833 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
834 dc
.SetBackgroundMode(wxTRANSPARENT
);
836 double x1
= (double)(GetX() - (GetWidth()/2.0));
837 double y1
= (double)(GetY() - (GetHeight()/2.0));
838 double x2
= (double)(GetX() + (GetWidth()/2.0));
839 double y2
= (double)(GetY() + (GetHeight()/2.0));
841 // Should subtract 1 pixel if drawing under Windows
848 dc
.SetPen(* m_leftSidePen
);
849 dc
.DrawLine(WXROUND(x1
), WXROUND(y2
), WXROUND(x1
), WXROUND(y1
));
853 dc
.SetPen(* m_topSidePen
);
854 dc
.DrawLine(WXROUND(x1
), WXROUND(y1
), WXROUND(x2
), WXROUND(y1
));
857 // For testing purposes, draw a rectangle so we know
858 // how big the division is.
859 // SetBrush(* wxCYAN_BRUSH);
860 // wxRectangleShape::OnDraw(dc);
863 void wxDivisionShape::OnDrawContents(wxDC
& dc
)
865 wxCompositeShape::OnDrawContents(dc
);
868 bool wxDivisionShape::OnMovePre(wxDC
& dc
, double x
, double y
, double oldx
, double oldy
, bool display
)
870 double diffX
= x
- oldx
;
871 double diffY
= y
- oldy
;
872 wxNode
*node
= m_children
.GetFirst();
875 wxShape
*object
= (wxShape
*)node
->GetData();
877 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
878 node
= node
->GetNext();
883 void wxDivisionShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
885 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
891 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
892 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
896 wxShape::OnDragLeft(draw
, x
, y
, keys
, attachment
);
899 void wxDivisionShape::OnBeginDragLeft(double x
, double 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()->OnBeginDragLeft(x
, y
, keys
, attachment
);
913 wxShape::OnBeginDragLeft(x
, y
, keys
, attachment
);
916 void wxDivisionShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
918 m_canvas
->ReleaseMouse();
919 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
925 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
926 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
931 wxClientDC
dc(GetCanvas());
932 GetCanvas()->PrepareDC(dc
);
934 dc
.SetLogicalFunction(wxCOPY
);
936 m_canvas
->Snap(&m_xpos
, &m_ypos
);
937 GetEventHandler()->OnMovePre(dc
, x
, y
, m_oldX
, m_oldY
);
939 ResetControlPoints();
942 GetEventHandler()->OnDrawControlPoints(dc
);
944 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
947 void wxDivisionShape::SetSize(double w
, double h
, bool recursive
)
951 wxRectangleShape::SetSize(w
, h
, recursive
);
954 void wxDivisionShape::CalculateSize()
958 void wxDivisionShape::Copy(wxShape
& copy
)
960 wxCompositeShape::Copy(copy
);
962 wxASSERT( copy
.IsKindOf(CLASSINFO(wxDivisionShape
)) ) ;
964 wxDivisionShape
& divisionCopy
= (wxDivisionShape
&) copy
;
966 divisionCopy
.m_leftSideStyle
= m_leftSideStyle
;
967 divisionCopy
.m_topSideStyle
= m_topSideStyle
;
968 divisionCopy
.m_leftSideColour
= m_leftSideColour
;
969 divisionCopy
.m_topSideColour
= m_topSideColour
;
971 divisionCopy
.m_leftSidePen
= m_leftSidePen
;
972 divisionCopy
.m_topSidePen
= m_topSidePen
;
973 divisionCopy
.m_handleSide
= m_handleSide
;
975 // Division geometry copying is handled at the wxCompositeShape level.
979 void wxDivisionShape::WriteAttributes(wxExpr
*clause
)
981 wxCompositeShape::WriteAttributes(clause
);
984 clause
->AddAttributeValue(_T("left_side"), (long)m_leftSide
->GetId());
986 clause
->AddAttributeValue(_T("top_side"), (long)m_topSide
->GetId());
988 clause
->AddAttributeValue(_T("right_side"), (long)m_rightSide
->GetId());
990 clause
->AddAttributeValue(_T("bottom_side"), (long)m_bottomSide
->GetId());
992 clause
->AddAttributeValue(_T("handle_side"), (long)m_handleSide
);
993 clause
->AddAttributeValueString(_T("left_colour"), m_leftSideColour
);
994 clause
->AddAttributeValueString(_T("top_colour"), m_topSideColour
);
995 clause
->AddAttributeValueString(_T("left_style"), m_leftSideStyle
);
996 clause
->AddAttributeValueString(_T("top_style"), m_topSideStyle
);
999 void wxDivisionShape::ReadAttributes(wxExpr
*clause
)
1001 wxCompositeShape::ReadAttributes(clause
);
1003 clause
->GetAttributeValue(_T("handle_side"), m_handleSide
);
1004 clause
->GetAttributeValue(_T("left_colour"), m_leftSideColour
);
1005 clause
->GetAttributeValue(_T("top_colour"), m_topSideColour
);
1006 clause
->GetAttributeValue(_T("left_style"), m_leftSideStyle
);
1007 clause
->GetAttributeValue(_T("top_style"), m_topSideStyle
);
1012 void wxDivisionShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
1014 if (keys
& KEY_CTRL
)
1019 else if (keys & KEY_SHIFT)
1021 if (m_leftSide || m_topSide || m_rightSide || m_bottomSide)
1026 GetParent()->Draw(dc);
1039 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1040 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1047 // Divide wxHORIZONTALly or wxVERTICALly
1048 bool wxDivisionShape::Divide(int direction
)
1050 // Calculate existing top-left, bottom-right
1051 double x1
= (double)(GetX() - (GetWidth()/2.0));
1052 double y1
= (double)(GetY() - (GetHeight()/2.0));
1053 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1054 double oldWidth
= GetWidth();
1055 double oldHeight
= GetHeight();
1059 wxClientDC
dc(GetCanvas());
1060 GetCanvas()->PrepareDC(dc
);
1062 if (direction
== wxVERTICAL
)
1064 // Dividing vertically means notionally putting a horizontal line through it.
1065 // Break existing piece into two.
1066 double newXPos1
= GetX();
1067 double newYPos1
= (double)(y1
+ (GetHeight()/4.0));
1068 double newXPos2
= GetX();
1069 double newYPos2
= (double)(y1
+ (3.0*GetHeight()/4.0));
1070 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1071 newDivision
->Show(true);
1075 // Anything adjoining the bottom of this division now adjoins the
1076 // bottom of the new division.
1077 wxNode
*node
= compositeParent
->GetDivisions().GetFirst();
1080 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->GetData();
1081 if (obj
->GetTopSide() == this)
1082 obj
->SetTopSide(newDivision
);
1083 node
= node
->GetNext();
1085 newDivision
->SetTopSide(this);
1086 newDivision
->SetBottomSide(m_bottomSide
);
1087 newDivision
->SetLeftSide(m_leftSide
);
1088 newDivision
->SetRightSide(m_rightSide
);
1089 m_bottomSide
= newDivision
;
1091 compositeParent
->GetDivisions().Append(newDivision
);
1093 // CHANGE: Need to insert this division at start of divisions in the object
1094 // list, because e.g.:
1096 // 2) Add contained object
1098 // Division is now receiving mouse events _before_ the contained object,
1099 // because it was added last (on top of all others)
1101 // Add after the image that visualizes the container
1102 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1104 m_handleSide
= DIVISION_SIDE_BOTTOM
;
1105 newDivision
->SetHandleSide(DIVISION_SIDE_TOP
);
1107 SetSize(oldWidth
, (double)(oldHeight
/2.0));
1108 Move(dc
, newXPos1
, newYPos1
);
1110 newDivision
->SetSize(oldWidth
, (double)(oldHeight
/2.0));
1111 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1115 // Dividing horizontally means notionally putting a vertical line through it.
1116 // Break existing piece into two.
1117 double newXPos1
= (double)(x1
+ (GetWidth()/4.0));
1118 double newYPos1
= GetY();
1119 double newXPos2
= (double)(x1
+ (3.0*GetWidth()/4.0));
1120 double newYPos2
= GetY();
1121 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1122 newDivision
->Show(true);
1126 // Anything adjoining the left of this division now adjoins the
1127 // left of the new division.
1128 wxNode
*node
= compositeParent
->GetDivisions().GetFirst();
1131 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->GetData();
1132 if (obj
->GetLeftSide() == this)
1133 obj
->SetLeftSide(newDivision
);
1134 node
= node
->GetNext();
1136 newDivision
->SetTopSide(m_topSide
);
1137 newDivision
->SetBottomSide(m_bottomSide
);
1138 newDivision
->SetLeftSide(this);
1139 newDivision
->SetRightSide(m_rightSide
);
1140 m_rightSide
= newDivision
;
1142 compositeParent
->GetDivisions().Append(newDivision
);
1143 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1145 m_handleSide
= DIVISION_SIDE_RIGHT
;
1146 newDivision
->SetHandleSide(DIVISION_SIDE_LEFT
);
1148 SetSize((double)(oldWidth
/2.0), oldHeight
);
1149 Move(dc
, newXPos1
, newYPos1
);
1151 newDivision
->SetSize((double)(oldWidth
/2.0), oldHeight
);
1152 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1154 if (compositeParent
->Selected())
1156 compositeParent
->DeleteControlPoints(& dc
);
1157 compositeParent
->MakeControlPoints();
1158 compositeParent
->MakeMandatoryControlPoints();
1160 compositeParent
->Draw(dc
);
1164 // Make one control point for every visible line
1165 void wxDivisionShape::MakeControlPoints()
1167 MakeMandatoryControlPoints();
1170 void wxDivisionShape::MakeMandatoryControlPoints()
1174 GetBoundingBoxMax(&maxX
, &maxY
);
1175 double x
= 0.0 , y
= 0.0;
1180 x = (double)(-maxX/2.0);
1182 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1183 CONTROL_POINT_HORIZONTAL);
1184 m_canvas->AddShape(control);
1185 m_controlPoints.Append(control);
1190 y = (double)(-maxY/2.0);
1191 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1192 CONTROL_POINT_VERTICAL);
1193 m_canvas->AddShape(control);
1194 m_controlPoints.Append(control);
1197 switch (m_handleSide
)
1199 case DIVISION_SIDE_LEFT
:
1201 x
= (double)(-maxX
/2.0);
1203 direction
= CONTROL_POINT_HORIZONTAL
;
1206 case DIVISION_SIDE_TOP
:
1209 y
= (double)(-maxY
/2.0);
1210 direction
= CONTROL_POINT_VERTICAL
;
1213 case DIVISION_SIDE_RIGHT
:
1215 x
= (double)(maxX
/2.0);
1217 direction
= CONTROL_POINT_HORIZONTAL
;
1220 case DIVISION_SIDE_BOTTOM
:
1223 y
= (double)(maxY
/2.0);
1224 direction
= CONTROL_POINT_VERTICAL
;
1230 if (m_handleSide
!= DIVISION_SIDE_NONE
)
1232 wxDivisionControlPoint
*control
= new wxDivisionControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, x
, y
,
1234 m_canvas
->AddShape(control
);
1235 m_controlPoints
.Append(control
);
1239 void wxDivisionShape::ResetControlPoints()
1241 ResetMandatoryControlPoints();
1244 void wxDivisionShape::ResetMandatoryControlPoints()
1246 if (m_controlPoints
.GetCount() < 1)
1251 GetBoundingBoxMax(&maxX
, &maxY
);
1253 wxNode *node = m_controlPoints.GetFirst();
1256 wxDivisionControlPoint *control = (wxDivisionControlPoint *)node->GetData();
1257 if (control->type == CONTROL_POINT_HORIZONTAL)
1259 control->xoffset = (double)(-maxX/2.0); control->m_yoffset = 0.0;
1261 else if (control->type == CONTROL_POINT_VERTICAL)
1263 control->xoffset = 0.0; control->m_yoffset = (double)(-maxY/2.0);
1265 node = node->GetNext();
1268 wxNode
*node
= m_controlPoints
.GetFirst();
1269 if ((m_handleSide
== DIVISION_SIDE_LEFT
) && node
)
1271 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1272 control
->m_xoffset
= (double)(-maxX
/2.0); control
->m_yoffset
= 0.0;
1275 if ((m_handleSide
== DIVISION_SIDE_TOP
) && node
)
1277 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1278 control
->m_xoffset
= 0.0; control
->m_yoffset
= (double)(-maxY
/2.0);
1281 if ((m_handleSide
== DIVISION_SIDE_RIGHT
) && node
)
1283 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1284 control
->m_xoffset
= (double)(maxX
/2.0); control
->m_yoffset
= 0.0;
1287 if ((m_handleSide
== DIVISION_SIDE_BOTTOM
) && node
)
1289 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1290 control
->m_xoffset
= 0.0; control
->m_yoffset
= (double)(maxY
/2.0);
1294 // Adjust a side, returning false if it's not physically possible.
1295 bool wxDivisionShape::AdjustLeft(double left
, bool test
)
1297 double x2
= (double)(GetX() + (GetWidth()/2.0));
1304 double newW
= x2
- left
;
1305 double newX
= (double)(left
+ newW
/2.0);
1306 SetSize(newW
, GetHeight());
1308 wxClientDC
dc(GetCanvas());
1309 GetCanvas()->PrepareDC(dc
);
1311 Move(dc
, newX
, GetY());
1316 bool wxDivisionShape::AdjustTop(double top
, bool test
)
1318 double y2
= (double)(GetY() + (GetHeight()/2.0));
1325 double newH
= y2
- top
;
1326 double newY
= (double)(top
+ newH
/2.0);
1327 SetSize(GetWidth(), newH
);
1329 wxClientDC
dc(GetCanvas());
1330 GetCanvas()->PrepareDC(dc
);
1332 Move(dc
, GetX(), newY
);
1337 bool wxDivisionShape::AdjustRight(double right
, bool test
)
1339 double x1
= (double)(GetX() - (GetWidth()/2.0));
1346 double newW
= right
- x1
;
1347 double newX
= (double)(x1
+ newW
/2.0);
1348 SetSize(newW
, GetHeight());
1350 wxClientDC
dc(GetCanvas());
1351 GetCanvas()->PrepareDC(dc
);
1353 Move(dc
, newX
, GetY());
1358 bool wxDivisionShape::AdjustBottom(double bottom
, bool test
)
1360 double y1
= (double)(GetY() - (GetHeight()/2.0));
1367 double newH
= bottom
- y1
;
1368 double newY
= (double)(y1
+ newH
/2.0);
1369 SetSize(GetWidth(), newH
);
1371 wxClientDC
dc(GetCanvas());
1372 GetCanvas()->PrepareDC(dc
);
1374 Move(dc
, GetX(), newY
);
1379 wxDivisionControlPoint::wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, double size
, double the_xoffset
, double the_yoffset
, int the_type
):
1380 wxControlPoint(the_canvas
, object
, size
, the_xoffset
, the_yoffset
, the_type
)
1382 SetEraseObject(false);
1385 wxDivisionControlPoint::~wxDivisionControlPoint()
1389 static double originalX
= 0.0;
1390 static double originalY
= 0.0;
1391 static double originalW
= 0.0;
1392 static double originalH
= 0.0;
1394 // Implement resizing of canvas object
1395 void wxDivisionControlPoint::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
1397 wxControlPoint::OnDragLeft(draw
, x
, y
, keys
, attachment
);
1400 void wxDivisionControlPoint::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
1402 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1403 originalX
= division
->GetX();
1404 originalY
= division
->GetY();
1405 originalW
= division
->GetWidth();
1406 originalH
= division
->GetHeight();
1408 wxControlPoint::OnBeginDragLeft(x
, y
, keys
, attachment
);
1411 void wxDivisionControlPoint::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
1413 wxControlPoint::OnEndDragLeft(x
, y
, keys
, attachment
);
1415 wxClientDC
dc(GetCanvas());
1416 GetCanvas()->PrepareDC(dc
);
1418 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1419 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)division
->GetParent();
1421 // Need to check it's within the bounds of the parent composite.
1422 double x1
= (double)(divisionParent
->GetX() - (divisionParent
->GetWidth()/2.0));
1423 double y1
= (double)(divisionParent
->GetY() - (divisionParent
->GetHeight()/2.0));
1424 double x2
= (double)(divisionParent
->GetX() + (divisionParent
->GetWidth()/2.0));
1425 double y2
= (double)(divisionParent
->GetY() + (divisionParent
->GetHeight()/2.0));
1427 // Need to check it has not made the division zero or negative width/height
1428 double dx1
= (double)(division
->GetX() - (division
->GetWidth()/2.0));
1429 double dy1
= (double)(division
->GetY() - (division
->GetHeight()/2.0));
1430 double dx2
= (double)(division
->GetX() + (division
->GetWidth()/2.0));
1431 double dy2
= (double)(division
->GetY() + (division
->GetHeight()/2.0));
1433 bool success
= true;
1434 switch (division
->GetHandleSide())
1436 case DIVISION_SIDE_LEFT
:
1438 if ((x
<= x1
) || (x
>= x2
) || (x
>= dx2
))
1440 // Try it out first...
1441 else if (!division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, true))
1444 division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, false);
1448 case DIVISION_SIDE_TOP
:
1450 if ((y
<= y1
) || (y
>= y2
) || (y
>= dy2
))
1452 else if (!division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, true))
1455 division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, false);
1459 case DIVISION_SIDE_RIGHT
:
1461 if ((x
<= x1
) || (x
>= x2
) || (x
<= dx1
))
1463 else if (!division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, true))
1466 division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, false);
1470 case DIVISION_SIDE_BOTTOM
:
1472 if ((y
<= y1
) || (y
>= y2
) || (y
<= dy1
))
1474 else if (!division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, true))
1477 division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, false);
1484 division
->SetSize(originalW
, originalH
);
1485 division
->Move(dc
, originalX
, originalY
);
1487 divisionParent
->Draw(dc
);
1488 division
->GetEventHandler()->OnDrawControlPoints(dc
);
1491 /* Resize adjoining divisions.
1493 Behaviour should be as follows:
1494 If right edge moves, find all objects whose left edge
1495 adjoins this object, and move left edge accordingly.
1496 If left..., move ... right.
1497 If top..., move ... bottom.
1498 If bottom..., move top.
1499 If size goes to zero or end position is other side of start position,
1500 resize to original size and return.
1502 bool wxDivisionShape::ResizeAdjoining(int side
, double newPos
, bool test
)
1504 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)GetParent();
1505 wxNode
*node
= divisionParent
->GetDivisions().GetFirst();
1508 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
1511 case DIVISION_SIDE_LEFT
:
1513 if (division
->m_rightSide
== this)
1515 bool success
= division
->AdjustRight(newPos
, test
);
1516 if (!success
&& test
)
1521 case DIVISION_SIDE_TOP
:
1523 if (division
->m_bottomSide
== this)
1525 bool success
= division
->AdjustBottom(newPos
, test
);
1526 if (!success
&& test
)
1531 case DIVISION_SIDE_RIGHT
:
1533 if (division
->m_leftSide
== this)
1535 bool success
= division
->AdjustLeft(newPos
, test
);
1536 if (!success
&& test
)
1541 case DIVISION_SIDE_BOTTOM
:
1543 if (division
->m_topSide
== this)
1545 bool success
= division
->AdjustTop(newPos
, test
);
1546 if (!success
&& test
)
1554 node
= node
->GetNext();
1561 * Popup menu for editing divisions
1564 class OGLPopupDivisionMenu
: public wxMenu
{
1566 OGLPopupDivisionMenu() : wxMenu() {
1567 Append(DIVISION_MENU_SPLIT_HORIZONTALLY
, wxT("Split horizontally"));
1568 Append(DIVISION_MENU_SPLIT_VERTICALLY
, wxT("Split vertically"));
1570 Append(DIVISION_MENU_EDIT_LEFT_EDGE
, wxT("Edit left edge"));
1571 Append(DIVISION_MENU_EDIT_TOP_EDGE
, wxT("Edit top edge"));
1574 void OnMenu(wxCommandEvent
& event
);
1576 DECLARE_EVENT_TABLE()
1579 BEGIN_EVENT_TABLE(OGLPopupDivisionMenu
, wxMenu
)
1580 EVT_MENU_RANGE(DIVISION_MENU_SPLIT_HORIZONTALLY
,
1581 DIVISION_MENU_EDIT_BOTTOM_EDGE
,
1582 OGLPopupDivisionMenu::OnMenu
)
1586 void OGLPopupDivisionMenu::OnMenu(wxCommandEvent
& event
)
1588 wxDivisionShape
*division
= (wxDivisionShape
*)GetClientData();
1589 switch (event
.GetInt())
1591 case DIVISION_MENU_SPLIT_HORIZONTALLY
:
1593 division
->Divide(wxHORIZONTAL
);
1596 case DIVISION_MENU_SPLIT_VERTICALLY
:
1598 division
->Divide(wxVERTICAL
);
1601 case DIVISION_MENU_EDIT_LEFT_EDGE
:
1603 division
->EditEdge(DIVISION_SIDE_LEFT
);
1606 case DIVISION_MENU_EDIT_TOP_EDGE
:
1608 division
->EditEdge(DIVISION_SIDE_TOP
);
1616 void wxDivisionShape::EditEdge(int WXUNUSED(side
))
1618 wxMessageBox(wxT("EditEdge() not implemented"), wxT("OGL"), wxOK
);
1621 wxBeginBusyCursor();
1623 wxPen
*currentPen
= NULL
;
1624 char **pColour
= NULL
;
1625 char **pStyle
= NULL
;
1626 if (side
== DIVISION_SIDE_LEFT
)
1628 currentPen
= m_leftSidePen
;
1629 pColour
= &m_leftSideColour
;
1630 pStyle
= &m_leftSideStyle
;
1634 currentPen
= m_topSidePen
;
1635 pColour
= &m_topSideColour
;
1636 pStyle
= &m_topSideStyle
;
1639 GraphicsForm
*form
= new GraphicsForm("Containers");
1640 int lineWidth
= currentPen
->GetWidth();
1642 form
->Add(wxMakeFormShort("Width", &lineWidth
, wxFORM_DEFAULT
, NULL
, NULL
, wxVERTICAL
,
1644 form
->Add(wxMakeFormString("Colour", pColour
, wxFORM_CHOICE
,
1645 new wxList(wxMakeConstraintStrings(
1669 NULL
), NULL
, wxVERTICAL
, 150));
1670 form
->Add(wxMakeFormString("Style", pStyle
, wxFORM_CHOICE
,
1671 new wxList(wxMakeConstraintStrings(
1678 NULL
), NULL
, wxVERTICAL
, 100));
1680 wxDialogBox
*dialog
= new wxDialogBox(m_canvas
->GetParent(), "Division properties", 10, 10, 500, 500);
1681 if (GraphicsLabelFont
)
1682 dialog
->SetLabelFont(GraphicsLabelFont
);
1683 if (GraphicsButtonFont
)
1684 dialog
->SetButtonFont(GraphicsButtonFont
);
1686 form
->AssociatePanel(dialog
);
1687 form
->dialog
= dialog
;
1690 dialog
->Centre(wxBOTH
);
1695 int lineStyle
= wxSOLID
;
1698 if (strcmp(*pStyle
, "Solid") == 0)
1699 lineStyle
= wxSOLID
;
1700 else if (strcmp(*pStyle
, "Dot") == 0)
1702 else if (strcmp(*pStyle
, "Short Dash") == 0)
1703 lineStyle
= wxSHORT_DASH
;
1704 else if (strcmp(*pStyle
, "Long Dash") == 0)
1705 lineStyle
= wxLONG_DASH
;
1706 else if (strcmp(*pStyle
, "Dot Dash") == 0)
1707 lineStyle
= wxDOT_DASH
;
1710 wxPen
*newPen
= wxThePenList
->FindOrCreatePen(*pColour
, lineWidth
, lineStyle
);
1713 if (side
== DIVISION_SIDE_LEFT
)
1714 m_leftSidePen
= newPen
;
1716 m_topSidePen
= newPen
;
1718 // Need to draw whole image again
1719 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1720 compositeParent
->Draw(dc
);
1725 void wxDivisionShape::PopupMenu(double x
, double y
)
1727 wxMenu
* oglPopupDivisionMenu
= new OGLPopupDivisionMenu
;
1729 oglPopupDivisionMenu
->SetClientData((void *)this);
1731 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, true);
1733 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, false);
1735 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, true);
1737 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, false);
1740 m_canvas
->GetViewStart(&x1
, &y1
);
1743 m_canvas
->GetScrollPixelsPerUnit(&unit_x
, &unit_y
);
1745 wxClientDC
dc(GetCanvas());
1746 GetCanvas()->PrepareDC(dc
);
1748 int mouse_x
= (int)(dc
.LogicalToDeviceX((long)(x
- x1
*unit_x
)));
1749 int mouse_y
= (int)(dc
.LogicalToDeviceY((long)(y
- y1
*unit_y
)));
1751 m_canvas
->PopupMenu(oglPopupDivisionMenu
, mouse_x
, mouse_y
);
1752 delete oglPopupDivisionMenu
;
1755 void wxDivisionShape::SetLeftSideColour(const wxString
& colour
)
1757 m_leftSideColour
= colour
;
1760 void wxDivisionShape::SetTopSideColour(const wxString
& colour
)
1762 m_topSideColour
= colour
;
1765 void wxDivisionShape::SetLeftSideStyle(const wxString
& style
)
1767 m_leftSideStyle
= style
;
1770 void wxDivisionShape::SetTopSideStyle(const wxString
& style
)
1772 m_topSideStyle
= style
;