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/basic.h>
32 #include <wx/ogl/basicp.h>
33 #include <wx/ogl/constrnt.h>
34 #include <wx/ogl/composit.h>
35 #include <wx/ogl/misc.h>
36 #include <wx/ogl/canvas.h>
39 // Sometimes, objects need to access the whole database to
40 // construct themselves.
41 wxExprDatabase
*GlobalwxExprDatabase
= NULL
;
45 * Division control point
48 class wxDivisionControlPoint
: public wxControlPoint
50 DECLARE_DYNAMIC_CLASS(wxDivisionControlPoint
)
52 wxDivisionControlPoint() {}
53 wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, double size
, double the_xoffset
, double the_yoffset
, int the_type
);
54 ~wxDivisionControlPoint();
56 void OnDragLeft(bool draw
, double x
, double y
, int keys
=0, int attachment
= 0);
57 void OnBeginDragLeft(double x
, double y
, int keys
=0, int attachment
= 0);
58 void OnEndDragLeft(double x
, double y
, int keys
=0, int attachment
= 0);
61 IMPLEMENT_DYNAMIC_CLASS(wxDivisionControlPoint
, wxControlPoint
)
68 IMPLEMENT_DYNAMIC_CLASS(wxCompositeShape
, wxRectangleShape
)
70 wxCompositeShape::wxCompositeShape(): wxRectangleShape(10.0, 10.0)
72 // selectable = FALSE;
77 wxCompositeShape::~wxCompositeShape()
79 wxNode
*node
= m_constraints
.GetFirst();
82 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
84 node
= node
->GetNext();
86 node
= m_children
.GetFirst();
89 wxShape
*object
= (wxShape
*)node
->GetData();
90 wxNode
*next
= node
->GetNext();
97 void wxCompositeShape::OnDraw(wxDC
& dc
)
99 double x1
= (double)(m_xpos
- m_width
/2.0);
100 double y1
= (double)(m_ypos
- m_height
/2.0);
102 if (m_shadowMode
!= SHADOW_NONE
)
105 dc
.SetBrush(* m_shadowBrush
);
106 dc
.SetPen(* g_oglTransparentPen
);
108 if (m_cornerRadius
!= 0.0)
109 dc
.DrawRoundedRectangle(WXROUND(x1
+ m_shadowOffsetX
), WXROUND(y1
+ m_shadowOffsetY
),
110 WXROUND(m_width
), WXROUND(m_height
), m_cornerRadius
);
112 dc
.DrawRectangle(WXROUND(x1
+ m_shadowOffsetX
), WXROUND(y1
+ m_shadowOffsetY
), WXROUND(m_width
), WXROUND(m_height
));
116 void wxCompositeShape::OnDrawContents(wxDC
& dc
)
118 wxNode
*node
= m_children
.GetFirst();
121 wxShape
*object
= (wxShape
*)node
->GetData();
123 object
->DrawLinks(dc
);
124 node
= node
->GetNext();
126 wxShape::OnDrawContents(dc
);
129 bool wxCompositeShape::OnMovePre(wxDC
& dc
, double x
, double y
, double oldx
, double oldy
, bool display
)
131 double diffX
= x
- oldx
;
132 double diffY
= y
- oldy
;
133 wxNode
*node
= m_children
.GetFirst();
136 wxShape
*object
= (wxShape
*)node
->GetData();
139 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
141 node
= node
->GetNext();
146 void wxCompositeShape::OnErase(wxDC
& dc
)
148 wxRectangleShape::OnErase(dc
);
149 wxNode
*node
= m_children
.GetFirst();
152 wxShape
*object
= (wxShape
*)node
->GetData();
154 node
= node
->GetNext();
158 static double objectStartX
= 0.0;
159 static double objectStartY
= 0.0;
161 void wxCompositeShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
165 m_canvas
->Snap(&xx
, &yy
);
166 double offsetX
= xx
- objectStartX
;
167 double offsetY
= yy
- objectStartY
;
169 wxClientDC
dc(GetCanvas());
170 GetCanvas()->PrepareDC(dc
);
172 dc
.SetLogicalFunction(OGLRBLF
);
173 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
174 dc
.SetPen(dottedPen
);
175 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
177 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
178 // wxShape::OnDragLeft(draw, x, y, keys, attachment);
181 void wxCompositeShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
186 wxClientDC
dc(GetCanvas());
187 GetCanvas()->PrepareDC(dc
);
191 dc
.SetLogicalFunction(OGLRBLF
);
193 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
194 dc
.SetPen(dottedPen
);
195 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
196 m_canvas
->CaptureMouse();
200 m_canvas
->Snap(&xx
, &yy
);
201 double offsetX
= xx
- objectStartX
;
202 double offsetY
= yy
- objectStartY
;
204 GetEventHandler()->OnDrawOutline(dc
, GetX() + offsetX
, GetY() + offsetY
, GetWidth(), GetHeight());
206 // wxShape::OnBeginDragLeft(x, y, keys, attachment);
209 void wxCompositeShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
211 // wxShape::OnEndDragLeft(x, y, keys, attachment);
213 wxClientDC
dc(GetCanvas());
214 GetCanvas()->PrepareDC(dc
);
216 m_canvas
->ReleaseMouse();
220 if (m_parent
) m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, 0);
224 dc
.SetLogicalFunction(wxCOPY
);
227 m_canvas
->Snap(&xx
, &yy
);
228 double offsetX
= xx
- objectStartX
;
229 double offsetY
= yy
- objectStartY
;
231 Move(dc
, GetX() + offsetX
, GetY() + offsetY
);
233 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
236 void wxCompositeShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
238 // If we get a ctrl-right click, this means send the message to
239 // the division, so we can invoke a user interface for dealing with regions.
242 wxNode
*node
= m_divisions
.GetFirst();
245 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
246 wxNode
*next
= node
->GetNext();
249 if (division
->HitTest(x
, y
, &attach
, &dist
))
251 division
->GetEventHandler()->OnRightClick(x
, y
, keys
, attach
);
260 void wxCompositeShape::SetSize(double w
, double h
, bool recursive
)
262 SetAttachmentSize(w
, h
);
264 double xScale
= (double)(w
/(wxMax(1.0, GetWidth())));
265 double yScale
= (double)(h
/(wxMax(1.0, GetHeight())));
270 if (!recursive
) return;
272 wxNode
*node
= m_children
.GetFirst();
274 wxClientDC
dc(GetCanvas());
275 GetCanvas()->PrepareDC(dc
);
277 double xBound
, yBound
;
280 wxShape
*object
= (wxShape
*)node
->GetData();
282 // Scale the position first
283 double newX
= (double)(((object
->GetX() - GetX())*xScale
) + GetX());
284 double newY
= (double)(((object
->GetY() - GetY())*yScale
) + GetY());
286 object
->Move(dc
, newX
, newY
);
289 // Now set the scaled size
290 object
->GetBoundingBoxMin(&xBound
, &yBound
);
291 object
->SetSize(object
->GetFixedWidth() ? xBound
: xScale
*xBound
,
292 object
->GetFixedHeight() ? yBound
: yScale
*yBound
);
294 node
= node
->GetNext();
296 SetDefaultRegionSize();
299 void wxCompositeShape::AddChild(wxShape
*child
, wxShape
*addAfter
)
301 m_children
.Append(child
);
302 child
->SetParent(this);
305 // Ensure we add at the right position
307 child
->RemoveFromCanvas(m_canvas
);
308 child
->AddToCanvas(m_canvas
, addAfter
);
312 void wxCompositeShape::RemoveChild(wxShape
*child
)
314 m_children
.DeleteObject(child
);
315 m_divisions
.DeleteObject(child
);
316 RemoveChildFromConstraints(child
);
317 child
->SetParent(NULL
);
320 void wxCompositeShape::DeleteConstraintsInvolvingChild(wxShape
*child
)
322 wxNode
*node
= m_constraints
.GetFirst();
325 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
326 wxNode
*nextNode
= node
->GetNext();
328 if ((constraint
->m_constrainingObject
== child
) ||
329 constraint
->m_constrainedObjects
.Member(child
))
338 void wxCompositeShape::RemoveChildFromConstraints(wxShape
*child
)
340 wxNode
*node
= m_constraints
.GetFirst();
343 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
344 wxNode
*nextNode
= node
->GetNext();
346 if (constraint
->m_constrainedObjects
.Member(child
))
347 constraint
->m_constrainedObjects
.DeleteObject(child
);
348 if (constraint
->m_constrainingObject
== child
)
349 constraint
->m_constrainingObject
= NULL
;
351 // Delete the constraint if no participants left
352 if (!constraint
->m_constrainingObject
)
362 void wxCompositeShape::Copy(wxShape
& copy
)
364 wxRectangleShape::Copy(copy
);
366 wxASSERT( copy
.IsKindOf(CLASSINFO(wxCompositeShape
)) ) ;
368 wxCompositeShape
& compositeCopy
= (wxCompositeShape
&) copy
;
370 // Associate old and new copies for compositeCopying constraints and division geometry
371 oglObjectCopyMapping
.Append((long)this, &compositeCopy
);
374 wxNode
*node
= m_children
.GetFirst();
377 wxShape
*object
= (wxShape
*)node
->GetData();
378 wxShape
*newObject
= object
->CreateNewCopy(FALSE
, FALSE
);
379 if (newObject
->GetId() == 0)
380 newObject
->SetId(wxNewId());
382 newObject
->SetParent(&compositeCopy
);
383 compositeCopy
.m_children
.Append(newObject
);
385 // Some m_children may be divisions
386 if (m_divisions
.Member(object
))
387 compositeCopy
.m_divisions
.Append(newObject
);
389 oglObjectCopyMapping
.Append((long)object
, newObject
);
391 node
= node
->GetNext();
394 // Copy the constraints
395 node
= m_constraints
.GetFirst();
398 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
400 wxShape
*newConstraining
= (wxShape
*)(oglObjectCopyMapping
.Find((long)constraint
->m_constrainingObject
)->GetData());
402 wxList newConstrainedList
;
403 wxNode
*node2
= constraint
->m_constrainedObjects
.GetFirst();
406 wxShape
*constrainedObject
= (wxShape
*)node2
->GetData();
407 wxShape
*newConstrained
= (wxShape
*)(oglObjectCopyMapping
.Find((long)constrainedObject
)->GetData());
408 newConstrainedList
.Append(newConstrained
);
409 node2
= node2
->GetNext();
412 wxOGLConstraint
*newConstraint
= new wxOGLConstraint(constraint
->m_constraintType
, newConstraining
,
414 newConstraint
->m_constraintId
= constraint
->m_constraintId
;
415 if (constraint
->m_constraintName
)
417 newConstraint
->m_constraintName
= constraint
->m_constraintName
;
419 newConstraint
->SetSpacing(constraint
->m_xSpacing
, constraint
->m_ySpacing
);
420 compositeCopy
.m_constraints
.Append(newConstraint
);
422 node
= node
->GetNext();
425 // Now compositeCopy the division geometry
426 node
= m_divisions
.GetFirst();
429 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
430 wxNode
*node1
= oglObjectCopyMapping
.Find((long)division
);
431 wxNode
*leftNode
= NULL
;
432 wxNode
*topNode
= NULL
;
433 wxNode
*rightNode
= NULL
;
434 wxNode
*bottomNode
= NULL
;
435 if (division
->GetLeftSide())
436 leftNode
= oglObjectCopyMapping
.Find((long)division
->GetLeftSide());
437 if (division
->GetTopSide())
438 topNode
= oglObjectCopyMapping
.Find((long)division
->GetTopSide());
439 if (division
->GetRightSide())
440 rightNode
= oglObjectCopyMapping
.Find((long)division
->GetRightSide());
441 if (division
->GetBottomSide())
442 bottomNode
= oglObjectCopyMapping
.Find((long)division
->GetBottomSide());
445 wxDivisionShape
*newDivision
= (wxDivisionShape
*)node1
->GetData();
447 newDivision
->SetLeftSide((wxDivisionShape
*)leftNode
->GetData());
449 newDivision
->SetTopSide((wxDivisionShape
*)topNode
->GetData());
451 newDivision
->SetRightSide((wxDivisionShape
*)rightNode
->GetData());
453 newDivision
->SetBottomSide((wxDivisionShape
*)bottomNode
->GetData());
455 node
= node
->GetNext();
459 wxOGLConstraint
*wxCompositeShape::AddConstraint(wxOGLConstraint
*constraint
)
461 m_constraints
.Append(constraint
);
462 if (constraint
->m_constraintId
== 0)
463 constraint
->m_constraintId
= wxNewId();
467 wxOGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxList
& constrained
)
469 wxOGLConstraint
*constraint
= new wxOGLConstraint(type
, constraining
, constrained
);
470 if (constraint
->m_constraintId
== 0)
471 constraint
->m_constraintId
= wxNewId();
472 m_constraints
.Append(constraint
);
476 wxOGLConstraint
*wxCompositeShape::AddConstraint(int type
, wxShape
*constraining
, wxShape
*constrained
)
479 l
.Append(constrained
);
480 wxOGLConstraint
*constraint
= new wxOGLConstraint(type
, constraining
, l
);
481 if (constraint
->m_constraintId
== 0)
482 constraint
->m_constraintId
= wxNewId();
483 m_constraints
.Append(constraint
);
487 wxOGLConstraint
*wxCompositeShape::FindConstraint(long cId
, wxCompositeShape
**actualComposite
)
489 wxNode
*node
= m_constraints
.GetFirst();
492 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
493 if (constraint
->m_constraintId
== cId
)
496 *actualComposite
= this;
499 node
= node
->GetNext();
501 // If not found, try children.
502 node
= m_children
.GetFirst();
505 wxShape
*child
= (wxShape
*)node
->GetData();
506 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
508 wxOGLConstraint
*constraint
= ((wxCompositeShape
*)child
)->FindConstraint(cId
, actualComposite
);
512 *actualComposite
= (wxCompositeShape
*)child
;
516 node
= node
->GetNext();
521 void wxCompositeShape::DeleteConstraint(wxOGLConstraint
*constraint
)
523 m_constraints
.DeleteObject(constraint
);
527 void wxCompositeShape::CalculateSize()
529 double maxX
= (double) -999999.9;
530 double maxY
= (double) -999999.9;
531 double minX
= (double) 999999.9;
532 double minY
= (double) 999999.9;
535 wxNode
*node
= m_children
.GetFirst();
538 wxShape
*object
= (wxShape
*)node
->GetData();
540 // Recalculate size of composite objects because may not conform
541 // to size it was set to - depends on the children.
542 object
->CalculateSize();
544 object
->GetBoundingBoxMax(&w
, &h
);
545 if ((object
->GetX() + (w
/2.0)) > maxX
)
546 maxX
= (double)(object
->GetX() + (w
/2.0));
547 if ((object
->GetX() - (w
/2.0)) < minX
)
548 minX
= (double)(object
->GetX() - (w
/2.0));
549 if ((object
->GetY() + (h
/2.0)) > maxY
)
550 maxY
= (double)(object
->GetY() + (h
/2.0));
551 if ((object
->GetY() - (h
/2.0)) < minY
)
552 minY
= (double)(object
->GetY() - (h
/2.0));
554 node
= node
->GetNext();
556 m_width
= maxX
- minX
;
557 m_height
= maxY
- minY
;
558 m_xpos
= (double)(m_width
/2.0 + minX
);
559 m_ypos
= (double)(m_height
/2.0 + minY
);
562 bool wxCompositeShape::Recompute()
564 int noIterations
= 0;
566 while (changed
&& (noIterations
< 500))
568 changed
= Constrain();
574 cerr << "Warning: constraint algorithm failed after 500 iterations.\n";
580 bool wxCompositeShape::Constrain()
584 bool changed
= FALSE
;
585 wxNode
*node
= m_children
.GetFirst();
588 wxShape
*object
= (wxShape
*)node
->GetData();
589 if (object
->Constrain())
591 node
= node
->GetNext();
594 node
= m_constraints
.GetFirst();
597 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
598 if (constraint
->Evaluate()) changed
= TRUE
;
599 node
= node
->GetNext();
605 void wxCompositeShape::WriteAttributes(wxExpr
*clause
)
607 wxRectangleShape::WriteAttributes(clause
);
609 // clause->AddAttributeValue("selectable", (long)selectable);
611 // Output constraints as constraint1 = (...), constraint2 = (...), etc.
612 int constraintNo
= 1;
613 char m_constraintNameBuf
[20];
614 wxNode
*node
= m_constraints
.GetFirst();
617 wxOGLConstraint
*constraint
= (wxOGLConstraint
*)node
->GetData();
618 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
620 // Each constraint is stored in the form
621 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
622 wxExpr
*constraintExpr
= new wxExpr(wxExprList
);
623 constraintExpr
->Append(new wxExpr((long)constraint
->m_constraintType
));
624 constraintExpr
->Append(new wxExpr(wxExprString
, constraint
->m_constraintName
));
625 constraintExpr
->Append(new wxExpr(constraint
->m_constraintId
));
626 constraintExpr
->Append(new wxExpr(constraint
->m_xSpacing
));
627 constraintExpr
->Append(new wxExpr(constraint
->m_ySpacing
));
628 constraintExpr
->Append(new wxExpr(constraint
->m_constrainingObject
->GetId()));
630 wxExpr
*objectList
= new wxExpr(wxExprList
);
631 wxNode
*node1
= constraint
->m_constrainedObjects
.GetFirst();
634 wxShape
*obj
= (wxShape
*)node1
->GetData();
635 objectList
->Append(new wxExpr(obj
->GetId()));
636 node1
= node1
->GetNext();
638 constraintExpr
->Append(objectList
);
640 clause
->AddAttributeValue(m_constraintNameBuf
, constraintExpr
);
642 node
= node
->GetNext();
646 // Write the ids of all the child images
647 wxExpr
*childrenExpr
= new wxExpr(wxExprList
);
648 node
= m_children
.GetFirst();
651 wxShape
*child
= (wxShape
*)node
->GetData();
652 childrenExpr
->Append(new wxExpr(child
->GetId()));
653 node
= node
->GetNext();
655 clause
->AddAttributeValue("children", childrenExpr
);
657 // Write the ids of all the division images
658 if (m_divisions
.GetCount() > 0)
660 wxExpr
*divisionsExpr
= new wxExpr(wxExprList
);
661 node
= m_divisions
.GetFirst();
664 wxShape
*child
= (wxShape
*)node
->GetData();
665 divisionsExpr
->Append(new wxExpr(child
->GetId()));
666 node
= node
->GetNext();
668 clause
->AddAttributeValue("divisions", divisionsExpr
);
672 // Problem. Child images are always written AFTER the parent
673 // so as to be able to link up to parent. So we may not be able
674 // to find the constraint participants until we've read everything
675 // in. Need to have another pass for composites.
676 void wxCompositeShape::ReadAttributes(wxExpr
*clause
)
678 wxRectangleShape::ReadAttributes(clause
);
680 // clause->GetAttributeValue("selectable", selectable);
683 void wxCompositeShape::ReadConstraints(wxExpr
*clause
, wxExprDatabase
*database
)
685 // Constraints are output as constraint1 = (...), constraint2 = (...), etc.
686 int constraintNo
= 1;
687 char m_constraintNameBuf
[20];
688 bool haveConstraints
= TRUE
;
690 while (haveConstraints
)
692 sprintf(m_constraintNameBuf
, "constraint%d", constraintNo
);
693 wxExpr
*constraintExpr
= NULL
;
694 clause
->GetAttributeValue(m_constraintNameBuf
, &constraintExpr
);
697 haveConstraints
= FALSE
;
701 double cXSpacing
= 0.0;
702 double cYSpacing
= 0.0;
705 wxShape
*m_constrainingObject
= NULL
;
706 wxList m_constrainedObjects
;
708 // Each constraint is stored in the form
709 // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
711 wxExpr
*typeExpr
= constraintExpr
->Nth(0);
712 wxExpr
*nameExpr
= constraintExpr
->Nth(1);
713 wxExpr
*idExpr
= constraintExpr
->Nth(2);
714 wxExpr
*xExpr
= constraintExpr
->Nth(3);
715 wxExpr
*yExpr
= constraintExpr
->Nth(4);
716 wxExpr
*constrainingExpr
= constraintExpr
->Nth(5);
717 wxExpr
*constrainedExpr
= constraintExpr
->Nth(6);
719 cType
= (int)typeExpr
->IntegerValue();
720 cXSpacing
= xExpr
->RealValue();
721 cYSpacing
= yExpr
->RealValue();
722 cName
= nameExpr
->StringValue();
723 cId
= idExpr
->IntegerValue();
725 wxExpr
*objExpr1
= database
->HashFind("node_image", constrainingExpr
->IntegerValue());
726 if (objExpr1
&& objExpr1
->GetClientData())
727 m_constrainingObject
= (wxShape
*)objExpr1
->GetClientData();
729 wxLogFatalError(wxT("Object graphics error: Couldn't find constraining image of composite."));
732 wxExpr
*currentIdExpr
= constrainedExpr
->Nth(i
);
733 while (currentIdExpr
)
735 long currentId
= currentIdExpr
->IntegerValue();
736 wxExpr
*objExpr2
= database
->HashFind("node_image", currentId
);
737 if (objExpr2
&& objExpr2
->GetClientData())
739 m_constrainedObjects
.Append((wxShape
*)objExpr2
->GetClientData());
743 wxLogFatalError(wxT("Object graphics error: Couldn't find constrained image of composite."));
747 currentIdExpr
= constrainedExpr
->Nth(i
);
749 wxOGLConstraint
*newConstraint
= AddConstraint(cType
, m_constrainingObject
, m_constrainedObjects
);
750 newConstraint
->SetSpacing(cXSpacing
, cYSpacing
);
751 newConstraint
->m_constraintId
= cId
;
752 newConstraint
->m_constraintName
= cName
;
758 // Make this composite into a container by creating one wxDivisionShape
759 void wxCompositeShape::MakeContainer()
761 wxDivisionShape
*division
= OnCreateDivision();
762 m_divisions
.Append(division
);
765 division
->SetSize(m_width
, m_height
);
767 wxClientDC
dc(GetCanvas());
768 GetCanvas()->PrepareDC(dc
);
770 division
->Move(dc
, GetX(), GetY());
772 division
->Show(TRUE
);
775 wxDivisionShape
*wxCompositeShape::OnCreateDivision()
777 return new wxDivisionShape
;
780 wxShape
*wxCompositeShape::FindContainerImage()
782 wxNode
*node
= m_children
.GetFirst();
785 wxShape
*child
= (wxShape
*)node
->GetData();
786 if (!m_divisions
.Member(child
))
788 node
= node
->GetNext();
793 // Returns TRUE if division is a descendant of this container
794 bool wxCompositeShape::ContainsDivision(wxDivisionShape
*division
)
796 if (m_divisions
.Member(division
))
798 wxNode
*node
= m_children
.GetFirst();
801 wxShape
*child
= (wxShape
*)node
->GetData();
802 if (child
->IsKindOf(CLASSINFO(wxCompositeShape
)))
804 bool ans
= ((wxCompositeShape
*)child
)->ContainsDivision(division
);
808 node
= node
->GetNext();
818 IMPLEMENT_DYNAMIC_CLASS(wxDivisionShape
, wxCompositeShape
)
820 wxDivisionShape::wxDivisionShape()
822 SetSensitivityFilter(OP_CLICK_LEFT
| OP_CLICK_RIGHT
| OP_DRAG_RIGHT
);
823 SetCentreResize(FALSE
);
824 SetAttachmentMode(TRUE
);
829 m_handleSide
= DIVISION_SIDE_NONE
;
830 m_leftSidePen
= wxBLACK_PEN
;
831 m_topSidePen
= wxBLACK_PEN
;
832 m_leftSideColour
= wxT("BLACK");
833 m_topSideColour
= wxT("BLACK");
834 m_leftSideStyle
= wxT("Solid");
835 m_topSideStyle
= wxT("Solid");
839 wxDivisionShape::~wxDivisionShape()
843 void wxDivisionShape::OnDraw(wxDC
& dc
)
845 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
846 dc
.SetBackgroundMode(wxTRANSPARENT
);
848 double x1
= (double)(GetX() - (GetWidth()/2.0));
849 double y1
= (double)(GetY() - (GetHeight()/2.0));
850 double x2
= (double)(GetX() + (GetWidth()/2.0));
851 double y2
= (double)(GetY() + (GetHeight()/2.0));
853 // Should subtract 1 pixel if drawing under Windows
860 dc
.SetPen(* m_leftSidePen
);
861 dc
.DrawLine(WXROUND(x1
), WXROUND(y2
), WXROUND(x1
), WXROUND(y1
));
865 dc
.SetPen(* m_topSidePen
);
866 dc
.DrawLine(WXROUND(x1
), WXROUND(y1
), WXROUND(x2
), WXROUND(y1
));
869 // For testing purposes, draw a rectangle so we know
870 // how big the division is.
871 // SetBrush(* wxCYAN_BRUSH);
872 // wxRectangleShape::OnDraw(dc);
875 void wxDivisionShape::OnDrawContents(wxDC
& dc
)
877 wxCompositeShape::OnDrawContents(dc
);
880 bool wxDivisionShape::OnMovePre(wxDC
& dc
, double x
, double y
, double oldx
, double oldy
, bool display
)
882 double diffX
= x
- oldx
;
883 double diffY
= y
- oldy
;
884 wxNode
*node
= m_children
.GetFirst();
887 wxShape
*object
= (wxShape
*)node
->GetData();
889 object
->Move(dc
, object
->GetX() + diffX
, object
->GetY() + diffY
, display
);
890 node
= node
->GetNext();
895 void wxDivisionShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
897 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
903 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
904 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
908 wxShape::OnDragLeft(draw
, x
, y
, keys
, attachment
);
911 void wxDivisionShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
913 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
919 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
920 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
925 wxShape::OnBeginDragLeft(x
, y
, keys
, attachment
);
928 void wxDivisionShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
930 m_canvas
->ReleaseMouse();
931 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
937 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
938 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
943 wxClientDC
dc(GetCanvas());
944 GetCanvas()->PrepareDC(dc
);
946 dc
.SetLogicalFunction(wxCOPY
);
948 m_canvas
->Snap(&m_xpos
, &m_ypos
);
949 GetEventHandler()->OnMovePre(dc
, x
, y
, m_oldX
, m_oldY
);
951 ResetControlPoints();
954 GetEventHandler()->OnDrawControlPoints(dc
);
956 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
959 void wxDivisionShape::SetSize(double w
, double h
, bool recursive
)
963 wxRectangleShape::SetSize(w
, h
, recursive
);
966 void wxDivisionShape::CalculateSize()
970 void wxDivisionShape::Copy(wxShape
& copy
)
972 wxCompositeShape::Copy(copy
);
974 wxASSERT( copy
.IsKindOf(CLASSINFO(wxDivisionShape
)) ) ;
976 wxDivisionShape
& divisionCopy
= (wxDivisionShape
&) copy
;
978 divisionCopy
.m_leftSideStyle
= m_leftSideStyle
;
979 divisionCopy
.m_topSideStyle
= m_topSideStyle
;
980 divisionCopy
.m_leftSideColour
= m_leftSideColour
;
981 divisionCopy
.m_topSideColour
= m_topSideColour
;
983 divisionCopy
.m_leftSidePen
= m_leftSidePen
;
984 divisionCopy
.m_topSidePen
= m_topSidePen
;
985 divisionCopy
.m_handleSide
= m_handleSide
;
987 // Division geometry copying is handled at the wxCompositeShape level.
991 void wxDivisionShape::WriteAttributes(wxExpr
*clause
)
993 wxCompositeShape::WriteAttributes(clause
);
996 clause
->AddAttributeValue("left_side", (long)m_leftSide
->GetId());
998 clause
->AddAttributeValue("top_side", (long)m_topSide
->GetId());
1000 clause
->AddAttributeValue("right_side", (long)m_rightSide
->GetId());
1002 clause
->AddAttributeValue("bottom_side", (long)m_bottomSide
->GetId());
1004 clause
->AddAttributeValue("handle_side", (long)m_handleSide
);
1005 clause
->AddAttributeValueString("left_colour", m_leftSideColour
);
1006 clause
->AddAttributeValueString("top_colour", m_topSideColour
);
1007 clause
->AddAttributeValueString("left_style", m_leftSideStyle
);
1008 clause
->AddAttributeValueString("top_style", m_topSideStyle
);
1011 void wxDivisionShape::ReadAttributes(wxExpr
*clause
)
1013 wxCompositeShape::ReadAttributes(clause
);
1015 clause
->GetAttributeValue("handle_side", m_handleSide
);
1016 clause
->GetAttributeValue("left_colour", m_leftSideColour
);
1017 clause
->GetAttributeValue("top_colour", m_topSideColour
);
1018 clause
->GetAttributeValue("left_style", m_leftSideStyle
);
1019 clause
->GetAttributeValue("top_style", m_topSideStyle
);
1024 void wxDivisionShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
1026 if (keys
& KEY_CTRL
)
1031 else if (keys & KEY_SHIFT)
1033 if (m_leftSide || m_topSide || m_rightSide || m_bottomSide)
1038 GetParent()->Draw(dc);
1051 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1052 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1059 // Divide wxHORIZONTALly or wxVERTICALly
1060 bool wxDivisionShape::Divide(int direction
)
1062 // Calculate existing top-left, bottom-right
1063 double x1
= (double)(GetX() - (GetWidth()/2.0));
1064 double y1
= (double)(GetY() - (GetHeight()/2.0));
1065 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1066 double oldWidth
= GetWidth();
1067 double oldHeight
= GetHeight();
1071 wxClientDC
dc(GetCanvas());
1072 GetCanvas()->PrepareDC(dc
);
1074 if (direction
== wxVERTICAL
)
1076 // Dividing vertically means notionally putting a horizontal line through it.
1077 // Break existing piece into two.
1078 double newXPos1
= GetX();
1079 double newYPos1
= (double)(y1
+ (GetHeight()/4.0));
1080 double newXPos2
= GetX();
1081 double newYPos2
= (double)(y1
+ (3.0*GetHeight()/4.0));
1082 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1083 newDivision
->Show(TRUE
);
1087 // Anything adjoining the bottom of this division now adjoins the
1088 // bottom of the new division.
1089 wxNode
*node
= compositeParent
->GetDivisions().GetFirst();
1092 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->GetData();
1093 if (obj
->GetTopSide() == this)
1094 obj
->SetTopSide(newDivision
);
1095 node
= node
->GetNext();
1097 newDivision
->SetTopSide(this);
1098 newDivision
->SetBottomSide(m_bottomSide
);
1099 newDivision
->SetLeftSide(m_leftSide
);
1100 newDivision
->SetRightSide(m_rightSide
);
1101 m_bottomSide
= newDivision
;
1103 compositeParent
->GetDivisions().Append(newDivision
);
1105 // CHANGE: Need to insert this division at start of divisions in the object
1106 // list, because e.g.:
1108 // 2) Add contained object
1110 // Division is now receiving mouse events _before_ the contained object,
1111 // because it was added last (on top of all others)
1113 // Add after the image that visualizes the container
1114 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1116 m_handleSide
= DIVISION_SIDE_BOTTOM
;
1117 newDivision
->SetHandleSide(DIVISION_SIDE_TOP
);
1119 SetSize(oldWidth
, (double)(oldHeight
/2.0));
1120 Move(dc
, newXPos1
, newYPos1
);
1122 newDivision
->SetSize(oldWidth
, (double)(oldHeight
/2.0));
1123 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1127 // Dividing horizontally means notionally putting a vertical line through it.
1128 // Break existing piece into two.
1129 double newXPos1
= (double)(x1
+ (GetWidth()/4.0));
1130 double newYPos1
= GetY();
1131 double newXPos2
= (double)(x1
+ (3.0*GetWidth()/4.0));
1132 double newYPos2
= GetY();
1133 wxDivisionShape
*newDivision
= compositeParent
->OnCreateDivision();
1134 newDivision
->Show(TRUE
);
1138 // Anything adjoining the left of this division now adjoins the
1139 // left of the new division.
1140 wxNode
*node
= compositeParent
->GetDivisions().GetFirst();
1143 wxDivisionShape
*obj
= (wxDivisionShape
*)node
->GetData();
1144 if (obj
->GetLeftSide() == this)
1145 obj
->SetLeftSide(newDivision
);
1146 node
= node
->GetNext();
1148 newDivision
->SetTopSide(m_topSide
);
1149 newDivision
->SetBottomSide(m_bottomSide
);
1150 newDivision
->SetLeftSide(this);
1151 newDivision
->SetRightSide(m_rightSide
);
1152 m_rightSide
= newDivision
;
1154 compositeParent
->GetDivisions().Append(newDivision
);
1155 compositeParent
->AddChild(newDivision
, compositeParent
->FindContainerImage());
1157 m_handleSide
= DIVISION_SIDE_RIGHT
;
1158 newDivision
->SetHandleSide(DIVISION_SIDE_LEFT
);
1160 SetSize((double)(oldWidth
/2.0), oldHeight
);
1161 Move(dc
, newXPos1
, newYPos1
);
1163 newDivision
->SetSize((double)(oldWidth
/2.0), oldHeight
);
1164 newDivision
->Move(dc
, newXPos2
, newYPos2
);
1166 if (compositeParent
->Selected())
1168 compositeParent
->DeleteControlPoints(& dc
);
1169 compositeParent
->MakeControlPoints();
1170 compositeParent
->MakeMandatoryControlPoints();
1172 compositeParent
->Draw(dc
);
1176 // Make one control point for every visible line
1177 void wxDivisionShape::MakeControlPoints()
1179 MakeMandatoryControlPoints();
1182 void wxDivisionShape::MakeMandatoryControlPoints()
1186 GetBoundingBoxMax(&maxX
, &maxY
);
1192 x = (double)(-maxX/2.0);
1194 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1195 CONTROL_POINT_HORIZONTAL);
1196 m_canvas->AddShape(control);
1197 m_controlPoints.Append(control);
1202 y = (double)(-maxY/2.0);
1203 wxDivisionControlPoint *control = new wxDivisionControlPoint(m_canvas, this, CONTROL_POINT_SIZE, x, y,
1204 CONTROL_POINT_VERTICAL);
1205 m_canvas->AddShape(control);
1206 m_controlPoints.Append(control);
1209 switch (m_handleSide
)
1211 case DIVISION_SIDE_LEFT
:
1213 x
= (double)(-maxX
/2.0);
1215 direction
= CONTROL_POINT_HORIZONTAL
;
1218 case DIVISION_SIDE_TOP
:
1221 y
= (double)(-maxY
/2.0);
1222 direction
= CONTROL_POINT_VERTICAL
;
1225 case DIVISION_SIDE_RIGHT
:
1227 x
= (double)(maxX
/2.0);
1229 direction
= CONTROL_POINT_HORIZONTAL
;
1232 case DIVISION_SIDE_BOTTOM
:
1235 y
= (double)(maxY
/2.0);
1236 direction
= CONTROL_POINT_VERTICAL
;
1242 if (m_handleSide
!= DIVISION_SIDE_NONE
)
1244 wxDivisionControlPoint
*control
= new wxDivisionControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, x
, y
,
1246 m_canvas
->AddShape(control
);
1247 m_controlPoints
.Append(control
);
1251 void wxDivisionShape::ResetControlPoints()
1253 ResetMandatoryControlPoints();
1256 void wxDivisionShape::ResetMandatoryControlPoints()
1258 if (m_controlPoints
.GetCount() < 1)
1263 GetBoundingBoxMax(&maxX
, &maxY
);
1265 wxNode *node = m_controlPoints.GetFirst();
1268 wxDivisionControlPoint *control = (wxDivisionControlPoint *)node->GetData();
1269 if (control->type == CONTROL_POINT_HORIZONTAL)
1271 control->xoffset = (double)(-maxX/2.0); control->m_yoffset = 0.0;
1273 else if (control->type == CONTROL_POINT_VERTICAL)
1275 control->xoffset = 0.0; control->m_yoffset = (double)(-maxY/2.0);
1277 node = node->GetNext();
1280 wxNode
*node
= m_controlPoints
.GetFirst();
1281 if ((m_handleSide
== DIVISION_SIDE_LEFT
) && 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_TOP
) && node
)
1289 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1290 control
->m_xoffset
= 0.0; control
->m_yoffset
= (double)(-maxY
/2.0);
1293 if ((m_handleSide
== DIVISION_SIDE_RIGHT
) && node
)
1295 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1296 control
->m_xoffset
= (double)(maxX
/2.0); control
->m_yoffset
= 0.0;
1299 if ((m_handleSide
== DIVISION_SIDE_BOTTOM
) && node
)
1301 wxDivisionControlPoint
*control
= (wxDivisionControlPoint
*)node
->GetData();
1302 control
->m_xoffset
= 0.0; control
->m_yoffset
= (double)(maxY
/2.0);
1306 // Adjust a side, returning FALSE if it's not physically possible.
1307 bool wxDivisionShape::AdjustLeft(double left
, bool test
)
1309 double x2
= (double)(GetX() + (GetWidth()/2.0));
1316 double newW
= x2
- left
;
1317 double newX
= (double)(left
+ newW
/2.0);
1318 SetSize(newW
, GetHeight());
1320 wxClientDC
dc(GetCanvas());
1321 GetCanvas()->PrepareDC(dc
);
1323 Move(dc
, newX
, GetY());
1328 bool wxDivisionShape::AdjustTop(double top
, bool test
)
1330 double y2
= (double)(GetY() + (GetHeight()/2.0));
1337 double newH
= y2
- top
;
1338 double newY
= (double)(top
+ newH
/2.0);
1339 SetSize(GetWidth(), newH
);
1341 wxClientDC
dc(GetCanvas());
1342 GetCanvas()->PrepareDC(dc
);
1344 Move(dc
, GetX(), newY
);
1349 bool wxDivisionShape::AdjustRight(double right
, bool test
)
1351 double x1
= (double)(GetX() - (GetWidth()/2.0));
1358 double newW
= right
- x1
;
1359 double newX
= (double)(x1
+ newW
/2.0);
1360 SetSize(newW
, GetHeight());
1362 wxClientDC
dc(GetCanvas());
1363 GetCanvas()->PrepareDC(dc
);
1365 Move(dc
, newX
, GetY());
1370 bool wxDivisionShape::AdjustBottom(double bottom
, bool test
)
1372 double y1
= (double)(GetY() - (GetHeight()/2.0));
1379 double newH
= bottom
- y1
;
1380 double newY
= (double)(y1
+ newH
/2.0);
1381 SetSize(GetWidth(), newH
);
1383 wxClientDC
dc(GetCanvas());
1384 GetCanvas()->PrepareDC(dc
);
1386 Move(dc
, GetX(), newY
);
1391 wxDivisionControlPoint::wxDivisionControlPoint(wxShapeCanvas
*the_canvas
, wxShape
*object
, double size
, double the_xoffset
, double the_yoffset
, int the_type
):
1392 wxControlPoint(the_canvas
, object
, size
, the_xoffset
, the_yoffset
, the_type
)
1394 SetEraseObject(FALSE
);
1397 wxDivisionControlPoint::~wxDivisionControlPoint()
1401 static double originalX
= 0.0;
1402 static double originalY
= 0.0;
1403 static double originalW
= 0.0;
1404 static double originalH
= 0.0;
1406 // Implement resizing of canvas object
1407 void wxDivisionControlPoint::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
1409 wxControlPoint::OnDragLeft(draw
, x
, y
, keys
, attachment
);
1412 void wxDivisionControlPoint::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
1414 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1415 originalX
= division
->GetX();
1416 originalY
= division
->GetY();
1417 originalW
= division
->GetWidth();
1418 originalH
= division
->GetHeight();
1420 wxControlPoint::OnBeginDragLeft(x
, y
, keys
, attachment
);
1423 void wxDivisionControlPoint::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
1425 wxControlPoint::OnEndDragLeft(x
, y
, keys
, attachment
);
1427 wxClientDC
dc(GetCanvas());
1428 GetCanvas()->PrepareDC(dc
);
1430 wxDivisionShape
*division
= (wxDivisionShape
*)m_shape
;
1431 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)division
->GetParent();
1433 // Need to check it's within the bounds of the parent composite.
1434 double x1
= (double)(divisionParent
->GetX() - (divisionParent
->GetWidth()/2.0));
1435 double y1
= (double)(divisionParent
->GetY() - (divisionParent
->GetHeight()/2.0));
1436 double x2
= (double)(divisionParent
->GetX() + (divisionParent
->GetWidth()/2.0));
1437 double y2
= (double)(divisionParent
->GetY() + (divisionParent
->GetHeight()/2.0));
1439 // Need to check it has not made the division zero or negative width/height
1440 double dx1
= (double)(division
->GetX() - (division
->GetWidth()/2.0));
1441 double dy1
= (double)(division
->GetY() - (division
->GetHeight()/2.0));
1442 double dx2
= (double)(division
->GetX() + (division
->GetWidth()/2.0));
1443 double dy2
= (double)(division
->GetY() + (division
->GetHeight()/2.0));
1445 bool success
= TRUE
;
1446 switch (division
->GetHandleSide())
1448 case DIVISION_SIDE_LEFT
:
1450 if ((x
<= x1
) || (x
>= x2
) || (x
>= dx2
))
1452 // Try it out first...
1453 else if (!division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, TRUE
))
1456 division
->ResizeAdjoining(DIVISION_SIDE_LEFT
, x
, FALSE
);
1460 case DIVISION_SIDE_TOP
:
1462 if ((y
<= y1
) || (y
>= y2
) || (y
>= dy2
))
1464 else if (!division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, TRUE
))
1467 division
->ResizeAdjoining(DIVISION_SIDE_TOP
, y
, FALSE
);
1471 case DIVISION_SIDE_RIGHT
:
1473 if ((x
<= x1
) || (x
>= x2
) || (x
<= dx1
))
1475 else if (!division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, TRUE
))
1478 division
->ResizeAdjoining(DIVISION_SIDE_RIGHT
, x
, FALSE
);
1482 case DIVISION_SIDE_BOTTOM
:
1484 if ((y
<= y1
) || (y
>= y2
) || (y
<= dy1
))
1486 else if (!division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, TRUE
))
1489 division
->ResizeAdjoining(DIVISION_SIDE_BOTTOM
, y
, FALSE
);
1496 division
->SetSize(originalW
, originalH
);
1497 division
->Move(dc
, originalX
, originalY
);
1499 divisionParent
->Draw(dc
);
1500 division
->GetEventHandler()->OnDrawControlPoints(dc
);
1503 /* Resize adjoining divisions.
1505 Behaviour should be as follows:
1506 If right edge moves, find all objects whose left edge
1507 adjoins this object, and move left edge accordingly.
1508 If left..., move ... right.
1509 If top..., move ... bottom.
1510 If bottom..., move top.
1511 If size goes to zero or end position is other side of start position,
1512 resize to original size and return.
1514 bool wxDivisionShape::ResizeAdjoining(int side
, double newPos
, bool test
)
1516 wxCompositeShape
*divisionParent
= (wxCompositeShape
*)GetParent();
1517 wxNode
*node
= divisionParent
->GetDivisions().GetFirst();
1520 wxDivisionShape
*division
= (wxDivisionShape
*)node
->GetData();
1523 case DIVISION_SIDE_LEFT
:
1525 if (division
->m_rightSide
== this)
1527 bool success
= division
->AdjustRight(newPos
, test
);
1528 if (!success
&& test
)
1533 case DIVISION_SIDE_TOP
:
1535 if (division
->m_bottomSide
== this)
1537 bool success
= division
->AdjustBottom(newPos
, test
);
1538 if (!success
&& test
)
1543 case DIVISION_SIDE_RIGHT
:
1545 if (division
->m_leftSide
== this)
1547 bool success
= division
->AdjustLeft(newPos
, test
);
1548 if (!success
&& test
)
1553 case DIVISION_SIDE_BOTTOM
:
1555 if (division
->m_topSide
== this)
1557 bool success
= division
->AdjustTop(newPos
, test
);
1558 if (!success
&& test
)
1566 node
= node
->GetNext();
1573 * Popup menu for editing divisions
1576 class OGLPopupDivisionMenu
: public wxMenu
{
1578 OGLPopupDivisionMenu() : wxMenu() {
1579 Append(DIVISION_MENU_SPLIT_HORIZONTALLY
, wxT("Split horizontally"));
1580 Append(DIVISION_MENU_SPLIT_VERTICALLY
, wxT("Split vertically"));
1582 Append(DIVISION_MENU_EDIT_LEFT_EDGE
, wxT("Edit left edge"));
1583 Append(DIVISION_MENU_EDIT_TOP_EDGE
, wxT("Edit top edge"));
1586 void OnMenu(wxCommandEvent
& event
);
1588 DECLARE_EVENT_TABLE()
1591 BEGIN_EVENT_TABLE(OGLPopupDivisionMenu
, wxMenu
)
1592 EVT_CUSTOM_RANGE(wxEVT_COMMAND_MENU_SELECTED
,
1593 DIVISION_MENU_SPLIT_HORIZONTALLY
,
1594 DIVISION_MENU_EDIT_BOTTOM_EDGE
,
1595 OGLPopupDivisionMenu::OnMenu
)
1599 void OGLPopupDivisionMenu::OnMenu(wxCommandEvent
& event
)
1601 wxDivisionShape
*division
= (wxDivisionShape
*)GetClientData();
1602 switch (event
.GetInt())
1604 case DIVISION_MENU_SPLIT_HORIZONTALLY
:
1606 division
->Divide(wxHORIZONTAL
);
1609 case DIVISION_MENU_SPLIT_VERTICALLY
:
1611 division
->Divide(wxVERTICAL
);
1614 case DIVISION_MENU_EDIT_LEFT_EDGE
:
1616 division
->EditEdge(DIVISION_SIDE_LEFT
);
1619 case DIVISION_MENU_EDIT_TOP_EDGE
:
1621 division
->EditEdge(DIVISION_SIDE_TOP
);
1629 void wxDivisionShape::EditEdge(int side
)
1631 wxMessageBox(wxT("EditEdge() not implemented"), wxT("OGL"), wxOK
);
1634 wxBeginBusyCursor();
1636 wxPen
*currentPen
= NULL
;
1637 char **pColour
= NULL
;
1638 char **pStyle
= NULL
;
1639 if (side
== DIVISION_SIDE_LEFT
)
1641 currentPen
= m_leftSidePen
;
1642 pColour
= &m_leftSideColour
;
1643 pStyle
= &m_leftSideStyle
;
1647 currentPen
= m_topSidePen
;
1648 pColour
= &m_topSideColour
;
1649 pStyle
= &m_topSideStyle
;
1652 GraphicsForm
*form
= new GraphicsForm("Containers");
1653 int lineWidth
= currentPen
->GetWidth();
1655 form
->Add(wxMakeFormShort("Width", &lineWidth
, wxFORM_DEFAULT
, NULL
, NULL
, wxVERTICAL
,
1657 form
->Add(wxMakeFormString("Colour", pColour
, wxFORM_CHOICE
,
1658 new wxList(wxMakeConstraintStrings(
1682 NULL
), NULL
, wxVERTICAL
, 150));
1683 form
->Add(wxMakeFormString("Style", pStyle
, wxFORM_CHOICE
,
1684 new wxList(wxMakeConstraintStrings(
1691 NULL
), NULL
, wxVERTICAL
, 100));
1693 wxDialogBox
*dialog
= new wxDialogBox(m_canvas
->GetParent(), "Division properties", 10, 10, 500, 500);
1694 if (GraphicsLabelFont
)
1695 dialog
->SetLabelFont(GraphicsLabelFont
);
1696 if (GraphicsButtonFont
)
1697 dialog
->SetButtonFont(GraphicsButtonFont
);
1699 form
->AssociatePanel(dialog
);
1700 form
->dialog
= dialog
;
1703 dialog
->Centre(wxBOTH
);
1708 int lineStyle
= wxSOLID
;
1711 if (strcmp(*pStyle
, "Solid") == 0)
1712 lineStyle
= wxSOLID
;
1713 else if (strcmp(*pStyle
, "Dot") == 0)
1715 else if (strcmp(*pStyle
, "Short Dash") == 0)
1716 lineStyle
= wxSHORT_DASH
;
1717 else if (strcmp(*pStyle
, "Long Dash") == 0)
1718 lineStyle
= wxLONG_DASH
;
1719 else if (strcmp(*pStyle
, "Dot Dash") == 0)
1720 lineStyle
= wxDOT_DASH
;
1723 wxPen
*newPen
= wxThePenList
->FindOrCreatePen(*pColour
, lineWidth
, lineStyle
);
1726 if (side
== DIVISION_SIDE_LEFT
)
1727 m_leftSidePen
= newPen
;
1729 m_topSidePen
= newPen
;
1731 // Need to draw whole image again
1732 wxCompositeShape
*compositeParent
= (wxCompositeShape
*)GetParent();
1733 compositeParent
->Draw(dc
);
1738 void wxDivisionShape::PopupMenu(double x
, double y
)
1740 wxMenu
* oglPopupDivisionMenu
= new OGLPopupDivisionMenu
;
1742 oglPopupDivisionMenu
->SetClientData((void *)this);
1744 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, TRUE
);
1746 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_LEFT_EDGE
, FALSE
);
1748 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, TRUE
);
1750 oglPopupDivisionMenu
->Enable(DIVISION_MENU_EDIT_TOP_EDGE
, FALSE
);
1753 m_canvas
->GetViewStart(&x1
, &y1
);
1756 m_canvas
->GetScrollPixelsPerUnit(&unit_x
, &unit_y
);
1758 wxClientDC
dc(GetCanvas());
1759 GetCanvas()->PrepareDC(dc
);
1761 int mouse_x
= (int)(dc
.LogicalToDeviceX((long)(x
- x1
*unit_x
)));
1762 int mouse_y
= (int)(dc
.LogicalToDeviceY((long)(y
- y1
*unit_y
)));
1764 m_canvas
->PopupMenu(oglPopupDivisionMenu
, mouse_x
, mouse_y
);
1765 delete oglPopupDivisionMenu
;
1768 void wxDivisionShape::SetLeftSideColour(const wxString
& colour
)
1770 m_leftSideColour
= colour
;
1773 void wxDivisionShape::SetTopSideColour(const wxString
& colour
)
1775 m_topSideColour
= colour
;
1778 void wxDivisionShape::SetLeftSideStyle(const wxString
& style
)
1780 m_leftSideStyle
= style
;
1783 void wxDivisionShape::SetTopSideStyle(const wxString
& style
)
1785 m_topSideStyle
= style
;