void SCH_EDIT_FRAME::CheckListConnections( PICKED_ITEMS_LIST& aItemsList, bool aAppend ) { std::vector< wxPoint > pts; std::vector< wxPoint > connections; GetSchematicConnections( connections ); for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); std::vector< wxPoint > new_pts; if( !item->IsConnectable() ) continue; item->GetConnectionPoints( new_pts ); pts.insert( pts.end(), new_pts.begin(), new_pts.end() ); // If the item is a line, we also add any connection points from the rest of the schematic // that terminate on the line after it is moved. if( item->Type() == SCH_LINE_T ) { SCH_LINE* line = (SCH_LINE*) item; for( auto i : connections ) if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), i ) ) pts.push_back( i ); } else { // Clean up any wires that short non-wire connections in the list for( auto point = new_pts.begin(); point != new_pts.end(); point++ ) { for( auto second_point = point + 1; second_point != new_pts.end(); second_point++ ) { aAppend |= TrimWire( *point, *second_point, aAppend ); } } } } // We always have some overlapping connection points. Drop duplicates here std::sort( pts.begin(), pts.end(), []( const wxPoint& a, const wxPoint& b ) -> bool { return a.x < b.x || (a.x == b.x && a.y < b.y); } ); pts.erase( unique( pts.begin(), pts.end() ), pts.end() ); for( auto point : pts ) { if( GetScreen()->IsJunctionNeeded( point, true ) ) { AddJunction( point, aAppend ); aAppend = true; } } }
void SCH_SCREEN::addConnectedItemsToBlock( const wxPoint& position ) { SCH_ITEM* item; ITEM_PICKER picker; bool addinlist = true; for( item = m_drawList.begin(); item; item = item->Next() ) { picker.SetItem( item ); if( !item->IsConnectable() || !item->IsConnected( position ) || (item->GetFlags() & SKIP_STRUCT) ) continue; if( item->IsSelected() && item->Type() != SCH_LINE_T ) continue; // A line having 2 ends, it can be tested twice: one time per end if( item->Type() == SCH_LINE_T ) { if( ! item->IsSelected() ) // First time this line is tested item->SetFlags( SELECTED | STARTPOINT | ENDPOINT ); else // second time (or more) this line is tested addinlist = false; SCH_LINE* line = (SCH_LINE*) item; if( line->GetStartPoint() == position ) item->ClearFlags( STARTPOINT ); else if( line->GetEndPoint() == position ) item->ClearFlags( ENDPOINT ); } else item->SetFlags( SELECTED ); if( addinlist ) { picker.SetFlags( item->GetFlags() ); m_BlockLocate.GetItems().PushItem( picker ); } } }
bool SCH_EDIT_FRAME::DeleteItemAtCrossHair( wxDC* DC ) { SCH_ITEM* item; SCH_SCREEN* screen = GetScreen(); item = LocateItem( GetCrossHairPosition(), SCH_COLLECTOR::ParentItems ); if( item ) { bool itemHasConnections = item->IsConnectable(); screen->SetCurItem( NULL ); SetRepeatItem( NULL ); DeleteItem( item ); if( itemHasConnections ) screen->TestDanglingEnds( m_canvas, DC ); OnModify(); return true; } return false; }
void SCH_SCREEN::SelectBlockItems() { PICKED_ITEMS_LIST* pickedlist = &m_BlockLocate.GetItems(); if( pickedlist->GetCount() == 0 ) return; ClearDrawingState(); for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) pickedlist->GetPickedItem( ii ); item->SetFlags( SELECTED ); } if( !m_BlockLocate.IsDragging() ) return; // Select all the items in the screen connected to the items in the block. // be sure end lines that are on the block limits are seen inside this block m_BlockLocate.Inflate( 1 ); unsigned last_select_id = pickedlist->GetCount(); for( unsigned ii = 0; ii < last_select_id; ii++ ) { SCH_ITEM* item = (SCH_ITEM*)pickedlist->GetPickedItem( ii ); item->SetFlags( IS_DRAGGED ); if( item->Type() == SCH_LINE_T ) { item->IsSelectStateChanged( m_BlockLocate ); if( !item->IsSelected() ) { // This is a special case: // this selected wire has no ends in block. // But it was selected (because it intersects the selecting area), // so we must keep it selected and select items connected to it // Note: an other option could be: remove it from drag list item->SetFlags( SELECTED | SKIP_STRUCT ); std::vector< wxPoint > connections; item->GetConnectionPoints( connections ); for( size_t i = 0; i < connections.size(); i++ ) addConnectedItemsToBlock( connections[i] ); } pickedlist->SetPickerFlags( item->GetFlags(), ii ); } else if( item->IsConnectable() ) { std::vector< wxPoint > connections; item->GetConnectionPoints( connections ); for( size_t jj = 0; jj < connections.size(); jj++ ) addConnectedItemsToBlock( connections[jj] ); } } m_BlockLocate.Inflate( -1 ); }
void SCH_SCREEN::addConnectedItemsToBlock( const SCH_ITEM* aItem, const wxPoint& position ) { SCH_ITEM* item; ITEM_PICKER picker; for( item = m_drawList.begin(); item; item = item->Next() ) { if( !item->IsConnectable() || ( item->GetFlags() & SKIP_STRUCT ) || !item->CanConnect( aItem ) || item == aItem ) continue; // A line having 2 ends, it can be tested twice: one time per end if( item->Type() == SCH_LINE_T ) { SCH_LINE* line = (SCH_LINE*) item; if( !item->HitTest( position ) ) continue; // First time through. Flags set to denote an end that is not moving if( !item->IsSelected() ) item->SetFlags( CANDIDATE | STARTPOINT | ENDPOINT ); if( line->GetStartPoint() == position ) item->ClearFlags( STARTPOINT ); else if( line->GetEndPoint() == position ) item->ClearFlags( ENDPOINT ); else // This picks up items such as labels that can connect to the middle of a line item->ClearFlags( STARTPOINT | ENDPOINT ); } // We want to move a mid-connected label or bus entry when the full line is being moved else if( !item->IsSelected() && aItem->Type() == SCH_LINE_T && !( aItem->GetFlags() & ( ENDPOINT | STARTPOINT ) ) ) { std::vector< wxPoint > connections; item->GetConnectionPoints( connections ); for( auto conn : connections ) { if( aItem->HitTest( conn ) ) { item->SetFlags( CANDIDATE ); break; } } } if( item->IsSelected() ) continue; if( ( item->GetFlags() & CANDIDATE ) || item->IsConnected( position ) ) // Deal with all non-line items { item->ClearFlags( CANDIDATE ); item->SetFlags( SELECTED ); picker.SetItem( item ); picker.SetFlags( item->GetFlags() ); m_BlockLocate.GetItems().PushItem( picker ); } } }
void SCH_SCREEN::SelectBlockItems() { auto addConnections = [ this ]( SCH_ITEM* item ) -> void { std::vector< wxPoint > connections; item->GetConnectionPoints( connections ); for( auto conn : connections ) addConnectedItemsToBlock( item, conn ); }; PICKED_ITEMS_LIST* pickedlist = &m_BlockLocate.GetItems(); if( pickedlist->GetCount() == 0 ) return; ClearDrawingState(); for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) pickedlist->GetPickedItem( ii ); item->SetFlags( SELECTED ); } if( !m_BlockLocate.IsDragging() ) return; // Select all the items in the screen connected to the items in the block. // be sure end lines that are on the block limits are seen inside this block m_BlockLocate.Inflate( 1 ); unsigned last_select_id = pickedlist->GetCount(); for( unsigned ii = 0; ii < last_select_id; ii++ ) { SCH_ITEM* item = (SCH_ITEM*)pickedlist->GetPickedItem( ii ); item->SetFlags( IS_DRAGGED ); if( item->Type() == SCH_LINE_T ) { item->IsSelectStateChanged( m_BlockLocate ); if( !item->IsSelected() ) { // This is a special case: // this selected wire has no ends in block. // But it was selected (because it intersects the selecting area), // so we must keep it selected and select items connected to it // Note: an other option could be: remove it from drag list item->SetFlags( SELECTED | SKIP_STRUCT ); addConnections( item ); } pickedlist->SetPickerFlags( item->GetFlags(), ii ); } else if( item->IsConnectable() ) { addConnections( item ); } } // Select the items that are connected to a block object that was added // to our selection list in the last step. for( unsigned ii = last_select_id; ii < pickedlist->GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*)pickedlist->GetPickedItem( ii ); if( item->Type() == SCH_COMPONENT_T || item->Type() == SCH_BUS_BUS_ENTRY_T || item->Type() == SCH_BUS_WIRE_ENTRY_T || item->Type() == SCH_SHEET_T || ( item->Type() == SCH_LINE_T && !( item->GetFlags() & ( ENDPOINT | STARTPOINT ) ) ) ) { item->SetFlags( IS_DRAGGED ); addConnections( item ); } } m_BlockLocate.Inflate( -1 ); }
void SCH_EDIT_FRAME::addCurrentItemToList( wxDC* aDC ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); wxCHECK_RET( item != NULL, wxT( "Cannot add current item to list." ) ); m_canvas->SetAutoPanRequest( false ); SCH_ITEM* undoItem = item; if( item->Type() == SCH_SHEET_PIN_T ) { SCH_SHEET* sheet = (SCH_SHEET*) item->GetParent(); wxCHECK_RET( (sheet != NULL) && (sheet->Type() == SCH_SHEET_T), wxT( "Cannot place sheet pin in invalid schematic sheet object." ) ); undoItem = sheet; } else if( item->Type() == SCH_FIELD_T ) { SCH_COMPONENT* cmp = (SCH_COMPONENT*) item->GetParent(); wxCHECK_RET( (cmp != NULL) && (cmp->Type() == SCH_COMPONENT_T), wxT( "Cannot place field in invalid schematic component object." ) ); undoItem = cmp; } if( item->IsNew() ) { if( item->Type() == SCH_SHEET_T ) { // Fix the size and position of the new sheet using the last values set by // the m_mouseCaptureCallback function. m_canvas->SetMouseCapture( NULL, NULL ); if( !EditSheet( (SCH_SHEET*)item, aDC ) ) { screen->SetCurItem( NULL ); item->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode ); delete item; return; } SetSheetNumberAndCount(); } if( undoItem == item ) { if( !screen->CheckIfOnDrawList( item ) ) // don't want a loop! screen->Append( item ); SetRepeatItem( item ); SaveCopyInUndoList( undoItem, UR_NEW ); } else { // Here, item is not a basic schematic item, but an item inside // a parent basic schematic item, // currently: sheet pin or component field. // currently, only a sheet pin can be found as new item, // because new component fields have a specific handling, and do not appears here SaveCopyInUndoList( undoItem, UR_CHANGED ); if( item->Type() == SCH_SHEET_PIN_T ) ( (SCH_SHEET*)undoItem )->AddPin( (SCH_SHEET_PIN*) item ); else wxLogMessage(wxT( "addCurrentItemToList: expected type = SCH_SHEET_PIN_T, actual type = %d" ), item->Type() ); } } else { SaveUndoItemInUndoList( undoItem ); } // Erase the wire representation before the 'normal' view is drawn. if ( item->IsWireImage() ) item->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode ); item->ClearFlags(); screen->SetModify(); screen->SetCurItem( NULL ); m_canvas->SetMouseCapture( NULL, NULL ); m_canvas->EndMouseCapture(); if( item->IsConnectable() ) screen->TestDanglingEnds(); if( aDC ) { EDA_CROSS_HAIR_MANAGER( m_canvas, aDC ); // Erase schematic cursor undoItem->Draw( m_canvas, aDC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE ); } }