/************************************/ /* 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, EDA_BaseStruct * 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() */ { EDA_BaseStruct * Struct; int count = 0; if ( frame->LocatePinEnd(ListStruct, pos) ) count++; for ( Struct = ListStruct; Struct != NULL; Struct = Struct->Pnext) { 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, EDA_BaseStruct * 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->Pnext) { 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; EDA_BaseStruct * DelStruct ; DrawPickedStruct * PickedItem, *PickedList = NULL; /* Clear .m_Flags member for all items */ for(DelStruct = GetScreen()->EEDrawList; DelStruct != NULL; DelStruct=DelStruct->Pnext) DelStruct->m_Flags = 0; BreakSegmentOnJunction( 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 */ while ( DelStruct && (DelStruct = PickStruct(GetScreen()->m_Curseur, DelStruct, 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->Pnext; } /* Mark all wires, junctions, .. connected to one of the item to delete */ if ( DeleteFullConnection ) { for ( DelStruct = GetScreen()->EEDrawList; DelStruct != NULL; DelStruct = DelStruct->Pnext) { 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->Pnext) { 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->Pnext) { 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->Pnext) { if ( DelStruct->m_Flags & STRUCT_DELETED ) continue; if ( DelStruct->Type() != DRAW_LABEL_STRUCT_TYPE ) continue; GetScreen()->m_Curseur = ((DrawTextStruct*)DelStruct)->m_Pos; EDA_BaseStruct * TstStruct = PickStruct(GetScreen()->m_Curseur, GetScreen()->EEDrawList,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->Pnext) 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 */ { EDA_BaseStruct * DelStruct; SCH_SCREEN * screen = frame->GetScreen(); bool item_deleted = FALSE; DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, MARKERITEM); if( DelStruct == NULL ) DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, JUNCTIONITEM); if( DelStruct == NULL ) DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, NOCONNECTITEM); if( DelStruct == NULL ) DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, RACCORDITEM); if( DelStruct == NULL ) DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, WIREITEM|BUSITEM); if( DelStruct == NULL ) DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, DRAWITEM); if( DelStruct == NULL ) DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, TEXTITEM|LABELITEM); if( DelStruct == NULL ) DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, LIBITEM); if( DelStruct == NULL ) DelStruct = PickStruct(screen->m_Curseur, screen->EEDrawList, SHEETITEM); if (DelStruct) { g_ItemToRepeat = NULL; DeleteStruct(frame->DrawPanel, DC, DelStruct); frame->TestDanglingEnds(frame->m_CurrentScreen->EEDrawList, DC); frame->GetScreen()->SetModify(); item_deleted = TRUE; } return item_deleted; } /***************************************************************/ void EraseStruct(EDA_BaseStruct *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; DrawSheetLabelStruct* SheetLabel, *NextLabel; if( DrawStruct == NULL ) return; if( Screen == NULL ) return; Screen->SetModify(); if (DrawStruct->Type() == DRAW_SHEETLABEL_STRUCT_TYPE) { /* Cette stucture est rattachee a une feuille, et n'est pas accessible par la liste globale directement */ 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 == (DrawSheetLabelStruct*) DrawStruct) { ((DrawSheetStruct *) DrawList)->m_Label = (DrawSheetLabelStruct *)SheetLabel->Pnext; delete DrawStruct; return; } else while( SheetLabel->Pnext )/* Examen de la liste dependante */ { NextLabel = (DrawSheetLabelStruct *)SheetLabel->Pnext; if( NextLabel == (DrawSheetLabelStruct*) DrawStruct ) { SheetLabel->Pnext = (EDA_BaseStruct *)NextLabel->Pnext; 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->Pnext; delete DrawStruct; } else { DrawList = Screen->EEDrawList; while ( DrawList && DrawList->Pnext) { if (DrawList->Pnext == PickedList->m_PickedStruct) { DrawList->Pnext = DrawList->Pnext->Pnext; delete DrawStruct; return; } DrawList = DrawList->Pnext; } } PickedList = (DrawPickedStruct *)PickedList->Pnext; } } else // structure usuelle */ { if (DrawStruct == Screen->EEDrawList) { Screen->EEDrawList = DrawStruct->Pnext; delete DrawStruct; } else { DrawList = Screen->EEDrawList; while (DrawList && DrawList->Pnext) { if (DrawList->Pnext == DrawStruct) { DrawList->Pnext = DrawStruct->Pnext; delete DrawStruct; return; } DrawList = DrawList->Pnext; } } } } /********************************/ void DeleteAllMarkers(int type) /********************************/ /* Effacement des marqueurs du type "type" */ { SCH_SCREEN * screen; EDA_BaseStruct * DrawStruct, * NextStruct; DrawMarkerStruct * Marker; EDA_ScreenList ScreenList(NULL); for ( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() ) { for ( DrawStruct = screen->EEDrawList; DrawStruct != NULL; DrawStruct = NextStruct) { NextStruct = DrawStruct->Pnext; 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, 0 , 0, DrawItem, CurrentUnit, 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(); delete DrawItem; } else /* Cas des autres items */ while(PreviousDrawItem) { if(PreviousDrawItem->Pnext == DrawItem) { PreviousDrawItem->Pnext = DrawItem->Pnext; delete DrawItem; break; } PreviousDrawItem = PreviousDrawItem->Next(); } } else /* Structure non reliee a un composant */ { delete DrawItem; } }