Exemple #1
0
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 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();
	}
}
Exemple #3
0
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();
	}
}
Exemple #4
0
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();
		}
	}
}
Exemple #5
0
void wxSFShapePasteEvent::SetPastedShapes(const ShapeList &list)
{
	ShapeList::compatibility_iterator node = list.GetFirst();
	while(node)
	{
		m_lstPastedShapes.Append(node->GetData());
		node = node->GetNext();
	}
}
Exemple #6
0
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();
    }
}
Exemple #8
0
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();
		}
	}
}
Exemple #9
0
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 );
	}
}
Exemple #10
0
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();
	}
}
Exemple #11
0
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();
	}
}
Exemple #12
0
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();
	}
}
Exemple #13
0
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();
		}
	}
}
Exemple #14
0
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();
		}
	}
}
Exemple #15
0
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 />");
}
Exemple #17
0
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();	
    }
}
Exemple #18
0
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;
}
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();
	}
}
Exemple #20
0
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;
}
Exemple #21
0
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);
	}
}
Exemple #22
0
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();
        }
    }
}
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;
}
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;
}
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;
}
Exemple #27
0
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;
}
Exemple #28
0
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();
		}
	}
}
Exemple #29
0
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;
}
Exemple #30
0
//**************************************************
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;
}