/************************************/ /* Delete.cpp: routines d'effacement */ /************************************/ #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "program.h" #include "libcmp.h" #include "general.h" #include "protos.h" /********************************************************************************/ static int CountConnectedItems( WinEDA_SchematicFrame* frame, SCH_ITEM* ListStruct, wxPoint pos, bool TstJunction ) /********************************************************************************/ /* Count number of items connected to point pos : * pins, end wire or bus, and junctions if TstJunction == TRUE * Return this count * * Used by WinEDA_SchematicFrame::DeleteConnection() */ { SCH_ITEM* Struct; int count = 0; if( frame->LocatePinEnd( ListStruct, pos ) ) count++; for( Struct = ListStruct; Struct != NULL; Struct = Struct->Next() ) { if( Struct->m_Flags & STRUCT_DELETED ) continue; if( Struct->m_Flags & SKIP_STRUCT ) continue; if( TstJunction && (Struct->Type() == DRAW_JUNCTION_STRUCT_TYPE) ) { #define JUNCTION ( (DrawJunctionStruct*) Struct ) if( (JUNCTION->m_Pos.x == pos.x) && (JUNCTION->m_Pos.y == pos.y) ) count++; #undef JUNCTION } if( Struct->Type() != DRAW_SEGMENT_STRUCT_TYPE ) continue; #define SEGM ( (EDA_DrawLineStruct*) Struct ) if( SEGM->IsOneEndPointAt( pos ) ) count++; #undef SEGM } return count; } /************************************************************************************/ static bool MarkConnected( WinEDA_SchematicFrame* frame, SCH_ITEM* ListStruct, EDA_DrawLineStruct* segment ) /************************************************************************************/ /* Mark to "CANDIDATE" all wires or junction connected to "segment" in list "ListStruct" * Search wire stop at an any pin * * Used by WinEDA_SchematicFrame::DeleteConnection() */ { EDA_BaseStruct* Struct; for( Struct = ListStruct; Struct != NULL; Struct = Struct->Next() ) { if( Struct->m_Flags ) continue; if( Struct->Type() == DRAW_JUNCTION_STRUCT_TYPE ) { #define JUNCTION ( (DrawJunctionStruct*) Struct ) if( segment->IsOneEndPointAt( JUNCTION->m_Pos ) ) Struct->m_Flags |= CANDIDATE; continue; #undef JUNCTION } if( Struct->Type() != DRAW_SEGMENT_STRUCT_TYPE ) continue; #define SEGM ( (EDA_DrawLineStruct*) Struct ) if( segment->IsOneEndPointAt( SEGM->m_Start ) ) { if( !frame->LocatePinEnd( ListStruct, SEGM->m_Start ) ) { Struct->m_Flags |= CANDIDATE; MarkConnected( frame, ListStruct, SEGM ); } } if( segment->IsOneEndPointAt( SEGM->m_End ) ) { if( !frame->LocatePinEnd( ListStruct, SEGM->m_End ) ) { Struct->m_Flags |= CANDIDATE; MarkConnected( frame, ListStruct, SEGM ); } } #undef SEGM } return TRUE; } /********************************************************************************/ void WinEDA_SchematicFrame::DeleteConnection( wxDC* DC, bool DeleteFullConnection ) /********************************************************************************/ /* Delete a connection, i.e wires or bus connected * stop on a node (more than 2 wires (bus) connected) */ { wxPoint refpos = GetScreen()->m_Curseur; SCH_ITEM* DelStruct; DrawPickedStruct* PickedItem, * PickedList = NULL; /* Clear .m_Flags member for all items */ for( DelStruct = GetScreen()->EEDrawList; DelStruct != NULL; DelStruct = DelStruct->Next() ) DelStruct->m_Flags = 0; BreakSegmentOnJunction( (SCH_SCREEN*) GetScreen() ); DelStruct = GetScreen()->EEDrawList; /* Locate all the wires, bus or junction under the mouse cursor, and put them in a list * of items to delete */ SCH_SCREEN* screen = (SCH_SCREEN*) GetScreen(); SCH_ITEM* savedEEDrawList = screen->EEDrawList; while( DelStruct && ( DelStruct = PickStruct( screen->m_Curseur, screen, JUNCTIONITEM | WIREITEM | BUSITEM ) ) != NULL ) { DelStruct->m_Flags = SELECTEDNODE | STRUCT_DELETED; /* Put this structure in the picked list: */ PickedItem = new DrawPickedStruct( DelStruct ); PickedItem->Pnext = PickedList; PickedList = PickedItem; DelStruct = DelStruct->Next(); screen->EEDrawList = DelStruct; } GetScreen()->EEDrawList = savedEEDrawList; /* Mark all wires, junctions, .. connected to one of the item to delete */ if( DeleteFullConnection ) { for( DelStruct = GetScreen()->EEDrawList; DelStruct != NULL; DelStruct = DelStruct->Next() ) { if( !(DelStruct->m_Flags & SELECTEDNODE) ) continue; #define SEGM ( (EDA_DrawLineStruct*) DelStruct ) if( DelStruct->Type() != DRAW_SEGMENT_STRUCT_TYPE ) continue; MarkConnected( this, GetScreen()->EEDrawList, SEGM ); #undef SEGM } // Search all removable wires (i.e wire with one new dangling end ) for( DelStruct = GetScreen()->EEDrawList; DelStruct != NULL; DelStruct = DelStruct->Next() ) { bool noconnect = FALSE; if( DelStruct->m_Flags & STRUCT_DELETED ) continue; // Already seen if( !(DelStruct->m_Flags & CANDIDATE) ) continue; // Already seen if( DelStruct->Type() != DRAW_SEGMENT_STRUCT_TYPE ) continue; DelStruct->m_Flags |= SKIP_STRUCT; #define SEGM ( (EDA_DrawLineStruct*) DelStruct ) /* Test the SEGM->m_Start point: if this point was connected to an STRUCT_DELETED wire, * and now is not connected, the wire can be deleted */ EDA_BaseStruct* removed_struct; for( removed_struct = GetScreen()->EEDrawList; removed_struct != NULL; removed_struct = removed_struct->Pnext ) { if( (removed_struct->m_Flags & STRUCT_DELETED) == 0 ) continue; if( removed_struct->Type() != DRAW_SEGMENT_STRUCT_TYPE ) continue; #define WIRE ( (EDA_DrawLineStruct*) removed_struct ) if( WIRE->IsOneEndPointAt( SEGM->m_Start ) ) break; } if( WIRE && !CountConnectedItems( this, GetScreen()->EEDrawList, SEGM->m_Start, TRUE ) ) noconnect = TRUE; /* Test the SEGM->m_End point: if this point was connected to an STRUCT_DELETED wire, * and now is not connected, the wire can be deleted */ for( removed_struct = GetScreen()->EEDrawList; removed_struct != NULL; removed_struct = removed_struct->Pnext ) { if( (removed_struct->m_Flags & STRUCT_DELETED) == 0 ) continue; if( removed_struct->Type() != DRAW_SEGMENT_STRUCT_TYPE ) continue; if( WIRE->IsOneEndPointAt( SEGM->m_End ) ) break; } if( removed_struct && !CountConnectedItems( this, GetScreen()->EEDrawList, SEGM->m_End, TRUE ) ) noconnect = TRUE; DelStruct->m_Flags &= ~SKIP_STRUCT; if( noconnect ) { DelStruct->m_Flags |= STRUCT_DELETED; /* Put this structure in the picked list: */ PickedItem = new DrawPickedStruct( DelStruct ); PickedItem->Pnext = PickedList; PickedList = PickedItem; DelStruct = GetScreen()->EEDrawList; } #undef SEGM } // Delete redundant junctions (junctions which connect < 3 end wires and no pin are removed) for( DelStruct = GetScreen()->EEDrawList; DelStruct != NULL; DelStruct = DelStruct->Next() ) { int count; if( DelStruct->m_Flags & STRUCT_DELETED ) continue; if( !(DelStruct->m_Flags & CANDIDATE) ) continue; if( DelStruct->Type() == DRAW_JUNCTION_STRUCT_TYPE ) { #define JUNCTION ( (DrawJunctionStruct*) DelStruct ) count = CountConnectedItems( this, GetScreen()->EEDrawList, JUNCTION->m_Pos, FALSE ); if( count <= 2 ) { DelStruct->m_Flags |= STRUCT_DELETED; /* Put this structure in the picked list: */ PickedItem = new DrawPickedStruct( DelStruct ); PickedItem->Pnext = PickedList; PickedList = PickedItem; } #undef JUNCTION } } // Delete labels attached to wires wxPoint pos = GetScreen()->m_Curseur; for( DelStruct = GetScreen()->EEDrawList; DelStruct != NULL; DelStruct = DelStruct->Next() ) { if( DelStruct->m_Flags & STRUCT_DELETED ) continue; if( DelStruct->Type() != TYPE_SCH_LABEL ) continue; GetScreen()->m_Curseur = ( (SCH_TEXT*) DelStruct )->m_Pos; EDA_BaseStruct* TstStruct = PickStruct( GetScreen()->m_Curseur, GetScreen(), WIREITEM | BUSITEM ); if( TstStruct && TstStruct->m_Flags & STRUCT_DELETED ) { DelStruct->m_Flags |= STRUCT_DELETED; /* Put this structure in the picked list: */ PickedItem = new DrawPickedStruct( DelStruct ); PickedItem->Pnext = PickedList; PickedList = PickedItem; } } GetScreen()->m_Curseur = pos; } for( DelStruct = GetScreen()->EEDrawList; DelStruct != NULL; DelStruct = DelStruct->Next() ) DelStruct->m_Flags = 0; if( PickedList ) { DeleteStruct( DrawPanel, DC, PickedList ); GetScreen()->SetModify(); } } /*****************************************************************/ bool LocateAndDeleteItem( WinEDA_SchematicFrame* frame, wxDC* DC ) /*****************************************************************/ /* Locate and delete the item found under the mouse cousor * If more than one item found: the priority order is: * 1 : MARKER * 2 : JUNCTION * 2 : NOCONNECT * 3 : WIRE ou BUS * 4 : DRAWITEM * 5 : TEXT * 6 : COMPOSANT * 7 : SHEET * * return TRUE if an item was deleted */ { SCH_ITEM* DelStruct; SCH_SCREEN* screen = (SCH_SCREEN*) ( frame->GetScreen() ); bool item_deleted = FALSE; DelStruct = PickStruct( screen->m_Curseur, screen, MARKERITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, JUNCTIONITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, NOCONNECTITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, RACCORDITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, WIREITEM | BUSITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, DRAWITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, TEXTITEM | LABELITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, LIBITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, SHEETITEM ); if( DelStruct ) { g_ItemToRepeat = NULL; DeleteStruct( frame->DrawPanel, DC, DelStruct ); frame->TestDanglingEnds( frame->GetScreen()->EEDrawList, DC ); frame->GetScreen()->SetModify(); item_deleted = TRUE; } return item_deleted; } /***************************************************************/ void EraseStruct( SCH_ITEM* DrawStruct, SCH_SCREEN* Screen ) /***************************************************************/ /* Suppression definitive d'une structure dans une liste chainee * d'elements de dessin * DrawStruct = pointeur sur la structure * Screen = pointeur sur l'ecran d'appartenance * Le chainage de la liste est modifie. * * Remarque: * pour les structures DRAW_SHEET_STRUCT_TYPE, l'ecran et les structures * correspondantes ne sont pas touches. * Ils doivent etre traites separement */ { EDA_BaseStruct* DrawList; DrawPickedStruct* PickedList = NULL; Hierarchical_PIN_Sheet_Struct* SheetLabel, * NextLabel; if( DrawStruct == NULL ) return; if( Screen == NULL ) return; Screen->SetModify(); if( DrawStruct->Type() == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE ) { /* Cette stucture est rattachee a une feuille, et n'est pas * accessible par la liste globale directement */ //this structure has a sheet attached, which we must find. DrawList = Screen->EEDrawList; for( ; DrawList != NULL; DrawList = DrawList->Pnext ) { if( DrawList->Type() != DRAW_SHEET_STRUCT_TYPE ) continue; /* Examen de la Sheet */ SheetLabel = ( (DrawSheetStruct*) DrawList )->m_Label; if( SheetLabel == NULL ) continue; if( SheetLabel == (Hierarchical_PIN_Sheet_Struct*) DrawStruct ) { ( (DrawSheetStruct*) DrawList )->m_Label = (Hierarchical_PIN_Sheet_Struct*) SheetLabel->Pnext; SAFE_DELETE( DrawStruct ); return; } else { while( SheetLabel->Pnext ) /* Examen de la liste dependante */ { NextLabel = (Hierarchical_PIN_Sheet_Struct*) SheetLabel->Pnext; if( NextLabel == (Hierarchical_PIN_Sheet_Struct*) DrawStruct ) { SheetLabel->Pnext = (EDA_BaseStruct*) NextLabel->Pnext; SAFE_DELETE( DrawStruct ); return; } SheetLabel = NextLabel; } } } return; } if( DrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE ) { PickedList = (DrawPickedStruct*) DrawStruct; while( PickedList ) { if( PickedList->m_PickedStruct == Screen->EEDrawList ) { Screen->EEDrawList = Screen->EEDrawList->Next(); SAFE_DELETE( DrawStruct ); } else { DrawList = Screen->EEDrawList; while( DrawList && DrawList->Pnext ) { if( DrawList->Pnext == PickedList->m_PickedStruct ) { DrawList->Pnext = DrawList->Pnext->Pnext; SAFE_DELETE( DrawStruct ); return; } DrawList = DrawList->Pnext; } } PickedList = (DrawPickedStruct*) PickedList->Pnext; } } else // structure usuelle */ { if( DrawStruct == Screen->EEDrawList ) { Screen->EEDrawList = DrawStruct->Next(); SAFE_DELETE( DrawStruct ); } else { DrawList = Screen->EEDrawList; while( DrawList && DrawList->Pnext ) { if( DrawList->Pnext == DrawStruct ) { DrawList->Pnext = DrawStruct->Pnext; SAFE_DELETE( DrawStruct ); return; } DrawList = DrawList->Pnext; } } } } /********************************/ void DeleteAllMarkers( int type ) /********************************/ /* Effacement des marqueurs du type "type" */ { SCH_SCREEN* screen; SCH_ITEM * DrawStruct, * NextStruct; DrawMarkerStruct* Marker; EDA_ScreenList ScreenList; for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() ) { for( DrawStruct = screen->EEDrawList; DrawStruct != NULL; DrawStruct = NextStruct ) { NextStruct = DrawStruct->Next(); if( DrawStruct->Type() != DRAW_MARKER_STRUCT_TYPE ) continue; /* Marqueur trouve */ Marker = (DrawMarkerStruct*) DrawStruct; if( Marker->m_Type != type ) continue; /* Suppression du marqueur */ EraseStruct( DrawStruct, screen ); } } } /********************************************************************/ void DeleteOneLibraryDrawStruct( WinEDA_DrawPanel* panel, wxDC* DC, EDA_LibComponentStruct* LibEntry, LibEDA_BaseStruct* DrawItem, int Affiche ) /********************************************************************/ /* Routine d'effacement d'un "LibraryDrawStruct" * (d'un element de dessin d'un composant ) * * Parametres d'entree * Pointeur sur le composant comportant la structure * (Si NULL la structure a effacer est supposee non rattachee * a un composant) * Pointeur sur la structure a effacer * * Efface egalement le graphique correspondant de l'ecran */ { LibEDA_BaseStruct* PreviousDrawItem; /* Effacement du graphique */ if( Affiche && DC ) DrawLibraryDrawStruct( panel, DC, LibEntry, wxPoint(0, 0), DrawItem, g_XorMode ); /* Effacement de la structure en memoire */ if( LibEntry ) /* Recherche du predecesseur */ { PreviousDrawItem = LibEntry->m_Drawings; /* Cas du 1er symbole graphique = struct a supprimer */ if( LibEntry->m_Drawings == DrawItem ) { LibEntry->m_Drawings = DrawItem->Next(); SAFE_DELETE( DrawItem ); } else /* Cas des autres items */ { while( PreviousDrawItem ) { if( PreviousDrawItem->Pnext == DrawItem ) { PreviousDrawItem->Pnext = DrawItem->Pnext; SAFE_DELETE( DrawItem ); break; } PreviousDrawItem = PreviousDrawItem->Next(); } } } else /* Structure non reliee a un composant */ { SAFE_DELETE( DrawItem ); } }