bool SCH_EDIT_FRAME::prepareForNetlist() { SCH_SHEET_LIST sheets; sheets.AnnotatePowerSymbols( Prj().SchLibs() ); // Performs some controls: if( CheckAnnotate( NULL, 0 ) ) { // Schematic must be annotated: call Annotate dialog and tell // the user why that is. InvokeDialogAnnotate( this, _( "Exporting the netlist requires a " "completely\nannotated schematic." ) ); if( CheckAnnotate( NULL, 0 ) ) return false; } // Test duplicate sheet names: if( TestDuplicateSheetNames( false ) > 0 ) { if( !IsOK( NULL, _( "Error: duplicate sheet names. Continue?" ) ) ) return false; } // Cleanup the entire hierarchy SCH_SCREENS screens; screens.SchematicCleanUp(); return true; }
void DIALOG_ERC::DisplayERC_MarkersList() { SCH_SHEET_LIST sheetList; m_MarkersList->ClearList(); SCH_SHEET_PATH* sheet = sheetList.GetFirst(); for( ; sheet != NULL; sheet = sheetList.GetNext() ) { SCH_ITEM* item = sheet->LastDrawList(); for( ; item != NULL; item = item->Next() ) { if( item->Type() != SCH_MARKER_T ) continue; SCH_MARKER* marker = (SCH_MARKER*) item; if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC ) continue; m_MarkersList->AppendToList( marker ); } } m_MarkersList->DisplayList(); }
void DIALOG_ERC::DisplayERC_MarkersList() { SCH_SHEET_LIST sheetList; m_MarkersList->ClearList(); SCH_SHEET_PATH* sheet = sheetList.GetFirst(); for( ; sheet != NULL; sheet = sheetList.GetNext() ) { SCH_ITEM* item = sheet->LastDrawList(); for( ; item != NULL; item = item->Next() ) { if( item->Type() != SCH_MARKER_T ) continue; SCH_MARKER* Marker = (SCH_MARKER*) item; if( Marker->GetMarkerType() != MARKER_BASE::MARKER_ERC ) continue; // Add marker without refresh the displayed list: m_MarkersList->AppendToList( Marker, false ); } } m_MarkersList->Refresh(); }
void SCH_EDIT_FRAME::SetSheetNumberAndCount() { SCH_SCREEN* screen = GetScreen(); SCH_SCREENS s_list; /* Set the sheet count, and the sheet number (1 for root sheet) */ int sheet_count = g_RootSheet->CountSheets(); int SheetNumber = 1; wxString current_sheetpath = m_CurrentSheet->Path(); SCH_SHEET_LIST SheetList; // Examine all sheets path to find the current sheets path, // and count them from root to the current sheet path: SCH_SHEET_PATH* sheet; for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) { wxString sheetpath = sheet->Path(); if( sheetpath == current_sheetpath ) // Current sheet path found break; SheetNumber++; /* Not found, increment sheet * number before this current * path */ } for( screen = s_list.GetFirst(); screen != NULL; screen = s_list.GetNext() ) { screen->m_NumberOfScreens = sheet_count; } GetScreen()->m_ScreenNumber = SheetNumber; }
void SCH_SHEET_PATH::GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols ) { // Search to sheet path number: int sheetnumber = 1; // 1 = root SCH_SHEET_LIST sheetList; for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext(), sheetnumber++ ) { if( Cmp( *path ) == 0 ) break; } for( SCH_ITEM* item = LastDrawList(); item; item = item->Next() ) { if( item->Type() == SCH_COMPONENT_T ) { SCH_COMPONENT* component = (SCH_COMPONENT*) item; // Skip pseudo components, which have a reference starting with #. This mainly // affects power symbols. if( !aIncludePowerSymbols && component->GetRef( this )[0] == wxT( '#' ) ) continue; LIB_PART* part = aLibs->FindLibPart( component->GetPartName() ); if( part ) { SCH_REFERENCE reference = SCH_REFERENCE( component, part, *this ); reference.SetSheetNumber( sheetnumber ); aReferences.AddItem( reference ); } } } }
bool WriteDiagnosticERC( const wxString& aFullFileName ) { wxString msg; wxFFile file( aFullFileName, wxT( "wt" ) ); if( !file.IsOpened() ) return false; msg = _( "ERC report" ); msg << wxT(" (") << DateAndTime() << wxT( ", " ) << _( "Encoding UTF8" ) << wxT( " )\n" ); int err_count = 0; int warn_count = 0; int total_count = 0; SCH_SHEET_LIST sheetList; SCH_SHEET_PATH* sheet; for( sheet = sheetList.GetFirst(); sheet != NULL; sheet = sheetList.GetNext() ) { msg << wxString::Format( _( "\n***** Sheet %s\n" ), GetChars( sheet->PathHumanReadable() ) ); for( SCH_ITEM* item = sheet->LastDrawList(); item != NULL; item = item->Next() ) { if( item->Type() != SCH_MARKER_T ) continue; SCH_MARKER* marker = (SCH_MARKER*) item; if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC ) continue; total_count++; if( marker->GetErrorLevel() == MARKER_BASE::MARKER_SEVERITY_ERROR ) err_count++; if( marker->GetErrorLevel() == MARKER_BASE::MARKER_SEVERITY_WARNING ) warn_count++; msg << marker->GetReporter().ShowReport(); } } msg << wxString::Format( _( "\n ** ERC messages: %d Errors %d Warnings %d\n" ), total_count, err_count, warn_count ); // Currently: write report unsing UTF8 (as usual in Kicad). // TODO: see if we can use the current encoding page (mainly for Windows users), // Or other format (HTML?) file.Write( msg ); // wxFFile dtor will close the file. return true; }
void DIALOG_ERC::OnLeftClickMarkersList( wxHtmlLinkEvent& event ) { wxString link = event.GetLinkInfo().GetHref(); m_lastMarkerFound = NULL; long index; if( !link.ToLong( &index ) ) return; const SCH_MARKER* marker = m_MarkersList->GetItem( index ); if( marker == NULL ) return; // Search for the selected marker SCH_SHEET_PATH* sheet; SCH_SHEET_LIST SheetList; bool notFound = true; for( sheet = SheetList.GetFirst(); sheet; sheet = SheetList.GetNext() ) { SCH_ITEM* item = (SCH_ITEM*) sheet->LastDrawList(); for( ; item; item = item->Next() ) { if( item == marker ) { notFound = false; break; } } if( notFound == false ) break; } if( notFound ) // Error { wxMessageBox( _( "Marker not found" ) ); // The marker was deleted, so rebuild marker list DisplayERC_MarkersList(); return; } if( *sheet != m_parent->GetCurrentSheet() ) { sheet->LastScreen()->SetZoom( m_parent->GetScreen()->GetZoom() ); m_parent->SetCurrentSheet( *sheet ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); } m_lastMarkerFound = marker; m_parent->SetCrossHairPosition( marker->m_Pos ); m_parent->RedrawScreen( marker->m_Pos, false); }
void SCH_EDIT_FRAME::OnFindDrcMarker( wxFindDialogEvent& event ) { static SCH_MARKER* lastMarker = NULL; wxString msg; SCH_SHEET_LIST schematic; SCH_SHEET_PATH* sheetFoundIn = NULL; bool wrap = ( event.GetFlags() & FR_SEARCH_WRAP ) != 0; wxRect clientRect( wxPoint( 0, 0 ), GetClientSize() ); bool warpCursor = ( ( event.GetId() == wxEVT_COMMAND_FIND_CLOSE ) || !( event.GetFlags() & FR_NO_WARP_CURSOR ) ); if( event.GetFlags() & FR_CURRENT_SHEET_ONLY ) { sheetFoundIn = m_CurrentSheet; lastMarker = (SCH_MARKER*) m_CurrentSheet->FindNextItem( SCH_MARKER_T, lastMarker, wrap ); } else { lastMarker = (SCH_MARKER*) schematic.FindNextItem( SCH_MARKER_T, &sheetFoundIn, lastMarker, wrap ); } if( lastMarker != NULL ) { if( *sheetFoundIn != *m_CurrentSheet ) { sheetFoundIn->LastScreen()->SetZoom( GetScreen()->GetZoom() ); *m_CurrentSheet = *sheetFoundIn; m_CurrentSheet->UpdateAllScreenReferences(); } sheetFoundIn->LastScreen()->SetCrossHairPosition( lastMarker->GetPosition() ); RedrawScreen( lastMarker->GetPosition(), warpCursor ); wxString path = sheetFoundIn->Path(); wxString units = GetAbbreviatedUnitsLabel(); double x = To_User_Unit( g_UserUnit, (double) lastMarker->GetPosition().x, m_internalUnits ); double y = To_User_Unit( g_UserUnit, (double) lastMarker->GetPosition().y, m_internalUnits ); msg.Printf( _( "Design rule check marker found in sheet %s at %0.3f%s, %0.3f%s" ), GetChars( path ), x, GetChars( units ), y, GetChars( units) ); SetStatusText( msg ); } else { SetStatusText( _( "No more markers were found." ) ); } }
int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOnly ) { // build the screen list SCH_SHEET_LIST SheetList; SCH_REFERENCE_LIST ComponentsList; // Build the list of components if( !aOneSheetOnly ) SheetList.GetComponents( Prj().SchLibs(), ComponentsList ); else m_CurrentSheet->GetComponents( Prj().SchLibs(), ComponentsList ); return ComponentsList.CheckAnnotation( aMessageList ); }
bool WriteDiagnosticERC( const wxString& aFullFileName ) { SCH_ITEM* item; SCH_MARKER* marker; static FILE* file; SCH_SHEET_PATH* sheet; wxString msg; int count = 0; if( ( file = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL ) return false; msg = _( "ERC report" ); fprintf( file, "%s (%s)\n", TO_UTF8( msg ), TO_UTF8( DateAndTime() ) ); SCH_SHEET_LIST sheetList; for( sheet = sheetList.GetFirst(); sheet != NULL; sheet = sheetList.GetNext() ) { msg.Printf( _( "\n***** Sheet %s\n" ), GetChars( sheet->PathHumanReadable() ) ); fprintf( file, "%s", TO_UTF8( msg ) ); for( item = sheet->LastDrawList(); item != NULL; item = item->Next() ) { if( item->Type() != SCH_MARKER_T ) continue; marker = (SCH_MARKER*) item; if( marker->GetMarkerType() != MARK_ERC ) continue; if( marker->GetMarkerType() == ERR ) count++; msg = marker->GetReporter().ShowReport(); fprintf( file, "%s", TO_UTF8( msg ) ); } } msg.Printf( _( "\n >> Errors ERC: %d\n" ), count ); fprintf( file, "%s", TO_UTF8( msg ) ); fclose( file ); return true; }
void NETLIST_EXPORTER::findAllInstancesOfComponent( SCH_COMPONENT* aComponent, LIB_PART* aEntry, SCH_SHEET_PATH* aSheetPath ) { wxString ref = aComponent->GetRef( aSheetPath ); wxString ref2; SCH_SHEET_LIST sheetList; for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() ) { for( EDA_ITEM* item = sheet->LastDrawList(); item; item = item->Next() ) { if( item->Type() != SCH_COMPONENT_T ) continue; SCH_COMPONENT* comp2 = (SCH_COMPONENT*) item; ref2 = comp2->GetRef( sheet ); if( ref2.CmpNoCase( ref ) != 0 ) continue; int unit2 = comp2->GetUnitSelection( sheet ); // slow for( LIB_PIN* pin = aEntry->GetNextPin(); pin; pin = aEntry->GetNextPin( pin ) ) { wxASSERT( pin->Type() == LIB_PIN_T ); if( pin->GetUnit() && pin->GetUnit() != unit2 ) continue; if( pin->GetConvert() && pin->GetConvert() != comp2->GetConvert() ) continue; // A suitable pin is found: add it to the current list addPinToComponentPinList( comp2, sheet, pin ); } } } }
void SCH_FIND_COLLECTOR::Collect( SCH_FIND_REPLACE_DATA& aFindReplaceData, SCH_SHEET_PATH* aSheetPath ) { if( !IsSearchRequired( aFindReplaceData ) && !m_List.empty() && !m_forceSearch ) return; m_findReplaceData = aFindReplaceData; Empty(); // empty the collection just in case m_data.clear(); m_foundIndex = 0; SetForceSearch( false ); if( aSheetPath ) { m_sheetPath = aSheetPath; EDA_ITEM::IterateForward( aSheetPath->LastDrawList(), this, NULL, m_ScanTypes ); } else { SCH_SHEET_LIST schematic; m_sheetPath = schematic.GetFirst(); while( m_sheetPath != NULL ) { EDA_ITEM::IterateForward( m_sheetPath->LastDrawList(), this, NULL, m_ScanTypes ); m_sheetPath = schematic.GetNext(); } } #if defined(DEBUG) dump(); #endif if( m_List.size() != m_data.size() ) { wxFAIL_MSG( wxT( "List size mismatch." ) ); m_List.clear(); m_data.clear(); } }
void SCH_SHEET_PATH::GetMultiUnitComponents( PART_LIBS* aLibs, SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols ) { // Find sheet path number int sheetnumber = 1; // 1 = root SCH_SHEET_LIST sheetList; for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext(), sheetnumber++ ) { if( Cmp( *path ) == 0 ) break; } for( SCH_ITEM* item = LastDrawList(); item; item = item->Next() ) { if( item->Type() != SCH_COMPONENT_T ) continue; SCH_COMPONENT* component = (SCH_COMPONENT*) item; // Skip pseudo components, which have a reference starting with #. This mainly // affects power symbols. if( !aIncludePowerSymbols && component->GetRef( this )[0] == wxT( '#' ) ) continue; LIB_PART* part = aLibs->FindLibPart( component->GetPartName() ); if( part && part->GetUnitCount() > 1 ) { SCH_REFERENCE reference = SCH_REFERENCE( component, part, *this ); reference.SetSheetNumber( sheetnumber ); wxString reference_str = reference.GetRef(); // Never lock unassigned references if( reference_str[reference_str.Len() - 1] == '?' ) continue; aRefList[reference_str].AddItem( reference ); } } }
/* Function CreateNetlist * > test for some issues (missing or duplicate references and sheet names) * > build netlist info * > create the netlist file * param aFormat = netlist format (NET_TYPE_PCBNEW ...) * param aFullFileName = full netlist file name * param aNetlistOptions = netlist options using OR'ed bits (see WriteNetListFile). * return true if success. */ bool SCH_EDIT_FRAME::CreateNetlist( int aFormat, const wxString& aFullFileName, unsigned aNetlistOptions ) { SCH_SHEET_LIST sheets; sheets.AnnotatePowerSymbols(); // Performs some controls: if( CheckAnnotate( NULL, 0 ) ) { if( !IsOK( NULL, _( "Some items are not annotated\n\ Do you want to annotate schematic?" ) ) ) return false; // Schematic must be annotated: call Annotate dialog: wxCommandEvent event; OnAnnotate( event ); if( CheckAnnotate( NULL, 0 ) ) return false; } // Test duplicate sheet names: if( TestDuplicateSheetNames( false ) > 0 ) { if( !IsOK( NULL, _( "Error: duplicate sheet names. Continue?" ) ) ) return false; } /* Cleanup the entire hierarchy */ SCH_SCREENS screens; screens.SchematicCleanUp(); BuildNetListBase(); bool success = WriteNetListFile( aFormat, aFullFileName, aNetlistOptions ); return success; }
void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) { wxFileName fn; m_writeErcFile = m_WriteResultOpt->GetValue(); m_TestSimilarLabels = m_cbTestSimilarLabels->GetValue(); m_tstUniqueGlobalLabels = m_cbTestUniqueGlbLabels->GetValue(); // Build the whole sheet list in hierarchy (sheet, not screen) SCH_SHEET_LIST sheets; sheets.AnnotatePowerSymbols( Prj().SchLibs() ); if( m_parent->CheckAnnotate( aMessagesList, false ) ) { if( aMessagesList ) { wxString msg = _( "Annotation required!" ); msg += wxT( "\n" ); aMessagesList->Add( msg ); } return; } SCH_SCREENS screens; // Erase all previous DRC markers. screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC ); for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() ) { /* Ff wire list has changed, delete Undo Redo list to avoid pointers on deleted * data problems. */ if( screen->SchematicCleanUp( NULL ) ) screen->ClearUndoRedoList(); } /* Test duplicate sheet names inside a given sheet, one cannot have sheets with * duplicate names (file names can be duplicated). */ TestDuplicateSheetNames( true ); std::auto_ptr<NETLIST_OBJECT_LIST> objectsConnectedList( m_parent->BuildNetListBase() ); // Reset the connection type indicator objectsConnectedList->ResetConnectionsType(); unsigned lastNet; unsigned nextNet = lastNet = 0; int MinConn = NOC; for( unsigned net = 0; net < objectsConnectedList->size(); net++ ) { if( objectsConnectedList->GetItemNet( lastNet ) != objectsConnectedList->GetItemNet( net ) ) { // New net found: MinConn = NOC; nextNet = net; } switch( objectsConnectedList->GetItemType( net ) ) { // These items do not create erc problems case NET_ITEM_UNSPECIFIED: case NET_SEGMENT: case NET_BUS: case NET_JUNCTION: case NET_LABEL: case NET_BUSLABELMEMBER: case NET_PINLABEL: case NET_GLOBBUSLABELMEMBER: break; case NET_HIERLABEL: case NET_HIERBUSLABELMEMBER: case NET_SHEETLABEL: case NET_SHEETBUSLABELMEMBER: // ERC problems when pin sheets do not match hierarchical labels. // Each pin sheet must match a hierarchical label // Each hierarchical label must match a pin sheet objectsConnectedList->TestforNonOrphanLabel( net, nextNet ); break; case NET_GLOBLABEL: if( m_tstUniqueGlobalLabels ) objectsConnectedList->TestforNonOrphanLabel( net, nextNet ); break; case NET_NOCONNECT: // ERC problems when a noconnect symbol is connected to more than one pin. MinConn = NET_NC; if( objectsConnectedList->CountPinsInNet( nextNet ) > 1 ) Diagnose( objectsConnectedList->GetItem( net ), NULL, MinConn, UNC ); break; case NET_PIN: // Look for ERC problems between pins: TestOthersItems( objectsConnectedList.get(), net, nextNet, &MinConn ); break; } lastNet = net; } // Test similar labels (i;e. labels which are identical when // using case insensitive comparisons) if( m_TestSimilarLabels ) objectsConnectedList->TestforSimilarLabels(); // Displays global results: updateMarkerCounts( &screens ); // Display diags: DisplayERC_MarkersList(); // Display new markers: m_parent->GetCanvas()->Refresh(); if( m_writeErcFile ) { fn = g_RootSheet->GetScreen()->GetFileName(); fn.SetExt( wxT( "erc" ) ); wxFileDialog dlg( this, _( "ERC File" ), fn.GetPath(), fn.GetFullName(), _( "Electronic rule check file (.erc)|*.erc" ), wxFD_SAVE ); if( dlg.ShowModal() == wxID_CANCEL ) return; if( WriteDiagnosticERC( dlg.GetPath() ) ) { Close( true ); ExecuteFile( this, Pgm().GetEditorName(), QuoteFullPath( fn ) ); } } }
void SCH_EDIT_FRAME::PasteListOfItems( wxDC* DC ) { unsigned i; SCH_ITEM* item; SCH_SHEET_LIST hierarchy; // This is the entire schematic hierarcy. if( m_blockItems.GetCount() == 0 ) { DisplayError( this, _( "No item to paste." ) ); return; } wxFileName destFn = m_CurrentSheet->Last()->GetFileName(); if( destFn.IsRelative() ) destFn.MakeAbsolute( Prj().GetProjectPath() ); // Make sure any sheets in the block to be pasted will not cause recursion in // the destination sheet. for( i = 0; i < m_blockItems.GetCount(); i++ ) { item = (SCH_ITEM*) m_blockItems.GetItem( i ); if( item->Type() == SCH_SHEET_T ) { SCH_SHEET* sheet = (SCH_SHEET*)item; wxFileName srcFn = sheet->GetFileName(); if( srcFn.IsRelative() ) srcFn.MakeAbsolute( Prj().GetProjectPath() ); SCH_SHEET_LIST sheetHierarchy( sheet ); if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) ) { wxString msg; msg.Printf( _( "The sheet changes cannot be made because the destination " "sheet already has the sheet <%s> or one of it's subsheets " "as a parent somewhere in the schematic hierarchy." ), GetChars( sheet->GetFileName() ) ); DisplayError( this, msg ); return; } // Duplicate sheet names and sheet time stamps are not valid. Use a time stamp // based sheet name and update the time stamp for each sheet in the block. unsigned long timeStamp = (unsigned long)GetNewTimeStamp(); sheet->SetName( wxString::Format( wxT( "sheet%8.8lX" ), timeStamp ) ); sheet->SetTimeStamp( (time_t)timeStamp ); } } PICKED_ITEMS_LIST picklist; for( i = 0; i < m_blockItems.GetCount(); i++ ) { item = DuplicateStruct( (SCH_ITEM*) m_blockItems.GetItem( i ) ); // Creates data, and push it as new data in undo item list buffer ITEM_PICKER picker( item, UR_NEW ); picklist.PushItem( picker ); // Clear annotation and init new time stamp for the new components and sheets: if( item->Type() == SCH_COMPONENT_T ) { ( (SCH_COMPONENT*) item )->SetTimeStamp( GetNewTimeStamp() ); ( (SCH_COMPONENT*) item )->ClearAnnotation( NULL ); } else if( item->Type() == SCH_SHEET_T ) { ( (SCH_SHEET*) item )->SetTimeStamp( GetNewTimeStamp() ); } SetSchItemParent( item, GetScreen() ); item->Draw( m_canvas, DC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE ); GetScreen()->Append( item ); } SaveCopyInUndoList( picklist, UR_NEW ); MoveItemsInList( picklist, GetScreen()->m_BlockLocate.GetMoveVector() ); // Clear flags for all items. GetScreen()->ClearDrawingState(); OnModify(); return; }
bool SCH_EDIT_FRAME::ProcessCmpToFootprintLinkFile( wxString& aFullFilename, bool aForceFieldsVisibleAttribute, bool aFieldsVisibleAttributeState ) { // Build a flat list of components in schematic: SCH_REFERENCE_LIST referencesList; SCH_SHEET_LIST SheetList; SheetList.GetComponents( referencesList, false ); FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) ); if( cmpFile == NULL ) return false; // cmpFileReader dtor will close cmpFile FILE_LINE_READER cmpFileReader( cmpFile, aFullFilename ); // Now, for each component found in file, // replace footprint field value by the new value: wxString reference; wxString footprint; wxString buffer; wxString value; while( cmpFileReader.ReadLine() ) { buffer = FROM_UTF8( cmpFileReader.Line() ); if( ! buffer.StartsWith( wxT("BeginCmp") ) ) continue; // Begin component description. reference.Empty(); footprint.Empty(); while( cmpFileReader.ReadLine() ) { buffer = FROM_UTF8( cmpFileReader.Line() ); if( buffer.StartsWith( wxT("EndCmp") ) ) break; // store string value, stored between '=' and ';' delimiters. value = buffer.AfterFirst( '=' ); value = value.BeforeLast( ';'); value.Trim(true); value.Trim(false); if( buffer.StartsWith( wxT("Reference") ) ) { reference = value; continue; } if( buffer.StartsWith( wxT("IdModule =" ) ) ) { footprint = value; continue; } } // A block is read: initialize the footprint field of the correponding component // if the footprint name is not empty if( reference.IsEmpty() ) continue; // Search the component in the flat list for( unsigned ii = 0; ii < referencesList.GetCount(); ii++ ) { if( reference.CmpNoCase( referencesList[ii].GetRef() ) == 0 ) { // We have found a candidate. // Note: it can be not unique (multiple parts per package) // So we *do not* stop the search here SCH_COMPONENT* component = referencesList[ii].GetComponent(); SCH_FIELD * fpfield = component->GetField( FOOTPRINT ); fpfield->SetText( footprint ); if( aForceFieldsVisibleAttribute ) { component->GetField( FOOTPRINT ) ->SetVisible( aFieldsVisibleAttributeState ); } } } } return true; }
bool NETLIST_OBJECT_LIST::BuildNetListInfo( SCH_SHEET_LIST& aSheets ) { SCH_SHEET_PATH* sheet; // Fill list with connected items from the flattened sheet list for( unsigned i = 0; i < aSheets.size(); i++ ) { sheet = &aSheets[i]; for( SCH_ITEM* item = sheet->LastScreen()->GetDrawItems(); item; item = item->Next() ) { item->GetNetListItem( *this, sheet ); } } if( size() == 0 ) return false; // Sort objects by Sheet SortListbySheet(); sheet = &(GetItem( 0 )->m_SheetPath); m_lastNetCode = m_lastBusNetCode = 1; for( unsigned ii = 0, istart = 0; ii < size(); ii++ ) { NETLIST_OBJECT* net_item = GetItem( ii ); if( net_item->m_SheetPath != *sheet ) // Sheet change { sheet = &(net_item->m_SheetPath); istart = ii; } switch( net_item->m_Type ) { case NET_ITEM_UNSPECIFIED: wxMessageBox( wxT( "BuildNetListInfo() error" ) ); break; case NET_PIN: case NET_PINLABEL: case NET_SHEETLABEL: case NET_NOCONNECT: if( net_item->GetNet() != 0 ) break; case NET_SEGMENT: // Test connections point to point type without bus. if( net_item->GetNet() == 0 ) { net_item->SetNet( m_lastNetCode ); m_lastNetCode++; } pointToPointConnect( net_item, IS_WIRE, istart ); break; case NET_JUNCTION: // Control of the junction outside BUS. if( net_item->GetNet() == 0 ) { net_item->SetNet( m_lastNetCode ); m_lastNetCode++; } segmentToPointConnect( net_item, IS_WIRE, istart ); // Control of the junction, on BUS. if( net_item->m_BusNetCode == 0 ) { net_item->m_BusNetCode = m_lastBusNetCode; m_lastBusNetCode++; } segmentToPointConnect( net_item, IS_BUS, istart ); break; case NET_LABEL: case NET_HIERLABEL: case NET_GLOBLABEL: // Test connections type junction without bus. if( net_item->GetNet() == 0 ) { net_item->SetNet( m_lastNetCode ); m_lastNetCode++; } segmentToPointConnect( net_item, IS_WIRE, istart ); break; case NET_SHEETBUSLABELMEMBER: if( net_item->m_BusNetCode != 0 ) break; case NET_BUS: // Control type connections point to point mode bus if( net_item->m_BusNetCode == 0 ) { net_item->m_BusNetCode = m_lastBusNetCode; m_lastBusNetCode++; } pointToPointConnect( net_item, IS_BUS, istart ); break; case NET_BUSLABELMEMBER: case NET_HIERBUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: // Control connections similar has on BUS if( net_item->GetNet() == 0 ) { net_item->m_BusNetCode = m_lastBusNetCode; m_lastBusNetCode++; } segmentToPointConnect( net_item, IS_BUS, istart ); break; } } #if defined(NETLIST_DEBUG) && defined(DEBUG) std::cout << "\n\nafter sheet local\n\n"; DumpNetTable(); #endif // Updating the Bus Labels Netcode connected by Bus connectBusLabels(); // Group objects by label. for( unsigned ii = 0; ii < size(); ii++ ) { switch( GetItem( ii )->m_Type ) { case NET_PIN: case NET_SHEETLABEL: case NET_SEGMENT: case NET_JUNCTION: case NET_BUS: case NET_NOCONNECT: break; case NET_LABEL: case NET_GLOBLABEL: case NET_PINLABEL: case NET_BUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: labelConnect( GetItem( ii ) ); break; case NET_SHEETBUSLABELMEMBER: case NET_HIERLABEL: case NET_HIERBUSLABELMEMBER: break; case NET_ITEM_UNSPECIFIED: break; } } #if defined(NETLIST_DEBUG) && defined(DEBUG) std::cout << "\n\nafter sheet global\n\n"; DumpNetTable(); #endif // Connection between hierarchy sheets for( unsigned ii = 0; ii < size(); ii++ ) { if( GetItem( ii )->m_Type == NET_SHEETLABEL || GetItem( ii )->m_Type == NET_SHEETBUSLABELMEMBER ) sheetLabelConnect( GetItem( ii ) ); } // Sort objects by NetCode SortListbyNetcode(); #if defined(NETLIST_DEBUG) && defined(DEBUG) std::cout << "\n\nafter qsort()\n"; DumpNetTable(); #endif // Compress numbers of Netcode having consecutive values. int NetCode = 0; m_lastNetCode = 0; for( unsigned ii = 0; ii < size(); ii++ ) { if( GetItem( ii )->GetNet() != m_lastNetCode ) { NetCode++; m_lastNetCode = GetItem( ii )->GetNet(); } GetItem( ii )->SetNet( NetCode ); } // Set the minimal connection info: setUnconnectedFlag(); // find the best label object to give the best net name to each net findBestNetNameForEachNet(); return true; }
void DIALOG_PLOT_SCHEMATIC::createPDFFile( bool aPlotAll, bool aPlotFrameRef ) { SCH_SCREEN* screen = m_parent->GetScreen(); SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); // sheetpath is saved here /* When printing all pages, the printed page is not the current page. In * complex hierarchies, we must update component references and others * parameters in the given printed SCH_SCREEN, accordint to the sheet path * because in complex hierarchies a SCH_SCREEN (a drawing ) is shared * between many sheets and component references depend on the actual sheet * path used */ SCH_SHEET_LIST sheetList; if( aPlotAll ) sheetList.BuildSheetList( g_RootSheet ); else sheetList.push_back( m_parent->GetCurrentSheet() ); // Allocate the plotter and set the job level parameter PDF_PLOTTER* plotter = new PDF_PLOTTER(); plotter->SetDefaultLineWidth( GetDefaultLineThickness() ); plotter->SetColorMode( getModeColor() ); plotter->SetCreator( wxT( "Eeschema-PDF" ) ); wxString msg; wxFileName plotFileName; REPORTER& reporter = m_MessagesBox->Reporter(); LOCALE_IO toggle; // Switch the locale to standard C for( unsigned i = 0; i < sheetList.size(); i++ ) { m_parent->SetCurrentSheet( sheetList[i] ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); screen = m_parent->GetCurrentSheet().LastScreen(); if( i == 0 ) { try { wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); wxString ext = PDF_PLOTTER::GetDefaultFileExtension(); plotFileName = createPlotFileName( m_outputDirectoryName, fname, ext, &reporter ); if( !plotter->OpenFile( plotFileName.GetFullPath() ) ) { msg.Printf( _( "Unable to create file '%s'.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); delete plotter; return; } // Open the plotter and do the first page setupPlotPagePDF( plotter, screen ); plotter->StartPlot(); } catch( const IO_ERROR& e ) { // Cannot plot PDF file msg.Printf( wxT( "PDF Plotter exception: %s" ), GetChars( e.errorText ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); restoreEnvironment( plotter, oldsheetpath ); return; } } else { /* For the following pages you need to close the (finished) page, * reconfigure, and then start a new one */ plotter->ClosePage(); setupPlotPagePDF( plotter, screen ); plotter->StartPage(); } plotOneSheetPDF( plotter, screen, aPlotFrameRef ); } // Everything done, close the plot and restore the environment msg.Printf( _( "Plot: '%s' OK.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ACTION ); restoreEnvironment( plotter, oldsheetpath ); }
int TestMultiunitFootprints( SCH_SHEET_LIST& aSheetList ) { int errors = 0; std::map<wxString, LIB_ID> footprints; SCH_MULTI_UNIT_REFERENCE_MAP refMap; aSheetList.GetMultiUnitComponents( refMap, true ); for( auto& component : refMap ) { auto& refList = component.second; if( refList.GetCount() == 0 ) { wxFAIL; // it should not happen continue; } // Reference footprint wxString fp; wxString unitName; for( unsigned i = 0; i < component.second.GetCount(); ++i ) { SCH_COMPONENT* cmp = refList.GetItem( i ).GetComp(); SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath(); fp = cmp->GetField( FOOTPRINT )->GetText(); if( !fp.IsEmpty() ) { unitName = cmp->GetRef( &sheetPath ) + LIB_PART::SubReference( cmp->GetUnit(), false ); break; } } for( unsigned i = 0; i < component.second.GetCount(); ++i ) { SCH_REFERENCE& ref = refList.GetItem( i ); SCH_COMPONENT* unit = ref.GetComp(); SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath(); const wxString curFp = unit->GetField( FOOTPRINT )->GetText(); if( !curFp.IsEmpty() && fp != curFp ) { wxString curUnitName = unit->GetRef( &sheetPath ) + LIB_PART::SubReference( unit->GetUnit(), false ); wxString msg = wxString::Format( _( "Unit %s has '%s' assigned, " "whereas unit %s has '%s' assigned" ), unitName, fp, curUnitName, curFp ); wxPoint pos = unit->GetPosition(); SCH_MARKER* marker = new SCH_MARKER(); marker->SetTimeStamp( GetNewTimeStamp() ); marker->SetData( ERCE_DIFFERENT_UNIT_FP, pos, msg, pos ); marker->SetMarkerType( MARKER_BASE::MARKER_ERC ); marker->SetErrorLevel( MARKER_BASE::MARKER_SEVERITY_WARNING ); ref.GetSheetPath().LastScreen()->Append( marker ); ++errors; } } } return errors; }
void DIALOG_PLOT_SCHEMATIC::createPSFile( bool aPlotAll, bool aPlotFrameRef ) { SCH_SCREEN* screen = m_parent->GetScreen(); SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); // sheetpath is saved here PAGE_INFO actualPage; // page size selected in schematic PAGE_INFO plotPage; // page size selected to plot /* When printing all pages, the printed page is not the current page. * In complex hierarchies, we must update component references * and others parameters in the given printed SCH_SCREEN, accordint to the sheet path * because in complex hierarchies a SCH_SCREEN (a drawing ) * is shared between many sheets and component references depend on the actual sheet path used */ SCH_SHEET_LIST sheetList; if( aPlotAll ) sheetList.BuildSheetList( g_RootSheet ); else sheetList.push_back( m_parent->GetCurrentSheet() ); for( unsigned i = 0; i < sheetList.size(); i++ ) { m_parent->SetCurrentSheet( sheetList[i] ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); screen = m_parent->GetCurrentSheet().LastScreen(); actualPage = screen->GetPageSettings(); switch( m_pageSizeSelect ) { case PAGE_SIZE_A: plotPage.SetType( wxT( "A" ) ); plotPage.SetPortrait( actualPage.IsPortrait() ); break; case PAGE_SIZE_A4: plotPage.SetType( wxT( "A4" ) ); plotPage.SetPortrait( actualPage.IsPortrait() ); break; case PAGE_SIZE_AUTO: default: plotPage = actualPage; break; } double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils(); double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils(); double scale = std::min( scalex, scaley ); wxPoint plot_offset; wxString outputDirName = m_outputDirectoryName->GetValue(); wxString msg; REPORTER& reporter = m_MessagesBox->Reporter(); try { wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); wxString ext = PS_PLOTTER::GetDefaultFileExtension(); wxFileName plotFileName = createPlotFileName( m_outputDirectoryName, fname, ext, &reporter ); if( plotOneSheetPS( plotFileName.GetFullPath(), screen, plotPage, plot_offset, scale, aPlotFrameRef ) ) { msg.Printf( _( "Plot: '%s' OK.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ACTION ); } else { // Error msg.Printf( _( "Unable to create file '%s'.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } catch( IO_ERROR& e ) { msg.Printf( wxT( "PS Plotter exception: %s"), GetChars( e.errorText ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } m_parent->SetCurrentSheet( oldsheetpath ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); }
bool NETLIST_EXPORTER_CADSTAR::Write( const wxString& aOutFileName, unsigned aNetlistOptions ) { (void)aNetlistOptions; //unused int ret = 0; FILE* f = NULL; if( ( f = wxFopen( aOutFileName, wxT( "wt" ) ) ) == NULL ) { wxString msg; msg.Printf( _( "Failed to create file '%s'" ), GetChars( aOutFileName ) ); DisplayError( NULL, msg ); return false; } wxString StartCmpDesc = StartLine + wxT( "ADD_COM" ); wxString msg; wxString footprint; SCH_SHEET_PATH* sheet; EDA_ITEM* DrawList; SCH_COMPONENT* component; wxString title = wxT( "Eeschema " ) + GetBuildVersion(); ret |= fprintf( f, "%sHEA\n", TO_UTF8( StartLine ) ); ret |= fprintf( f, "%sTIM %s\n", TO_UTF8( StartLine ), TO_UTF8( DateAndTime() ) ); ret |= fprintf( f, "%sAPP ", TO_UTF8( StartLine ) ); ret |= fprintf( f, "\"%s\"\n", TO_UTF8( title ) ); ret |= fprintf( f, "\n" ); // Prepare list of nets generation for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) m_masterList->GetItem( ii )->m_Flag = 0; // Create netlist module section m_ReferencesAlreadyFound.Clear(); SCH_SHEET_LIST SheetList; for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) { for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() ) { DrawList = component = findNextComponentAndCreatePinList( DrawList, sheet ); if( component == NULL ) break; /* doing nothing with footprint if( !component->GetField( FOOTPRINT )->IsVoid() ) { footprint = component->GetField( FOOTPRINT )->m_Text; footprint.Replace( wxT( " " ), wxT( "_" ) ); } else footprint = wxT( "$noname" ); */ msg = component->GetRef( sheet ); ret |= fprintf( f, "%s ", TO_UTF8( StartCmpDesc ) ); ret |= fprintf( f, "%s", TO_UTF8( msg ) ); msg = component->GetField( VALUE )->GetText(); msg.Replace( wxT( " " ), wxT( "_" ) ); ret |= fprintf( f, " \"%s\"", TO_UTF8( msg ) ); ret |= fprintf( f, "\n" ); } } ret |= fprintf( f, "\n" ); m_SortedComponentPinList.clear(); if( ! writeListOfNets( f ) ) ret = -1; // set error ret |= fprintf( f, "\n%sEND\n", TO_UTF8( StartLine ) ); fclose( f ); return ret >= 0; }
bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy ) { if( aSheet == NULL || aHierarchy == NULL ) return false; SCH_SHEET_LIST hierarchy; // This is the schematic sheet hierarchy. // Get the new texts DIALOG_SCH_SHEET_PROPS dlg( this ); wxString units = GetUnitsLabel( g_UserUnit ); dlg.SetFileName( aSheet->GetFileName() ); dlg.SetFileNameTextSize( StringFromValue( g_UserUnit, aSheet->GetFileNameSize() ) ); dlg.SetFileNameTextSizeUnits( units ); dlg.SetSheetName( aSheet->GetName() ); dlg.SetSheetNameTextSize( StringFromValue( g_UserUnit, aSheet->GetSheetNameSize() ) ); dlg.SetSheetNameTextSizeUnits( units ); dlg.SetSheetTimeStamp( wxString::Format( wxT("%8.8lX"), (unsigned long) aSheet->GetTimeStamp() ) ); /* This ugly hack fixes a bug in wxWidgets 2.8.7 and likely earlier * versions for the flex grid sizer in wxGTK that prevents the last * column from being sized correctly. It doesn't cause any problems * on win32 so it doesn't need to wrapped in ugly #ifdef __WXGTK__ * #endif. * Still presen in wxWidgets 3.0.2 */ dlg.Layout(); dlg.Fit(); dlg.SetMinSize( dlg.GetSize() ); dlg.GetSizer()->Fit( &dlg ); if( dlg.ShowModal() == wxID_CANCEL ) return false; wxFileName fileName = dlg.GetFileName(); fileName.SetExt( SchematicFileExtension ); if( !fileName.IsOk() ) { DisplayError( this, _( "File name is not valid!" ) ); return false; } // Duplicate sheet names are not valid. const SCH_SHEET* sheet = hierarchy.FindSheetByName( dlg.GetSheetName() ); if( sheet && (sheet != aSheet) ) { DisplayError( this, wxString::Format( _( "A sheet named \"%s\" already exists." ), GetChars( dlg.GetSheetName() ) ) ); return false; } wxString msg; bool loadFromFile = false; SCH_SCREEN* useScreen = NULL; wxString newFilename = fileName.GetFullPath(); // Search for a schematic file having the same filename // already in use in the hierarchy or on disk, in order to reuse it. if( !g_RootSheet->SearchHierarchy( newFilename, &useScreen ) ) { // if user entered a relative path, allow that to stay, but do the // file existence test with an absolute (full) path. This transformation // is local to this scope, but is the same one used at load time later. wxString absolute = Prj().AbsolutePath( newFilename ); loadFromFile = wxFileExists( absolute ); } // Inside Eeschema, filenames are stored using unix notation newFilename.Replace( wxT( "\\" ), wxT( "/" ) ); if( aSheet->GetScreen() == NULL ) // New sheet. { if( useScreen || loadFromFile ) // Load from existing file. { if( useScreen != NULL ) { msg.Printf( _( "A file named '%s' already exists in the current schematic " "hierarchy." ), GetChars( newFilename ) ); } else { msg.Printf( _( "A file named '%s' already exists." ), GetChars( newFilename ) ); } msg += _( "\n\nDo you want to create a sheet with the contents of this file?" ); if( !IsOK( this, msg ) ) { return false; } } else // New file. { aSheet->SetScreen( new SCH_SCREEN( &Kiway() ) ); aSheet->GetScreen()->SetMaxUndoItems( m_UndoRedoCountMax ); aSheet->GetScreen()->SetFileName( newFilename ); } } else // Existing sheet. { bool isUndoable = true; bool renameFile = false; // We are always using here a case insensitive comparison // to avoid issues under Windows, although under Unix // filenames are case sensitive. // But many users create schematic under both Unix and Windows if( newFilename.CmpNoCase( aSheet->GetFileName() ) != 0 ) { // Sheet file name changes cannot be undone. isUndoable = false; msg = _( "Changing the sheet file name cannot be undone. " ); if( useScreen || loadFromFile ) // Load from existing file. { wxString tmp; if( useScreen != NULL ) { tmp.Printf( _( "A file named <%s> already exists in the current schematic " "hierarchy." ), GetChars( newFilename ) ); } else { tmp.Printf( _( "A file named <%s> already exists." ), GetChars( newFilename ) ); } msg += tmp; msg += _( "\n\nDo you want to replace the sheet with the contents of this file?" ); if( !IsOK( this, msg ) ) return false; if( loadFromFile ) aSheet->SetScreen( NULL ); } else // Save to new file name. { if( aSheet->GetScreenCount() > 1 ) { msg += _( "This sheet uses shared data in a complex hierarchy.\n\n" ); msg += _( "Do you wish to convert it to a simple hierarchical sheet?" ); if( !IsOK( NULL, msg ) ) return false; } renameFile = true; } } m_canvas->SetIgnoreMouseEvents( true ); if( isUndoable ) SaveCopyInUndoList( aSheet, UR_CHANGED ); if( renameFile ) { aSheet->GetScreen()->SetFileName( newFilename ); SaveEEFile( aSheet->GetScreen() ); // If the the associated screen is shared by more than one sheet, remove the // screen and reload the file to a new screen. Failure to do this will trash // the screen reference counting in complex hierarchies. if( aSheet->GetScreenCount() > 1 ) { aSheet->SetScreen( NULL ); loadFromFile = true; } } } aSheet->SetFileName( newFilename ); if( useScreen ) aSheet->SetScreen( useScreen ); else if( loadFromFile ) aSheet->Load( this ); aSheet->SetFileNameSize( ValueFromString( g_UserUnit, dlg.GetFileNameTextSize() ) ); aSheet->SetName( dlg.GetSheetName() ); aSheet->SetSheetNameSize( ValueFromString( g_UserUnit, dlg.GetSheetNameTextSize() ) ); if( aSheet->GetName().IsEmpty() ) aSheet->SetName( wxString::Format( wxT( "Sheet%8.8lX" ), (long unsigned) aSheet->GetTimeStamp() ) ); // Make sure the sheet changes do not cause any recursion. SCH_SHEET_LIST sheetHierarchy( aSheet ); // Make sure files have fully qualified path and file name. wxFileName destFn = aHierarchy->Last()->GetFileName(); if( destFn.IsRelative() ) destFn.MakeAbsolute( Prj().GetProjectPath() ); if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) ) { msg.Printf( _( "The sheet changes cannot be made because the destination sheet already " "has the sheet <%s> or one of it's subsheets as a parent somewhere in " "the schematic hierarchy." ), GetChars( newFilename ) ); DisplayError( this, msg ); return false; } m_canvas->MoveCursorToCrossHair(); m_canvas->SetIgnoreMouseEvents( false ); OnModify(); return true; }
void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic, ANNOTATE_ORDER_T aSortOption, ANNOTATE_OPTION_T aAlgoOption, bool aResetAnnotation, bool aRepairTimestamps, bool aLockUnits ) { SCH_REFERENCE_LIST references; SCH_SCREENS screens; // Build the sheet list. SCH_SHEET_LIST sheets; // Map of locked components SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents; // Test for and replace duplicate time stamps in components and sheets. Duplicate // time stamps can happen with old schematics, schematic conversions, or manual // editing of files. if( aRepairTimestamps ) { int count = screens.ReplaceDuplicateTimeStamps(); if( count ) { wxString msg; msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count ); DisplayInfoMessage( NULL, msg, 2 ); } } // If units must be locked, collect all the sets that must be annotated together. if( aLockUnits ) { if( aAnnotateSchematic ) { sheets.GetMultiUnitComponents( Prj().SchLibs(), lockedComponents ); } else { m_CurrentSheet->GetMultiUnitComponents( Prj().SchLibs(), lockedComponents ); } } // If it is an annotation for all the components, reset previous annotation. if( aResetAnnotation ) DeleteAnnotation( !aAnnotateSchematic ); // Set sheet number and number of sheets. SetSheetNumberAndCount(); // Build component list if( aAnnotateSchematic ) { sheets.GetComponents( Prj().SchLibs(), references ); } else { m_CurrentSheet->GetComponents( Prj().SchLibs(), references ); } // Break full components reference in name (prefix) and number: // example: IC1 become IC, and 1 references.SplitReferences(); switch( aSortOption ) { default: case SORT_BY_X_POSITION: references.SortByXCoordinate(); break; case SORT_BY_Y_POSITION: references.SortByYCoordinate(); break; } bool useSheetNum = false; int idStep = 100; switch( aAlgoOption ) { default: case INCREMENTAL_BY_REF: break; case SHEET_NUMBER_X_100: useSheetNum = true; break; case SHEET_NUMBER_X_1000: useSheetNum = true; idStep = 1000; break; } // Recalculate and update reference numbers in schematic references.Annotate( useSheetNum, idStep, lockedComponents ); references.UpdateAnnotation(); wxArrayString errors; // Final control (just in case ... ). if( CheckAnnotate( &errors, !aAnnotateSchematic ) ) { wxString msg; for( size_t i = 0; i < errors.GetCount(); i++ ) msg += errors[i]; // wxLogWarning is a cheap and dirty way to dump a potentially long list of // strings to a dialog that can be saved to a file. This should be replaced // by a more elegant solution. wxLogWarning( msg ); } OnModify(); // Update on screen references, that can be modified by previous calculations: m_CurrentSheet->UpdateAllScreenReferences(); SetSheetNumberAndCount(); m_canvas->Refresh( true ); }
void DIALOG_PLOT_SCHEMATIC::createHPGLFile( bool aPlotAll, bool aPlotFrameRef ) { SCH_SCREEN* screen = m_parent->GetScreen(); SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); /* When printing all pages, the printed page is not the current page. * In complex hierarchies, we must setup references and other parameters * in the printed SCH_SCREEN * because in complex hierarchies a SCH_SCREEN (a schematic drawings) * is shared between many sheets */ SCH_SHEET_LIST sheetList; if( aPlotAll ) sheetList.BuildSheetList( g_RootSheet ); else sheetList.push_back( m_parent->GetCurrentSheet() ); REPORTER& reporter = m_MessagesBox->Reporter(); SetHPGLPenWidth(); for( unsigned i = 0; i < sheetList.size(); i++ ) { m_parent->SetCurrentSheet( sheetList[i] ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); screen = m_parent->GetCurrentSheet().LastScreen(); if( !screen ) // LastScreen() may return NULL screen = m_parent->GetScreen(); const PAGE_INFO& curPage = screen->GetPageSettings(); PAGE_INFO plotPage = curPage; // if plotting on a page size other than curPage if( m_HPGLPaperSizeOption->GetSelection() != PAGE_DEFAULT ) plotPage.SetType( plot_sheet_list( m_HPGLPaperSizeOption->GetSelection() ) ); // Calculation of conversion scales. double plot_scale = (double) plotPage.GetWidthMils() / curPage.GetWidthMils(); // Calculate offsets wxPoint plotOffset; wxString msg; if( GetPlotOriginCenter() ) { plotOffset.x = plotPage.GetWidthIU() / 2; plotOffset.y = -plotPage.GetHeightIU() / 2; } try { wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); wxString ext = HPGL_PLOTTER::GetDefaultFileExtension(); wxFileName plotFileName = createPlotFileName( m_outputDirectoryName, fname, ext, &reporter ); LOCALE_IO toggle; if( Plot_1_Page_HPGL( plotFileName.GetFullPath(), screen, plotPage, plotOffset, plot_scale, aPlotFrameRef ) ) { msg.Printf( _( "Plot: '%s' OK.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ACTION ); } else { msg.Printf( _( "Unable to create file '%s'.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } catch( IO_ERROR& e ) { msg.Printf( wxT( "HPGL Plotter exception: %s"), GetChars( e.errorText ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } m_parent->SetCurrentSheet( oldsheetpath ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); }
SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference, bool aSearchHierarchy, SCH_SEARCH_T aSearchType, const wxString& aSearchText, bool aWarpMouse ) { SCH_SHEET_PATH* sheet; SCH_SHEET_PATH* sheetWithComponentFound = NULL; SCH_ITEM* item = NULL; SCH_COMPONENT* Component = NULL; wxPoint pos, curpos; bool centerAndRedraw = false; bool notFound = true; wxString msg; LIB_PIN* pin; SCH_SHEET_LIST sheetList; sheet = sheetList.GetFirst(); if( !aSearchHierarchy ) sheet = m_CurrentSheet; for( ; sheet != NULL; sheet = sheetList.GetNext() ) { item = (SCH_ITEM*) sheet->LastDrawList(); for( ; ( item != NULL ) && ( notFound == true ); item = item->Next() ) { if( item->Type() != SCH_COMPONENT_T ) continue; SCH_COMPONENT* pSch = (SCH_COMPONENT*) item; if( aReference.CmpNoCase( pSch->GetRef( sheet ) ) == 0 ) { Component = pSch; sheetWithComponentFound = sheet; switch( aSearchType ) { default: case FIND_COMPONENT_ONLY: // Find component only notFound = false; pos = pSch->GetPosition(); break; case FIND_PIN: // find a pin pos = pSch->GetPosition(); // temporary: will be changed if the pin is found. pin = pSch->GetPin( aSearchText ); if( pin == NULL ) break; notFound = false; pos += pin->GetPosition(); break; case FIND_REFERENCE: // find reference notFound = false; pos = pSch->GetField( REFERENCE )->GetPosition(); break; case FIND_VALUE: // find value pos = pSch->GetPosition(); if( aSearchText.CmpNoCase( pSch->GetField( VALUE )->m_Text ) != 0 ) break; notFound = false; pos = pSch->GetField( VALUE )->GetPosition(); break; } } } if( (aSearchHierarchy == false) || (notFound == false) ) break; } if( Component ) { sheet = sheetWithComponentFound; if( *sheet != *m_CurrentSheet ) { sheet->LastScreen()->SetZoom( GetScreen()->GetZoom() ); *m_CurrentSheet = *sheet; m_CurrentSheet->UpdateAllScreenReferences(); centerAndRedraw = true; } wxPoint delta; pos -= Component->GetPosition(); delta = Component->GetTransform().TransformCoordinate( pos ); pos = delta + Component->GetPosition(); /* There may be need to reframe the drawing */ if( ! m_canvas->IsPointOnDisplay( pos ) ) { centerAndRedraw = true; } if( centerAndRedraw ) { GetScreen()->SetCrossHairPosition(pos); RedrawScreen( pos, aWarpMouse ); } else { INSTALL_UNBUFFERED_DC( dc, m_canvas ); m_canvas->CrossHairOff( &dc ); if( aWarpMouse ) m_canvas->MoveCursor( pos ); GetScreen()->SetCrossHairPosition(pos); m_canvas->CrossHairOn( &dc ); } } /* Print diag */ wxString msg_item; msg = aReference; switch( aSearchType ) { default: case FIND_COMPONENT_ONLY: // Find component only break; case FIND_PIN: // find a pin msg_item = _( "Pin " ) + aSearchText; break; case FIND_REFERENCE: // find reference msg_item = _( "Ref " ) + aSearchText; break; case FIND_VALUE: // find value msg_item = _( "Value " ) + aSearchText; break; case FIND_FIELD: // find field. todo msg_item = _( "Field " ) + aSearchText; break; } if( Component ) { if( !notFound ) { if( !msg_item.IsEmpty() ) msg += wxT( " " ) + msg_item; msg += _( " found" ); } else { msg += _( " found" ); if( !msg_item.IsEmpty() ) { msg += wxT( " but " ) + msg_item + _( " not found" ); } } } else { if( !msg_item.IsEmpty() ) msg += wxT( " " ) + msg_item; msg += _( " not found" ); } SetStatusText( msg ); return item; }
XNODE* NETLIST_EXPORTER_GENERIC::makeComponents() { XNODE* xcomps = node( wxT( "components" ) ); wxString timeStamp; // some strings we need many times, but don't want to construct more // than once for performance. These are used within loops so the // enclosing wxString constructor would fire on each loop iteration if // they were in a nested scope. // these are actually constructor invocations, not assignments as it appears: wxString sFields = wxT( "fields" ); wxString sField = wxT( "field" ); wxString sComponent = wxT( "comp" ); // use "part" ? wxString sName = wxT( "name" ); wxString sRef = wxT( "ref" ); wxString sPins = wxT( "pins" ); wxString sPin = wxT( "pin" ); wxString sValue = wxT( "value" ); wxString sSheetPath = wxT( "sheetpath" ); wxString sFootprint = wxT( "footprint" ); wxString sDatasheet = wxT( "datasheet" ); wxString sTStamp = wxT( "tstamp" ); wxString sTStamps = wxT( "tstamps" ); wxString sTSFmt = wxT( "%8.8lX" ); // comp->m_TimeStamp wxString sLibSource = wxT( "libsource" ); wxString sLibPart = wxT( "libpart" ); wxString sLib = wxT( "lib" ); wxString sPart = wxT( "part" ); wxString sNames = wxT( "names" ); m_ReferencesAlreadyFound.Clear(); SCH_SHEET_LIST sheetList; // Output is xml, so there is no reason to remove spaces from the field values. // And XML element names need not be translated to various languages. for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() ) { for( EDA_ITEM* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) { SCH_COMPONENT* comp = findNextComponentAndCreatePinList( schItem, path ); if( !comp ) break; // No component left schItem = comp; XNODE* xcomp; // current component being constructed // Output the component's elements in order of expected access frequency. // This may not always look best, but it will allow faster execution // under XSL processing systems which do sequential searching within // an element. xcomps->AddChild( xcomp = node( sComponent ) ); xcomp->AddAttribute( sRef, comp->GetRef( path->Last() ) ); xcomp->AddChild( node( sValue, comp->GetField( VALUE )->GetText() ) ); if( !comp->GetField( FOOTPRINT )->IsVoid() ) xcomp->AddChild( node( sFootprint, comp->GetField( FOOTPRINT )->GetText() ) ); if( !comp->GetField( DATASHEET )->IsVoid() ) xcomp->AddChild( node( sDatasheet, comp->GetField( DATASHEET )->GetText() ) ); // Export all user defined fields within the component, // which start at field index MANDATORY_FIELDS. Only output the <fields> // container element if there are any <field>s. if( comp->GetFieldCount() > MANDATORY_FIELDS ) { XNODE* xfields; xcomp->AddChild( xfields = node( sFields ) ); for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx ) { SCH_FIELD* f = comp->GetField( fldNdx ); // only output a field if non empty and not just "~" if( !f->IsVoid() ) { XNODE* xfield; xfields->AddChild( xfield = node( sField, f->GetText() ) ); xfield->AddAttribute( sName, f->GetName() ); } } } XNODE* xlibsource; xcomp->AddChild( xlibsource = node( sLibSource ) ); // "logical" library name, which is in anticipation of a better search // algorithm for parts based on "logical_lib.part" and where logical_lib // is merely the library name minus path and extension. LIB_PART* part = m_libs->FindLibPart( comp->GetPartName() ); if( part ) xlibsource->AddAttribute( sLib, part->GetLib()->GetLogicalName() ); xlibsource->AddAttribute( sPart, comp->GetPartName() ); XNODE* xsheetpath; xcomp->AddChild( xsheetpath = node( sSheetPath ) ); xsheetpath->AddAttribute( sNames, path->PathHumanReadable() ); xsheetpath->AddAttribute( sTStamps, path->Path() ); timeStamp.Printf( sTSFmt, (unsigned long)comp->GetTimeStamp() ); xcomp->AddChild( node( sTStamp, timeStamp ) ); } } return xcomps; }
XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader() { SCH_SCREEN* screen; XNODE* xdesign = node( wxT("design") ); XNODE* xtitleBlock; XNODE* xsheet; XNODE* xcomment; wxString sheetTxt; wxFileName sourceFileName; // the root sheet is a special sheet, call it source xdesign->AddChild( node( wxT( "source" ), g_RootSheet->GetScreen()->GetFileName() ) ); xdesign->AddChild( node( wxT( "date" ), DateAndTime() ) ); // which Eeschema tool xdesign->AddChild( node( wxT( "tool" ), wxT( "Eeschema " ) + GetBuildVersion() ) ); /* Export the sheets information */ SCH_SHEET_LIST sheetList; for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() ) { screen = sheet->LastScreen(); xdesign->AddChild( xsheet = node( wxT( "sheet" ) ) ); // get the string representation of the sheet index number. // Note that sheet->GetIndex() is zero index base and we need to increment the number by one to make // human readable sheetTxt.Printf( wxT( "%d" ), ( sheetList.GetIndex() + 1 ) ); xsheet->AddAttribute( wxT( "number" ), sheetTxt ); xsheet->AddAttribute( wxT( "name" ), sheet->PathHumanReadable() ); xsheet->AddAttribute( wxT( "tstamps" ), sheet->Path() ); TITLE_BLOCK tb = screen->GetTitleBlock(); xsheet->AddChild( xtitleBlock = node( wxT( "title_block" ) ) ); xtitleBlock->AddChild( node( wxT( "title" ), tb.GetTitle() ) ); xtitleBlock->AddChild( node( wxT( "company" ), tb.GetCompany() ) ); xtitleBlock->AddChild( node( wxT( "rev" ), tb.GetRevision() ) ); xtitleBlock->AddChild( node( wxT( "date" ), tb.GetDate() ) ); // We are going to remove the fileName directories. sourceFileName = wxFileName( screen->GetFileName() ); xtitleBlock->AddChild( node( wxT( "source" ), sourceFileName.GetFullName() ) ); xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xcomment->AddAttribute( wxT("number"), wxT("1") ); xcomment->AddAttribute( wxT( "value" ), tb.GetComment1() ); xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xcomment->AddAttribute( wxT("number"), wxT("2") ); xcomment->AddAttribute( wxT( "value" ), tb.GetComment2() ); xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xcomment->AddAttribute( wxT("number"), wxT("3") ); xcomment->AddAttribute( wxT( "value" ), tb.GetComment3() ); xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xcomment->AddAttribute( wxT("number"), wxT("4") ); xcomment->AddAttribute( wxT( "value" ), tb.GetComment4() ); } return xdesign; }
void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) { static wxPoint itemPosition; // the actual position of the matched item. SCH_SHEET_LIST schematic; wxString msg; SCH_FIND_REPLACE_DATA searchCriteria; bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR ); SCH_FIND_COLLECTOR_DATA data; searchCriteria.SetFlags( aEvent.GetFlags() ); searchCriteria.SetFindString( aEvent.GetFindString() ); searchCriteria.SetReplaceString( aEvent.GetReplaceString() ); if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE ) { if( m_foundItems.GetCount() == 0 ) return; } else if( m_foundItems.IsSearchRequired( searchCriteria ) ) { if( aEvent.GetFlags() & FR_CURRENT_SHEET_ONLY && g_RootSheet->CountSheets() > 1 ) { m_foundItems.Collect( searchCriteria, m_CurrentSheet ); } else { m_foundItems.Collect( searchCriteria ); } } else { EDA_ITEM* currentItem = m_foundItems.GetItem( data ); if( currentItem != NULL ) currentItem->SetForceVisible( false ); m_foundItems.UpdateIndex(); } if( m_foundItems.GetItem( data ) != NULL ) { wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() ); SCH_SHEET_PATH* sheet = schematic.GetSheet( data.GetSheetPath() ); wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() ); // Make the item temporarily visible just in case it's hide flag is set. This // has no effect on objects that don't support hiding. If this is a close find // dialog event, clear the temporary visibility flag. if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE ) m_foundItems.GetItem( data )->SetForceVisible( false ); else m_foundItems.GetItem( data )->SetForceVisible( true ); if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() ) { sheet->LastScreen()->SetZoom( GetScreen()->GetZoom() ); *m_CurrentSheet = *sheet; m_CurrentSheet->UpdateAllScreenReferences(); SetScreen( sheet->LastScreen() ); } sheet->LastScreen()->SetCrossHairPosition( data.GetPosition() ); RedrawScreen( data.GetPosition(), warpCursor ); msg = m_foundItems.GetText(); if( aEvent.GetFlags() & FR_SEARCH_REPLACE ) aEvent.SetFlags( aEvent.GetFlags() | FR_REPLACE_ITEM_FOUND ); } else { if( aEvent.GetFlags() & FR_SEARCH_REPLACE ) aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND ); msg.Printf( _( "No item found matching %s." ), GetChars( aEvent.GetFindString() ) ); } SetStatusText( msg ); }
void SCH_EDIT_FRAME::backAnnotateFootprints( const std::string& aChangedSetOfReferences ) throw( IO_ERROR, boost::bad_pointer ) { // Build a flat list of components in schematic: SCH_REFERENCE_LIST refs; SCH_SHEET_LIST sheets; bool isChanged = false; sheets.GetComponents( Prj().SchLibs(), refs, false ); DSNLEXER lexer( aChangedSetOfReferences, FROM_UTF8( __func__ ) ); PTREE doc; try { Scan( &doc, &lexer ); #if defined(DEBUG) && 0 STRING_FORMATTER sf; Format( &sf, 0, 0, doc ); printf( "%s: '%s'\n", __func__, sf.GetString().c_str() ); #endif CPTREE& back_anno = doc.get_child( "back_annotation" ); wxString footprint; for( PTREE::const_iterator ref = back_anno.begin(); ref != back_anno.end(); ++ref ) { wxASSERT( ref->first == "ref" ); wxString reference = (UTF8&) ref->second.front().first; // Ensure the "fpid" node contains a footprint name, // and get it if exists if( ref->second.get_child( "fpid" ).size() ) { wxString tmp = (UTF8&) ref->second.get_child( "fpid" ).front().first; footprint = tmp; } else footprint.Empty(); // DBG( printf( "%s: ref:%s fpid:%s\n", __func__, TO_UTF8( reference ), TO_UTF8( footprint ) ); ) // Search the component in the flat list for( unsigned ii = 0; ii < refs.GetCount(); ++ii ) { if( Cmp_KEEPCASE( reference, refs[ii].GetRef() ) == 0 ) { // We have found a candidate. // Note: it can be not unique (multiple parts per package) // So we *do not* stop the search here SCH_COMPONENT* component = refs[ii].GetComp(); SCH_FIELD* fpfield = component->GetField( FOOTPRINT ); const wxString& oldfp = fpfield->GetText(); if( !oldfp && fpfield->IsVisible() ) { fpfield->SetVisible( false ); } // DBG( printf("%s: ref:%s fpid:%s\n", __func__, TO_UTF8( refs[ii].GetRef() ), TO_UTF8( footprint ) );) if( oldfp != footprint ) isChanged = true; fpfield->SetText( footprint ); } } } } catch( const PTREE_ERROR& ex ) { // remap the exception to something the caller is likely to understand. THROW_IO_ERROR( ex.what() ); } if( isChanged ) OnModify(); }