X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2e5ed787e9f0f4eac35b9a55e97ea4a177e2fdda..31811e1acaf3dd16403b94f5ff93c41e4e4ca9bb:/utils/ogl/src/basic.cpp?ds=sidebyside diff --git a/utils/ogl/src/basic.cpp b/utils/ogl/src/basic.cpp index ce0ed54a71..6961d45852 100644 --- a/utils/ogl/src/basic.cpp +++ b/utils/ogl/src/basic.cpp @@ -28,7 +28,7 @@ #include #endif -#if USE_IOSTREAMH +#if wxUSE_IOSTREAMH #include #else #include @@ -127,6 +127,12 @@ void wxShapeEvtHandler::OnDrawContents(wxDC& dc) m_previousHandler->OnDrawContents(dc); } +void wxShapeEvtHandler::OnDrawBranches(wxDC& dc, bool erase) +{ + if (m_previousHandler) + m_previousHandler->OnDrawBranches(dc, erase); +} + void wxShapeEvtHandler::OnSize(double x, double y) { if (m_previousHandler) @@ -171,6 +177,12 @@ void wxShapeEvtHandler::OnLeftClick(double x, double y, int keys, int attachment m_previousHandler->OnLeftClick(x, y, keys, attachment); } +void wxShapeEvtHandler::OnLeftDoubleClick(double x, double y, int keys, int attachment) +{ + if (m_previousHandler) + m_previousHandler->OnLeftDoubleClick(x, y, keys, attachment); +} + void wxShapeEvtHandler::OnRightClick(double x, double y, int keys, int attachment) { if (m_previousHandler) @@ -276,7 +288,7 @@ wxShape::wxShape(wxShapeCanvas *can) m_visible = FALSE; m_clientData = NULL; m_selected = FALSE; - m_attachmentMode = FALSE; + m_attachmentMode = ATTACHMENT_MODE_NONE; m_spaceAttachments = TRUE; m_disableLabel = FALSE; m_fixedWidth = FALSE; @@ -294,8 +306,13 @@ wxShape::wxShape(wxShapeCanvas *can) m_textMarginY = 5.0; m_regionName = "0"; m_centreResize = TRUE; + m_maintainAspectRatio = FALSE; m_highlighted = FALSE; m_rotation = 0.0; + m_branchNeckLength = 10; + m_branchStemLength = 10; + m_branchSpacing = 10; + m_branchStyle = BRANCHING_ATTACHMENT_NORMAL; // Set up a default region. Much of the above will be put into // the region eventually (the duplication is for compatibility) @@ -540,7 +557,6 @@ bool wxShape::HitTest(double x, double y, int *attachment, double *distance) int nearest_attachment = 0; - // If within the bounding box, check the attachment points // within the object. @@ -549,10 +565,13 @@ bool wxShape::HitTest(double x, double y, int *attachment, double *distance) int n = GetNumberOfAttachments(); double nearest = 999999.0; + // GetAttachmentPosition[Edge] takes a logical attachment position, + // i.e. if it's rotated through 90%, position 0 is East-facing. + for (int i = 0; i < n; i++) { double xp, yp; - if (GetAttachmentPosition(i, &xp, &yp)) + if (GetAttachmentPositionEdge(i, &xp, &yp)) { double l = (double)sqrt(((xp - x) * (xp - x)) + ((yp - y) * (yp - y))); @@ -1037,7 +1056,8 @@ void wxShape::DrawLinks(wxDC& dc, int attachment, bool recurse) // This is the default, rectangular implementation. bool wxShape::AttachmentSortTest(int attachmentPoint, const wxRealPoint& pt1, const wxRealPoint& pt2) { - switch (attachmentPoint) + int physicalAttachment = LogicalToPhysicalAttachment(attachmentPoint); + switch (physicalAttachment) { case 0: case 2: @@ -1059,7 +1079,7 @@ bool wxShape::AttachmentSortTest(int attachmentPoint, const wxRealPoint& pt1, co bool wxShape::MoveLineToNewAttachment(wxDC& dc, wxLineShape *to_move, double x, double y) { - if (!GetAttachmentMode()) + if (GetAttachmentMode() == ATTACHMENT_MODE_NONE) return FALSE; int newAttachment, oldAttachment; @@ -1501,6 +1521,7 @@ void wxShape::Draw(wxDC& dc) GetEventHandler()->OnDraw(dc); GetEventHandler()->OnDrawContents(dc); GetEventHandler()->OnDrawControlPoints(dc); + GetEventHandler()->OnDrawBranches(dc); } } @@ -1534,6 +1555,7 @@ void wxShape::Erase(wxDC& dc) { GetEventHandler()->OnErase(dc); GetEventHandler()->OnEraseControlPoints(dc); + GetEventHandler()->OnDrawBranches(dc, TRUE); } void wxShape::EraseContents(wxDC& dc) @@ -1590,6 +1612,43 @@ void wxShape::AddLine(wxLineShape *line, wxShape *other, // The line ordering int positionFrom, int positionTo) { + if (positionFrom == -1) + { + if (!m_lines.Member(line)) + m_lines.Append(line); + } + else + { + // Don't preserve old ordering if we have new ordering instructions + m_lines.DeleteObject(line); + if (positionFrom < m_lines.Number()) + { + wxNode* node = m_lines.Nth(positionFrom); + m_lines.Insert(node, line); + } + else + m_lines.Append(line); + } + + if (positionTo == -1) + { + if (!other->m_lines.Member(line)) + other->m_lines.Append(line); + } + else + { + // Don't preserve old ordering if we have new ordering instructions + other->m_lines.DeleteObject(line); + if (positionTo < other->m_lines.Number()) + { + wxNode* node = other->m_lines.Nth(positionTo); + other->m_lines.Insert(node, line); + } + else + other->m_lines.Append(line); + } +#if 0 + // Wrong: doesn't preserve ordering of shape already linked m_lines.DeleteObject(line); other->m_lines.DeleteObject(line); @@ -1618,6 +1677,7 @@ void wxShape::AddLine(wxLineShape *line, wxShape *other, else other->m_lines.Append(line); } +#endif line->SetFrom(this); line->SetTo(other); @@ -1635,12 +1695,7 @@ void wxShape::RemoveLine(wxLineShape *line) } #ifdef PROLOGIO -char *wxShape::GetFunctor() -{ - return "node_image"; -} - -void wxShape::WritePrologAttributes(wxExpr *clause) +void wxShape::WriteAttributes(wxExpr *clause) { clause->AddAttributeValueString("type", GetClassInfo()->GetClassName()); clause->AddAttributeValue("id", m_id); @@ -1687,7 +1742,7 @@ void wxShape::WritePrologAttributes(wxExpr *clause) int n_lines = m_lines.Number(); if (n_lines > 0) { - wxExpr *list = new wxExpr(PrologList); + wxExpr *list = new wxExpr(wxExprList); wxNode *node = m_lines.First(); while (node) { @@ -1714,6 +1769,7 @@ void wxShape::WritePrologAttributes(wxExpr *clause) clause->AddAttributeValue("shadow_mode", (long)m_shadowMode); if (m_centreResize != TRUE) clause->AddAttributeValue("centre_resize", (long)0); + clause->AddAttributeValue("maintain_aspect_ratio", (long) m_maintainAspectRatio); if (m_highlighted != FALSE) clause->AddAttributeValue("hilite", (long)m_highlighted); @@ -1723,15 +1779,23 @@ void wxShape::WritePrologAttributes(wxExpr *clause) if (m_rotation != 0.0) clause->AddAttributeValue("rotation", m_rotation); + if (!this->IsKindOf(CLASSINFO(wxLineShape))) + { + clause->AddAttributeValue("neck_length", (long) m_branchNeckLength); + clause->AddAttributeValue("stem_length", (long) m_branchStemLength); + clause->AddAttributeValue("branch_spacing", (long) m_branchSpacing); + clause->AddAttributeValue("branch_style", (long) m_branchStyle); + } + // Write user-defined attachment points, if any if (m_attachmentPoints.Number() > 0) { - wxExpr *attachmentList = new wxExpr(PrologList); + wxExpr *attachmentList = new wxExpr(wxExprList); wxNode *node = m_attachmentPoints.First(); while (node) { wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data(); - wxExpr *pointExpr = new wxExpr(PrologList); + wxExpr *pointExpr = new wxExpr(wxExprList); pointExpr->Append(new wxExpr((long)point->m_id)); pointExpr->Append(new wxExpr(point->m_x)); pointExpr->Append(new wxExpr(point->m_y)); @@ -1762,9 +1826,9 @@ void wxShape::WriteRegions(wxExpr *clause) // Original text and region attributes: // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY // formatMode fontSize fontFamily fontStyle fontWeight textColour) - wxExpr *regionExpr = new wxExpr(PrologList); - regionExpr->Append(new wxExpr(PrologString, (region->m_regionName ? region->m_regionName : ""))); - regionExpr->Append(new wxExpr(PrologString, (region->m_regionText ? region->m_regionText : ""))); + wxExpr *regionExpr = new wxExpr(wxExprList); + regionExpr->Append(new wxExpr(wxExprString, (region->m_regionName ? region->m_regionName : ""))); + regionExpr->Append(new wxExpr(wxExprString, (region->m_regionText ? region->m_regionText : ""))); regionExpr->Append(new wxExpr(region->m_x)); regionExpr->Append(new wxExpr(region->m_y)); @@ -1782,24 +1846,24 @@ void wxShape::WriteRegions(wxExpr *clause) regionExpr->Append(new wxExpr((long)(region->m_font ? region->m_font->GetFamily() : wxDEFAULT))); regionExpr->Append(new wxExpr((long)(region->m_font ? region->m_font->GetStyle() : wxDEFAULT))); regionExpr->Append(new wxExpr((long)(region->m_font ? region->m_font->GetWeight() : wxNORMAL))); - regionExpr->Append(new wxExpr(PrologString, region->m_textColour ? region->m_textColour : "BLACK")); + regionExpr->Append(new wxExpr(wxExprString, region->m_textColour ? region->m_textColour : "BLACK")); // New members for pen colour/style - regionExpr->Append(new wxExpr(PrologString, region->m_penColour ? region->m_penColour : "BLACK")); + regionExpr->Append(new wxExpr(wxExprString, region->m_penColour ? region->m_penColour : "BLACK")); regionExpr->Append(new wxExpr((long)region->m_penStyle)); // Formatted text: // text1 = ((x y string) (x y string) ...) - wxExpr *textExpr = new wxExpr(PrologList); + wxExpr *textExpr = new wxExpr(wxExprList); wxNode *textNode = region->m_formattedText.First(); while (textNode) { wxShapeTextLine *line = (wxShapeTextLine *)textNode->Data(); - wxExpr *list2 = new wxExpr(PrologList); + wxExpr *list2 = new wxExpr(wxExprList); list2->Append(new wxExpr(line->GetX())); list2->Append(new wxExpr(line->GetY())); - list2->Append(new wxExpr(PrologString, line->GetText())); + list2->Append(new wxExpr(wxExprString, line->GetText())); textExpr->Append(list2); textNode = textNode->Next(); } @@ -1813,7 +1877,7 @@ void wxShape::WriteRegions(wxExpr *clause) } } -void wxShape::ReadPrologAttributes(wxExpr *clause) +void wxShape::ReadAttributes(wxExpr *clause) { clause->GetAttributeValue("id", m_id); RegisterId(m_id); @@ -1824,7 +1888,7 @@ void wxShape::ReadPrologAttributes(wxExpr *clause) // Input text strings (FOR COMPATIBILITY WITH OLD FILES ONLY. SEE REGION CODE BELOW.) ClearText(); wxExpr *strings = clause->AttributeValue("text"); - if (strings && strings->Type() == PrologList) + if (strings && strings->Type() == wxExprList) { m_formatted = TRUE; // Assume text is formatted unless we prove otherwise wxExpr *node = strings->value.first; @@ -1837,27 +1901,27 @@ void wxShape::ReadPrologAttributes(wxExpr *clause) // string_expr can either be a string, or a list of // 3 elements: x, y, and string. - if (string_expr->Type() == PrologString) + if (string_expr->Type() == wxExprString) { the_string = string_expr->StringValue(); m_formatted = FALSE; } - else if (string_expr->Type() == PrologList) + else if (string_expr->Type() == wxExprList) { wxExpr *first = string_expr->value.first; wxExpr *second = first ? first->next : NULL; wxExpr *third = second ? second->next : NULL; if (first && second && third && - (first->Type() == PrologReal || first->Type() == PrologInteger) && - (second->Type() == PrologReal || second->Type() == PrologInteger) && - third->Type() == PrologString) + (first->Type() == wxExprReal || first->Type() == wxExprInteger) && + (second->Type() == wxExprReal || second->Type() == wxExprInteger) && + third->Type() == wxExprString) { - if (first->Type() == PrologReal) + if (first->Type() == wxExprReal) the_x = first->RealValue(); else the_x = (double)first->IntegerValue(); - if (second->Type() == PrologReal) + if (second->Type() == wxExprReal) the_y = second->RealValue(); else the_y = (double)second->IntegerValue(); @@ -1877,7 +1941,7 @@ void wxShape::ReadPrologAttributes(wxExpr *clause) int pen_width = 1; int pen_style = wxSOLID; int brush_style = wxSOLID; - m_attachmentMode = FALSE; + m_attachmentMode = ATTACHMENT_MODE_NONE; clause->GetAttributeValue("pen_colour", pen_string); clause->GetAttributeValue("text_colour", m_textColourName); @@ -1893,7 +1957,7 @@ void wxShape::ReadPrologAttributes(wxExpr *clause) int iVal = (int) m_attachmentMode; clause->GetAttributeValue("use_attachments", iVal); - m_attachmentMode = (iVal != 0); + m_attachmentMode = iVal; clause->GetAttributeValue("sensitivity", m_sensitivity); @@ -1912,10 +1976,28 @@ void wxShape::ReadPrologAttributes(wxExpr *clause) clause->GetAttributeValue("format_mode", m_formatMode); clause->GetAttributeValue("shadow_mode", m_shadowMode); + iVal = m_branchNeckLength; + clause->GetAttributeValue("neck_length", iVal); + m_branchNeckLength = iVal; + + iVal = m_branchStemLength; + clause->GetAttributeValue("stem_length", iVal); + m_branchStemLength = iVal; + + iVal = m_branchSpacing; + clause->GetAttributeValue("branch_spacing", iVal); + m_branchSpacing = iVal; + + clause->GetAttributeValue("branch_style", m_branchStyle); + iVal = (int) m_centreResize; clause->GetAttributeValue("centre_resize", iVal); m_centreResize = (iVal != 0); + iVal = (int) m_maintainAspectRatio; + clause->GetAttributeValue("maintain_aspect_ratio", iVal); + m_maintainAspectRatio = (iVal != 0); + iVal = (int) m_highlighted; clause->GetAttributeValue("hilite", iVal); m_highlighted = (iVal != 0); @@ -2022,7 +2104,7 @@ void wxShape::ReadRegions(wxExpr *clause) wxString penColour(""); int penStyle = wxSOLID; - if (regionExpr->Type() == PrologList) + if (regionExpr->Type() == wxExprList) { wxExpr *nameExpr = regionExpr->Nth(0); wxExpr *textExpr = regionExpr->Nth(1); @@ -2100,7 +2182,7 @@ void wxShape::ReadRegions(wxExpr *clause) * */ textExpr = clause->AttributeValue(textNameBuf); - if (textExpr && (textExpr->Type() == PrologList)) + if (textExpr && (textExpr->Type() == wxExprList)) { wxExpr *node = textExpr->value.first; while (node) @@ -2112,27 +2194,27 @@ void wxShape::ReadRegions(wxExpr *clause) // string_expr can either be a string, or a list of // 3 elements: x, y, and string. - if (string_expr->Type() == PrologString) + if (string_expr->Type() == wxExprString) { the_string = string_expr->StringValue(); m_formatted = FALSE; } - else if (string_expr->Type() == PrologList) + else if (string_expr->Type() == wxExprList) { wxExpr *first = string_expr->value.first; wxExpr *second = first ? first->next : NULL; wxExpr *third = second ? second->next : NULL; if (first && second && third && - (first->Type() == PrologReal || first->Type() == PrologInteger) && - (second->Type() == PrologReal || second->Type() == PrologInteger) && - third->Type() == PrologString) + (first->Type() == wxExprReal || first->Type() == wxExprInteger) && + (second->Type() == wxExprReal || second->Type() == wxExprInteger) && + third->Type() == wxExprString) { - if (first->Type() == PrologReal) + if (first->Type() == wxExprReal) the_x = first->RealValue(); else the_x = (double)first->IntegerValue(); - if (second->Type() == PrologReal) + if (second->Type() == wxExprReal) the_y = second->RealValue(); else the_y = (double)second->IntegerValue(); @@ -2191,6 +2273,7 @@ void wxShape::Copy(wxShape& copy) copy.m_brush = m_brush; copy.m_textColour = m_textColour; copy.m_centreResize = m_centreResize; + copy.m_maintainAspectRatio = m_maintainAspectRatio; copy.m_attachmentMode = m_attachmentMode; copy.m_spaceAttachments = m_spaceAttachments; copy.m_highlighted = m_highlighted; @@ -2211,6 +2294,10 @@ void wxShape::Copy(wxShape& copy) copy.m_shadowOffsetY = m_shadowOffsetY; copy.m_shadowBrush = m_shadowBrush; + copy.m_branchNeckLength = m_branchNeckLength; + copy.m_branchStemLength = m_branchStemLength; + copy.m_branchSpacing = m_branchSpacing; + // Copy text regions copy.ClearRegions(); wxNode *node = m_regions.First(); @@ -2548,7 +2635,7 @@ bool wxShape::AncestorSelected() const return GetParent()->AncestorSelected(); } -int wxShape::GetNumberOfAttachments() +int wxShape::GetNumberOfAttachments() const { // Should return the MAXIMUM attachment point id here, // so higher-level functions can iterate through all attachments, @@ -2570,10 +2657,12 @@ int wxShape::GetNumberOfAttachments() } } -bool wxShape::AttachmentIsValid(int attachment) +bool wxShape::AttachmentIsValid(int attachment) const { - if ((attachment >= 0) && (attachment < 4)) - return TRUE; + if (m_attachmentPoints.Number() == 0) + { + return ((attachment >= 0) && (attachment < 4)) ; + } wxNode *node = m_attachmentPoints.First(); while (node) @@ -2589,28 +2678,97 @@ bool wxShape::AttachmentIsValid(int attachment) bool wxShape::GetAttachmentPosition(int attachment, double *x, double *y, int nth, int no_arcs, wxLineShape *line) { - if (!m_attachmentMode) - { - *x = m_xpos; *y = m_ypos; - return TRUE; - } - else - { - wxNode *node = m_attachmentPoints.First(); - while (node) + if (m_attachmentMode == ATTACHMENT_MODE_NONE) { - wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data(); - if (point->m_id == attachment) - { - *x = (double)(m_xpos + point->m_x); - *y = (double)(m_ypos + point->m_y); + *x = m_xpos; *y = m_ypos; + return TRUE; + } + else if (m_attachmentMode == ATTACHMENT_MODE_BRANCHING) + { + wxRealPoint pt, stemPt; + GetBranchingAttachmentPoint(attachment, nth, pt, stemPt); + *x = pt.x; + *y = pt.y; return TRUE; - } - node = node->Next(); } - *x = m_xpos; *y = m_ypos; + else if (m_attachmentMode == ATTACHMENT_MODE_EDGE) + { + if (m_attachmentPoints.Number() > 0) + { + wxNode *node = m_attachmentPoints.First(); + while (node) + { + wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data(); + if (point->m_id == attachment) + { + *x = (double)(m_xpos + point->m_x); + *y = (double)(m_ypos + point->m_y); + return TRUE; + } + node = node->Next(); + } + *x = m_xpos; *y = m_ypos; + return FALSE; + } + else + { + // Assume is rectangular + double w, h; + GetBoundingBoxMax(&w, &h); + double top = (double)(m_ypos + h/2.0); + double bottom = (double)(m_ypos - h/2.0); + double left = (double)(m_xpos - w/2.0); + double right = (double)(m_xpos + w/2.0); + + bool isEnd = (line && line->IsEnd(this)); + + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + + // Simplified code + switch (physicalAttachment) + { + case 0: + { + wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, bottom), wxRealPoint(right, bottom), + nth, no_arcs, line); + + *x = pt.x; *y = pt.y; + break; + } + case 1: + { + wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(right, bottom), wxRealPoint(right, top), + nth, no_arcs, line); + + *x = pt.x; *y = pt.y; + break; + } + case 2: + { + wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, top), wxRealPoint(right, top), + nth, no_arcs, line); + + *x = pt.x; *y = pt.y; + break; + } + case 3: + { + wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, bottom), wxRealPoint(left, top), + nth, no_arcs, line); + + *x = pt.x; *y = pt.y; + break; + } + default: + { + return FALSE; + break; + } + } + return TRUE; + } + } return FALSE; - } } void wxShape::GetBoundingBoxMax(double *w, double *h) @@ -2754,3 +2912,365 @@ int wxShape::GetLinePosition(wxLineShape* line) return 0; } +// +// |________| +// | <- root +// | <- neck +// shoulder1 ->---------<- shoulder2 +// | | | | | +// <- branching attachment point N-1 + +// This function gets information about where branching connections go. +// Returns FALSE if there are no lines at this attachment. +bool wxShape::GetBranchingAttachmentInfo(int attachment, wxRealPoint& root, wxRealPoint& neck, + wxRealPoint& shoulder1, wxRealPoint& shoulder2) +{ + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + + // Number of lines at this attachment. + int lineCount = GetAttachmentLineCount(attachment); + + if (lineCount == 0) + return FALSE; + + int totalBranchLength = m_branchSpacing * (lineCount - 1); + + root = GetBranchingAttachmentRoot(attachment); + + // Assume that we have attachment points 0 to 3: top, right, bottom, left. + switch (physicalAttachment) + { + case 0: + { + neck.x = GetX(); + neck.y = root.y - m_branchNeckLength; + + shoulder1.x = root.x - (totalBranchLength/2.0) ; + shoulder2.x = root.x + (totalBranchLength/2.0) ; + + shoulder1.y = neck.y; + shoulder2.y = neck.y; + break; + } + case 1: + { + neck.x = root.x + m_branchNeckLength; + neck.y = root.y; + + shoulder1.x = neck.x ; + shoulder2.x = neck.x ; + + shoulder1.y = neck.y - (totalBranchLength/2.0) ; + shoulder2.y = neck.y + (totalBranchLength/2.0) ; + break; + } + case 2: + { + neck.x = GetX(); + neck.y = root.y + m_branchNeckLength; + + shoulder1.x = root.x - (totalBranchLength/2.0) ; + shoulder2.x = root.x + (totalBranchLength/2.0) ; + + shoulder1.y = neck.y; + shoulder2.y = neck.y; + break; + } + case 3: + { + neck.x = root.x - m_branchNeckLength; + neck.y = root.y ; + + shoulder1.x = neck.x ; + shoulder2.x = neck.x ; + + shoulder1.y = neck.y - (totalBranchLength/2.0) ; + shoulder2.y = neck.y + (totalBranchLength/2.0) ; + break; + } + default: + { + wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentInfo." ); + break; + } + } + return TRUE; +} + +// n is the number of the adjoining line, from 0 to N-1 where N is the number of lines +// at this attachment point. +// Get the attachment point where the arc joins the stem, and also the point where the +// the stem meets the shoulder. +bool wxShape::GetBranchingAttachmentPoint(int attachment, int n, wxRealPoint& pt, wxRealPoint& stemPt) +{ + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + + wxRealPoint root, neck, shoulder1, shoulder2; + GetBranchingAttachmentInfo(attachment, root, neck, shoulder1, shoulder2); + + // Assume that we have attachment points 0 to 3: top, right, bottom, left. + switch (physicalAttachment) + { + case 0: + { + pt.y = neck.y - m_branchStemLength; + pt.x = shoulder1.x + n*m_branchSpacing; + + stemPt.x = pt.x; + stemPt.y = neck.y; + break; + } + case 2: + { + pt.y = neck.y + m_branchStemLength; + pt.x = shoulder1.x + n*m_branchSpacing; + + stemPt.x = pt.x; + stemPt.y = neck.y; + break; + } + case 1: + { + pt.x = neck.x + m_branchStemLength; + pt.y = shoulder1.y + n*m_branchSpacing; + + stemPt.x = neck.x; + stemPt.y = pt.y; + break; + } + case 3: + { + pt.x = neck.x - m_branchStemLength; + pt.y = shoulder1.y + n*m_branchSpacing; + + stemPt.x = neck.x; + stemPt.y = pt.y; + break; + } + default: + { + wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentPoint." ); + break; + } + } + + return TRUE; +} + +// Get the number of lines at this attachment position. +int wxShape::GetAttachmentLineCount(int attachment) const +{ + int count = 0; + wxNode* node = m_lines.First(); + while (node) + { + wxLineShape* lineShape = (wxLineShape*) node->Data(); + if ((lineShape->GetFrom() == this) && (lineShape->GetAttachmentFrom() == attachment)) + count ++; + else if ((lineShape->GetTo() == this) && (lineShape->GetAttachmentTo() == attachment)) + count ++; + + node = node->Next(); + } + return count; +} + +// This function gets the root point at the given attachment. +wxRealPoint wxShape::GetBranchingAttachmentRoot(int attachment) +{ + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + + wxRealPoint root; + + double width, height; + GetBoundingBoxMax(& width, & height); + + // Assume that we have attachment points 0 to 3: top, right, bottom, left. + switch (physicalAttachment) + { + case 0: + { + root.x = GetX() ; + root.y = GetY() - height/2.0; + break; + } + case 1: + { + root.x = GetX() + width/2.0; + root.y = GetY() ; + break; + } + case 2: + { + root.x = GetX() ; + root.y = GetY() + height/2.0; + break; + } + case 3: + { + root.x = GetX() - width/2.0; + root.y = GetY() ; + break; + } + default: + { + wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentRoot." ); + break; + } + } + return root; +} + +// Draw or erase the branches (not the actual arcs though) +void wxShape::OnDrawBranches(wxDC& dc, int attachment, bool erase) +{ + int count = GetAttachmentLineCount(attachment); + if (count == 0) + return; + + wxRealPoint root, neck, shoulder1, shoulder2; + GetBranchingAttachmentInfo(attachment, root, neck, shoulder1, shoulder2); + + if (erase) + { + dc.SetPen(*wxWHITE_PEN); + dc.SetBrush(*wxWHITE_BRUSH); + } + else + { + dc.SetPen(*wxBLACK_PEN); + dc.SetBrush(*wxBLACK_BRUSH); + } + + // Draw neck + dc.DrawLine((long) root.x, (long) root.y, (long) neck.x, (long) neck.y); + + if (count > 1) + { + // Draw shoulder-to-shoulder line + dc.DrawLine((long) shoulder1.x, (long) shoulder1.y, (long) shoulder2.x, (long) shoulder2.y); + } + // Draw all the little branches + int i; + for (i = 0; i < count; i++) + { + wxRealPoint pt, stemPt; + GetBranchingAttachmentPoint(attachment, i, pt, stemPt); + dc.DrawLine((long) stemPt.x, (long) stemPt.y, (long) pt.x, (long) pt.y); + + if ((GetBranchStyle() & BRANCHING_ATTACHMENT_BLOB) && (count > 1)) + { + long blobSize=6; +// dc.DrawEllipse((long) (stemPt.x + 0.5 - (blobSize/2.0)), (long) (stemPt.y + 0.5 - (blobSize/2.0)), blobSize, blobSize); + dc.DrawEllipse((long) (stemPt.x - (blobSize/2.0)), (long) (stemPt.y - (blobSize/2.0)), blobSize, blobSize); + } + } +} + +// Draw or erase the branches (not the actual arcs though) +void wxShape::OnDrawBranches(wxDC& dc, bool erase) +{ + if (m_attachmentMode != ATTACHMENT_MODE_BRANCHING) + return; + + int count = GetNumberOfAttachments(); + int i; + for (i = 0; i < count; i++) + OnDrawBranches(dc, i, erase); +} + +// Only get the attachment position at the _edge_ of the shape, ignoring +// branching mode. This is used e.g. to indicate the edge of interest, not the point +// on the attachment branch. +bool wxShape::GetAttachmentPositionEdge(int attachment, double *x, double *y, + int nth, int no_arcs, wxLineShape *line) +{ + int oldMode = m_attachmentMode; + + // Calculate as if to edge, not branch + if (m_attachmentMode == ATTACHMENT_MODE_BRANCHING) + m_attachmentMode = ATTACHMENT_MODE_EDGE; + bool success = GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); + m_attachmentMode = oldMode; + + return success; +} + +// Rotate the standard attachment point from physical (0 is always North) +// to logical (0 -> 1 if rotated by 90 degrees) +int wxShape::PhysicalToLogicalAttachment(int physicalAttachment) const +{ + const double pi = 3.1415926535897932384626433832795 ; + int i; + if (oglRoughlyEqual(GetRotation(), 0.0)) + { + i = physicalAttachment; + } + else if (oglRoughlyEqual(GetRotation(), (pi/2.0))) + { + i = physicalAttachment - 1; + } + else if (oglRoughlyEqual(GetRotation(), pi)) + { + i = physicalAttachment - 2; + } + else if (oglRoughlyEqual(GetRotation(), (3.0*pi/2.0))) + { + i = physicalAttachment - 3; + } + else + // Can't handle -- assume the same. + return physicalAttachment; + + if (i < 0) + i += 4; + + return i; +} + +// Rotate the standard attachment point from logical +// to physical (0 is always North) +int wxShape::LogicalToPhysicalAttachment(int logicalAttachment) const +{ + const double pi = 3.1415926535897932384626433832795 ; + int i; + if (oglRoughlyEqual(GetRotation(), 0.0)) + { + i = logicalAttachment; + } + else if (oglRoughlyEqual(GetRotation(), (pi/2.0))) + { + i = logicalAttachment + 1; + } + else if (oglRoughlyEqual(GetRotation(), pi)) + { + i = logicalAttachment + 2; + } + else if (oglRoughlyEqual(GetRotation(), (3.0*pi/2.0))) + { + i = logicalAttachment + 3; + } + else + // Can't handle -- assume the same. + return logicalAttachment; + + if (i > 3) + i -= 4; + + return i; +} + +void wxShape::Rotate(double WXUNUSED(x), double WXUNUSED(y), double theta) +{ + const double pi = 3.1415926535897932384626433832795 ; + m_rotation = theta; + if (m_rotation < 0.0) + { + m_rotation += 2*pi; + } + else if (m_rotation > 2*pi) + { + m_rotation -= 2*pi; + } +} +