void udStateChartOptimizer::FindTransWithIdenticalActions(ShapeList& transitions, ShapeList& sublist) { sublist.Clear(); ShapeList::compatibility_iterator node = transitions.GetFirst(); if( !node ) return; udTransElementItem *pTransElement; wxSFLineShape *pTrans = (wxSFLineShape*)node->GetData(); wxString sActions, sTemplate = ((udTransElementItem*)pTrans->GetUserData())->GetActionsString(); sTemplate.Replace(wxT(" "), wxT("")); while(node) { pTrans = (wxSFLineShape*)node->GetData(); pTransElement = (udTransElementItem*)pTrans->GetUserData(); sActions = pTransElement->GetActionsString(); sActions.Replace(wxT(" "), wxT("")); if( sActions == sTemplate ) { node = node->GetNext(); transitions.DeleteObject(pTrans); sublist.Append(pTrans); } else node = node->GetNext(); } }
void wxSFAutoLayout::Layout(wxSFDiagramManager& manager, const wxString& algname) { wxSFLayoutAlgorithm *pAlg = m_mapAlgorithms[ algname ]; if( pAlg ) { ShapeList lstShapes; manager.GetShapes( CLASSINFO(wxSFShapeBase), lstShapes ); // remove all child shapes ShapeList::compatibility_iterator it = lstShapes.GetFirst(); while( it ) { wxSFShapeBase *pShape = it->GetData(); if( pShape->GetParentShape() || pShape->IsKindOf(CLASSINFO(wxSFLineShape)) ) { lstShapes.DeleteNode( it ); it = lstShapes.GetFirst(); } else it = it->GetNext(); } pAlg->DoLayout( lstShapes ); manager.MoveShapesFromNegatives(); if( manager.GetShapeCanvas() ) UpdateCanvas( manager.GetShapeCanvas() ); } }
void wxSFShapeBase::ScaleChildren(double x, double y) { ShapeList m_lstChildren; GetChildShapes(sfANY, m_lstChildren, sfRECURSIVE); ShapeList::compatibility_iterator node = m_lstChildren.GetFirst(); while(node) { wxSFShapeBase* pShape = node->GetData(); if((pShape->GetStyle() & sfsSIZE_CHANGE) && !pShape->IsKindOf(CLASSINFO(wxSFTextShape))) { pShape->Scale(x, y, sfWITHOUTCHILDREN); } if( (pShape->GetStyle() & sfsPOSITION_CHANGE) && ((pShape->GetVAlign() == valignNONE) || (pShape->GetHAlign() == halignNONE)) ) { pShape->SetRelativePosition(pShape->m_nRelativePosition.x*x, pShape->m_nRelativePosition.y*y); } // re-align shapes which have set any alignment mode pShape->DoAlignment(); node = node->GetNext(); } }
void wxSFDiagramManager::RemoveShape(wxSFShapeBase* shape, bool refresh) { if(shape) { wxSFShapeBase *pParent = shape->GetParentShape(); // remove connected lines (to all children) ShapeList lstChildren; ShapeList lstConnections; ShapeList lstRemovedConnections; // get all shape's children shape->GetChildShapes(sfANY, lstChildren, sfRECURSIVE); lstChildren.Append(shape); // retrieve all assigned lines ShapeList::compatibility_iterator snode = lstChildren.GetFirst(); while(snode) { GetAssignedConnections(snode->GetData(), CLASSINFO(wxSFLineShape), wxSFShapeBase::lineBOTH, lstConnections); snode = snode->GetNext(); } // remove all assigne lines ShapeList::compatibility_iterator node = lstConnections.GetFirst(); while(node) { // one connection may be used by the parent and also by his child if(lstRemovedConnections.IndexOf(node->GetData()) == wxNOT_FOUND) { lstRemovedConnections.Append(node->GetData()); RemoveShape(node->GetData(), false); } node = node->GetNext(); } // remove the shape also from m_lstCurrentShapes list if( m_pShapeCanvas ) m_pShapeCanvas->RemoveFromTemporaries( shape ); // remove the shape RemoveItem(shape); if( pParent ) pParent->Update(); if( refresh && m_pShapeCanvas ) m_pShapeCanvas->Refresh(false); } }
void wxSFDiagramManager::MoveShapesFromNegatives() { wxSFShapeBase *pShape; wxRealPoint shapePos; double minx = 0, miny = 0; // find the maximal negative position value ShapeList shapes; GetShapes(CLASSINFO(wxSFShapeBase), shapes); ShapeList::compatibility_iterator node = shapes.GetFirst(); while(node) { shapePos = node->GetData()->GetAbsolutePosition(); if(node == shapes.GetFirst()) { minx = shapePos.x; miny = shapePos.y; } else { if(shapePos.x < minx)minx = shapePos.x; if(shapePos.y < miny)miny = shapePos.y; } node = node->GetNext(); } // move all parents shape so they (and their children) will be located in the positive values only if((minx < 0) || (miny < 0)) { node = shapes.GetFirst(); while(node) { pShape = node->GetData(); if(pShape->GetParentShape() == NULL) { if(minx < 0)pShape->MoveBy(abs((int)minx), 0); if(miny < 0)pShape->MoveBy(0, abs((int)miny)); } node = node->GetNext(); } } }
void wxSFMultiSelRect::OnTopHandle(wxSFShapeHandle& handle) { if(GetParentCanvas() && !AnyHeightExceeded(wxPoint(0, -handle.GetDelta().y))) { wxXS::RealPointList::compatibility_iterator ptnode; wxSFLineShape* pLine; wxRealPoint* pt; double dy, sy = (GetRectSize().y - 2*sfDEFAULT_ME_OFFSET - handle.GetDelta().y)/(GetRectSize().y - 2*sfDEFAULT_ME_OFFSET); ShapeList m_lstSelection; GetParentCanvas()->GetSelectedShapes(m_lstSelection); ShapeList::compatibility_iterator node = m_lstSelection.GetFirst(); while(node) { wxSFShapeBase* pShape = node->GetData(); if(!pShape->IsKindOf(CLASSINFO(wxSFLineShape))) { if(pShape->ContainsStyle(sfsPOSITION_CHANGE)) { if(pShape->GetParentShape()) { pShape->SetRelativePosition(pShape->GetRelativePosition().x, pShape->GetRelativePosition().y*sy); } else { double dy = handle.GetDelta().y - (pShape->GetAbsolutePosition().y - (GetAbsolutePosition().y + sfDEFAULT_ME_OFFSET))/(GetRectSize().y - 2*sfDEFAULT_ME_OFFSET)*handle.GetDelta().y; pShape->MoveBy(0, dy); } } if(pShape->ContainsStyle(sfsSIZE_CHANGE))pShape->Scale(1, sy, sfWITHCHILDREN); if( ! pShape->ContainsStyle( sfsNO_FIT_TO_CHILDREN ) ) pShape->FitToChildren(); } else { if(pShape->ContainsStyle(sfsPOSITION_CHANGE)) { pLine = (wxSFLineShape*)pShape; ptnode = pLine->GetControlPoints().GetFirst(); while(ptnode) { pt = ptnode->GetData(); dy = handle.GetDelta().y - (pt->y - (GetAbsolutePosition().y + sfDEFAULT_ME_OFFSET))/(GetRectSize().y - 2*sfDEFAULT_ME_OFFSET)*handle.GetDelta().y; pt->y += dy; pt->y = floor(pt->y); ptnode = ptnode->GetNext(); } } } node = node->GetNext(); } } }
void wxSFShapePasteEvent::SetPastedShapes(const ShapeList &list) { ShapeList::compatibility_iterator node = list.GetFirst(); while(node) { m_lstPastedShapes.Append(node->GetData()); node = node->GetNext(); } }
void udStateChartOptimizer::FindTransWithIdenticalTarget(ShapeList& transitions, ShapeList& sublist) { sublist.Clear(); ShapeList::compatibility_iterator node = transitions.GetFirst(); if( !node ) return; wxSFLineShape *pTrans = (wxSFLineShape*)node->GetData(); int nTrgId = pTrans->GetTrgShapeId(); while(node) { pTrans = (wxSFLineShape*)node->GetData(); if( pTrans->GetTrgShapeId() == nTrgId ) { node = node->GetNext(); transitions.DeleteObject(pTrans); sublist.Append(pTrans); } else node = node->GetNext(); } }
void wxSFDiagramManager::RemoveShapes(const ShapeList& selection) { wxSFShapeBase* pShape; ShapeList::compatibility_iterator node = selection.GetFirst(); while(node) { pShape = node->GetData(); // it is important to check whether double-linked shapes already exist before // they are deleted if(Contains(pShape))RemoveShape(pShape, false); node = node->GetNext(); } }
void udLoopCaseAlgorithm::ProcessState(wxSFShapeBase *state) { wxASSERT(state); if(!state)return; // check whether the state is already processed if( m_lstProcessedElements.IndexOf(state) != wxNOT_FOUND )return; wxSFDiagramManager *pDiagManager = state->GetShapeManager(); udLanguage *pLang = m_pParentGenerator->GetActiveLanguage(); pLang->SingleLineCommentCmd(wxT("State ID: ") + m_pParentGenerator->MakeIDName(state)); // find state neighbours ShapeList lstNeighbours; pDiagManager->GetNeighbours(state, lstNeighbours, CLASSINFO(umlTransitionItem), wxSFShapeBase::lineSTARTING, sfDIRECT); // find next processable state if( !lstNeighbours.IsEmpty() && ( m_lstProcessedElements.IndexOf(lstNeighbours.GetFirst()->GetData()) == wxNOT_FOUND ) ) { m_pNextElement = lstNeighbours.GetFirst()->GetData(); } else m_pNextElement = NULL; // process given element udElementProcessor *pProcessor = GetElementProcessor(state->GetClassInfo()->GetClassName()); if(pProcessor) { pProcessor->ProcessElement(state); } else { pLang->SingleLineCommentCmd(wxString::Format(wxT( "!!! WARNING: UNSUPPORTED ELEMENT ('%s') !!!"), ((udProjectItem*)state->GetUserData())->GetName().c_str())); IPluginManager::Get()->Log(wxString::Format(wxT("WARNING: '%s' element is not supported by this algorithm."), ((udProjectItem*)state->GetUserData())->GetName().c_str())); } // set the state as processes m_lstProcessedElements.Append(state); m_pPrevElement = state; // process connected states ShapeList::compatibility_iterator node = lstNeighbours.GetFirst(); while(node) { wxSFShapeBase *pNext = node->GetData(); ProcessState( pNext ); node = node->GetNext(); } }
void wxSFMultiSelRect::OnRightHandle(wxSFShapeHandle& handle) { if(GetParentCanvas() && !AnyWidthExceeded(handle.GetDelta())) { wxXS::RealPointList::compatibility_iterator ptnode; wxSFLineShape* pLine; wxRealPoint* pt; double dx, sx = (GetRectSize().x - 2*sfDEFAULT_ME_OFFSET + handle.GetDelta().x)/(GetRectSize().x - 2*sfDEFAULT_ME_OFFSET); ShapeList m_lstSelection; GetParentCanvas()->GetSelectedShapes(m_lstSelection); ShapeList::compatibility_iterator node = m_lstSelection.GetFirst(); while(node) { wxSFShapeBase* pShape = node->GetData(); // scale main parent shape if(!pShape->IsKindOf(CLASSINFO(wxSFLineShape))) { dx = (pShape->GetAbsolutePosition().x - (GetAbsolutePosition().x + sfDEFAULT_ME_OFFSET))/(GetRectSize().x - 2*sfDEFAULT_ME_OFFSET)*handle.GetDelta().x; if(pShape->ContainsStyle(sfsSIZE_CHANGE))pShape->Scale(sx, 1, sfWITHCHILDREN); if(pShape->ContainsStyle(sfsPOSITION_CHANGE))pShape->MoveBy(dx, 0); if( ! pShape->ContainsStyle( sfsNO_FIT_TO_CHILDREN ) ) pShape->FitToChildren(); } else { if(pShape->ContainsStyle(sfsPOSITION_CHANGE)) { pLine = (wxSFLineShape*)pShape; ptnode = pLine->GetControlPoints().GetFirst(); while(ptnode) { pt = ptnode->GetData(); dx = ( pt->x - (GetAbsolutePosition().x + sfDEFAULT_ME_OFFSET))/(GetRectSize().x - 2*sfDEFAULT_ME_OFFSET)*handle.GetDelta().x; pt->x += dx; pt->x = floor(pt->x); ptnode = ptnode->GetNext(); } } } node = node->GetNext(); } } }
void wxSFShapeBase::_OnDragging(const wxPoint& pos) { //wxASSERT(m_pParentManager); if( !m_pParentManager )return; if(m_fVisible && m_fActive && (m_nStyle & sfsPOSITION_CHANGE)) { if(m_fFirstMove) { m_nMouseOffset = wxRealPoint(pos.x, pos.y) - this->GetAbsolutePosition(); } // get shape BB BEFORE movement and combine it with BB of assigned lines wxRect prevBB; GetCompleteBoundingBox(prevBB, bbSELF | bbCONNECTIONS | bbCHILDREN | bbSHADOW); this->MoveTo(pos.x - m_nMouseOffset.x, pos.y - m_nMouseOffset.y); this->OnDragging(pos); // GUI controls in child control shapes must be updated explicitely wxSFControlShape *pCtrl; ShapeList lstChildCtrls; GetChildShapes( CLASSINFO(wxSFControlShape), lstChildCtrls, sfRECURSIVE ); ShapeList::compatibility_iterator node = lstChildCtrls.GetFirst(); while( node ) { pCtrl = (wxSFControlShape*) node->GetData(); pCtrl->UpdateControl(); node = node->GetNext(); } // get shape BB AFTER movement and combine it with BB of assigned lines wxRect currBB; GetCompleteBoundingBox(currBB, bbSELF | bbCONNECTIONS | bbCHILDREN | bbSHADOW); // update canvas Refresh( prevBB.Union(currBB), sfDELAYED ); m_fFirstMove = false; } if( GetParentShape() && (m_nStyle & sfsPROPAGATE_DRAGGING) ) { GetParentShape()->_OnDragging( pos ); } }
void wxSFDiagramManager::GetShapesAtPosition(const wxPoint& pos, ShapeList& shapes) { shapes.Clear(); wxSFShapeBase *pShape; ShapeList lstShapes; GetShapes(CLASSINFO(wxSFShapeBase), lstShapes); ShapeList::compatibility_iterator node = lstShapes.GetFirst(); while(node) { pShape = node->GetData(); if(pShape->IsVisible() && pShape->IsActive() && pShape->Contains(pos))shapes.Append(pShape); node = node->GetNext(); } }
void wxSFDiagramManager::GetShapesInside(const wxRect& rct, ShapeList& shapes) { shapes.Clear(); wxSFShapeBase* pShape; ShapeList lstShapes; GetShapes(CLASSINFO(wxSFShapeBase), lstShapes); ShapeList::compatibility_iterator node = lstShapes.GetFirst(); while(node) { pShape = node->GetData(); if(pShape->IsVisible() && pShape->IsActive() && pShape->Intersects(rct))shapes.Append(pShape); node = node->GetNext(); } }
void wxSFMultiSelRect::OnEndHandle(wxSFShapeHandle& handle) { // inform all selected shapes about end of the handle dragging if(GetParentCanvas()) { ShapeList lstShapes; GetParentCanvas()->GetSelectedShapes(lstShapes); ShapeList::compatibility_iterator node = lstShapes.GetFirst(); while(node) { node->GetData()->OnEndHandle(handle); node = node->GetNext(); } } }
void wxSFDiagramManager::UpdateAll() { wxSFShapeBase *pShape; ShapeList lstShapes; GetShapes( CLASSINFO(wxSFShapeBase), lstShapes ); ShapeList::compatibility_iterator node = lstShapes.GetFirst(); while( node ) { pShape = node->GetData(); // update only shapes withour children because the Update() function is called recursively on all parents if( !HasChildren( pShape ) ) pShape->Update(); node = node->GetNext(); } }
void wxSFDiagramManager::UpdateConnections() { if( !m_lstLinesForUpdate.IsEmpty() ) { wxSFLineShape* pLine; IDPair* pIDPair; // now check ids long oldSrcId, oldTrgId; long newSrcId, newTrgId; IDList::compatibility_iterator idnode; ShapeList::compatibility_iterator node = m_lstLinesForUpdate.GetFirst(); while(node) { pLine = (wxSFLineShape*)node->GetData(); newSrcId = oldSrcId = pLine->GetSrcShapeId(); newTrgId = oldTrgId = pLine->GetTrgShapeId(); idnode = m_lstIDPairs.GetFirst(); while(idnode) { pIDPair = idnode->GetData(); /*if(pIDPair->m_nNewID != pIDPair->m_nOldID) {*/ if(oldSrcId == pIDPair->m_nOldID) newSrcId = pIDPair->m_nNewID; if(oldTrgId == pIDPair->m_nOldID) newTrgId = pIDPair->m_nNewID; /*}*/ idnode = idnode->GetNext(); } pLine->SetSrcShapeId(newSrcId); pLine->SetTrgShapeId(newTrgId); // check whether line's src and trg shapes really exists if(!GetItem(pLine->GetSrcShapeId()) || !GetItem(pLine->GetTrgShapeId())) { RemoveItem(pLine); } node = node->GetNext(); } m_lstLinesForUpdate.Clear(); } }
wxString wxSFShapeDataObject::SerializeSelectedShapes(const ShapeList& selection, wxSFDiagramManager* manager) { // create root node wxSFShapeBase *pShape; wxXmlNode *root = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("chart")); // serialize copied shapes to XML node ShapeList::compatibility_iterator node = selection.GetFirst(); while(node) { pShape = node->GetData(); if(pShape) { // serialize parent's children manager->SerializeObjects(pShape, root, serINCLUDE_PARENTS); } node = node->GetNext(); } // create XML document in the memory stream wxMemoryOutputStream outstream; wxXmlDocument xmlDoc; xmlDoc.SetRoot(root); xmlDoc.Save(outstream); char *buffer = new char [outstream.GetSize()]; if(buffer) { memset(buffer, 0, outstream.GetSize()); outstream.CopyTo(buffer, outstream.GetSize()-1); wxString output(buffer, wxConvUTF8); delete [] buffer; return output; } else return wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?><chart />"); }
void wxSFDiagramManager::UpdateGrids() { if( !m_lstGridsForUpdate.IsEmpty() ) { // now check ids wxSFGridShape* pGrid; IDPair* pIDPair; int nIndex; IDList::compatibility_iterator idnode; ShapeList::compatibility_iterator node = m_lstGridsForUpdate.GetFirst(); while(node) { pGrid = (wxSFGridShape*)node->GetData(); nIndex = wxNOT_FOUND; idnode = m_lstIDPairs.GetFirst(); while(idnode) { pIDPair = idnode->GetData(); nIndex = pGrid->m_arrCells.Index( pIDPair->m_nOldID ); if( nIndex != wxNOT_FOUND ) pGrid->m_arrCells[ nIndex ] = pIDPair->m_nNewID; idnode = idnode->GetNext(); } // check whether grid's children really exists for( size_t i = 0; i < pGrid->m_arrCells.GetCount(); ) { if( !GetItem( pGrid->m_arrCells[i] ) ) pGrid->RemoveFromGrid( pGrid->m_arrCells[i] ); else i++; } node = node->GetNext(); } m_lstGridsForUpdate.Clear(); } }
bool wxSFShapeBase::AcceptCurrentlyDraggedShapes() { //wxASSERT(m_pParentManager); //wxASSERT(m_pParentManager->GetShapeCanvas()); if(!m_pParentManager || !GetShapeManager()->GetShapeCanvas())return false; if(!IsChildAccepted(wxT("All"))) { ShapeList lstSelection; GetShapeManager()->GetShapeCanvas()->GetSelectedShapes(lstSelection); ShapeList::compatibility_iterator node = lstSelection.GetFirst(); while(node) { if(m_arrAcceptedChildren.Index(node->GetData()->GetClassInfo()->GetClassName()) == wxNOT_FOUND)return false; node = node->GetNext(); } } return true; }
bool wxSFMultiSelRect::AnyHeightExceeded(const wxPoint& delta) { if(GetParentCanvas()) { wxSFShapeBase* pShape; ShapeList m_lstSelection; GetParentCanvas()->GetSelectedShapes(m_lstSelection); // first determine whether any shape in the selection exceeds its bounds ShapeList::compatibility_iterator node = m_lstSelection.GetFirst(); while(node) { pShape = node->GetData(); if(!pShape->IsKindOf(CLASSINFO(wxSFLineShape))) if((pShape->GetBoundingBox().GetHeight() + delta.y) <= 1)return true; node = node->GetNext(); } return false; } return true; }
//************************************************** bool wxSFBotLineShape::LineCanConnect(wxSFShapeBase* pShapeUnder) { ShapeList m_lstLines; if(!GetShapeManager()->GetShapes(CLASSINFO(wxSFBotLineShape), m_lstLines)) return true; wxSFShapeBase *pSrc = GetShapeManager()->FindShape(GetSrcShapeId()); wxSFShapeBase *pTrg = pShapeUnder; wxSFBotLineShape* pLine = (wxSFBotLineShape*)NULL; ShapeList::compatibility_iterator ciLine; //Если фигура источник, хочет присоедениться к фигуре источнику if(pSrc == pTrg) return false; //Если фигура источник - цикл, при этом соединяется с другой фигурой в составе цикла //то проверим что бы фигура с которой соединяемся была в составе фигуры источника if( pSrc->GetParentShape() ) { //if( pSrc->IsKindOf(CLASSINFO(wxSFCycle)) ) if( pTrg->GetParentShape() ) { if( pTrg->GetParent() != pSrc ) if( pSrc->GetParentShape() != pTrg->GetParentShape() ) return false; } else return false; } else if( pSrc->IsKindOf(CLASSINFO(wxSFCycle)) ) if( pTrg->GetParentShape() ) if( pSrc != pTrg->GetParentShape() ) return false; //Если фигура назначения в составе другой фигуры, то проверим что бы фигура контейнер была на том же уровне //что и фигура источник if( pTrg->GetParentShape() ) if( pSrc->GetParentShape() ) { if( pSrc->GetParentShape() != pTrg->GetParentShape() ) if( pSrc != pTrg->GetParentShape() ) return false; } else if( pSrc != pTrg->GetParentShape() ) return false; ciLine = m_lstLines.GetFirst(); while(ciLine) { pLine = (wxSFBotLineShape*)ciLine->GetData(); //Если фигура источник имеет тип - цикл, то может иметь 2 исходящих соединения, //все остальные фигуры только по одному if( pTrg->IsKindOf(CLASSINFO(wxSFCycle)) ) { if( (pLine != this) && (pLine->GetTrgShapeId() == pTrg->GetId()) ) return false; } else { //Если фигура источник имеет уже исходящие соединения, то соединять не будем if( (pLine != this) && //Удостоверимся что проверяем все линии кроме, той которой хотим соединить (pLine->GetTrgShapeId() == pTrg->GetId()) ) return false; } ciLine = ciLine->GetNext(); } long currentID = GetSrcShapeId(); long trgID = pShapeUnder->GetId(); bool broke = true; while(broke) { broke = false; ShapeList::compatibility_iterator node = m_lstLines.GetFirst(); while(node) { if(currentID == trgID) return false; pLine = (wxSFBotLineShape*)node->GetData(); if(pLine->GetTrgShapeId() == currentID) { if(pLine != this) { currentID = pLine->GetSrcShapeId(); broke = true; } } node = node->GetNext(); } } return true; }
void wxSFShapeBase::_GetNeighbours(ShapeList& neighbours, wxClassInfo *shapeInfo, CONNECTMODE condir, bool direct) { //wxASSERT(m_pParentManager); if( m_pParentManager ) { if( m_lstProcessed.IndexOf(this) != wxNOT_FOUND )return; ShapeList lstConnections; wxSFLineShape *pLine; wxSFShapeBase *pOposite = NULL; GetAssignedConnections(shapeInfo, condir, lstConnections); // find oposite shpes in direct branches ShapeList::compatibility_iterator node = lstConnections.GetFirst(); while(node) { pLine = (wxSFLineShape*)node->GetData(); switch(condir) { case lineSTARTING: pOposite = GetShapeManager()->FindShape(pLine->GetTrgShapeId()); break; case lineENDING: pOposite = GetShapeManager()->FindShape(pLine->GetSrcShapeId()); break; case lineBOTH: { if(GetId() == pLine->GetSrcShapeId())pOposite = GetShapeManager()->FindShape(pLine->GetTrgShapeId()); else pOposite = GetShapeManager()->FindShape(pLine->GetSrcShapeId()); } } // add oposite shape to the list (if applicable) if(pOposite && !pOposite->IsKindOf(CLASSINFO(wxSFLineShape)) && ( neighbours.IndexOf(pOposite) == wxNOT_FOUND )) neighbours.Append(pOposite); // find next shapes if( !direct && pOposite ) { // in the case of indirect branches we must differentiate between connections // and ordinary shapes m_lstProcessed.Append(this); if( pOposite->IsKindOf(CLASSINFO(wxSFLineShape)) ) { pLine = (wxSFLineShape*)pOposite; switch(condir) { case lineSTARTING: { pOposite = GetShapeManager()->FindShape( pLine->GetSrcShapeId() ); if( pOposite->IsKindOf(CLASSINFO(wxSFLineShape)) )pOposite->_GetNeighbours(neighbours, shapeInfo, condir, direct); else if( neighbours.IndexOf(pOposite) == wxNOT_FOUND )neighbours.Append(pOposite); } break; case lineENDING: { pOposite = GetShapeManager()->FindShape( pLine->GetTrgShapeId() ); if( pOposite->IsKindOf(CLASSINFO(wxSFLineShape)) )pOposite->_GetNeighbours(neighbours, shapeInfo, condir, direct); else if( neighbours.IndexOf(pOposite) == wxNOT_FOUND )neighbours.Append(pOposite); } break; case lineBOTH: { pOposite = GetShapeManager()->FindShape( pLine->GetSrcShapeId() ); if( pOposite->IsKindOf(CLASSINFO(wxSFLineShape)) )pOposite->_GetNeighbours(neighbours, shapeInfo, condir, direct); else if( neighbours.IndexOf(pOposite) == wxNOT_FOUND )neighbours.Append(pOposite); pOposite = GetShapeManager()->FindShape( pLine->GetTrgShapeId() ); if( pOposite->IsKindOf(CLASSINFO(wxSFLineShape)) )pOposite->_GetNeighbours(neighbours, shapeInfo, condir, direct); else if( neighbours.IndexOf(pOposite) == wxNOT_FOUND )neighbours.Append(pOposite); } break; } } else pLine->_GetNeighbours(neighbours, shapeInfo, condir, direct); } node = node->GetNext(); } } }
void udStateChartOptimizer::TrackBranch(wxSFShapeBase *state, wxSFLineShape *intrans, ShapeList *branch) { wxASSERT(state); if( !state ) return; wxSFDiagramManager *pManager = (wxSFDiagramManager*)state->GetParentManager(); wxASSERT(pManager); if( !pManager ) return; wxSFShapeBase *pSrcState; wxSFLineShape *pTrans; udTransElementItem *pTransElement; ShapeList lstST, lstET, lstST2; pManager->GetAssignedConnections(state, CLASSINFO(umlTransitionItem), wxSFShapeBase::lineSTARTING, lstST); pManager->GetAssignedConnections(state, CLASSINFO(umlTransitionItem), wxSFShapeBase::lineENDING, lstET); //if there are any ending transitions in the state then we can proceed to another step... if( intrans && lstET.GetFirst() && !udPROJECT::GetDiagramElement( state )->IsKindOf(CLASSINFO(udSubDiagramElementItem)) && !state->IsKindOf(CLASSINFO(umlCompStateItem))) { pTransElement = (udTransElementItem*)intrans->GetUserData(); // if the transition is conditionless then insert it into branch buffer if( pTransElement && !pTransElement->HasCondition() ) { lstST2.Clear(); // determine whether this transition is only one path from previous state pSrcState = pManager->FindShape(intrans->GetSrcShapeId()); pManager->GetAssignedConnections(pSrcState, CLASSINFO(umlTransitionItem), wxSFShapeBase::lineSTARTING, lstST2); if( lstST2.GetCount() == 1 ) { // if current branch list exists then use it, otherwise create new branch and append it to branches list if(branch) { branch->Append(state); } else { branch = new ShapeList; branch->Append(state); m_lstBranches.Append(branch); } if((lstST.GetCount()>1)||(lstET.GetCount()>1)||state->IsKindOf(CLASSINFO(umlHistoryItem)))branch = NULL; } else branch = NULL; } else { // this state is not part of direct branch so reset the current branch list branch = NULL; } } else { // this state is not part of direct branch so reset the current branch list branch = NULL; } // add state to 'processed' list if(m_lstProcessed.IndexOf(state)==wxNOT_FOUND) { m_lstProcessed.Append(state); // check next states ShapeList::compatibility_iterator node = lstST.GetFirst(); while(node) { pTrans = (wxSFLineShape*)node->GetData(); TrackBranch(pManager->FindShape(pTrans->GetTrgShapeId()), pTrans, branch); node = node->GetNext(); } } }
bool udStateChartOptimizer::InvertConditions(udDiagramItem *src) { bool fInverted = false; long nTmpId; ShapeList lstStates, lstTrans; umlTransitionItem *pFirstTrans, *pSecondTrans; udTransElementItem *pFirstTranElement, *pSecondTranElement; // get all (pseudo) states in the source diagram PaletteArray *pDiagramElements = m_mapElementPalettes[src->GetDiagramType()]; if( !pDiagramElements ) return false; for( size_t i = 0; i < pDiagramElements->GetCount(); i++ ) { if( pDiagramElements->Item(i).m_nType == udPaletteItem::pitELEMENT ) { src->GetDiagramManager().GetShapes(wxClassInfo::FindClass(pDiagramElements->Item(i).m_sClassName), lstStates); } } ShapeList::compatibility_iterator snode = lstStates.GetFirst(); while( snode ) { lstTrans.Clear(); src->GetDiagramManager().GetAssignedConnections(snode->GetData(), CLASSINFO(umlTransitionItem), wxSFShapeBase::lineSTARTING, lstTrans); // optimize only states with two outcomming transitions if( lstTrans.GetCount() == 2 ) { pFirstTrans = (umlTransitionItem*)lstTrans.Item(0)->GetData(); pFirstTranElement = (udTransElementItem*)pFirstTrans->GetUserData(); pSecondTrans = (umlTransitionItem*)lstTrans.Item(1)->GetData(); pSecondTranElement = (udTransElementItem*)pSecondTrans->GetUserData(); if( !pSecondTranElement->HasCondition() ) { if( pSecondTranElement->HasActions() && pFirstTranElement->HasCondition() && !pFirstTranElement->HasActions() ) { // create new condition udCodeItem *pCond = (udCodeItem*)pFirstTranElement->GetCondition( udfORIGINAL )->Clone(); pCond->SetInverted( true ); // clear previous condition and assign the new one pFirstTranElement->ClearCodeItems( CLASSINFO(udConditionItem) ); pFirstTranElement->ClearCodeItems( CLASSINFO(udEventItem) ); pFirstTranElement->AssignCodeItem( pCond ); // copy actions form second transition to the first pFirstTranElement->CopyActionItems( pSecondTranElement ); // clear actions in the second transition pSecondTranElement->ClearCodeItems( CLASSINFO(udActionItem) ); // swap targets nTmpId = pFirstTrans->GetTrgShapeId(); pFirstTrans->SetTrgShapeId(pSecondTrans->GetTrgShapeId()); pSecondTrans->SetTrgShapeId(nTmpId); fInverted = true; } } else if( !pFirstTranElement->HasCondition() ) { if( pFirstTranElement->HasActions() && pSecondTranElement->HasCondition() && !pSecondTranElement->HasActions() ) { // create new condition udCodeItem *pCond = (udCodeItem*)pSecondTranElement->GetCondition( udfORIGINAL )->Clone(); pCond->SetInverted( true ); // clear previous condition and assign the new one pSecondTranElement->ClearCodeItems( CLASSINFO(udConditionItem) ); pSecondTranElement->ClearCodeItems( CLASSINFO(udEventItem) ); pSecondTranElement->AssignCodeItem( pCond ); // copy actions form second transition to the first pSecondTranElement->CopyActionItems( pFirstTranElement ); // clear actions in the second transition pFirstTranElement->ClearCodeItems( CLASSINFO(udActionItem) ); // swap targets nTmpId = pSecondTrans->GetTrgShapeId(); pSecondTrans->SetTrgShapeId(pFirstTrans->GetTrgShapeId()); pFirstTrans->SetTrgShapeId(nTmpId); fInverted = true; } } } snode = snode->GetNext(); } return fInverted; }
void wxSFShapeBase::_GetCompleteBoundingBox(wxRect &rct, int mask) { //wxASSERT(m_pParentManager); if(!m_pParentManager)return; if( m_lstProcessed.IndexOf(this) != wxNOT_FOUND )return; else m_lstProcessed.Append(this); ShapeList lstChildren; //SerializableList lstConnections; // firts, get bounding box of the current shape if(mask & bbSELF) { if(rct.IsEmpty())rct = this->GetBoundingBox().Inflate( abs(m_nHBorder), abs(m_nVBorder) ); else rct.Union(this->GetBoundingBox().Inflate( abs(m_nHBorder), abs(m_nVBorder)) ); // add also shadow offset if neccessary if( (mask & bbSHADOW) && (m_nStyle & sfsSHOW_SHADOW) && GetParentCanvas() ) { wxRealPoint nOffset = GetParentCanvas()->GetShadowOffset(); if( nOffset.x < 0 ) { rct.SetX(rct.GetX() + (int)nOffset.x); rct.SetWidth(rct.GetWidth() - (int)nOffset.x); } else rct.SetWidth(rct.GetWidth() + (int)nOffset.x); if( nOffset.y < 0 ) { rct.SetY(rct.GetY() + (int)nOffset.y); rct.SetHeight(rct.GetHeight() - (int)nOffset.y); } else rct.SetHeight(rct.GetHeight() + (int)nOffset.y);; } } else mask |= bbSELF; // get list of all connection lines assigned to the shape and find their child shapes if(mask & bbCONNECTIONS) { wxSFShapeBase *pLine; ShapeList lstLines; GetAssignedConnections( CLASSINFO(wxSFLineShape), lineBOTH, lstLines ); ShapeList::compatibility_iterator node = lstLines.GetFirst(); while(node) { pLine = node->GetData(); //rct.Union(pLine->GetBoundingBox()); lstChildren.Append(pLine); // get children of the connections pLine->GetChildShapes(sfANY, lstChildren); node = node->GetNext(); } } // get children of this shape if(mask & bbCHILDREN) { this->GetChildShapes(sfANY, lstChildren, sfNORECURSIVE); // now, call this function for all children recursively... ShapeList::compatibility_iterator node = lstChildren.GetFirst(); while(node) { node->GetData()->_GetCompleteBoundingBox(rct, mask); node = node->GetNext(); } } }
bool udStateChartOptimizer::MergeDirectBranches(udDiagramItem *src) { bool fMerged = false; wxString sNewAction; m_lstProcessed.Clear(); m_lstBranches.Clear(); // find all direct diagram branches ShapeList *pBranch, lstST, lstET; ShapeList lstInitialStates; src->GetDiagramManager().GetShapes(CLASSINFO(umlInitialItem), lstInitialStates); src->GetDiagramManager().GetShapes(CLASSINFO(umlEntryItem), lstInitialStates); src->GetDiagramManager().GetShapes(CLASSINFO(umlHistoryItem), lstInitialStates); ShapeList::compatibility_iterator node = lstInitialStates.GetFirst(); while( node ) { TrackBranch(node->GetData(), NULL, NULL); node = node->GetNext(); } if( m_lstBranches.GetFirst() ) { wxSFShapeBase *pFirst, *pLast, *pState; wxSFLineShape *pUpdatedTransition, *pTrans; udTransElementItem *pUpdTransElement, *pTransElement; // process all branches containing more than one state BranchList::compatibility_iterator bnode = m_lstBranches.GetFirst(); while( bnode ) { pBranch = bnode->GetData(); if( pBranch->GetCount() > 1 ) { pFirst = pBranch->GetFirst()->GetData(); pLast = pBranch->GetLast()->GetData(); // get previous state of the first state lstET.Clear(); src->GetDiagramManager().GetAssignedConnections(pFirst, CLASSINFO(umlTransitionItem), wxSFShapeBase::lineENDING, lstET); pUpdatedTransition = (wxSFLineShape*)lstET.GetFirst()->GetData(); pUpdTransElement = (udTransElementItem*)pUpdatedTransition->GetUserData(); // reconnect updated transition pUpdatedTransition->SetTrgShapeId(pLast->GetId()); ShapeList::compatibility_iterator snode = pBranch->GetFirst(); while( snode && (snode != pBranch->GetLast()) ) { pState = snode->GetData(); // get outcomming transition lstST.Clear(); src->GetDiagramManager().GetAssignedConnections(pState, CLASSINFO(umlTransitionItem), wxSFShapeBase::lineSTARTING, lstST); pTrans = (wxSFLineShape*)lstST.GetFirst()->GetData(); // get action list from the transition pTransElement = (udTransElementItem*)pTrans->GetUserData(); if( pTransElement->HasActions() ) { if( !pUpdTransElement->HasActions() ) { //pUpdTransElement->SetActionString(pTransElement->GetActionsString()); pUpdTransElement->ClearCodeItems( CLASSINFO(udActionItem) ); pUpdTransElement->CopyActionItems( pTransElement ); } else //pUpdTransElement->SetActionString(pUpdTransElement->GetActionsString() + wxT(", ") + pTransElement->GetActionsString()); pUpdTransElement->CopyActionItems( pTransElement ); } // remove ununsed states and transition from automaton src->GetDiagramManager().RemoveShape(pState); fMerged = true; snode = snode->GetNext(); } } bnode = bnode->GetNext(); } } // clean up m_lstProcessed.Clear(); m_lstBranches.DeleteContents(true); m_lstBranches.Clear(); m_lstBranches.DeleteContents(false); return fMerged; }
wxSFShapeBase* wxSFDiagramManager::GetShapeAtPosition(const wxPoint& pos, int zorder, SEARCHMODE mode) { int nCounter = 0; ShapeList m_lstSortedShapes; wxSFShapeBase* pShape; // sort shapes list in the way that the line shapes will be at the top of the list ShapeList shapes; GetShapes(CLASSINFO(wxSFShapeBase), shapes, xsSerializable::searchBFS); ShapeList::compatibility_iterator node = shapes.GetFirst(); while(node) { pShape = node->GetData(); if(pShape->IsKindOf(CLASSINFO(wxSFLineShape))) { m_lstSortedShapes.Insert(pShape); nCounter++; } else m_lstSortedShapes.Insert(nCounter, pShape); node = node->GetNext(); } // find the topmost shape according to the given rules nCounter = 1; node = m_lstSortedShapes.GetFirst(); while(node) { pShape = (wxSFShapeBase*)node->GetData(); if(pShape->IsVisible() && pShape->IsActive() && pShape->Contains(pos)) { switch(mode) { case searchSELECTED: if(pShape->IsSelected()) { if(nCounter == zorder)return pShape; else nCounter++; } break; case searchUNSELECTED: if(!pShape->IsSelected()) { if(nCounter == zorder)return pShape; else nCounter++; } break; case searchBOTH: if(nCounter == zorder)return pShape; else nCounter++; break; } } node = node->GetNext(); } return NULL; }
wxSFShapeBase* wxSFDiagramManager::AddShape(wxSFShapeBase* shape, xsSerializable* parent, const wxPoint& pos, bool initialize, bool saveState, wxSF::ERRCODE *err) { if(shape) { if( shape->IsKindOf(CLASSINFO(wxSFShapeBase)) && IsShapeAccepted(shape->GetClassInfo()->GetClassName()) ) { if( m_pShapeCanvas ) { wxPoint newPos = m_pShapeCanvas->FitPositionToGrid(m_pShapeCanvas->DP2LP(pos)); shape->SetRelativePosition( Conv2RealPoint(newPos) ); } else shape->SetRelativePosition( Conv2RealPoint(pos) ); // add parent shape to the data manager (serializer) if(parent) { AddItem(parent, shape); } else AddItem(GetRootItem(), shape); // initialize added shape if(initialize) { shape->CreateHandles(); if( m_pShapeCanvas ) { shape->SetHoverColour(m_pShapeCanvas->GetHoverColour()); } if(HasChildren(shape)) { wxSFShapeBase* pChild; ShapeList lstChildren; // get shape's children (if exist) shape->GetChildShapes(sfANY, lstChildren, sfRECURSIVE); // initialize shape's children ShapeList::compatibility_iterator node = lstChildren.GetFirst(); while(node) { pChild = (wxSFShapeBase*)node->GetData(); pChild->CreateHandles(); pChild->Update(); if( m_pShapeCanvas ) { pChild->SetHoverColour(m_pShapeCanvas->GetHoverColour()); } node = node->GetNext(); } } } // reset scale of assigned shape canvas (if exists and it is necessary...) if( m_pShapeCanvas && shape->IsKindOf( CLASSINFO(wxSFControlShape) ) ) { m_pShapeCanvas->SetScale( 1 ); } if( m_pShapeCanvas ) { if( saveState ) { m_pShapeCanvas->SaveCanvasState(); } } if( err ) *err = wxSF::errOK; } else { //wxMessageBox(wxString::Format(wxT("Unable to add '%s' class object to the canvas"), shape->GetClassInfo()->GetClassName()), wxT("ShapeFramework"), wxICON_WARNING); delete shape; shape = NULL; if( err ) *err = wxSF::errNOT_ACCEPTED; } } else if( err ) *err = wxSF::errINVALID_INPUT; return shape; }
bool udStateChartOptimizer::MergeTransitions(udDiagramItem *src) { bool fFirstRun, fConditionLess, fMerged = false; int nIndex; wxString sNewCondition;//, sCondString; //udCodeItem *pCondition; udConditionItem *pNewCond; wxSFShapeBase *pState; wxSFLineShape *pTrans; udTransElementItem *pLineElement; ShapeList lstStates, lstTransitions, lstSubTrans, lstSubActs; udLanguage *pLang = m_pGenerator->GetActiveLanguage(); // get all (pseudo) states in the source diagram PaletteArray *pDiagramElements = m_mapElementPalettes[src->GetDiagramType()]; if( !pDiagramElements ) return false; for( size_t i = 0; i < pDiagramElements->GetCount(); i++ ) { if( pDiagramElements->Item(i).m_nType == udPaletteItem::pitELEMENT ) { src->GetDiagramManager().GetShapes(wxClassInfo::FindClass(pDiagramElements->Item(i).m_sClassName), lstStates); } } ShapeList::compatibility_iterator snode = lstStates.GetFirst(); while(snode) { pState = snode->GetData(); // get all transitions starting in this state src->GetDiagramManager().GetAssignedConnections(pState, CLASSINFO(umlTransitionItem), wxSFShapeBase::lineSTARTING, lstTransitions); while( lstTransitions.GetFirst() ) { // get subsets with identical targets FindTransWithIdenticalTarget(lstTransitions, lstSubTrans); if( lstSubTrans.GetCount() > 1 ) { nIndex = 1; while( lstSubTrans.GetFirst() ) { // get subsets with actions FindTransWithIdenticalActions(lstSubTrans, lstSubActs); if( lstSubActs.GetCount() > 1 ) { // create combined action fFirstRun = true; fConditionLess = false; sNewCondition = wxT(""); ShapeList::compatibility_iterator anode = lstSubActs.GetFirst(); while( anode ) { pTrans = (wxSFLineShape*)anode->GetData(); pLineElement = (udTransElementItem*)pTrans->GetUserData(); //pCondition = ((udTransElementItem*)pTrans->GetUserData())->GetCondition(); //sCondString = ((udTransElementItem*)pTrans->GetUserData())->GetConditionString( pLang ); if( !pLineElement->HasCondition() ) { sNewCondition = wxT(""); fConditionLess = true; } if( fFirstRun ) { if( !fConditionLess )sNewCondition << wxT("( ") << pLineElement->GetConditionAsString( udCodeItem::cfCALL, pLang ); //pCondition->ToString( udCodeItem::cfCALL, pLang ); fFirstRun = false; } else { if( !fConditionLess )sNewCondition << wxT(" ) ") << pLang->Or() << wxT(" ( ") << pLineElement->GetConditionAsString( udCodeItem::cfCALL, pLang );//pCondition->ToString( udCodeItem::cfCALL, pLang ); // remove partial transition src->GetDiagramManager().RemoveShape(pTrans, false); } anode = anode->GetNext(); } if( !fConditionLess )sNewCondition << wxT(" )"); pLineElement = (udTransElementItem*)lstSubActs.GetFirst()->GetData()->GetUserData(); // create new guard string //pLineElement->SetConditionString(sNewCondition); pNewCond = new udConditionItem(); pNewCond->SetInline( true ); pNewCond->SetCode( sNewCondition ); // clear previous condition pLineElement->ClearCodeItems( CLASSINFO(udConditionItem) ); pLineElement->ClearCodeItems( CLASSINFO(udEventItem) ); // set new condition pLineElement->AssignCodeItem( pNewCond ); pLineElement->SetName(wxString::Format(wxT("Optimized transition %d"), nIndex)); nIndex++; fMerged = true; } } } } snode = snode->GetNext(); } return fMerged; }