/*---------------------------------------------------------------------- | NPT_String::ToInteger +---------------------------------------------------------------------*/ NPT_Result NPT_String::ToInteger(NPT_UInt64& value, bool relaxed) const { return NPT_ParseInteger64U(GetChars(), value, relaxed); }
void DIALOG_DRC_CONTROL::OnStartdrcClick( wxCommandEvent& event ) { wxString reportName; bool make_report = m_CreateRptCtrl->IsChecked(); if( make_report ) // Create a rpt file { reportName = m_RptFilenameCtrl->GetValue(); if( reportName.IsEmpty() ) { wxCommandEvent dummy; OnButtonBrowseRptFileClick( dummy ); } if( !reportName.IsEmpty() ) reportName = makeValidFileNameReport(); } SetDrcParmeters(); m_tester->SetSettings( true, // Pad to pad DRC test enabled true, // unconnected pads DRC test enabled true, // DRC test for zones enabled true, // DRC test for keepout areas enabled m_cbCourtyardOverlap->GetValue(), m_cbCourtyardMissing->GetValue(), reportName, make_report ); DelDRCMarkers(); wxBeginBusyCursor(); // run all the tests, with no UI at this time. m_Messages->Clear(); wxSafeYield(); // Allows time slice to refresh the m_Messages window m_brdEditor->GetBoard()->m_Status_Pcb = 0; // Force full connectivity and ratsnest recalculations m_tester->RunTests(m_Messages); m_Notebook->ChangeSelection( 0 ); // display the 1at tab "...Markers ..." // Generate the report if( !reportName.IsEmpty() ) { if( writeReport( reportName ) ) { wxString msg; msg.Printf( _( "Report file \"%s\" created" ), GetChars( reportName ) ); wxString caption( _( "Disk File Report Completed" ) ); wxMessageDialog popupWindow( this, msg, caption ); popupWindow.ShowModal(); } else DisplayError( this, wxString::Format( _( "Unable to create report file \"%s\" "), GetChars( reportName ) ) ); } wxEndBusyCursor(); RedrawDrawPanel(); }
MODULE* PCB_BASE_FRAME::LoadModuleFromLibrary( const wxString& aLibrary, FP_LIB_TABLE* aTable, bool aUseFootprintViewer, wxDC* aDC ) { MODULE* module = NULL; wxPoint curspos = GetCrossHairPosition(); wxString moduleName, keys; wxString libName = aLibrary; bool allowWildSeach = true; static wxArrayString HistoryList; static wxString lastComponentName; // Ask for a component name or key words DIALOG_GET_COMPONENT dlg( this, HistoryList, _( "Load Footprint" ), aUseFootprintViewer ); dlg.SetComponentName( lastComponentName ); if( dlg.ShowModal() == wxID_CANCEL ) return NULL; if( dlg.m_GetExtraFunction ) { // SelectFootprintFromLibBrowser() returns the "full" footprint name, i.e. // <lib_name>/<footprint name> or FPID format "lib_name:fp_name:rev#" moduleName = SelectFootprintFromLibBrowser(); } else { moduleName = dlg.GetComponentName(); } if( moduleName.IsEmpty() ) // Cancel command { m_canvas->MoveCursorToCrossHair(); return NULL; } if( dlg.IsKeyword() ) // Selection by keywords { allowWildSeach = false; keys = moduleName; moduleName = SelectFootprint( this, libName, wxEmptyString, keys, aTable ); if( moduleName.IsEmpty() ) // Cancel command { m_canvas->MoveCursorToCrossHair(); return NULL; } } else if( moduleName.Contains( wxT( "?" ) ) || moduleName.Contains( wxT( "*" ) ) ) // Selection wild card { allowWildSeach = false; moduleName = SelectFootprint( this, libName, moduleName, wxEmptyString, aTable ); if( moduleName.IsEmpty() ) { m_canvas->MoveCursorToCrossHair(); return NULL; // Cancel command. } } FPID fpid; wxCHECK_MSG( fpid.Parse( moduleName ) < 0, NULL, wxString::Format( wxT( "Could not parse FPID string '%s'." ), GetChars( moduleName ) ) ); try { module = loadFootprint( fpid ); } catch( const IO_ERROR& ioe ) { wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ), fpid.Format().c_str(), GetChars( ioe.errorText ) ); } if( !module && allowWildSeach ) // Search with wild card { allowWildSeach = false; wxString wildname = wxChar( '*' ) + moduleName + wxChar( '*' ); moduleName = wildname; moduleName = SelectFootprint( this, libName, moduleName, wxEmptyString, aTable ); if( moduleName.IsEmpty() ) { m_canvas->MoveCursorToCrossHair(); return NULL; // Cancel command. } else { FPID fpid; wxCHECK_MSG( fpid.Parse( moduleName ) < 0, NULL, wxString::Format( wxT( "Could not parse FPID string '%s'." ), GetChars( moduleName ) ) ); try { module = loadFootprint( fpid ); } catch( const IO_ERROR& ioe ) { wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ), fpid.Format().c_str(), GetChars( ioe.errorText ) ); } } } SetCrossHairPosition( curspos ); m_canvas->MoveCursorToCrossHair(); if( module ) { GetBoard()->Add( module, ADD_APPEND ); lastComponentName = moduleName; AddHistoryComponentName( HistoryList, moduleName ); module->SetFlags( IS_NEW ); module->SetLink( 0 ); if( IsGalCanvasActive() ) module->SetPosition( wxPoint( 0, 0 ) ); // cursor in GAL may not be initialized at the moment else module->SetPosition( curspos ); module->SetTimeStamp( GetNewTimeStamp() ); GetBoard()->m_Status_Pcb = 0; // Put it on FRONT layer, // (Can be stored flipped if the lib is an archive built from a board) if( module->IsFlipped() ) module->Flip( module->GetPosition() ); // Place it in orientation 0, // even if it is not saved with orientation 0 in lib // (Can happen if the lib is an archive built from a board) Rotate_Module( NULL, module, 0, false ); RecalculateAllTracksNetcode(); if( aDC ) module->Draw( m_canvas, aDC, GR_OR ); } return module; }
/** * Function Append_Track_Width_List * creates a wxMenu * which shows the last used track widths and via diameters * @return a pointer to the menu */ static wxMenu* Append_Track_Width_List( BOARD* aBoard ) { wxString msg; wxMenu* trackwidth_menu; wxString value; trackwidth_menu = new wxMenu; trackwidth_menu->Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Auto Width" ), _( "Use the track width when starting on a track, otherwise the current track width" ), true ); if( aBoard->GetDesignSettings().m_UseConnectedTrackWidth ) trackwidth_menu->Check( ID_POPUP_PCB_SELECT_AUTO_WIDTH, true ); if( aBoard->GetViaSizeIndex() != 0 || aBoard->GetTrackWidthIndex() != 0 || aBoard->GetDesignSettings().m_UseConnectedTrackWidth ) trackwidth_menu->Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Netclass Values" ), _( "Use track and via sizes from their Netclass values" ), true ); for( unsigned ii = 0; ii < aBoard->m_TrackWidthList.size(); ii++ ) { value = ReturnStringFromValue( g_UserUnit, aBoard->m_TrackWidthList[ii], true ); msg.Printf( _( "Track %s" ), GetChars( value ) ); if( ii == 0 ) msg << _( " uses NetClass" ); trackwidth_menu->Append( ID_POPUP_PCB_SELECT_WIDTH1 + ii, msg, wxEmptyString, true ); } trackwidth_menu->AppendSeparator(); for( unsigned ii = 0; ii < aBoard->m_ViasDimensionsList.size(); ii++ ) { value = ReturnStringFromValue( g_UserUnit, aBoard->m_ViasDimensionsList[ii].m_Diameter, true ); wxString drill = ReturnStringFromValue( g_UserUnit, aBoard->m_ViasDimensionsList[ii].m_Drill, true ); if( aBoard->m_ViasDimensionsList[ii].m_Drill <= 0 ) { msg.Printf( _( "Via %s" ), GetChars( value ) ); } else { msg.Printf( _( "Via %s, drill %s" ), GetChars( value ), GetChars( drill ) ); } if( ii == 0 ) msg << _( " uses NetClass" ); trackwidth_menu->Append( ID_POPUP_PCB_SELECT_VIASIZE1 + ii, msg, wxEmptyString, true ); } return trackwidth_menu; }
int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName ) { wxFileName fn; if( !aFullFileName.IsEmpty() ) { fn = m_NetlistFileName; fn.SetExt( ComponentFileExtension ); } else { wxFileDialog dlg( this, _( "Save Component Footprint Link File" ), wxEmptyString, _( "Unnamed file" ), ComponentFileWildcard, wxFD_SAVE ); if( dlg.ShowModal() == wxID_CANCEL ) return -1; fn = dlg.GetPath(); if( !fn.HasExt() ) fn.SetExt( ComponentFileExtension ); // Save the project specific footprint library table. if( !m_footprintLibTable->IsEmpty( false ) ) { wxFileName fpLibFileName = fn; fpLibFileName.ClearExt(); fpLibFileName.SetName( FP_LIB_TABLE::GetFileName() ); if( fpLibFileName.FileExists() && IsOK( this, _( "A footprint library table already exists in this path.\n\nDo " "you want to overwrite it?" ) ) ) { try { m_footprintLibTable->Save( fpLibFileName ); } catch( IO_ERROR& ioe ) { DisplayError( this, wxString::Format( _( "An error occurred attempting to save the " "footprint library table <%s>\n\n%s" ), GetChars( fpLibFileName.GetFullPath() ), GetChars( ioe.errorText ) ) ); } } } } if( !IsWritable( fn.GetFullPath() ) ) return 0; if( WriteComponentLinkFile( fn.GetFullPath() ) == 0 ) { DisplayError( this, _( "Unable to create component footprint link file (.cmp)" ) ); return 0; } wxString msg; msg.Printf( _("File %s saved"), GetChars( fn.GetFullPath() ) ); SetStatusText( msg ); return 1; }
/** * Function ClipAreaPolygon * Process an area that has been modified, by clipping its polygon against itself. * This may change the number and order of copper areas in the net. * @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new areas pickers (useful in * undo commands) can be NULL * @param aCurrArea = the zone to process * @param bMessageBoxInt == true, shows message when clipping occurs. * @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs. * @param bRetainArcs = true to handle arcs (not really used in KiCad) * @return: * -1 if arcs intersect other sides, so polygon can't be clipped * 0 if no intersecting sides * 1 if intersecting sides * Also sets areas->utility1 flags if areas are modified */ int BOARD::ClipAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE_CONTAINER* aCurrArea, bool bMessageBoxArc, bool bMessageBoxInt, bool bRetainArcs ) { CPolyLine* curr_polygon = aCurrArea->m_Poly; int test = TestAreaPolygon( aCurrArea ); // this sets utility2 flag if( test == -1 && !bRetainArcs ) test = 1; if( test == -1 ) { // arc intersections, don't clip unless bRetainArcs == false if( bMessageBoxArc && bDontShowSelfIntersectionArcsWarning == false ) { wxString str; str.Printf( wxT( "Area %08lX of net \"%s\" has arcs intersecting other sides.\n" ), aCurrArea->GetTimeStamp(), GetChars( aCurrArea->m_Netname ) ); str += wxT( "This may cause problems with other editing operations,\n" ); str += wxT( "such as adding cutouts. It can't be fixed automatically.\n" ); str += wxT( "Manual correction is recommended." ); wxMessageBox( str ); } return -1; // arcs intersect with other sides, error } // mark all areas as unmodified except this one for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ ) m_ZoneDescriptorList[ia]->utility = 0; aCurrArea->utility = 1; if( test == 1 ) { // non-arc intersections, clip the polygon if( bMessageBoxInt && bDontShowSelfIntersectionWarning == false ) { wxString str; str.Printf( wxT( "Area %08lX of net \"%s\" is self-intersecting and will be clipped.\n" ), aCurrArea->GetTimeStamp(), GetChars( aCurrArea->m_Netname ) ); str += wxT( "This may result in splitting the area.\n" ); str += wxT( "If the area is complex, this may take a few seconds." ); wxMessageBox( str ); // bDontShowSelfIntersectionWarning = dlg.bDontShowBoxState; } } //** TODO test for cutouts outside of area //** if( test == 1 ) { std::vector<CPolyLine*>* pa = new std::vector<CPolyLine*>; curr_polygon->UnHatch(); int n_poly = aCurrArea->m_Poly->NormalizeAreaOutlines( pa, bRetainArcs ); // i.e if clipping has created some polygons, we must add these new copper areas. if( n_poly > 1 ) { ZONE_CONTAINER* NewArea; for( int ip = 1; ip < n_poly; ip++ ) { // create new copper area and copy poly into it CPolyLine* new_p = (*pa)[ip - 1]; NewArea = AddArea( aNewZonesList, aCurrArea->GetNet(), aCurrArea->GetLayer(), wxPoint(0, 0), CPolyLine::NO_HATCH ); // remove the poly that was automatically created for the new area // and replace it with a poly from NormalizeAreaOutlines delete NewArea->m_Poly; NewArea->m_Poly = new_p; NewArea->m_Poly->Hatch(); NewArea->utility = 1; } } curr_polygon->Hatch(); delete pa; } return test; }
void PCB_EDIT_FRAME::ReadMacros() { wxString str; wxFileName fn; fn = GetBoard()->GetFileName(); fn.SetExt( MacrosFileExtension ); wxFileDialog dlg( this, _( "Read Macros File" ), fn.GetPath(), fn.GetFullName(), MacrosFileWildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) return; if( !wxFileExists( dlg.GetPath() ) ) { wxString msg; msg.Printf( _( "File %s not found" ), GetChars( dlg.GetPath() ) ); DisplayError( this, msg ); return; } wxXmlDocument xml; xml.SetFileEncoding( wxT( "UTF-8" ) ); if( !xml.Load( dlg.GetFilename() ) ) return; XNODE *macrosNode = (XNODE*) xml.GetRoot()->GetChildren(); while( macrosNode ) { int number = -1; if( macrosNode->GetName() == wxT( "macros" ) ) { number = wxAtoi( macrosNode->GetAttribute( wxT( "number" ), wxT( "-1" ) ) ); if( number >= 0 && number < 10 ) { m_Macros[number].m_Record.clear(); XNODE *hotkeyNode = (XNODE*) macrosNode->GetChildren(); while( hotkeyNode ) { if( hotkeyNode->GetName() == wxT( "hotkey" ) ) { int x = wxAtoi( hotkeyNode->GetAttribute( wxT( "x" ), wxT( "0" ) ) ); int y = wxAtoi( hotkeyNode->GetAttribute( wxT( "y" ), wxT( "0" ) ) ); int hk = wxAtoi( hotkeyNode->GetAttribute( wxT( "hkcode" ), wxT( "0" ) ) ); MACROS_RECORD macros_record; macros_record.m_HotkeyCode = hk; macros_record.m_Position.x = x; macros_record.m_Position.y = y; m_Macros[number].m_Record.push_back( macros_record ); } hotkeyNode = (XNODE*) hotkeyNode->GetNext(); } } } macrosNode = (XNODE*) macrosNode->GetNext(); } }
PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : PCB_BASE_FRAME( parent, PCB_FRAME_TYPE, title, pos, size, style, PCB_EDIT_FRAME_NAME ) { m_FrameName = PCB_EDIT_FRAME_NAME; m_showBorderAndTitleBlock = true; // true to display sheet references m_showAxis = false; // true to display X and Y axis m_showOriginAxis = true; m_showGridAxis = true; m_SelTrackWidthBox = NULL; m_SelViaSizeBox = NULL; m_SelLayerBox = NULL; m_show_microwave_tools = false; m_show_layer_manager_tools = true; m_HotkeysZoomAndGridList = g_Board_Editor_Hokeys_Descr; m_hasAutoSave = true; m_RecordingMacros = -1; m_microWaveToolBar = NULL; m_useCmpFileForFpNames = true; m_footprintLibTable = NULL; m_globalFootprintTable = NULL; m_rotationAngle = 900; #ifdef KICAD_SCRIPTING_WXPYTHON m_pythonPanel = NULL; #endif for ( int i = 0; i < 10; i++ ) m_Macros[i].m_Record.clear(); SetBoard( new BOARD() ); if( GetGalCanvas() ) { ViewReloadBoard( m_Pcb ); // update the tool manager with the new board and its view. if( m_toolManager ) m_toolManager->SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), GetGalCanvas()->GetViewControls(), this ); } // Create the PCB_LAYER_WIDGET *after* SetBoard(): wxFont font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); int pointSize = font.GetPointSize(); int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y ); // printf( "pointSize:%d 80%%:%d\n", pointSize, (pointSize*8)/10 ); if( screenHeight <= 900 ) pointSize = (pointSize * 8) / 10; m_Layers = new PCB_LAYER_WIDGET( this, GetCanvas(), pointSize ); m_drc = new DRC( this ); // these 2 objects point to each other wxIcon icon; icon.CopyFromBitmap( KiBitmap( icon_pcbnew_xpm ) ); SetIcon( icon ); SetScreen( new PCB_SCREEN( GetPageSettings().GetSizeIU() ) ); // PCB drawings start in the upper left corner. GetScreen()->m_Center = false; // LoadSettings() *after* creating m_LayersManager, because LoadSettings() // initialize parameters in m_LayersManager LoadSettings(); // Be sure options are updated m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill; m_DisplayPadFill = DisplayOpt.DisplayPadFill; m_DisplayViaFill = DisplayOpt.DisplayViaFill; m_DisplayPadNum = DisplayOpt.DisplayPadNum; m_DisplayModEdge = DisplayOpt.DisplayModEdge; m_DisplayModText = DisplayOpt.DisplayModText; SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); GetScreen()->AddGrid( m_UserGridSize, m_UserGridUnit, ID_POPUP_GRID_USER ); GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); if( m_canvas ) m_canvas->SetEnableBlockCommands( true ); ReCreateMenuBar(); ReCreateHToolbar(); ReCreateAuxiliaryToolbar(); ReCreateVToolbar(); ReCreateOptToolbar(); ReCreateMicrowaveVToolbar(); m_auimgr.SetManagedWindow( this ); EDA_PANEINFO horiz; horiz.HorizontalToolbarPane(); EDA_PANEINFO vert; vert.VerticalToolbarPane(); EDA_PANEINFO mesg; mesg.MessageToolbarPane(); // Create a wxAuiPaneInfo for the Layers Manager, not derived from the template. // LAYER_WIDGET is floatable, but initially docked at far right EDA_PANEINFO lyrs; lyrs.LayersToolbarPane(); lyrs.MinSize( m_Layers->GetBestSize() ); // updated in ReFillLayerWidget lyrs.BestSize( m_Layers->GetBestSize() ); lyrs.Caption( _( "Visibles" ) ); if( m_mainToolBar ) // The main horizontal toolbar { m_auimgr.AddPane( m_mainToolBar, wxAuiPaneInfo( horiz ).Name( wxT( "m_mainToolBar" ) ).Top().Row( 0 ) ); } if( m_auxiliaryToolBar ) // the auxiliary horizontal toolbar, that shows track and via sizes, zoom ...) { m_auimgr.AddPane( m_auxiliaryToolBar, wxAuiPaneInfo( horiz ).Name( wxT( "m_auxiliaryToolBar" ) ).Top().Row( 1 ) ); } if( m_microWaveToolBar ) // The auxiliary vertical right toolbar (currently microwave tools) m_auimgr.AddPane( m_microWaveToolBar, wxAuiPaneInfo( vert ).Name( wxT( "m_microWaveToolBar" ) ).Right().Layer( 1 ).Position(1).Hide() ); if( m_drawToolBar ) // The main right vertical toolbar m_auimgr.AddPane( m_drawToolBar, wxAuiPaneInfo( vert ).Name( wxT( "m_VToolBar" ) ).Right().Layer( 2 ) ); // Add the layer manager ( most right side of pcbframe ) m_auimgr.AddPane( m_Layers, lyrs.Name( wxT( "m_LayersManagerToolBar" ) ).Right().Layer( 3 ) ); if( m_optionsToolBar ) // The left vertical toolbar (fast acces display options of Pcbnew) { m_auimgr.AddPane( m_optionsToolBar, wxAuiPaneInfo( vert ).Name( wxT( "m_optionsToolBar" ) ).Left().Layer(1) ); m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).Show( m_show_layer_manager_tools ); m_auimgr.GetPane( wxT( "m_microWaveToolBar" ) ).Show( m_show_microwave_tools ); } if( m_canvas ) m_auimgr.AddPane( m_canvas, wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() ); if( GetGalCanvas() ) m_auimgr.AddPane( (wxWindow*) GetGalCanvas(), wxAuiPaneInfo().Name( wxT( "DrawFrameGal" ) ).CentrePane().Hide() ); if( m_messagePanel ) m_auimgr.AddPane( m_messagePanel, wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom().Layer(10) ); #ifdef KICAD_SCRIPTING_WXPYTHON // Add the scripting panel EDA_PANEINFO pythonAuiInfo; pythonAuiInfo.ScriptingToolbarPane(); pythonAuiInfo.Caption( wxT( "Python Scripting" ) ); pythonAuiInfo.MinSize( wxSize( 200, 100 ) ); pythonAuiInfo.BestSize( wxSize( GetClientSize().x/2, 200 ) ); pythonAuiInfo.Hide(); m_pythonPanel = CreatePythonShellWindow( this ); m_auimgr.AddPane( m_pythonPanel, pythonAuiInfo.Name( wxT( "PythonPanel" ) ).Bottom().Layer(9) ); m_pythonPanelHidden = true; #endif ReFillLayerWidget(); // this is near end because contents establish size m_Layers->ReFillRender(); // Update colors in Render after the config is read syncLayerWidgetLayer(); m_auimgr.Update(); if( m_globalFootprintTable == NULL ) { try { m_globalFootprintTable = new FP_LIB_TABLE(); if( !FP_LIB_TABLE::LoadGlobalTable( *m_globalFootprintTable ) ) { DisplayInfoMessage( this, wxT( "You have run Pcbnew for the first time using the " "new footprint library table method for finding " "footprints. Pcbnew has either copied the default " "table or created an empty table in your home " "folder. You must first configure the library " "table to include all footprint libraries not " "included with KiCad. See the \"Footprint Library " "Table\" section of the CvPcb documentation for " "more information." ) ); } } catch( IO_ERROR ioe ) { wxString msg; msg.Printf( _( "An error occurred attempting to load the global footprint library " "table:\n\n%s" ), GetChars( ioe.errorText ) ); DisplayError( this, msg ); } } setupTools(); }
/* Add some X2 attributes to the file header, as defined in the * Gerber file format specification J4 and "Revision 2015.06" */ void AddGerberX2Attribute( PLOTTER * aPlotter, const BOARD *aBoard, LAYER_NUM aLayer ) { wxString text; // Creates the TF,.GenerationSoftware. Format is: // %TF,.GenerationSoftware,<vendor>,<application name>[,<application version>]*% text.Printf( wxT( "%%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() ); aPlotter->AddLineToHeader( text ); // creates the TF.CreationDate ext: // The attribute value must conform to the full version of the ISO 8601 // date and time format, including time and time zone. Note that this is // the date the Gerber file was effectively created, // not the time the project of PCB was started wxDateTime date( wxDateTime::GetTimeNow() ); // Date format: see http://www.cplusplus.com/reference/ctime/strftime wxString msg = date.Format( wxT( "%z" ) ); // Extract the time zone offset // The time zone offset format is + (or -) mm or hhmm (mm = number of minutes, hh = number of hours) // we want +(or -) hh:mm if( msg.Len() > 3 ) msg.insert( 3, ":", 1 ), text.Printf( wxT( "%%TF.CreationDate,%s%s*%%" ), GetChars( date.FormatISOCombined() ), GetChars( msg ) ); aPlotter->AddLineToHeader( text ); // Creates the TF,.ProjectId. Format is (from Gerber file format doc): // %TF.ProjectId,<project id>,<project GUID>,<revision id>*% // <project id> is the name of the project, restricted to basic ASCII symbols only, // and comma not accepted // All illegal chars will be replaced by underscore // <project GUID> is a 32 hexadecimal digits string which is an unique id of a project. // This is a random 128-bit number expressed in 32 hexadecimal digits. // See en.wikipedia.org/wiki/GUID for more information // However Kicad does not handle such a project GUID, so it is built from the board name // Rem: <project id> accepts only ASCII 7 code (only basic ASCII codes are allowed in gerber files). wxFileName fn = aBoard->GetFileName(); msg = fn.GetFullName(); wxString guid; // Build a 32 digits GUID from the board name: for( unsigned ii = 0; ii < msg.Len(); ii++ ) { int cc1 = int( msg[ii] ) & 0x0F; int cc2 = ( int( msg[ii] ) >> 4) & 0x0F; guid << wxString::Format( wxT( "%X%X" ), cc2, cc1 ); if( guid.Len() >= 32 ) break; } // guid has 32 digits, so add missing digits int cnt = 32 - guid.Len(); if( cnt > 0 ) guid.Append( '0', cnt ); // build the <project id> string: this is the board short filename (without ext) // and all non ASCII chars and comma are replaced by '_' msg = fn.GetName(); msg.Replace( wxT( "," ), wxT( "_" ) ); // build the <rec> string. All non ASCII chars and comma are replaced by '_' wxString rev = ((BOARD*)aBoard)->GetTitleBlock().GetRevision(); rev.Replace( wxT( "," ), wxT( "_" ) ); if( rev.IsEmpty() ) rev = wxT( "rev?" ); text.Printf( wxT( "%%TF.ProjectId,%s,%s,%s*%%" ), msg.ToAscii(), GetChars( guid ), rev.ToAscii() ); aPlotter->AddLineToHeader( text ); // Add the TF.FileFunction text = GetGerberFileFunctionAttribute( aBoard, aLayer, false ); aPlotter->AddLineToHeader( text ); // Add the TF.FilePolarity (for layers which support that) text = GetGerberFilePolarityAttribute( aLayer ); if( !text.IsEmpty() ) aPlotter->AddLineToHeader( text ); }
// Generate the drill map of the board void DIALOG_GENDRILL::GenDrillMap( const wxString aFullFileNameWithoutExt, EXCELLON_WRITER& aExcellonWriter, PlotFormat format ) { wxString ext, wildcard; /* Init extension */ switch( format ) { case PLOT_FORMAT_HPGL: ext = HPGL_PLOTTER::GetDefaultFileExtension(); wildcard = _( "HPGL plot files (.plt)|*.plt" ); break; case PLOT_FORMAT_POST: ext = PS_PLOTTER::GetDefaultFileExtension(); wildcard = PSFileWildcard; break; case PLOT_FORMAT_GERBER: ext = GERBER_PLOTTER::GetDefaultFileExtension(); wildcard = _( "Gerber files (.pho)|*.pho" ); break; case PLOT_FORMAT_DXF: ext = DXF_PLOTTER::GetDefaultFileExtension(); wildcard = _( "DXF files (.dxf)|*.dxf" ); break; case PLOT_FORMAT_SVG: ext = SVG_PLOTTER::GetDefaultFileExtension(); wildcard = SVGFileWildcard; break; case PLOT_FORMAT_PDF: ext = PDF_PLOTTER::GetDefaultFileExtension(); wildcard = PdfFileWildcard; break; default: wxLogMessage( wxT( "DIALOG_GENDRILL::GenDrillMap() error, fmt % unkown" ), format ); return; } // Add file name extension wxString fullFilename = aFullFileNameWithoutExt; fullFilename << wxT(".") << ext; bool success = aExcellonWriter.GenDrillMapFile( fullFilename, m_parent->GetPageSettings(), format ); wxString msg; if( ! success ) { msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fullFilename ) ); m_messagesBox->AppendText( msg ); return; } else { msg.Printf( _( "Plot: %s OK\n" ), GetChars( fullFilename ) ); m_messagesBox->AppendText( msg ); } }
/* Prepare the right-click pullup menu. * The menu already has a list of zoom commands. */ bool GERBVIEW_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* aPopMenu ) { GERBER_DRAW_ITEM* currItem = (GERBER_DRAW_ITEM*) GetScreen()->GetCurItem(); wxString msg; bool BlockActive = !GetScreen()->m_BlockLocate.IsIdle(); bool busy = currItem && currItem->GetFlags(); // Do not initiate a start block validation on menu. m_canvas->SetCanStartBlock( -1 ); // Simple location of elements where possible. if( !busy ) { currItem = Locate( aPosition, CURSEUR_OFF_GRILLE ); busy = currItem && currItem->GetFlags(); } // If command in progress, end command. if( GetToolId() != ID_NO_TOOL_SELECTED ) { if( busy ) AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel" ), KiBitmap( cancel_xpm ) ); else AddMenuItem( aPopMenu, ID_POPUP_CLOSE_CURRENT_TOOL, _( "End Tool" ), KiBitmap( cursor_xpm ) ); aPopMenu->AppendSeparator(); } else { if( busy || BlockActive ) { if( BlockActive ) { AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel Block" ), KiBitmap( cancel_xpm ) ); aPopMenu->AppendSeparator(); AddMenuItem( aPopMenu, ID_POPUP_PLACE_BLOCK, _( "Place Block" ), KiBitmap( checked_ok_xpm ) ); } else { AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel" ), KiBitmap( cancel_xpm ) ); } aPopMenu->AppendSeparator(); } } if( BlockActive ) return true; if( currItem ) { GetScreen()->SetCurItem( currItem ); bool add_separator = false; // Now, display a context menu // to allow highlighting items which share the same attributes // as the selected item (net attributes and aperture attributes) const GBR_NETLIST_METADATA& net_attr = currItem->GetNetAttributes(); if( ( net_attr.m_NetAttribType & GBR_NETLIST_METADATA::GBR_NETINFO_PAD ) || ( net_attr.m_NetAttribType & GBR_NETLIST_METADATA::GBR_NETINFO_CMP ) ) { AddMenuItem( aPopMenu, ID_HIGHLIGHT_CMP_ITEMS, wxString::Format( _( "Highlight items of component \"%s\"" ), GetChars( net_attr.m_Cmpref ) ), KiBitmap( file_footprint_xpm ) ); add_separator = true; } if( ( net_attr.m_NetAttribType & GBR_NETLIST_METADATA::GBR_NETINFO_NET ) ) { AddMenuItem( aPopMenu, ID_HIGHLIGHT_NET_ITEMS, wxString::Format( _( "Highlight items of net \"%s\"" ), GetChars( net_attr.m_Netname ) ), KiBitmap( general_ratsnest_xpm ) ); add_separator = true; } D_CODE* apertDescr = currItem->GetDcodeDescr(); if( apertDescr && !apertDescr->m_AperFunction.IsEmpty() ) { AddMenuItem( aPopMenu, ID_HIGHLIGHT_APER_ATTRIBUTE_ITEMS, wxString::Format( _( "Highlight aperture type \"%s\"" ), GetChars( apertDescr->m_AperFunction ) ), KiBitmap( flag_xpm ) ); add_separator = true; } if( add_separator ) aPopMenu->AppendSeparator(); } AddMenuItem( aPopMenu, ID_HIGHLIGHT_REMOVE_ALL, _( "Clear highlight" ), KiBitmap( gerbview_clear_layers_xpm ) ); aPopMenu->AppendSeparator(); return true; }
/** * Function GenDrillAndMapFiles * Calls the functions to create EXCELLON drill files and/or drill map files * >When all holes are through holes, only one excellon file is created. * >When there are some partial holes (some blind or buried vias), * one excellon file is created, for all plated through holes, * and one file per layer pair, which have one or more holes, excluding * through holes, already in the first file. * one file for all Not Plated through holes */ void DIALOG_GENDRILL::GenDrillAndMapFiles(bool aGenDrill, bool aGenMap) { wxString layer_extend; /* added to the Board FileName to * create FullFileName (= Board * FileName + layer pair names) */ wxString msg; bool hasBuriedVias = false; /* If true, drill files are created * layer pair by layer pair for * buried vias */ int layer1 = LAYER_N_BACK; int layer2 = LAYER_N_FRONT; bool gen_through_holes = true; bool gen_NPTH_holes = false; wxString currentWD = ::wxGetCwd(); UpdateConfig(); // set params and Save drill options m_parent->ClearMsgPanel(); if( m_microViasCount || m_blindOrBuriedViasCount ) hasBuriedVias = true; EXCELLON_WRITER excellonWriter( m_parent->GetBoard(), m_FileDrillOffset ); excellonWriter.SetFormat( !m_UnitDrillIsInch, (EXCELLON_WRITER::zeros_fmt) m_ZerosFormat, m_Precision.m_lhs, m_Precision.m_rhs ); excellonWriter.SetOptions( m_Mirror, m_MinimalHeader, m_FileDrillOffset ); wxFileName fn; for( ; ; ) { excellonWriter.BuildHolesList( layer1, layer2, gen_through_holes ? false : true, gen_NPTH_holes ); if( excellonWriter.GetHolesCount() > 0 ) // has holes? { fn = m_parent->GetBoard()->GetFileName(); layer_extend.Empty(); if( gen_NPTH_holes ) { layer_extend << wxT( "-NPTH" ); } else if( !gen_through_holes ) { if( layer1 == LAYER_N_BACK ) layer_extend << wxT( "-back" ); else layer_extend << wxT( "-inner" ) << layer1; if( layer2 == LAYER_N_FRONT ) layer_extend << wxT( "-front" ); else layer_extend << wxT( "-inner" ) << layer2; } fn.SetName( fn.GetName() + layer_extend ); wxString defaultPath = m_plotOpts.GetOutputDirectory(); if( defaultPath.IsEmpty() ) defaultPath = ::wxGetCwd(); fn.SetPath( defaultPath ); if( aGenDrill ) { fn.SetExt( DrillFileExtension ); wxString fullFilename = fn.GetFullPath(); FILE* file = wxFopen( fullFilename, wxT( "w" ) ); if( file == 0 ) { msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fullFilename ) ); m_messagesBox->AppendText( msg ); break; } else { msg.Printf( _( "Plot: %s OK\n" ), GetChars( fullFilename ) ); m_messagesBox->AppendText( msg ); } excellonWriter.CreateDrillFile( file ); } if( aGenMap ) { const PlotFormat filefmt[6] = { // Keep these format ids in the same order than m_Choice_Drill_Map choices PLOT_FORMAT_HPGL, PLOT_FORMAT_POST, PLOT_FORMAT_GERBER, PLOT_FORMAT_DXF, PLOT_FORMAT_SVG, PLOT_FORMAT_PDF }; unsigned choice = (unsigned) m_Choice_Drill_Map->GetSelection(); if( choice >= m_Choice_Drill_Map->GetCount() ) choice = 1; fn.SetExt( wxEmptyString ); // Will be added by GenDrillMap wxString fullfilename = fn.GetFullPath() + wxT( "-drl_map" ); GenDrillMap( fullfilename, excellonWriter, filefmt[choice] ); } } if( gen_NPTH_holes ) // The last drill file was created break; if( !hasBuriedVias ) gen_NPTH_holes = true; else { if( gen_through_holes ) layer2 = layer1 + 1; // prepare generation of first layer pair else { if( layer2 >= LAYER_N_FRONT ) // no more layer pair to consider { layer1 = LAYER_N_BACK; layer2 = LAYER_N_FRONT; gen_NPTH_holes = true; continue; } layer1++; layer2++; // use next layer pair if( layer2 == m_parent->GetBoard()->GetCopperLayerCount() - 1 ) layer2 = LAYER_N_FRONT; // the last layer is always the // Front layer } gen_through_holes = false; } } ::wxSetWorkingDirectory( currentWD ); }
void DIALOG_PLOT::Plot( wxCommandEvent& event ) { applyPlotSettings(); // Create output directory if it does not exist (also transform it in // absolute form). Bail if it fails wxFileName outputDir = wxFileName::DirName( m_plotOpts.GetOutputDirectory() ); wxString boardFilename = m_parent->GetBoard()->GetFileName(); REPORTER& reporter = m_messagesPanel->Reporter(); if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) ) { wxString msg; msg.Printf( _( "Could not write plot files to folder \"%s\"." ), GetChars( outputDir.GetPath() ) ); DisplayError( this, msg ); return; } m_plotOpts.SetAutoScale( false ); m_plotOpts.SetScale( 1 ); switch( m_plotOpts.GetScaleSelection() ) { default: break; case 0: // Autoscale option m_plotOpts.SetAutoScale( true ); break; case 2: // 3:2 option m_plotOpts.SetScale( 1.5 ); break; case 3: // 2:1 option m_plotOpts.SetScale( 2 ); break; case 4: // 3:1 option m_plotOpts.SetScale( 3 ); break; } /* If the scale factor edit controls are disabled or the scale value * is 0, don't adjust the base scale factor. This fixes a bug when * the default scale adjust is initialized to 0 and saved in program * settings resulting in a divide by zero fault. */ if( m_fineAdjustXscaleOpt->IsEnabled() && m_XScaleAdjust != 0.0 ) m_plotOpts.SetFineScaleAdjustX( m_XScaleAdjust ); if( m_fineAdjustYscaleOpt->IsEnabled() && m_YScaleAdjust != 0.0 ) m_plotOpts.SetFineScaleAdjustY( m_YScaleAdjust ); if( m_PSFineAdjustWidthOpt->IsEnabled() ) m_plotOpts.SetWidthAdjust( m_PSWidthAdjust ); wxString file_ext( GetDefaultPlotExtension( m_plotOpts.GetFormat() ) ); // Test for a reasonable scale value // XXX could this actually happen? isn't it constrained in the apply // function? if( m_plotOpts.GetScale() < PLOT_MIN_SCALE ) DisplayInfoMessage( this, _( "Warning: Scale option set to a very small value" ) ); if( m_plotOpts.GetScale() > PLOT_MAX_SCALE ) DisplayInfoMessage( this, _( "Warning: Scale option set to a very large value" ) ); // Save the current plot options in the board m_parent->SetPlotSettings( m_plotOpts ); wxBusyCursor dummy; for( LSEQ seq = m_plotOpts.GetLayerSelection().UIOrder(); seq; ++seq ) { LAYER_ID layer = *seq; // Pick the basename from the board file wxFileName fn( boardFilename ); // Use Gerber Extensions based on layer number // (See http://en.wikipedia.org/wiki/Gerber_File) if( m_plotOpts.GetFormat() == PLOT_FORMAT_GERBER && m_useGerberExtensions->GetValue() ) file_ext = GetGerberExtension( layer ); // Create file name (from the English layer name for non copper layers). BuildPlotFileName( &fn, outputDir.GetPath(), m_board->GetStandardLayerName( layer ), file_ext ); LOCALE_IO toggle; BOARD* board = m_parent->GetBoard(); PLOTTER* plotter = StartPlotBoard( board, &m_plotOpts, layer, fn.GetFullPath(), wxEmptyString ); // Print diags in messages box: wxString msg; if( plotter ) { PlotOneBoardLayer( board, plotter, layer, m_plotOpts ); plotter->EndPlot(); delete plotter; msg.Printf( _( "Plot file '%s' created." ), GetChars( fn.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ACTION ); } else { msg.Printf( _( "Unable to create file '%s'." ), GetChars( fn.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } // If no layer selected, we have nothing plotted. // Prompt user if it happens because he could think there is a bug in Pcbnew. if( !m_plotOpts.GetLayerSelection().any() ) DisplayError( this, _( "No layer selected" ) ); }
/*---------------------------------------------------------------------- | NPT_String::ToFloat +---------------------------------------------------------------------*/ NPT_Result NPT_String::ToFloat(float& value, bool relaxed) const { return NPT_ParseFloat(GetChars(), value, relaxed); }
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 ); }
const wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode ) { wxString attrib; switch( aLayer ) { case F_Adhes: attrib = "Glue,Top"; break; case B_Adhes: attrib = "Glue,Bot"; break; case F_SilkS: attrib = "Legend,Top"; break; case B_SilkS: attrib = "Legend,Bot"; break; case F_Mask: attrib = "Soldermask,Top"; break; case B_Mask: attrib = "Soldermask,Bot"; break; case F_Paste: attrib = "Paste,Top"; break; case B_Paste: attrib = "Paste,Bot"; break; case Edge_Cuts: // Board outline. // Can be "Profile,NP" (Not Plated: usual) or "Profile,P" // This last is the exception (Plated) attrib = "Profile,NP"; break; case Dwgs_User: attrib = "Drawing"; break; case Cmts_User: attrib = "Other,Comment"; break; case Eco1_User: attrib = "Other,ECO1"; break; case Eco2_User: attrib = "Other,ECO2"; break; case B_Fab: attrib = "Other,Fab,Bot"; break; case F_Fab: attrib = "Other,Fab,Top"; break; case B_Cu: attrib.Printf( wxT( "Copper,L%d,Bot" ), aBoard->GetCopperLayerCount() ); break; case F_Cu: attrib = "Copper,L1,Top"; break; default: if( IsCopperLayer( aLayer ) ) attrib.Printf( wxT( "Copper,L%d,Inr" ), aLayer+1 ); else attrib.Printf( wxT( "Other,User" ), aLayer+1 ); break; } // Add the signal type of the layer, if relevant if( IsCopperLayer( aLayer ) ) { LAYER_T type = aBoard->GetLayerType( ToLAYER_ID( aLayer ) ); switch( type ) { case LT_SIGNAL: attrib += ",Signal"; break; case LT_POWER: attrib += ",Plane"; break; case LT_MIXED: attrib += ",Mixed"; break; default: break; // do nothing (but avoid a warning for unhandled LAYER_T values from GCC) } } wxString fileFct; if( aUseX1CompatibilityMode ) fileFct.Printf( "G04 #@! TF.FileFunction,%s*", GetChars( attrib ) ); else fileFct.Printf( "%%TF.FileFunction,%s*%%", GetChars( attrib ) ); return fileFct; }
void DIALOG_PLOT_SCHEMATIC::createHPGLFile( bool aPlotAll, bool aPlotFrameRef ) { wxString plotFileName; SCH_SCREEN* screen = m_parent->GetScreen(); SCH_SHEET_PATH* sheetpath; 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( NULL ); sheetpath = SheetList.GetFirst(); SCH_SHEET_PATH list; SetHPGLPenWidth(); while( true ) { if( aPlotAll ) { if( sheetpath == NULL ) break; list.Clear(); if( list.BuildSheetPathInfoFromSheetPathValue( sheetpath->Path() ) ) { m_parent->SetCurrentSheet( list ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); screen = m_parent->GetCurrentSheet().LastScreen(); if( !screen ) // LastScreen() may return NULL screen = m_parent->GetScreen(); } else // Should not happen return; sheetpath = SheetList.GetNext(); } 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; if( GetPlotOriginCenter() ) { plotOffset.x = plotPage.GetWidthIU() / 2; plotOffset.y = -plotPage.GetHeightIU() / 2; } plotFileName = m_parent->GetUniqueFilenameForCurrentSheet() + wxT( "." ) + HPGL_PLOTTER::GetDefaultFileExtension(); plotFileName = Prj().AbsolutePath( plotFileName ); LOCALE_IO toggle; wxString msg; if( Plot_1_Page_HPGL( plotFileName, screen, plotPage, plotOffset, plot_scale, aPlotFrameRef ) ) msg.Printf( _( "Plot: <%s> OK\n" ), GetChars( plotFileName ) ); else // Error msg.Printf( _( "Unable to create <%s>\n" ), GetChars( plotFileName ) ); m_MessagesBox->AppendText( msg ); if( !aPlotAll ) break; } m_parent->SetCurrentSheet( oldsheetpath ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); }
void CVPCB_MAINFRAME::DisplayStatus() { wxString msg; COMPONENT* component; if( wxWindow::FindFocus() == m_compListBox || wxWindow::FindFocus() == m_libListBox ) { msg.Printf( _( "Components: %d, unassigned: %d" ), (int) m_netlist.GetCount(), m_undefinedComponentCnt ); SetStatusText( msg, 0 ); msg.Empty(); component = GetSelectedComponent(); if( component ) { for( unsigned ii = 0; ii < component->GetFootprintFilters().GetCount(); ii++ ) { if( msg.IsEmpty() ) msg += component->GetFootprintFilters()[ii]; else msg += wxT( ", " ) + component->GetFootprintFilters()[ii]; } msg = _( "Filter list: " ) + msg; } SetStatusText( msg, 1 ); } else { wxString footprintName = GetSelectedFootprint(); FOOTPRINT_INFO* module = m_FootprintsList.GetModuleInfo( footprintName ); if( module ) // can be NULL if no netlist loaded { msg = _( "Description: " ) + module->GetDoc(); SetStatusText( msg, 0 ); msg = _( "Key words: " ) + module->GetKeywords(); SetStatusText( msg, 1 ); } } msg.Empty(); wxString filters; if( m_footprintListBox ) { if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_COMPONENT_KEYWORD ) ) filters = _( "key words" ); if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_PIN_COUNT ) ) { if( !filters.IsEmpty() ) filters += wxT( "+" ); filters += _( "pin count" ); } if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_LIBRARY ) ) { if( !filters.IsEmpty() ) filters += wxT( "+" ); filters += _( "library" ); } if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_NAME ) ) { if( !filters.IsEmpty() ) filters += wxT( "+" ); filters += _( "name" ); } if( filters.IsEmpty() ) msg = _( "No filtering" ); else msg.Printf( _( "Filtered by %s" ), GetChars( filters ) ); msg << wxT( ": " ) << m_footprintListBox->GetCount(); SetStatusText( msg, 2 ); } }
/** * Function CombineAllAreasInNet * Checks all copper areas in net for intersections, combining them if found * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in * undo commands can be NULL * @param aNetCode = net to consider * @param bMessageBox : if true display warning message box * @param bUseUtility : if true, don't check areas if both utility flags are 0 * Sets utility flag = 1 for any areas modified * If an area has self-intersecting arcs, doesn't try to combine it */ int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, bool bMessageBox, bool bUseUtility ) { if( m_ZoneDescriptorList.size() <= 1 ) return 0; // start by testing all area polygons to set utility2 flags for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ ) if( m_ZoneDescriptorList[ia]->GetNet() == aNetCode ) TestAreaPolygon( m_ZoneDescriptorList[ia] ); // now loop through all combinations for( unsigned ia1 = 0; ia1 < m_ZoneDescriptorList.size() - 1; ia1++ ) { ZONE_CONTAINER* curr_area = m_ZoneDescriptorList[ia1]; if( curr_area->GetNet() != aNetCode ) continue; // legal polygon CRect b1 = curr_area->m_Poly->GetCornerBounds(); bool mod_ia1 = false; for( unsigned ia2 = m_ZoneDescriptorList.size() - 1; ia2 > ia1; ia2-- ) { ZONE_CONTAINER* area2 = m_ZoneDescriptorList[ia2]; if( area2->GetNet() != aNetCode ) continue; if( curr_area->GetPriority() != area2->GetPriority() ) continue; if( curr_area->GetLayer() == area2->GetLayer() && curr_area->utility2 != -1 && area2->utility2 != -1 ) { CRect b2 = area2->m_Poly->GetCornerBounds(); if( !( b1.left > b2.right || b1.right < b2.left || b1.bottom > b2.top || b1.top < b2.bottom ) ) { // check area2 against curr_area if( curr_area->utility || area2->utility || bUseUtility == false ) { int ret = TestAreaIntersection( curr_area, area2 ); if( ret == 1 ) ret = CombineAreas( aDeletedList, curr_area, area2 ); if( ret == 1 ) { mod_ia1 = true; } else if( ret == 2 ) { if( bMessageBox && bDontShowIntersectionArcsWarning == false ) { wxString str; str.Printf( wxT( "Areas %d and %d of net \"%s\" intersect, but some of the intersecting sides are arcs.\n" ), ia1 + 1, ia2 + 1, GetChars( curr_area->m_Netname ) ); str += wxT( "Therefore, these areas can't be combined." ); wxMessageBox( str ); } } } } } } if( mod_ia1 ) ia1--; // if modified, we need to check it again } return 0; }
void DialogEditModuleText::initDlg( ) { SetFocus(); wxString msg; if( m_module ) { wxString format = m_ModuleInfoText->GetLabel(); msg.Printf( format, GetChars( m_module->GetReference() ), GetChars( m_module->GetValue() ), m_module->GetOrientation() / 10.0 ); } else { msg.Empty(); } m_ModuleInfoText->SetLabel( msg ); switch( m_currentText->GetType() ) { case TEXTE_MODULE::TEXT_is_VALUE: m_TextDataTitle->SetLabel( _( "Value:" ) ); break; case TEXTE_MODULE::TEXT_is_DIVERS: m_TextDataTitle->SetLabel( _( "Text:" ) ); break; default: m_TextDataTitle->SetLabel( _( "Reference:" ) ); break; } m_Name->SetValue( m_currentText->GetText() ); m_Style->SetSelection( m_currentText->IsItalic() ? 1 : 0 ); AddUnitSymbol( *m_SizeXTitle ); PutValueInLocalUnits( *m_TxtSizeCtrlX, m_currentText->GetSize().x ); AddUnitSymbol( *m_SizeYTitle ); PutValueInLocalUnits( *m_TxtSizeCtrlY, m_currentText->GetSize().y ); AddUnitSymbol( *m_PosXTitle ); PutValueInLocalUnits( *m_TxtPosCtrlX, m_currentText->GetPos0().x ); AddUnitSymbol( *m_PosYTitle ); PutValueInLocalUnits( *m_TxtPosCtrlY, m_currentText->GetPos0().y ); AddUnitSymbol( *m_WidthTitle ); PutValueInLocalUnits( *m_TxtWidthCtlr, m_currentText->GetThickness() ); double text_orient = m_currentText->GetOrientation(); NORMALIZE_ANGLE_90( text_orient ); if( (text_orient != 0) ) m_Orient->SetSelection( 1 ); if( !m_currentText->IsVisible() ) m_Show->SetSelection( 1 );; }
void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) { int id = event.GetId(); wxFileName fn; switch( id ) { case ID_MENU_PCB_SHOW_HIDE_LAYERS_MANAGER_DIALOG: m_show_layer_manager_tools = ! m_show_layer_manager_tools; m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).Show( m_show_layer_manager_tools ); m_auimgr.Update(); GetMenuBar()->SetLabel( ID_MENU_PCB_SHOW_HIDE_LAYERS_MANAGER_DIALOG, m_show_layer_manager_tools ? _("Hide &Layers Manager" ) : _("Show &Layers Manager" )); break; case ID_MENU_PCB_SHOW_HIDE_MUWAVE_TOOLBAR: m_show_microwave_tools = ! m_show_microwave_tools; m_auimgr.GetPane( wxT( "m_microWaveToolBar" ) ).Show( m_show_microwave_tools ); m_auimgr.Update(); GetMenuBar()->SetLabel( ID_MENU_PCB_SHOW_HIDE_MUWAVE_TOOLBAR, m_show_microwave_tools ? _( "Hide Microwave Toolbar" ): _( "Show Microwave Toolbar" )); break; case ID_PCB_LAYERS_SETUP: if( InvokeLayerSetup( this, GetBoard() ) ) { LAYER_ID cur_layer = GetActiveLayer(); // If after showing the dialog the user has removed the active layer, // then select a new active layer (front copper layer). if( !GetBoard()->GetEnabledLayers()[ cur_layer ] ) cur_layer = F_Cu; SetActiveLayer( cur_layer ); OnModify(); ReCreateLayerBox(); ReFillLayerWidget(); if( IsGalCanvasActive() ) static_cast<PCB_DRAW_PANEL_GAL*>( GetGalCanvas() )->SyncLayersVisibility( GetBoard() ); } break; case ID_PCB_LIB_WIZARD: case ID_PCB_LIB_TABLE_EDIT: { bool tableChanged = false; int r = 0; if( id == ID_PCB_LIB_TABLE_EDIT ) r = InvokePcbLibTableEditor( this, &GFootprintTable, Prj().PcbFootprintLibs() ); else r = InvokeFootprintWizard( this, &GFootprintTable, Prj().PcbFootprintLibs() ); if( r & 1 ) { try { FILE_OUTPUTFORMATTER sf( FP_LIB_TABLE::GetGlobalTableFileName() ); GFootprintTable.Format( &sf, 0 ); tableChanged = true; } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error occurred saving the global footprint library " "table:\n\n%s" ), GetChars( ioe.errorText.GetData() ) ); wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); } } // If no board file is defined, do not save the project specific library table. It // is kept in memory and created in the path when the new board is saved. if( (r & 2) && !GetBoard()->GetFileName().IsEmpty() ) { wxString tblName = Prj().FootprintLibTblName(); try { Prj().PcbFootprintLibs()->Save( tblName ); tableChanged = true; } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error occurred saving project specific footprint library " "table:\n\n%s" ), GetChars( ioe.errorText ) ); wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); } } FOOTPRINT_VIEWER_FRAME* viewer; if( tableChanged && (viewer = (FOOTPRINT_VIEWER_FRAME*)Kiway().Player( FRAME_PCB_MODULE_VIEWER, false )) != NULL ) { viewer->ReCreateLibraryList(); } } break; case ID_PCB_MASK_CLEARANCE: { DIALOG_PADS_MASK_CLEARANCE dlg( this ); if( dlg.ShowModal() == 1 && IsGalCanvasActive() ) { for( MODULE* module = GetBoard()->m_Modules; module; module = module->Next() ) module->ViewUpdate(); GetGalCanvas()->Refresh(); } } break; case wxID_PREFERENCES: { DIALOG_GENERALOPTIONS dlg( this ); dlg.ShowModal(); } break; case ID_PCB_PAD_SETUP: InstallPadOptionsFrame( NULL ); break; case ID_CONFIG_SAVE: SaveProjectSettings( true ); break; case ID_CONFIG_READ: { fn = GetBoard()->GetFileName(); fn.SetExt( ProjectFileExtension ); wxFileDialog dlg( this, _( "Read Project File" ), fn.GetPath(), fn.GetFullName(), ProjectFileWildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) break; if( !wxFileExists( dlg.GetPath() ) ) { wxString msg = wxString::Format( _( "File %s not found" ), GetChars( dlg.GetPath() ) ); DisplayError( this, msg ); break; } wxString pro_file = dlg.GetPath(); Prj().ConfigLoad( Kiface().KifaceSearch(), GROUP_PCB, GetProjectFileParameters(), pro_file ); } break; // Hotkey IDs case ID_PREFERENCES_HOTKEY_EXPORT_CONFIG: ExportHotkeyConfigToFile( g_Board_Editor_Hokeys_Descr, wxT( "pcbnew" ) ); break; case ID_PREFERENCES_HOTKEY_IMPORT_CONFIG: ImportHotkeyConfigFromFile( g_Board_Editor_Hokeys_Descr, wxT( "pcbnew" ) ); break; case ID_PREFERENCES_HOTKEY_SHOW_EDITOR: InstallHotkeyFrame( this, g_Board_Editor_Hokeys_Descr ); break; case ID_PREFERENCES_HOTKEY_SHOW_CURRENT_LIST: // Display current hotkey list for Pcbnew. DisplayHotkeyList( this, g_Board_Editor_Hokeys_Descr ); break; // Macros IDs case ID_PREFRENCES_MACROS_SAVE: SaveMacros(); break; case ID_PREFRENCES_MACROS_READ: ReadMacros(); break; default: DisplayError( this, wxT( "PCB_EDIT_FRAME::Process_Config error" ) ); } }
bool CMP_READER::Load( NETLIST* aNetlist ) { wxCHECK_MSG( aNetlist != NULL,true, wxT( "No netlist passed to CMP_READER::Load()" ) ); wxString reference; // Stores value read from line like Reference = BUS1; wxString timestamp; // Stores value read from line like TimeStamp = /32307DE2/AA450F67; wxString footprint; // Stores value read from line like IdModule = CP6; wxString buffer; wxString value; bool ok = true; while( m_lineReader->ReadLine() ) { buffer = FROM_UTF8( m_lineReader->Line() ); if( !buffer.StartsWith( wxT( "BeginCmp" ) ) ) continue; // Begin component description. reference.Empty(); footprint.Empty(); timestamp.Empty(); while( m_lineReader->ReadLine() ) { buffer = FROM_UTF8( m_lineReader->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; } if( buffer.StartsWith( wxT( "TimeStamp =" ) ) ) { timestamp = value; continue; } } // Find the corresponding item in component list: COMPONENT* component = aNetlist->GetComponentByReference( reference ); // The corresponding component could no longer existing in the netlist. This // can happen when it is removed from schematic and still exists in footprint // assignment list. This is an usual case during the life of a design. if( component ) { LIB_ID fpid; if( !footprint.IsEmpty() && fpid.Parse( footprint ) >= 0 ) { wxString error; error.Printf( _( "invalid footprint ID in\nfile: \"%s\"\nline: %d" ), GetChars( m_lineReader->GetSource() ), m_lineReader->LineNumber() ); THROW_IO_ERROR( error ); } // For checking purpose, store the existing LIB_ID (if any) in the alternate fpid copy // if this existing LIB_ID differs from the LIB_ID read from the .cmp file. // CvPcb can ask for user to chose the right LIB_ID. // It happens if the LIB_ID was modified outside CvPcb. if( fpid != component->GetFPID() && !component->GetFPID().empty() ) component->SetAltFPID( component->GetFPID() ); component->SetFPID( fpid ); } else { ok = false; // can be used to display a warning in Pcbnew. } } return ok; }
bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() { COMPONENT* component; wxString msg; bool isLegacy = true; ReadSchematicNetlist(); if( m_ListCmp == NULL ) return false; LoadProjectFile( m_NetlistFileName.GetFullPath() ); LoadFootprintFiles(); BuildFOOTPRINTS_LISTBOX(); BuildLIBRARY_LISTBOX(); m_ListCmp->Clear(); m_undefinedComponentCnt = 0; if( m_netlist.AnyFootprintsLinked() ) { for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); if( component->GetFPID().empty() ) continue; if( isLegacy ) { if( !component->GetFPID().IsLegacy() ) isLegacy = false; } } } else { isLegacy = false; // None of the components have footprints assigned. } wxString missingLibs; // Check if footprint links were generated before the footprint library table was implemented. if( isLegacy ) { if( m_footprintLibTable->MissingLegacyLibs( m_ModuleLibNames, &missingLibs ) ) { msg = wxT( "The following legacy libraries are defined in the project file " "were not found in the footprint library table:\n\n" ) + missingLibs; msg += wxT( "\nDo you want to update the footprint library table before " "attempting to update the assigned footprints?" ); if( IsOK( this, msg ) ) { wxCommandEvent cmd; OnEditFootprintLibraryTable( cmd ); } } msg = wxT( "Some or all of the assigned footprints contain legacy entries. Would you " "like CvPcb to attempt to convert them to the new footprint library table " "format?" ); if( IsOK( this, msg ) ) { msg.Clear(); WX_STRING_REPORTER reporter( &msg ); if( !m_footprintLibTable->ConvertFromLegacy( m_netlist, m_ModuleLibNames, &reporter ) ) { HTML_MESSAGE_BOX dlg( this, wxEmptyString ); dlg.MessageSet( wxT( "The following errors occurred attempt to convert the " "footprint assignments:\n\n" ) ); dlg.ListSet( msg ); dlg.MessageSet( wxT( "\nYou will need to reassign them manually if you want them " "to be updated correctly the next time you import the " "netlist in Pcbnew." ) ); dlg.ShowModal(); } m_modified = true; } else { // Clear the legacy footprint assignments. for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { FPID emptyFPID; component = m_netlist.GetComponent( i ); component->SetFPID( emptyFPID ); m_modified = true; } } } for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); msg.Printf( CMP_FORMAT, m_ListCmp->GetCount() + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); m_ListCmp->AppendLine( msg ); if( component->GetFPID().empty() ) { m_undefinedComponentCnt += 1; continue; } } if( !m_netlist.IsEmpty() ) m_ListCmp->SetSelection( 0, true ); DisplayStatus(); UpdateTitle(); UpdateFileHistory( m_NetlistFileName.GetFullPath() ); return true; }
void DIALOG_LABEL_EDITOR::InitDialog() { wxString msg; bool multiLine = false; if( m_CurrentText->IsMultilineAllowed() ) { m_textLabel = m_textLabelMultiLine; m_textLabelSingleLine->Show( false ); multiLine = true; } else { m_textLabel = m_textLabelSingleLine; m_textLabelMultiLine->Show( false ); wxTextValidator* validator = (wxTextValidator*) m_textLabel->GetValidator(); wxArrayString excludes; // Add invalid label characters to this list. excludes.Add( wxT( " " ) ); validator->SetExcludes( excludes ); } m_textLabel->SetValue( m_CurrentText->GetText() ); m_textLabel->SetFocus(); switch( m_CurrentText->Type() ) { case SCH_GLOBAL_LABEL_T: SetTitle( _( "Global Label Properties" ) ); break; case SCH_HIERARCHICAL_LABEL_T: SetTitle( _( "Hierarchical Label Properties" ) ); break; case SCH_LABEL_T: SetTitle( _( "Label Properties" ) ); break; case SCH_SHEET_PIN_T: SetTitle( _( "Hierarchical Sheet Pin Properties." ) ); break; default: SetTitle( _( "Text Properties" ) ); m_textLabel->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler ( DIALOG_LABEL_EDITOR::OnEnterKey ), NULL, this ); break; } const int MINTEXTWIDTH = 40; // M's are big characters, a few establish a lot of width int max_len = 0; if ( !multiLine ) { max_len = m_CurrentText->GetText().Length(); } else { // calculate the length of the biggest line // we cannot use the length of the entire text that has no meaning int curr_len = MINTEXTWIDTH; int imax = m_CurrentText->GetText().Length(); for( int count = 0; count < imax; count++ ) { if( m_CurrentText->GetText()[count] == '\n' || m_CurrentText->GetText()[count] == '\r' ) // new line { curr_len = 0; } else { curr_len++; if ( max_len < curr_len ) max_len = curr_len; } } } if( max_len < MINTEXTWIDTH ) max_len = MINTEXTWIDTH; wxString textWidth; textWidth.Append( 'M', MINTEXTWIDTH ); EnsureTextCtrlWidth( m_textLabel, &textWidth ); // Set validators m_TextOrient->SetSelection( m_CurrentText->GetOrientation() ); m_TextShape->SetSelection( m_CurrentText->GetShape() ); int style = 0; if( m_CurrentText->IsItalic() ) style = 1; if( m_CurrentText->IsBold() ) style += 2; m_TextStyle->SetSelection( style ); wxString units = ReturnUnitSymbol( g_UserUnit, wxT( "(%s)" ) ); msg.Printf( _( "H%s x W%s" ), GetChars( units ), GetChars( units ) ); m_staticSizeUnits->SetLabel( msg ); msg = StringFromValue( g_UserUnit, m_CurrentText->GetSize().x ); m_TextSize->SetValue( msg ); if( m_CurrentText->Type() != SCH_GLOBAL_LABEL_T && m_CurrentText->Type() != SCH_HIERARCHICAL_LABEL_T ) { m_TextShape->Show( false ); } m_sdbSizer1OK->SetDefault(); }
void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) { COMPONENT* component; bool hasFootprint = false; int componentIndex; wxString description; if( m_netlist.IsEmpty() ) return; // If no component is selected, select the first one if( m_ListCmp->GetFirstSelected() < 0 ) { componentIndex = 0; m_ListCmp->SetSelection( componentIndex, true ); } // iterate over the selection while( m_ListCmp->GetFirstSelected() != -1 ) { // Get the component for the current iteration componentIndex = m_ListCmp->GetFirstSelected(); component = m_netlist.GetComponent( componentIndex ); if( component == NULL ) return; // Check to see if the component has already a footprint set. hasFootprint = !component->GetFPID().empty(); FPID fpid; if( !aFootprintName.IsEmpty() ) { wxCHECK_RET( fpid.Parse( aFootprintName ) < 0, wxString::Format( wxT( "<%s> is not a valid FPID." ), GetChars( aFootprintName ) ) ); } component->SetFPID( fpid ); // create the new component description description.Printf( CMP_FORMAT, componentIndex + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); // If the component hasn't had a footprint associated with it // it now has, so we decrement the count of components without // a footprint assigned. if( !hasFootprint ) { hasFootprint = true; m_undefinedComponentCnt -= 1; } // Set the new description and deselect the processed component m_ListCmp->SetString( componentIndex, description ); m_ListCmp->SetSelection( componentIndex, false ); } // Mark this "session" as modified m_modified = true; // select the next component, if there is one if( componentIndex < (m_ListCmp->GetCount() - 1) ) componentIndex++; m_ListCmp->SetSelection( componentIndex, true ); // update the statusbar DisplayStatus(); }
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() ); std::vector< std::vector< const SCH_SHEET* > > sheetHierarchy; sheet->GetSheetPaths( sheetHierarchy ); if( g_RootSheet->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; }
void DIALOG_DRC_CONTROL::OnListUnconnectedClick( wxCommandEvent& event ) { wxString reportName; bool make_report = m_CreateRptCtrl->IsChecked(); if( make_report ) // Create a file rpt { reportName = m_RptFilenameCtrl->GetValue(); if( reportName.IsEmpty() ) { wxCommandEvent junk; OnButtonBrowseRptFileClick( junk ); } if( !reportName.IsEmpty() ) reportName = makeValidFileNameReport(); } SetDrcParmeters(); m_tester->SetSettings( true, // Pad to pad DRC test enabled true, // unconnected pads DRC test enabled true, // DRC test for zones enabled true, // DRC test for keepout areas enabled m_cbCourtyardOverlap->GetValue(), m_cbCourtyardMissing->GetValue(), reportName, make_report ); DelDRCMarkers(); wxBeginBusyCursor(); m_Messages->Clear(); m_tester->ListUnconnectedPads(); m_Notebook->ChangeSelection( 1 ); // display the 2nd tab "Unconnected..." // Generate the report if( !reportName.IsEmpty() ) { if( writeReport( reportName ) ) { wxString msg; msg.Printf( _( "Report file \"%s\" created" ), GetChars( reportName ) ); wxString caption( _( "Disk File Report Completed" ) ); wxMessageDialog popupWindow( this, msg, caption ); popupWindow.ShowModal(); } else DisplayError( this, wxString::Format( _( "Unable to create report file \"%s\""), GetChars( reportName ) ) ); } UpdateDisplayedCounts(); wxEndBusyCursor(); /* there is currently nothing visible on the DrawPanel for unconnected pads * RedrawDrawPanel(); */ }
/** * Function WriteHotkeyConfig * Store the current hotkey list * It is stored using the standard wxConfig mechanism or a file. * * @param aDescList = pointer to the current hotkey list. * @param aFullFileName = a wxString pointer to a full file name. * if NULL, use the standard wxConfig mechanism (default) * the output format is: shortcut "key" "function" * lines starting with # are comments */ int EDA_BASE_FRAME::WriteHotkeyConfig( struct EDA_HOTKEY_CONFIG* aDescList, wxString* aFullFileName ) { wxString msg; wxString keyname, infokey; msg = wxT( "$hotkey list\n" ); // Print the current hotkey list EDA_HOTKEY** list; for( ; aDescList->m_HK_InfoList != NULL; aDescList++ ) { if( aDescList->m_Comment ) { msg += wxT( "# " ); msg += wxString( aDescList->m_Comment ); msg += wxT( "\n" ); } msg += *aDescList->m_SectionTag; msg += wxT( "\n" ); list = aDescList->m_HK_InfoList; for( ; *list != NULL; list++ ) { EDA_HOTKEY* hk_decr = *list; msg += wxT( "shortcut " ); keyname = KeyNameFromKeyCode( hk_decr->m_KeyCode ); AddDelimiterString( keyname ); infokey = hk_decr->m_InfoMsg; AddDelimiterString( infokey ); msg += keyname + wxT( ": " ) + infokey + wxT( "\n" ); } } msg += wxT( "$Endlist\n" ); if( aFullFileName ) { FILE* file = wxFopen( *aFullFileName, wxT( "wt" ) ); if( file ) { fputs( TO_UTF8( msg ), file ); fclose( file ); } else { msg.Printf( wxT( "Unable to write file %s" ), GetChars( *aFullFileName ) ); return 0; } } else { wxConfig config( m_FrameName ); config.Write( HOTKEYS_CONFIG_KEY, msg ); } return 1; }
wxString PCB_BASE_FRAME::SelectFootprint( EDA_DRAW_FRAME* aWindow, const wxString& aLibraryName, const wxString& aMask, const wxString& aKeyWord, FP_LIB_TABLE* aTable ) { static wxString oldName; // Save the name of the last module loaded. wxString fpname; wxString msg; wxArrayString libraries; std::vector< wxArrayString > rows; wxASSERT( aTable != NULL ); MList.ReadFootprintFiles( aTable, !aLibraryName ? NULL : &aLibraryName ); if( MList.GetErrorCount() ) { MList.DisplayErrors( this ); return wxEmptyString; } if( MList.GetCount() == 0 ) { wxString tmp; for( unsigned i = 0; i < libraries.GetCount(); i++ ) { tmp += libraries[i] + wxT( "\n" ); } msg.Printf( _( "No footprints could be read from library file(s):\n\n%s\nin any of " "the library search paths. Verify your system is configured properly " "so the footprint libraries can be found." ), GetChars( tmp ) ); DisplayError( aWindow, msg ); return wxEmptyString; } if( !aKeyWord.IsEmpty() ) // Create a list of modules found by keyword. { for( unsigned ii = 0; ii < MList.GetCount(); ii++ ) { if( KeyWordOk( aKeyWord, MList.GetItem( ii ).GetKeywords() ) ) { wxArrayString cols; cols.Add( MList.GetItem( ii ).GetFootprintName() ); cols.Add( MList.GetItem( ii ).GetNickname() ); rows.push_back( cols ); } } } else if( !aMask.IsEmpty() ) // Create a list of modules found by pattern { for( unsigned ii = 0; ii < MList.GetCount(); ii++ ) { const wxString& candidate = MList.GetItem( ii ).GetFootprintName(); if( WildCompareString( aMask, candidate, false ) ) { wxArrayString cols; cols.Add( MList.GetItem( ii ).GetFootprintName() ); cols.Add( MList.GetItem( ii ).GetNickname() ); rows.push_back( cols ); } } } else // Create the full list of modules { for( unsigned ii = 0; ii < MList.GetCount(); ii++ ) { wxArrayString cols; cols.Add( MList.GetItem( ii ).GetFootprintName() ); cols.Add( MList.GetItem( ii ).GetNickname() ); rows.push_back( cols ); } } if( !rows.empty() ) { wxArrayString headers; headers.Add( _( "Footprint" ) ); headers.Add( _( "Library" ) ); msg.Printf( _( "Footprints [%d items]" ), (int) rows.size() ); EDA_LIST_DIALOG dlg( aWindow, msg, headers, rows, oldName, DisplayCmpDoc ); if( dlg.ShowModal() == wxID_OK ) { fpname = dlg.GetTextSelection(); fpname = dlg.GetTextSelection( 1 ) + wxT( ":" ) + fpname; SkipNextLeftButtonReleaseEvent(); } else fpname.Empty(); } else { DisplayError( aWindow, _( "No footprint found." ) ); fpname.Empty(); } if( fpname != wxEmptyString ) oldName = fpname; wxLogDebug( wxT( "Footprint '%s' was selected." ), GetChars( fpname ) ); return fpname; }
/*---------------------------------------------------------------------- | NPT_String::ToInteger +---------------------------------------------------------------------*/ NPT_Result NPT_String::ToInteger(NPT_Int32& value, bool relaxed) const { return NPT_ParseInteger32(GetChars(), value, relaxed); }