diff --git a/3d-viewer/3d_canvas.cpp b/3d-viewer/3d_canvas.cpp index 248cd3bb3d..1764d6faa0 100644 --- a/3d-viewer/3d_canvas.cpp +++ b/3d-viewer/3d_canvas.cpp @@ -228,8 +228,6 @@ void EDA_3D_CANVAS::SetView3D( int keycode ) void EDA_3D_CANVAS::OnMouseWheel( wxMouseEvent& event ) { - wxSize size( GetClientSize() ); - if( event.ShiftDown() ) { if( event.GetWheelRotation() < 0 ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07d9441b1b..9f72329925 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,8 +88,8 @@ if( CMAKE_COMPILER_IS_GNUCXX ) # Establish -Wall early, so specialized relaxations of this may come # subsequently on the command line, such as in pcbnew/github/CMakeLists.txt - set( CMAKE_C_FLAGS "-Wall" ) - set( CMAKE_CXX_FLAGS "-Wall" ) + set( CMAKE_C_FLAGS "-Wall ${CMAKE_C_FLAGS}" ) + set( CMAKE_CXX_FLAGS "-Wall ${CMAKE_CXX_FLAGS}" ) # The optimization level is -O1 instead of the usual -O2 level because # boost::polygon has a function (inflate polygon) broken by the -O2 level @@ -459,11 +459,6 @@ add_custom_target( uninstall # Installation #================================================ -add_custom_target( install_user_configuration_files - "${CMAKE_COMMAND}" -E copy "${PROJECT_SOURCE_DIR}/template/fp-lib-table" ${KICAD_USER_CONFIG_DIR}/ - COMMENT "Install template fp-lib-table into your home directory." - ) - install( FILES INSTALL.txt DESTINATION ${KICAD_DOCS} COMPONENT resources ) @@ -534,10 +529,6 @@ if( UNIX AND NOT APPLE ) #set( CPACK_PACKAGE_CONTACT Firstname Lastname ) set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "KiCad built by CMake build system." ) - # Tell debian CPack about all files which are configuration files - add_conffiles() # clear file - add_conffiles( ${KICAD_USER_CONFIG_DIR}/fp-lib-table ) # append to it - include( CPack ) endif() diff --git a/CMakeModules/download_boost.cmake b/CMakeModules/download_boost.cmake index 7fe4f0d243..5f19823c71 100644 --- a/CMakeModules/download_boost.cmake +++ b/CMakeModules/download_boost.cmake @@ -58,7 +58,7 @@ set( BOOST_LIBS_BUILT #-------------------------------------------------------------------- - +find_package( BZip2 REQUIRED ) string( REGEX REPLACE "\\." "_" BOOST_VERS "${BOOST_RELEASE}" ) set( PREFIX ${DOWNLOAD_DIR}/boost_${BOOST_VERS} ) diff --git a/TODO.txt b/TODO.txt index 7895089ec2..7a534122bb 100644 --- a/TODO.txt +++ b/TODO.txt @@ -26,92 +26,6 @@ Common but is now in scripts/python/ky temporarily. -FP LIB TABLE ------------- - -Dialog: -- - - - - -a) check for duplicate nicknames in a single table, complain, give the user a nice indication of the duplicate(s) - -b) in the uri column give a small button popup a window(dialog?) which lets user choose a file or directory local to his system by pointing at it. - -c) Active library table load and save functions. There are two tables active at any time, but -they look like one table. Identify a place to keep the access mechanism (pointer). Modify -the project specific portion of this RAM table when the board changes. - - -Other: -- - - - - -a) develop a syntax for nickname:footprint combo, i.e. bring to life class FPID - with development and testing of parsing and formatting. - - -b) modify cvpcb to handle the nickname:footprint, i.e. textual form of FPID. -This means having a wider textfield for the FPID than was allocated for the footprint name alone. -Needed is the ability to pick a footprint from any active library. - - -c) modify the netlist format to handle nickname:footprint, save and load. -The nickname needs to be optional. I would say allowed in the grammar in the -footprint position are: - - footprint | (fp_id FPID) - -or just - - FPID # if it can be parsed when nickname is missing. - - -d) write functions to lookup a footprint from - i) FPID - ii) footprint alone since most old netlists don't have nicknames in them. - -e) Replace MODULE::m_LibRef which is a wxString with FPID. FPID supports - the footprint name only which is backwards compatible with the current - design. - -f) On the first time an empty global footprint table is encountered, add - standard KiCad and user libraries not located in the project directory - or any of it's sub-directories to the global footprint library table. - -g) When a project is opened and the project footprint library table is - empty, add any user library that is located in the project path or any - of it's sub-directories to the project footprint library table. - -h) When populating the footprint library tables, use the library file name - without the extension as the FPID nickname. When duplicate names exist, - append an incremental integer to the nickname so that the second logic - libraries FPID nickname becomes logic1. Assign FPID library nicknames - to each MODULE based on the legacy library search order when loading an - existing board that does not have fully defined MODULE FPIDs. - -i) Add check for KISYSMOD environment variable, on Pcbnew and CvPcb start up - and set it to the known directory of the default KiCad footprint libraries. - The code should look something like: - -{ - const char* envar; - - envar = getenv( "KISYSMOD" ); - - if( !envar ) - { - envvar = knownDirOfSysMods; - - setenv( "KISYSMOD", envar ); - } -} - - -These i) and ii) merge into one if footprint alone is a valid FPID. -Incorporate any environment variable in the the uri expansion using: -const wxString FP_LIB_TABLE::ExpandSubtitutions( const wxString aString ) - - - - Eeschema -------- @@ -148,10 +62,6 @@ PCBNew Dick's Final TODO List: ====================== -*) Rewrite - PCB_BASE_FRAME::Save_Module_In_Library - PCB_EDIT_FRAME::ArchiveModulesOnBoard - to use FP_LIB_TABLE mechanisms. *) Apply Fabrizio and Alexander's linux desktop patches after unifying them. *) Get licensing cleaned up. *) Re-arrange the repo architecture. diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 6a226f0b9f..b4d676ef67 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -159,7 +159,7 @@ set(COMMON_SRCS math/math_util.cpp system/fcontext.s - + tool/tool_base.cpp tool/tool_manager.cpp tool/tool_dispatcher.cpp @@ -231,7 +231,7 @@ set(PCB_COMMON_SRCS ) set(PCB_COMMON_SRCS - ${PCB_COMMON_SRCS} + ${PCB_COMMON_SRCS} ../pcbnew/pcb_painter.cpp ) diff --git a/common/base_screen.cpp b/common/base_screen.cpp index 717154b2e3..cb2cfd0e98 100644 --- a/common/base_screen.cpp +++ b/common/base_screen.cpp @@ -30,6 +30,7 @@ */ #include +#include #include #include #include diff --git a/common/base_struct.cpp b/common/base_struct.cpp index 280bdc9da6..07edc9d2e9 100644 --- a/common/base_struct.cpp +++ b/common/base_struct.cpp @@ -67,7 +67,6 @@ EDA_ITEM::EDA_ITEM( const EDA_ITEM& base ) InitVars(); m_StructType = base.m_StructType; m_Parent = base.m_Parent; - m_Son = base.m_Son; m_Flags = base.m_Flags; // A copy of an item cannot have the same time stamp as the original item. @@ -82,7 +81,6 @@ void EDA_ITEM::InitVars() Pnext = NULL; // Linked list: Link (next struct) Pback = NULL; // Linked list: Link (previous struct) m_Parent = NULL; // Linked list: Link (parent struct) - m_Son = NULL; // Linked list: Link (son struct) m_List = NULL; // I am not on any list yet m_Image = NULL; // Link to an image copy for undelete or abort command m_Flags = 0; // flags for editions and other @@ -235,7 +233,6 @@ EDA_ITEM& EDA_ITEM::operator=( const EDA_ITEM& aItem ) m_Image = aItem.m_Image; m_StructType = aItem.m_StructType; m_Parent = aItem.m_Parent; - m_Son = aItem.m_Son; m_Flags = aItem.m_Flags; m_TimeStamp = aItem.m_TimeStamp; m_Status = aItem.m_Status; @@ -535,7 +532,7 @@ double EDA_RECT::GetArea() const /* Calculate the bounding box of this, when rotated */ -EDA_RECT EDA_RECT::GetBoundingBoxRotated( wxPoint aRotCenter, double aAngle ) +const EDA_RECT EDA_RECT::GetBoundingBoxRotated( wxPoint aRotCenter, double aAngle ) { wxPoint corners[4]; diff --git a/common/basicframe.cpp b/common/basicframe.cpp index b5434b01b5..d513ac5839 100644 --- a/common/basicframe.cpp +++ b/common/basicframe.cpp @@ -459,7 +459,12 @@ void EDA_BASE_FRAME::AddHelpVersionInfoMenuEntry( wxMenu* aMenu ) static inline const char* KICAD_BUILD_OPTIONS_SIGNATURE() { return - " (" __WX_BO_UNICODE __ABI_VERSION __BO_COMPILER __WX_BO_STL +#ifdef __WXDEBUG__ + " (debug," +#else + " (release," +#endif + __WX_BO_UNICODE __ABI_VERSION __BO_COMPILER __WX_BO_STL __WX_BO_WXWIN_COMPAT_2_6 __WX_BO_WXWIN_COMPAT_2_8 ")" ; } @@ -469,7 +474,11 @@ static inline const char* KICAD_BUILD_OPTIONS_SIGNATURE() static inline const char* KICAD_BUILD_OPTIONS_SIGNATURE() { return - " (" __WX_BO_DEBUG "," +#ifdef __WXDEBUG__ + " (debug," +#else + " (release," +#endif __WX_BO_UNICODE __ABI_VERSION __BO_COMPILER __WX_BO_STL __WX_BO_WXWIN_COMPAT_2_4 __WX_BO_WXWIN_COMPAT_2_6 ")" ; @@ -490,8 +499,14 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event ) wxPlatformInfo info; tmp = wxT( "Application: " ) + wxGetApp().GetTitle() + wxT( "\n" ); - tmp += wxT( "Version: " ) + GetBuildVersion() + wxT( "\n" ); - tmp << wxT( "Build: " ) << wxVERSION_STRING + tmp << wxT( "Version: " ) << GetBuildVersion() +#ifdef DEBUG + << wxT( " Debug" ) +#else + << wxT( " Release" ) +#endif + << wxT( " build\n" ); + tmp << wxT( "wxWidgets: Version " ) << FROM_UTF8( wxVERSION_NUM_DOT_STRING ) << FROM_UTF8( KICAD_BUILD_OPTIONS_SIGNATURE() ) << wxT( "\n" ) << wxT( "Platform: " ) << wxGetOsDescription() << wxT( ", " ) << info.GetArchName() << wxT( ", " ) << info.GetEndiannessName() << wxT( ", " ) @@ -537,6 +552,22 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event ) tmp << wxT( "OFF\n" ); #endif + tmp << wxT( " USE_FP_LIB_TABLE=" ); +#ifdef USE_FP_LIB_TABLE + tmp << wxT( "ON\n" ); +#else + tmp << wxT( "OFF\n" ); +#endif + + tmp << wxT( " BUILD_GITHUB_PLUGIN=" ); +#ifdef BUILD_GITHUB_PLUGIN + tmp << wxT( "ON\n" ); +#else + tmp << wxT( "OFF\n" ); +#endif + + wxMessageBox( tmp, _("Version Information (copied to the clipboard)") ); + wxTheClipboard->SetData( new wxTextDataObject( tmp ) ); wxTheClipboard->Close(); } diff --git a/common/confirm.cpp b/common/confirm.cpp index b44186da9b..738ad17003 100644 --- a/common/confirm.cpp +++ b/common/confirm.cpp @@ -52,9 +52,9 @@ public: }; private: - void OnSaveAndExit( wxCommandEvent& event ) { EndModal( wxID_YES ); } - void OnCancel( wxCommandEvent& event ) { EndModal( wxID_CANCEL ); } - void OnExitNoSave( wxCommandEvent& event ) { EndModal( wxID_NO ); } + void OnSaveAndExit( wxCommandEvent& event ) { EndModal( wxID_YES ); } + void OnCancel( wxCommandEvent& event ) { EndModal( wxID_CANCEL ); } + void OnExitNoSave( wxCommandEvent& event ) { EndModal( wxID_NO ); } }; @@ -73,10 +73,14 @@ void DisplayError( wxWindow* parent, const wxString& text, int displaytime ) if( displaytime > 0 ) dialog = new wxMessageDialog( parent, text, _( "Warning" ), - wxOK | wxCENTRE | wxICON_INFORMATION ); + wxOK | wxCENTRE | wxICON_INFORMATION + | wxRESIZE_BORDER + ); else dialog = new wxMessageDialog( parent, text, _( "Error" ), - wxOK | wxCENTRE | wxICON_ERROR ); + wxOK | wxCENTRE | wxICON_ERROR + | wxRESIZE_BORDER + ); dialog->ShowModal(); dialog->Destroy(); diff --git a/common/dcsvg.cpp.unused b/common/dcsvg.cpp.unused deleted file mode 100644 index 7693052204..0000000000 --- a/common/dcsvg.cpp.unused +++ /dev/null @@ -1,1599 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: svg.cpp -// Purpose: SVG plot -// Author: Chris Elliott -// Modified by: JP Charras (dec 2006) -// Licence: wxWindows license -///////////////////////////////////////////////////////////////////////////// - - - -// For compilers that support precompilation, includes "wx/wx.h". -#include - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include -#endif - -#include - -#include -#include -#include -#include - -#if wxCHECK_VERSION( 2, 9, 0 ) - -// We could do nothing, because wxWidgets 3 supports the SVG format -// (previously, it was a contribution library, not included in wxWidgets) -// However arcs are drawn as pies, and we must change it. -// Unfortunately most of functions are private, and we cannot derive -// our KicadSVGFileDCImpl from wxSVGFileDCImpl -// and just override the 2 incorrect functions -// Just wxWidget dcsvg is copied here and 2 functions are modified: -// KicadSVGFileDCImpl::DoDrawArc() and KicadSVGFileDCImpl::DoDrawEllipticArc() - -namespace -{ - -inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } - -// This function returns a string representation of a floating point number in -// C locale (i.e. always using "." for the decimal separator) and with the -// fixed precision (which is 2 for some unknown reason but this is what it was -// in this code originally). -inline wxString NumStr(double f) -{ - return wxString::FromCDouble(f, 2); -} - -// Return the colour representation as HTML-like "#rrggbb" string and also -// returns its alpha as opacity number in 0..1 range. -wxString Col2SVG(wxColour c, float *opacity) -{ - if ( c.Alpha() != wxALPHA_OPAQUE ) - { - *opacity = c.Alpha()/255.; - - // Remove the alpha before using GetAsString(wxC2S_HTML_SYNTAX) as it - // doesn't support colours with alpha channel. - c = wxColour(c.GetRGB()); - } - else // No alpha. - { - *opacity = 1.; - } - - return c.GetAsString(wxC2S_HTML_SYNTAX); -} - -wxString wxPenString(wxColour c, int style = wxPENSTYLE_SOLID) -{ - float opacity; - wxString s = wxT("stroke:") + Col2SVG(c, &opacity) + wxT("; "); - - switch ( style ) - { - case wxPENSTYLE_SOLID: - s += wxString::Format(wxT("stroke-opacity:%s; "), NumStr(opacity)); - break; - case wxPENSTYLE_TRANSPARENT: - s += wxT("stroke-opacity:0.0; "); - break; - default : - wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Pen Style not available")); - } - - return s; -} - -wxString wxBrushString(wxColour c, int style = wxBRUSHSTYLE_SOLID) -{ - float opacity; - wxString s = wxT("fill:") + Col2SVG(c, &opacity) + wxT("; "); - - switch ( style ) - { - case wxBRUSHSTYLE_SOLID: - s += wxString::Format(wxT("fill-opacity:%s; "), NumStr(opacity)); - break; - case wxBRUSHSTYLE_TRANSPARENT: - s += wxT("fill-opacity:0.0; "); - break; - default : - wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available")); - } - - return s; -} - -} // anonymous namespace - -// ---------------------------------------------------------- -// KicadSVGFileDCImpl -// ---------------------------------------------------------- - -IMPLEMENT_ABSTRACT_CLASS(KicadSVGFileDCImpl, wxDC) - -KicadSVGFileDCImpl::KicadSVGFileDCImpl( KicadSVGFileDC *owner, const wxString &aFilename, - wxPoint aOrigin, wxSize aSize, double aDpi ) : - wxDCImpl( owner ) - { - Init( aFilename, aOrigin, aSize, aDpi ); - } - -void KicadSVGFileDCImpl::Init ( const wxString &aFilename, - wxPoint aOrigin, wxSize aSize, double aDpi) -{ - m_width = aSize.x; - m_height = aSize.y; - - m_dpi = aDpi; - - m_OK = true; - - m_mm_to_pix_x = m_dpi/25.4; - m_mm_to_pix_y = m_dpi/25.4; - - m_backgroundBrush = *wxTRANSPARENT_BRUSH; - m_textForegroundColour = *wxBLACK; - m_textBackgroundColour = *wxWHITE; - m_colour = wxColourDisplay(); - - m_pen = *wxBLACK_PEN; - m_font = *wxNORMAL_FONT; - m_brush = *wxWHITE_BRUSH; - - m_graphics_changed = true; - - ////////////////////code here - - m_outfile = new wxFileOutputStream(aFilename); - m_OK = m_outfile->IsOk(); - if (m_OK) - { - m_filename = aFilename; - m_sub_images = 0; - wxString s; - s = wxT("") + wxString(wxT("\n")); - write(s); - s = wxT(" ") + wxString(wxT("\n")); - write(s); - s = wxT(" \n"), - NumStr(float(m_width)/m_dpi*2.54), NumStr(float(m_height)/m_dpi*2.54), - aOrigin.x, aOrigin.y, m_width, m_height ); - write(s); - s = wxT("SVG Picture created as ") + wxFileName(m_filename).GetFullName() + wxT(" ") + wxT("\n"); - write(s); - s = wxString (wxT("Picture generated by wxSVG ")) + wxSVGVersion + wxT(" ")+ wxT("\n"); - write(s); - s = wxT("") + wxString(wxT("\n")); - write(s); - } -} - -KicadSVGFileDCImpl::~KicadSVGFileDCImpl() -{ - wxString s = wxT(" \n \n"); - write(s); - delete m_outfile; -} - -void KicadSVGFileDCImpl::DoGetSizeMM( int *width, int *height ) const -{ - if (width) - *width = KiROUND( (double)m_width / m_mm_to_pix_x ); - - if (height) - *height = KiROUND( (double)m_height / m_mm_to_pix_y ); -} - -wxSize KicadSVGFileDCImpl::GetPPI() const -{ - return wxSize( KiROUND(m_dpi), KiROUND(m_dpi) ); -} - -void KicadSVGFileDCImpl::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) -{ - if (m_graphics_changed) NewGraphics(); - wxString s; - s.Printf ( wxT(" \n"), x1,y1,x2,y2 ); - if (m_OK) - { - write(s); - } - CalcBoundingBox(x1, y1); - CalcBoundingBox(x2, y2); -} - -void KicadSVGFileDCImpl::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset ) -{ - for ( int i = 1; i < n; i++ ) - { - DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset, - points [ i ].x + xoffset, points [ i ].y + yoffset ); - } -} - -void KicadSVGFileDCImpl::DoDrawPoint (wxCoord x1, wxCoord y1) -{ - wxString s; - if (m_graphics_changed) NewGraphics(); - s = wxT(" ") + wxString(wxT("\n")); - write(s); - DoDrawLine ( x1,y1,x1,y1 ); - s = wxT(""); - write(s); -} - -void KicadSVGFileDCImpl::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height) -{ - wxDCImpl::DoDrawCheckMark (x1,y1,width,height); -} - -void KicadSVGFileDCImpl::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1) -{ - DoDrawRotatedText(text, x1,y1,0.0); -} - -void KicadSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle) -{ - //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW - if (m_graphics_changed) NewGraphics(); - wxString s, sTmp; - - // calculate bounding box - wxCoord w, h, desc; - DoGetTextExtent(sText, &w, &h, &desc); - - double rad = DegToRad(angle); - - // wxT("upper left") and wxT("upper right") - CalcBoundingBox(x, y); - CalcBoundingBox((wxCoord)(x + w*cos(rad)), (wxCoord)(y - h*sin(rad))); - - // wxT("bottom left") and wxT("bottom right") - x += (wxCoord)(h*sin(rad)); - y += (wxCoord)(h*cos(rad)); - CalcBoundingBox(x, y); - CalcBoundingBox((wxCoord)(x + h*sin(rad)), (wxCoord)(y + h*cos(rad))); - - if (m_backgroundMode == wxBRUSHSTYLE_SOLID) - { - // draw background first - // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background - - sTmp.Printf ( wxT(" "), NumStr(-angle), x,y ); - s += sTmp + wxT("\n"); - write(s); - } - //now do the text itself - s.Printf (wxT(" 0) s += wxT("style=\"font-family:") + sTmp + wxT("; "); - else s += wxT("style=\" "); - - wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") }; - s += wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + wxT("; "); - - wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") }; - s += wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + wxT("; "); - - sTmp.Printf (wxT("font-size:%dpt; "), m_font.GetPointSize() ); - s += sTmp; - //text will be solid, unless alpha value isn't opaque in the foreground colour - s += wxBrushString(m_textForegroundColour) + wxPenString(m_textForegroundColour); - sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %s %d %d ) \" >"), NumStr(-angle), x,y ); - s += sTmp + sText + wxT(" ") + wxT("\n"); - if (m_OK) - { - write(s); - } -} - -void KicadSVGFileDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) -{ - DoDrawRoundedRectangle(x, y, width, height, 0); -} - -void KicadSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) - -{ - if (m_graphics_changed) NewGraphics(); - wxString s; - - s.Printf ( wxT(" \n"); - write(s); - - CalcBoundingBox(x, y); - CalcBoundingBox(x + width, y + height); -} - -void KicadSVGFileDCImpl::DoDrawPolygon(int n, wxPoint points[], - wxCoord xoffset, wxCoord yoffset, - wxPolygonFillMode fillStyle) -{ - if (m_graphics_changed) NewGraphics(); - wxString s, sTmp; - s = wxT(" \n"); - write(s); -} - -void KicadSVGFileDCImpl::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height) - -{ - if (m_graphics_changed) NewGraphics(); - - int rh = height /2; - int rw = width /2; - - wxString s; - s.Printf ( wxT(" \n"); - - write(s); - - CalcBoundingBox(x, y); - CalcBoundingBox(x + width, y + height); -} - -void KicadSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc) -{ - /* Draws an arc of a circle, centred on (xc, yc), with starting point - (x1, y1) and ending at (x2, y2). The current pen is used for the outline - and the current brush for filling the shape. - - The arc is drawn in an anticlockwise direction from the start point to - the end point - */ - - if (m_graphics_changed) NewGraphics(); - wxString s; - - // we need the radius of the circle which has two estimates - double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) ); - double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) ); - - wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")); - if ( fabs ( r2-r1 ) > 3 ) //pixels - { - s = wxT(" \n"); - write(s); - } - - double theta1 = atan2((double)(yc-y1),(double)(x1-xc)); - if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2; - double theta2 = atan2((double)(yc-y2), (double)(x2-xc)); - if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2; - if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2; - - int fArc; // flag for large or small arc 0 means less than 180 degrees - if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0; - - int fSweep = 0; // flag for sweep always 0 - - // Draw a pie: - // the z means close the path and fill - // s.Printf ( wxT(" \n"); - - if (m_OK) - { - write(s); - } -} - -void KicadSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea) -{ - /* - Draws an arc of an ellipse. The current pen is used for drawing the arc - and the current brush is used for drawing the pie. This function is - currently only available for X window and PostScript device contexts. - - x and y specify the x and y coordinates of the upper-left corner of the - rectangle that contains the ellipse. - - width and height specify the width and height of the rectangle that - contains the ellipse. - - start and end specify the start and end of the arc relative to the - three-o'clock position from the center of the rectangle. Angles are - specified in degrees (360 is a complete circle). Positive values mean - counter-clockwise motion. If start is equal to end, a complete ellipse - will be drawn. */ - - //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW - - if (m_graphics_changed) NewGraphics(); - - wxString s; - //radius - double rx = w / 2; - double ry = h / 2; - // center - double xc = x + rx; - double yc = y + ry; - - double xs, ys, xe, ye; - xs = xc + rx * cos (DegToRad(sa)); - xe = xc + rx * cos (DegToRad(ea)); - ys = yc - ry * sin (DegToRad(sa)); - ye = yc - ry * sin (DegToRad(ea)); - - ///now same as circle arc... - - double theta1 = atan2(ys-yc, xs-xc); - double theta2 = atan2(ye-yc, xe-xc); - - int fArc; // flag for large or small arc 0 means less than 180 degrees - if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0; - - int fSweep; - if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0; - - // Draw a pie: - // s.Printf ( wxT(" \n"); - - if (m_OK) - { - write(s); - } -} - -void KicadSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const - -{ - wxScreenDC sDC; - - sDC.SetFont (m_font); - if ( font != NULL ) sDC.SetFont ( *font ); - sDC.GetTextExtent(string, w, h, descent, externalLeading ); -} - -wxCoord KicadSVGFileDCImpl::GetCharHeight() const -{ - wxScreenDC sDC; - sDC.SetFont (m_font); - - return sDC.GetCharHeight(); - -} - -wxCoord KicadSVGFileDCImpl::GetCharWidth() const -{ - wxScreenDC sDC; - sDC.SetFont (m_font); - - return sDC.GetCharWidth(); -} - - -// ---------------------------------------------------------- -// wxSVGFileDCImpl - set functions -// ---------------------------------------------------------- - -void KicadSVGFileDCImpl::SetBackground( const wxBrush &brush ) -{ - m_backgroundBrush = brush; -} - - -void KicadSVGFileDCImpl::SetBackgroundMode( int mode ) -{ - m_backgroundMode = mode; -} - - -void KicadSVGFileDCImpl::SetBrush(const wxBrush& brush) - -{ - m_brush = brush; - - m_graphics_changed = true; -} - - -void KicadSVGFileDCImpl::SetPen(const wxPen& pen) -{ - // width, color, ends, joins : currently implemented - // dashes, stipple : not implemented - m_pen = pen; - - m_graphics_changed = true; -} - -void KicadSVGFileDCImpl::NewGraphics() -{ - wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn; - - sBrush = wxT("\n"), - m_pen.GetWidth(), NumStr(m_logicalOriginX), NumStr(m_logicalOriginY), NumStr(m_scaleX), NumStr(m_scaleY) ); - - s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + wxT("\n") + sWarn; - write(s); - m_graphics_changed = false; -} - - -void KicadSVGFileDCImpl::SetFont(const wxFont& font) - -{ - m_font = font; -} - -// export a bitmap as a raster image in png -bool KicadSVGFileDCImpl::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, - wxDC* source, wxCoord xsrc, wxCoord ysrc, - wxRasterOperationMode logicalFunc /*= wxCOPY*/, bool useMask /*= false*/, - wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/) -{ - if (logicalFunc != wxCOPY) - { - wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")); - return false; - } - if (useMask != false) - { - wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested false mask; this is not possible")); - return false; - } - wxBitmap myBitmap (width, height); - wxMemoryDC memDC; - memDC.SelectObject( myBitmap ); - memDC.Blit(0, 0, width, height, source, xsrc, ysrc); - memDC.SelectObject( wxNullBitmap ); - DoDrawBitmap(myBitmap, xdest, ydest); - return false; -} - -void KicadSVGFileDCImpl::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y) -{ - wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() ); - wxMemoryDC memDC; - memDC.SelectObject( myBitmap ); - memDC.DrawIcon(myIcon,0,0); - memDC.SelectObject( wxNullBitmap ); - DoDrawBitmap(myBitmap, x, y); -} - -void KicadSVGFileDCImpl::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ ) -{ - if (m_graphics_changed) NewGraphics(); - - wxString sTmp, s, sPNG; - if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG) == NULL ) - wxImage::AddHandler(new wxPNGHandler); - -// create suitable file name - sTmp.Printf ( wxT("_image%d.png"), m_sub_images); - sPNG = m_filename.BeforeLast(wxT('.')) + sTmp; - while (wxFile::Exists(sPNG) ) - { - m_sub_images ++; - sTmp.Printf ( wxT("_image%d.png"), m_sub_images); - sPNG = m_filename.BeforeLast(wxT('.')) + sTmp; - } - -//create copy of bitmap (wxGTK doesn't like saving a constant bitmap) - wxBitmap myBitmap = bmp; -//save it - bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG); - -// reference the bitmap from the SVG doc -// only use filename & ext - sPNG = sPNG.AfterLast(wxFileName::GetPathSeparator()); - -// reference the bitmap from the SVG doc - int w = myBitmap.GetWidth(); - int h = myBitmap.GetHeight(); - sTmp.Printf ( wxT(" \n"), sPNG.c_str() ); - s += sTmp + wxT("Image from wxSVG ") + wxT("\n"); - - if (m_OK && bPNG_OK) - { - write(s); - } - m_OK = m_outfile->IsOk() && bPNG_OK; -} - -void KicadSVGFileDCImpl::write(const wxString &s) -{ - const wxCharBuffer buf = s.utf8_str(); - m_outfile->Write(buf, strlen((const char *)buf)); - m_OK = m_outfile->IsOk(); -} - -#else - -#define newline wxString( wxT( "\n" ) ) -#define space wxString( wxT( " " ) ) -#define semicolon wxString( wxT( ";" ) ) - -#ifdef __BORLANDC__ -#pragma warn -rch -#pragma warn -ccc -#endif - - -/* some define not included in early wxWidget versions: */ -#ifndef twips2mm -#define twips2mm 0.0176388888889 -#endif -#ifndef pt2mm -#define pt2mm 0.352777777778 -#endif - -static inline double DegToRad( double deg ) -{ - return (deg * M_PI) / 180.0; -} - -wxString wxColStr( wxColour c ) -{ - unsigned char r, g, b; - - r = c.Red(); - g = c.Green(); - b = c.Blue(); - - // possible Unicode bug here - wxString s = wxDecToHex( r ) + wxDecToHex( g ) + wxDecToHex( b ); - return s; -} - - -wxString wxBrushString( wxColour c, int style ) -{ - wxString s = wxT( "fill:#" ) + wxColStr( c ) + semicolon + space; - - switch( style ) - { - case wxSOLID: - s = s + wxT( "fill-opacity:1.0; " ); - break; - - case wxTRANSPARENT: - s = s + wxT( "fill-opacity:0.0; " ); - break; - - default: - wxASSERT_MSG( false, wxT( "wxSVGFileDC::Requested Brush Style not available" ) ); - } - - s = s + newline; - return s; -} - - -/***********************************************************************/ -void wxSVGFileDC::Init( const wxString& aFilename, - wxPoint aOrigin, wxSize aSize, double aDpi ) -/***********************************************************************/ - -/* set up things first wxDCBase does all this? - */ -{ - m_width = aSize.x; - m_height = aSize.y; - - m_clipping = false; - m_OK = true; - - m_mm_to_pix_x = aDpi / 25.4; - m_mm_to_pix_y = aDpi / 25.4; - - m_signX = m_signY = 1; - - m_userScaleX = m_userScaleY = - m_deviceOriginX = m_deviceOriginY = 0; - - m_OriginX = m_OriginY = 0; - m_logicalOriginX = m_logicalOriginY = 0; - m_logicalScaleX = m_logicalScaleY = 0; - m_scaleX = m_scaleY = 1.0; - - m_logicalFunction = wxCOPY; - m_backgroundMode = wxTRANSPARENT; - m_mappingMode = wxMM_TEXT; - - m_backgroundBrush = *wxTRANSPARENT_BRUSH; - m_textForegroundColour = *wxBLACK; - m_textBackgroundColour = *wxWHITE; - m_colour = wxColourDisplay(); - - m_pen = *wxBLACK_PEN; - m_font = *wxNORMAL_FONT; - m_brush = *wxWHITE_BRUSH; - - m_graphics_changed = true; - - ////////////////////code here - - m_outfile = new wxFileOutputStream( aFilename ); - m_OK = m_outfile->Ok(); - if( m_OK ) - { - m_filename = aFilename; - m_sub_images = 0; - wxString s; - s = wxT( "" ); s = s + newline; - write( s ); - s = wxT( " " ) + newline; - write( s ); - - s.Printf( wxT( "\n" ) ); - write( s ); - - s = wxT( " SVG Picture created as " ) + wxFileNameFromPath( aFilename ) + - wxT( " " ) + newline; - write( s ); - s = wxString( wxT( " Picture generated by wxSVG " ) ) + wxSVGVersion + wxT( - " " ) + newline; - write( s ); - s = wxT( " " ) + newline; - write( s ); - } -} - - -// constructor -wxSVGFileDC::wxSVGFileDC( const wxString &aFilename, - wxPoint aOrigin, wxSize aSize, double aDpi ) -{ - Init( aFilename, aOrigin, aSize, aDpi); -} - -wxSVGFileDC::~wxSVGFileDC() -{ - wxString s = wxT( " \n \n" ); - - write( s ); - delete m_outfile; -} - - -////////////////////////////////////////////////////////////////////////////////////////// - -void wxSVGFileDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) -{ - if( m_graphics_changed ) - NewGraphics(); - wxString s; - s.Printf( wxT( " \n" ), x1, y1, x2, y2 ); - if( m_OK ) - { - write( s ); - } - CalcBoundingBox( x1, y1 ); - CalcBoundingBox( x2, y2 ); - return; -} - -void wxSVGFileDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset ) -{ - for( int i = 1; i < n; i++ ) - { - DoDrawLine( points[i - 1].x + xoffset, points[i - 1].y + yoffset, - points[ i ].x + xoffset, points[ i ].y + yoffset ); - } -} - - -void wxSVGFileDC::DoDrawPoint( wxCoord x1, wxCoord y1 ) -{ - wxString s; - - if( m_graphics_changed ) - NewGraphics(); - s = wxT( " " ) + newline; - write( s ); - DrawLine( x1, y1, x1, y1 ); - s = wxT( "" ); - write( s ); -} - - -void wxSVGFileDC::DoDrawCheckMark( wxCoord x1, wxCoord y1, wxCoord width, wxCoord height ) -{ - wxDCBase::DoDrawCheckMark( x1, y1, width, height ); -} - - -void wxSVGFileDC::DoDrawText( const wxString& text, wxCoord x1, wxCoord y1 ) -{ - DoDrawRotatedText( text, x1, y1, 0.0 ); -} - - -void wxSVGFileDC::DoDrawRotatedText( const wxString& sText, wxCoord x, wxCoord y, double angle ) -{ - //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW - if( m_graphics_changed ) - NewGraphics(); - wxString s, sTmp; - - // calculate bounding box - wxCoord w, h, desc; - DoGetTextExtent( sText, &w, &h, &desc ); - - double rad = DegToRad( angle ); - - // wxT("upper left") and wxT("upper right") - CalcBoundingBox( x, y ); - CalcBoundingBox( (wxCoord) ( x + w * cos( rad ) ), (wxCoord) ( y - h * sin( rad ) ) ); - - // wxT("bottom left") and wxT("bottom right") - x += (wxCoord) ( h * sin( rad ) ); - y += (wxCoord) ( h * cos( rad ) ); - CalcBoundingBox( x, y ); - CalcBoundingBox( (wxCoord) ( x + h * sin( rad ) ), (wxCoord) ( y + h * cos( rad ) ) ); - - if( m_backgroundMode == wxSOLID ) - { - // draw background first - // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background - - sTmp.Printf( wxT( - " " ), -angle, x, y ); - s = s + sTmp + newline; - write( s ); - } - - //now do the text itself - s.Printf( wxT( " 0 ) - s = s + wxT( "style=\"font-family:" ) + sTmp + wxT( "; " ); - else - s = s + wxT( "style=\" " ); - - wxString fontweights[3] = { wxT( "normal" ), wxT( "lighter" ), wxT( "bold" ) }; - s = s + wxT( "font-weight:" ) + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space; - - wxString fontstyles[5] = { - wxT( "normal" ), wxT( "style error" ), wxT( "style error" ), wxT( - "italic" ), wxT( "oblique" ) - }; - s = s + wxT( "font-style:" ) + fontstyles[m_font.GetStyle() - wxNORMAL] + semicolon + space; - - sTmp.Printf( wxT( "font-size:%dpt; fill:#" ), m_font.GetPointSize() ); - s = s + sTmp; - s = s + wxColStr( m_textForegroundColour ) + wxT( "; stroke:#" ) + wxColStr( - m_textForegroundColour ) + wxT( "; " ); - sTmp.Printf( wxT( "stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >" ), -angle, x, y ); - s = s + sTmp + sText + wxT( " " ) + newline; - if( m_OK ) - { - write( s ); - } -} - - -void wxSVGFileDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) -{ - DoDrawRoundedRectangle( x, y, width, height, 0 ); -} - - -void wxSVGFileDC::DoDrawRoundedRectangle( wxCoord x, - wxCoord y, - wxCoord width, - wxCoord height, - double radius ) - -{ - if( m_graphics_changed ) - NewGraphics(); - wxString s; - - s.Printf( wxT( " " ) + newline; - write( s ); - - CalcBoundingBox( x, y ); - CalcBoundingBox( x + width, y + height ); -} - - -void wxSVGFileDC::DoDrawPolygon( int n, - wxPoint points[], - wxCoord xoffset, - wxCoord yoffset, - int fillStyle ) -{ - if( m_graphics_changed ) - NewGraphics(); - wxString s, sTmp; - s = wxT( " " ); - s = s + newline; - write( s ); -} - - -void wxSVGFileDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) - -{ - if( m_graphics_changed ) - NewGraphics(); - - int rh = height / 2; - int rw = width / 2; - - wxString s; - s.Printf( wxT( " " ) + newline; - - write( s ); - - CalcBoundingBox( x, y ); - CalcBoundingBox( x + width, y + height ); -} - - -void wxSVGFileDC::DoDrawArc( wxCoord x1, - wxCoord y1, - wxCoord x2, - wxCoord y2, - wxCoord xc, - wxCoord yc ) -{ - /* Draws an arc of a circle, centred on (xc, yc), with starting point - * (x1, y1) and ending at (x2, y2). The current pen is used for the outline - * and the current brush for filling the shape. - * - * The arc is drawn in an anticlockwise direction from the start point to - * the end point. */ - - if( m_graphics_changed ) - NewGraphics(); - wxString s; - - // we need the radius of the circle which has two estimates - double r1 = sqrt( double ( (x1 - xc) * (x1 - xc) ) + double ( (y1 - yc) * (y1 - yc) ) ); - double r2 = sqrt( double ( (x2 - xc) * (x2 - xc) ) + double ( (y2 - yc) * (y2 - yc) ) ); - - wxASSERT_MSG( (fabs( r2 - r1 ) <= 3), - wxT( "wxSVGFileDC::DoDrawArc Error in getting radii of circle" ) ); - if( fabs( r2 - r1 ) > 3 ) //pixels - { - s = wxT( " \n" ); - write( s ); - } - - double theta1 = atan2( (double) (yc - y1), (double) (x1 - xc) ); - if( theta1 < 0 ) - theta1 = theta1 + M_PI * 2; - double theta2 = atan2( (double) (yc - y2), (double) (x2 - xc) ); - if( theta2 < 0 ) - theta2 = theta2 + M_PI * 2; - if( theta2 < theta1 ) - theta2 = theta2 + M_PI * 2; - - int fArc; // flag for large or small arc 0 means less than 180 degrees - if( fabs( theta2 - theta1 ) > M_PI ) - fArc = 1;else - fArc = 0; - - int fSweep; - if( (theta2 - theta1) > 0 ) - fSweep = 0;else - fSweep = 1; - float Axis_rotation = 0.0; - -// Draw arc as pie: -// s.Printf ( wxT(" " ) + newline; - - - if( m_OK ) - { - write( s ); - } -} - - -void wxSVGFileDC::DoDrawEllipticArc( wxCoord x, - wxCoord y, - wxCoord w, - wxCoord h, - double sa, - double ea ) -{ - /* - * Draws an arc of an ellipse. The current pen is used for drawing the arc - * and the current brush is used for drawing the pie. This function is - * currently only available for X window and PostScript device contexts. - * - * x and y specify the x and y coordinates of the upper-left corner of the - * rectangle that contains the ellipse. - * - * width and height specify the width and height of the rectangle that - * contains the ellipse. - * - * start and end specify the start and end of the arc relative to the - * three-o'clock position from the center of the rectangle. Angles are - * specified in degrees (360 is a complete circle). Positive values mean - * counter-clockwise motion. If start is equal to end, a complete ellipse - * will be drawn. */ - - //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW - - if( m_graphics_changed ) - NewGraphics(); - - wxString s; - - //radius - double rx = w / 2; - double ry = h / 2; - - // center - double xc = x + rx; - double yc = y + ry; - - double xs, ys, xe, ye; - xs = xc + rx* cos( DegToRad (sa) ); - - xe = xc + rx* cos( DegToRad (ea) ); - - ys = yc - ry* sin( DegToRad (sa) ); - - ye = yc - ry* sin( DegToRad (ea) ); - - ///now same as circle arc... - - double theta1 = atan2( ys - yc, xs - xc ); - double theta2 = atan2( ye - yc, xe - xc ); - - int fArc; // flag for large or small arc 0 means less than 180 degrees - if( fabs( theta2 - theta1 ) > M_PI ) - fArc = 1;else - fArc = 0; - - int fSweep; - if( (theta2 - theta1) > 0 ) - fSweep = 0;else - fSweep = 1; - float Axis_rotation = 0.0; - - // Draw a single arc: - s.Printf( wxT( " " ) + newline; - - if( m_OK ) - { - write( s ); - } -} - - -void wxSVGFileDC::DoGetTextExtent( const wxString& string, - wxCoord* w, - wxCoord* h, - wxCoord* descent, - wxCoord* externalLeading, - wxFont* font ) const - -{ - wxScreenDC sDC; - - sDC.SetFont( m_font ); - if( font != NULL ) - sDC.SetFont( *font ); - sDC.GetTextExtent( string, w, h, descent, externalLeading ); -} - - -wxCoord wxSVGFileDC::GetCharHeight() const - -{ - wxScreenDC sDC; - - sDC.SetFont( m_font ); - - return sDC.GetCharHeight(); -} - - -wxCoord wxSVGFileDC::GetCharWidth() const -{ - wxScreenDC sDC; - - sDC.SetFont( m_font ); - - return sDC.GetCharWidth(); -} - - -/// Set Functions ///////////////////////////////////////////////////////////////// -void wxSVGFileDC::SetBackground( const wxBrush& brush ) -{ - m_backgroundBrush = brush; - return; -} - - -void wxSVGFileDC::SetBackgroundMode( int mode ) -{ - m_backgroundMode = mode; - return; -} - - -void wxSVGFileDC::SetBrush( const wxBrush& brush ) - -{ - m_brush = brush; - - m_graphics_changed = true; -} - - -void wxSVGFileDC::SetPen( const wxPen& pen ) -{ - // width, color, ends, joins : currently implemented - // dashes, stipple : not implemented - m_pen = pen; - - m_graphics_changed = true; -} - - -void wxSVGFileDC::NewGraphics() -{ - int w = m_pen.GetWidth(); - wxColour c = m_pen.GetColour(); - - wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn; - - sBrush = wxT( "\n \n" ); - } - - sLast.Printf( wxT( - "stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">" ), - w, m_OriginX, m_OriginY, m_scaleX, m_scaleY ); - - s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn; - write( s ); - m_graphics_changed = false; -} - - -void wxSVGFileDC::SetFont( const wxFont& font ) - -{ - m_font = font; -} - - -void wxSVGFileDC::ComputeScaleAndOrigin() -{ - m_scaleX = m_logicalScaleX * m_userScaleX; - m_scaleY = m_logicalScaleY * m_userScaleY; - m_OriginX = m_logicalOriginX * m_logicalScaleX + m_deviceOriginX; - m_OriginY = m_logicalOriginY * m_logicalScaleY + m_deviceOriginY; - m_graphics_changed = true; -} - - -int wxSVGFileDC::GetMapMode() -{ - return m_mappingMode; -} - - -void wxSVGFileDC::SetMapMode( int mode ) -{ - switch( mode ) - { - case wxMM_TWIPS: - SetLogicalScale( twips2mm * m_mm_to_pix_x, twips2mm * m_mm_to_pix_y ); - break; - - case wxMM_POINTS: - SetLogicalScale( pt2mm * m_mm_to_pix_x, pt2mm * m_mm_to_pix_y ); - break; - - case wxMM_METRIC: - SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y ); - break; - - case wxMM_LOMETRIC: - SetLogicalScale( m_mm_to_pix_x / 10.0, m_mm_to_pix_y / 10.0 ); - break; - - default: - case wxMM_TEXT: - SetLogicalScale( 1.0, 1.0 ); - break; - } - - m_mappingMode = mode; - - /* we don't do this mega optimisation - * if (mode != wxMM_TEXT) - * { - * m_needComputeScaleX = true; - * m_needComputeScaleY = true; - * } - */ -} - - -void wxSVGFileDC::GetUserScale( double* x, double* y ) const -{ - *x = m_userScaleX; - *y = m_userScaleY; -} - - -void wxSVGFileDC::SetUserScale( double x, double y ) -{ - // allow negative ? -> no - m_userScaleX = x; - m_userScaleY = y; - ComputeScaleAndOrigin(); -} - - -void wxSVGFileDC::SetLogicalScale( double x, double y ) -{ - // allow negative ? - m_logicalScaleX = x; - m_logicalScaleY = y; - ComputeScaleAndOrigin(); -} - - -void wxSVGFileDC::SetLogicalOrigin( wxCoord x, wxCoord y ) -{ - // is this still correct ? - m_logicalOriginX = x * m_signX; - m_logicalOriginY = y * m_signY; - ComputeScaleAndOrigin(); -} - - -void wxSVGFileDC::SetDeviceOrigin( wxCoord x, wxCoord y ) -{ - // only wxPostScripDC has m_signX = -1, - m_deviceOriginX = x; - m_deviceOriginY = y; - ComputeScaleAndOrigin(); -} - - -void wxSVGFileDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) -{ - // only wxPostScripDC has m_signX = -1, - m_signX = (xLeftRight ? 1 : -1); - m_signY = (yBottomUp ? -1 : 1); - ComputeScaleAndOrigin(); -} - - -// export a bitmap as a raster image in png -bool wxSVGFileDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, - wxDC* source, wxCoord xsrc, wxCoord ysrc, - int logicalFunc /*= wxCOPY*/, bool useMask /*= false*/, - wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/ ) -{ - if( logicalFunc != wxCOPY ) - { - wxASSERT_MSG( false, - wxT( "wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible" ) - ); - return false; - } - if( useMask != false ) - { - wxASSERT_MSG( false, - wxT( "wxSVGFileDC::DoBlit Call requested False mask ; this is not possible" ) - ); - return false; - } - wxBitmap myBitmap( width, height ); - wxMemoryDC memDC; - memDC.SelectObject( myBitmap ); - memDC.Blit( 0, 0, width, height, source, xsrc, ysrc ); - memDC.SelectObject( wxNullBitmap ); - DoDrawBitmap( myBitmap, xdest, ydest ); - return false; -} - - -void wxSVGFileDC::DoDrawIcon( const class wxIcon& myIcon, wxCoord x, wxCoord y ) -{ - wxBitmap myBitmap( myIcon.GetWidth(), myIcon.GetHeight() ); - wxMemoryDC memDC; - - memDC.SelectObject( myBitmap ); - memDC.DrawIcon( myIcon, 0, 0 ); - memDC.SelectObject( wxNullBitmap ); - DoDrawBitmap( myBitmap, x, y ); - return; -} - - -void wxSVGFileDC::DoDrawBitmap( const class wxBitmap& bmp, - wxCoord x, - wxCoord y, - bool bTransparent /*=0*/ ) -{ - if( m_graphics_changed ) - NewGraphics(); - - wxString sTmp, s, sPNG; - wxImage::AddHandler( new wxPNGHandler ); - -// create suitable file name - sTmp.Printf( wxT( "_image%d.png" ), m_sub_images ); - sPNG = m_filename.BeforeLast( wxT( '.' ) ) + sTmp; - while( wxFile::Exists( sPNG ) ) - { - m_sub_images++; - sTmp.Printf( wxT( "_image%d.png" ), m_sub_images ); - sPNG = m_filename.BeforeLast( wxT( '.' ) ) + sTmp; - } - -//create copy of bitmap (wxGTK doesn't like saving a constant bitmap) - wxBitmap myBitmap = bmp; - -//save it - bool bPNG_OK = myBitmap.SaveFile( sPNG, wxBITMAP_TYPE_PNG ); - -// refrence the bitmap from the SVG doc - int w = myBitmap.GetWidth(); - int h = myBitmap.GetHeight(); - sTmp.Printf( wxT( " \n" ), GetChars( sPNG ) ); - s = s + sTmp + wxT( "Image from wxSVG " ) + newline; - - if( m_OK && bPNG_OK ) - { - write( s ); - } - m_OK = m_outfile->Ok() && bPNG_OK; - - return; -} - - -// --------------------------------------------------------------------------- -// coordinates transformations -// --------------------------------------------------------------------------- - -wxCoord wxSVGFileDC::DeviceToLogicalX( wxCoord x ) const -{ - return XDEV2LOG( x ); -} - - -wxCoord wxSVGFileDC::DeviceToLogicalY( wxCoord y ) const -{ - return YDEV2LOG( y ); -} - - -wxCoord wxSVGFileDC::DeviceToLogicalXRel( wxCoord x ) const -{ - return XDEV2LOGREL( x ); -} - - -wxCoord wxSVGFileDC::DeviceToLogicalYRel( wxCoord y ) const -{ - return YDEV2LOGREL( y ); -} - - -wxCoord wxSVGFileDC::LogicalToDeviceX( wxCoord x ) const -{ - return XLOG2DEV( x ); -} - - -wxCoord wxSVGFileDC::LogicalToDeviceY( wxCoord y ) const -{ - return YLOG2DEV( y ); -} - - -wxCoord wxSVGFileDC::LogicalToDeviceXRel( wxCoord x ) const -{ - return XLOG2DEVREL( x ); -} - - -wxCoord wxSVGFileDC::LogicalToDeviceYRel( wxCoord y ) const -{ - return YLOG2DEVREL( y ); -} - - -void wxSVGFileDC::write( const wxString& s ) -{ - const wxWX2MBbuf buf = s.mb_str( wxConvUTF8 ); - - m_outfile->Write( buf, strlen( (const char*) buf ) ); - m_OK = m_outfile->Ok(); -} - -#endif // wxCHECK_VERSION diff --git a/common/dialog_shim.cpp b/common/dialog_shim.cpp index 47066e77c7..1d50a08908 100644 --- a/common/dialog_shim.cpp +++ b/common/dialog_shim.cpp @@ -46,7 +46,17 @@ static RECT_MAP class_map; bool DIALOG_SHIM::Show( bool show ) { bool ret; - const char* classname = typeid(*this).name(); + const char* hash_key; + + if( m_hash_key.size() ) + { + // a special case like EDA_LIST_DIALOG, which has multiple uses. + hash_key = m_hash_key.c_str(); + } + else + { + hash_key = typeid(*this).name(); + } // Show or hide the window. If hiding, save current position and size. // If showing, use previous position and size. @@ -55,7 +65,7 @@ bool DIALOG_SHIM::Show( bool show ) ret = wxDialog::Show( show ); // classname is key, returns a zeroed out default EDA_RECT if none existed before. - EDA_RECT r = class_map[ classname ]; + EDA_RECT r = class_map[ hash_key ]; if( r.GetSize().x != 0 && r.GetSize().y != 0 ) SetSize( r.GetPosition().x, r.GetPosition().y, r.GetSize().x, r.GetSize().y, 0 ); @@ -64,7 +74,7 @@ bool DIALOG_SHIM::Show( bool show ) { // Save the dialog's position & size before hiding, using classname as key EDA_RECT r( wxDialog::GetPosition(), wxDialog::GetSize() ); - class_map[ classname ] = r; + class_map[ hash_key ] = r; ret = wxDialog::Show( show ); } diff --git a/common/dialogs/dialog_get_component_base.cpp b/common/dialogs/dialog_get_component_base.cpp index 452a27a065..8e8810c5d0 100644 --- a/common/dialogs/dialog_get_component_base.cpp +++ b/common/dialogs/dialog_get_component_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Apr 10 2012) +// C++ code generated with wxFormBuilder (version Nov 5 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -24,6 +24,7 @@ DIALOG_GET_COMPONENT_BASE::DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindow bSizerLeft->Add( m_staticTextName, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_textCmpNameCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_textCmpNameCtrl->SetMaxLength( 0 ); bSizerLeft->Add( m_textCmpNameCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); m_staticTextHistory = new wxStaticText( this, wxID_ANY, _("History list:"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -63,6 +64,7 @@ DIALOG_GET_COMPONENT_BASE::DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindow this->SetSizer( bSizerMain ); this->Layout(); + bSizerMain->Fit( this ); this->Centre( wxBOTH ); diff --git a/common/dialogs/dialog_get_component_base.fbp b/common/dialogs/dialog_get_component_base.fbp index a39d3372e4..10a950c93f 100644 --- a/common/dialogs/dialog_get_component_base.fbp +++ b/common/dialogs/dialog_get_component_base.fbp @@ -20,8 +20,10 @@ . 1 + 1 1 1 + UI 0 0 @@ -42,7 +44,7 @@ DIALOG_GET_COMPONENT_BASE - 375,210 + -1,-1 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h diff --git a/common/dialogs/dialog_get_component_base.h b/common/dialogs/dialog_get_component_base.h index e40fc7a99c..a0a39d5b27 100644 --- a/common/dialogs/dialog_get_component_base.h +++ b/common/dialogs/dialog_get_component_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Apr 10 2012) +// C++ code generated with wxFormBuilder (version Nov 5 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -11,6 +11,8 @@ #include #include #include +class DIALOG_SHIM; + #include "dialog_shim.h" #include #include @@ -57,7 +59,7 @@ class DIALOG_GET_COMPONENT_BASE : public DIALOG_SHIM public: - DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 375,210 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_GET_COMPONENT_BASE(); }; diff --git a/common/dialogs/dialog_list_selector_base.cpp b/common/dialogs/dialog_list_selector_base.cpp index a4574c9bcf..d8598769b2 100644 --- a/common/dialogs/dialog_list_selector_base.cpp +++ b/common/dialogs/dialog_list_selector_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) +// C++ code generated with wxFormBuilder (version Nov 5 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -29,10 +29,10 @@ EDA_LIST_DIALOG_BASE::EDA_LIST_DIALOG_BASE( wxWindow* parent, wxWindowID id, con m_staticText2->Wrap( -1 ); bSizerMain->Add( m_staticText2, 0, wxRIGHT|wxLEFT, 5 ); - m_listBox = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxVSCROLL ); - m_listBox->SetMinSize( wxSize( 300,200 ) ); + m_listBox = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES|wxALWAYS_SHOW_SB|wxVSCROLL ); + m_listBox->SetMinSize( wxSize( -1,200 ) ); - bSizerMain->Add( m_listBox, 1, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + bSizerMain->Add( m_listBox, 3, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); m_staticTextMsg = new wxStaticText( this, wxID_ANY, _("Messages:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextMsg->Wrap( -1 ); @@ -41,7 +41,7 @@ EDA_LIST_DIALOG_BASE::EDA_LIST_DIALOG_BASE( wxWindow* parent, wxWindowID id, con m_messages = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); m_messages->SetMinSize( wxSize( -1,80 ) ); - bSizerMain->Add( m_messages, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizerMain->Add( m_messages, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); m_sdbSizer = new wxStdDialogButtonSizer(); m_sdbSizerOK = new wxButton( this, wxID_OK ); @@ -55,6 +55,7 @@ EDA_LIST_DIALOG_BASE::EDA_LIST_DIALOG_BASE( wxWindow* parent, wxWindowID id, con this->SetSizer( bSizerMain ); this->Layout(); + bSizerMain->Fit( this ); this->Centre( wxBOTH ); diff --git a/common/dialogs/dialog_list_selector_base.fbp b/common/dialogs/dialog_list_selector_base.fbp index 74591b43d2..7e13578477 100644 --- a/common/dialogs/dialog_list_selector_base.fbp +++ b/common/dialogs/dialog_list_selector_base.fbp @@ -20,8 +20,10 @@ . 1 + 1 1 1 + UI 0 0 @@ -32,7 +34,7 @@ 1 1 - impl_virtual + decl_pure_virtual @@ -42,7 +44,7 @@ EDA_LIST_DIALOG_BASE - 329,398 + -1,-1 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h @@ -351,7 +353,7 @@ 5 wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND - 1 + 3 1 1 @@ -385,7 +387,7 @@ 0 - 300,200 + -1,200 1 m_listBox 1 @@ -397,7 +399,7 @@ Resizable 1 - wxLC_REPORT + wxLC_HRULES|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES 0 @@ -407,7 +409,7 @@ - wxVSCROLL + wxALWAYS_SHOW_SB|wxVSCROLL @@ -539,7 +541,7 @@ 5 wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT - 0 + 1 1 1 diff --git a/common/dialogs/dialog_list_selector_base.h b/common/dialogs/dialog_list_selector_base.h index 7f6c6239f7..162e43785d 100644 --- a/common/dialogs/dialog_list_selector_base.h +++ b/common/dialogs/dialog_list_selector_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) +// C++ code generated with wxFormBuilder (version Nov 5 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -48,17 +48,17 @@ class EDA_LIST_DIALOG_BASE : public DIALOG_SHIM wxButton* m_sdbSizerCancel; // Virtual event handlers, overide them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void textChangeInFilterBox( wxCommandEvent& event ) { event.Skip(); } - virtual void onListItemActivated( wxListEvent& event ) { event.Skip(); } - virtual void onListItemSelected( wxListEvent& event ) { event.Skip(); } - virtual void onCancelClick( wxCommandEvent& event ) { event.Skip(); } - virtual void onOkClick( wxCommandEvent& event ) { event.Skip(); } + virtual void onClose( wxCloseEvent& event ) = 0; + virtual void textChangeInFilterBox( wxCommandEvent& event ) = 0; + virtual void onListItemActivated( wxListEvent& event ) = 0; + virtual void onListItemSelected( wxListEvent& event ) = 0; + virtual void onCancelClick( wxCommandEvent& event ) = 0; + virtual void onOkClick( wxCommandEvent& event ) = 0; public: - EDA_LIST_DIALOG_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 329,398 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + EDA_LIST_DIALOG_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~EDA_LIST_DIALOG_BASE(); }; diff --git a/common/displlst.cpp b/common/displlst.cpp index 5dcaca5f52..1717f2a0f8 100644 --- a/common/displlst.cpp +++ b/common/displlst.cpp @@ -1,7 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or @@ -27,6 +28,7 @@ */ #include +#include #include #include #include @@ -34,8 +36,8 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( EDA_DRAW_FRAME* aParent, const wxString& aTitle, const wxArrayString& aItemHeaders, const std::vector& aItemList, - const wxString& aRefText, - void(*aCallBackFunction)(wxString& Text), + const wxString& aSelection, + void( *aCallBackFunction )( wxString& ), bool aSortList ) : EDA_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle ) { @@ -46,42 +48,90 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( EDA_DRAW_FRAME* aParent, const wxString& aTitl for( unsigned i = 0; i < aItemHeaders.Count(); i++ ) { wxListItem column; + column.SetId( i ); column.SetText( aItemHeaders.Item( i ) ); - column.SetWidth( 300 / aItemHeaders.Count() ); + m_listBox->InsertColumn( i, column ); } InsertItems( aItemList, 0 ); - if( !aRefText.IsEmpty() ) // try to select the item matching aRefText - { - for( unsigned ii = 0; ii < aItemList.size(); ii++ ) - { - if( aItemList[ii][0] == aRefText ) - { - m_listBox->SetItemState( ii, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); - break; - } - } - } - if( m_callBackFct == NULL ) { m_messages->Show( false ); m_staticTextMsg->Show( false ); } - m_filterBox->SetFocus(); + for( unsigned col = 0; col < aItemHeaders.Count(); ++col ) + { + m_listBox->SetColumnWidth( col, wxLIST_AUTOSIZE ); - GetSizer()->Fit( this ); - GetSizer()->SetSizeHints( this ); +#if !wxCHECK_VERSION( 2, 9, 0 ) + // include the column header in the width decision, wx 2.8 forgets this: + wxListItem col_info; + + m_listBox->GetColumn( col, col_info ); + + wxString header = col_info.GetText(); + int headerz = GetTextSize( header, m_listBox ).x; + + // A reasonable column header has about 14 pixels of whitespace + // in addition to the width of the text itself. + headerz += 14; + + if( headerz > col_info.GetWidth() ) + { + col_info.SetWidth( headerz ); + + m_listBox->SetColumn( col, col_info ); + } +#endif + } + + +#if !wxCHECK_VERSION( 2, 9, 0 ) + // wx 2.8.x has bug in wxListCtrl WRT honoring the omission of wxHSCROLL, at least + // on gtk2. Fix by setting minimum width so horizontal wxListCtrl scrolling is + // not needed on 2.8.x because of minumum visible width setting: + { + int width = 0; + + for( unsigned col = 0; col < aItemHeaders.Count(); ++col ) + { + width += m_listBox->GetColumnWidth( col ) + 2; + } + + wxSize sz = m_listBox->GetSize(); + + sz.SetWidth( width ); + + m_listBox->SetMinSize( sz ); + } +#endif + + Fit(); Centre(); -} + if( !!aSelection ) + { + for( unsigned row = 0; row < aItemList.size(); ++row ) + { + if( aItemList[row][0] == aSelection ) + { + m_listBox->SetItemState( row, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); + m_listBox->EnsureVisible( row ); + break; + } + } + } -EDA_LIST_DIALOG::~EDA_LIST_DIALOG() -{ + // DIALOG_SHIM needs a unique hash_key because classname is not sufficient + // because so many dialogs share this same class, with different numbers of + // columns, different column names, and column widths. + m_hash_key = TO_UTF8( aTitle ); + + m_filterBox->SetFocus(); } @@ -111,22 +161,24 @@ void EDA_LIST_DIALOG::textChangeInFilterBox( wxCommandEvent& event ) wxString EDA_LIST_DIALOG::GetTextSelection( int aColumn ) { - wxCHECK_MSG( aColumn < m_listBox->GetColumnCount(), wxEmptyString, + wxCHECK_MSG( unsigned( aColumn ) < unsigned( m_listBox->GetColumnCount() ), wxEmptyString, wxT( "Invalid list control column." ) ); - wxListItem info; - wxString text; - long item = -1; - item = m_listBox->GetNextItem( item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); + long item = m_listBox->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - info.m_mask = wxLIST_MASK_TEXT; - info.m_itemId = item; - info.m_col = aColumn; + if( item >= 0 ) // if something is selected. + { + wxListItem info; - if( !m_listBox->GetItem( info ) ) - return wxEmptyString; + info.m_mask = wxLIST_MASK_TEXT; + info.m_itemId = item; + info.m_col = aColumn; - return info.m_text; + if( m_listBox->GetItem( info ) ) + return info.m_text; + } + + return wxEmptyString; } @@ -150,9 +202,9 @@ void EDA_LIST_DIALOG::InsertItems( const std::vector< wxArrayString >& itemList, { wxASSERT( (int) itemList[row].GetCount() == m_listBox->GetColumnCount() ); + long itemIndex = 0; for( unsigned col = 0; col < itemList[row].GetCount(); col++ ) { - long itemIndex; if( col == 0 ) { diff --git a/common/drawpanel.cpp b/common/drawpanel.cpp index d733d49584..a055fb83b8 100644 --- a/common/drawpanel.cpp +++ b/common/drawpanel.cpp @@ -95,7 +95,9 @@ EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id, #if wxCHECK_VERSION( 2, 9, 5 ) ShowScrollbars( wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS ); + DisableKeyboardScrolling(); #endif + m_scrollIncrementX = std::min( size.x / 8, 10 ); m_scrollIncrementY = std::min( size.y / 8, 10 ); @@ -904,11 +906,22 @@ void EDA_DRAW_PANEL::OnMouseWheel( wxMouseEvent& event ) bool offCenterReq = event.ControlDown() && event.ShiftDown(); offCenterReq = offCenterReq || m_enableZoomNoCenter; +#if wxMAJOR_VERSION >= 2 && wxMINOR_VERSION >= 9 + int axis = event.GetWheelAxis(); +#else + const int axis = 0; +#endif + // This is a zoom in or out command if( event.GetWheelRotation() > 0 ) { if( event.ShiftDown() && !event.ControlDown() ) - cmd.SetId( ID_PAN_UP ); + { + if( axis == 0 ) + cmd.SetId( ID_PAN_UP ); + else + cmd.SetId( ID_PAN_RIGHT ); + } else if( event.ControlDown() && !event.ShiftDown() ) cmd.SetId( ID_PAN_LEFT ); else if( offCenterReq ) @@ -919,7 +932,12 @@ void EDA_DRAW_PANEL::OnMouseWheel( wxMouseEvent& event ) else if( event.GetWheelRotation() < 0 ) { if( event.ShiftDown() && !event.ControlDown() ) - cmd.SetId( ID_PAN_DOWN ); + { + if( axis == 0 ) + cmd.SetId( ID_PAN_DOWN ); + else + cmd.SetId( ID_PAN_LEFT ); + } else if( event.ControlDown() && !event.ShiftDown() ) cmd.SetId( ID_PAN_RIGHT ); else if( offCenterReq ) diff --git a/common/eda_text.cpp b/common/eda_text.cpp index 1ee1906c31..fdadf86c82 100644 --- a/common/eda_text.cpp +++ b/common/eda_text.cpp @@ -32,15 +32,13 @@ #include // RotatePoint #include // EDA_DRAW_PANEL -// until bzr rev 4410, Y position of vertical justification +// until bzr rev 4476, Y position of vertical justification // of multiline texts was incorrectly calculated for BOTTOM // and CENTER vertical justification. (Only the first line was justified) // If this line is left uncommented, the bug is fixed, but // creates a (very minor) issue for existing texts, mainly in Pcbnew // because the text position is sometimes critical. -// Currently, this change is broken for rotated or mirrored texts, -// so keep this line commented until there are fixes -//#define FIX_MULTILINE_VERT_JUSTIF +#define FIX_MULTILINE_VERT_JUSTIF // Conversion to application internal units defined at build time. #if defined( PCBNEW ) @@ -267,38 +265,17 @@ void EDA_TEXT::Draw( EDA_RECT* aClipBox, wxDC* aDC, const wxPoint& aOffset, { if( m_MultilineAllowed ) { - wxPoint pos = m_Pos; + std::vector positions; wxArrayString* list = wxStringSplit( m_Text, '\n' ); - wxPoint offset; + positions.reserve( list->Count() ); - offset.y = GetInterline(); + GetPositionsOfLinesOfMultilineText(positions, list->Count() ); -#ifdef FIX_MULTILINE_VERT_JUSTIF - if( list->Count() > 1 ) + for( unsigned ii = 0; ii < list->Count(); ii++ ) { - switch( m_VJustify ) - { - case GR_TEXT_VJUSTIFY_TOP: - break; - - case GR_TEXT_VJUSTIFY_CENTER: - pos.y -= ( list->Count() - 1 ) * offset.y / 2; - break; - - case GR_TEXT_VJUSTIFY_BOTTOM: - pos.y -= ( list->Count() - 1 ) * offset.y; - break; - } - } -#endif - RotatePoint( &offset, m_Orient ); - - for( unsigned i = 0; iCount(); i++ ) - { - wxString txt = list->Item( i ); + wxString& txt = list->Item( ii ); drawOneLineOfText( aClipBox, aDC, aOffset, aColor, - aDrawMode, aFillMode, txt, pos ); - pos += offset; + aDrawMode, aFillMode, txt, positions[ii] ); } delete (list); @@ -317,6 +294,49 @@ void EDA_TEXT::Draw( EDA_RECT* aClipBox, wxDC* aDC, const wxPoint& aOffset, } +void EDA_TEXT::GetPositionsOfLinesOfMultilineText( + std::vector& aPositions, int aLineCount ) +{ + wxPoint pos = m_Pos; // Position of first line of the + // multiline text according to + // the center of the multiline text block + + wxPoint offset; // Offset to next line. + + offset.y = GetInterline(); + +#ifdef FIX_MULTILINE_VERT_JUSTIF + if( aLineCount > 1 ) + { + switch( m_VJustify ) + { + case GR_TEXT_VJUSTIFY_TOP: + break; + + case GR_TEXT_VJUSTIFY_CENTER: + pos.y -= ( aLineCount - 1 ) * offset.y / 2; + break; + + case GR_TEXT_VJUSTIFY_BOTTOM: + pos.y -= ( aLineCount - 1 ) * offset.y; + break; + } + } + + // Rotate the position of the first line + // around the center of the multiline text block + RotatePoint( &pos, m_Pos, m_Orient ); +#endif + // Rotate the offset lines to increase happened in the right direction + RotatePoint( &offset, m_Orient ); + + for( int ii = 0; ii < aLineCount; ii++ ) + { + aPositions.push_back( pos ); + pos += offset; + } +} + void EDA_TEXT::drawOneLineOfText( EDA_RECT* aClipBox, wxDC* aDC, const wxPoint& aOffset, EDA_COLOR_T aColor, GR_DRAWMODE aDrawMode, EDA_DRAW_MODE_T aFillMode, diff --git a/common/edaappl.cpp b/common/edaappl.cpp index 7a218868df..afc4d7644c 100644 --- a/common/edaappl.cpp +++ b/common/edaappl.cpp @@ -51,6 +51,7 @@ #include #include #include +#include static const wxChar* CommonConfigPath = wxT( "kicad_common" ); @@ -1160,19 +1161,20 @@ bool EDA_APP::LockFile( const wxString& fileName ) bool EDA_APP::SetFootprintLibTablePath() { - wxString path; + wxString path; + wxString kisysmod( wxT( KISYSMOD ) ); // Set the KISYSMOD environment variable for the current process if it is not already // defined in the user's environment. This is required to expand the global footprint // library table paths. - if( wxGetEnv( wxT( "KISYSMOD" ), &path ) && wxFileName::DirExists( path ) ) + if( wxGetEnv( kisysmod, &path ) && wxFileName::DirExists( path ) ) return true; // Set the KISYSMOD environment variable to the path defined in the user's configuration // if it is defined and the path exists. if( m_commonSettings->Read( kicadFpLibPath, &path ) && wxFileName::DirExists( path ) ) { - wxSetEnv( wxT( "KISYSMOD" ), path ); + wxSetEnv( kisysmod, path ); return true; } @@ -1198,7 +1200,7 @@ bool EDA_APP::SetFootprintLibTablePath() if( modFileCount != 0 ) { - wxSetEnv( wxT( "KISYSMOD" ), bestPath ); + wxSetEnv( kisysmod, bestPath ); return true; } } diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp index 8385662c3d..77fa491615 100644 --- a/common/fp_lib_table.cpp +++ b/common/fp_lib_table.cpp @@ -49,9 +49,6 @@ using namespace FP_LIB_TABLE_T; */ static const wxString traceFpLibTable( wxT( "KicadFpLibTable" ) ); -/// The evinronment variable name for the current project path. This is used interanally -/// at run time and is not exposed outside of the current process. -static wxString projectPathEnvVariableName( wxT( "KIPRJMOD" ) ); /// The footprint library table name used when no project file is passed to Pcbnew or CvPcb. /// This is used temporarily to store the project specific library table until the project @@ -74,7 +71,71 @@ void FP_LIB_TABLE::ROW::SetType( const wxString& aType ) void FP_LIB_TABLE::ROW::SetFullURI( const wxString& aFullURI ) { uri_user = aFullURI; + +#if !FP_LATE_ENVVAR uri_expanded = FP_LIB_TABLE::ExpandSubstitutions( aFullURI ); +#endif +} + + +const wxString FP_LIB_TABLE::ROW::GetFullURI( bool aSubstituted ) const +{ + if( aSubstituted ) + { +#if !FP_LATE_ENVVAR // early expansion + return uri_expanded; + +#else // late expansion + return FP_LIB_TABLE::ExpandSubstitutions( uri_user ); +#endif + } + else + return uri_user; +} + + +FP_LIB_TABLE::ROW::ROW( const ROW& a ) : + nickName( a.nickName ), + type( a.type ), + options( a.options ), + description( a.description ), + properties( 0 ) +{ + // may call ExpandSubstitutions() + SetFullURI( a.uri_user ); + + if( a.properties ) + properties = new PROPERTIES( *a.properties ); +} + + +FP_LIB_TABLE::ROW& FP_LIB_TABLE::ROW::operator=( const ROW& r ) +{ + nickName = r.nickName; + type = r.type; + options = r.options; + description = r.description; + properties = r.properties ? new PROPERTIES( *r.properties ) : NULL; + + // may call ExpandSubstitutions() + SetFullURI( r.uri_user ); + + // Do not copy the PLUGIN, it is lazily created. Delete any existing + // destination plugin. + setPlugin( NULL ); + + return *this; +} + + +bool FP_LIB_TABLE::ROW::operator==( const ROW& r ) const +{ + return nickName == r.nickName + && uri_user == r.uri_user + && type == r.type + && options == r.options + && description == r.description + ; } @@ -111,6 +172,12 @@ MODULE* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname, const wxString& // having to copy the FPID and its two strings, twice each. FPID& fpid = (FPID&) ret->GetFPID(); + // Catch any misbehaving plugin, which should be setting internal footprint name properly: + wxASSERT( aFootprintName == FROM_UTF8( fpid.GetFootprintName().c_str() ) ); + + // and clearing nickname + wxASSERT( !fpid.GetLibNickname().size() ); + fpid.SetLibNickname( row->GetNickName() ); } @@ -118,11 +185,27 @@ MODULE* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname, const wxString& } -void FP_LIB_TABLE::FootprintSave( const wxString& aNickname, const MODULE* aFootprint ) +FP_LIB_TABLE::SAVE_T FP_LIB_TABLE::FootprintSave( const wxString& aNickname, const MODULE* aFootprint, bool aOverwrite ) { const ROW* row = FindRow( aNickname ); wxASSERT( (PLUGIN*) row->plugin ); - return row->plugin->FootprintSave( row->GetFullURI( true ), aFootprint, row->GetProperties() ); + + if( !aOverwrite ) + { + // Try loading the footprint to see if it already exists, caller wants overwrite + // protection, which is atypical, not the default. + + wxString fpname = FROM_UTF8( aFootprint->GetFPID().GetFootprintName().c_str() ); + + std::auto_ptr m( row->plugin->FootprintLoad( row->GetFullURI( true ), fpname, row->GetProperties() ) ); + + if( m.get() ) + return SAVE_SKIPPED; + } + + row->plugin->FootprintSave( row->GetFullURI( true ), aFootprint, row->GetProperties() ); + + return SAVE_OK; } @@ -142,6 +225,33 @@ bool FP_LIB_TABLE::IsFootprintLibWritable( const wxString& aNickname ) } +void FP_LIB_TABLE::FootprintLibDelete( const wxString& aNickname ) +{ + const ROW* row = FindRow( aNickname ); + wxASSERT( (PLUGIN*) row->plugin ); + row->plugin->FootprintLibDelete( row->GetFullURI( true ), row->GetProperties() ); +} + + +void FP_LIB_TABLE::FootprintLibCreate( const wxString& aNickname ) +{ + const ROW* row = FindRow( aNickname ); + wxASSERT( (PLUGIN*) row->plugin ); + row->plugin->FootprintLibCreate( row->GetFullURI( true ), row->GetProperties() ); +} + + +const wxString FP_LIB_TABLE::GetDescription( const wxString& aNickname ) +{ + // use "no exception" form of find row: + const ROW* row = findRow( aNickname ); + if( row ) + return row->description; + else + return wxEmptyString; +} + + void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR ) { /* @@ -726,14 +836,20 @@ void FP_LIB_TABLE::SetProjectPathEnvVariable( const wxFileName& aPath ) path = aPath.GetPath(); wxLogTrace( traceFpLibTable, wxT( "Setting env %s to <%s>." ), - GetChars( projectPathEnvVariableName ), GetChars( path ) ); - wxSetEnv( projectPathEnvVariableName, path ); + GetChars( ProjectPathEnvVariableName() ), GetChars( path ) ); + wxSetEnv( ProjectPathEnvVariableName(), path ); } -const wxString& FP_LIB_TABLE::GetProjectPathEnvVariableName() const +const wxString FP_LIB_TABLE::ProjectPathEnvVariableName() { - return projectPathEnvVariableName; + return wxT( "KIPRJMOD" ); +} + + +const wxString FP_LIB_TABLE::GlobalPathEnvVariableName() +{ + return wxT( KISYSMOD ); } diff --git a/common/gal/opengl/gpu_manager.cpp b/common/gal/opengl/gpu_manager.cpp index c3f15829ce..8b556b32ce 100644 --- a/common/gal/opengl/gpu_manager.cpp +++ b/common/gal/opengl/gpu_manager.cpp @@ -189,7 +189,7 @@ void GPU_CACHED_MANAGER::uploadToGpu() { #ifdef __WXDEBUG__ prof_counter totalTime; - prof_start( &totalTime, false ); + prof_start( &totalTime ); #endif /* __WXDEBUG__ */ if( !m_buffersInitialized ) @@ -214,8 +214,7 @@ void GPU_CACHED_MANAGER::uploadToGpu() #ifdef __WXDEBUG__ prof_end( &totalTime ); - wxLogDebug( wxT( "Uploading %d vertices to GPU / %.1f ms" ), - bufferSize, (double) totalTime.value / 1000.0 ); + wxLogDebug( wxT( "Uploading %d vertices to GPU / %.1f ms" ), bufferSize, totalTime.msecs() ); #endif /* __WXDEBUG__ */ } diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index d01a90a426..970cc32d16 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -1053,8 +1053,8 @@ void CALLBACK ErrorCallback( GLenum aErrorCode ) { const GLubyte* eString = gluErrorString( aErrorCode ); - DisplayError( NULL, wxString( std::string( "Tessellation error: " ) + - std::string( (const char*)( eString ) ) ) ); + DisplayError( NULL, wxT( "Tessellation error: " ) + + wxString( (const char*)( eString ), wxConvUTF8 ) ); exit( 1 ); } diff --git a/common/grid_tricks.cpp b/common/grid_tricks.cpp index 079dbd62eb..83f412e05c 100644 --- a/common/grid_tricks.cpp +++ b/common/grid_tricks.cpp @@ -188,7 +188,9 @@ void GRID_TRICKS::onKeyDown( wxKeyEvent& ev ) cutcopy( true ); } else - ev.Skip(); + { + ev.Skip( true ); + } } diff --git a/common/math/math_util.cpp b/common/math/math_util.cpp index 9743acb1b2..d3f69e81a7 100644 --- a/common/math/math_util.cpp +++ b/common/math/math_util.cpp @@ -68,7 +68,7 @@ int64_t rescale( int64_t aNumerator, int64_t aValue, int64_t aDenominator ) a0 = a0 * b0 + t1a; a1 = a1 * b1 + ( t1 >> 32 ) + ( a0 < t1a ); a0 += r; - a1 += ( (uint64_t) a0 ) < r; + a1 += a0 < (uint64_t)r; for( i = 63; i >= 0; i-- ) { diff --git a/common/profile.h b/common/profile.h deleted file mode 100644 index f779dfae59..0000000000 --- a/common/profile.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2013 CERN - * @author Tomasz Wlostowski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/** - * @file profile.h: - * @brief Simple profiling functions for measuring code execution time. - */ - -#ifndef __TPROFILE_H -#define __TPROFILE_H - -#include -#include - -/** - * Function rdtsc - * Returns processor's time-stamp counter. Main purpose is precise time measuring of code - * execution time. - * @return unsigned long long - Value of time-stamp counter. - */ -#if defined(__i386__) -static __inline__ unsigned long long rdtsc() -{ - unsigned long long int x; - __asm__ volatile ( ".byte 0x0f, 0x31" : "=A" ( x ) ); - - return x; -} - - -#elif defined(__x86_64__) -static __inline__ unsigned long long rdtsc() -{ - unsigned hi, lo; - __asm__ __volatile__ ( "rdtsc" : "=a" ( lo ), "=d" ( hi ) ); - - return ( (unsigned long long) lo ) | ( ( (unsigned long long) hi ) << 32 ); -} - - -#elif defined(__powerpc__) -static __inline__ unsigned long long rdtsc() -{ - unsigned long long int result = 0; - unsigned long int upper, lower, tmp; - __asm__ volatile ( - "0: \n" - "\tmftbu %0 \n" - "\tmftb %1 \n" - "\tmftbu %2 \n" - "\tcmpw %2,%0 \n" - "\tbne 0b \n" - : "=r" ( upper ), "=r" ( lower ), "=r" ( tmp ) - ); - - result = upper; - result = result << 32; - result = result | lower; - - return result; -} - - -#endif /* __powerpc__ */ - -// Fixme: OS X version -/** - * Function get_tics - * Returns the number of microseconds that have elapsed since the system was started. - * @return uint64_t Number of microseconds. - */ -static inline uint64_t get_tics() -{ - struct timeval tv; - gettimeofday( &tv, NULL ); - - return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec; -} - - -/** - * Structure for storing data related to profiling counters. - */ -struct prof_counter -{ - uint64_t value; /// Stored timer value - bool use_rdtsc; /// Method of time measuring (rdtsc or tics) -}; - -/** - * Function prof_start - * Begins code execution time counting for a given profiling counter. - * @param cnt is the counter which should be started. - * @param use_rdtsc tells if processor's time-stamp counter should be used for time counting. - * Otherwise is system tics method will be used. IMPORTANT: time-stamp counter should not - * be used on multicore machines executing threaded code. - */ -static inline void prof_start( prof_counter* cnt, bool use_rdtsc ) -{ - cnt->use_rdtsc = use_rdtsc; - - if( use_rdtsc ) - { - cnt->value = rdtsc(); - } - else - { - cnt->value = get_tics(); - } -} - - -/** - * Function prof_stop - * Ends code execution time counting for a given profiling counter. - * @param cnt is the counter which should be stopped. - */ -static inline void prof_end( prof_counter* cnt ) -{ - if( cnt->use_rdtsc ) - cnt->value = rdtsc() - cnt->value; - else - cnt->value = get_tics() - cnt->value; -} - -#endif diff --git a/common/selcolor.cpp b/common/selcolor.cpp index ac5e22fdd3..dfffccfdee 100644 --- a/common/selcolor.cpp +++ b/common/selcolor.cpp @@ -6,7 +6,6 @@ */ #include -#include #include #include @@ -64,7 +63,7 @@ WinEDA_SelColorFrame::WinEDA_SelColorFrame( wxWindow* parent, const wxPoint& framepos, int OldColor ) : wxDialog( parent, -1, _( "Colors" ), framepos, wxDefaultSize, - wxDEFAULT_DIALOG_STYLE | MAYBE_RESIZE_BORDER ) + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) { Init_Dialog( OldColor ); diff --git a/common/string.cpp b/common/string.cpp index 7bef64abb5..7d3a74f0c4 100644 --- a/common/string.cpp +++ b/common/string.cpp @@ -1,3 +1,26 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004 KiCad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + /** * @file string.cpp * @brief Some useful functions to handle strings. @@ -5,9 +28,18 @@ #include #include +#include // StrPrintf #include +/** + * Illegal file name characters used to insure file names will be valid on all supported + * platforms. This is the list of illegal file name characters for Windows which includes + * the illegal file name characters for Linux and OSX. + */ +static const char illegalFileNameChars[] = "\\/:\"<>|"; + + int ReadDelimitedText( wxString* aDest, const char* aSource ) { std::string utf8; // utf8 but without escapes and quotes. @@ -414,3 +446,34 @@ int SplitString( wxString strToSplit, return 0; } + + +wxString GetIllegalFileNameWxChars() +{ + return FROM_UTF8( illegalFileNameChars ); +} + + +bool ReplaceIllegalFileNameChars( std::string* aName ) +{ + bool changed = false; + std::string result; + + for( std::string::iterator it = aName->begin(); it != aName->end(); ++it ) + { + if( strchr( illegalFileNameChars, *it ) ) + { + StrPrintf( &result, "%%%02x", *it ); + changed = true; + } + else + { + result += *it; + } + } + + if( changed ) + *aName = result; + + return changed; +} diff --git a/common/system/fcontext.s b/common/system/fcontext.s index 7e6e8f9a86..fb81fbde7e 100644 --- a/common/system/fcontext.s +++ b/common/system/fcontext.s @@ -33,6 +33,10 @@ #include "jump_x86_64_sysv_elf_gas.S" #include "make_x86_64_sysv_elf_gas.S" + #elif __arm__ + #include "jump_arm_aapcs_elf_gas.S" + #include "make_arm_aapcs_elf_gas.S" + #else #error "Missing make_fcontext & jump_fcontext routines for this architecture" #endif diff --git a/common/system/jump_arm_aapcs_elf_gas.S b/common/system/jump_arm_aapcs_elf_gas.S new file mode 100644 index 0000000000..7c406f65ac --- /dev/null +++ b/common/system/jump_arm_aapcs_elf_gas.S @@ -0,0 +1,76 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| 0x20| 0x24| * + * ------------------------------------------------------------- * + * | v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8 | sp | lr | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | | * + * ------------------------------------------------------------- * + * | 0x28| | * + * ------------------------------------------------------------- * + * | pc | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 11 | 12 | | * + * ------------------------------------------------------------- * + * | 0x2c| 0x30| | * + * ------------------------------------------------------------- * + * | sp | size| | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | * + * ------------------------------------------------------------- * + * | 0x34| 0x38|0x3c| 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58 | * + * ------------------------------------------------------------- * + * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | s24 | s25 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 23 | 24 | 25 | 26 | 27 | 28 | | * + * ------------------------------------------------------------- * + * | 0x5c| 0x60| 0x64| 0x68| 0x6c| 0x70| | * + * ------------------------------------------------------------- * + * | s26 | s27 | s28 | s29 | s30 | s31 | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,%function +jump_fcontext: + stmia a1, {v1-v8,sp-lr} @ save V1-V8,SP-LR + str lr, [a1,#40] @ save LR as PC + +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) + cmp a4, #0 @ test if fpu env should be preserved + beq 1f + + mov a4, a1 + add a4, #52 + vstmia a4, {d8-d15} @ save S16-S31 + + mov a4, a2 + add a4, #52 + vldmia a4, {d8-d15} @ restore S16-S31 +1: +#endif + + mov a1, a3 @ use third arg as return value after jump + @ and as first arg in context function + ldmia a2, {v1-v8,sp-pc} @ restore v1-V8,SP-PC +.size jump_fcontext,.-jump_fcontext + +/* Mark that we don't need executable stack. */ +.section .note.GNU-stack,"",%progbits diff --git a/common/system/make_arm_aapcs_elf_gas.S b/common/system/make_arm_aapcs_elf_gas.S new file mode 100644 index 0000000000..ca3206067a --- /dev/null +++ b/common/system/make_arm_aapcs_elf_gas.S @@ -0,0 +1,79 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| 0x20| 0x24| * + * ------------------------------------------------------------- * + * | v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8 | sp | lr | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | | * + * ------------------------------------------------------------- * + * | 0x28| | * + * ------------------------------------------------------------- * + * | pc | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 11 | 12 | | * + * ------------------------------------------------------------- * + * | 0x2c| 0x30| | * + * ------------------------------------------------------------- * + * | sp | size| | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | * + * ------------------------------------------------------------- * + * | 0x34| 0x38|0x3c| 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58 | * + * ------------------------------------------------------------- * + * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | s24 | s25 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 23 | 24 | 25 | 26 | 27 | 28 | | * + * ------------------------------------------------------------- * + * | 0x5c| 0x60| 0x64| 0x68| 0x6c| 0x70| | * + * ------------------------------------------------------------- * + * | s26 | s27 | s28 | s29 | s30 | s31 | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,%function +make_fcontext: + mov a4, a1 @ save address of context stack (base) A4 + sub a1, a1, #116 @ reserve space for fcontext_t at top of context stack + + @ shift address in A1 to lower 16 byte boundary + @ == pointer to fcontext_t and address of context stack + bic a1, a1, #15 + + str a4, [a1,#44] @ save address of context stack (base) in fcontext_t + str a2, [a1,#48] @ save context stack size in fcontext_t + str a3, [a1,#40] @ save address of context function in fcontext_t + + str a1, [a1,#32] @ save address in A4 as stack pointer for context function + + adr a2, finish @ compute abs address of label finish + str a2, [a1,#36] @ save address of finish as return address for context function + @ entered after context function returns + + bx lr + +finish: + @ SP points to same addras SP on entry of context function + mov a1, #0 @ exit code is zero + bl _exit@PLT @ exit application +.size make_fcontext,.-make_fcontext + +/* Mark that we don't need executable stack. */ +.section .note.GNU-stack,"",%progbits diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index a2534c0623..75ac02574e 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -139,8 +139,9 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) { if( !static_cast( aTool )->Init() ) { - DisplayError( NULL, wxString( std::string( "Initialization of the %s tool failed" ) + - aTool->GetName() ) ); + std::string msg = StrPrintf( "Initialization of the %s tool failed", aTool->GetName().c_str() ); + + DisplayError( NULL, wxString::FromUTF8( msg.c_str() ) ); // Unregister the tool m_toolState.erase( aTool ); diff --git a/common/validators.cpp b/common/validators.cpp new file mode 100644 index 0000000000..86a2a6d1db --- /dev/null +++ b/common/validators.cpp @@ -0,0 +1,48 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Wayne Stambaugh + * Copyright (C) 2004-2013 KiCad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file validators.cpp + * @brief Custom text control validator implementations. + */ + +#include +#include + + +FOOTPRINT_NAME_VALIDATOR::FOOTPRINT_NAME_VALIDATOR( wxString* aValue ) : + wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST, aValue ) +{ + // The Windows (DOS) file system forbidden characters already include the forbidden + // file name characters for both Posix and OSX systems. The characters \/*?|"<> are + // illegal and filtered by the validator. + wxString illegalChars = GetIllegalFileNameWxChars(); + wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST ); + wxArrayString illegalCharList; + + for( unsigned i = 0; i < illegalChars.size(); i++ ) + illegalCharList.Add( wxString( illegalChars[i] ) ); + + SetExcludes( illegalCharList ); +} diff --git a/common/view/view.cpp b/common/view/view.cpp index 9f01da2d13..8bde0d5aca 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -985,7 +985,7 @@ void VIEW::RecacheAllItems( bool aImmediately ) #ifdef __WXDEBUG__ prof_counter totalRealTime; - prof_start( &totalRealTime, false ); + prof_start( &totalRealTime ); #endif /* __WXDEBUG__ */ for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i ) @@ -1006,7 +1006,7 @@ void VIEW::RecacheAllItems( bool aImmediately ) prof_end( &totalRealTime ); wxLogDebug( wxT( "RecacheAllItems::immediately: %u %.1f ms" ), - aImmediately, (double) totalRealTime.value / 1000.0 ); + aImmediately, totalRealTime.msecs() ); #endif /* __WXDEBUG__ */ } diff --git a/eeschema/dialogs/dialog_color_config.h b/eeschema/dialogs/dialog_color_config.h index 2912d3a50c..73b3df17b7 100644 --- a/eeschema/dialogs/dialog_color_config.h +++ b/eeschema/dialogs/dialog_color_config.h @@ -61,7 +61,7 @@ private: const wxString& aCaption = _( "EESchema Colors" ), const wxPoint& aPosition = wxDefaultPosition, const wxSize& aSize = wxDefaultSize, - long aStyle = wxDEFAULT_DIALOG_STYLE | MAYBE_RESIZE_BORDER ); + long aStyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ); // Initializes member variables void Init(); diff --git a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp index 61d33c37d4..f10a58628d 100644 --- a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp +++ b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp @@ -793,13 +793,15 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToSelectedField() rotateCheckBox->SetValue( field.GetOrientation() == TEXT_ORIENT_VERT ); // Copy the text justification - EDA_TEXT_HJUSTIFY_T hjustify[3] = { - GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_CENTER, + static const EDA_TEXT_HJUSTIFY_T hjustify[] = { + GR_TEXT_HJUSTIFY_LEFT, + GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_HJUSTIFY_RIGHT }; - EDA_TEXT_VJUSTIFY_T vjustify[3] = { - GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_CENTER, + static const EDA_TEXT_VJUSTIFY_T vjustify[] = { + GR_TEXT_VJUSTIFY_BOTTOM, + GR_TEXT_VJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_TOP }; diff --git a/eeschema/dialogs/dialog_edit_label.cpp b/eeschema/dialogs/dialog_edit_label.cpp index addeb7cee6..fb1805e298 100644 --- a/eeschema/dialogs/dialog_edit_label.cpp +++ b/eeschema/dialogs/dialog_edit_label.cpp @@ -1,9 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2008 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2013 Wayne Stambaugh + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -295,7 +295,7 @@ void DIALOG_LABEL_EDITOR::TextPropertiesAccept( wxCommandEvent& aEvent ) m_Parent->OnModify(); - /* Make the text size as new default size if it is a new text */ + // Make the text size the new default size ( if it is a new text ): if( m_CurrentText->IsNew() ) m_Parent->SetDefaultLabelSize( m_CurrentText->GetSize().x ); diff --git a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.cpp b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.cpp index f46a64ed50..a859617859 100644 --- a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.cpp +++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Apr 30 2013) +// C++ code generated with wxFormBuilder (version Nov 5 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -43,7 +43,7 @@ DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE::DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE bSizerFiledsList->Add( moveUpButton, 0, wxALL|wxEXPAND, 5 ); - bSizerFieldsSetup->Add( bSizerFiledsList, 1, wxEXPAND, 5 ); + bSizerFieldsSetup->Add( bSizerFiledsList, 3, wxEXPAND, 5 ); wxBoxSizer* fieldEditBoxSizer; fieldEditBoxSizer = new wxBoxSizer( wxVERTICAL ); @@ -179,7 +179,7 @@ DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE::DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE fieldEditBoxSizer->Add( fgSizerPosSize, 1, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - bSizerFieldsSetup->Add( fieldEditBoxSizer, 0, wxEXPAND, 5 ); + bSizerFieldsSetup->Add( fieldEditBoxSizer, 2, wxEXPAND, 5 ); mainSizer->Add( bSizerFieldsSetup, 1, wxEXPAND, 5 ); diff --git a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.fbp b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.fbp index 6cb1bc0d36..d6a0535ca9 100644 --- a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.fbp +++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.fbp @@ -20,8 +20,10 @@ . 1 + 1 1 1 + UI 0 0 @@ -45,7 +47,7 @@ -1,-1 wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU - Fields Properties + Field Properties @@ -103,17 +105,17 @@ 5 wxEXPAND - 1 - + 3 + bSizerFiledsList wxVERTICAL none - + 8 wxEXPAND|wxTOP|wxRIGHT|wxLEFT 1 - + 1 1 1 @@ -214,11 +216,11 @@ - + 5 wxEXPAND|wxTOP|wxRIGHT|wxLEFT 0 - + 1 1 1 @@ -302,11 +304,11 @@ - + 5 wxEXPAND|wxTOP|wxRIGHT|wxLEFT 0 - + 1 1 1 @@ -390,11 +392,11 @@ - + 5 wxALL|wxEXPAND 0 - + 1 1 1 @@ -483,7 +485,7 @@ 5 wxEXPAND - 0 + 2 fieldEditBoxSizer diff --git a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.h b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.h index d08d4756dc..82188f2008 100644 --- a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.h +++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Apr 30 2013) +// C++ code generated with wxFormBuilder (version Nov 5 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -80,7 +80,7 @@ class DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE : public wxDialog public: - DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Fields Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU ); + DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Field Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU ); ~DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE(); }; diff --git a/eeschema/dialogs/dialog_lib_edit_text_base.cpp b/eeschema/dialogs/dialog_lib_edit_text_base.cpp index 14cf94f803..64f93d038a 100644 --- a/eeschema/dialogs/dialog_lib_edit_text_base.cpp +++ b/eeschema/dialogs/dialog_lib_edit_text_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) +// C++ code generated with wxFormBuilder (version Nov 6 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -93,7 +93,7 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow wxString m_TextVJustificationOptChoices[] = { _("Align bottom"), _("Align center"), _("Align top") }; int m_TextVJustificationOptNChoices = sizeof( m_TextVJustificationOptChoices ) / sizeof( wxString ); - m_TextVJustificationOpt = new wxRadioBox( this, wxID_ANY, _("Verticle Justify"), wxDefaultPosition, wxDefaultSize, m_TextVJustificationOptNChoices, m_TextVJustificationOptChoices, 1, wxRA_SPECIFY_COLS ); + m_TextVJustificationOpt = new wxRadioBox( this, wxID_ANY, _("Vertical Justify"), wxDefaultPosition, wxDefaultSize, m_TextVJustificationOptNChoices, m_TextVJustificationOptChoices, 1, wxRA_SPECIFY_COLS ); m_TextVJustificationOpt->SetSelection( 1 ); bBottomtBoxSizer->Add( m_TextVJustificationOpt, 1, wxALL|wxEXPAND, 5 ); diff --git a/eeschema/dialogs/dialog_lib_edit_text_base.fbp b/eeschema/dialogs/dialog_lib_edit_text_base.fbp index 4cb52473d6..a2a6f9d714 100644 --- a/eeschema/dialogs/dialog_lib_edit_text_base.fbp +++ b/eeschema/dialogs/dialog_lib_edit_text_base.fbp @@ -20,8 +20,10 @@ . 1 + 1 1 1 + UI 1 0 @@ -1150,7 +1152,7 @@ 0 0 wxID_ANY - Verticle Justify + Vertical Justify 1 0 diff --git a/eeschema/dialogs/dialog_lib_edit_text_base.h b/eeschema/dialogs/dialog_lib_edit_text_base.h index fe68b8be27..3cafc4f1f4 100644 --- a/eeschema/dialogs/dialog_lib_edit_text_base.h +++ b/eeschema/dialogs/dialog_lib_edit_text_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) +// C++ code generated with wxFormBuilder (version Nov 6 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! diff --git a/eeschema/dialogs/dialog_lib_new_component.fbp b/eeschema/dialogs/dialog_lib_new_component.fbp index d9393e75a9..eabf24c837 100644 --- a/eeschema/dialogs/dialog_lib_new_component.fbp +++ b/eeschema/dialogs/dialog_lib_new_component.fbp @@ -664,7 +664,7 @@ 0 0 wxID_ANY - Number of &parts per package: + Number of units per &package: 0 @@ -1094,7 +1094,7 @@ 0 0 wxID_ANY - Units in package locked (cannot be swapped) + Units are not &interchangeable 0 diff --git a/eeschema/dialogs/dialog_lib_new_component_base.cpp b/eeschema/dialogs/dialog_lib_new_component_base.cpp index 4a8f1a64e5..744f72fa5f 100644 --- a/eeschema/dialogs/dialog_lib_new_component_base.cpp +++ b/eeschema/dialogs/dialog_lib_new_component_base.cpp @@ -81,7 +81,7 @@ DIALOG_LIB_NEW_COMPONENT_BASE::DIALOG_LIB_NEW_COMPONENT_BASE( wxWindow* parent, bSizer4->Add( 12, 0, 0, wxEXPAND, 3 ); - m_staticText4 = new wxStaticText( this, wxID_ANY, _("Number of &parts per package:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText4 = new wxStaticText( this, wxID_ANY, _("Number of units per &package:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText4->Wrap( -1 ); m_staticText4->SetToolTip( _("This is the number of parts in this component package.\nA 74LS00 gate has 4 parts per packages.") ); @@ -133,7 +133,7 @@ DIALOG_LIB_NEW_COMPONENT_BASE::DIALOG_LIB_NEW_COMPONENT_BASE( wxWindow* parent, bSizer9->Add( 12, 0, 0, wxEXPAND, 3 ); - m_checkLockItems = new wxCheckBox( this, wxID_ANY, _("Units in package locked (cannot be swapped)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkLockItems = new wxCheckBox( this, wxID_ANY, _("Units are not &interchangeable"), wxDefaultPosition, wxDefaultSize, 0 ); m_checkLockItems->SetToolTip( _("Check this option if Eeschema cannot change parts selections inside a given package\nThis happens when parts are different in this package.\nWhen this option is not checked, Eeschema automatically choose the parts in packages to minimize packages count") ); bSizer9->Add( m_checkLockItems, 0, wxALIGN_CENTER_VERTICAL|wxALL, 3 ); diff --git a/eeschema/edit_label.cpp b/eeschema/edit_label.cpp index 07f466af74..0a6f87fbcd 100644 --- a/eeschema/edit_label.cpp +++ b/eeschema/edit_label.cpp @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2004-2013 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -105,7 +105,6 @@ SCH_TEXT* SCH_EDIT_FRAME::CreateNewText( wxDC* aDC, int aType ) textItem->SetSize( wxSize( GetDefaultLabelSize(), GetDefaultLabelSize() ) ); textItem->SetFlags( IS_NEW | IS_MOVED ); - textItem->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode ); EditSchematicText( textItem ); if( textItem->GetText().IsEmpty() ) @@ -123,7 +122,8 @@ SCH_TEXT* SCH_EDIT_FRAME::CreateNewText( wxDC* aDC, int aType ) lastGlobalLabelShape = textItem->GetShape(); } - textItem->Draw( m_canvas, aDC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE ); + // Prepare display to move the new item + textItem->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode ); MoveItem( (SCH_ITEM*) textItem, aDC ); return textItem; diff --git a/eeschema/hierarch.cpp b/eeschema/hierarch.cpp index b74ff81b56..ff00871935 100644 --- a/eeschema/hierarch.cpp +++ b/eeschema/hierarch.cpp @@ -138,7 +138,8 @@ void SCH_EDIT_FRAME::InstallHierarchyFrame( wxDC* DC, wxPoint& pos ) HIERARCHY_NAVIG_DLG::HIERARCHY_NAVIG_DLG( SCH_EDIT_FRAME* parent, wxDC* DC, const wxPoint& pos ) : - wxDialog( parent, -1, _( "Navigator" ), pos, wxSize( 110, 50 ), DIALOG_STYLE ) + wxDialog( parent, -1, _( "Navigator" ), pos, wxSize( 110, 50 ), + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) { wxTreeItemId cellule; diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp index 6ab7aa4393..81dfce998e 100644 --- a/eeschema/lib_arc.cpp +++ b/eeschema/lib_arc.cpp @@ -484,7 +484,7 @@ void LIB_ARC::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOf } -EDA_RECT LIB_ARC::GetBoundingBox() const +const EDA_RECT LIB_ARC::GetBoundingBox() const { int minX, minY, maxX, maxY, angleStart, angleEnd; EDA_RECT rect; diff --git a/eeschema/lib_arc.h b/eeschema/lib_arc.h index 61f4c3c0fa..2c017b9c20 100644 --- a/eeschema/lib_arc.h +++ b/eeschema/lib_arc.h @@ -104,7 +104,7 @@ public: bool HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); diff --git a/eeschema/lib_bezier.cpp b/eeschema/lib_bezier.cpp index 2caa429e01..43b7b81140 100644 --- a/eeschema/lib_bezier.cpp +++ b/eeschema/lib_bezier.cpp @@ -378,7 +378,7 @@ bool LIB_BEZIER::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTra } -EDA_RECT LIB_BEZIER::GetBoundingBox() const +const EDA_RECT LIB_BEZIER::GetBoundingBox() const { EDA_RECT rect; int xmin, xmax, ymin, ymax; diff --git a/eeschema/lib_bezier.h b/eeschema/lib_bezier.h index d2a4136641..00a320b43f 100644 --- a/eeschema/lib_bezier.h +++ b/eeschema/lib_bezier.h @@ -76,7 +76,7 @@ public: bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual bool Inside( EDA_RECT& aRect ) const; diff --git a/eeschema/lib_circle.cpp b/eeschema/lib_circle.cpp index d59be27771..f6c639735f 100644 --- a/eeschema/lib_circle.cpp +++ b/eeschema/lib_circle.cpp @@ -105,7 +105,7 @@ bool LIB_CIRCLE::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTra if( aThreshold < 0 ) aThreshold = GetPenSize() / 2; - int dist = KiROUND( GetLineLength( aPosRef, aTransform.TransformCoordinate( m_Pos ) ) ); + int dist = KiROUND( GetLineLength( aPosRef, aTransform.TransformCoordinate( m_Pos ) ) ); if( abs( dist - m_Radius ) <= aThreshold ) return true; @@ -251,7 +251,7 @@ void LIB_CIRCLE::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& } -EDA_RECT LIB_CIRCLE::GetBoundingBox() const +const EDA_RECT LIB_CIRCLE::GetBoundingBox() const { EDA_RECT rect; diff --git a/eeschema/lib_circle.h b/eeschema/lib_circle.h index 2a713f099f..49f0f605ac 100644 --- a/eeschema/lib_circle.h +++ b/eeschema/lib_circle.h @@ -67,7 +67,7 @@ public: int GetPenSize( ) const; - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); diff --git a/eeschema/lib_draw_item.h b/eeschema/lib_draw_item.h index 786472eecb..8efffd827e 100644 --- a/eeschema/lib_draw_item.h +++ b/eeschema/lib_draw_item.h @@ -260,7 +260,7 @@ public: /** * @return the boundary box for this, in library coordinates */ - virtual EDA_RECT GetBoundingBox() const { return EDA_ITEM::GetBoundingBox(); } + virtual const EDA_RECT GetBoundingBox() const { return EDA_ITEM::GetBoundingBox(); } /** * Function GetMsgPanelInfo diff --git a/eeschema/lib_field.cpp b/eeschema/lib_field.cpp index d68d6cc043..97c015672d 100644 --- a/eeschema/lib_field.cpp +++ b/eeschema/lib_field.cpp @@ -524,7 +524,7 @@ wxString LIB_FIELD::GetFullText( int unit ) } -EDA_RECT LIB_FIELD::GetBoundingBox() const +const EDA_RECT LIB_FIELD::GetBoundingBox() const { /* Y coordinates for LIB_ITEMS are bottom to top, so we must invert the Y position when * calling GetTextBox() that works using top to bottom Y axis orientation. diff --git a/eeschema/lib_field.h b/eeschema/lib_field.h index 1a99b1a7a2..1e475fa913 100644 --- a/eeschema/lib_field.h +++ b/eeschema/lib_field.h @@ -165,7 +165,7 @@ public: return (m_Attributs & TEXT_NO_VISIBLE) == 0 ? true : false; } - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp index 4494a3068a..46a662ae70 100644 --- a/eeschema/lib_pin.cpp +++ b/eeschema/lib_pin.cpp @@ -1869,7 +1869,7 @@ void LIB_PIN::GetMsgPanelInfo( MSG_PANEL_ITEMS& aList ) } -EDA_RECT LIB_PIN::GetBoundingBox() const +const EDA_RECT LIB_PIN::GetBoundingBox() const { LIB_COMPONENT* entry = (LIB_COMPONENT*) m_Parent; EDA_RECT bbox; diff --git a/eeschema/lib_pin.h b/eeschema/lib_pin.h index 9866cd29e3..c89538a216 100644 --- a/eeschema/lib_pin.h +++ b/eeschema/lib_pin.h @@ -139,7 +139,7 @@ public: bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual /** * Function ReturnPinEndPoint diff --git a/eeschema/lib_polyline.cpp b/eeschema/lib_polyline.cpp index 27c5f4b4bf..caad9aafd7 100644 --- a/eeschema/lib_polyline.cpp +++ b/eeschema/lib_polyline.cpp @@ -353,7 +353,7 @@ bool LIB_POLYLINE::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& } -EDA_RECT LIB_POLYLINE::GetBoundingBox() const +const EDA_RECT LIB_POLYLINE::GetBoundingBox() const { EDA_RECT rect; int xmin, xmax, ymin, ymax; diff --git a/eeschema/lib_polyline.h b/eeschema/lib_polyline.h index 2a0c5566b1..81a4d8a08e 100644 --- a/eeschema/lib_polyline.h +++ b/eeschema/lib_polyline.h @@ -78,7 +78,7 @@ public: bool HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual int GetPenSize( ) const; diff --git a/eeschema/lib_rectangle.cpp b/eeschema/lib_rectangle.cpp index 508e49ff42..e73fd57b57 100644 --- a/eeschema/lib_rectangle.cpp +++ b/eeschema/lib_rectangle.cpp @@ -256,7 +256,7 @@ void LIB_RECTANGLE::GetMsgPanelInfo( MSG_PANEL_ITEMS& aList ) } -EDA_RECT LIB_RECTANGLE::GetBoundingBox() const +const EDA_RECT LIB_RECTANGLE::GetBoundingBox() const { EDA_RECT rect; diff --git a/eeschema/lib_rectangle.h b/eeschema/lib_rectangle.h index eec2777df2..739f20b60e 100644 --- a/eeschema/lib_rectangle.h +++ b/eeschema/lib_rectangle.h @@ -71,7 +71,7 @@ public: int GetPenSize( ) const; - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); diff --git a/eeschema/lib_text.cpp b/eeschema/lib_text.cpp index cdfd1eb644..332028b2c7 100644 --- a/eeschema/lib_text.cpp +++ b/eeschema/lib_text.cpp @@ -430,7 +430,7 @@ void LIB_TEXT::GetMsgPanelInfo( MSG_PANEL_ITEMS& aList ) } -EDA_RECT LIB_TEXT::GetBoundingBox() const +const EDA_RECT LIB_TEXT::GetBoundingBox() const { /* Y coordinates for LIB_ITEMS are bottom to top, so we must invert the Y position when * calling GetTextBox() that works using top to bottom Y axis orientation. diff --git a/eeschema/lib_text.h b/eeschema/lib_text.h index 21ce2e9eb8..3db14c11a8 100644 --- a/eeschema/lib_text.h +++ b/eeschema/lib_text.h @@ -96,7 +96,7 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // virtual void Rotate(); diff --git a/eeschema/operations_on_items_lists.cpp b/eeschema/operations_on_items_lists.cpp index a080833d0a..2b417e0020 100644 --- a/eeschema/operations_on_items_lists.cpp +++ b/eeschema/operations_on_items_lists.cpp @@ -202,7 +202,6 @@ void DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST& aItemsList, { SCH_SHEET* sheet = (SCH_SHEET*) newitem; sheet->SetTimeStamp( GetNewTimeStamp() ); - sheet->SetSon( NULL ); break; } diff --git a/eeschema/sch_bitmap.cpp b/eeschema/sch_bitmap.cpp index a69ec64b45..fb93c40c37 100644 --- a/eeschema/sch_bitmap.cpp +++ b/eeschema/sch_bitmap.cpp @@ -176,7 +176,7 @@ bool SCH_BITMAP::Load( LINE_READER& aLine, wxString& aErrorMsg ) } -EDA_RECT SCH_BITMAP::GetBoundingBox() const +const EDA_RECT SCH_BITMAP::GetBoundingBox() const { EDA_RECT rect = m_Image->GetBoundingBox(); diff --git a/eeschema/sch_bitmap.h b/eeschema/sch_bitmap.h index cf77d16ed8..27e96e0dba 100644 --- a/eeschema/sch_bitmap.h +++ b/eeschema/sch_bitmap.h @@ -90,7 +90,7 @@ public: */ wxSize GetSize() const; - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void SwapData( SCH_ITEM* aItem ); diff --git a/eeschema/sch_bus_entry.cpp b/eeschema/sch_bus_entry.cpp index dfd9e54900..8a92a95908 100644 --- a/eeschema/sch_bus_entry.cpp +++ b/eeschema/sch_bus_entry.cpp @@ -110,7 +110,7 @@ bool SCH_BUS_BUS_ENTRY::Save( FILE* aFile ) const } -bool SCH_BUS_ENTRY_BASE::Load( LINE_READER& aLine, wxString& aErrorMsg, +bool SCH_BUS_ENTRY_BASE::Load( LINE_READER& aLine, wxString& aErrorMsg, SCH_ITEM **out ) { char Name1[256]; @@ -136,7 +136,7 @@ bool SCH_BUS_ENTRY_BASE::Load( LINE_READER& aLine, wxString& aErrorMsg, this_new = new SCH_BUS_WIRE_ENTRY; *out = this_new; - if( !aLine.ReadLine() || sscanf( (char*) aLine, "%d %d %d %d ", + if( !aLine.ReadLine() || sscanf( (char*) aLine, "%d %d %d %d ", &this_new->m_pos.x, &this_new->m_pos.y, &this_new->m_size.x, &this_new->m_size.y ) != 4 ) { @@ -153,7 +153,7 @@ bool SCH_BUS_ENTRY_BASE::Load( LINE_READER& aLine, wxString& aErrorMsg, } -EDA_RECT SCH_BUS_ENTRY_BASE::GetBoundingBox() const +const EDA_RECT SCH_BUS_ENTRY_BASE::GetBoundingBox() const { EDA_RECT box; diff --git a/eeschema/sch_bus_entry.h b/eeschema/sch_bus_entry.h index 2e90c43859..771469830e 100644 --- a/eeschema/sch_bus_entry.h +++ b/eeschema/sch_bus_entry.h @@ -76,7 +76,7 @@ public: static bool Load( LINE_READER& aLine, wxString& aErrorMsg, SCH_ITEM **out ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void Move( const wxPoint& aMoveVector ) { diff --git a/eeschema/sch_component.cpp b/eeschema/sch_component.cpp index 4d214bdd16..3b0bdd7d6a 100644 --- a/eeschema/sch_component.cpp +++ b/eeschema/sch_component.cpp @@ -1229,7 +1229,7 @@ bool SCH_COMPONENT::Load( LINE_READER& aLine, wxString& aErrorMsg ) int multi = atoi( name1 ); - if( multi < 0 || multi > 25 ) + if( multi < 0 || multi > 26 ) multi = 1; AddHierarchicalReference( path, ref, multi ); @@ -1430,7 +1430,7 @@ EDA_RECT SCH_COMPONENT::GetBodyBoundingBox() const } -EDA_RECT SCH_COMPONENT::GetBoundingBox() const +const EDA_RECT SCH_COMPONENT::GetBoundingBox() const { EDA_RECT bbox = GetBodyBoundingBox(); for( size_t i = 0; i < m_Fields.size(); i++ ) diff --git a/eeschema/sch_component.h b/eeschema/sch_component.h index 5e52ad2406..d145f78404 100644 --- a/eeschema/sch_component.h +++ b/eeschema/sch_component.h @@ -220,7 +220,7 @@ public: */ void SetTimeStamp( time_t aNewTimeStamp ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual //---------------------------------------------------------------- diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp index 67256b5653..af21d0add0 100644 --- a/eeschema/sch_field.cpp +++ b/eeschema/sch_field.cpp @@ -259,7 +259,7 @@ void SCH_FIELD::SwapData( SCH_ITEM* aItem ) } -EDA_RECT SCH_FIELD::GetBoundingBox() const +const EDA_RECT SCH_FIELD::GetBoundingBox() const { SCH_COMPONENT* parentComponent = (SCH_COMPONENT*) m_Parent; int linewidth = ( m_Thickness == 0 ) ? GetDefaultLineThickness() : m_Thickness; diff --git a/eeschema/sch_field.h b/eeschema/sch_field.h index fd1fca9e7c..1092bdae24 100644 --- a/eeschema/sch_field.h +++ b/eeschema/sch_field.h @@ -100,7 +100,7 @@ public: void Place( SCH_EDIT_FRAME* frame, wxDC* DC ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual /** * Function IsVoid diff --git a/eeschema/sch_junction.cpp b/eeschema/sch_junction.cpp index 4b1bcbceb8..cc26dc5f3a 100644 --- a/eeschema/sch_junction.cpp +++ b/eeschema/sch_junction.cpp @@ -98,7 +98,7 @@ bool SCH_JUNCTION::Load( LINE_READER& aLine, wxString& aErrorMsg ) } -EDA_RECT SCH_JUNCTION::GetBoundingBox() const +const EDA_RECT SCH_JUNCTION::GetBoundingBox() const { EDA_RECT rect; diff --git a/eeschema/sch_junction.h b/eeschema/sch_junction.h index 7371622887..1e8d90fc29 100644 --- a/eeschema/sch_junction.h +++ b/eeschema/sch_junction.h @@ -55,7 +55,7 @@ public: void SwapData( SCH_ITEM* aItem ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, GR_DRAWMODE aDrawMode, EDA_COLOR_T aColor = UNSPECIFIED_COLOR ); diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp index 4cc9821b04..20929a8c61 100644 --- a/eeschema/sch_line.cpp +++ b/eeschema/sch_line.cpp @@ -116,7 +116,7 @@ void SCH_LINE::Show( int nestLevel, std::ostream& os ) const #endif -EDA_RECT SCH_LINE::GetBoundingBox() const +const EDA_RECT SCH_LINE::GetBoundingBox() const { int width = 25; diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h index 8ae7735f81..08f983db2f 100644 --- a/eeschema/sch_line.h +++ b/eeschema/sch_line.h @@ -76,7 +76,7 @@ public: void SetEndPoint( const wxPoint& aPosition ) { m_end = aPosition; } - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual /** * Function GetLength diff --git a/eeschema/sch_marker.cpp b/eeschema/sch_marker.cpp index 8663cc2aca..f7cb4fba8f 100644 --- a/eeschema/sch_marker.cpp +++ b/eeschema/sch_marker.cpp @@ -151,7 +151,7 @@ bool SCH_MARKER::Matches( wxFindReplaceData& aSearchData, wxPoint * aFindLocatio * object, and the units should be in the pcb or schematic coordinate system. * It is OK to overestimate the size by a few counts. */ -EDA_RECT SCH_MARKER::GetBoundingBox() const +const EDA_RECT SCH_MARKER::GetBoundingBox() const { return GetBoundingBoxMarker(); } diff --git a/eeschema/sch_marker.h b/eeschema/sch_marker.h index 1a3a4fb6d2..6c94bb79cc 100644 --- a/eeschema/sch_marker.h +++ b/eeschema/sch_marker.h @@ -72,7 +72,7 @@ public: bool Save( FILE* aFile ) const; - EDA_RECT GetBoundingBox() const; + EDA_RECT const GetBoundingBox() const; // Virtual // Geometric transforms (used in block operations): diff --git a/eeschema/sch_no_connect.cpp b/eeschema/sch_no_connect.cpp index 662ebd756a..ecda593c83 100644 --- a/eeschema/sch_no_connect.cpp +++ b/eeschema/sch_no_connect.cpp @@ -71,7 +71,7 @@ void SCH_NO_CONNECT::SwapData( SCH_ITEM* aItem ) } -EDA_RECT SCH_NO_CONNECT::GetBoundingBox() const +const EDA_RECT SCH_NO_CONNECT::GetBoundingBox() const { int delta = ( GetPenSize() + m_size.x ) / 2; EDA_RECT box; diff --git a/eeschema/sch_no_connect.h b/eeschema/sch_no_connect.h index ccb71d47be..acd9ec4aa9 100644 --- a/eeschema/sch_no_connect.h +++ b/eeschema/sch_no_connect.h @@ -62,7 +62,7 @@ public: bool Load( LINE_READER& aLine, wxString& aErrorMsg ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual // Geometric transforms (used in block operations): diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp index 7c0c97e1c8..4cc05e83d6 100644 --- a/eeschema/sch_sheet.cpp +++ b/eeschema/sch_sheet.cpp @@ -628,7 +628,7 @@ void SCH_SHEET::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, } -EDA_RECT SCH_SHEET::GetBoundingBox() const +const EDA_RECT SCH_SHEET::GetBoundingBox() const { wxPoint end; EDA_RECT box( m_pos, m_size ); diff --git a/eeschema/sch_sheet.h b/eeschema/sch_sheet.h index 99a668e3bc..8eb016963c 100644 --- a/eeschema/sch_sheet.h +++ b/eeschema/sch_sheet.h @@ -398,7 +398,7 @@ public: GR_DRAWMODE aDrawMode, EDA_COLOR_T aColor = UNSPECIFIED_COLOR ); - EDA_RECT GetBoundingBox() const; + EDA_RECT const GetBoundingBox() const; /** * Function GetResizePos diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index abfc85948b..e6e3bbf915 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -574,7 +574,7 @@ void SCH_TEXT::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -EDA_RECT SCH_TEXT::GetBoundingBox() const +const EDA_RECT SCH_TEXT::GetBoundingBox() const { // We must pass the effective text thickness to GetTextBox // when calculating the bounding box @@ -673,20 +673,17 @@ void SCH_TEXT::Plot( PLOTTER* aPlotter ) if( m_MultilineAllowed ) { - wxPoint pos = textpos; + std::vector positions; wxArrayString* list = wxStringSplit( m_Text, '\n' ); - wxPoint offset; + positions.reserve( list->Count() ); - offset.y = GetInterline(); + GetPositionsOfLinesOfMultilineText(positions, list->Count() ); - RotatePoint( &offset, m_Orient ); - - for( unsigned i = 0; iCount(); i++ ) + for( unsigned ii = 0; ii < list->Count(); ii++ ) { - wxString txt = list->Item( i ); - aPlotter->Text( pos, color, txt, m_Orient, m_Size, m_HJustify, + wxString& txt = list->Item( ii ); + aPlotter->Text( positions[ii], color, txt, m_Orient, m_Size, m_HJustify, m_VJustify, thickness, m_Italic, m_Bold ); - pos += offset; } delete (list); @@ -969,7 +966,7 @@ void SCH_LABEL::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset, } -EDA_RECT SCH_LABEL::GetBoundingBox() const +const EDA_RECT SCH_LABEL::GetBoundingBox() const { int x, y, dx, dy, length, height; @@ -1397,7 +1394,7 @@ void SCH_GLOBALLABEL::CreateGraphicShape( std::vector & aPoints, const } -EDA_RECT SCH_GLOBALLABEL::GetBoundingBox() const +const EDA_RECT SCH_GLOBALLABEL::GetBoundingBox() const { int x, y, dx, dy, length, height; @@ -1663,7 +1660,7 @@ void SCH_HIERLABEL::CreateGraphicShape( std::vector & aPoints, const wx } -EDA_RECT SCH_HIERLABEL::GetBoundingBox() const +const EDA_RECT SCH_HIERLABEL::GetBoundingBox() const { int x, y, dx, dy, length, height; diff --git a/eeschema/sch_text.h b/eeschema/sch_text.h index 3b135d0265..12efd1a967 100644 --- a/eeschema/sch_text.h +++ b/eeschema/sch_text.h @@ -151,7 +151,7 @@ public: virtual void SwapData( SCH_ITEM* aItem ); - virtual EDA_RECT GetBoundingBox() const; + virtual const EDA_RECT GetBoundingBox() const; virtual bool Save( FILE* aFile ) const; @@ -249,7 +249,7 @@ public: void Rotate( wxPoint aPosition ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual bool Save( FILE* aFile ) const; @@ -298,7 +298,7 @@ public: bool Load( LINE_READER& aLine, wxString& aErrorMsg ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void CreateGraphicShape( std::vector & aPoints, const wxPoint& aPos ); @@ -353,7 +353,7 @@ public: bool Load( LINE_READER& aLine, wxString& aErrorMsg ); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual void MirrorY( int aYaxis_position ); diff --git a/eeschema/sheetlab.cpp b/eeschema/sheetlab.cpp index ea41663d7d..1d018fb851 100644 --- a/eeschema/sheetlab.cpp +++ b/eeschema/sheetlab.cpp @@ -117,6 +117,8 @@ SCH_SHEET_PIN* SCH_EDIT_FRAME::CreateSheetPin( SCH_SHEET* aSheet, wxDC* aDC ) m_lastSheetPinType = sheetPin->GetShape(); m_lastSheetPinTextSize = sheetPin->GetSize(); + sheetPin->SetPosition( GetCrossHairPosition() ); + sheetPin->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode ); MoveItem( (SCH_ITEM*) sheetPin, aDC ); OnModify(); @@ -160,7 +162,9 @@ SCH_SHEET_PIN* SCH_EDIT_FRAME::ImportSheetPin( SCH_SHEET* aSheet, wxDC* aDC ) sheetPin->SetSize( m_lastSheetPinTextSize ); m_lastSheetPinType = label->GetShape(); sheetPin->SetShape( label->GetShape() ); + sheetPin->SetPosition( GetCrossHairPosition() ); + sheetPin->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode ); MoveItem( (SCH_ITEM*) sheetPin, aDC ); return sheetPin; diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp index 9bed410359..c73d8972da 100644 --- a/gerbview/class_gerber_draw_item.cpp +++ b/gerbview/class_gerber_draw_item.cpp @@ -234,7 +234,7 @@ D_CODE* GERBER_DRAW_ITEM::GetDcodeDescr() } -EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const +const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const { // return a rectangle which is (pos,dim) in nature. therefore the +1 EDA_RECT bbox( m_Start, wxSize( 1, 1 ) ); diff --git a/gerbview/class_gerber_draw_item.h b/gerbview/class_gerber_draw_item.h index cb304dbc64..2989333c0a 100644 --- a/gerbview/class_gerber_draw_item.h +++ b/gerbview/class_gerber_draw_item.h @@ -218,7 +218,7 @@ public: */ D_CODE* GetDcodeDescr(); - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; // Virtual /* Display on screen: */ void Draw( EDA_DRAW_PANEL* aPanel, diff --git a/gerbview/dialogs/dialog_select_one_pcb_layer.cpp b/gerbview/dialogs/dialog_select_one_pcb_layer.cpp index dd22789103..80dd1b46cc 100644 --- a/gerbview/dialogs/dialog_select_one_pcb_layer.cpp +++ b/gerbview/dialogs/dialog_select_one_pcb_layer.cpp @@ -86,7 +86,7 @@ SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent, bool aShowDeselectOption ) : wxDialog( parent, -1, _( "Select Layer:" ), wxPoint( -1, -1 ), wxSize( 470, 250 ), - DIALOG_STYLE ) + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) { wxButton* Button; LAYER_NUM ii; diff --git a/include/base_struct.h b/include/base_struct.h index d3b6738fff..90e3b4b67a 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -283,7 +283,7 @@ public: * useful to calculate bounding box of rotated items, when * rotation if not k*90 degrees */ - EDA_RECT GetBoundingBoxRotated( wxPoint aRotCenter, double aAngle ); + const EDA_RECT GetBoundingBoxRotated( wxPoint aRotCenter, double aAngle ); }; @@ -346,8 +346,7 @@ protected: EDA_ITEM* Pback; ///< previous in linked list DHEAD* m_List; ///< which DLIST I am on. - EDA_ITEM* m_Parent; /* Linked list: Link (parent struct) */ - EDA_ITEM* m_Son; /* Linked list: Link (son struct) */ + EDA_ITEM* m_Parent; ///< Linked list: Link (parent struct) time_t m_TimeStamp; ///< Time stamp used for logical links /// Set to true to override the visibility setting of the item. @@ -379,13 +378,11 @@ public: EDA_ITEM* Next() const { return (EDA_ITEM*) Pnext; } EDA_ITEM* Back() const { return (EDA_ITEM*) Pback; } EDA_ITEM* GetParent() const { return m_Parent; } - EDA_ITEM* GetSon() const { return m_Son; } DHEAD* GetList() const { return m_List; } void SetNext( EDA_ITEM* aNext ) { Pnext = aNext; } void SetBack( EDA_ITEM* aBack ) { Pback = aBack; } void SetParent( EDA_ITEM* aParent ) { m_Parent = aParent; } - void SetSon( EDA_ITEM* aSon ) { m_Son = aSon; } void SetList( DHEAD* aList ) { m_List = aList; } inline bool IsNew() const { return m_Flags & IS_NEW; } @@ -479,7 +476,7 @@ public: * system. * It is OK to overestimate the size by a few counts. */ - virtual EDA_RECT GetBoundingBox() const + virtual const EDA_RECT GetBoundingBox() const { #if defined(DEBUG) printf( "Missing GetBoundingBox()\n" ); diff --git a/include/class_board_item.h b/include/class_board_item.h index 11676e418d..6f6bf201d6 100644 --- a/include/class_board_item.h +++ b/include/class_board_item.h @@ -130,6 +130,17 @@ public: virtual void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset = ZeroOffset ) = 0; + /** + * Swap data between aItem and aImage. + * aItem and aImage should have the same type + * Used in undo redo command to swap values between an item and its copy + * Only values like layer, size .. which are modified by edition are swapped, + * not the pointers like + * Pnext and Pback because aItem is not changed in the linked list + * @param aImage = the item image which contains data to swap + */ + void SwapData( BOARD_ITEM* aImage ); + /** * Function IsOnLayer * tests to see if this object is on the given layer. Is virtual so @@ -172,11 +183,13 @@ public: /** * Function DeleteStructure - * deletes this object after UnLink()ing it from its owner. + * deletes this object after UnLink()ing it from its owner if it has one. */ void DeleteStructure() { - UnLink(); + if( GetList() != NULL ) + UnLink(); + delete this; } diff --git a/include/dialog_helpers.h b/include/dialog_helpers.h index dc621cab8a..9b33e23d37 100644 --- a/include/dialog_helpers.h +++ b/include/dialog_helpers.h @@ -74,7 +74,8 @@ public: const wxString& aRefText, void(*aCallBackFunction)(wxString& Text) = NULL, bool aSortList = false ); - ~EDA_LIST_DIALOG(); + + // ~EDA_LIST_DIALOG() {} void Append( const wxArrayString& aItemStr ); void InsertItems( const std::vector& aItemList, int aPosition = 0 ); diff --git a/include/dialog_shim.h b/include/dialog_shim.h index 8cd8025981..56e30253fb 100644 --- a/include/dialog_shim.h +++ b/include/dialog_shim.h @@ -52,15 +52,20 @@ public: const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE, - const wxString& name = wxDialogNameStr ); + const wxString& name = wxDialogNameStr + ); bool Show( bool show ); // overload wxDialog::Show +protected: + std::string m_hash_key; // alternate for class_map when classname re-used. #if DLGSHIM_USE_SETFOCUS private: void onInit( wxInitDialogEvent& aEvent ); #endif + + }; #endif // DIALOG_SHIM_ diff --git a/include/eda_text.h b/include/eda_text.h index b5988c244f..7de9dbd2c7 100644 --- a/include/eda_text.h +++ b/include/eda_text.h @@ -265,6 +265,17 @@ public: void SetHorizJustify( EDA_TEXT_HJUSTIFY_T aType ) { m_HJustify = aType; }; void SetVertJustify( EDA_TEXT_VJUSTIFY_T aType ) { m_VJustify = aType; }; + /** + * Function GetPositionsOfLinesOfMultilineText + * Populates aPositions with the position of each line of + * a multiline text, according to the vertical justification and the + * rotation of the whole text + * @param aPositions is the list to populate by the wxPoint positions + * @param aLineCount is the number of lines (not recalculated here + * for efficiency reasons + */ + void GetPositionsOfLinesOfMultilineText( + std::vector& aPositions, int aLineCount ); /** * Function Format * outputs the object to \a aFormatter in s-expression form. diff --git a/include/fctsys.h b/include/fctsys.h index ff239ce9de..a9522d2d51 100644 --- a/include/fctsys.h +++ b/include/fctsys.h @@ -26,32 +26,6 @@ #define DBG(x) // nothing #endif -/** - * Function Clamp - * limits @a value within the range @a lower <= @a value <= @a upper. It will work - * on temporary expressions, since they are evaluated only once, and it should work - * on most if not all numeric types, string types, or any type for which "operator < ()" - * is present. The arguments are accepted in this order so you can remember the - * expression as a memory aid: - *

- * result is: lower <= value <= upper - */ -template inline const T& Clamp( const T& lower, const T& value, const T& upper ) -{ - wxASSERT( lower <= upper ); - if( value < lower ) - return lower; - else if( upper < value ) - return upper; - return value; -} - -#define USE_RESIZE_BORDER -#if defined(__UNIX__) || defined(USE_RESIZE_BORDER) -#define MAYBE_RESIZE_BORDER wxRESIZE_BORDER // Linux users like resizeable borders -#else -#define MAYBE_RESIZE_BORDER 0 // no resizeable border -#endif // wxNullPtr is not defined prior to wxWidgets 2.9.0. #if !wxCHECK_VERSION( 2, 9, 0 ) diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index 6820265483..5a754320b6 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -27,13 +27,15 @@ #define FP_LIB_TABLE_H_ #include - #include #include - #include + +#define FP_LATE_ENVVAR 1 ///< late=1/early=0 environment variable expansion +#define KISYSMOD "KISYSMOD" + class wxFileName; class OUTPUTFORMATTER; class MODULE; @@ -120,44 +122,17 @@ public: SetType( aType ); } - ROW( const ROW& a ) : - nickName( a.nickName ), - uri_user( a.uri_user ), - uri_expanded( a.uri_expanded ), - type( a.type ), - options( a.options ), - description( a.description ), - properties( 0 ) - { - if( a.properties ) - properties = new PROPERTIES( *a.properties ); - } + ROW( const ROW& a ); ~ROW() { delete properties; } - ROW& operator=( const ROW& r ) - { - nickName = r.nickName; - uri_user = r.uri_user; - uri_expanded = r.uri_expanded; - type = r.type; - options = r.options; - description = r.description; - properties = r.properties ? new PROPERTIES( *r.properties ) : NULL; + ROW& operator=( const ROW& r ); - // do not copy the PLUGIN, it is lazily created. - setPlugin( NULL ); - - return *this; - } - - bool operator==( const ROW& r ) const - { - return nickName==r.nickName && uri_user==r.uri_user && type==r.type && options==r.options; - } + /// Used in DIALOG_FP_LIB_TABLE for detecting an edit. + bool operator==( const ROW& r ) const; bool operator!=( const ROW& r ) const { return !( *this == r ); } @@ -194,13 +169,7 @@ public: * * @param aSubstituted Tells if caller wanted the substituted form, else not. */ - const wxString& GetFullURI( bool aSubstituted = false ) const - { - if( aSubstituted ) - return uri_expanded; - else - return uri_user; - } + const wxString GetFullURI( bool aSubstituted = false ) const; /** * Function SetFullURI @@ -278,7 +247,11 @@ public: wxString nickName; wxString uri_user; ///< what user entered from UI or loaded from disk + +#if !FP_LATE_ENVVAR wxString uri_expanded; ///< from ExpandSubstitutions() +#endif + LIB_T type; wxString options; wxString description; @@ -421,6 +394,16 @@ public: */ MODULE* FootprintLoad( const wxString& aNickname, const wxString& aFootprintName ); + /** + * Enum SAVE_T + * is the set of return values from FootprintSave() below. + */ + enum SAVE_T + { + SAVE_OK, + SAVE_SKIPPED, + }; + /** * Function FootprintSave * will write @a aFootprint to an existing library given by @a aNickname. @@ -432,9 +415,14 @@ public: * @param aFootprint is what to store in the library. The caller continues * to own the footprint after this call. * + * @param aOverwrite when true means overwrite any existing footprint by the + * same name, else if false means skip the write and return SAVE_SKIPPED. + * + * @return SAVE_T - SAVE_OK or SAVE_SKIPPED. If error saving, then IO_ERROR is thrown. + * * @throw IO_ERROR if there is a problem saving. */ - void FootprintSave( const wxString& aNickname, const MODULE* aFootprint ); + SAVE_T FootprintSave( const wxString& aNickname, const MODULE* aFootprint, bool aOverwrite = true ); /** * Function FootprintDelete @@ -458,8 +446,18 @@ public: */ bool IsFootprintLibWritable( const wxString& aNickname ); + void FootprintLibDelete( const wxString& aNickname ); + + void FootprintLibCreate( const wxString& aNickname ); + //-------------------------------- + /** + * Function GetDescription + * returns the library desicription from @a aNickname, or an empty string + * if aNickname does not exist. + */ + const wxString GetDescription( const wxString& aNickname ); /** * Function InsertRow @@ -567,7 +565,22 @@ public: static void SetProjectPathEnvVariable( const wxFileName& aPath ); - const wxString& GetProjectPathEnvVariableName() const; + /** + * Function ProjectPathEnvVarVariableName + * returns the name of the environment variable used to hold the directory of + * the current project on program startup. + */ + static const wxString ProjectPathEnvVariableName(); + + /** + * Function GlobalPathEnvVarVariableName + * returns the name of the environment variable used to hold the directory of + * locally installed "KiCad sponsored" system footprint libraries. These can + * be either legacy or pretty format. The only thing special about this + * particular environment variable is that it is set automatically by + * KiCad on program startup, iff it is not set already in the environment. + */ + static const wxString GlobalPathEnvVariableName(); static wxString GetProjectFileName( const wxFileName& aPath ); @@ -587,10 +600,10 @@ protected: /** * Function findRow - * returns a ROW if aNickName is found in this table or in any chained + * returns a ROW if aNickname is found in this table or in any chained * fallBack table fragment, else NULL. */ - ROW* findRow( const wxString& aNickName ) const; + ROW* findRow( const wxString& aNickname ) const; void reindex() { diff --git a/include/kicad_string.h b/include/kicad_string.h index 91d5a0ad0c..49d23742c1 100644 --- a/include/kicad_string.h +++ b/include/kicad_string.h @@ -1,6 +1,27 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004 KiCad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + /** - * This file is part of the common library \n - * Custom string manipulation routines. * @file kicad_string.h * @see common.h, string.cpp */ @@ -10,6 +31,7 @@ #define KICAD_STRING_H_ #include +#include /** @@ -57,7 +79,7 @@ std::string EscapedUTF8( const wxString& aString ); char* GetLine( FILE* aFile, char* Line, int* LineNum = NULL, int SizeLine = 255 ); /** - * Funxtion StrPurge + * Function StrPurge * removes leading and training spaces, tabs and end of line chars in \a text * return a pointer on the first n char in text */ @@ -79,7 +101,7 @@ wxString DateAndTime(); * * @param aString1 A wxChar pointer to the reference string. * @param aString2 A wxChar pointer to the comparison string. - * @param aLength The numbere of characters to compare. Set to -1 to compare + * @param aLength The number of characters to compare. Set to -1 to compare * the entire string. * @param aIgnoreCase Use true to make the comparison case insensitive. * @return An integer value of -1 if \a aString1 is less than \a aString2, 0 if @@ -121,4 +143,25 @@ int SplitString( wxString strToSplit, wxString* strDigits, wxString* strEnd ); +/** + * Function GetIllegalFileNameWxChars + * @return a wString object containing the illegal file name characters for all platforms. + */ +wxString GetIllegalFileNameWxChars(); + +/** + * Function ReplaceIllegalFileNameChars + * checks \a aName for illegal file name characters. + * + * The Windows (DOS) file system forbidden characters already include the forbidden file + * name characters for both Posix and OSX systems. The characters \/?*|"\<\> are illegal + * and are replaced with %xx where xx the hexadecimal equivalent of the replaced character. + * This replacement may not be as elegant as using an underscore ('_') or hyphen ('-') but + * it guarentees that there will be no naming conflicts when fixing footprint library names. + * + * @param aName is a point to a std::string object containing the footprint name to verify. + * @return true if any characters have been replaced in \a aName. + */ +bool ReplaceIllegalFileNameChars( std::string* aName ); + #endif // KICAD_STRING_H_ diff --git a/include/macros.h b/include/macros.h index 3e0d953fba..0c5fc9dcf2 100644 --- a/include/macros.h +++ b/include/macros.h @@ -77,4 +77,25 @@ template inline void EXCHG( T& a, T2& b ) b = temp; } +/** + * Function Clamp + * limits @a value within the range @a lower <= @a value <= @a upper. It will work + * on temporary expressions, since they are evaluated only once, and it should work + * on most if not all numeric types, string types, or any type for which "operator < ()" + * is present. The arguments are accepted in this order so you can remember the + * expression as a memory aid: + *

+ * result is: lower <= value <= upper + */ +template inline const T& Clamp( const T& lower, const T& value, const T& upper ) +{ + wxASSERT( lower <= upper ); + if( value < lower ) + return lower; + else if( upper < value ) + return upper; + return value; +} + + #endif /* ifdef MACRO_H */ diff --git a/include/profile.h b/include/profile.h index f779dfae59..c0b1010faa 100644 --- a/include/profile.h +++ b/include/profile.h @@ -31,60 +31,9 @@ #define __TPROFILE_H #include +#include #include -/** - * Function rdtsc - * Returns processor's time-stamp counter. Main purpose is precise time measuring of code - * execution time. - * @return unsigned long long - Value of time-stamp counter. - */ -#if defined(__i386__) -static __inline__ unsigned long long rdtsc() -{ - unsigned long long int x; - __asm__ volatile ( ".byte 0x0f, 0x31" : "=A" ( x ) ); - - return x; -} - - -#elif defined(__x86_64__) -static __inline__ unsigned long long rdtsc() -{ - unsigned hi, lo; - __asm__ __volatile__ ( "rdtsc" : "=a" ( lo ), "=d" ( hi ) ); - - return ( (unsigned long long) lo ) | ( ( (unsigned long long) hi ) << 32 ); -} - - -#elif defined(__powerpc__) -static __inline__ unsigned long long rdtsc() -{ - unsigned long long int result = 0; - unsigned long int upper, lower, tmp; - __asm__ volatile ( - "0: \n" - "\tmftbu %0 \n" - "\tmftb %1 \n" - "\tmftbu %2 \n" - "\tcmpw %2,%0 \n" - "\tbne 0b \n" - : "=r" ( upper ), "=r" ( lower ), "=r" ( tmp ) - ); - - result = upper; - result = result << 32; - result = result | lower; - - return result; -} - - -#endif /* __powerpc__ */ - -// Fixme: OS X version /** * Function get_tics * Returns the number of microseconds that have elapsed since the system was started. @@ -98,14 +47,22 @@ static inline uint64_t get_tics() return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec; } - /** * Structure for storing data related to profiling counters. */ struct prof_counter { - uint64_t value; /// Stored timer value - bool use_rdtsc; /// Method of time measuring (rdtsc or tics) + uint64_t start, end; // Stored timer value + + uint64_t usecs() const + { + return end - start; + } + + float msecs() const + { + return ( end - start ) / 1000.0; + } }; /** @@ -116,32 +73,19 @@ struct prof_counter * Otherwise is system tics method will be used. IMPORTANT: time-stamp counter should not * be used on multicore machines executing threaded code. */ -static inline void prof_start( prof_counter* cnt, bool use_rdtsc ) +static inline void prof_start( prof_counter* aCnt ) { - cnt->use_rdtsc = use_rdtsc; - - if( use_rdtsc ) - { - cnt->value = rdtsc(); - } - else - { - cnt->value = get_tics(); - } + aCnt->start = get_tics(); } - /** * Function prof_stop * Ends code execution time counting for a given profiling counter. * @param cnt is the counter which should be stopped. */ -static inline void prof_end( prof_counter* cnt ) +static inline void prof_end( prof_counter* aCnt ) { - if( cnt->use_rdtsc ) - cnt->value = rdtsc() - cnt->value; - else - cnt->value = get_tics() - cnt->value; + aCnt->end = get_tics(); } #endif diff --git a/include/validators.h b/include/validators.h new file mode 100644 index 0000000000..ca98be89ab --- /dev/null +++ b/include/validators.h @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Wayne Stambaugh + * Copyright (C) 2004-2013 KiCad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file validators.h + * @brief Custom text control validator definitions. + */ + +#include + +/** + * Class FOOTPRINT_NAME_VALIDATOR + * + * This class provides a custom wxValidator object for limiting the allowable characters when + * defining footprint names. Since the introduction of the PRETTY footprint library format, + * footprint names cannot have any characters that would prevent file creation on any platform. + */ +class FOOTPRINT_NAME_VALIDATOR : public wxTextValidator +{ +public: + FOOTPRINT_NAME_VALIDATOR( wxString* aValue = NULL ) : + wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST, aValue ) + { + // The Windows (DOS) file system forbidden characters already include the forbidden + // file name characters for both Posix and OSX systems. The characters \/*?|"<> are + // illegal and filtered by the validator. + wxString illegalChars = wxFileName::GetForbiddenChars( wxPATH_DOS ); + wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST ); + wxArrayString illegalCharList; + + for( unsigned i = 0; i < illegalChars.size(); i++ ) + illegalCharList.Add( wxString( illegalChars[i] ) ); + + SetExcludes( illegalCharList ); + } +}; diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index f28fe191a2..ff0db2f2c2 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -127,6 +127,16 @@ public: ~PCB_BASE_FRAME(); + /** + * Function LoadFootprint + * attempts to load \a aFootprintId from the footprint library table. + * + * @param aFootprintId is the #FPID of component footprint to load. + * @return the #MODULE if found or NULL if \a aFootprintId not found in any of the + * libraries in #m_footprintLibTable. + */ + MODULE* LoadFootprint( const FPID& aFootprintId ); + /** * Function GetBoardBoundingBox * calculates the bounding box containing all board items (or board edge segments). @@ -285,7 +295,7 @@ public: * @param aLibName = name of the library to use * @param aModule = the given footprint * @param aOverwrite = true to overwrite an existing footprint, false to - * abort an existing footprint is found + * abort if an existing footprint with same name is found * @param aDisplayDialog = true to display a dialog to enter or confirm the * footprint name * @return : true if OK, false if abort @@ -295,6 +305,16 @@ public: bool aOverwrite, bool aDisplayDialog ); + /** + * Function SelectLibrary + * puts up a dialog and allows the user to pick a library, for unspecified use. + * + * @param aNicknameExisting is the current choice to highlight + * + * @return wxString - the library or wxEmptyString on abort. + */ + wxString SelectLibrary( const wxString& aNicknameExisting ); + MODULE* GetModuleByName(); /** diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index bcdf51c56f..fc7d379a07 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -119,7 +119,7 @@ protected: void setupTools(); void destroyTools(); - void onGenericCommand( wxCommandEvent& aEvent ); + void onGenericCommand( wxCommandEvent& aEvent ); // we'll use lower case function names for private member functions. void createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu* aPopMenu ); @@ -906,12 +906,11 @@ public: /** * Function ArchiveModulesOnBoard * Save modules in a library: - * @param aLibName: the full filename of the library to create or modify * @param aNewModulesOnly: * true : save modules not already existing in this lib * false: save all modules */ - void ArchiveModulesOnBoard( const wxString& aLibName, bool aNewModulesOnly ); + void ArchiveModulesOnBoard( bool aNewModulesOnly ); /** * Function RecreateBOMFileFromBoard @@ -1495,7 +1494,7 @@ public: // Autoplacement: - void AutoPlace( wxCommandEvent& event ); + void OnPlaceOrRouteFootprints( wxCommandEvent& event ); /** * Function ScriptingConsoleEnableDisable @@ -1521,7 +1520,17 @@ public: */ bool ReOrientModules( const wxString& ModuleMask, double Orient, bool include_fixe ); void LockModule( MODULE* aModule, bool aLocked ); - void AutoMoveModulesOnPcb( bool PlaceModulesHorsPcb ); + + /** + * Function SpreadFootprints + * Footprints (after loaded by reading a netlist for instance) are moved + * to be in a small free area (outside the current board) without overlapping. + * @param aFootprintsOutsideBoardOnly: true to move only + * footprints outside the board outlines + * (they are outside if the position of a footprint is outside + * the board outlines bounding box + */ + void SpreadFootprints( bool aFootprintsOutsideBoardOnly ); /** * Function AutoPlaceModule @@ -1531,52 +1540,6 @@ public: */ void AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ); - /** - * Function GetOptimalModulePlacement - * searches for the optimal position of the \a aModule. - * - * @param aModule A pointer to the MODULE object to get the optimal placement. - * @param aDC The device context to draw on. - * @return 1 if placement impossible or 0 if OK. - */ - int GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ); - - void GenModuleOnBoard( MODULE* Module ); - - /** - * Function Compute_Ratsnest_PlaceModule - * displays the module's ratsnest during displacement, and assess the "cost" - * of the position. - * - * The cost is the longest ratsnest distance with penalty for connections - * approaching 45 degrees. - */ - double Compute_Ratsnest_PlaceModule( wxDC* DC ); - - /** - * Function GenPlaceBoard - * generates board board (component side copper + rating): - * Allocate the memory needed to represent in "bitmap" on the grid - * Current: - * - The size of clearance area of component (the board) - * - The bitmap PENALTIES - * And initialize the cells of the board has - * - Hole in the cells occupied by a segment EDGE - * - CELL_is_ZONE for cell internal contour EDGE (if closed) - * - * Placement surface (board) gives the cells internal to the contour - * PCB, and among the latter the free cells and cells already occupied - * - * The bitmap PENALTIES give cells occupied by the modules, - * Plus a surface penalty related to the number of pads of the module - * - * Bitmap of the penalty is set to 0 - * Occupation cell is a 0 leaves - */ - int GenPlaceBoard(); - - void DrawInfoPlace( wxDC* DC ); - // Autorouting: int Solve( wxDC* DC, int two_sides ); void Reset_Noroutable( wxDC* DC ); diff --git a/include/wxstruct.h b/include/wxstruct.h index f97a1fb494..5b91ee655d 100644 --- a/include/wxstruct.h +++ b/include/wxstruct.h @@ -51,9 +51,7 @@ #include #endif -// Option for dialog boxes -#define DIALOG_STYLE wxDEFAULT_DIALOG_STYLE | wxFRAME_FLOAT_ON_PARENT | MAYBE_RESIZE_BORDER - +// Option for main frames #define KICAD_DEFAULT_DRAWFRAME_STYLE wxDEFAULT_FRAME_STYLE | wxWANTS_CHARS @@ -973,15 +971,15 @@ public: /** * Function UseGalCanvas * used to switch between standard and GAL-based canvas. - * - * @param aEnable True for GAL-based canvas, false for standard canvas. + * + * @param aEnable True for GAL-based canvas, false for standard canvas. */ virtual void UseGalCanvas( bool aEnable ); - + /** * Function IsNewCanvasActive * is used to check which canvas (GAL-based or standard) is currently in use. - * + * * @return True for GAL-based canvas, false for standard canvas. */ bool IsGalCanvasActive() { return m_galCanvasActive; } diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index f243ce065f..360f98a5c3 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -124,12 +124,14 @@ set( PCBNEW_IMPORT_DXF ) set( PCBNEW_AUTOROUTER_SRCS - autorouter/automove.cpp - autorouter/autoplac.cpp + autorouter/rect_placement/rect_placement.cpp + autorouter/move_and_route_event_functions.cpp + autorouter/auto_place_footprints.cpp autorouter/autorout.cpp autorouter/routing_matrix.cpp autorouter/dist.cpp autorouter/queue.cpp + autorouter/spread_footprints.cpp autorouter/solve.cpp autorouter/graphpcb.cpp autorouter/work.cpp diff --git a/pcbnew/autorouter/autoplac.cpp b/pcbnew/autorouter/auto_place_footprints.cpp similarity index 57% rename from pcbnew/autorouter/autoplac.cpp rename to pcbnew/autorouter/auto_place_footprints.cpp index 5aa3db6d0d..7322f5690b 100644 --- a/pcbnew/autorouter/autoplac.cpp +++ b/pcbnew/autorouter/auto_place_footprints.cpp @@ -1,6 +1,6 @@ /** * @file autoplac.cpp - * @brief Routiness to automatically place MODULES on a board. + * @brief Functions to automatically place Footprints on a board. */ /* @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -50,61 +49,97 @@ #include #include #include +#include +#include #define GAIN 16 #define KEEP_OUT_MARGIN 500 -/* Penalty for guidance given by CntRot90 and CntRot180: - * graduated from 0 (rotation allowed) to 10 (rotation count null) - * the count is increased. +/* Penalty (cost) for CntRot90 and CntRot180: + * CntRot90 and CntRot180 are from 0 (rotation allowed) to 10 (rotation not allowed) */ static const double OrientPenality[11] = { - 2.0f, // CntRot = 0 rotation prohibited - 1.9f, // CntRot = 1 - 1.8f, // CntRot = 2 - 1.7f, // CntRot = 3 - 1.6f, // CntRot = 4 - 1.5f, // CntRot = 5 - 1.4f, // CntRot = 5 - 1.3f, // CntRot = 7 - 1.2f, // CntRot = 8 - 1.1f, // CntRot = 9 - 1.0f // CntRot = 10 rotation authorized, no penalty + 2.0, // CntRot = 0 rotation prohibited + 1.9, // CntRot = 1 + 1.8, // CntRot = 2 + 1.7, // CntRot = 3 + 1.6, // CntRot = 4 + 1.5, // CntRot = 5 + 1.4, // CntRot = 5 + 1.3, // CntRot = 7 + 1.2, // CntRot = 8 + 1.1, // CntRot = 9 + 1.0 // CntRot = 10 rotation authorized, no penalty }; // Cell states. -#define OUT_OF_BOARD -2 -#define OCCUPED_By_MODULE -1 +#define OUT_OF_BOARD -2 +#define OCCUPED_By_MODULE -1 +#define FREE_CELL 0 -static wxPoint CurrPosition; // Current position of the current module placement -static bool AutoPlaceShowAll = true; - +static wxPoint CurrPosition; // Current position of the current module placement double MinCout; -static int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide ); -static void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, - int marge, int aKeepOut, int aLayerMask ); +/* generates the Routing matrix, used to fing the best placement + * of a footprint. + * Allocate a "bitmap" which is an image of the real board + * the bitmap handles: + * - The free areas + * - penalties (cell not occupied, but near occupied areas) + * - cells occupied by footprints, board cutout ... + */ +int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel ); -static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC ); -static int propagate(); +/* searches for the optimal position of aModule. + * return 1 if placement impossible or 0 if OK. + */ +static int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, + MODULE* aModule, wxDC* aDC ); + +/* + * Function compute_Ratsnest_PlaceModule + * displays the module's ratsnest during displacement, and assess the "cost" + * of the position. + * + * The cost is the longest ratsnest distance with penalty for connections + * approaching 45 degrees. + */ +static double compute_Ratsnest_PlaceModule( BOARD* aBrd ); + +/* Place a footprint on the Routing matrix. + */ +void genModuleOnRoutingMatrix( MODULE* Module ); +/* + * Displays the Placement/Routing matrix on the screen + */ +static void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC ); + +static int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide ); + +static void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, + int marge, int aKeepOut, int aLayerMask ); + +static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC ); +static int propagate(); void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) { - MODULE* currModule = NULL; - wxPoint PosOK; - wxPoint memopos; - int error; - LAYER_NUM lay_tmp_TOP, lay_tmp_BOTTOM; + MODULE* currModule = NULL; + wxPoint PosOK; + wxPoint memopos; + int error; + LAYER_NUM lay_tmp_TOP, lay_tmp_BOTTOM; // Undo: init list - PICKED_ITEMS_LIST newList; + PICKED_ITEMS_LIST newList; + newList.m_Status = UR_CHANGED; - ITEM_PICKER picker( NULL, UR_CHANGED ); + ITEM_PICKER picker( NULL, UR_CHANGED ); if( GetBoard()->m_Modules == NULL ) return; @@ -113,44 +148,46 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) switch( place_mode ) { - case PLACE_1_MODULE: - currModule = Module; + case PLACE_1_MODULE: + currModule = Module; - if( currModule == NULL ) - return; + if( currModule == NULL ) + return; - currModule->SetIsPlaced( false ); - currModule->SetNeedsPlaced( false ); - break; + currModule->SetIsPlaced( false ); + currModule->SetNeedsPlaced( false ); + break; - case PLACE_OUT_OF_BOARD: - break; + case PLACE_OUT_OF_BOARD: + break; - case PLACE_ALL: - if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) ) - return; + case PLACE_ALL: - break; + if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) ) + return; - case PLACE_INCREMENTAL: - if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) ) - return; + break; + + case PLACE_INCREMENTAL: + + if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) ) + return; break; } memopos = CurrPosition; - lay_tmp_BOTTOM = g_Route_Layer_BOTTOM; - lay_tmp_TOP = g_Route_Layer_TOP; + lay_tmp_BOTTOM = g_Route_Layer_BOTTOM; + lay_tmp_TOP = g_Route_Layer_TOP; RoutingMatrix.m_GridRouting = (int) GetScreen()->GetGridSize().x; // Ensure Board.m_GridRouting has a reasonable value: - if( RoutingMatrix.m_GridRouting < 10*IU_PER_MILS ) - RoutingMatrix.m_GridRouting = 10*IU_PER_MILS; // Min value = 1/1000 inch + if( RoutingMatrix.m_GridRouting < Millimeter2iu( 0.25 ) ) + RoutingMatrix.m_GridRouting = Millimeter2iu( 0.25 ); // Compute module parameters used in auto place - if( GenPlaceBoard() == 0 ) + if( genPlacementRoutingMatrix( GetBoard(), m_messagePanel ) == 0 ) return; int moduleCount = 0; @@ -163,6 +200,7 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) switch( place_mode ) { case PLACE_1_MODULE: + if( currModule == Module ) { // Module will be placed, add to undo. @@ -202,6 +240,7 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) break; case PLACE_INCREMENTAL: + if( Module->IsLocked() ) { Module->SetIsPlaced( false ); @@ -219,62 +258,61 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) break; } - - if( Module->NeedsPlaced() ) // Erase from screen + if( Module->NeedsPlaced() ) // Erase from screen { moduleCount++; Module->Draw( m_canvas, DC, GR_XOR ); } else { - GenModuleOnBoard( Module ); + genModuleOnRoutingMatrix( Module ); } } - // Undo command: commit list + // Undo command: prepare list if( newList.GetCount() ) SaveCopyInUndoList( newList, UR_CHANGED ); - int cnt = 0; - int ii; - wxString msg; + int cnt = 0; + wxString msg; while( ( Module = PickModule( this, DC ) ) != NULL ) { // Display some info about activity, module placement can take a while: - msg.Printf( _("Place module %d of %d"), cnt, moduleCount ); + msg.Printf( _( "Place module %d of %d" ), cnt, moduleCount ); SetStatusText( msg ); + double initialOrient = Module->GetOrientation(); // Display fill area of interest, barriers, penalties. - DrawInfoPlace( DC ); + drawPlacementRoutingMatrix( GetBoard(), DC ); - error = GetOptimalModulePlacement( Module, DC ); - double BestScore = MinCout; - PosOK = CurrPosition; + error = getOptimalModulePlacement( this, Module, DC ); + double bestScore = MinCout; + double bestRotation = 0.0; + int rotAllowed; + PosOK = CurrPosition; if( error == ESC ) goto end_of_tst; - // Determine if the best orientation of a module is 180. - ii = Module->GetPlacementCost180() & 0x0F; + // Try orientations 90, 180, 270 degrees from initial orientation + rotAllowed = Module->GetPlacementCost180(); - if( ii != 0 ) + if( rotAllowed != 0 ) { - int Angle_Rot_Module = 1800; - Rotate_Module( DC, Module, Angle_Rot_Module, false ); - Module->CalculateBoundingBox(); - error = GetOptimalModulePlacement( Module, DC ); - MinCout *= OrientPenality[ii]; + Rotate_Module( DC, Module, 1800.0, true ); + error = getOptimalModulePlacement( this, Module, DC ); + MinCout *= OrientPenality[rotAllowed]; - if( BestScore > MinCout ) // This orientation is best. + if( bestScore > MinCout ) // This orientation is better. { - PosOK = CurrPosition; - BestScore = MinCout; + PosOK = CurrPosition; + bestScore = MinCout; + bestRotation = 1800.0; } else { - Angle_Rot_Module = -1800; - Rotate_Module( DC, Module, Angle_Rot_Module, false ); + Rotate_Module( DC, Module, initialOrient, false ); } if( error == ESC ) @@ -282,49 +320,45 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) } // Determine if the best orientation of a module is 90. - ii = Module->GetPlacementCost90() & 0x0F; + rotAllowed = Module->GetPlacementCost90(); - if( ii != 0 ) + if( rotAllowed != 0 ) { - int Angle_Rot_Module = 900; - Rotate_Module( DC, Module, Angle_Rot_Module, false ); - error = GetOptimalModulePlacement( Module, DC ); - MinCout *= OrientPenality[ii]; + Rotate_Module( DC, Module, 900.0, true ); + error = getOptimalModulePlacement( this, Module, DC ); + MinCout *= OrientPenality[rotAllowed]; - if( BestScore > MinCout ) // This orientation is best. + if( bestScore > MinCout ) // This orientation is better. { - PosOK = CurrPosition; - BestScore = MinCout; + PosOK = CurrPosition; + bestScore = MinCout; + bestRotation = 900.0; } else { - Angle_Rot_Module = -900; - Rotate_Module( DC, Module, Angle_Rot_Module, false ); + Rotate_Module( DC, Module, initialOrient, false ); } if( error == ESC ) goto end_of_tst; } - // Determine if the best orientation of a module is 270. - ii = (Module->GetPlacementCost90() >> 4 ) & 0x0F; - - if( ii != 0 ) + // Determine if the best orientation of a module is -90. + if( rotAllowed != 0 ) { - int Angle_Rot_Module = 2700; - Rotate_Module( DC, Module, Angle_Rot_Module, false ); - error = GetOptimalModulePlacement( Module, DC ); - MinCout *= OrientPenality[ii]; + Rotate_Module( DC, Module, 2700.0, true ); + error = getOptimalModulePlacement( this, Module, DC ); + MinCout *= OrientPenality[rotAllowed]; - if( BestScore > MinCout ) // This orientation is best. + if( bestScore > MinCout ) // This orientation is better. { - PosOK = CurrPosition; - BestScore = MinCout; + PosOK = CurrPosition; + bestScore = MinCout; + bestRotation = 2700.0; } else { - Angle_Rot_Module = -2700; - Rotate_Module( DC, Module, Angle_Rot_Module, false ); + Rotate_Module( DC, Module, initialOrient, false ); } if( error == ESC ) @@ -339,12 +373,19 @@ end_of_tst: // Place module. CurrPosition = GetCrossHairPosition(); SetCrossHairPosition( PosOK ); + PlaceModule( Module, DC ); + + bestRotation += initialOrient; + + if( bestRotation != Module->GetOrientation() ) + Rotate_Module( DC, Module, bestRotation, false ); + SetCrossHairPosition( CurrPosition ); Module->CalculateBoundingBox(); - GenModuleOnBoard( Module ); + genModuleOnRoutingMatrix( Module ); Module->SetIsPlaced( true ); Module->SetNeedsPlaced( false ); } @@ -353,8 +394,8 @@ end_of_tst: RoutingMatrix.UnInitRoutingMatrix(); - g_Route_Layer_TOP = lay_tmp_TOP; - g_Route_Layer_BOTTOM = lay_tmp_BOTTOM; + g_Route_Layer_TOP = lay_tmp_TOP; + g_Route_Layer_BOTTOM = lay_tmp_BOTTOM; Module = GetBoard()->m_Modules; @@ -369,11 +410,11 @@ end_of_tst: } -void PCB_EDIT_FRAME::DrawInfoPlace( wxDC* DC ) +void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC ) { - int ii, jj; + int ii, jj; EDA_COLOR_T color; - int ox, oy; + int ox, oy; MATRIX_CELL top_state, bottom_state; GRSetDrawMode( DC, GR_COPY ); @@ -384,11 +425,11 @@ void PCB_EDIT_FRAME::DrawInfoPlace( wxDC* DC ) for( jj = 0; jj < RoutingMatrix.m_Ncols; jj++ ) { - ox = RoutingMatrix.m_BrdBox.GetX() + (jj * RoutingMatrix.m_GridRouting); - color = BLACK; + ox = RoutingMatrix.m_BrdBox.GetX() + (jj * RoutingMatrix.m_GridRouting); + color = BLACK; - top_state = RoutingMatrix.GetCell( ii, jj, TOP ); - bottom_state = RoutingMatrix.GetCell( ii, jj, BOTTOM ); + top_state = RoutingMatrix.GetCell( ii, jj, TOP ); + bottom_state = RoutingMatrix.GetCell( ii, jj, BOTTOM ); if( top_state & CELL_is_ZONE ) color = BLUE; @@ -400,43 +441,43 @@ void PCB_EDIT_FRAME::DrawInfoPlace( wxDC* DC ) color = LIGHTRED; else if( bottom_state & (HOLE | CELL_is_MODULE) ) color = LIGHTGREEN; - else // Display the filling and keep out regions. + else // Display the filling and keep out regions. { - if( RoutingMatrix.GetDist( ii, jj, TOP ) || - RoutingMatrix.GetDist( ii, jj, BOTTOM ) ) + if( RoutingMatrix.GetDist( ii, jj, TOP ) + || RoutingMatrix.GetDist( ii, jj, BOTTOM ) ) color = DARKGRAY; } - GRPutPixel( m_canvas->GetClipBox(), DC, ox, oy, color ); + GRPutPixel( NULL, DC, ox, oy, color ); } } } -int PCB_EDIT_FRAME::GenPlaceBoard() +int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel ) { - wxString msg; + wxString msg; RoutingMatrix.UnInitRoutingMatrix(); - EDA_RECT bbox = GetBoard()->ComputeBoundingBox( true ); + EDA_RECT bbox = aBrd->ComputeBoundingBox( true ); if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 ) { - DisplayError( this, _( "No PCB edge found, unknown board size!" ) ); + DisplayError( NULL, _( "No PCB edge found, unknown board size!" ) ); return 0; } - RoutingMatrix.ComputeMatrixSize( GetBoard(), true ); + RoutingMatrix.ComputeMatrixSize( aBrd, true ); int nbCells = RoutingMatrix.m_Ncols * RoutingMatrix.m_Nrows; - m_messagePanel->EraseMsgBox(); + messagePanel->EraseMsgBox(); msg.Printf( wxT( "%d" ), RoutingMatrix.m_Ncols ); - m_messagePanel->SetMessage( 1, _( "Cols" ), msg, GREEN ); + messagePanel->SetMessage( 1, _( "Cols" ), msg, GREEN ); msg.Printf( wxT( "%d" ), RoutingMatrix.m_Nrows ); - m_messagePanel->SetMessage( 7, _( "Lines" ), msg, GREEN ); + messagePanel->SetMessage( 7, _( "Lines" ), msg, GREEN ); msg.Printf( wxT( "%d" ), nbCells ); - m_messagePanel->SetMessage( 14, _( "Cells." ), msg, YELLOW ); + messagePanel->SetMessage( 14, _( "Cells." ), msg, YELLOW ); // Choose the number of board sides. RoutingMatrix.m_RoutingLayersCount = 2; @@ -445,7 +486,7 @@ int PCB_EDIT_FRAME::GenPlaceBoard() // Display memory usage. msg.Printf( wxT( "%d" ), RoutingMatrix.m_MemSize / 1024 ); - m_messagePanel->SetMessage( 24, wxT( "Mem(Kb)" ), msg, CYAN ); + messagePanel->SetMessage( 24, wxT( "Mem(Kb)" ), msg, CYAN ); g_Route_Layer_BOTTOM = LAYER_N_FRONT; @@ -461,7 +502,7 @@ int PCB_EDIT_FRAME::GenPlaceBoard() TmpSegm.SetNet( -1 ); TmpSegm.SetWidth( RoutingMatrix.m_GridRouting / 2 ); - EDA_ITEM* PtStruct = GetBoard()->m_Drawings; + EDA_ITEM* PtStruct = aBrd->m_Drawings; for( ; PtStruct != NULL; PtStruct = PtStruct->Next() ) { @@ -476,7 +517,7 @@ int PCB_EDIT_FRAME::GenPlaceBoard() break; TmpSegm.SetStart( DrawSegm->GetStart() ); - TmpSegm.SetEnd( DrawSegm->GetEnd() ); + TmpSegm.SetEnd( DrawSegm->GetEnd() ); TmpSegm.SetShape( DrawSegm->GetShape() ); TmpSegm.m_Param = DrawSegm->GetAngle(); @@ -509,19 +550,21 @@ int PCB_EDIT_FRAME::GenPlaceBoard() } -/* Place module on board. +/* Place module on Routing matrix. */ -void PCB_EDIT_FRAME::GenModuleOnBoard( MODULE* Module ) +void genModuleOnRoutingMatrix( MODULE* Module ) { - int ox, oy, fx, fy; - int marge = RoutingMatrix.m_GridRouting / 2; - int layerMask; - D_PAD* Pad; + int ox, oy, fx, fy; + int layerMask; + D_PAD* Pad; - ox = Module->GetBoundingBox().GetX() - marge; - fx = Module->GetBoundingBox().GetRight() + marge; - oy = Module->GetBoundingBox().GetY() - marge; - fy = Module->GetBoundingBox().GetBottom() + marge; + EDA_RECT fpBBox = Module->GetBoundingBox(); + + fpBBox.Inflate( RoutingMatrix.m_GridRouting / 2 ); + ox = fpBBox.GetX(); + fx = fpBBox.GetRight(); + oy = fpBBox.GetY(); + fy = fpBBox.GetBottom(); if( ox < RoutingMatrix.m_BrdBox.GetX() ) ox = RoutingMatrix.m_BrdBox.GetX(); @@ -558,70 +601,78 @@ void PCB_EDIT_FRAME::GenModuleOnBoard( MODULE* Module ) TraceFilledRectangle( ox, oy, fx, fy, layerMask, CELL_is_MODULE, WRITE_OR_CELL ); - int trackWidth = GetBoard()->m_NetClasses.GetDefault()->GetTrackWidth(); - int clearance = GetBoard()->m_NetClasses.GetDefault()->GetClearance(); - - // Trace pads and surface safely. - marge = trackWidth + clearance; - + // Trace pads + clearance areas. for( Pad = Module->Pads(); Pad != NULL; Pad = Pad->Next() ) { - ::PlacePad( Pad, CELL_is_MODULE, marge, WRITE_OR_CELL ); + int margin = (RoutingMatrix.m_GridRouting / 2) + Pad->GetClearance(); + ::PlacePad( Pad, CELL_is_MODULE, margin, WRITE_OR_CELL ); } // Trace clearance. - marge = ( RoutingMatrix.m_GridRouting * Module->GetPadCount() ) / GAIN; - CreateKeepOutRectangle( ox, oy, fx, fy, marge, KEEP_OUT_MARGIN, layerMask ); + int margin = ( RoutingMatrix.m_GridRouting * Module->GetPadCount() ) / GAIN; + CreateKeepOutRectangle( ox, oy, fx, fy, margin, KEEP_OUT_MARGIN, layerMask ); } - -int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) +// A minor helper function to draw a bounding box: +inline void draw_FootprintRect(EDA_RECT * aClipBox, wxDC* aDC, EDA_RECT& fpBBox, EDA_COLOR_T aColor) +{ +#ifndef USE_WX_OVERLAY + GRRect( aClipBox, aDC, fpBBox, 0, aColor ); +#endif +} + +int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aDC ) { - int cx, cy; - int ox, oy, fx, fy; // occupying part of the module focuses on the cursor int error = 1; - int showRat = 0; wxPoint LastPosOK; - double mincout, cout, Score; - int keepOut; + double min_cost, curr_cost, Score; bool TstOtherSide; bool showRats = g_Show_Module_Ratsnest; + BOARD* brd = aFrame->GetBoard(); + + aModule->CalculateBoundingBox(); g_Show_Module_Ratsnest = false; - SetMsgPanel( aModule ); + brd->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK; + aFrame->SetMsgPanel( aModule ); - LastPosOK.x = RoutingMatrix.m_BrdBox.GetX(); - LastPosOK.y = RoutingMatrix.m_BrdBox.GetY(); + LastPosOK = RoutingMatrix.m_BrdBox.GetOrigin(); - cx = aModule->GetPosition().x; - cy = aModule->GetPosition().y; - ox = aModule->GetBoundingBox().GetX() - cx; - fx = aModule->GetBoundingBox().GetWidth() + ox; - oy = aModule->GetBoundingBox().GetY() - cy; - fy = aModule->GetBoundingBox().GetHeight() + oy; + wxPoint mod_pos = aModule->GetPosition(); + EDA_RECT fpBBox = aModule->GetFootprintRect(); - CurrPosition.x = RoutingMatrix.m_BrdBox.GetX() - ox; - CurrPosition.y = RoutingMatrix.m_BrdBox.GetY() - oy; + // Move fpBBox to have the footprint position at (0,0) + fpBBox.Move( -mod_pos ); + wxPoint fpBBoxOrg = fpBBox.GetOrigin(); - // Module placement on grid. - CurrPosition.x -= CurrPosition.x % RoutingMatrix.m_GridRouting; - CurrPosition.y -= CurrPosition.y % RoutingMatrix.m_GridRouting; + // Calculate the limit of the footprint position, relative + // to the routing matrix area + wxPoint xylimit = RoutingMatrix.m_BrdBox.GetEnd() - fpBBox.GetEnd(); - g_Offset_Module.x = cx - CurrPosition.x; - g_Offset_Module.y = cy - CurrPosition.y; - GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK; + wxPoint initialPos = RoutingMatrix.m_BrdBox.GetOrigin() - fpBBoxOrg; - /* Test pads, a printed circuit with components of the 2 dimensions - * can become a component on opposite side if there is at least 1 patch - * appearing on the other side. + // Stay on grid. + initialPos.x -= initialPos.x % RoutingMatrix.m_GridRouting; + initialPos.y -= initialPos.y % RoutingMatrix.m_GridRouting; + + CurrPosition = initialPos; + + // Undraw the current footprint + g_Offset_Module = wxPoint( 0, 0 ); + DrawModuleOutlines( aFrame->GetCanvas(), aDC, aModule ); + + g_Offset_Module = mod_pos - CurrPosition; + + /* Examine pads, and set TstOtherSide to true if a footprint + * has at least 1 pad through. */ TstOtherSide = false; if( RoutingMatrix.m_RoutingLayersCount > 1 ) { - D_PAD* Pad; - int otherLayerMask = LAYER_BACK; + D_PAD* Pad; + int otherLayerMask = LAYER_BACK; if( aModule->GetLayer() == LAYER_N_BACK ) otherLayerMask = LAYER_FRONT; @@ -636,102 +687,74 @@ int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) } } - DrawModuleOutlines( m_canvas, aDC, aModule ); + // Draw the initial bounding box position + EDA_COLOR_T color = BROWN; + fpBBox.SetOrigin( fpBBoxOrg + CurrPosition ); + draw_FootprintRect(aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color); - mincout = -1.0; - SetStatusText( wxT( "Score ??, pos ??" ) ); + min_cost = -1.0; + aFrame->SetStatusText( wxT( "Score ??, pos ??" ) ); - for( ; CurrPosition.x < RoutingMatrix.m_BrdBox.GetRight() - fx; - CurrPosition.x += RoutingMatrix.m_GridRouting ) + for( ; CurrPosition.x < xylimit.x; CurrPosition.x += RoutingMatrix.m_GridRouting ) { wxYield(); - if( m_canvas->GetAbortRequest() ) + if( aFrame->GetCanvas()->GetAbortRequest() ) { - if( IsOK( this, _( "OK to abort?" ) ) ) + if( IsOK( aFrame, _( "OK to abort?" ) ) ) return ESC; else - m_canvas->SetAbortRequest( false ); + aFrame->GetCanvas()->SetAbortRequest( false ); } - cx = aModule->GetPosition().x; - cy = aModule->GetPosition().y; - aModule->GetBoundingBox().SetX( ox + CurrPosition.x ); - aModule->GetBoundingBox().SetY( oy + CurrPosition.y ); + CurrPosition.y = initialPos.y; - DrawModuleOutlines( m_canvas, aDC, aModule ); - - g_Offset_Module.x = cx - CurrPosition.x; - CurrPosition.y = RoutingMatrix.m_BrdBox.GetY() - oy; - - // Placement on grid. - CurrPosition.y -= CurrPosition.y % RoutingMatrix.m_GridRouting; - - DrawModuleOutlines( m_canvas, aDC, aModule ); - - for( ; CurrPosition.y < RoutingMatrix.m_BrdBox.GetBottom() - fy; - CurrPosition.y += RoutingMatrix.m_GridRouting ) + for( ; CurrPosition.y < xylimit.y; CurrPosition.y += RoutingMatrix.m_GridRouting ) { -#ifndef USE_WX_OVERLAY // Erase traces. - DrawModuleOutlines( m_canvas, aDC, aModule ); + draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color ); - if( showRat ) - Compute_Ratsnest_PlaceModule( aDC ); -#endif - showRat = 0; - aModule->GetBoundingBox().SetX( ox + CurrPosition.x ); - aModule->GetBoundingBox().SetY( oy + CurrPosition.y ); + fpBBox.SetOrigin( fpBBoxOrg + CurrPosition ); + g_Offset_Module = mod_pos - CurrPosition; + int keepOutCost = TstModuleOnBoard( brd, aModule, TstOtherSide ); - g_Offset_Module.y = cy - CurrPosition.y; -#ifndef USE_WX_OVERLAY - DrawModuleOutlines( m_canvas, aDC, aModule ); -#endif - keepOut = TstModuleOnBoard( GetBoard(), aModule, TstOtherSide ); + // Draw at new place + color = keepOutCost >= 0 ? BROWN : RED; + draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color ); - if( keepOut >= 0 ) // i.e. if the module can be put here + if( keepOutCost >= 0 ) // i.e. if the module can be put here { error = 0; - build_ratsnest_module( aModule ); - cout = Compute_Ratsnest_PlaceModule( aDC ); - showRat = 1; - Score = cout + keepOut; + aFrame->build_ratsnest_module( aModule ); + curr_cost = compute_Ratsnest_PlaceModule( brd ); + Score = curr_cost + keepOutCost; - if( (mincout >= Score ) || (mincout < 0 ) ) + if( (min_cost >= Score ) || (min_cost < 0 ) ) { - LastPosOK = CurrPosition; - mincout = Score; + LastPosOK = CurrPosition; + min_cost = Score; wxString msg; - msg.Printf( wxT( "Score %g, pos %3.4g, %3.4g" ), - mincout, - (double) LastPosOK.x / 10000, - (double) LastPosOK.y / 10000 ); - SetStatusText( msg ); + msg.Printf( wxT( "Score %g, pos %s, %s" ), + min_cost, + GetChars( ::CoordinateToString( LastPosOK.x ) ), + GetChars( ::CoordinateToString( LastPosOK.y ) ) ); + aFrame->SetStatusText( msg ); } } - - if( showRat ) - Compute_Ratsnest_PlaceModule( aDC ); - - showRat = 0; } } - DrawModuleOutlines( m_canvas, aDC, aModule ); // erasing the last traces + // erasing the last traces + GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN ); g_Show_Module_Ratsnest = showRats; - if( showRat ) - Compute_Ratsnest_PlaceModule( aDC ); - // Regeneration of the modified variable. - aModule->GetBoundingBox().SetX( ox + cx ); - aModule->GetBoundingBox().SetY( oy + cy ); CurrPosition = LastPosOK; - GetBoard()->m_Status_Pcb &= ~( RATSNEST_ITEM_LOCAL_OK | LISTE_PAD_OK ); + brd->m_Status_Pcb &= ~( RATSNEST_ITEM_LOCAL_OK | LISTE_PAD_OK ); - MinCout = mincout; + MinCout = min_cost; return error; } @@ -740,29 +763,29 @@ int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) * - is a free zone (except OCCUPED_By_MODULE returns) * - is on the working surface of the board (otherwise returns OUT_OF_BOARD) * - * Returns 0 if OK + * Returns OUT_OF_BOARD, or OCCUPED_By_MODULE or FREE_CELL if OK */ -int TstRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1, int side ) +int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side ) { - int row, col; - int row_min, row_max, col_min, col_max; - unsigned int data; + EDA_RECT rect = aRect; - ux0 -= Pcb->GetBoundingBox().GetX(); - uy0 -= Pcb->GetBoundingBox().GetY(); - ux1 -= Pcb->GetBoundingBox().GetX(); - uy1 -= Pcb->GetBoundingBox().GetY(); + rect.Inflate( RoutingMatrix.m_GridRouting / 2 ); - row_max = uy1 / RoutingMatrix.m_GridRouting; - col_max = ux1 / RoutingMatrix.m_GridRouting; - row_min = uy0 / RoutingMatrix.m_GridRouting; + wxPoint start = rect.GetOrigin(); + wxPoint end = rect.GetEnd(); - if( uy0 > row_min * RoutingMatrix.m_GridRouting ) + start -= RoutingMatrix.m_BrdBox.GetOrigin(); + end -= RoutingMatrix.m_BrdBox.GetOrigin(); + + int row_min = start.y / RoutingMatrix.m_GridRouting; + int row_max = end.y / RoutingMatrix.m_GridRouting; + int col_min = start.x / RoutingMatrix.m_GridRouting; + int col_max = end.x / RoutingMatrix.m_GridRouting; + + if( start.y > row_min * RoutingMatrix.m_GridRouting ) row_min++; - col_min = ux0 / RoutingMatrix.m_GridRouting; - - if( ux0 > col_min * RoutingMatrix.m_GridRouting ) + if( start.x > col_min * RoutingMatrix.m_GridRouting ) col_min++; if( row_min < 0 ) @@ -777,49 +800,45 @@ int TstRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1, int side ) if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) ) col_max = RoutingMatrix.m_Ncols - 1; - for( row = row_min; row <= row_max; row++ ) + for( int row = row_min; row <= row_max; row++ ) { - for( col = col_min; col <= col_max; col++ ) + for( int col = col_min; col <= col_max; col++ ) { - data = RoutingMatrix.GetCell( row, col, side ); + unsigned int data = RoutingMatrix.GetCell( row, col, side ); if( ( data & CELL_is_ZONE ) == 0 ) return OUT_OF_BOARD; - if( data & CELL_is_MODULE ) + if( (data & CELL_is_MODULE) ) return OCCUPED_By_MODULE; } } - return 0; + return FREE_CELL; } /* Calculates and returns the clearance area of the rectangular surface - * (ux, ux .. y0, y1): + * aRect): * (Sum of cells in terms of distance) */ -unsigned int CalculateKeepOutArea( int ux0, int uy0, int ux1, int uy1, int side ) +unsigned int CalculateKeepOutArea( const EDA_RECT& aRect, int side ) { - int row, col; - int row_min, row_max, col_min, col_max; - unsigned int keepOut; + wxPoint start = aRect.GetOrigin(); + wxPoint end = aRect.GetEnd(); - ux0 -= RoutingMatrix.m_BrdBox.GetX(); - uy0 -= RoutingMatrix.m_BrdBox.GetY(); - ux1 -= RoutingMatrix.m_BrdBox.GetX(); - uy1 -= RoutingMatrix.m_BrdBox.GetY(); + start -= RoutingMatrix.m_BrdBox.GetOrigin(); + end -= RoutingMatrix.m_BrdBox.GetOrigin(); - row_max = uy1 / RoutingMatrix.m_GridRouting; - col_max = ux1 / RoutingMatrix.m_GridRouting; - row_min = uy0 / RoutingMatrix.m_GridRouting; + int row_min = start.y / RoutingMatrix.m_GridRouting; + int row_max = end.y / RoutingMatrix.m_GridRouting; + int col_min = start.x / RoutingMatrix.m_GridRouting; + int col_max = end.x / RoutingMatrix.m_GridRouting; - if( uy0 > row_min * RoutingMatrix.m_GridRouting ) + if( start.y > row_min * RoutingMatrix.m_GridRouting ) row_min++; - col_min = ux0 / RoutingMatrix.m_GridRouting; - - if( ux0 > col_min * RoutingMatrix.m_GridRouting ) + if( start.x > col_min * RoutingMatrix.m_GridRouting ) col_min++; if( row_min < 0 ) @@ -834,104 +853,95 @@ unsigned int CalculateKeepOutArea( int ux0, int uy0, int ux1, int uy1, int side if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) ) col_max = RoutingMatrix.m_Ncols - 1; - keepOut = 0; + unsigned int keepOutCost = 0; - for( row = row_min; row <= row_max; row++ ) + for( int row = row_min; row <= row_max; row++ ) { - for( col = col_min; col <= col_max; col++ ) + for( int col = col_min; col <= col_max; col++ ) { - keepOut += RoutingMatrix.GetDist( row, col, side ); + // RoutingMatrix.GetDist returns the "cost" of the cell + // at position (row, col) + // in autoplace this is the cost of the cell, if it is + // inside aRect + keepOutCost += RoutingMatrix.GetDist( row, col, side ); } } - return keepOut; + return keepOutCost; } /* Test if the module can be placed on the board. * Returns the value TstRectangle(). - * Module is known by its rectangle + * Module is known by its bounding box */ -int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide ) +int TstModuleOnBoard( BOARD* Pcb, MODULE* aModule, bool TstOtherSide ) { - int ox, oy, fx, fy; - int error, marge, side, otherside; + int side = TOP; + int otherside = BOTTOM; - side = TOP; otherside = BOTTOM; - - if( Module->GetLayer() == LAYER_N_BACK ) + if( aModule->GetLayer() == LAYER_N_BACK ) { side = BOTTOM; otherside = TOP; } - ox = Module->GetBoundingBox().GetX(); - fx = Module->GetBoundingBox().GetRight(); - oy = Module->GetBoundingBox().GetY(); - fy = Module->GetBoundingBox().GetBottom(); + EDA_RECT fpBBox = aModule->GetFootprintRect(); + fpBBox.Move( -g_Offset_Module ); - error = TstRectangle( Pcb, ox, oy, fx, fy, side ); + int diag = TstRectangle( Pcb, fpBBox, side ); - if( error < 0 ) - return error; + if( diag != FREE_CELL ) + return diag; if( TstOtherSide ) { - error = TstRectangle( Pcb, ox, oy, fx, fy, otherside ); + diag = TstRectangle( Pcb, fpBBox, otherside ); - if( error < 0 ) - return error; + if( diag != FREE_CELL ) + return diag; } - marge = ( RoutingMatrix.m_GridRouting * Module->GetPadCount() ) / GAIN; + int marge = ( RoutingMatrix.m_GridRouting * aModule->GetPadCount() ) / GAIN; - return CalculateKeepOutArea( ox - marge, oy - marge, fx + marge, fy + marge, side ); + fpBBox.Inflate( marge ); + return CalculateKeepOutArea( fpBBox, side ); } -double PCB_EDIT_FRAME::Compute_Ratsnest_PlaceModule( wxDC* DC ) +double compute_Ratsnest_PlaceModule( BOARD* aBrd ) { - double cout, icout; + double curr_cost; wxPoint start; // start point of a ratsnest wxPoint end; // end point of a ratsnest - int dx, dy; + int dx, dy; - if( ( GetBoard()->m_Status_Pcb & RATSNEST_ITEM_LOCAL_OK ) == 0 ) + if( ( aBrd->m_Status_Pcb & RATSNEST_ITEM_LOCAL_OK ) == 0 ) return -1; - cout = 0; + curr_cost = 0; - EDA_COLOR_T color = g_ColorsSettings.GetItemColor(RATSNEST_VISIBLE); - - if( AutoPlaceShowAll ) - GRSetDrawMode( DC, GR_XOR ); - - for( unsigned ii = 0; ii < GetBoard()->m_LocalRatsnest.size(); ii++ ) + for( unsigned ii = 0; ii < aBrd->m_LocalRatsnest.size(); ii++ ) { - RATSNEST_ITEM* pt_local_rats_nest = &GetBoard()->m_LocalRatsnest[ii]; + RATSNEST_ITEM* pt_local_rats_nest = &aBrd->m_LocalRatsnest[ii]; if( ( pt_local_rats_nest->m_Status & LOCAL_RATSNEST_ITEM ) ) - continue; // Skip ratsnest between 2 pads of the current module + continue; // Skip ratsnest between 2 pads of the current module // Skip modules not inside the board area - MODULE * module = pt_local_rats_nest->m_PadEnd->GetParent(); + MODULE* module = pt_local_rats_nest->m_PadEnd->GetParent(); + if( !RoutingMatrix.m_BrdBox.Contains( module->GetPosition() ) ) continue; - start = pt_local_rats_nest->m_PadStart->GetPosition() - g_Offset_Module; - end = pt_local_rats_nest->m_PadEnd->GetPosition(); + start = pt_local_rats_nest->m_PadStart->GetPosition() - g_Offset_Module; + end = pt_local_rats_nest->m_PadEnd->GetPosition(); -#ifndef USE_WX_OVERLAY - if( AutoPlaceShowAll ) - { - GRLine( m_canvas->GetClipBox(), DC, start, end, 0, color ); - } -#endif // Cost of the ratsnest. - dx = end.x - start.x; - dy = end.y - start.y; + dx = end.x - start.x; + dy = end.y - start.y; - dx = abs( dx ); - dy = abs( dy ); + dx = abs( dx ); + dy = abs( dy ); // ttry to have always dx >= dy to calculate the cost of the rastsnet if( dx < dy ) @@ -942,11 +952,11 @@ double PCB_EDIT_FRAME::Compute_Ratsnest_PlaceModule( wxDC* DC ) // the penalty is max for 45 degrees ratsnests, // and 0 for horizontal or vertical ratsnests. // For Horizontal and Vertical ratsnests, dy = 0; - icout = hypot( dx, dy * 2.0 ); - cout += icout; // Total cost = sum of costs of each connection + double conn_cost = hypot( dx, dy * 2.0 ); + curr_cost += conn_cost; // Total cost = sum of costs of each connection } - return cout; + return curr_cost; } @@ -957,23 +967,23 @@ double PCB_EDIT_FRAME::Compute_Ratsnest_PlaceModule( wxDC* DC ) * incremented by value aKeepOut * Cell outside this rectangle, but inside the rectangle * x0,y0 -marge to x1,y1 + marge are incremented by a decreasing value - * (aKeepOut ... 0). The decreasing value de pends on the distance to the first rectangle - * Therefore the cost is high in rect x0,y0 a x1,y1, and decrease outside this rectangle + * (aKeepOut ... 0). The decreasing value depends on the distance to the first rectangle + * Therefore the cost is high in rect x0,y0 to x1,y1, and decrease outside this rectangle */ void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, int marge, int aKeepOut, int aLayerMask ) { - int row, col; - int row_min, row_max, col_min, col_max, pmarge; - int trace = 0; - DIST_CELL data, LocalKeepOut; - int lgain, cgain; + int row, col; + int row_min, row_max, col_min, col_max, pmarge; + int trace = 0; + DIST_CELL data, LocalKeepOut; + int lgain, cgain; if( aLayerMask & GetLayerMask( g_Route_Layer_BOTTOM ) ) - trace = 1; // Trace on bottom layer. + trace = 1; // Trace on bottom layer. if( ( aLayerMask & GetLayerMask( g_Route_Layer_TOP ) ) && RoutingMatrix.m_RoutingLayersCount ) - trace |= 2; // Trace on top layer. + trace |= 2; // Trace on top layer. if( trace == 0 ) return; @@ -1027,6 +1037,12 @@ void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, for( col = col_min; col <= col_max; col++ ) { + // RoutingMatrix Dist map containt the "cost" of the cell + // at position (row, col) + // in autoplace this is the cost of the cell, when + // a footprint overlaps it, near a "master" footprint + // this cost is hight near the "master" footprint + // and decrease with the distance cgain = 256; LocalKeepOut = aKeepOut; @@ -1048,8 +1064,8 @@ void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, if( trace & 2 ) { - data = RoutingMatrix.GetDist( row, col, TOP ); - data = std::max( data, LocalKeepOut ); + data = RoutingMatrix.GetDist( row, col, TOP ); + data = std::max( data, LocalKeepOut ); RoutingMatrix.SetDist( row, col, TOP, data ); } } @@ -1069,7 +1085,7 @@ static bool Tri_PlaceModules( MODULE* ref, MODULE* compare ) } -static bool Tri_RatsModules( MODULE* ref, MODULE* compare ) +static bool sortFootprintsByRatsnestSize( MODULE* ref, MODULE* compare ) { double ff1, ff2; @@ -1088,7 +1104,7 @@ static bool Tri_RatsModules( MODULE* ref, MODULE* compare ) */ static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) { - MODULE* Module; + MODULE* Module; std::vector moduleList; // Build sorted footprints list (sort by decreasing size ) @@ -1097,7 +1113,7 @@ static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) for( ; Module != NULL; Module = Module->Next() ) { Module->CalculateBoundingBox(); - moduleList.push_back(Module); + moduleList.push_back( Module ); } sort( moduleList.begin(), moduleList.end(), Tri_PlaceModules ); @@ -1125,11 +1141,11 @@ static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK; - sort( moduleList.begin(), moduleList.end(), Tri_RatsModules ); + sort( moduleList.begin(), moduleList.end(), sortFootprintsByRatsnestSize ); // Search for "best" module. - MODULE* bestModule = NULL; - MODULE* altModule = NULL; + MODULE* bestModule = NULL; + MODULE* altModule = NULL; for( unsigned ii = 0; ii < moduleList.size(); ii++ ) { @@ -1180,10 +1196,10 @@ static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) */ int propagate() { - int row, col; - long current_cell, old_cell_H; - std::vector< long > pt_cell_V; - int nbpoints = 0; + int row, col; + long current_cell, old_cell_H; + std::vector pt_cell_V; + int nbpoints = 0; #define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE) @@ -1199,7 +1215,7 @@ int propagate() { current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; - if( current_cell == 0 ) // a free cell is found + if( current_cell == 0 ) // a free cell is found { if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) ) { @@ -1224,7 +1240,7 @@ int propagate() { current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; - if( current_cell == 0 ) // a free cell is found + if( current_cell == 0 ) // a free cell is found { if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) ) { @@ -1249,7 +1265,7 @@ int propagate() { current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; - if( current_cell == 0 ) // a free cell is found + if( current_cell == 0 ) // a free cell is found { if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) ) { @@ -1274,7 +1290,7 @@ int propagate() { current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; - if( current_cell == 0 ) // a free cell is found + if( current_cell == 0 ) // a free cell is found { if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) ) { diff --git a/pcbnew/autorouter/automove.cpp b/pcbnew/autorouter/move_and_route_event_functions.cpp similarity index 55% rename from pcbnew/autorouter/automove.cpp rename to pcbnew/autorouter/move_and_route_event_functions.cpp index 19d04e5885..8fb6ffcf56 100644 --- a/pcbnew/autorouter/automove.cpp +++ b/pcbnew/autorouter/move_and_route_event_functions.cpp @@ -55,15 +55,13 @@ typedef enum { } SelectFixeFct; -static bool sortModulesbySize( MODULE* ref, MODULE* compare ); - wxString ModulesMaskSelection = wxT( "*" ); /* Called on events (popup menus) relative to automove and autoplace footprints */ -void PCB_EDIT_FRAME::AutoPlace( wxCommandEvent& event ) +void PCB_EDIT_FRAME::OnPlaceOrRouteFootprints( wxCommandEvent& event ) { int id = event.GetId(); @@ -130,12 +128,19 @@ void PCB_EDIT_FRAME::AutoPlace( wxCommandEvent& event ) AutoPlaceModule( NULL, PLACE_INCREMENTAL, &dc ); break; - case ID_POPUP_PCB_AUTOMOVE_ALL_MODULES: - AutoMoveModulesOnPcb( false ); - break; + case ID_POPUP_PCB_SPREAD_ALL_MODULES: + if( !IsOK( this, + _("Not locked footprints inside the board will be moved. OK?") ) ) + break; + // Fall through + case ID_POPUP_PCB_SPREAD_NEW_MODULES: + if( GetBoard()->m_Modules == NULL ) + { + DisplayError( this, _( "No modules found!" ) ); + return; + } - case ID_POPUP_PCB_AUTOMOVE_NEW_MODULES: - AutoMoveModulesOnPcb( true ); + SpreadFootprints( id == ID_POPUP_PCB_SPREAD_NEW_MODULES ); break; case ID_POPUP_PCB_AUTOROUTE_ALL_MODULES: @@ -159,7 +164,7 @@ void PCB_EDIT_FRAME::AutoPlace( wxCommandEvent& event ) break; default: - wxMessageBox( wxT( "AutoPlace command error" ) ); + wxMessageBox( wxT( "OnPlaceOrRouteFootprints command error" ) ); break; } @@ -168,135 +173,6 @@ void PCB_EDIT_FRAME::AutoPlace( wxCommandEvent& event ) } -/* Function to move components in a rectangular area format 4 / 3, - * starting from the mouse cursor - * The components with the FIXED status set are not moved - */ -void PCB_EDIT_FRAME::AutoMoveModulesOnPcb( bool PlaceModulesHorsPcb ) -{ - std::vector moduleList; - wxPoint start, current; - int Ymax_size, Xsize_allowed; - int pas_grille = (int) GetScreen()->GetGridSize().x; - double surface; - - // Undo: init list - PICKED_ITEMS_LIST newList; - newList.m_Status = UR_CHANGED; - ITEM_PICKER picker( NULL, UR_CHANGED ); - - if( GetBoard()->m_Modules == NULL ) - { - DisplayError( this, _( "No modules found!" ) ); - return; - } - - // Confirmation - if( !IsOK( this, _( "Move modules?" ) ) ) - return; - - EDA_RECT bbbox = GetBoard()->ComputeBoundingBox( true ); - - bool edgesExist = ( bbbox.GetWidth() || bbbox.GetHeight() ); - - // no edges exist - if( PlaceModulesHorsPcb && !edgesExist ) - { - DisplayError( this, - _( "Could not automatically place modules. No board outlines detected." ) ); - return; - } - - // Build sorted footprints list (sort by decreasing size ) - MODULE* Module = GetBoard()->m_Modules; - - for( ; Module != NULL; Module = Module->Next() ) - { - Module->CalculateBoundingBox(); - moduleList.push_back(Module); - } - - sort( moduleList.begin(), moduleList.end(), sortModulesbySize ); - - /* to move modules outside the board, the cursor is placed below - * the current board, to avoid placing components in board area. - */ - if( PlaceModulesHorsPcb && edgesExist ) - { - if( GetCrossHairPosition().y < (bbbox.GetBottom() + 2000) ) - { - wxPoint pos = GetCrossHairPosition(); - pos.y = bbbox.GetBottom() + 2000; - SetCrossHairPosition( pos ); - } - } - - // calculate the area needed by footprints - surface = 0.0; - - for( unsigned ii = 0; ii < moduleList.size(); ii++ ) - { - Module = moduleList[ii]; - - if( PlaceModulesHorsPcb && edgesExist ) - { - if( bbbox.Contains( Module->GetPosition() ) ) - continue; - } - - surface += Module->GetArea(); - } - - Xsize_allowed = (int) ( sqrt( surface ) * 4.0 / 3.0 ); - - start = current = GetCrossHairPosition(); - Ymax_size = 0; - - for( unsigned ii = 0; ii < moduleList.size(); ii++ ) - { - Module = moduleList[ii]; - - if( Module->IsLocked() ) - continue; - - if( PlaceModulesHorsPcb && edgesExist ) - { - if( bbbox.Contains( Module->GetPosition() ) ) - continue; - } - - // Undo: add copy of old Module to undo - picker.SetItem( Module ); - picker.SetLink( Module->Clone() ); - - if( current.x > (Xsize_allowed + start.x) ) - { - current.x = start.x; - current.y += Ymax_size + pas_grille; - Ymax_size = 0; - } - - SetCrossHairPosition( current + Module->GetPosition() - - Module->GetBoundingBox().GetPosition() ); - - Ymax_size = std::max( Ymax_size, Module->GetBoundingBox().GetHeight() ); - - PlaceModule( Module, NULL, true ); - - // Undo: add new Module to undo - newList.PushItem( picker ); - - current.x += Module->GetBoundingBox().GetWidth() + pas_grille; - } - - // Undo: commit - if( newList.GetCount() ) - SaveCopyInUndoList( newList, UR_CHANGED ); - - m_canvas->Refresh(); -} - - /* Set or reset (true or false) Lock attribute of aModule or all modules if aModule == NULL */ void PCB_EDIT_FRAME::LockModule( MODULE* aModule, bool aLocked ) @@ -322,8 +198,3 @@ void PCB_EDIT_FRAME::LockModule( MODULE* aModule, bool aLocked ) } } - -static bool sortModulesbySize( MODULE* ref, MODULE* compare ) -{ - return compare->GetArea() < ref->GetArea(); -} diff --git a/pcbnew/autorouter/rect_placement/RectanglePlacement.txt b/pcbnew/autorouter/rect_placement/RectanglePlacement.txt new file mode 100644 index 0000000000..cecbf2efd9 --- /dev/null +++ b/pcbnew/autorouter/rect_placement/RectanglePlacement.txt @@ -0,0 +1,38 @@ +A class that fits subrectangles into a power-of-2 rectangle + +(C) Copyright 2000-2002 by Javier Arevalo +This code is free to use and modify for all purposes + +You have a bunch of rectangular pieces. You need to arrange them in a +rectangular surface so that they don't overlap, keeping the total area of the +rectangle as small as possible. This is fairly common when arranging characters +in a bitmapped font, lightmaps for a 3D engine, and I guess other situations as +well. + +The idea of this algorithm is that, as we add rectangles, we can pre-select +"interesting" places where we can try to add the next rectangles. For optimal +results, the rectangles should be added in order. I initially tried using area +as a sorting criteria, but it didn't work well with very tall or very flat +rectangles. I then tried using the longest dimension as a selector, and it +worked much better. So much for intuition... + +These "interesting" places are just to the right and just below the currently +added rectangle. The first rectangle, obviously, goes at the top left, the next +one would go either to the right or below this one, and so on. It is a weird way +to do it, but it seems to work very nicely. + +The way we search here is fairly brute-force, the fact being that for most off- +line purposes the performance seems more than adequate. I have generated a +japanese font with around 8500 characters and all the time was spent generating +the bitmaps. + +Also, for all we care, we could grow the parent rectangle in a different way +than power of two. It just happens that power of 2 is very convenient for +graphics hardware textures. + +I'd be interested in hearing of other approaches to this problem. Make sure +to post them on http://www.flipcode.com + +See also +http://www.flipcode.com/archives/Rectangle_Placement.shtml +http://kossovsky.net/index.php/2009/07/cshar-rectangle-packing diff --git a/pcbnew/autorouter/rect_placement/rect_placement.cpp b/pcbnew/autorouter/rect_placement/rect_placement.cpp new file mode 100644 index 0000000000..f562c2b9ae --- /dev/null +++ b/pcbnew/autorouter/rect_placement/rect_placement.cpp @@ -0,0 +1,259 @@ +// ---------------------------------------------------------------------------------------- +// Name : rect_placement.cpp +// Description : A class that fits subrectangles into a power-of-2 rectangle +// (C) Copyright 2000-2002 by Javier Arevalo +// This code is free to use and modify for all purposes +// ---------------------------------------------------------------------------------------- + +/* + * You have a bunch of rectangular pieces. You need to arrange them in a + * rectangular surface so that they don't overlap, keeping the total area of the + * rectangle as small as possible. This is fairly common when arranging characters + * in a bitmapped font, lightmaps for a 3D engine, and I guess other situations as + * well. + * + * The idea of this algorithm is that, as we add rectangles, we can pre-select + * "interesting" places where we can try to add the next rectangles. For optimal + * results, the rectangles should be added in order. I initially tried using area + * as a sorting criteria, but it didn't work well with very tall or very flat + * rectangles. I then tried using the longest dimension as a selector, and it + * worked much better. So much for intuition... + * + * These "interesting" places are just to the right and just below the currently + * added rectangle. The first rectangle, obviously, goes at the top left, the next + * one would go either to the right or below this one, and so on. It is a weird way + * to do it, but it seems to work very nicely. + * + * The way we search here is fairly brute-force, the fact being that for most off- + * line purposes the performance seems more than adequate. I have generated a + * japanese font with around 8500 characters and all the time was spent generating + * the bitmaps. + * + * Also, for all we care, we could grow the parent rectangle. + * + * I'd be interested in hearing of other approaches to this problem. Make sure + * to post them on http://www.flipcode.com + */ + +#include "rect_placement.h" + +// -------------------------------------------------------------------------------- +// Name : +// Description : +// -------------------------------------------------------------------------------- +void CRectPlacement::Init( int w, int h ) +{ + End(); + m_size = TRect( 0, 0, w, h ); + m_vPositions.push_back( TPos( 0, 0 ) ); + m_area = 0; +} + + +// -------------------------------------------------------------------------------- +// Name : +// Description : +// -------------------------------------------------------------------------------- +void CRectPlacement::End() +{ + m_vPositions.clear(); + m_vRects.clear(); + m_size.w = 0; +} + + +// -------------------------------------------------------------------------------- +// Name : IsFree +// Description : Check if the given rectangle is partially or totally used +// -------------------------------------------------------------------------------- +bool CRectPlacement::IsFree( const TRect& r ) const +{ + if( !m_size.Contains( r ) ) + return false; + + for( CRectArray::const_iterator it = m_vRects.begin(); + it != m_vRects.end(); ++it ) + { + if( it->Intersects( r ) ) + return false; + } + + return true; +} + + +// -------------------------------------------------------------------------------- +// Name : AddPosition +// Description : Add new anchor point +// -------------------------------------------------------------------------------- +void CRectPlacement::AddPosition( const TPos& p ) +{ + // Try to insert anchor as close as possible to the top left corner + // So it will be tried first + bool bFound = false; + CPosArray::iterator it; + + for( it = m_vPositions.begin(); + !bFound && it != m_vPositions.end(); + ++it ) + { + if( p.x + p.y < it->x + it->y ) + bFound = true; + } + + if( bFound ) + m_vPositions.insert( it, p ); + else + m_vPositions.push_back( p ); +} + + +// -------------------------------------------------------------------------------- +// Name : AddRect +// Description : Add the given rect and updates anchor points +// -------------------------------------------------------------------------------- +void CRectPlacement::AddRect( const TRect& r ) +{ + m_vRects.push_back( r ); + m_area += r.w * r.h; + + // Add two new anchor points + AddPosition( TPos( r.x, r.y + r.h ) ); + AddPosition( TPos( r.x + r.w, r.y ) ); +} + + +// -------------------------------------------------------------------------------- +// Name : AddAtEmptySpot +// Description : Add the given rectangle +// -------------------------------------------------------------------------------- +bool CRectPlacement::AddAtEmptySpot( TRect& r ) +{ + // Find a valid spot among available anchors. + bool bFound = false; + CPosArray::iterator it; + + for( it = m_vPositions.begin(); + !bFound && it != m_vPositions.end(); + ++it ) + { + TRect Rect( it->x, it->y, r.w, r.h ); + + if( IsFree( Rect ) ) + { + r = Rect; + bFound = true; + break; // Don't let the loop increase the iterator. + } + } + + if( bFound ) + { + int x, y; + + // Remove the used anchor point + m_vPositions.erase( it ); + + // Sometimes, anchors end up displaced from the optimal position + // due to irregular sizes of the subrects. + // So, try to adjut it up & left as much as possible. + for( x = 1; x <= r.x; x++ ) + { + if( !IsFree( TRect( r.x - x, r.y, r.w, r.h ) ) ) + break; + } + + for( y = 1; y <= r.y; y++ ) + { + if( !IsFree( TRect( r.x, r.y - y, r.w, r.h ) ) ) + break; + } + + if( y > x ) + r.y -= y - 1; + else + r.x -= x - 1; + + AddRect( r ); + } + + return bFound; +} + +#include +// -------------------------------------------------------------------------------- +// Name : AddAtEmptySpotAutoGrow +// Description : Add a rectangle of the given size, growing our area if needed +// Area grows only until the max given. +// Returns the placement of the rect in the rect's x,y coords +// -------------------------------------------------------------------------------- +bool CRectPlacement::AddAtEmptySpotAutoGrow( TRect* pRect, int maxW, int maxH ) +{ + double growing_factor = 1.2; // Must be > 1.0, and event > 1.1 for fast optimization + + #define GROW(x) ((x * growing_factor) + 1) + + if( pRect->w <= 0 ) + return true; + + int orgW = m_size.w; + int orgH = m_size.h; + + // Try to add it in the existing space + while( !AddAtEmptySpot( *pRect ) ) + { + int pw = m_size.w; + int ph = m_size.h; + + // Sanity check - if area is complete. + if( pw >= maxW && ph >= maxH ) + { + m_size.w = orgW; + m_size.h = orgH; + return false; + } + + // Try growing the smallest dim + if( pw < maxW && ( pw < ph || ( (pw == ph) && (pRect->w >= pRect->h) ) ) ) + m_size.w = GROW( pw ); + else + m_size.h = GROW( ph ); + + if( AddAtEmptySpot( *pRect ) ) + break; + + // Try growing the other dim instead + if( pw != m_size.w ) + { + m_size.w = pw; + + if( ph < maxW ) + m_size.h = GROW( ph ); + } + else + { + m_size.h = ph; + + if( pw < maxW ) + m_size.w = GROW( pw ); + } + + if( pw != m_size.w || ph != m_size.h ) + if( AddAtEmptySpot( *pRect ) ) + break; + + + + // Grow both if possible, and reloop. + m_size.w = pw; + m_size.h = ph; + + if( pw < maxW ) + m_size.w = GROW( pw ); + + if( ph < maxH ) + m_size.h = GROW( ph ); + } + + return true; +} diff --git a/pcbnew/autorouter/rect_placement/rect_placement.h b/pcbnew/autorouter/rect_placement/rect_placement.h new file mode 100644 index 0000000000..c9d9585f5d --- /dev/null +++ b/pcbnew/autorouter/rect_placement/rect_placement.h @@ -0,0 +1,104 @@ +// -------------------------------------------------------------------------------- +// Name : rect_placement.h +// Description : A class that allocates subrectangles into power-of-2 rectangles +// (C) Copyright 2000-2002 by Javier Arevalo +// This code is free to use and modify for all purposes +// -------------------------------------------------------------------------------- + +/** + * @file rect_placement.h + */ + +#ifndef _RECT_PLACEMENT_H_ +#define _RECT_PLACEMENT_H_ + +#include + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +class CRectPlacement +{ +public: + + // Helper classes + struct TPos + { + int x, y; + + TPos() { } + TPos( int _x, int _y ) : x( _x ), y( _y ) { } + + bool operator ==( const TPos& p ) const { return x == p.x && y == p.y; } + }; + + struct TRect : public TPos + { + int w, h; + + TRect() { } + TRect( int _x, int _y, int _w, int _h ) : TPos( _x, _y ), w( _w > 0 ? _w : 0 ), h( + _h > 0 ? _h : 0 ) { } + + bool Contains( const TPos& p ) const + { + return p.x >= x && p.y >= y && p.x < (x + w) && p.y < (y + h); + } + bool Contains( const TRect& r ) const + { + return r.x >= x && r.y >= y && + (r.x + r.w) <= (x + w) && (r.y + r.h) <= (y + h); + } + bool Intersects( const TRect& r ) const + { + return w > 0 && h > 0 && r.w > 0 && r.h > 0 + && ( (r.x + r.w) > x && r.x < (x + w) && (r.y + r.h) > y && r.y < (y + h) ); + } + + // static bool Greater(const TRect &a, const TRect &b) + // { return a.w*a.h > b.w*b.h; } + // Greater rect area. Not as good as the next heuristic: + // Greater size in at least one dim. + static bool Greater( const TRect& a, const TRect& b ) + { + return (a.w > b.w && a.w > b.h) || (a.h > b.w && a.h > b.h); + } + }; + + // --------------------- + + typedef std::vector CPosArray; + typedef std::vector CRectArray; + + // --------------------- + + CRectPlacement() { Init(); } + ~CRectPlacement() { End(); } + + void Init( int w = 1, int h = 1 ); + void End(); + + bool IsOk() const { return m_size.w > 0; } + + int GetW() const { return m_size.w; } + int GetH() const { return m_size.h; } + double GetArea() const { return m_area; } + double GetTotalArea() const { return (double)m_size.w * m_size.h; } + + bool AddAtEmptySpotAutoGrow( TRect* pRect, int maxW, int maxH ); + +private: + TRect m_size; + CRectArray m_vRects; + CPosArray m_vPositions; + double m_area; + + // --------------------- + + bool IsFree( const TRect& r ) const; + void AddPosition( const TPos& p ); + void AddRect( const TRect& r ); + bool AddAtEmptySpot( TRect& r ); +}; + +#endif // _RECT_PLACEMENT_H_ diff --git a/pcbnew/autorouter/solve.cpp b/pcbnew/autorouter/solve.cpp index c3c174d352..c06d8545eb 100644 --- a/pcbnew/autorouter/solve.cpp +++ b/pcbnew/autorouter/solve.cpp @@ -324,7 +324,6 @@ int PCB_EDIT_FRAME::Solve( wxDC* DC, int aLayersCount ) AppendMsgPanel( wxT( "Activity" ), msg, BROWN ); } - pt_cur_ch = pt_cur_ch; segm_oX = GetBoard()->GetBoundingBox().GetX() + (RoutingMatrix.m_GridRouting * col_source); segm_oY = GetBoard()->GetBoundingBox().GetY() + (RoutingMatrix.m_GridRouting * row_source); segm_fX = GetBoard()->GetBoundingBox().GetX() + (RoutingMatrix.m_GridRouting * col_target); diff --git a/pcbnew/autorouter/spread_footprints.cpp b/pcbnew/autorouter/spread_footprints.cpp new file mode 100644 index 0000000000..ee9ea8a6cb --- /dev/null +++ b/pcbnew/autorouter/spread_footprints.cpp @@ -0,0 +1,356 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2013 Wayne Stambaugh + * + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file spread_footprints.cpp + * @brief functions to spread footprints on free areas outside a board. + * this is usefull after reading a netlist, when new footprints are loaded + * and stacked at 0,0 coordinate. + * Often, spread them on a free area near the board being edited make more easy + * their selection. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct TSubRect : public CRectPlacement::TRect +{ + int n; // Original index of this subrect, before sorting + + TSubRect() { } + TSubRect( int _w, int _h, int _n ) : + TRect( 0, 0, _w, _h ), n( _n ) { } +}; + +typedef std::vector CSubRectArray; + +// Use 0.01 mm units to calculate placement, to avoid long calculation time +const int scale = (int)(0.01 * IU_PER_MM); + +// Populates a list of rectangles, from a list of modules +void fillRectList( CSubRectArray& vecSubRects, std::vector & aModuleList ) +{ + vecSubRects.clear(); + + for( unsigned ii = 0; ii < aModuleList.size(); ii++ ) + { + EDA_RECT fpBox = aModuleList[ii]->GetBoundingBox(); + TSubRect fpRect( fpBox.GetWidth()/scale, fpBox.GetHeight()/scale, ii ); + vecSubRects.push_back( fpRect ); + } +} + +// Populates a list of rectangles, from a list of EDA_RECT +void fillRectList( CSubRectArray& vecSubRects, std::vector & aRectList ) +{ + vecSubRects.clear(); + + for( unsigned ii = 0; ii < aRectList.size(); ii++ ) + { + EDA_RECT& rect = aRectList[ii]; + TSubRect fpRect( rect.GetWidth()/scale, rect.GetHeight()/scale, ii ); + vecSubRects.push_back( fpRect ); + } +} + + + +// Spread a list of rectangles inside a placement area +void spreadRectangles( CRectPlacement& aPlacementArea, + CSubRectArray& vecSubRects, + int areaSizeX, int areaSizeY ) +{ + areaSizeX/= scale; + areaSizeY/= scale; + + // Sort the subRects based on dimensions, larger dimension goes first. + std::sort( vecSubRects.begin(), vecSubRects.end(), CRectPlacement::TRect::Greater ); + + // gives the initial size to the area + aPlacementArea.Init( areaSizeX, areaSizeY ); + + // Add all subrects + CSubRectArray::iterator it; + for( it = vecSubRects.begin(); it != vecSubRects.end(); ) + { + CRectPlacement::TRect r( 0, 0, it->w, it->h ); + + bool bPlaced = aPlacementArea.AddAtEmptySpotAutoGrow( &r, areaSizeX, areaSizeY ); + + if( !bPlaced ) // No room to place the rectangle: enlarge area and retry + { + areaSizeX = ceil(areaSizeX * 1.1); + areaSizeY = ceil(areaSizeY * 1.1); + aPlacementArea.Init( areaSizeX, areaSizeY ); + it = vecSubRects.begin(); + continue; + } + + // When correctly placed in a placement area, the coords are returned in r.x and r.y + // Store them. + it->x = r.x; + it->y = r.y; + + it++; + } +} + + +void moveFootprintsInArea( CRectPlacement& aPlacementArea, + std::vector & aModuleList, EDA_RECT& aFreeArea, + bool aFindAreaOnly ) +{ + CSubRectArray vecSubRects; + + fillRectList( vecSubRects, aModuleList ); + spreadRectangles( aPlacementArea, vecSubRects, + aFreeArea.GetWidth(), aFreeArea.GetHeight() ); + + if( aFindAreaOnly ) + return; + + for( unsigned it = 0; it < vecSubRects.size(); ++it ) + { + wxPoint pos( vecSubRects[it].x, vecSubRects[it].y ); + pos.x *= scale; + pos.y *= scale; + + MODULE * module = aModuleList[vecSubRects[it].n]; + + EDA_RECT fpBBox = module->GetBoundingBox(); + wxPoint mod_pos = pos + ( module->GetPosition() - fpBBox.GetOrigin() ) + + aFreeArea.GetOrigin(); + + module->Move( mod_pos - module->GetPosition() ); + } +} + +static bool sortModulesbySheetPath( MODULE* ref, MODULE* compare ); + +/* Function to move components in a rectangular area format 4 / 3, + * starting from the mouse cursor + * The components with the FIXED status set are not moved + */ +void PCB_EDIT_FRAME::SpreadFootprints( bool aFootprintsOutsideBoardOnly ) +{ + EDA_RECT bbox = GetBoard()->ComputeBoundingBox( true ); + bool edgesExist = ( bbox.GetWidth() || bbox.GetHeight() ); + + // no edges exist + if( aFootprintsOutsideBoardOnly && !edgesExist ) + { + DisplayError( this, + _( "Could not automatically place modules. No board outlines detected." ) ); + return; + } + + // if aFootprintsOutsideBoardOnly is true, and if board outline exists, + // wue have to filter footprints to move: + bool outsideBrdFilter = aFootprintsOutsideBoardOnly && edgesExist; + + // Build candidate list + // calculate also the area needed by these footprints + MODULE* Module = GetBoard()->m_Modules; + std::vector moduleList; + + for( ; Module != NULL; Module = Module->Next() ) + { + Module->CalculateBoundingBox(); + + if( outsideBrdFilter ) + { + if( bbox.Contains( Module->GetPosition() ) ) + continue; + } + + if( Module->IsLocked() ) + continue; + + moduleList.push_back(Module); + } + + if( moduleList.size() == 0 ) // Nothing to do + return; + + // sort footprints by sheet path. we group them later by sheet + sort( moduleList.begin(), moduleList.end(), sortModulesbySheetPath ); + + // Undo command: init undo list + PICKED_ITEMS_LIST undoList; + undoList.m_Status = UR_CHANGED; + ITEM_PICKER picker( NULL, UR_CHANGED ); + + for( unsigned ii = 0; ii < moduleList.size(); ii++ ) + { + Module = moduleList[ii]; + + // Undo: add copy of module to undo list + picker.SetItem( Module ); + picker.SetLink( Module->Clone() ); + undoList.PushItem( picker ); + } + + // Extract and place footprints by sheet + std::vector moduleListBySheet; + std::vector placementSheetAreas; + wxString curr_sheetPath ; + double subsurface; + double placementsurface = 0.0; + + wxPoint placementAreaPosition = GetCrossHairPosition(); + + // We do not want to move footprints inside an existing board. + // move the placement area position outside the board bounding box + // to the left of the board + if( edgesExist ) + { + if( placementAreaPosition.x < bbox.GetEnd().x && + placementAreaPosition.y < bbox.GetEnd().y ) + { + placementAreaPosition.x = bbox.GetEnd().x; + placementAreaPosition.y = bbox.GetOrigin().y; + } + } + + // The placement uses 2 passes: + // the first pass creates the rectangular areas to place footprints + // each sheet in schematic creates one rectangular area. + // the second pass moves footprints inside these areas + for( int pass = 0; pass < 2; pass++ ) + { + int subareaIdx = 0; + curr_sheetPath = moduleList[0]->GetPath().BeforeLast( '/' ); + moduleListBySheet.clear(); + subsurface = 0.0; + + for( unsigned ii = 0; ii < moduleList.size(); ii++ ) + { + Module = moduleList[ii]; + bool iscurrPath = curr_sheetPath == moduleList[ii]->GetPath().BeforeLast( '/' ); + + if( iscurrPath ) + { + moduleListBySheet.push_back( Module ); + subsurface += Module->GetArea(); + } + + if( !iscurrPath || (ii == moduleList.size()-1) ) + { + // end of the footprint sublist relative to the same sheet path + // calculate placement of the current sublist + EDA_RECT freeArea; + int Xsize_allowed = (int) ( sqrt( subsurface ) * 4.0 / 3.0 ); + int Ysize_allowed = (int) ( subsurface / Xsize_allowed ); + + freeArea.SetWidth( Xsize_allowed ); + freeArea.SetHeight( Ysize_allowed ); + CRectPlacement placementArea; + + if( pass == 1 ) + { + wxPoint areapos = placementSheetAreas[subareaIdx].GetOrigin() + + placementAreaPosition; + freeArea.SetOrigin( areapos ); + } + + bool findAreaOnly = pass == 0; + moveFootprintsInArea( placementArea, moduleListBySheet, + freeArea, findAreaOnly ); + + if( pass == 0 ) + { + // Populate sheet placement areas list + EDA_RECT sub_area; + sub_area.SetWidth( placementArea.GetW()*scale ); + sub_area.SetHeight( placementArea.GetH()*scale ); + // Add a margin around the sheet placement area: + sub_area.Inflate( Millimeter2iu( 1.5 ) ); + + placementSheetAreas.push_back( sub_area ); + + placementsurface += (double) sub_area.GetWidth()* + sub_area.GetHeight(); + } + + curr_sheetPath = moduleList[ii]->GetPath().BeforeLast( '/' ); + subsurface = 0.0; + moduleListBySheet.clear(); + + // Enter first module of next sheet + moduleListBySheet.push_back( Module ); + subsurface += Module->GetArea(); + + subareaIdx++; + } + } + + // End of pass: + // At the end of the first pass, we have to find position of each sheet + // placement area + if( pass == 0 ) + { + int Xsize_allowed = (int) ( sqrt( placementsurface ) * 4.0 / 3.0 ); + int Ysize_allowed = (int) ( placementsurface / Xsize_allowed ); + CRectPlacement placementArea; + CSubRectArray vecSubRects; + + fillRectList( vecSubRects, placementSheetAreas ); + spreadRectangles( placementArea, vecSubRects, Xsize_allowed, Ysize_allowed ); + + for( unsigned it = 0; it < vecSubRects.size(); ++it ) + { + TSubRect& srect = vecSubRects[it]; + wxPoint pos( srect.x*scale, srect.y*scale ); + wxSize size( srect.w*scale, srect.h*scale ); + placementSheetAreas[srect.n].SetOrigin( pos ); + placementSheetAreas[srect.n].SetSize( size ); + } + } + } // End pass + + // Undo: commit list + SaveCopyInUndoList( undoList, UR_CHANGED ); + OnModify(); + + m_canvas->Refresh(); +} + + +static bool sortModulesbySheetPath( MODULE* ref, MODULE* compare ) +{ + return compare->GetPath().Cmp( ref->GetPath() ) < 0; +} diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 89c5a8866e..aeda80468a 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -608,10 +608,10 @@ void PCB_BASE_FRAME::UseGalCanvas( bool aEnable ) { EDA_DRAW_FRAME::UseGalCanvas( aEnable ); - m_toolManager->SetEnvironment( m_Pcb, m_galCanvas->GetView(), - m_galCanvas->GetViewControls(), this ); - ViewReloadBoard( m_Pcb ); + + m_toolManager->SetEnvironment( m_Pcb, m_galCanvas->GetView(), + m_galCanvas->GetViewControls(), this ); } diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index 58a39e8aa6..e58e734320 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -38,6 +38,7 @@ #include #include #include +#include /* Functions to undo and redo edit commands. @@ -173,122 +174,114 @@ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem ) } -void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage ) +void BOARD_ITEM::SwapData( BOARD_ITEM* aImage ) { - if( aItem == NULL || aImage == NULL ) + if( aImage == NULL ) { - wxMessageBox( wxT( "SwapData error: NULL pointer" ) ); return; } - // Swap layers: - if( aItem->Type() != PCB_MODULE_T && aItem->Type() != PCB_ZONE_AREA_T ) - { - // These items have a global swap function. - LAYER_NUM layer, layerimg; - layer = aItem->GetLayer(); - layerimg = aImage->GetLayer(); - aItem->SetLayer( layerimg ); - aImage->SetLayer( layer ); - } + EDA_ITEM * pnext = Next(); + EDA_ITEM * pback = Back(); - switch( aItem->Type() ) + switch( Type() ) { case PCB_MODULE_T: - { - MODULE* tmp = (MODULE*) aImage->Clone(); - ( (MODULE*) aImage )->Copy( (MODULE*) aItem ); - ( (MODULE*) aItem )->Copy( tmp ); - delete tmp; - } + { + MODULE* tmp = (MODULE*) aImage->Clone(); + ( (MODULE*) aImage )->Copy( (MODULE*) this ); + ( (MODULE*) this )->Copy( tmp ); + delete tmp; + } break; case PCB_ZONE_AREA_T: - { - ZONE_CONTAINER* tmp = (ZONE_CONTAINER*) aImage->Clone(); - ( (ZONE_CONTAINER*) aImage )->Copy( (ZONE_CONTAINER*) aItem ); - ( (ZONE_CONTAINER*) aItem )->Copy( tmp ); - delete tmp; - } + { + ZONE_CONTAINER* tmp = (ZONE_CONTAINER*) aImage->Clone(); + ( (ZONE_CONTAINER*) aImage )->Copy( (ZONE_CONTAINER*) this ); + ( (ZONE_CONTAINER*) this )->Copy( tmp ); + delete tmp; + } break; case PCB_LINE_T: -#if 0 - EXCHG( ( (DRAWSEGMENT*) aItem )->m_Start, ( (DRAWSEGMENT*) aImage )->m_Start ); - EXCHG( ( (DRAWSEGMENT*) aItem )->m_End, ( (DRAWSEGMENT*) aImage )->m_End ); - EXCHG( ( (DRAWSEGMENT*) aItem )->m_Width, ( (DRAWSEGMENT*) aImage )->m_Width ); - EXCHG( ( (DRAWSEGMENT*) aItem )->m_Shape, ( (DRAWSEGMENT*) aImage )->m_Shape ); -#else - { - DRAWSEGMENT tmp = *(DRAWSEGMENT*) aImage; - *aImage = *aItem; - *aItem = tmp; - } -#endif + std::swap( *((DRAWSEGMENT*)this), *((DRAWSEGMENT*)aImage) ); break; case PCB_TRACE_T: case PCB_VIA_T: - { - TRACK* track = (TRACK*) aItem; - TRACK* image = (TRACK*) aImage; + { + TRACK* track = (TRACK*) this; + TRACK* image = (TRACK*) aImage; - // swap start, end, width and shape for track and image. - wxPoint exchp = track->GetStart(); - track->SetStart( image->GetStart() ); - image->SetStart( exchp ); - exchp = track->GetEnd(); - track->SetEnd( image->GetEnd() ); - image->SetEnd( exchp ); + EXCHG(track->m_Layer, image->m_Layer ); - int atmp = track->GetWidth(); - track->SetWidth( image->GetWidth() ); - image->SetWidth( atmp ); - atmp = track->GetShape(); - track->SetShape( image->GetShape() ); - image->SetShape( atmp ); + // swap start, end, width and shape for track and image. + wxPoint exchp = track->GetStart(); + track->SetStart( image->GetStart() ); + image->SetStart( exchp ); + exchp = track->GetEnd(); + track->SetEnd( image->GetEnd() ); + image->SetEnd( exchp ); - atmp = track->GetDrillValue(); + int atmp = track->GetWidth(); + track->SetWidth( image->GetWidth() ); + image->SetWidth( atmp ); + atmp = track->GetShape(); + track->SetShape( image->GetShape() ); + image->SetShape( atmp ); - if( track->IsDrillDefault() ) - atmp = -1; + atmp = track->GetDrillValue(); - int itmp = image->GetDrillValue(); + if( track->IsDrillDefault() ) + atmp = -1; - if( image->IsDrillDefault() ) - itmp = -1; + int itmp = image->GetDrillValue(); - EXCHG(itmp, atmp ); + if( image->IsDrillDefault() ) + itmp = -1; - if( atmp > 0 ) - track->SetDrill( atmp ); - else - track->SetDrillDefault(); + EXCHG(itmp, atmp ); - if( itmp > 0 ) - image->SetDrill( itmp ); - else - image->SetDrillDefault(); - } + if( atmp > 0 ) + track->SetDrill( atmp ); + else + track->SetDrillDefault(); + + if( itmp > 0 ) + image->SetDrill( itmp ); + else + image->SetDrillDefault(); + } break; case PCB_TEXT_T: - std::swap( *((TEXTE_PCB*)aItem), *((TEXTE_PCB*)aImage) ); + std::swap( *((TEXTE_PCB*)this), *((TEXTE_PCB*)aImage) ); break; case PCB_TARGET_T: - ( (PCB_TARGET*) aItem )->Exchg( (PCB_TARGET*) aImage ); + std::swap( *((PCB_TARGET*)this), *((PCB_TARGET*)aImage) ); break; case PCB_DIMENSION_T: - std::swap( *((DIMENSION*)aItem), *((DIMENSION*)aImage) ); + std::swap( *((DIMENSION*)this), *((DIMENSION*)aImage) ); break; case PCB_ZONE_T: default: - wxMessageBox( wxT( "SwapData() error: unexpected type" ) ); + wxLogMessage( wxT( "SwapData() error: unexpected type %d" ), Type() ); break; } + + if( pnext != Next() || pback != Back() ) + { + Pnext = pnext; + Pback = pback; +#ifdef DEBUG + wxLogMessage( wxT( "SwapData Error: %s Pnext or Pback pointers modified" ), + GetClass().GetData() ); +#endif + } } @@ -491,7 +484,7 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed case UR_CHANGED: /* Exchange old and new data for each item */ { BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii ); - SwapData( item, image ); + item->SwapData( image ); } break; diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 53d0439565..ca97243fc2 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -2134,7 +2134,7 @@ MODULE* BOARD::GetFootprint( const wxPoint& aPosition, LAYER_NUM aActiveLayer, // Filter non visible modules if requested if( (!aVisibleOnly) || IsModuleLayerVisible( layer ) ) { - EDA_RECT bb = pt_module->GetFootPrintRect(); + EDA_RECT bb = pt_module->GetFootprintRect(); int offx = bb.GetX() + bb.GetWidth() / 2; int offy = bb.GetY() + bb.GetHeight() / 2; diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 0d05ebd54d..4cd30d1f6f 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -857,7 +857,7 @@ public: * as long as the BOARD has not changed. Remember, ComputeBoundingBox()'s * aBoardEdgesOnly argument is considered in this return value also. */ - EDA_RECT GetBoundingBox() const { return m_BoundingBox; } // override + const EDA_RECT GetBoundingBox() const { return m_BoundingBox; } // override void SetBoundingBox( const EDA_RECT& aBox ) { m_BoundingBox = aBox; } diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp index 9b72529f31..e49ca7e5dd 100644 --- a/pcbnew/class_dimension.cpp +++ b/pcbnew/class_dimension.cpp @@ -446,7 +446,7 @@ bool DIMENSION::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) } -EDA_RECT DIMENSION::GetBoundingBox() const +const EDA_RECT DIMENSION::GetBoundingBox() const { EDA_RECT bBox; int xmin, xmax, ymin, ymax; diff --git a/pcbnew/class_dimension.h b/pcbnew/class_dimension.h index e6248fb5fc..1ea29bd8dc 100644 --- a/pcbnew/class_dimension.h +++ b/pcbnew/class_dimension.h @@ -139,7 +139,8 @@ public: return wxT( "DIMENSION" ); } - EDA_RECT GetBoundingBox() const; + // Virtual function + const EDA_RECT GetBoundingBox() const; wxString GetSelectMenuText() const; diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 62126b2fca..d627e11700 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -44,7 +44,6 @@ #include #include -#include #include #include @@ -361,7 +360,7 @@ void DRAWSEGMENT::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) } -EDA_RECT DRAWSEGMENT::GetBoundingBox() const +const EDA_RECT DRAWSEGMENT::GetBoundingBox() const { EDA_RECT bbox; diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index f0c895ef35..66fc4c1d4e 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -168,7 +168,7 @@ public: virtual void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); - virtual EDA_RECT GetBoundingBox() const; + virtual const EDA_RECT GetBoundingBox() const; virtual bool HitTest( const wxPoint& aPosition ); diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp index 8c834d9290..7513096095 100644 --- a/pcbnew/class_edge_mod.cpp +++ b/pcbnew/class_edge_mod.cpp @@ -66,17 +66,27 @@ EDGE_MODULE::~EDGE_MODULE() } +const EDGE_MODULE& EDGE_MODULE::operator = ( const EDGE_MODULE& rhs ) +{ + if( &rhs == this ) + return *this; + + DRAWSEGMENT::operator=( rhs ); + + m_Start0 = rhs.m_Start0; + m_End0 = rhs.m_End0; + + m_PolyPoints = rhs.m_PolyPoints; // std::vector copy + return *this; +} + + void EDGE_MODULE::Copy( EDGE_MODULE* source ) { if( source == NULL ) return; - DRAWSEGMENT::Copy( source ); - - m_Start0 = source->m_Start0; - m_End0 = source->m_End0; - - m_PolyPoints = source->m_PolyPoints; // std::vector copy + *this = *source; } diff --git a/pcbnew/class_edge_mod.h b/pcbnew/class_edge_mod.h index 48fd300d26..8c6559ad74 100644 --- a/pcbnew/class_edge_mod.h +++ b/pcbnew/class_edge_mod.h @@ -32,6 +32,8 @@ #define CLASS_EDGE_MOD_H_ +#include + #include @@ -52,6 +54,9 @@ public: EDGE_MODULE* Next() const { return (EDGE_MODULE*) Pnext; } EDGE_MODULE* Back() const { return (EDGE_MODULE*) Pback; } + /// skip the linked list stuff, and parent + const EDGE_MODULE& operator = ( const EDGE_MODULE& rhs ); + void Copy( EDGE_MODULE* source ); // copy structure void SetStart0( const wxPoint& aPoint ) { m_Start0 = aPoint; } diff --git a/pcbnew/class_mire.cpp b/pcbnew/class_mire.cpp index f03413cd4b..d2fb096755 100644 --- a/pcbnew/class_mire.cpp +++ b/pcbnew/class_mire.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -71,16 +70,6 @@ PCB_TARGET::~PCB_TARGET() { } - -void PCB_TARGET::Exchg( PCB_TARGET* source ) -{ - EXCHG( m_Pos, source->m_Pos ); - EXCHG( m_Width, source->m_Width ); - EXCHG( m_Size, source->m_Size ); - EXCHG( m_Shape, source->m_Shape ); -} - - void PCB_TARGET::Copy( PCB_TARGET* source ) { m_Layer = source->m_Layer; @@ -205,7 +194,7 @@ void PCB_TARGET::Flip(const wxPoint& aCentre ) } -EDA_RECT PCB_TARGET::GetBoundingBox() const +const EDA_RECT PCB_TARGET::GetBoundingBox() const { EDA_RECT bBox; bBox.SetX( m_Pos.x - m_Size/2 ); diff --git a/pcbnew/class_mire.h b/pcbnew/class_mire.h index 8d6f240db5..da42a07fb0 100644 --- a/pcbnew/class_mire.h +++ b/pcbnew/class_mire.h @@ -71,12 +71,6 @@ public: void SetWidth( int aWidth ) { m_Width = aWidth; } int GetWidth() const { return m_Width; } - /** - * Function Exchg - * swaps data with another PCB_TARGET for use by undo-redo. - */ - void Exchg( PCB_TARGET* aTarget ); - void Move( const wxPoint& aMoveVector ) { m_Pos += aMoveVector; @@ -98,7 +92,8 @@ public: */ bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0 ) const; - EDA_RECT GetBoundingBox() const; + // Virtual function + const EDA_RECT GetBoundingBox() const; wxString GetSelectMenuText() const; diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 96a6ee1949..dd1aca96e5 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -409,12 +409,12 @@ void MODULE::DrawEdgesOnly( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offs void MODULE::CalculateBoundingBox() { - m_BoundaryBox = GetFootPrintRect(); + m_BoundaryBox = GetFootprintRect(); m_Surface = std::abs( (double) m_BoundaryBox.GetWidth() * m_BoundaryBox.GetHeight() ); } -EDA_RECT MODULE::GetFootPrintRect() const +EDA_RECT MODULE::GetFootprintRect() const { EDA_RECT area; @@ -433,9 +433,9 @@ EDA_RECT MODULE::GetFootPrintRect() const } -EDA_RECT MODULE::GetBoundingBox() const +const EDA_RECT MODULE::GetBoundingBox() const { - EDA_RECT area = GetFootPrintRect(); + EDA_RECT area = GetFootprintRect(); // Calculate extended area including text fields area.Merge( m_Reference->GetBoundingBox() ); diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index e7fd39ec23..184e9e7288 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -96,13 +96,14 @@ public: void CalculateBoundingBox(); /** - * Function GetFootPrintRect() + * Function GetFootprintRect() * Returns the area of the module footprint excluding any text. * @return EDA_RECT - The rectangle containing the footprint. */ - EDA_RECT GetFootPrintRect() const; + EDA_RECT GetFootprintRect() const; - EDA_RECT GetBoundingBox() const; + // Virtual function + const EDA_RECT GetBoundingBox() const; DLIST& Pads() { return m_Pads; } const DLIST& Pads() const { return m_Pads; } diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 1f223e2335..f984e4aa9b 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -120,7 +119,7 @@ int D_PAD::boundingRadius() const } -EDA_RECT D_PAD::GetBoundingBox() const +const EDA_RECT D_PAD::GetBoundingBox() const { EDA_RECT area; wxPoint quadrant1, quadrant2, quadrant3, quadrant4; diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 765b8d46fc..5a385ea917 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -392,7 +392,8 @@ public: return wxT( "PAD" ); } - EDA_RECT GetBoundingBox() const; + // Virtual function: + const EDA_RECT GetBoundingBox() const; /** * Function Compare diff --git a/pcbnew/class_pcb_text.cpp b/pcbnew/class_pcb_text.cpp index ee916e1ea4..c375713b82 100644 --- a/pcbnew/class_pcb_text.cpp +++ b/pcbnew/class_pcb_text.cpp @@ -158,7 +158,7 @@ void TEXTE_PCB::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) aList.push_back( MSG_PANEL_ITEM( _( "Size Y" ), msg, RED ) ); } -EDA_RECT TEXTE_PCB::GetBoundingBox() const +const EDA_RECT TEXTE_PCB::GetBoundingBox() const { EDA_RECT rect = GetTextBox( -1, -1 ); diff --git a/pcbnew/class_pcb_text.h b/pcbnew/class_pcb_text.h index 8a51aaae9b..cdc36fc6c9 100644 --- a/pcbnew/class_pcb_text.h +++ b/pcbnew/class_pcb_text.h @@ -130,7 +130,8 @@ public: BITMAP_DEF GetMenuImage() const { return add_text_xpm; } - EDA_RECT GetBoundingBox() const; + // Virtual function + const EDA_RECT GetBoundingBox() const; EDA_ITEM* Clone() const; diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index eda5544b03..fbebde39bd 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -182,12 +182,12 @@ bool TEXTE_MODULE::HitTest( const wxPoint& aPosition ) } -/** - * Function GetBoundingBox +/* + * Function GetBoundingBox (virtual) * returns the bounding box of this Text (according to text and footprint * orientation) */ -EDA_RECT TEXTE_MODULE::GetBoundingBox() const +const EDA_RECT TEXTE_MODULE::GetBoundingBox() const { double angle = GetDrawRotation(); EDA_RECT text_area = GetTextBox( -1, -1 ); diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h index 3b444c4b00..3452d4f316 100644 --- a/pcbnew/class_text_mod.h +++ b/pcbnew/class_text_mod.h @@ -123,7 +123,8 @@ public: */ double GetDrawRotation() const; - EDA_RECT GetBoundingBox() const; + // Virtual function + const EDA_RECT GetBoundingBox() const; void SetDrawCoord(); // Set absolute coordinates. diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index 889f1f9f61..5b48a8eb0a 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -310,7 +310,7 @@ STATUS_FLAGS TRACK::IsPointOnEnds( const wxPoint& point, int min_dist ) } -EDA_RECT TRACK::GetBoundingBox() const +const EDA_RECT TRACK::GetBoundingBox() const { // end of track is round, this is its radius, rounded up int radius = ( m_Width + 1 ) / 2; diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h index e358f7e243..594678bf40 100644 --- a/pcbnew/class_track.h +++ b/pcbnew/class_track.h @@ -127,7 +127,8 @@ public: int GetShape() const { return m_Shape; } void SetShape( int aShape ) { m_Shape = aShape; } - EDA_RECT GetBoundingBox() const; + // Virtual function + const EDA_RECT GetBoundingBox() const; /** * Function GetBestInsertPoint diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 94f19b8484..642023de9d 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -41,7 +41,6 @@ #include #include -#include #include #include @@ -359,7 +358,7 @@ void ZONE_CONTAINER::DrawFilledArea( EDA_DRAW_PANEL* panel, } -EDA_RECT ZONE_CONTAINER::GetBoundingBox() const +const EDA_RECT ZONE_CONTAINER::GetBoundingBox() const { const int PRELOAD = 0x7FFFFFFF; // Biggest integer (32 bits) diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 27816806b6..513859b9d8 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -151,10 +151,10 @@ public: void DrawWhileCreateOutline( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE draw_mode = GR_OR ); - /** Function GetBoundingBox + /** Function GetBoundingBox (virtual) * @return an EDA_RECT that is the bounding box of the zone outline */ - EDA_RECT GetBoundingBox() const; + const EDA_RECT GetBoundingBox() const; int GetClearance( BOARD_CONNECTED_ITEM* aItem = NULL ) const; diff --git a/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp b/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp index 364106624a..d2c81102fe 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include @@ -62,6 +64,7 @@ DIALOG_MODULE_MODULE_EDITOR::DIALOG_MODULE_MODULE_EDITOR( FOOTPRINT_EDIT_FRAME* icon.CopyFromBitmap( KiBitmap( icon_modedit_xpm ) ); SetIcon( icon ); + m_FootprintNameCtrl->SetValidator( FOOTPRINT_NAME_VALIDATOR() ); initModeditProperties(); m_sdbSizerStdButtonsOK->SetDefault(); GetSizer()->SetSizeHints( this ); @@ -100,15 +103,15 @@ void DIALOG_MODULE_MODULE_EDITOR::initModeditProperties() S3D_MASTER* draw3DCopy = new S3D_MASTER(NULL); draw3DCopy->Copy( draw3D ); m_shapes3D_list.push_back( draw3DCopy ); - m_3D_ShapeNameListBox->Append(draw3DCopy->m_Shape3DName); + m_3D_ShapeNameListBox->Append( draw3DCopy->m_Shape3DName ); } draw3D = (S3D_MASTER*) draw3D->Next(); } m_DocCtrl->SetValue( m_currentModule->GetDescription() ); m_KeywordCtrl->SetValue( m_currentModule->GetKeywords() ); - m_referenceCopy = new TEXTE_MODULE(NULL); - m_valueCopy = new TEXTE_MODULE(NULL); + m_referenceCopy = new TEXTE_MODULE( NULL ); + m_valueCopy = new TEXTE_MODULE( NULL ); m_referenceCopy->Copy( &m_currentModule->Reference() ); m_valueCopy->Copy( &m_currentModule->Value() ); m_ReferenceCtrl->SetValue( m_referenceCopy->GetText() ); @@ -147,7 +150,6 @@ void DIALOG_MODULE_MODULE_EDITOR::initModeditProperties() m_AutoPlaceCtrl->SetItemToolTip( 1, _( "Disable hotkey move commands and Auto Placement" ) ); m_CostRot90Ctrl->SetValue( m_currentModule->GetPlacementCost90() ); - m_CostRot180Ctrl->SetValue( m_currentModule->GetPlacementCost180() ); // Initialize 3D parameters @@ -168,7 +170,7 @@ void DIALOG_MODULE_MODULE_EDITOR::initModeditProperties() PutValueInLocalUnits( *m_SolderPasteMarginCtrl, m_currentModule->GetLocalSolderPasteMargin() ); if( m_currentModule->GetLocalSolderPasteMargin() == 0 ) - m_SolderPasteMarginCtrl->SetValue( wxT("-") + m_SolderPasteMarginCtrl->GetValue() ); + m_SolderPasteMarginCtrl->SetValue( wxT( "-" ) + m_SolderPasteMarginCtrl->GetValue() ); if( m_currentModule->GetLocalSolderPasteMarginRatio() == 0.0 ) msg.Printf( wxT( "-%f" ), m_currentModule->GetLocalSolderPasteMarginRatio() * 100.0 ); @@ -179,12 +181,11 @@ void DIALOG_MODULE_MODULE_EDITOR::initModeditProperties() // Add solder paste margin ration in per cent // for the usual default value 0.0, display -0.0 (or -0,0 in some countries) - msg.Printf( wxT( "%f" ), - m_currentModule->GetLocalSolderPasteMarginRatio() * 100.0 ); + msg.Printf( wxT( "%f" ), m_currentModule->GetLocalSolderPasteMarginRatio() * 100.0 ); if( m_currentModule->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0') // Sometimes Printf adds a sign if the value is very small (0.0) - m_SolderPasteMarginRatioCtrl->SetValue( wxT("-") + msg ); + m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg ); else m_SolderPasteMarginRatioCtrl->SetValue( msg ); @@ -208,9 +209,7 @@ void DIALOG_MODULE_MODULE_EDITOR::Transfert3DValuesToDisplay( S3D_MASTER * aStru if( aStruct3DSource ) { m_3D_Scale->SetValue( aStruct3DSource->m_MatScale ); - m_3D_Offset->SetValue( aStruct3DSource->m_MatPosition ); - m_3D_Rotation->SetValue( aStruct3DSource->m_MatRotation ); } else @@ -221,6 +220,7 @@ void DIALOG_MODULE_MODULE_EDITOR::Transfert3DValuesToDisplay( S3D_MASTER * aStru } } + /** Copy 3D info displayed in dialog box to values in a item in m_shapes3D_list * @param aIndexSelection = item index in m_shapes3D_list */ @@ -240,6 +240,7 @@ void DIALOG_MODULE_MODULE_EDITOR::On3DShapeNameSelected(wxCommandEvent& event) { if( m_lastSelected3DShapeIndex >= 0 ) TransfertDisplayTo3DValues( m_lastSelected3DShapeIndex ); + m_lastSelected3DShapeIndex = m_3D_ShapeNameListBox->GetSelection(); if( m_lastSelected3DShapeIndex < 0 ) // happens under wxGTK when deleting an item in m_3D_ShapeNameListBox wxListBox @@ -247,10 +248,11 @@ void DIALOG_MODULE_MODULE_EDITOR::On3DShapeNameSelected(wxCommandEvent& event) if( m_lastSelected3DShapeIndex >= (int)m_shapes3D_list.size() ) { - wxMessageBox(wxT("On3DShapeNameSelected() error")); + wxMessageBox( wxT( "On3DShapeNameSelected() error" ) ); m_lastSelected3DShapeIndex = -1; return; } + Transfert3DValuesToDisplay( m_shapes3D_list[m_lastSelected3DShapeIndex] ); } @@ -261,18 +263,19 @@ void DIALOG_MODULE_MODULE_EDITOR::Remove3DShape(wxCommandEvent& event) TransfertDisplayTo3DValues( m_lastSelected3DShapeIndex ); int ii = m_3D_ShapeNameListBox->GetSelection(); + if( ii < 0 ) return; - m_shapes3D_list.erase(m_shapes3D_list.begin() + ii ); - m_3D_ShapeNameListBox->Delete(ii); + m_shapes3D_list.erase( m_shapes3D_list.begin() + ii ); + m_3D_ShapeNameListBox->Delete( ii ); if( m_3D_ShapeNameListBox->GetCount() == 0) Transfert3DValuesToDisplay( NULL ); else { m_lastSelected3DShapeIndex = 0; - m_3D_ShapeNameListBox->SetSelection(m_lastSelected3DShapeIndex); + m_3D_ShapeNameListBox->SetSelection( m_lastSelected3DShapeIndex ); Transfert3DValuesToDisplay( m_shapes3D_list[m_lastSelected3DShapeIndex] ); } } @@ -284,6 +287,7 @@ void DIALOG_MODULE_MODULE_EDITOR::BrowseAndAdd3DLib( wxCommandEvent& event ) wxString fullpath; fullpath = wxGetApp().ReturnLastVisitedLibraryPath( LIB3D_PATH ); + #ifdef __WINDOWS__ fullpath.Replace( wxT( "/" ), wxT( "\\" ) ); #endif @@ -313,6 +317,7 @@ void DIALOG_MODULE_MODULE_EDITOR::BrowseAndAdd3DLib( wxCommandEvent& event ) shortfilename = wxGetApp().ReturnFilenameWithRelativePathInLibPath( fullfilename ); wxFileName aux = shortfilename; + if( aux.IsAbsolute() ) { // Absolute path, ask if the user wants a relative one int diag = wxMessageBox( @@ -322,12 +327,13 @@ void DIALOG_MODULE_MODULE_EDITOR::BrowseAndAdd3DLib( wxCommandEvent& event ) if( diag == wxYES ) { // Make it relative - aux.MakeRelativeTo( wxT(".") ); + aux.MakeRelativeTo( wxT( "." ) ); shortfilename = aux.GetPathWithSep() + aux.GetFullName(); } } S3D_MASTER* new3DShape = new S3D_MASTER(NULL); + #ifdef __WINDOWS__ // Store filename in Unix notation shortfilename.Replace( wxT( "\\" ), wxT( "/" ) ); @@ -341,7 +347,7 @@ void DIALOG_MODULE_MODULE_EDITOR::BrowseAndAdd3DLib( wxCommandEvent& event ) TransfertDisplayTo3DValues( m_lastSelected3DShapeIndex ); m_lastSelected3DShapeIndex = m_3D_ShapeNameListBox->GetCount() - 1; - m_3D_ShapeNameListBox->SetSelection(m_lastSelected3DShapeIndex); + m_3D_ShapeNameListBox->SetSelection( m_lastSelected3DShapeIndex ); Transfert3DValuesToDisplay( m_shapes3D_list[m_lastSelected3DShapeIndex] ); } @@ -357,12 +363,13 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event ) { // First, test for invalid chars in module name wxString footprintName = m_FootprintNameCtrl->GetValue(); + if( ! footprintName.IsEmpty() ) { if( ! MODULE::IsLibNameValid( footprintName ) ) { wxString msg; - msg.Printf( _("Error:\none of invalid chars <%s> found\nin <%s>" ), + msg.Printf( _( "Error:\none of invalid chars <%s> found\nin <%s>" ), MODULE::ReturnStringLibNameInvalidChars( true ), GetChars( footprintName ) ); @@ -404,9 +411,7 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event ) // Initialize masks clearances m_currentModule->SetLocalClearance( ReturnValueFromTextCtrl( *m_NetClearanceValueCtrl ) ); - m_currentModule->SetLocalSolderMaskMargin( ReturnValueFromTextCtrl( *m_SolderMaskMarginCtrl ) ); - m_currentModule->SetLocalSolderPasteMargin( ReturnValueFromTextCtrl( *m_SolderPasteMarginCtrl ) ); double dtmp; wxString msg = m_SolderPasteMarginRatioCtrl->GetValue(); @@ -415,6 +420,7 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event ) // A -50% margin ratio means no paste on a pad, the ratio must be >= -50 % if( dtmp < -50.0 ) dtmp = -50.0; + // A margin ratio is always <= 0 if( dtmp > 0.0 ) dtmp = 0.0; @@ -423,14 +429,19 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event ) // Update 3D shape list int ii = m_3D_ShapeNameListBox->GetSelection(); + if ( ii >= 0 ) - TransfertDisplayTo3DValues( ii ); + TransfertDisplayTo3DValues( ii ); + S3D_MASTER* draw3D = m_currentModule->Models(); + for( unsigned ii = 0; ii < m_shapes3D_list.size(); ii++ ) { S3D_MASTER* draw3DCopy = m_shapes3D_list[ii]; + if( draw3DCopy->m_Shape3DName.IsEmpty() ) continue; + if( draw3D == NULL ) { draw3D = new S3D_MASTER( draw3D ); @@ -447,6 +458,7 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event ) // Remove old extra 3D shapes S3D_MASTER* nextdraw3D; + for( ; draw3D != NULL; draw3D = nextdraw3D ) { nextdraw3D = (S3D_MASTER*) draw3D->Next(); @@ -484,4 +496,3 @@ void DIALOG_MODULE_MODULE_EDITOR::OnEditValue(wxCommandEvent& event) m_parent->SetCrossHairPosition( tmp ); m_ValueCtrl->SetValue( m_valueCopy->GetText() ); } - diff --git a/pcbnew/dialogs/dialog_exchange_modules_base.cpp b/pcbnew/dialogs/dialog_exchange_modules_base.cpp index 45613575c3..e80b4c16af 100644 --- a/pcbnew/dialogs/dialog_exchange_modules_base.cpp +++ b/pcbnew/dialogs/dialog_exchange_modules_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) +// C++ code generated with wxFormBuilder (version Nov 6 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -22,7 +22,7 @@ DIALOG_EXCHANGE_MODULE_BASE::DIALOG_EXCHANGE_MODULE_BASE( wxWindow* parent, wxWi wxBoxSizer* bLeftSizer; bLeftSizer = new wxBoxSizer( wxVERTICAL ); - m_staticText6 = new wxStaticText( this, wxID_ANY, _("Current Module"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText6 = new wxStaticText( this, wxID_ANY, _("Current footprint"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText6->Wrap( -1 ); bLeftSizer->Add( m_staticText6, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); @@ -30,7 +30,7 @@ DIALOG_EXCHANGE_MODULE_BASE::DIALOG_EXCHANGE_MODULE_BASE( wxWindow* parent, wxWi m_OldModule->SetMaxLength( 0 ); bLeftSizer->Add( m_OldModule, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - m_staticText7 = new wxStaticText( this, wxID_ANY, _("Current Value"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText7 = new wxStaticText( this, wxID_ANY, _("Current value"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText7->Wrap( -1 ); bLeftSizer->Add( m_staticText7, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); @@ -38,7 +38,7 @@ DIALOG_EXCHANGE_MODULE_BASE::DIALOG_EXCHANGE_MODULE_BASE( wxWindow* parent, wxWi m_OldValue->SetMaxLength( 0 ); bLeftSizer->Add( m_OldValue, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - m_staticText8 = new wxStaticText( this, wxID_ANY, _("New Module"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText8 = new wxStaticText( this, wxID_ANY, _("New footprint"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText8->Wrap( -1 ); bLeftSizer->Add( m_staticText8, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); @@ -54,8 +54,8 @@ DIALOG_EXCHANGE_MODULE_BASE::DIALOG_EXCHANGE_MODULE_BASE( wxWindow* parent, wxWi wxString m_SelectionChoices[] = { _("Change module"), _("Change same modules"), _("Ch. same module+value"), _("Change all") }; int m_SelectionNChoices = sizeof( m_SelectionChoices ) / sizeof( wxString ); - m_Selection = new wxRadioBox( this, ID_SELECTION_CLICKED, _("Browse Libs modules"), wxDefaultPosition, wxDefaultSize, m_SelectionNChoices, m_SelectionChoices, 1, wxRA_SPECIFY_COLS ); - m_Selection->SetSelection( 0 ); + m_Selection = new wxRadioBox( this, ID_SELECTION_CLICKED, _("Options"), wxDefaultPosition, wxDefaultSize, m_SelectionNChoices, m_SelectionChoices, 1, wxRA_SPECIFY_COLS ); + m_Selection->SetSelection( 2 ); bMiddleSizer->Add( m_Selection, 0, wxALL, 5 ); @@ -65,13 +65,16 @@ DIALOG_EXCHANGE_MODULE_BASE::DIALOG_EXCHANGE_MODULE_BASE( wxWindow* parent, wxWi bRightSizer = new wxBoxSizer( wxVERTICAL ); m_OKbutton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - bRightSizer->Add( m_OKbutton, 0, wxALL, 5 ); + bRightSizer->Add( m_OKbutton, 0, wxALL|wxEXPAND, 5 ); m_Quitbutton = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); - bRightSizer->Add( m_Quitbutton, 0, wxALL, 5 ); + bRightSizer->Add( m_Quitbutton, 0, wxALL|wxEXPAND, 5 ); + + m_buttonCmpList = new wxButton( this, wxID_ANY, _("Rebuild .cmp List"), wxDefaultPosition, wxDefaultSize, 0 ); + bRightSizer->Add( m_buttonCmpList, 0, wxALL|wxEXPAND, 5 ); m_Browsebutton = new wxButton( this, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - bRightSizer->Add( m_Browsebutton, 0, wxALL, 5 ); + bRightSizer->Add( m_Browsebutton, 0, wxALL|wxEXPAND, 5 ); bUpperSizer->Add( bRightSizer, 0, wxALIGN_CENTER_VERTICAL, 5 ); @@ -98,6 +101,7 @@ DIALOG_EXCHANGE_MODULE_BASE::DIALOG_EXCHANGE_MODULE_BASE( wxWindow* parent, wxWi m_Selection->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::OnSelectionClicked ), NULL, this ); m_OKbutton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::OnOkClick ), NULL, this ); m_Quitbutton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::OnQuit ), NULL, this ); + m_buttonCmpList->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::RebuildCmpList ), NULL, this ); m_Browsebutton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::BrowseAndSelectFootprint ), NULL, this ); } @@ -107,6 +111,7 @@ DIALOG_EXCHANGE_MODULE_BASE::~DIALOG_EXCHANGE_MODULE_BASE() m_Selection->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::OnSelectionClicked ), NULL, this ); m_OKbutton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::OnOkClick ), NULL, this ); m_Quitbutton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::OnQuit ), NULL, this ); + m_buttonCmpList->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::RebuildCmpList ), NULL, this ); m_Browsebutton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_MODULE_BASE::BrowseAndSelectFootprint ), NULL, this ); } diff --git a/pcbnew/dialogs/dialog_exchange_modules_base.fbp b/pcbnew/dialogs/dialog_exchange_modules_base.fbp index 51fbc246eb..4e71f2ee55 100644 --- a/pcbnew/dialogs/dialog_exchange_modules_base.fbp +++ b/pcbnew/dialogs/dialog_exchange_modules_base.fbp @@ -20,8 +20,10 @@ . 1 + 1 1 1 + UI 0 0 @@ -141,7 +143,7 @@ 0 0 wxID_ANY - Current Module + Current footprint 0 @@ -315,7 +317,7 @@ 0 0 wxID_ANY - Current Value + Current value 0 @@ -489,7 +491,7 @@ 0 0 wxID_ANY - New Module + New footprint 0 @@ -675,7 +677,7 @@ 0 0 ID_SELECTION_CLICKED - Browse Libs modules + Options 1 0 @@ -692,7 +694,7 @@ 1 Resizable - 0 + 2 1 wxRA_SPECIFY_COLS @@ -745,7 +747,7 @@ none 5 - wxALL + wxALL|wxEXPAND 0 1 @@ -833,7 +835,7 @@ 5 - wxALL + wxALL|wxEXPAND 0 1 @@ -921,7 +923,95 @@ 5 - wxALL + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Rebuild .cmp List + + 0 + + + 0 + + 1 + m_buttonCmpList + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + RebuildCmpList + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND 0 1 diff --git a/pcbnew/dialogs/dialog_exchange_modules_base.h b/pcbnew/dialogs/dialog_exchange_modules_base.h index a34722fc82..089f374574 100644 --- a/pcbnew/dialogs/dialog_exchange_modules_base.h +++ b/pcbnew/dialogs/dialog_exchange_modules_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) +// C++ code generated with wxFormBuilder (version Nov 6 2013) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -47,6 +47,7 @@ class DIALOG_EXCHANGE_MODULE_BASE : public DIALOG_SHIM wxRadioBox* m_Selection; wxButton* m_OKbutton; wxButton* m_Quitbutton; + wxButton* m_buttonCmpList; wxButton* m_Browsebutton; wxStaticText* m_staticTextMsg; wxTextCtrl* m_WinMessages; @@ -55,6 +56,7 @@ class DIALOG_EXCHANGE_MODULE_BASE : public DIALOG_SHIM virtual void OnSelectionClicked( wxCommandEvent& event ) { event.Skip(); } virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnQuit( wxCommandEvent& event ) { event.Skip(); } + virtual void RebuildCmpList( wxCommandEvent& event ) { event.Skip(); } virtual void BrowseAndSelectFootprint( wxCommandEvent& event ) { event.Skip(); } diff --git a/pcbnew/dialogs/dialog_fp_lib_table.cpp b/pcbnew/dialogs/dialog_fp_lib_table.cpp index c9b1ac48cb..8c287a35bb 100644 --- a/pcbnew/dialogs/dialog_fp_lib_table.cpp +++ b/pcbnew/dialogs/dialog_fp_lib_table.cpp @@ -40,7 +40,7 @@ #include #include #include - +#include /// grid column order is established by this sequence enum COL_ORDER @@ -244,7 +244,7 @@ protected: } catch( PARSE_ERROR& pe ) { - // @todo tell what line and offset + DisplayError( NULL, pe.errorText ); parsed = false; } @@ -330,11 +330,12 @@ public: wxGrid* g = i==0 ? m_global_grid : m_project_grid; // all but COL_OPTIONS, which is edited with Option Editor anyways. - g->AutoSizeColumn( COL_NICKNAME, true ); + g->AutoSizeColumn( COL_NICKNAME, false ); g->AutoSizeColumn( COL_TYPE, false ); g->AutoSizeColumn( COL_URI, false ); g->AutoSizeColumn( COL_DESCR, false ); + // would set this to width of title, if it was easily known. g->SetColSize( COL_OPTIONS, 80 ); } @@ -692,6 +693,12 @@ private: } } + // Make sure this special environment variable shows up even if it was + // not used yet. It is automatically set by KiCad to the directory holding + // the current project. + unique.insert( FP_LIB_TABLE::ProjectPathEnvVariableName() ); + unique.insert( FP_LIB_TABLE::GlobalPathEnvVariableName() ); + m_path_subs_grid->AppendRows( unique.size() ); row = 0; diff --git a/pcbnew/dialogs/dialog_fp_plugin_options.cpp b/pcbnew/dialogs/dialog_fp_plugin_options.cpp index 641882082d..edbfedb6ec 100644 --- a/pcbnew/dialogs/dialog_fp_plugin_options.cpp +++ b/pcbnew/dialogs/dialog_fp_plugin_options.cpp @@ -257,14 +257,15 @@ private: void onListBoxItemSelected( wxCommandEvent& event ) { + // change the help text based on the m_listbox selection: if( event.IsSelection() ) { - const char* option = TO_UTF8( event.GetString() ); - string help_text; + string option = TO_UTF8( event.GetString() ); + string help_text; - if( m_choices.Value( option, &help_text ) ) + if( m_choices.Value( option.c_str(), &help_text ) ) { - wxString page( FROM_UTF8( help_text.c_str() ) ); + wxString page = FROM_UTF8( help_text.c_str() ); m_html->SetPage( page ); } diff --git a/pcbnew/dialogs/dialog_fp_plugin_options_base.cpp b/pcbnew/dialogs/dialog_fp_plugin_options_base.cpp index 3ab37111d0..324d98a634 100644 --- a/pcbnew/dialogs/dialog_fp_plugin_options_base.cpp +++ b/pcbnew/dialogs/dialog_fp_plugin_options_base.cpp @@ -93,7 +93,7 @@ DIALOG_FP_PLUGIN_OPTIONS_BASE::DIALOG_FP_PLUGIN_OPTIONS_BASE( wxWindow* parent, m_listbox = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_ALWAYS_SB|wxLB_SINGLE ); m_listbox->SetToolTip( _("Options supported by current plugin") ); - m_options_sizer->Add( m_listbox, 0, wxALL|wxEXPAND, 5 ); + m_options_sizer->Add( m_listbox, 2, wxALL|wxEXPAND, 5 ); m_append_choice_button = new wxButton( this, wxID_ANY, _("<< Append Selected Option"), wxDefaultPosition, wxDefaultSize, 0 ); m_options_sizer->Add( m_append_choice_button, 0, wxALIGN_CENTER|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); @@ -105,7 +105,7 @@ DIALOG_FP_PLUGIN_OPTIONS_BASE::DIALOG_FP_PLUGIN_OPTIONS_BASE( wxWindow* parent, m_html = new wxHtmlWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO|wxVSCROLL ); m_html->SetMinSize( wxSize( 300,300 ) ); - m_options_sizer->Add( m_html, 1, wxALL|wxEXPAND, 5 ); + m_options_sizer->Add( m_html, 3, wxALL|wxEXPAND, 5 ); m_horizontal_sizer->Add( m_options_sizer, 2, wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/dialog_fp_plugin_options_base.fbp b/pcbnew/dialogs/dialog_fp_plugin_options_base.fbp index 4ba5939dc2..c0e3ceb544 100644 --- a/pcbnew/dialogs/dialog_fp_plugin_options_base.fbp +++ b/pcbnew/dialogs/dialog_fp_plugin_options_base.fbp @@ -651,7 +651,7 @@ 5 wxALL|wxEXPAND - 0 + 2 1 1 @@ -910,7 +910,7 @@ 5 wxALL|wxEXPAND - 1 + 3 1 1 diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp index 561c29fa2a..ddff38dbd8 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp @@ -1,6 +1,30 @@ -/**************************************/ -/* dialog_graphic_item_properties.cpp */ -/**************************************/ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010 Jean-Pierre Charras + * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file dialog_graphic_item_properties.cpp + */ /* Edit parameters values of graphic items type DRAWSEGMENTS: * Lines @@ -26,6 +50,7 @@ #include #include + class DIALOG_GRAPHIC_ITEM_PROPERTIES: public DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE { private: @@ -41,12 +66,12 @@ public: private: void initDlg( ); void OnOkClick( wxCommandEvent& event ); - void OnCancelClick( wxCommandEvent& event ); + void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } void OnLayerChoice( wxCommandEvent& event ); }; DIALOG_GRAPHIC_ITEM_PROPERTIES::DIALOG_GRAPHIC_ITEM_PROPERTIES( PCB_EDIT_FRAME* aParent, - DRAWSEGMENT * aItem, wxDC * aDC): + DRAWSEGMENT * aItem, wxDC * aDC ): DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( aParent ) { m_parent = aParent; @@ -60,32 +85,24 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES::DIALOG_GRAPHIC_ITEM_PROPERTIES( PCB_EDIT_FRAME* } -/*******************************************************************************************/ -void PCB_EDIT_FRAME::InstallGraphicItemPropertiesDialog(DRAWSEGMENT * aItem, wxDC* aDC) -/*******************************************************************************************/ +void PCB_EDIT_FRAME::InstallGraphicItemPropertiesDialog( DRAWSEGMENT* aItem, wxDC* aDC ) { if ( aItem == NULL ) { - DisplayError(this, wxT("InstallGraphicItemPropertiesDialog() error: NULL item")); + DisplayError( this, wxT( "InstallGraphicItemPropertiesDialog() error: NULL item" ) ); return; } m_canvas->SetIgnoreMouseEvents( true ); - DIALOG_GRAPHIC_ITEM_PROPERTIES* dialog = new DIALOG_GRAPHIC_ITEM_PROPERTIES( this, aItem, aDC ); - dialog->ShowModal(); - dialog->Destroy(); + DIALOG_GRAPHIC_ITEM_PROPERTIES dlg( this, aItem, aDC ); + dlg.ShowModal(); m_canvas->MoveCursorToCrossHair(); m_canvas->SetIgnoreMouseEvents( false ); } -/**************************************************************************/ + void DIALOG_GRAPHIC_ITEM_PROPERTIES::initDlg( ) -/**************************************************************************/ -/* Initialize messages and values in text control, - * according to the item parameters values -*/ { - SetFocus(); m_StandardButtonsSizerOK->SetDefault(); // Set unit symbol @@ -104,6 +121,7 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::initDlg( ) { if( texts_unit[ii] == NULL ) break; + texts_unit[ii]->SetLabel( GetAbbreviatedUnitsLabel() ); } @@ -113,31 +131,30 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::initDlg( ) switch ( m_Item->GetShape() ) { case S_CIRCLE: - m_StartPointXLabel->SetLabel(_("Center X")); - m_StartPointYLabel->SetLabel(_("Center Y")); - m_EndPointXLabel->SetLabel(_("Point X")); - m_EndPointYLabel->SetLabel(_("Point Y")); - m_Angle_Text->Show(false); - m_Angle_Ctrl->Show(false); - m_AngleUnit->Show(false); + m_StartPointXLabel->SetLabel( _( "Center X" ) ); + m_StartPointYLabel->SetLabel( _( "Center Y" ) ); + m_EndPointXLabel->SetLabel( _( "Point X" ) ); + m_EndPointYLabel->SetLabel( _( "Point Y" ) ); + m_Angle_Text->Show( false ); + m_Angle_Ctrl->Show( false ); + m_AngleUnit->Show( false ); break; case S_ARC: - m_StartPointXLabel->SetLabel(_("Center X")); - m_StartPointYLabel->SetLabel(_("Center Y")); - m_EndPointXLabel->SetLabel(_("Start Point X")); - m_EndPointYLabel->SetLabel(_("Start Point Y")); + m_StartPointXLabel->SetLabel( _( "Center X" ) ); + m_StartPointYLabel->SetLabel( _( "Center Y" ) ); + m_EndPointXLabel->SetLabel( _( "Start Point X" ) ); + m_EndPointYLabel->SetLabel( _( "Start Point Y" ) ); - // Here the angle is a double, but the UI is still working - // with integers + // Here the angle is a double, but the UI is still working with integers. msg << int( m_Item->GetAngle() ); - m_Angle_Ctrl->SetValue(msg); + m_Angle_Ctrl->SetValue( msg ); break; default: - m_Angle_Text->Show(false); - m_Angle_Ctrl->Show(false); - m_AngleUnit->Show(false); + m_Angle_Text->Show( false ); + m_Angle_Ctrl->Show( false ); + m_AngleUnit->Show( false ); break; } @@ -168,16 +185,14 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::initDlg( ) if( m_LayerSelectionCtrl->SetLayerSelection( m_Item->GetLayer() ) < 0 ) { - wxMessageBox( _("This item has an illegal layer id.\n" - "Now, forced on the drawings layer. Please, fix it") ); + wxMessageBox( _( "This item has an illegal layer id.\n" + "Now, forced on the drawings layer. Please, fix it" ) ); m_LayerSelectionCtrl->SetLayerSelection( DRAW_N ); } } -/*******************************************************************/ void DIALOG_GRAPHIC_ITEM_PROPERTIES::OnLayerChoice( wxCommandEvent& event ) -/*******************************************************************/ { int thickness; @@ -189,11 +204,8 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::OnLayerChoice( wxCommandEvent& event ) PutValueInLocalUnits( *m_DefaultThicknessCtrl, thickness ); } -/*******************************************************************/ + void DIALOG_GRAPHIC_ITEM_PROPERTIES::OnOkClick( wxCommandEvent& event ) -/*******************************************************************/ -/* Copy values in text control to the item parameters -*/ { m_parent->SaveCopyInUndoList( m_Item, UR_CHANGED ); @@ -246,9 +258,3 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::OnOkClick( wxCommandEvent& event ) Close( true ); } - -void DIALOG_GRAPHIC_ITEM_PROPERTIES::OnCancelClick( wxCommandEvent& event ) -{ - event.Skip(); -} - diff --git a/pcbnew/dialogs/dialog_netlist.cpp b/pcbnew/dialogs/dialog_netlist.cpp index 6315e63a00..50ad5f0063 100644 --- a/pcbnew/dialogs/dialog_netlist.cpp +++ b/pcbnew/dialogs/dialog_netlist.cpp @@ -167,7 +167,7 @@ void DIALOG_NETLIST::OnReadNetlistFileClick( wxCommandEvent& event ) "sure you want to read the netlist?" ) ) ) return; - wxBusyCursor busy(); + wxBusyCursor busy; m_MessageWindow->Clear(); msg.Printf( _( "Reading netlist file \"%s\".\n" ), GetChars( netlistFileName ) ); diff --git a/pcbnew/dialogs/dialog_target_properties_base.cpp b/pcbnew/dialogs/dialog_target_properties_base.cpp index 4027e64c0c..c71a48fcc9 100644 --- a/pcbnew/dialogs/dialog_target_properties_base.cpp +++ b/pcbnew/dialogs/dialog_target_properties_base.cpp @@ -27,38 +27,38 @@ TARGET_PROPERTIES_DIALOG_EDITOR_BASE::TARGET_PROPERTIES_DIALOG_EDITOR_BASE( wxWi m_staticTextSize = new wxStaticText( this, wxID_ANY, wxT("Size"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextSize->Wrap( -1 ); - fgSizer->Add( m_staticTextSize, 0, wxALL, 5 ); + fgSizer->Add( m_staticTextSize, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - m_MireWidthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer->Add( m_MireWidthCtrl, 0, wxALL|wxEXPAND, 5 ); + m_TargetSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer->Add( m_TargetSizeCtrl, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); m_staticTextSizeUnits = new wxStaticText( this, wxID_ANY, wxT("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextSizeUnits->Wrap( -1 ); - fgSizer->Add( m_staticTextSizeUnits, 0, wxALL, 5 ); + fgSizer->Add( m_staticTextSizeUnits, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); m_staticTextThickness = new wxStaticText( this, wxID_ANY, wxT("Thickness"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextThickness->Wrap( -1 ); - fgSizer->Add( m_staticTextThickness, 0, wxALL, 5 ); + fgSizer->Add( m_staticTextThickness, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - m_MireSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer->Add( m_MireSizeCtrl, 0, wxALL|wxEXPAND, 5 ); + m_TargetThicknessCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer->Add( m_TargetThicknessCtrl, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); m_staticTextThicknessUnits = new wxStaticText( this, wxID_ANY, wxT("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextThicknessUnits->Wrap( -1 ); - fgSizer->Add( m_staticTextThicknessUnits, 0, wxALL, 5 ); + fgSizer->Add( m_staticTextThicknessUnits, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); m_staticTextShape = new wxStaticText( this, wxID_ANY, wxT("Shape"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextShape->Wrap( -1 ); - fgSizer->Add( m_staticTextShape, 0, wxALL, 5 ); + fgSizer->Add( m_staticTextShape, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - wxString m_MireShapeChoices[] = { wxT("+"), wxT("X") }; - int m_MireShapeNChoices = sizeof( m_MireShapeChoices ) / sizeof( wxString ); - m_MireShape = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_MireShapeNChoices, m_MireShapeChoices, 0 ); - m_MireShape->SetSelection( 0 ); - fgSizer->Add( m_MireShape, 0, wxALL|wxEXPAND, 5 ); + wxString m_TargetShapeChoices[] = { wxT("+"), wxT("X") }; + int m_TargetShapeNChoices = sizeof( m_TargetShapeChoices ) / sizeof( wxString ); + m_TargetShape = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_TargetShapeNChoices, m_TargetShapeChoices, 0 ); + m_TargetShape->SetSelection( 0 ); + fgSizer->Add( m_TargetShape, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer->Add( 0, 0, 1, wxEXPAND, 5 ); + fgSizer->Add( 0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); bSizerUpper->Add( fgSizer, 1, wxEXPAND, 5 ); @@ -66,8 +66,8 @@ TARGET_PROPERTIES_DIALOG_EDITOR_BASE::TARGET_PROPERTIES_DIALOG_EDITOR_BASE( wxWi bSizerMain->Add( bSizerUpper, 1, wxEXPAND, 5 ); - m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerMain->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 ); + m_staticline = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMain->Add( m_staticline, 0, wxEXPAND | wxALL, 5 ); m_sdbSizerButts = new wxStdDialogButtonSizer(); m_sdbSizerButtsOK = new wxButton( this, wxID_OK ); @@ -76,11 +76,12 @@ TARGET_PROPERTIES_DIALOG_EDITOR_BASE::TARGET_PROPERTIES_DIALOG_EDITOR_BASE( wxWi m_sdbSizerButts->AddButton( m_sdbSizerButtsCancel ); m_sdbSizerButts->Realize(); - bSizerMain->Add( m_sdbSizerButts, 0, wxALIGN_RIGHT|wxEXPAND, 5 ); + bSizerMain->Add( m_sdbSizerButts, 0, wxALIGN_RIGHT|wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); this->SetSizer( bSizerMain ); this->Layout(); + bSizerMain->Fit( this ); this->Centre( wxBOTH ); diff --git a/pcbnew/dialogs/dialog_target_properties_base.fbp b/pcbnew/dialogs/dialog_target_properties_base.fbp index e10ec98e5b..fd436604d9 100644 --- a/pcbnew/dialogs/dialog_target_properties_base.fbp +++ b/pcbnew/dialogs/dialog_target_properties_base.fbp @@ -42,7 +42,7 @@ TARGET_PROPERTIES_DIALOG_EDITOR_BASE - 285,170 + -1,-1 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Target Properties @@ -118,7 +118,7 @@ 0 5 - wxALL + wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL 0 1 @@ -201,7 +201,7 @@ 5 - wxALL|wxEXPAND + wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL 0 1 @@ -239,7 +239,7 @@ 0 1 - m_MireWidthCtrl + m_TargetSizeCtrl 1 @@ -292,7 +292,7 @@ 5 - wxALL + wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT 0 1 @@ -375,7 +375,7 @@ 5 - wxALL + wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL 0 1 @@ -458,7 +458,7 @@ 5 - wxALL|wxEXPAND + wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALL 0 1 @@ -496,7 +496,7 @@ 0 1 - m_MireSizeCtrl + m_TargetThicknessCtrl 1 @@ -549,7 +549,7 @@ 5 - wxALL + wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT 0 1 @@ -632,7 +632,7 @@ 5 - wxALL + wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL 0 1 @@ -715,7 +715,7 @@ 5 - wxALL|wxEXPAND + wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL 0 1 @@ -753,7 +753,7 @@ 0 1 - m_MireShape + m_TargetShape 1 @@ -803,7 +803,7 @@ 5 - wxEXPAND + wxEXPAND|wxALIGN_CENTER_VERTICAL 1 0 @@ -854,7 +854,7 @@ 0 1 - m_staticline1 + m_staticline 1 @@ -898,7 +898,7 @@ 5 - wxALIGN_RIGHT|wxEXPAND + wxALIGN_RIGHT|wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT 0 0 diff --git a/pcbnew/dialogs/dialog_target_properties_base.h b/pcbnew/dialogs/dialog_target_properties_base.h index e8a815dd7a..293ffcf675 100644 --- a/pcbnew/dialogs/dialog_target_properties_base.h +++ b/pcbnew/dialogs/dialog_target_properties_base.h @@ -38,14 +38,14 @@ class TARGET_PROPERTIES_DIALOG_EDITOR_BASE : public DIALOG_SHIM protected: wxStaticText* m_staticTextSize; - wxTextCtrl* m_MireWidthCtrl; + wxTextCtrl* m_TargetSizeCtrl; wxStaticText* m_staticTextSizeUnits; wxStaticText* m_staticTextThickness; - wxTextCtrl* m_MireSizeCtrl; + wxTextCtrl* m_TargetThicknessCtrl; wxStaticText* m_staticTextThicknessUnits; wxStaticText* m_staticTextShape; - wxChoice* m_MireShape; - wxStaticLine* m_staticline1; + wxChoice* m_TargetShape; + wxStaticLine* m_staticline; wxStdDialogButtonSizer* m_sdbSizerButts; wxButton* m_sdbSizerButtsOK; wxButton* m_sdbSizerButtsCancel; @@ -57,7 +57,7 @@ class TARGET_PROPERTIES_DIALOG_EDITOR_BASE : public DIALOG_SHIM public: - TARGET_PROPERTIES_DIALOG_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Target Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 285,170 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + TARGET_PROPERTIES_DIALOG_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Target Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~TARGET_PROPERTIES_DIALOG_EDITOR_BASE(); }; diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index 083d4534df..703bb57ddd 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -65,6 +65,8 @@ Load() TODO's #include #include #include +#include +#include #include #include @@ -93,23 +95,6 @@ typedef boost::optional opt_bool; const wxChar* traceEaglePlugin = wxT( "KicadEaglePlugin" ); -/// Test footprint name for kicad legality, fix if needed and return true if fixing was required. -static bool fix_eagle_package_name( string* aName ) -{ - bool changed = false; - - for( string::iterator it = aName->begin(); it != aName->end(); ++it ) - { - switch( *it ) // for mapping, I always prefer a tabular switch presentation: - { - case ':': *it = '_'; changed = true; break; - case '/': *it = '-'; changed = true; break; - } - } - - return changed; -} - /// segment (element) of our XPATH into the Eagle XML document tree in PTREE form. struct TRIPLET @@ -927,7 +912,7 @@ EELEMENT::EELEMENT( CPTREE& aElement ) value = attribs.get( "value" ); package = attribs.get( "package" ); - fix_eagle_package_name( &package ); + ReplaceIllegalFileNameChars( &package ); x = attribs.get( "x" ); y = attribs.get( "y" ); @@ -1094,17 +1079,15 @@ EAGLE_PLUGIN::~EAGLE_PLUGIN() } -const wxString& EAGLE_PLUGIN::PluginName() const +const wxString EAGLE_PLUGIN::PluginName() const { - static const wxString name = wxT( "Eagle" ); - return name; + return wxT( "Eagle" ); } -const wxString& EAGLE_PLUGIN::GetFileExtension() const +const wxString EAGLE_PLUGIN::GetFileExtension() const { - static const wxString extension = wxT( "brd" ); - return extension; + return wxT( "brd" ); } @@ -1291,9 +1274,6 @@ void EAGLE_PLUGIN::loadDesignRules( CPTREE& aDesignRules ) void EAGLE_PLUGIN::loadLayerDefs( CPTREE& aLayers ) { - if( m_board == NULL ) - return; - typedef std::vector ELAYERS; typedef ELAYERS::const_iterator EITER; @@ -1332,17 +1312,21 @@ void EAGLE_PLUGIN::loadLayerDefs( CPTREE& aLayers ) } #endif - m_board->SetCopperLayerCount( cu.size() ); - - for( EITER it = cu.begin(); it != cu.end(); ++it ) + // Set the layer names and cu count iff we're loading a board. + if( m_board ) { - LAYER_NUM layer = kicad_layer( it->number ); + m_board->SetCopperLayerCount( cu.size() ); - // these function provide their own protection against UNDEFINED_LAYER: - m_board->SetLayerName( layer, FROM_UTF8( it->name.c_str() ) ); - m_board->SetLayerType( layer, LT_SIGNAL ); + for( EITER it = cu.begin(); it != cu.end(); ++it ) + { + LAYER_NUM layer = kicad_layer( it->number ); - // could map the colors here + // these function provide their own protection against UNDEFINED_LAYER: + m_board->SetLayerName( layer, FROM_UTF8( it->name.c_str() ) ); + m_board->SetLayerType( layer, LT_SIGNAL ); + + // could map the colors here + } } } @@ -1606,7 +1590,7 @@ void EAGLE_PLUGIN::loadLibrary( CPTREE& aLib, const string* aLibName ) string pack_name( pack_ref ); - fix_eagle_package_name( &pack_name ); + ReplaceIllegalFileNameChars( &pack_name ); #if 0 && defined(DEBUG) if( pack_name == "TO220H" ) @@ -1624,13 +1608,15 @@ void EAGLE_PLUGIN::loadLibrary( CPTREE& aLib, const string* aLibName ) // add the templating MODULE to the MODULE template factory "m_templates" std::pair r = m_templates.insert( key, m ); - if( !r.second ) + if( !r.second + // && !( m_props && m_props->Value( "ignore_duplicates" ) ) + ) { wxString lib = aLibName ? FROM_UTF8( aLibName->c_str() ) : m_lib_path; wxString pkg = FROM_UTF8( pack_name.c_str() ); wxString emsg = wxString::Format( - _( " name:'%s' duplicated in eagle :'%s'" ), + _( " name: '%s' duplicated in eagle : '%s'" ), GetChars( pkg ), GetChars( lib ) ); @@ -2875,6 +2861,19 @@ MODULE* EAGLE_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxStrin } +void EAGLE_PLUGIN::FootprintLibOptions( PROPERTIES* aListToAppendTo ) const +{ + PLUGIN::FootprintLibOptions( aListToAppendTo ); + + /* + (*aListToAppendTo)["ignore_duplicates"] = wxString( _( + "Ignore duplicately named footprints within the same Eagle library. " + "Only the first similarly named footprint will be loaded." + )).utf8_str(); + */ +} + + /* void EAGLE_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties ) { diff --git a/pcbnew/eagle_plugin.h b/pcbnew/eagle_plugin.h index abe92427e7..1dde4a94e5 100644 --- a/pcbnew/eagle_plugin.h +++ b/pcbnew/eagle_plugin.h @@ -80,11 +80,11 @@ class EAGLE_PLUGIN : public PLUGIN public: //------------------------------------------------------- - const wxString& PluginName() const; + const wxString PluginName() const; BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties = NULL ); - const wxString& GetFileExtension() const; + const wxString GetFileExtension() const; wxArrayString FootprintEnumerate( const wxString& aLibraryPath, const PROPERTIES* aProperties = NULL); @@ -95,6 +95,8 @@ public: return false; // until someone writes others like FootprintSave(), etc. } + void FootprintLibOptions( PROPERTIES* aProperties ) const; + /* void Save( const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties = NULL ); diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index 9ca03faa0d..cf90c3fad9 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -1177,11 +1177,11 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_MENU_ARCHIVE_NEW_MODULES: - ArchiveModulesOnBoard( wxEmptyString, true ); + ArchiveModulesOnBoard( true ); break; case ID_MENU_ARCHIVE_ALL_MODULES: - ArchiveModulesOnBoard( wxEmptyString, false ); + ArchiveModulesOnBoard( false ); break; case ID_GEN_IMPORT_DXF_FILE: diff --git a/pcbnew/edit_pcb_text.cpp b/pcbnew/edit_pcb_text.cpp index 7c518322e4..e4ecfcb5a2 100644 --- a/pcbnew/edit_pcb_text.cpp +++ b/pcbnew/edit_pcb_text.cpp @@ -37,8 +37,7 @@ #include #include - -#include +#include static void Move_Texte_Pcb( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, @@ -54,7 +53,6 @@ static TEXTE_PCB s_TextCopy( (BOARD_ITEM*) NULL ); /* copy of the edited text /* * Abort current text edit progress. - * * If a text is selected, its initial coord are regenerated */ void Abort_Edit_Pcb_Text( EDA_DRAW_PANEL* Panel, wxDC* DC ) @@ -78,7 +76,7 @@ void Abort_Edit_Pcb_Text( EDA_DRAW_PANEL* Panel, wxDC* DC ) } - SwapData( TextePcb, &s_TextCopy ); + TextePcb->SwapData( &s_TextCopy ); TextePcb->ClearFlags(); #ifndef USE_WX_OVERLAY TextePcb->Draw( Panel, DC, GR_OR ); @@ -117,11 +115,11 @@ void PCB_EDIT_FRAME::Place_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ) else { // Restore initial params - SwapData( TextePcb, &s_TextCopy ); + TextePcb->SwapData( &s_TextCopy ); // Prepare undo command SaveCopyInUndoList( TextePcb, UR_CHANGED ); - SwapData( TextePcb, &s_TextCopy ); // Restore current params + TextePcb->SwapData( &s_TextCopy ); } TextePcb->ClearFlags(); diff --git a/pcbnew/gen_modules_placefile.cpp b/pcbnew/gen_modules_placefile.cpp index 0c17cc06d9..6d4301df6b 100644 --- a/pcbnew/gen_modules_placefile.cpp +++ b/pcbnew/gen_modules_placefile.cpp @@ -200,6 +200,15 @@ bool DIALOG_GEN_MODULE_POSITION::CreateFiles() bool singleFile = OneFileOnly(); int fullcount = 0; + // Count the footprints to place, do not yet create a file + int fpcount = m_parent->DoGenFootprintsPositionFile( wxEmptyString, UnitsMM(), + ForceAllSmd(), 2 ); + if( fpcount == 0) + { + wxMessageBox( _( "No modules for automated placement." ) ); + return false; + } + fn = m_parent->GetBoard()->GetFileName(); fn.SetPath( GetOutputDirectory() ); frontLayerName = brd->GetLayerName( LAYER_N_FRONT ); @@ -208,18 +217,19 @@ bool DIALOG_GEN_MODULE_POSITION::CreateFiles() // Create the the Front or Top side placement file, // or the single file int side = 1; + if( singleFile ) { side = 2; fn.SetName( fn.GetName() + wxT( "-" ) + wxT("all") ); } - else + else fn.SetName( fn.GetName() + wxT( "-" ) + frontLayerName ); fn.SetExt( FootprintPlaceFileExtension ); - int fpcount = m_parent->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(), - ForceAllSmd(), side ); + fpcount = m_parent->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(), + ForceAllSmd(), side ); if( fpcount < 0 ) { msg.Printf( _( "Unable to create <%s>" ), GetChars( fn.GetFullPath() ) ); @@ -228,12 +238,6 @@ bool DIALOG_GEN_MODULE_POSITION::CreateFiles() return false; } - if( fpcount == 0) - { - wxMessageBox( _( "No modules for automated placement." ) ); - return false; - } - if( singleFile ) msg.Printf( _( "Place file: <%s>\n" ), GetChars( fn.GetFullPath() ) ); else @@ -339,6 +343,8 @@ void PCB_EDIT_FRAME::GenFootprintsPositionFile( wxCommandEvent& event ) * aSide = 0 -> Back (bottom) side) * aSide = 1 -> Front (top) side) * aSide = 2 -> both sides + * if aFullFileName is empty, the file is not crated, only the + * count of footprints to place is returned * * The format is: * ### Module positions - created on 04/12/2012 15:24:24 ### @@ -405,6 +411,9 @@ int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName, moduleCount++; } + if( aFullFileName.IsEmpty() ) + return moduleCount; + FILE * file = wxFopen( aFullFileName, wxT( "wt" ) ); if( file == NULL ) return -1; diff --git a/pcbnew/github/github_plugin.cpp b/pcbnew/github/github_plugin.cpp index 9650361ccd..b552669381 100644 --- a/pcbnew/github/github_plugin.cpp +++ b/pcbnew/github/github_plugin.cpp @@ -24,24 +24,15 @@ /* - This is a pcbnew PLUGIN which supports some of the PLUGIN::Footprint*() functions - in the PLUGIN interface, and could do so by utilizing the version 3 github.com - API documented here: - - http://developer.github.com - https://help.github.com/articles/creating-an-access-token-for-command-line-use - - but it does not. Rather it simply reads in a zip file of the repo and unzips it - from RAM as needed. Therefore the PLUGIN is read only for accessing - remote pretty libraries. If you want to support writing to the repo, then you - could use the above API. - -@todo: - Derive this PLUGIN from KICAD_PLUGIN so we can use its FootprintSave(). - Support local footprints if they are present in an optional directory. - Possibly cache the zip file locally. Use HTTP's "have changed" or whatever it is called. */ + +#ifndef WIN32_LEAN_AND_MEAN +// when WIN32_LEAN_AND_MEAN is defined, some useless includes in +// are skipped, and this avoid some compil issues +#define WIN32_LEAN_AND_MEAN +#endif + #ifdef WIN32 // defines needed by avhttp // Minimal Windows version is XP: Google for _WIN32_WINNT @@ -51,6 +42,7 @@ #include #include +#include #include #include @@ -69,9 +61,14 @@ #include #include #include +#include // ExpandSubstitutions() using namespace std; + +static const char* PRETTY_DIR = "allow_pretty_writing_to_this_dir"; + + typedef boost::ptr_map MODULE_MAP; typedef MODULE_MAP::iterator MODULE_ITER; typedef MODULE_MAP::const_iterator MODULE_CITER; @@ -88,28 +85,27 @@ struct GH_CACHE : public MODULE_MAP GITHUB_PLUGIN::GITHUB_PLUGIN() : - m_cache( 0 ) + PCB_IO(), + m_gh_cache( 0 ) { } GITHUB_PLUGIN::~GITHUB_PLUGIN() { - delete m_cache; + delete m_gh_cache; } -const wxString& GITHUB_PLUGIN::PluginName() const +const wxString GITHUB_PLUGIN::PluginName() const { - static wxString name( wxT( "Github" ) ); - return name; + return wxT( "Github" ); } -const wxString& GITHUB_PLUGIN::GetFileExtension() const +const wxString GITHUB_PLUGIN::GetFileExtension() const { - static wxString empty_ext; - return empty_ext; + return wxEmptyString; } @@ -117,14 +113,30 @@ wxArrayString GITHUB_PLUGIN::FootprintEnumerate( const wxString& aLibraryPath, const PROPERTIES* aProperties ) { //D(printf("%s: this:%p aLibraryPath:'%s'\n", __func__, this, TO_UTF8(aLibraryPath) );) + cacheLib( aLibraryPath, aProperties ); - cacheLib( aLibraryPath ); + typedef std::set MYSET; - wxArrayString ret; + MYSET unique; - for( MODULE_ITER it = m_cache->begin(); it!=m_cache->end(); ++it ) + if( m_pretty_dir.size() ) { - ret.Add( FROM_UTF8( it->first.c_str() ) ); + wxArrayString locals = PCB_IO::FootprintEnumerate( m_pretty_dir ); + + for( unsigned i=0; ibegin(); it!=m_gh_cache->end(); ++it ) + { + unique.insert( FROM_UTF8( it->first.c_str() ) ); + } + + wxArrayString ret; + + for( MYSET::const_iterator it = unique.begin(); it != unique.end(); ++it ) + { + ret.Add( *it ); } return ret; @@ -136,13 +148,29 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath, { // D(printf("%s: this:%p aLibraryPath:'%s'\n", __func__, this, TO_UTF8(aLibraryPath) );) - cacheLib( aLibraryPath ); + // clear or set to valid the variable m_pretty_dir + cacheLib( aLibraryPath, aProperties ); + + if( m_pretty_dir.size() ) + { + // API has FootprintLoad() *not* throwing an exception if footprint not found. + MODULE* local = PCB_IO::FootprintLoad( m_pretty_dir, aFootprintName, aProperties ); + + if( local ) + { + // It has worked, see /scripts/test_kicad_plugin.py. So this was not firing: + // wxASSERT( aFootprintName == FROM_UTF8( local->GetFPID().GetFootprintName().c_str() ) ); + // Moving it to higher API layer FP_LIB_TABLE::FootprintLoad(). + + return local; + } + } string fp_name = TO_UTF8( aFootprintName ); - MODULE_CITER it = m_cache->find( fp_name ); + MODULE_CITER it = m_gh_cache->find( fp_name ); - if( it != m_cache->end() ) // fp_name is present + if( it != m_gh_cache->end() ) // fp_name is present { wxMemoryInputStream mis( &m_zip_image[0], m_zip_image.size() ); @@ -155,13 +183,21 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath, if( zis.OpenEntry( *entry ) ) { INPUTSTREAM_LINE_READER reader( &zis ); +#if 1 + // I am a PCB_IO derivative with my own PCB_PARSER + m_parser->SetLineReader( &reader ); // ownership not passed + + MODULE* ret = (MODULE*) m_parser->Parse(); +#else PCB_PARSER parser( &reader ); MODULE* ret = (MODULE*) parser.Parse(); +#endif // Dude, the footprint name comes from the file name in // a github library. Zero out the library name, we don't know it here. - // Caller always has to set the library nickname if it knows it. + // Some caller may set the library nickname, one such instance is + // FP_LIB_TABLE::FootprintLoad(). ret->SetFPID( fp_name ); return ret; @@ -174,7 +210,109 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath, bool GITHUB_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath ) { - return false; + if( m_pretty_dir.size() ) + return PCB_IO::IsFootprintLibWritable( m_pretty_dir ); + else + return false; +} + + +void GITHUB_PLUGIN::FootprintSave( const wxString& aLibraryPath, + const MODULE* aFootprint, const PROPERTIES* aProperties ) +{ + // set m_pretty_dir to either empty or something in aProperties + cacheLib( aLibraryPath, aProperties ); + + if( GITHUB_PLUGIN::IsFootprintLibWritable( aLibraryPath ) ) + { + PCB_IO::FootprintSave( m_pretty_dir, aFootprint, aProperties ); + } + else + { + // This typically will not happen if the caller first properly calls + // IsFootprintLibWritable() to determine if calling FootprintSave() is + // even legal, so I spend no time on internationalization here: + + string msg = StrPrintf( "Github library\n'%s'\nis only writable if you set option '%s' in Library Tables dialog.", + (const char*) TO_UTF8( aLibraryPath ), PRETTY_DIR ); + + THROW_IO_ERROR( msg ); + } +} + + +void GITHUB_PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName, + const PROPERTIES* aProperties ) +{ + // set m_pretty_dir to either empty or something in aProperties + cacheLib( aLibraryPath, aProperties ); + + if( GITHUB_PLUGIN::IsFootprintLibWritable( aLibraryPath ) ) + { + // Does the PCB_IO base class have this footprint? + // We cannot write to github. + + wxArrayString pretties = PCB_IO::FootprintEnumerate( m_pretty_dir, aProperties ); + + if( pretties.Index( aFootprintName ) != wxNOT_FOUND ) + { + PCB_IO::FootprintDelete( m_pretty_dir, aFootprintName, aProperties ); + } + else + { + wxString msg = wxString::Format( + _( "Footprint\n'%s'\nis not in the writable portion of this Github library\n'%s'" ), + GetChars( aFootprintName ), + GetChars( aLibraryPath ) + ); + + THROW_IO_ERROR( msg ); + } + } + else + { + // This typically will not happen if the caller first properly calls + // IsFootprintLibWritable() to determine if calling FootprintSave() is + // even legal, so I spend no time on internationalization here: + + string msg = StrPrintf( "Github library\n'%s'\nis only writable if you set option '%s' in Library Tables dialog.", + (const char*) TO_UTF8( aLibraryPath ), PRETTY_DIR ); + + THROW_IO_ERROR( msg ); + } +} + + +void GITHUB_PLUGIN::FootprintLibCreate( const wxString& aLibraryPath, const PROPERTIES* aProperties ) +{ + // set m_pretty_dir to either empty or something in aProperties + cacheLib( aLibraryPath, aProperties ); + + if( m_pretty_dir.size() ) + { + PCB_IO::FootprintLibCreate( m_pretty_dir, aProperties ); + } + else + { + // THROW_IO_ERROR() @todo + } +} + + +bool GITHUB_PLUGIN::FootprintLibDelete( const wxString& aLibraryPath, const PROPERTIES* aProperties ) +{ + // set m_pretty_dir to either empty or something in aProperties + cacheLib( aLibraryPath, aProperties ); + + if( m_pretty_dir.size() ) + { + return PCB_IO::FootprintLibDelete( m_pretty_dir, aProperties ); + } + else + { + // THROW_IO_ERROR() @todo + return false; + } } @@ -183,32 +321,74 @@ void GITHUB_PLUGIN::FootprintLibOptions( PROPERTIES* aListToAppendTo ) const // inherit options supported by all PLUGINs. PLUGIN::FootprintLibOptions( aListToAppendTo ); - (*aListToAppendTo)["allow_pretty_writing_to_this_dir"] = wxString( _( + (*aListToAppendTo)[ PRETTY_DIR ] = wxString( _( "Set this property to a directory where footprints are to be written as pretty " "footprints when saving to this library. Anything saved will take precedence over " "footprints by the same name in the github repo. These saved footprints can then " "be sent to the library maintainer as updates. " - "

The directory should have a .pretty file extension because the " - "Kicad plugin is used to do the saving.

" + "

The directory must have a .pretty file extension because the " + "format of the save is pretty.

" )).utf8_str(); + /* (*aListToAppendTo)["cache_github_zip_in_this_dir"] = wxString( _( "Set this property to a directory where the github *.zip file will be cached. " "This should speed up subsequent visits to this library." )).utf8_str(); + */ } -void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath ) throw( IO_ERROR ) +void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aProperties ) throw( IO_ERROR ) { - if( !m_cache || m_lib_path != aLibraryPath ) + // This is edge triggered based on a change in 'aLibraryPath', + // usually it does nothing. When the edge fires, m_pretty_dir is set + // to either: + // 1) empty or + // 2) a verified and validated, writable, *.pretty directory. + + if( !m_gh_cache || m_lib_path != aLibraryPath ) { + delete m_gh_cache; + m_gh_cache = 0; + + m_pretty_dir.clear(); + + if( aProperties ) + { + string pretty_dir; + + if( aProperties->Value( PRETTY_DIR, &pretty_dir ) ) + { + wxString wx_pretty_dir = FROM_UTF8( pretty_dir.c_str() ); + + wx_pretty_dir = FP_LIB_TABLE::ExpandSubstitutions( wx_pretty_dir ); + + wxFileName wx_pretty_fn = wx_pretty_dir; + + if( !wx_pretty_fn.IsOk() || + !wx_pretty_fn.IsDirWritable() || + wx_pretty_fn.GetExt() != wxT( "pretty" ) + ) + { + wxString msg = wxString::Format( + _( "option '%s' for Github library '%s' must point to a writable directory ending with '.pretty'." ), + GetChars( FROM_UTF8( PRETTY_DIR ) ), + GetChars( aLibraryPath ) + ); + + THROW_IO_ERROR( msg ); + } + + m_pretty_dir = wx_pretty_dir; + } + } + // operator==( wxString, wxChar* ) does not exist, construct wxString once here. const wxString kicad_mod( wxT( "kicad_mod" ) ); //D(printf("%s: this:%p m_lib_path:'%s' aLibraryPath:'%s'\n", __func__, this, TO_UTF8( m_lib_path), TO_UTF8(aLibraryPath) );) - delete m_cache; - m_cache = new GH_CACHE(); + m_gh_cache = new GH_CACHE(); // INIT_LOGGER( "/tmp", "test.log" ); remote_get_zip( aLibraryPath ); @@ -231,7 +411,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath ) throw( IO_ERROR ) { string fp_name = TO_UTF8( fn.GetName() ); // omit extension & path - m_cache->insert( fp_name, entry ); + m_gh_cache->insert( fp_name, entry ); } else delete entry; diff --git a/pcbnew/github/github_plugin.h b/pcbnew/github/github_plugin.h index 12d4629ecd..02a0f3536e 100644 --- a/pcbnew/github/github_plugin.h +++ b/pcbnew/github/github_plugin.h @@ -25,45 +25,182 @@ #ifndef GITHUB_PLUGIN_H_ #define GITHUB_PLUGIN_H_ +#include struct GH_CACHE; /** - * Class GITHUB_PLUGIN - * implements a portion of pcbnew PLUGIN to provide read only access to a github - * repo consisting of pretty footprints - * - * @author Dick Hollenbeck - * @date Original date: 10-Sep-2013 + Class GITHUB_PLUGIN + implements a portion of pcbnew's PLUGIN interface to provide read only access + to a github repo consisting of pretty footprints, and optionally provides "Copy On Write" + support of edited footprints. + +

It could have used version 3 of the github.com API documented here: + +

+       http://developer.github.com
+       https://help.github.com/articles/creating-an-access-token-for-command-line-use
+   
+ + but it does not, since a better technique was discovered. Cleverly this + plugin simply reads in a zip file of the repo and unzips it from RAM as + needed. Therefore this "Github" plugin is read only for accessing remote + pretty libraries at https://github.com. + +

The fp-lib-table dialog is entered via menu choice "Preferences | Library + Tables". For easy options editing in the current row, click on the "Edit + Options" button. The "Library Path" in the fp-lib-table row for a Github + library should be set to the full https:// URL. + +

For example: + +

+        https://github.com/liftoff-sr/pretty_footprints
+   
+ + This is typically + +
+        https://github.com/user_name/repo_name
+   
+

+ + The "Plugin Type" should be set to "Github". + +

This plugin also supports "Copy On Write", a.k.a. "COW". Thus a Github + library may take an optional option called + allow_pretty_writing_to_this_dir. This option is essentially the + "Library Path" for a local "KiCad" (pretty) type library which is combined to + make up the Github library found in the same fp-lib-table row. If the option + is missing, then the Github library is read only as always. If the option is + present for a Github library, then any writes to this hybrid library will go + to the local *.pretty directory. Note that the github.com resident portion of + this hybrid COW library is always read only, meaning you cannot delete + anything or modify any footprint at github directly. The aggregate library + type remains "Github" in your discussions, but it consists of a local R/W + portion and a remote R/O portion. + +

Below is an fp-lib-table entry for the case without option + allow_pretty_writing_to_this_dir: + + + + + + + + + + +
NicknameLibrary PathPlugin TypeOptionsDescription
githubhttps://github.com/liftoff-sr/pretty_footprintsGithubLiftoff's GH footprints
+ + Below is an fp-lib-table entry with the COW option given. Note the use of the environment variable + ${HOME}, as an example only. The github.pretty directory is based in ${HOME}/pretty/. Anytime you + use option allow_pretty_writing_to_this_dir, you will create that directory manually and it must + end in extension .pretty. + + + + + + + + + + + + +
NicknameLibrary PathPlugin TypeOptionsDescription
githubhttps://github.com/liftoff-sr/pretty_footprintsGithuballow_pretty_writing_to_this_dir=${HOME}/pretty/github.prettyLiftoff's GH footprints
+ +

Any footprint loads will always give precedence to the local footprints + found in the pretty dir given by option + allow_pretty_writing_to_this_dir. So once you have written to the COW + library's local directory by doing a footprint save, no github updates will + be seen when loading a footprint by the same name as one for which you've + written locally. + +

Always keep a separate local *.pretty directory for each Github library, + never combine them by referring to the same directory more than once. Also, + do not also use the same COW (*.pretty) directory in a "KiCad" fp-lib-table + entry. This would likely create a mess. The COW directory should be manually + created in advance, and the directory name must end with ".pretty". The value + of the option allow_pretty_writing_to_this_dir will be path + substituted with any environment variable strings embedded, just like the + "Library Path" is. + +

What's the point of COW? It is to turbo-charge the sharing of footprints. + If you periodically email your COW pretty footprint modifications to the + Github repo maintainer, you can help update the Github copy. Simply email the + individual *.kicad_mod files you find in your COW directories. After you've + received confirmation that your changes have been committed up at github.com, + you can safely delete your COW file(s) and those from github.com will flow + down. Your goal should be to keep the COW file set as small as possible by + contributing frequently to the shared master copies at https://github.com. + +

Note that if you use the module editor to delete a footprint and it is + present in the COW local dir, it will get deleted from there. However, it may + not be deleted from the library as a whole if the footprint of the same name + also exists in the github repo. In this case deleting the local copy will + simply unmask the one at the github repo. Remember, it is masked out if there + is a local COW copy, since the local copy always takes precedence. And + remember you cannot modify the github copy except by emailing a COW + modification to the repo maintainer. + +

If you happen to be the repo maintainer, then the obvious solution for you + is to make your COW directory be your working copy directory. From + there you can push to github. And you can receive *.kicad_mod files by email + and put them into your local working copy directory also and do diffs, + reverting or denying when appropriate, editing when appropriate before + pushing or denying the change. Ultimately you would owe the sender either a + note of acceptance or denial by email. + + @author Dick Hollenbeck + @date Original date: 10-Sep-2013 + */ -class GITHUB_PLUGIN : public PLUGIN +class GITHUB_PLUGIN : public PCB_IO { public: //--------------------------------------------------------------- - // ("read-only" subset) + const wxString PluginName() const; - const wxString& PluginName() const; + const wxString GetFileExtension() const; - const wxString& GetFileExtension() const; - - wxArrayString FootprintEnumerate( const wxString& aLibraryPath, const PROPERTIES* aProperties ); + wxArrayString FootprintEnumerate( const wxString& aLibraryPath, + const PROPERTIES* aProperties = NULL ); MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, const PROPERTIES* aProperties ); + void FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, + const PROPERTIES* aProperties = NULL ); + + void FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName, + const PROPERTIES* aProperties = NULL ); + bool IsFootprintLibWritable( const wxString& aLibraryPath ); void FootprintLibOptions( PROPERTIES* aListToAppendTo ) const; + // Since I derive from PCB_IO, I have to implement this, else I'd inherit his, which is bad since + // my lib_path is not his. Note: it is impossible to create a Github library, but can the C.O.W. portion. + void FootprintLibCreate( const wxString& aLibraryPath, const PROPERTIES* aProperties ); + + // Since I derive from PCB_IO, I have to implement this, else I'd inherit his, which is bad since + // my lib_path is not his. Note: it is impossible to delete a Github library, but can the C.O.W portion. + bool FootprintLibDelete( const wxString& aLibraryPath, const PROPERTIES* aProperties ); + //-------------------------------------------------------------- GITHUB_PLUGIN(); // constructor, if any, must be zero arg ~GITHUB_PLUGIN(); -private: +protected: - void cacheLib( const wxString& aLibraryPath ) throw( IO_ERROR ); + void init( const PROPERTIES* aProperties ); + + void cacheLib( const wxString& aLibraryPath, const PROPERTIES* aProperties ) throw( IO_ERROR ); /** * Function repoURL_zipURL @@ -84,7 +221,9 @@ private: wxString m_lib_path; ///< from aLibraryPath, something like https://github.com/liftoff-sr/pretty_footprints std::string m_zip_image; ///< byte image of the zip file in its entirety. - GH_CACHE* m_cache; + GH_CACHE* m_gh_cache; + wxString m_pretty_dir; }; + #endif // GITHUB_PLUGIN_H_ diff --git a/pcbnew/gpcb_plugin.h b/pcbnew/gpcb_plugin.h index 3e38d67e36..b1fb4a9c72 100644 --- a/pcbnew/gpcb_plugin.h +++ b/pcbnew/gpcb_plugin.h @@ -52,16 +52,14 @@ public: //-------------------------------------------------------------- - const wxString& PluginName() const + const wxString PluginName() const { - static const wxString name = wxT( "Geda PCB" ); - return name; + return wxT( "Geda PCB" ); } - const wxString& GetFileExtension() const + const wxString GetFileExtension() const { - static const wxString extension = wxT( "fp" ); - return extension; + return wxT( "fp" ); } wxArrayString FootprintEnumerate( const wxString& aLibraryPath, const PROPERTIES* aProperties = NULL); diff --git a/pcbnew/io_mgr.h b/pcbnew/io_mgr.h index bd5b92a61d..58f6459d17 100644 --- a/pcbnew/io_mgr.h +++ b/pcbnew/io_mgr.h @@ -220,13 +220,13 @@ public: * Function PluginName * returns a brief hard coded name for this PLUGIN. */ - virtual const wxString& PluginName() const = 0; + virtual const wxString PluginName() const = 0; /** * Function GetFileExtension * returns the file extension for the PLUGIN. */ - virtual const wxString& GetFileExtension() const = 0; + virtual const wxString GetFileExtension() const = 0; /** * Function Load @@ -286,11 +286,11 @@ public: * Function FootprintEnumerate * returns a list of footprint names contained within the library at @a aLibraryPath. * - * @param aLibraryPath is a locator for the "library", usually a directory - * or file containing several footprints. + * @param aLibraryPath is a locator for the "library", usually a directory, file, + * or URL containing several footprints. * * @param aProperties is an associative array that can be used to tell the - * plugin how to access the library. + * plugin anything needed about how to perform with respect to @a aLibraryPath. * The caller continues to own this object (plugin may not delete it), and * plugins should expect it to be optionally NULL. * @@ -307,8 +307,8 @@ public: * loads a footprint having @a aFootprintName from the @a aLibraryPath containing * a library format that this PLUGIN knows about. * - * @param aLibraryPath is a locator for the "library", usually a directory - * or file containing several footprints. + * @param aLibraryPath is a locator for the "library", usually a directory, file, + * or URL containing several footprints. * * @param aFootprintName is the name of the footprint to load. * @@ -331,9 +331,8 @@ public: * will write @a aModule to an existing library located at @a aLibraryPath. * If a footprint by the same name already exists, it is replaced. * - * @param aLibraryPath is a locator for the "library", usually a directory - * or file containing several footprints. This is where the footprint is - * to be stored. + * @param aLibraryPath is a locator for the "library", usually a directory, file, + * or URL containing several footprints. * * @param aFootprint is what to store in the library. The caller continues * to own the footprint after this call. @@ -351,15 +350,15 @@ public: /** * Function FootprintDelete - * deletes the @a aFootprintName from the library at @a aLibraryPath. + * deletes @a aFootprintName from the library at @a aLibraryPath. * - * @param aLibraryPath is a locator for the "library", usually a directory - * or file containing several footprints. + * @param aLibraryPath is a locator for the "library", usually a directory, file, + * or URL containing several footprints. * * @param aFootprintName is the name of a footprint to delete from the specified library. * * @param aProperties is an associative array that can be used to tell the - * library create function anything special, because it can take any number of + * library delete function anything special, because it can take any number of * additional named tuning arguments that the plugin is known to support. * The caller continues to own this object (plugin may not delete it), and * plugins should expect it to be optionally NULL. @@ -375,8 +374,8 @@ public: * error to attempt to create an existing library or to attempt to create * on a "read only" location. * - * @param aLibraryPath is a locator for the "library", usually a directory - * or file which will contain footprints. + * @param aLibraryPath is a locator for the "library", usually a directory, file, + * or URL containing several footprints. * * @param aProperties is an associative array that can be used to tell the * library create function anything special, because it can take any number of @@ -414,6 +413,9 @@ public: * returns true iff the library at @a aLibraryPath is writable. (Often * system libraries are read only because of where they are installed.) * + * @param aLibraryPath is a locator for the "library", usually a directory, file, + * or URL containing several footprints. + * * @throw IO_ERROR if no library at aLibraryPath exists. */ virtual bool IsFootprintLibWritable( const wxString& aLibraryPath ); diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 23092f07e5..a50a299663 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -85,7 +85,10 @@ public: wxString GetName() const { return m_file_name.GetDirs().Last(); } wxFileName GetFileName() const { return m_file_name; } + + /// Tell if the disk content or the lib_path has changed. bool IsModified() const; + MODULE* GetModule() const { return m_module.get(); } void UpdateModificationTime() { m_mod_time = m_file_name.GetModificationTime(); } }; @@ -339,6 +342,7 @@ bool FP_CACHE::IsModified( const wxString& aLibPath, const wxString& aFootprintN for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it ) { wxFileName fn = m_lib_path; + fn.SetName( it->second->GetFileName().GetName() ); fn.SetExt( KiCadFootprintFileExtension ); @@ -966,12 +970,15 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const else m_out->Print( 0, "\n" ); - m_out->Print( aNestLevel+1, "(at %s", FMT_IU( aModule->GetPosition() ).c_str() ); + if( !( m_ctl & CTL_OMIT_AT ) ) + { + m_out->Print( aNestLevel+1, "(at %s", FMT_IU( aModule->GetPosition() ).c_str() ); - if( aModule->GetOrientation() != 0.0 ) - m_out->Print( 0, " %s", FMT_ANGLE( aModule->GetOrientation() ).c_str() ); + if( aModule->GetOrientation() != 0.0 ) + m_out->Print( 0, " %s", FMT_ANGLE( aModule->GetOrientation() ).c_str() ); - m_out->Print( 0, ")\n" ); + m_out->Print( 0, ")\n" ); + } if( !aModule->GetDescription().IsEmpty() ) m_out->Print( aNestLevel+1, "(descr %s)\n", @@ -1804,7 +1811,7 @@ void PCB_IO::FootprintDelete( const wxString& aLibraryPath, const wxString& aFoo { LOCALE_IO toggle; // toggles on, then off, the C locale. - init( NULL ); + init( aProperties ); cacheLib( aLibraryPath ); diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h index 515e1b1a71..ce7c40ef38 100644 --- a/pcbnew/kicad_plugin.h +++ b/pcbnew/kicad_plugin.h @@ -43,6 +43,8 @@ class PCB_PARSER; #define CTL_OMIT_TSTAMPS (1 << 2) #define CTL_OMIT_INITIAL_COMMENTS (1 << 3) ///< omit MODULE initial comments #define CTL_OMIT_PATH (1 << 4) +#define CTL_OMIT_AT (1 << 5) + // common combinations of the above: @@ -50,7 +52,7 @@ class PCB_PARSER; #define CTL_FOR_CLIPBOARD (CTL_STD_LAYER_NAMES|CTL_OMIT_NETS) /// Format output for a footprint library instead of clipboard or BOARD -#define CTL_FOR_LIBRARY (CTL_STD_LAYER_NAMES|CTL_OMIT_NETS|CTL_OMIT_TSTAMPS|CTL_OMIT_PATH) +#define CTL_FOR_LIBRARY (CTL_STD_LAYER_NAMES|CTL_OMIT_NETS|CTL_OMIT_TSTAMPS|CTL_OMIT_PATH|CTL_OMIT_AT) /// The zero arg constructor when PCB_IO is used for PLUGIN::Load() and PLUGIN::Save()ing /// a BOARD file underneath IO_MGR. @@ -83,20 +85,18 @@ public: //-------------------------------------------------------------- - const wxString& PluginName() const + const wxString PluginName() const { - static const wxString name = wxT( "KiCad" ); - return name; + return wxT( "KiCad" ); } - const wxString& GetFileExtension() const + const wxString GetFileExtension() const { // Would have used wildcards_and_files_ext.cpp's KiCadPcbFileExtension, // but to be pure, a plugin should not assume that it will always be linked // with the core of the pcbnew code. (Might someday be a DLL/DSO.) Besides, // file extension policy should be controlled by the plugin. - static const wxString extension = wxT( "kicad_pcb" ); - return extension; + return wxT( "kicad_pcb" ); } void Save( const wxString& aFileName, BOARD* aBoard, @@ -172,6 +172,10 @@ protected: int m_ctl; PCB_PARSER* m_parser; + /// we only cache one footprint library, this determines which one. + void cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName = wxEmptyString ); + + void init( const PROPERTIES* aProperties ); private: void format( BOARD* aBoard, int aNestLevel = 0 ) const @@ -211,11 +215,6 @@ private: void formatLayers( LAYER_MSK aLayerMask, int aNestLevel = 0 ) const throw( IO_ERROR ); - - /// we only cache one footprint library for now, this determines which one. - void cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName = wxEmptyString ); - - void init( const PROPERTIES* aProperties ); }; #endif // KICAD_PLUGIN_H_ diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index 9f912da92e..c941c00210 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -281,6 +281,10 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend ) FPID fpid; std::string fpName = StrPurge( line + SZ( "$MODULE" ) ); + // The footprint names in legacy libraries can contain the '/' and ':' + // characters which will cause the FPID parser to choke. + ReplaceIllegalFileNameChars( &fpName ); + if( !fpName.empty() ) fpid = FPID( fpName ); @@ -4031,6 +4035,10 @@ void LP_CACHE::LoadModules( LINE_READER* aReader ) std::string footprintName = StrPurge( line + SZ( "$MODULE" ) ); + // The footprint names in legacy libraries can contain the '/' and ':' + // characters which will cause the FPID parser to choke. + ReplaceIllegalFileNameChars( &footprintName ); + // set the footprint name first thing, so exceptions can use name. module->SetFPID( FPID( footprintName ) ); diff --git a/pcbnew/legacy_plugin.h b/pcbnew/legacy_plugin.h index b17aecb79d..c5eba40083 100644 --- a/pcbnew/legacy_plugin.h +++ b/pcbnew/legacy_plugin.h @@ -64,16 +64,14 @@ public: //--------------------------------------------------- - const wxString& PluginName() const + const wxString PluginName() const { - static const wxString name = wxT( "KiCad-Legacy" ); - return name; + return wxT( "KiCad-Legacy" ); } - const wxString& GetFileExtension() const + const wxString GetFileExtension() const { - static const wxString extension = wxT( "brd" ); - return extension; + return wxT( "brd" ); } BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties = NULL ); diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index d2187d7ab7..f1badcc0f5 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -53,29 +54,29 @@ // unique, "file local" translations: -#define FMT_OK_OVERWRITE _( "Library <%s> exists, OK to replace ?" ) +#define FMT_OK_OVERWRITE _( "Library '%s' exists, OK to replace ?" ) #define FMT_CREATE_LIB _( "Create New Library" ) -#define FMT_OK_DELETE _( "OK to delete module %s in library <%s>" ) +#define FMT_OK_DELETE _( "OK to delete module %s in library '%s'" ) #define FMT_IMPORT_MODULE _( "Import Footprint Module" ) -#define FMT_FILE_NOT_FOUND _( "File <%s> not found" ) +#define FMT_FILE_NOT_FOUND _( "File '%s' not found" ) #define FMT_NOT_MODULE _( "Not a module file" ) -#define FMT_MOD_NOT_FOUND _( "Unable to find or load footprint %s from lib path <%s>" ) -#define FMT_BAD_PATH _( "Unable to find or load footprint from path <%s>" ) -#define FMT_BAD_PATHS _( "The footprint library <%s> could not be found in any of the search paths." ) -#define FMT_LIB_READ_ONLY _( "Library <%s> is read only, not writable" ) +#define FMT_MOD_NOT_FOUND _( "Unable to find or load footprint %s from lib path '%s'" ) +#define FMT_BAD_PATH _( "Unable to find or load footprint from path '%s'" ) +#define FMT_BAD_PATHS _( "The footprint library '%s' could not be found in any of the search paths." ) +#define FMT_LIB_READ_ONLY _( "Library '%s' is read only, not writable" ) #define FMT_EXPORT_MODULE _( "Export Module" ) #define FMT_SAVE_MODULE _( "Save Module" ) #define FMT_MOD_REF _( "Module Reference:" ) -#define FMT_EXPORTED _( "Module exported to file <%s>" ) -#define FMT_MOD_DELETED _( "Module %s deleted from library <%s>" ) +#define FMT_EXPORTED _( "Module exported to file '%s'" ) +#define FMT_MOD_DELETED _( "Module %s deleted from library '%s'" ) #define FMT_MOD_CREATE _( "Module Creation" ) #define FMT_NO_MODULES _( "No modules to archive!" ) #define FMT_LIBRARY _( "Library" ) // window title -#define FMT_MOD_EXISTS _( "Module %s already exists in library <%s>" ) +#define FMT_MOD_EXISTS _( "Module %s already exists in library '%s'" ) #define FMT_NO_REF_ABORTED _( "No reference, aborted" ) -#define FMT_SELECT_LIB _( "Select Active Library:" ) +#define FMT_SELECT_LIB _( "Select Library" ) static const wxString ModExportFileWildcard( _( "KiCad foot print export files (*.emp)|*.emp" ) ); @@ -377,7 +378,7 @@ wxString FOOTPRINT_EDIT_FRAME::CreateNewLibrary() wxString wildcard; - wildcard << wxGetTranslation( LegacyFootprintLibPathWildcard ) << wxChar('|') + wildcard << wxGetTranslation( LegacyFootprintLibPathWildcard ) << wxChar( '|' ) << wxGetTranslation( KiCadFootprintLibPathWildcard ); // prompt user for libPath and PLUGIN (library) type @@ -463,6 +464,53 @@ wxString FOOTPRINT_EDIT_FRAME::CreateNewLibrary() bool FOOTPRINT_EDIT_FRAME::DeleteModuleFromCurrentLibrary() { +#if defined(USE_FP_LIB_TABLE) + + wxString nickname = getLibNickName(); + + if( !m_footprintLibTable->IsFootprintLibWritable( nickname ) ) + { + wxString msg = wxString::Format( + _( "Library '%s' is read only" ), + GetChars( nickname ) + ); + + DisplayError( this, msg ); + return false; + } + + wxString fpid_txt = PCB_BASE_FRAME::SelectFootprint( this, nickname, + wxEmptyString, wxEmptyString, m_footprintLibTable ); + + if( !fpid_txt ) + return false; + + FPID fpid( fpid_txt ); + wxString fpname = FROM_UTF8( fpid.GetFootprintName().c_str() ); + + // Confirmation + wxString msg = wxString::Format( FMT_OK_DELETE, fpname.GetData(), nickname.GetData() ); + + if( !IsOK( this, msg ) ) + return false; + + try + { + m_footprintLibTable->FootprintDelete( nickname, fpname ); + } + catch( IO_ERROR ioe ) + { + DisplayError( this, ioe.errorText ); + return false; + } + + msg.Printf( FMT_MOD_DELETED, fpname.GetData(), nickname.GetData() ); + + SetStatusText( msg ); + + return true; + +#else PCB_EDIT_FRAME* parent = (PCB_EDIT_FRAME*) GetParent(); wxString libPath = getLibPath(); wxString footprintName = PCB_BASE_FRAME::SelectFootprint( this, libPath, @@ -497,17 +545,73 @@ bool FOOTPRINT_EDIT_FRAME::DeleteModuleFromCurrentLibrary() SetStatusText( msg ); return true; + +#endif } -/* Save modules in a library: - * param aNewModulesOnly: - * true : save modules not already existing in this lib - * false: save all modules - */ -void PCB_EDIT_FRAME::ArchiveModulesOnBoard( const wxString& aLibName, bool aNewModulesOnly ) +#if defined(USE_FP_LIB_TABLE) +void PCB_EDIT_FRAME::ArchiveModulesOnBoard( bool aNewModulesOnly ) { - wxString fileName = aLibName; + if( GetBoard()->m_Modules == NULL ) + { + DisplayInfoMessage( this, FMT_NO_MODULES ); + return; + } + + wxString last_nickname = wxGetApp().ReturnLastVisitedLibraryPath(); + + wxString nickname = SelectLibrary( last_nickname ); + + if( !nickname ) + return; + + wxGetApp().SaveLastVisitedLibraryPath( nickname ); + + if( !aNewModulesOnly ) + { + wxString msg = wxString::Format( FMT_OK_OVERWRITE, GetChars( nickname ) ); + + if( !IsOK( this, msg ) ) + return; + } + + m_canvas->SetAbortRequest( false ); + + try + { + // Delete old library if we're replacing it entirely. + if( !aNewModulesOnly ) + { + m_footprintLibTable->FootprintLibDelete( nickname ); + m_footprintLibTable->FootprintLibCreate( nickname ); + + for( MODULE* m = GetBoard()->m_Modules; m; m = m->Next() ) + { + m_footprintLibTable->FootprintSave( nickname, m, true ); + } + } + else + { + for( MODULE* m = GetBoard()->m_Modules; m; m = m->Next() ) + { + m_footprintLibTable->FootprintSave( nickname, m, false ); + + // Check for request to stop backup (ESCAPE key actuated) + if( m_canvas->GetAbortRequest() ) + break; + } + } + } + catch( IO_ERROR ioe ) + { + DisplayError( this, ioe.errorText ); + } +} +#else +void PCB_EDIT_FRAME::ArchiveModulesOnBoard( bool aNewModulesOnly ) +{ + wxString fileName; wxString path; if( GetBoard()->m_Modules == NULL ) @@ -518,7 +622,6 @@ void PCB_EDIT_FRAME::ArchiveModulesOnBoard( const wxString& aLibName, bool aNewM path = wxGetApp().ReturnLastVisitedLibraryPath(); - if( !aLibName ) { wxFileDialog dlg( this, FMT_LIBRARY, path, wxEmptyString, @@ -532,7 +635,9 @@ void PCB_EDIT_FRAME::ArchiveModulesOnBoard( const wxString& aLibName, bool aNewM } wxFileName fn( fileName ); + wxGetApp().SaveLastVisitedLibraryPath( fn.GetPath() ); + bool lib_exists = wxFileExists( fileName ); if( !aNewModulesOnly && lib_exists ) @@ -584,12 +689,12 @@ void PCB_EDIT_FRAME::ArchiveModulesOnBoard( const wxString& aLibName, bool aNewM catch( IO_ERROR ioe ) { DisplayError( this, ioe.errorText ); - return; } } +#endif -bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibPath, +bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibrary, MODULE* aModule, bool aOverwrite, bool aDisplayDialog ) @@ -618,10 +723,10 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibPath, if( ! MODULE::IsLibNameValid( footprintName ) ) { - wxString msg; - msg.Printf( _("Error:\none of invalid chars '%s' found\nin '%s'" ), - MODULE::ReturnStringLibNameInvalidChars( true ), - GetChars( footprintName ) ); + wxString msg = wxString::Format( + _("Error:\none of invalid chars '%s' found\nin '%s'" ), + MODULE::ReturnStringLibNameInvalidChars( true ), + GetChars( footprintName ) ); DisplayError( NULL, msg ); return false; @@ -637,25 +742,24 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibPath, aModule->SetFPID( footprintName ); } - IO_MGR::PCB_FILE_T pluginType = IO_MGR::GuessPluginTypeFromLibPath( aLibPath ); - - MODULE* module_exists = NULL; + bool module_exists = false; +#if defined(USE_FP_LIB_TABLE) try { - PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); + MODULE* m = m_footprintLibTable->FootprintLoad( aLibrary, footprintName ); - module_exists = pi->FootprintLoad( aLibPath, footprintName ); - - if( module_exists ) + if( m ) { - delete module_exists; + delete m; + + module_exists = true; // an existing footprint is found in current lib if( aDisplayDialog ) { wxString msg = wxString::Format( FMT_MOD_EXISTS, - footprintName.GetData(), aLibPath.GetData() ); + footprintName.GetData(), aLibrary.GetData() ); SetStatusText( msg ); } @@ -669,7 +773,46 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibPath, // this always overwrites any existing footprint, but should yell on its // own if the library or footprint is not writable. - pi->FootprintSave( aLibPath, aModule ); + m_footprintLibTable->FootprintSave( aLibrary, aModule ); + +#else + + + IO_MGR::PCB_FILE_T pluginType = IO_MGR::GuessPluginTypeFromLibPath( aLibrary ); + + try + { + PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); + + MODULE* m = pi->FootprintLoad( aLibrary, footprintName ); + + if( m ) + { + delete m; + + module_exists = true; + + // an existing footprint is found in current lib + if( aDisplayDialog ) + { + wxString msg = wxString::Format( FMT_MOD_EXISTS, + footprintName.GetData(), aLibrary.GetData() ); + + SetStatusText( msg ); + } + + if( !aOverwrite ) + { + // Do not save the given footprint: an old one exists + return true; + } + } + + // this always overwrites any existing footprint, but should yell on its + // own if the library or footprint is not writable. + pi->FootprintSave( aLibrary, aModule ); +#endif + } catch( IO_ERROR ioe ) { @@ -680,10 +823,10 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibPath, if( aDisplayDialog ) { wxString fmt = module_exists ? - _( "Component [%s] replaced in <%s>" ) : - _( "Component [%s] added in <%s>" ); + _( "Component [%s] replaced in '%s'" ) : + _( "Component [%s] added in '%s'" ); - wxString msg = wxString::Format( fmt, footprintName.GetData(), aLibPath.GetData() ); + wxString msg = wxString::Format( fmt, footprintName.GetData(), aLibrary.GetData() ); SetStatusText( msg ); } @@ -703,6 +846,7 @@ MODULE* PCB_BASE_FRAME::Create_1_Module( const wxString& aModuleName ) if( moduleName.IsEmpty() ) { wxTextEntryDialog dlg( this, FMT_MOD_REF, FMT_MOD_CREATE, moduleName ); + dlg.SetTextValidator( FOOTPRINT_NAME_VALIDATOR() ); if( dlg.ShowModal() != wxID_OK ) return NULL; //Aborted by user @@ -750,10 +894,10 @@ MODULE* PCB_BASE_FRAME::Create_1_Module( const wxString& aModuleName ) #if !defined( USE_FP_LIB_TABLE ) -void FOOTPRINT_EDIT_FRAME::Select_Active_Library() +wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting ) { if( g_LibraryNames.GetCount() == 0 ) - return; + return wxEmptyString; wxArrayString headers; headers.Add( _( "Library" ) ); @@ -768,66 +912,60 @@ void FOOTPRINT_EDIT_FRAME::Select_Active_Library() itemsToDisplay.push_back( item ); } - EDA_LIST_DIALOG dlg( this, FMT_SELECT_LIB, headers, itemsToDisplay, getLibNickName() ); + EDA_LIST_DIALOG dlg( this, FMT_SELECT_LIB, headers, itemsToDisplay, aNicknameExisting ); if( dlg.ShowModal() != wxID_OK ) - return; + return wxEmptyString; wxFileName fileName = wxFileName( wxEmptyString, dlg.GetTextSelection(), LegacyFootprintLibPathExtension ); fileName = wxGetApp().FindLibraryPath( fileName ); - if( fileName.IsOk() && fileName.FileExists() ) - { - setLibNickName( fileName.GetName() ); - setLibPath( fileName.GetFullPath() ); - } - else + if( !fileName.IsOk() || !fileName.FileExists() ) { wxString msg = wxString::Format( FMT_BAD_PATHS, GetChars( dlg.GetTextSelection() ) ); DisplayError( this, msg ); - setLibNickName( wxEmptyString ); - setLibPath( wxEmptyString ); + return wxEmptyString; } - updateTitle(); + return fileName.GetFullPath(); } #else -void FOOTPRINT_EDIT_FRAME::Select_Active_Library() +wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting ) { - if( m_footprintLibTable->IsEmpty() ) - return; - wxArrayString headers; - headers.Add( _( "Library" ) ); + + headers.Add( _( "Nickname" ) ); + headers.Add( _( "Description" ) ); std::vector< wxArrayString > itemsToDisplay; - std::vector< wxString > libNames = m_footprintLibTable->GetLogicalLibs(); + std::vector< wxString > nicknames = m_footprintLibTable->GetLogicalLibs(); - for( unsigned i = 0; i < libNames.size(); i++ ) + for( unsigned i = 0; i < nicknames.size(); i++ ) { wxArrayString item; - item.Add( libNames[i] ); + + item.Add( nicknames[i] ); + item.Add( m_footprintLibTable->GetDescription( nicknames[i] ) ); + itemsToDisplay.push_back( item ); } - EDA_LIST_DIALOG dlg( this, FMT_SELECT_LIB, headers, itemsToDisplay, getLibNickName() ); + EDA_LIST_DIALOG dlg( this, FMT_SELECT_LIB, headers, itemsToDisplay, aNicknameExisting ); if( dlg.ShowModal() != wxID_OK ) - return; + return wxEmptyString; wxString nickname = dlg.GetTextSelection(); - setLibNickName( nickname ); + wxLogDebug( wxT( "Chose footprint library '%s'." ), GetChars( nickname ) ); - wxLogDebug( wxT( "Chose footprint library <%s>." ), GetChars( nickname ) ); - - updateTitle(); + return nickname; } #endif diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index cd5a1982b8..a38c5aa9f9 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -336,7 +336,22 @@ MODULE* PCB_BASE_FRAME::loadFootprintFromLibrary( const wxString& aLibraryPath, { PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) ); - wxString libPath = wxGetApp().FindLibraryPath( aLibraryPath ); + // Ensure the library name has the right extension + // (sometimes the name is given without ext) + wxString libname = aLibraryPath; + + if( !libname.EndsWith( wxT(".") + LegacyFootprintLibPathExtension) ) + libname << wxT(".") << LegacyFootprintLibPathExtension; + + wxString libPath = wxGetApp().FindLibraryPath( libname ); + + if( libPath.IsEmpty() ) + { + wxString msg = wxString::Format( _( "Library '%s' not found." ), + libname.GetData() ); + DisplayError( NULL, msg ); + return NULL; + } MODULE* footprint = pi->FootprintLoad( libPath, aFootprintName ); @@ -429,6 +444,26 @@ MODULE* PCB_BASE_FRAME::loadFootprintFromLibraries( return NULL; } +/* attempts to load aFootprintId from the footprint library table. + * return the #MODULE if found or NULL if not found or error. + */ +MODULE* PCB_BASE_FRAME::LoadFootprint( const FPID& aFootprintId ) +{ + MODULE* module = NULL; + + try + { + module = loadFootprint( aFootprintId ); + } + catch( IO_ERROR ioe ) + { + wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ), + aFootprintId.Format().c_str(), GetChars( ioe.errorText ) ); + } + + return module; +} + MODULE* PCB_BASE_FRAME::loadFootprint( const FPID& aFootprintId ) throw( IO_ERROR, PARSE_ERROR ) @@ -470,11 +505,13 @@ wxString PCB_BASE_FRAME::SelectFootprint( EDA_DRAW_FRAME* aWindow, const wxString& aKeyWord, FP_LIB_TABLE* aTable ) { - static wxString OldName; // Save the name of the last module loaded. - wxString CmpName; - wxString msg; - wxArrayString libraries; - FP_LIB_TABLE libTable; + static wxString oldName; // Save the name of the last module loaded. + + wxString fpname; + wxString msg; + wxArrayString libraries; + FP_LIB_TABLE libTable; + std::vector< wxArrayString > rows; #if !defined( USE_FP_LIB_TABLE ) @@ -581,33 +618,33 @@ wxString PCB_BASE_FRAME::SelectFootprint( EDA_DRAW_FRAME* aWindow, msg.Printf( _( "Modules [%d items]" ), (int) rows.size() ); - EDA_LIST_DIALOG dlg( aWindow, msg, headers, rows, OldName, DisplayCmpDoc ); + EDA_LIST_DIALOG dlg( aWindow, msg, headers, rows, oldName, DisplayCmpDoc ); if( dlg.ShowModal() == wxID_OK ) { - CmpName = dlg.GetTextSelection(); + fpname = dlg.GetTextSelection(); #if defined( USE_FP_LIB_TABLE ) - CmpName = dlg.GetTextSelection( 1 ) + wxT( ":" ) + CmpName; + fpname = dlg.GetTextSelection( 1 ) + wxT( ":" ) + fpname; #endif SkipNextLeftButtonReleaseEvent(); } else - CmpName.Empty(); + fpname.Empty(); } else { DisplayError( aWindow, _( "No footprint found." ) ); - CmpName.Empty(); + fpname.Empty(); } - if( CmpName != wxEmptyString ) - OldName = CmpName; + if( fpname != wxEmptyString ) + oldName = fpname; - wxLogDebug( wxT( "Footprint '%s' was selected." ), GetChars( CmpName ) ); + wxLogDebug( wxT( "Footprint '%s' was selected." ), GetChars( fpname ) ); - return CmpName; + return fpname; } @@ -628,27 +665,29 @@ static void DisplayCmpDoc( wxString& Name ) MODULE* FOOTPRINT_EDIT_FRAME::SelectFootprint( BOARD* aPcb ) { - MODULE* module; - static wxString OldName; // Save name of last module selected. - wxString CmpName, msg; + static wxString oldName; // Save name of last module selected. - wxArrayString listnames; + wxString fpname; + wxString msg; + wxArrayString listnames; + MODULE* module = aPcb->m_Modules; - module = aPcb->m_Modules; - - for( ; module != NULL; module = (MODULE*) module->Next() ) + for( ; module; module = module->Next() ) listnames.Add( module->GetReference() ); msg.Printf( _( "Modules [%d items]" ), listnames.GetCount() ); wxArrayString headers; + headers.Add( _( "Module" ) ); + std::vector itemsToDisplay; // Conversion from wxArrayString to vector of ArrayString for( unsigned i = 0; i < listnames.GetCount(); i++ ) { wxArrayString item; + item.Add( listnames[i] ); itemsToDisplay.push_back( item ); } @@ -656,17 +695,17 @@ MODULE* FOOTPRINT_EDIT_FRAME::SelectFootprint( BOARD* aPcb ) EDA_LIST_DIALOG dlg( this, msg, headers, itemsToDisplay, wxEmptyString, NULL, SORT_LIST ); if( dlg.ShowModal() == wxID_OK ) - CmpName = dlg.GetTextSelection(); + fpname = dlg.GetTextSelection(); else return NULL; - OldName = CmpName; + oldName = fpname; module = aPcb->m_Modules; - for( ; module != NULL; module = (MODULE*) module->Next() ) + for( ; module; module = module->Next() ) { - if( CmpName == module->GetReference() ) + if( fpname == module->GetReference() ) break; } diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index 37fc32f77f..25c24e1e5a 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -249,7 +249,22 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_MODEDIT_SELECT_CURRENT_LIB: - Select_Active_Library(); + { + wxString library = SelectLibrary( getLibNickName() ); + + if( library.size() ) + { +#if defined(USE_FP_LIB_TABLE) + setLibNickName( library ); +#else + wxFileName fileName( library ); + + setLibNickName( fileName.GetName() ); + setLibPath( fileName.GetFullPath() ); +#endif + updateTitle(); + } + } break; case ID_OPEN_MODULE_VIEWER: @@ -282,29 +297,29 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_MODEDIT_NEW_MODULE: + { + Clear_Pcb( true ); + GetScreen()->ClearUndoRedoList(); + SetCurItem( NULL ); + SetCrossHairPosition( wxPoint( 0, 0 ) ); + + MODULE* module = Create_1_Module( wxEmptyString ); + + if( module ) // i.e. if create module command not aborted { - Clear_Pcb( true ); - GetScreen()->ClearUndoRedoList(); - SetCurItem( NULL ); - SetCrossHairPosition( wxPoint( 0, 0 ) ); + // Initialize data relative to nets and netclasses (for a new + // module the defaults are used) + // This is mandatory to handle and draw pads + GetBoard()->BuildListOfNets(); + redraw = true; + module->SetPosition( wxPoint( 0, 0 ) ); - MODULE* module = Create_1_Module( wxEmptyString ); + if( GetBoard()->m_Modules ) + GetBoard()->m_Modules->ClearFlags(); - if( module ) // i.e. if create module command not aborted - { - // Initialize data relative to nets and netclasses (for a new - // module the defaults are used) - // This is mandatory to handle and draw pads - GetBoard()->BuildListOfNets(); - redraw = true; - module->SetPosition( wxPoint( 0, 0 ) ); - - if( GetBoard()->m_Modules ) - GetBoard()->m_Modules->ClearFlags(); - - Zoom_Automatique( false ); - } + Zoom_Automatique( false ); } + } break; case ID_MODEDIT_NEW_MODULE_FROM_WIZARD: @@ -349,11 +364,19 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_MODEDIT_SAVE_LIBMODULE: +#if defined(USE_FP_LIB_TABLE) + if( GetBoard()->m_Modules && getLibNickName().size() ) + { + Save_Module_In_Library( getLibNickName(), GetBoard()->m_Modules, true, true ); + GetScreen()->ClrModify(); + } +#else if( GetBoard()->m_Modules && getLibPath() != wxEmptyString ) { Save_Module_In_Library( getLibPath(), GetBoard()->m_Modules, true, true ); GetScreen()->ClrModify(); } +#endif break; case ID_MODEDIT_INSERT_MODULE_IN_BOARD: diff --git a/pcbnew/modedit_undo_redo.cpp b/pcbnew/modedit_undo_redo.cpp index 5e1fc518cc..4f273eb3c7 100644 --- a/pcbnew/modedit_undo_redo.cpp +++ b/pcbnew/modedit_undo_redo.cpp @@ -30,10 +30,17 @@ void FOOTPRINT_EDIT_FRAME::SaveCopyInUndoList( BOARD_ITEM* aItem, lastcmd->PushItem( wrapper ); GetScreen()->PushCommandToUndoList( lastcmd ); + /* Clear current flags (which can be temporary set by a current edit command) */ for( item = CopyItem->GraphicalItems(); item != NULL; item = item->Next() ) item->ClearFlags(); + for( D_PAD* pad = CopyItem->Pads(); pad; pad = pad->Next() ) + pad->ClearFlags(); + + CopyItem->Reference().ClearFlags(); + CopyItem->Value().ClearFlags(); + /* Clear redo list, because after new save there is no redo to do */ GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); } diff --git a/pcbnew/module_editor_frame.h b/pcbnew/module_editor_frame.h index d022c55a2a..01e9a304ca 100644 --- a/pcbnew/module_editor_frame.h +++ b/pcbnew/module_editor_frame.h @@ -401,8 +401,6 @@ public: */ bool DeleteModuleFromCurrentLibrary(); - void Select_Active_Library(); - virtual EDA_COLOR_T GetGridColor( void ) const; DECLARE_EVENT_TABLE() @@ -432,13 +430,11 @@ protected: */ void updateTitle(); - wxString m_lib_nick_name; - /// The library nickName is a short string, for now the same as the library path /// but without path and without extension. After library table support it becomes /// a lookup key. - wxString getLibNickName() const { return m_lib_nick_name; } - void setLibNickName( const wxString& aLibNickName ) { m_lib_nick_name = aLibNickName; } + const wxString& getLibNickName() const; + void setLibNickName( const wxString& aNickname ); #if !defined(USE_FP_LIB_TABLE) diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index 25bb6a03a2..31cb657ea5 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -255,12 +255,28 @@ FOOTPRINT_EDIT_FRAME::~FOOTPRINT_EDIT_FRAME() m_Pcb = 0; } -#if defined(USE_FP_LIB_TABLE) + +const wxString& FOOTPRINT_EDIT_FRAME::getLibNickName() const +{ + return wxGetApp().GetModuleLibraryNickname(); +} + + +void FOOTPRINT_EDIT_FRAME::setLibNickName( const wxString& aNickname ) +{ + wxGetApp().SetModuleLibraryNickname( aNickname ); +} + + +#if 1 && defined(USE_FP_LIB_TABLE) wxString FOOTPRINT_EDIT_FRAME::getLibPath() { try { - const FP_LIB_TABLE::ROW* row = GetFootprintLibraryTable()->FindRow( m_lib_nick_name ); + const wxString& nickname = getLibNickName(); + + const FP_LIB_TABLE::ROW* row = GetFootprintLibraryTable()->FindRow( nickname ); + return row->GetFullURI( true ); } catch( IO_ERROR ioe ) @@ -347,9 +363,15 @@ void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) case wxID_YES: // code from FOOTPRINT_EDIT_FRAME::Process_Special_Functions, // at case ID_MODEDIT_SAVE_LIBMODULE +#if defined(USE_FP_LIB_TABLE) + if( GetBoard()->m_Modules && getLibNickName().size() ) + { + if( Save_Module_In_Library( getLibNickName(), GetBoard()->m_Modules, true, true ) ) +#else if( GetBoard()->m_Modules && getLibPath() != wxEmptyString ) { if( Save_Module_In_Library( getLibPath(), GetBoard()->m_Modules, true, true ) ) +#endif { // save was correct GetScreen()->ClrModify(); @@ -600,6 +622,8 @@ void FOOTPRINT_EDIT_FRAME::OnModify() void FOOTPRINT_EDIT_FRAME::updateTitle() { wxString title = _( "Module Editor " ); + +#if !defined(USE_FP_LIB_TABLE) wxString libPath = getLibPath(); if( !libPath ) @@ -633,5 +657,36 @@ void FOOTPRINT_EDIT_FRAME::updateTitle() } } +#else + + wxString nickname = getLibNickName(); + + if( !nickname ) + { + L_none: + title += _( "(no active library)" ); + } + else + { + try + { + bool writable = m_footprintLibTable->IsFootprintLibWritable( nickname ); + + // no exception was thrown, this means libPath is valid, but it may be read only. + title = _( "Module Editor (active library: " ) + nickname + wxT( ")" ); + + if( !writable ) + title += _( " [Read Only]" ); + } + catch( IO_ERROR ioe ) + { + // user may be bewildered as to why after selecting a library it is not showing up + // in the title, we could show an error message, but that should have been done at time + // of libary selection UI. + goto L_none; + } + } +#endif + SetTitle( title ); } diff --git a/pcbnew/muonde.cpp b/pcbnew/muonde.cpp index 39e9f6c90e..723fba11da 100644 --- a/pcbnew/muonde.cpp +++ b/pcbnew/muonde.cpp @@ -791,7 +791,8 @@ END_EVENT_TABLE() WinEDA_SetParamShapeFrame::WinEDA_SetParamShapeFrame( PCB_EDIT_FRAME* parent, const wxPoint& framepos ) : - wxDialog( parent, -1, _( "Complex shape" ), framepos, wxSize( 350, 280 ), DIALOG_STYLE ) + wxDialog( parent, -1, _( "Complex shape" ), framepos, wxSize( 350, 280 ), + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) { m_Parent = parent; diff --git a/pcbnew/netlist.cpp b/pcbnew/netlist.cpp index eaf9cd16c1..54855d33f2 100644 --- a/pcbnew/netlist.cpp +++ b/pcbnew/netlist.cpp @@ -119,8 +119,6 @@ void PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFileName, MODULE* PCB_EDIT_FRAME::ListAndSelectModuleName() { - MODULE* Module; - if( GetBoard()->m_Modules == NULL ) { DisplayError( this, _( "No Modules" ) ); @@ -128,10 +126,11 @@ MODULE* PCB_EDIT_FRAME::ListAndSelectModuleName() } wxArrayString listnames; - Module = (MODULE*) GetBoard()->m_Modules; - for( ; Module != NULL; Module = (MODULE*) Module->Next() ) - listnames.Add( Module->GetReference() ); + MODULE* module; + + for( module = GetBoard()->m_Modules; module; module = module->Next() ) + listnames.Add( module->GetReference() ); wxArrayString headers; headers.Add( wxT( "Module" ) ); @@ -151,15 +150,14 @@ MODULE* PCB_EDIT_FRAME::ListAndSelectModuleName() return NULL; wxString ref = dlg.GetTextSelection(); - Module = (MODULE*) GetBoard()->m_Modules; - for( ; Module != NULL; Module = Module->Next() ) + for( module = GetBoard()->m_Modules; module; module = module->Next() ) { - if( Module->GetReference() == ref ) + if( module->GetReference() == ref ) break; } - return Module; + return module; } diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index 1923608adb..37d53b3795 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -386,25 +386,26 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu ) { wxMenu* commands = new wxMenu; AddMenuItem( aPopMenu, commands, ID_POPUP_PCB_AUTOPLACE_COMMANDS, - _( "Global Move and Place" ), KiBitmap( move_xpm ) ); + _( "Global Spread and Place" ), KiBitmap( move_xpm ) ); AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES, - _( "Unlock All Modules" ), KiBitmap( unlocked_xpm ) ); + _( "Unlock All Footprints" ), KiBitmap( unlocked_xpm ) ); AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES, - _( "Lock All Modules" ), KiBitmap( locked_xpm ) ); + _( "Lock All Footprints" ), KiBitmap( locked_xpm ) ); commands->AppendSeparator(); - AddMenuItem( commands, ID_POPUP_PCB_AUTOMOVE_ALL_MODULES, - _( "Move All Modules" ), KiBitmap( move_xpm ) ); - commands->Append( ID_POPUP_PCB_AUTOMOVE_NEW_MODULES, _( "Move New Modules" ) ); + AddMenuItem( commands, ID_POPUP_PCB_SPREAD_ALL_MODULES, + _( "Spread out All Footprints" ), KiBitmap( move_xpm ) ); + commands->Append( ID_POPUP_PCB_SPREAD_NEW_MODULES, + _( "Spread out Footprints not Already on Board" ) ); commands->AppendSeparator(); commands->Append( ID_POPUP_PCB_AUTOPLACE_ALL_MODULES, - _( "Automatically Place All Modules" ) ); + _( "Automatically Place All Footprints" ) ); commands->Append( ID_POPUP_PCB_AUTOPLACE_NEW_MODULES, - _( "Automatically Place New Modules" ) ); + _( "Automatically Place New Footprints" ) ); commands->Append( ID_POPUP_PCB_AUTOPLACE_NEXT_MODULE, - _( "Automatically Place Next Module" ) ); + _( "Automatically Place Next Footprints" ) ); commands->AppendSeparator(); AddMenuItem( commands, ID_POPUP_PCB_REORIENT_ALL_MODULES, - _( "Orient All Modules" ), KiBitmap( rotate_module_pos_xpm ) ); + _( "Orient All Footprints" ), KiBitmap( rotate_module_pos_xpm ) ); aPopMenu->AppendSeparator(); } diff --git a/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.cpp b/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.cpp index c605f42a26..0c7c75c974 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.cpp +++ b/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.cpp @@ -55,19 +55,15 @@ PCAD_PLUGIN::~PCAD_PLUGIN() } -const wxString& PCAD_PLUGIN::PluginName() const +const wxString PCAD_PLUGIN::PluginName() const { - static const wxString name = wxT( "P-Cad" ); - - return name; + return wxT( "P-Cad" ); } -const wxString& PCAD_PLUGIN::GetFileExtension() const +const wxString PCAD_PLUGIN::GetFileExtension() const { - static const wxString extension = wxT( "pcb" ); - - return extension; + return wxT( "pcb" ); } diff --git a/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.h b/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.h index 55949829ff..45ecbd92b4 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.h +++ b/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.h @@ -39,18 +39,19 @@ public: // ------------------------------------------------------- - const wxString& PluginName() const; + const wxString PluginName() const; BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties = NULL ); - const wxString& GetFileExtension() const; + const wxString GetFileExtension() const; // ------------------------------------------------------ PCAD_PLUGIN(); ~PCAD_PLUGIN(); + private: const PROPERTIES* m_props; BOARD* m_board; diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_arc.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_arc.cpp index f69f81534d..0cac7b3db2 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcb_arc.cpp +++ b/pcbnew/pcad2kicadpcb_plugin/pcb_arc.cpp @@ -60,8 +60,8 @@ void PCB_ARC::Parse( XNODE* aNode, XNODE* lNode; double a = 0.0; int r = 0; - int endX; - int endY; + int endX = 0; + int endY = 0; m_PCadLayer = aLayer; m_KiCadLayer = GetKiCadLayer(); diff --git a/pcbnew/pcb_plot_params.cpp b/pcbnew/pcb_plot_params.cpp index 7c4bf15ed3..326c33d056 100644 --- a/pcbnew/pcb_plot_params.cpp +++ b/pcbnew/pcb_plot_params.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 473e0c736b..b6a2a2c2d5 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -1,10 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr - * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 2010 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2013 Wayne Stambaugh + * Copyright (C) 2013 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -119,14 +119,14 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_MENU( wxID_EXIT, PCB_EDIT_FRAME::OnQuit ) // menu Config - - /* Tom's hacks start */ + + /* Tom's hacks start */ EVT_MENU ( ID_SELECTION_TOOL, PCB_EDIT_FRAME::onGenericCommand ) EVT_TOOL ( ID_SELECTION_TOOL, PCB_EDIT_FRAME::onGenericCommand ) EVT_MENU ( ID_PNS_ROUTER_TOOL, PCB_EDIT_FRAME::onGenericCommand ) EVT_TOOL ( ID_PNS_ROUTER_TOOL, PCB_EDIT_FRAME::onGenericCommand ) /* Tom's hacks end */ - + EVT_MENU( ID_PCB_DRAWINGS_WIDTHS_SETUP, PCB_EDIT_FRAME::OnConfigurePcbOptions ) EVT_MENU( ID_CONFIG_REQ, PCB_EDIT_FRAME::Process_Config ) EVT_MENU( ID_PCB_LIB_TABLE_EDIT, PCB_EDIT_FRAME::Process_Config ) @@ -237,7 +237,7 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) PCB_EDIT_FRAME::ProcessMuWaveFunctions ) EVT_MENU_RANGE( ID_POPUP_PCB_AUTOPLACE_START_RANGE, ID_POPUP_PCB_AUTOPLACE_END_RANGE, - PCB_EDIT_FRAME::AutoPlace ) + PCB_EDIT_FRAME::OnPlaceOrRouteFootprints ) EVT_MENU( ID_POPUP_PCB_REORIENT_ALL_MODULES, PCB_EDIT_FRAME::OnOrientFootprints ) @@ -598,6 +598,10 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) SaveSettings(); + // Delete board structs and undo/redo lists, to avoid crash on exit + // when deleting some structs (mainly in undo/redo lists) too late + Clear_Pcb( false ); + // do not show the window because ScreenPcb will be deleted and we do not // want any paint event Show( false ); diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index 4534b9d18c..1a03a3764c 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -216,8 +216,8 @@ enum pcbnew_ids ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES, ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES, ID_POPUP_PCB_AUTOPLACE_CURRENT_MODULE, - ID_POPUP_PCB_AUTOMOVE_ALL_MODULES, - ID_POPUP_PCB_AUTOMOVE_NEW_MODULES, + ID_POPUP_PCB_SPREAD_ALL_MODULES, + ID_POPUP_PCB_SPREAD_NEW_MODULES, ID_POPUP_PCB_AUTOPLACE_COMMANDS, ID_POPUP_PCB_AUTOPLACE_ALL_MODULES, ID_POPUP_PCB_AUTOPLACE_NEW_MODULES, diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 1922a20091..e9272f1ca8 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -477,20 +477,18 @@ void BRDITEMS_PLOTTER::PlotTextePcb( TEXTE_PCB* pt_texte ) if( pt_texte->IsMultilineAllowed() ) { + std::vector positions; wxArrayString* list = wxStringSplit( pt_texte->GetText(), '\n' ); - wxPoint offset; + positions.reserve( list->Count() ); - offset.y = pt_texte->GetInterline(); + pt_texte->GetPositionsOfLinesOfMultilineText( positions, list->Count() ); - RotatePoint( &offset, orient ); - - for( unsigned i = 0; i < list->Count(); i++ ) + for( unsigned ii = 0; ii < list->Count(); ii++ ) { - wxString txt = list->Item( i ); - m_plotter->Text( pos, UNSPECIFIED_COLOR, txt, orient, size, + wxString& txt = list->Item( ii ); + m_plotter->Text( positions[ii], UNSPECIFIED_COLOR, txt, orient, size, pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(), thickness, pt_texte->IsItalic(), allow_bold ); - pos += offset; } delete list; diff --git a/pcbnew/plugin.cpp b/pcbnew/plugin.cpp index 0e19cd1289..65e032cd95 100644 --- a/pcbnew/plugin.cpp +++ b/pcbnew/plugin.cpp @@ -112,9 +112,10 @@ bool PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath ) void PLUGIN::FootprintLibOptions( PROPERTIES* aListToAppendTo ) const { + // disable all these in another couple of months, after everyone has seen them: #if 1 (*aListToAppendTo)["debug_level"] = wxString( _( - "Enable debug logging for Footprint*() functions in this PLUGIN." + "Enable debug logging for Footprint*() functions in this PLUGIN." )).utf8_str(); (*aListToAppendTo)["read_filter_regex"] = wxString( _( @@ -125,6 +126,14 @@ void PLUGIN::FootprintLibOptions( PROPERTIES* aListToAppendTo ) const "Enable transaction logging. The mere presence of this option turns on the " " logging, no need to set a Value." )).utf8_str(); + + (*aListToAppendTo)["username"] = wxString( _( + "User name for login to some special library server." + )).utf8_str(); + + (*aListToAppendTo)["password"] = wxString( _( + "Password for login to some special library server." + )).utf8_str(); #endif #if 1 diff --git a/pcbnew/printout_controler.cpp b/pcbnew/printout_controler.cpp index 755142e107..7be6b40d3c 100644 --- a/pcbnew/printout_controler.cpp +++ b/pcbnew/printout_controler.cpp @@ -327,7 +327,7 @@ void BOARD_PRINTOUT_CONTROLLER::DrawPage() wxLogTrace( tracePrinting, wxT( "Logical origin: x=%d, y=%d" ), offset.x, offset.y ); -#if defined(wxUSE_LOG_TRACE) +#if defined(wxUSE_LOG_TRACE) && defined( DEBUG ) wxRect paperRect = GetPaperRectPixels(); wxLogTrace( tracePrinting, wxT( "Paper rectangle: left=%d, top=%d, " "right=%d, bottom=%d" ), diff --git a/pcbnew/protos.h b/pcbnew/protos.h index b469212b7b..5c4fd5e9c1 100644 --- a/pcbnew/protos.h +++ b/pcbnew/protos.h @@ -37,18 +37,6 @@ class BOARD_ITEM; class TRACK; class MODULE; -/** - * Function SwapData - * Used in undo / redo command: - * swap data between Item and a copy - * swapped data is data modified by edition, mainly sizes and texts - * so ONLY FEW values are swapped - * @param aItem = the item - * @param aImage = a copy of the item - */ -void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage ); - - /***************/ /* TRPISTE.CPP */ @@ -72,19 +60,8 @@ void DrawTraces( EDA_DRAW_PANEL* panel, int nbsegment, GR_DRAWMODE mode_color ); -/*************/ -/* MODULES.C */ -/*************/ - void DrawModuleOutlines( EDA_DRAW_PANEL* panel, wxDC* DC, MODULE* module ); - -/****************/ -/* EDITRACK.C : */ -/****************/ - -TRACK* LocateIntrusion( TRACK* listStart, TRACK* aTrack, LAYER_NUM aLayer, const wxPoint& aRef ); - void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ); @@ -94,12 +71,15 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo */ void CalculateSegmentEndPoint( const wxPoint& aPosition, int ox, int oy, int* fx, int* fy ); - -/****************/ -/* CONTROLE.CPP */ -/****************/ void RemoteCommand( const char* cmdline ); + +/** + * Finds the projection of a grid point on a track. This is the point + * from where we want to draw new orthogonal tracks when starting on a track. + */ bool Project( wxPoint* res, wxPoint on_grid, const TRACK* track ); +TRACK* LocateIntrusion( TRACK* listStart, TRACK* aTrack, LAYER_NUM aLayer, const wxPoint& aRef ); + #endif /* #define PROTO_H */ diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index ebde946a93..35677230bd 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -343,11 +343,11 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead ) PNS_LINE* currentLine = lineStack.top(); - prof_start( &totalRealTime, false ); + prof_start( &totalRealTime ); nearest = node->NearestObstacle( currentLine, PNS_ITEM::ANY ); prof_end( &totalRealTime ); - TRACE( 2, "t-nearestObstacle %lld us", (totalRealTime.value ) ); + TRACE( 2, "t-nearestObstacle %lld us", totalRealTime.usecs() ); if( !nearest ) { @@ -362,7 +362,7 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead ) TRACE( 1, "Iter %d optimize-line [range %d-%d, total %d]", iter % r_start % r_end % original->GetCLine().PointCount() ); // lastWalkSolid = NULL; - prof_start( &totalRealTime, false ); + prof_start( &totalRealTime ); if( optimizer.Optimize( original, &optimized ) ) { @@ -376,7 +376,7 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead ) prof_end( &totalRealTime ); - TRACE( 2, "t-optimizeObstacle %lld us", (totalRealTime.value ) ); + TRACE( 2, "t-optimizeObstacle %lld us", totalRealTime.usecs() ); } lineStack.pop(); @@ -393,12 +393,12 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead ) PNS_LINE* collidingLine = node->AssembleLine( pseg ); PNS_LINE* shovedLine = collidingLine->CloneProperties(); - prof_start( &totalRealTime, false ); + prof_start( &totalRealTime ); ShoveStatus st = shoveSingleLine( node, currentLine, collidingLine, *pseg, shovedLine ); prof_end( &totalRealTime ); - TRACE( 2, "t-shoveSingle %lld us", (totalRealTime.value ) ); + TRACE( 2, "t-shoveSingle %lld us", totalRealTime.usecs() ); if( st == SH_OK ) { @@ -441,11 +441,11 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead ) walkaround.SetSolidsOnly( true ); walkaround.SetSingleDirection( true ); - prof_start( &totalRealTime, false ); + prof_start( &totalRealTime ); walkaround.Route( *currentLine, *walkaroundLine, false ); prof_end( &totalRealTime ); - TRACE( 2, "t-walkSolid %lld us", (totalRealTime.value ) ); + TRACE( 2, "t-walkSolid %lld us", totalRealTime.usecs() ); node->Replace( currentLine, walkaroundLine ); diff --git a/pcbnew/swap_layers.cpp b/pcbnew/swap_layers.cpp index 08d8915b16..73d3347efa 100644 --- a/pcbnew/swap_layers.cpp +++ b/pcbnew/swap_layers.cpp @@ -68,7 +68,7 @@ END_EVENT_TABLE() SWAP_LAYERS_DIALOG::SWAP_LAYERS_DIALOG( PCB_BASE_FRAME* parent ) : DIALOG_SHIM( parent, -1, _( "Swap Layers:" ), wxPoint( -1, -1 ), - wxDefaultSize, wxDEFAULT_DIALOG_STYLE | MAYBE_RESIZE_BORDER ) + wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) { BOARD* board = parent->GetBoard(); diff --git a/pcbnew/target_edit.cpp b/pcbnew/target_edit.cpp index ed31e1dfc8..dba25a86d2 100644 --- a/pcbnew/target_edit.cpp +++ b/pcbnew/target_edit.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -100,14 +99,17 @@ TARGET_PROPERTIES_DIALOG_EDITOR::TARGET_PROPERTIES_DIALOG_EDITOR( PCB_EDIT_FRAME // Size: m_staticTextSizeUnits->SetLabel( GetUnitsLabel( g_UserUnit ) ); - m_MireSizeCtrl->SetValue( ReturnStringFromValue( g_UserUnit, m_Target->GetSize() ) ); + m_TargetSizeCtrl->SetValue( ReturnStringFromValue( g_UserUnit, m_Target->GetSize() ) ); // Thickness: m_staticTextThicknessUnits->SetLabel( GetUnitsLabel( g_UserUnit ) ); - m_MireWidthCtrl->SetValue( ReturnStringFromValue( g_UserUnit, m_Target->GetWidth() ) ); + m_TargetThicknessCtrl->SetValue( ReturnStringFromValue( g_UserUnit, m_Target->GetWidth() ) ); // Shape - m_MireShape->SetSelection( m_Target->GetShape() ? 1 : 0 ); + m_TargetShape->SetSelection( m_Target->GetShape() ? 1 : 0 ); + + // OK button on return key. + SetDefaultItem( m_sdbSizerButtsOK ); GetSizer()->Fit( this ); GetSizer()->SetSizeHints( this ); @@ -135,13 +137,13 @@ void TARGET_PROPERTIES_DIALOG_EDITOR::OnOkClick( wxCommandEvent& event ) m_Target->SetFlags( IN_EDIT ); // set flag in edit to force // undo/redo/abort proper operation - int tmp = ReturnValueFromString( g_UserUnit, m_MireWidthCtrl->GetValue() ); + int tmp = ReturnValueFromString( g_UserUnit, m_TargetThicknessCtrl->GetValue() ); m_Target->SetWidth( tmp ); - MireDefaultSize = ReturnValueFromString( g_UserUnit, m_MireSizeCtrl->GetValue() ); + MireDefaultSize = ReturnValueFromString( g_UserUnit, m_TargetSizeCtrl->GetValue() ); m_Target->SetSize( MireDefaultSize ); - m_Target->SetShape( m_MireShape->GetSelection() ? 1 : 0 ); + m_Target->SetShape( m_TargetShape->GetSelection() ? 1 : 0 ); m_Target->Draw( m_Parent->GetCanvas(), m_DC, ( m_Target->IsMoving() ) ? GR_XOR : GR_OR ); @@ -255,9 +257,9 @@ void PCB_EDIT_FRAME::PlaceTarget( PCB_TARGET* aTarget, wxDC* DC ) if( (aTarget->GetFlags() & IN_EDIT) ) { - SwapData( aTarget, &s_TargetCopy ); + aTarget->SwapData( &s_TargetCopy ); SaveCopyInUndoList( aTarget, UR_CHANGED ); - SwapData( aTarget, &s_TargetCopy ); + aTarget->SwapData( &s_TargetCopy ); } aTarget->ClearFlags(); diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 45523ab76a..fbd2aee6f6 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -67,9 +67,6 @@ SELECTION_TOOL::~SELECTION_TOOL() void SELECTION_TOOL::Reset() { - m_selection.group->Clear(); - m_selection.items.clear(); - // Reinsert the VIEW_GROUP, in case it was removed from the VIEW getView()->Remove( m_selection.group ); getView()->Add( m_selection.group ); @@ -81,9 +78,9 @@ void SELECTION_TOOL::Reset() int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) { - BOARD* board = getModel( PCB_T ); - VIEW* view = getView(); - assert( board != NULL ); + VIEW* view = getView(); + + assert( getModel( PCB_T ) != NULL ); view->Add( m_selection.group ); @@ -503,7 +500,7 @@ void SELECTION_TOOL::selectItem( BOARD_ITEM* aItem ) { SELECTION& s; - public: + public: selectBase_( SELECTION& s_ ) : s( s_ ) {} void operator()( BOARD_ITEM* item ) diff --git a/pcbnew/xchgmod.cpp b/pcbnew/xchgmod.cpp index b2cc016880..a267cb8f41 100644 --- a/pcbnew/xchgmod.cpp +++ b/pcbnew/xchgmod.cpp @@ -5,8 +5,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2013 Wayne Stambaugh + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -41,17 +43,14 @@ #include #include -static char* quiet_gcc_4_4_3; // GCC 4.4.3 and next .. - -int s_SelectionMode = 0; // Remember the last exchange option, when exit dialog. - +static bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName ); class DIALOG_EXCHANGE_MODULE : public DIALOG_EXCHANGE_MODULE_BASE { private: - - PCB_EDIT_FRAME* m_Parent; - MODULE* m_CurrentModule; + PCB_EDIT_FRAME* m_parent; + MODULE* m_currentModule; + static int m_selectionMode; // Remember the last exchange option public: DIALOG_EXCHANGE_MODULE( PCB_EDIT_FRAME* aParent, MODULE* aModule ); @@ -62,26 +61,26 @@ private: void OnOkClick( wxCommandEvent& event ); void OnQuit( wxCommandEvent& event ); void BrowseAndSelectFootprint( wxCommandEvent& event ); - void Init(); + void RebuildCmpList( wxCommandEvent& event ); + void init(); - void Change_Current_Module(); - void Change_ModuleId( bool aUseValue ); - void Change_ModuleAll(); - int Maj_ListeCmp( const wxString& reference, const FPID& old_name, - const FPID& new_name, bool ShowError ); - bool Change_1_Module( MODULE* Module, - const FPID& new_module, + void ChangeCurrentFootprint(); + void ChangeSameFootprints( bool aUseValue); + void ChangeAllFootprints(); + bool Change_1_Module( MODULE* aModule, + const FPID& aNewFootprintFPID, PICKED_ITEMS_LIST* aUndoPickList, - bool ShowError ); + bool eShowError ); }; +int DIALOG_EXCHANGE_MODULE::m_selectionMode = 0; DIALOG_EXCHANGE_MODULE::DIALOG_EXCHANGE_MODULE( PCB_EDIT_FRAME* parent, MODULE* Module ) : DIALOG_EXCHANGE_MODULE_BASE( parent ) { - m_Parent = parent; - m_CurrentModule = Module; - Init(); + m_parent = parent; + m_currentModule = Module; + init(); GetSizer()->Fit( this ); GetSizer()->SetSizeHints( this ); } @@ -97,19 +96,19 @@ void PCB_EDIT_FRAME::InstallExchangeModuleFrame( MODULE* Module ) void DIALOG_EXCHANGE_MODULE::OnQuit( wxCommandEvent& event ) { - s_SelectionMode = m_Selection->GetSelection(); + m_selectionMode = m_Selection->GetSelection(); EndModal( 0 ); } -void DIALOG_EXCHANGE_MODULE::Init() +void DIALOG_EXCHANGE_MODULE::init() { SetFocus(); - m_OldModule->AppendText( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) ); - m_NewModule->AppendText( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) ); - m_OldValue->AppendText( m_CurrentModule->GetValue() ); - m_Selection->SetSelection( s_SelectionMode ); + m_OldModule->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) ); + m_NewModule->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) ); + m_OldValue->AppendText( m_currentModule->GetValue() ); + m_Selection->SetSelection( m_selectionMode ); // Enable/disable widgets: wxCommandEvent event; @@ -119,23 +118,24 @@ void DIALOG_EXCHANGE_MODULE::Init() void DIALOG_EXCHANGE_MODULE::OnOkClick( wxCommandEvent& event ) { - s_SelectionMode = m_Selection->GetSelection(); + m_selectionMode = m_Selection->GetSelection(); + switch( m_Selection->GetSelection() ) { case 0: - Change_Current_Module(); + ChangeCurrentFootprint(); break; case 1: - Change_ModuleId( false ); + ChangeSameFootprints( false ); break; case 2: - Change_ModuleId( true ); + ChangeSameFootprints( true ); break; case 3: - Change_ModuleAll(); + ChangeAllFootprints(); break; } } @@ -143,131 +143,61 @@ void DIALOG_EXCHANGE_MODULE::OnOkClick( wxCommandEvent& event ) void DIALOG_EXCHANGE_MODULE::OnSelectionClicked( wxCommandEvent& event ) { + bool enable = true; + switch( m_Selection->GetSelection() ) { case 0: case 1: case 2: - m_NewModule->Enable( true ); - m_Browsebutton->Enable( true ); break; case 3: - m_NewModule->Enable( false ); - m_Browsebutton->Enable( false ); + enable = false; break; } + + m_NewModule->Enable( enable ); + m_Browsebutton->Enable( enable ); } /* - * Updates the file name.CMP (if any) after an exchange module - * (By command changeMod), if the modules are managed by this file - * - * If ShowError! = 0 displays error message if the file. Cmp is not found. - * Return 1 if error + * Rebuild the file name.CMP (if any) after exchanging footprints + * if the footprint are managed by this file + * Return false if error */ -int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference, - const FPID& old_name, - const FPID& new_name, - bool ShowError ) +void DIALOG_EXCHANGE_MODULE::RebuildCmpList( wxCommandEvent& event ) { wxFileName fn; - wxFileName tmpFileName; - FILE* FichCmp, * NewFile; - char line[1024]; wxString msg; - if( old_name == new_name ) - return 0; - // Build CMP file name by changing the extension of NetList filename - fn = m_Parent->GetBoard()->GetFileName(); + fn = m_parent->GetBoard()->GetFileName(); fn.SetExt( ComponentFileExtension ); - FichCmp = wxFopen( fn.GetFullPath(), wxT( "rt" ) ); - - if( FichCmp == NULL ) + if( RecreateCmpFile( m_parent->GetBoard(), fn.GetFullPath() ) ) { - if( ShowError ) - { - msg.Printf( _( "file <%s> not found" ), GetChars( fn.GetFullPath() ) ); - m_WinMessages->AppendText( msg ); - } - - return 1; + msg.Printf( _( "File '%s' created\n" ), + GetChars( fn.GetFullPath() ) ); + } + else + { + msg.Printf( _( "** Could not create file '%s' ***\n" ), + GetChars( fn.GetFullPath() ) ); } - tmpFileName = fn; - tmpFileName.SetExt( wxT( "$$$" ) ); - NewFile = wxFopen( tmpFileName.GetFullPath(), wxT( "wt" ) ); - - if( NewFile == NULL ) - { - if( ShowError ) - { - msg.Printf( _( "Unable to create file <%s>" ), - GetChars( tmpFileName.GetFullPath() ) ); - m_WinMessages->AppendText( msg ); - } - - return 1; - } - - quiet_gcc_4_4_3 = fgets( line, sizeof(line), FichCmp ); - - fprintf( NewFile, "Cmp-Mod V01 Created by PcbNew date = %s\n", TO_UTF8( DateAndTime() ) ); - - bool start_descr = false; - - while( fgets( line, sizeof(line), FichCmp ) != NULL ) - { - if( strnicmp( line, "Reference = ", 9 ) == 0 ) - { - char buf[1024]; - strcpy( buf, line + 12 ); - strtok( buf, ";\n\r" ); - - if( stricmp( buf, TO_UTF8( reference ) ) == 0 ) - { - start_descr = true; - } - } - - if( (strnicmp( line, "Begin", 5 ) == 0) || (strnicmp( line, "End", 3 ) == 0) ) - { - start_descr = false; - } - - if( start_descr && strnicmp( line, "IdModule", 8 ) == 0 ) - { - sprintf( line + 8, " = %s;\n", new_name.Format().c_str() ); - - msg = wxT( " * in <" ) + fn.GetFullPath() + wxT( ">.\n" ); - m_WinMessages->AppendText( msg ); - - start_descr = false; - } - - fputs( line, NewFile ); - } - - fclose( FichCmp ); - fclose( NewFile ); - wxRemoveFile( fn.GetFullPath() ); - wxRenameFile( tmpFileName.GetFullPath(), fn.GetFullPath() ); - return 0; + m_WinMessages->AppendText( msg ); } -/* Change the module at the current cursor position. +/* Change the current footprint at the current cursor position. * Retains the following: - * - Same direction - * - Same position - * - Same text value and ref - * - Same NetNames for pads same name + * - position, orientation and side + * - value and ref + * - pads net names */ -void DIALOG_EXCHANGE_MODULE::Change_Current_Module() +void DIALOG_EXCHANGE_MODULE::ChangeCurrentFootprint() { wxString newmodulename = m_NewModule->GetValue(); @@ -276,31 +206,31 @@ void DIALOG_EXCHANGE_MODULE::Change_Current_Module() PICKED_ITEMS_LIST pickList; - if( Change_1_Module( m_CurrentModule, newmodulename, &pickList, true ) ) + if( Change_1_Module( m_currentModule, newmodulename, &pickList, true ) ) { - if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) - m_Parent->Compile_Ratsnest( NULL, true ); + if( m_parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) + m_parent->Compile_Ratsnest( NULL, true ); - m_Parent->GetCanvas()->Refresh(); + m_parent->GetCanvas()->Refresh(); } if( pickList.GetCount() ) - m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); + m_parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); } /* - * Change of all modules with the same name as that lib + * Change all footprints having the same fpid by a new one from lib * Retains: - * - Same direction - * - Same position - * - Same text value and ref - * - Same NetNames for pads same name - * And replacing the old module with the new module - * Note: m_CurrentModule no longer on the module reference + * - direction, position, side + * - value and ref + * - pads net names + * Note: m_currentModule is no longer the current footprint * since it has been changed! + * if aUseValue is true, footprints having the same fpid should + * also have the same value */ -void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ) +void DIALOG_EXCHANGE_MODULE::ChangeSameFootprints( bool aUseValue ) { wxString msg; MODULE* Module, * PtBack; @@ -311,22 +241,22 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ) bool check_module_value = false; int ShowErr = 3; // Post 3 error messages max. - if( m_Parent->GetBoard()->m_Modules == NULL ) + if( m_parent->GetBoard()->m_Modules == NULL ) return; if( newmodulename == wxEmptyString ) return; - lib_reference = m_CurrentModule->GetFPID(); + lib_reference = m_currentModule->GetFPID(); if( aUseValue ) { check_module_value = true; - value = m_CurrentModule->GetValue(); + value = m_currentModule->GetValue(); msg.Printf( _( "Change modules %s -> %s (for value = %s)?" ), - GetChars( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) ), + GetChars( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) ), GetChars( newmodulename ), - GetChars( m_CurrentModule->GetValue() ) ); + GetChars( m_currentModule->GetValue() ) ); } else { @@ -338,15 +268,15 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ) if( !IsOK( this, msg ) ) return; - /* The change is done from the last module for the routine - * Change_1_Module () modifies the last module in the list. + /* The change is done from the last module because + * Change_1_Module () modifies the last item in the list. */ PICKED_ITEMS_LIST pickList; /* note: for the first module in chain (the last here), Module->Back() * points the board or is NULL */ - Module = m_Parent->GetBoard()->m_Modules.GetLast(); + Module = m_parent->GetBoard()->m_Modules.GetLast(); for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack ) { @@ -369,38 +299,37 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ) if( change ) { - if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) - m_Parent->Compile_Ratsnest( NULL, true ); + if( m_parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) + m_parent->Compile_Ratsnest( NULL, true ); - m_Parent->GetCanvas()->Refresh(); + m_parent->GetCanvas()->Refresh(); } if( pickList.GetCount() ) - m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); + m_parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); } /* * Change all modules with module of the same name in library. * Maintains: - * - Same direction - * - Same position - * - Same text value and ref - * - Same NetNames for pads same name + * - direction, position, side + * - value and ref + * - pads net names */ -void DIALOG_EXCHANGE_MODULE::Change_ModuleAll() +void DIALOG_EXCHANGE_MODULE::ChangeAllFootprints() { MODULE* Module, * PtBack; bool change = false; - int ShowErr = 3; // Post 3 error messages max. + int ShowErr = 3; // Post 3 error max. - if( m_Parent->GetBoard()->m_Modules == NULL ) + if( m_parent->GetBoard()->m_Modules == NULL ) return; if( !IsOK( this, _( "Change ALL modules ?" ) ) ) return; - /* The change is done from the last module for the routine + /* The change is done from the last module because the function * Change_1_Module () modifies the last module in the list */ PICKED_ITEMS_LIST pickList; @@ -408,7 +337,7 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleAll() /* note: for the first module in chain (the last here), Module->Back() * points the board or is NULL */ - Module = m_Parent->GetBoard()->m_Modules.GetLast(); + Module = m_parent->GetBoard()->m_Modules.GetLast(); for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack ) { @@ -422,72 +351,72 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleAll() if( change ) { - if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) - m_Parent->Compile_Ratsnest( NULL, true ); + if( m_parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) + m_parent->Compile_Ratsnest( NULL, true ); - m_Parent->GetCanvas()->Refresh(); + m_parent->GetCanvas()->Refresh(); } if( pickList.GetCount() ) - m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); + m_parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); } /* - * Change the number empr module with the module name new_module - * - Same direction - * - Same position - * - Same text value and ref - * - Same NetNames for pads same name - * Returns: - * False if no change (if the new module is not free) - * True if OK - * Ratsnest must be recalculated after module exchange + * Change aModule to a new, fresh one from lib + * Retains + * - direction, position, side + * - value and ref + * - pads net names + * Returns: false if no change (if the new module is not found) + * true if OK */ -bool DIALOG_EXCHANGE_MODULE::Change_1_Module( MODULE* Module, - const FPID& new_module, +bool DIALOG_EXCHANGE_MODULE::Change_1_Module( MODULE* aModule, + const FPID& aNewFootprintFPID, PICKED_ITEMS_LIST* aUndoPickList, - bool ShowError ) + bool aShowError ) { - FPID namecmp, oldnamecmp; - MODULE* NewModule; + MODULE* newModule; wxString line; - if( Module == NULL ) + if( aModule == NULL ) return false; wxBusyCursor dummy; // Copy parameters from the old module. - oldnamecmp = Module->GetFPID(); - namecmp = new_module; + FPID oldFootprintFPID = aModule->GetFPID(); // Load module. - line.Printf( _( "Change module %s (from %s) " ), - GetChars( Module->GetReference() ), - oldnamecmp.Format().c_str() ); + line.Printf( _( "Change module %s (from %s) to %s" ), + GetChars( aModule->GetReference() ), + oldFootprintFPID.Format().c_str(), + aNewFootprintFPID.Format().c_str() ); m_WinMessages->AppendText( line ); - NewModule = m_Parent->GetModuleLibrary( FROM_UTF8( namecmp.GetLibNickname().c_str() ), - FROM_UTF8( namecmp.GetFootprintName().c_str() ), - ShowError ); + wxString moduleName = FROM_UTF8( aNewFootprintFPID.GetFootprintName().c_str() ); + wxString libName = FROM_UTF8( aNewFootprintFPID.GetLibNickname().c_str() ); - if( NewModule == NULL ) // New module not found, redraw the old one. +#if !defined( USE_FP_LIB_TABLE ) + newModule = m_parent->GetModuleLibrary( libName, moduleName, aShowError ); +#else + newModule = m_parent->LoadFootprint( aNewFootprintFPID ); +#endif + + if( newModule == NULL ) // New module not found, redraw the old one. { - m_WinMessages->AppendText( wxT( "No\n" ) ); + m_WinMessages->AppendText( wxT( " No\n" ) ); return false; } - m_Parent->GetBoard()->Add( NewModule, ADD_APPEND ); + m_parent->GetBoard()->Add( newModule, ADD_APPEND ); - if( Module == m_CurrentModule ) - m_CurrentModule = NewModule; + if( aModule == m_currentModule ) + m_currentModule = newModule; - m_WinMessages->AppendText( wxT( "OK\n" ) ); + m_WinMessages->AppendText( wxT( " OK\n" ) ); - m_Parent->Exchange_Module( Module, NewModule, aUndoPickList ); - - Maj_ListeCmp( NewModule->GetReference(), oldnamecmp, namecmp, ShowError ); + m_parent->Exchange_Module( aModule, newModule, aUndoPickList ); return true; } @@ -497,24 +426,13 @@ void PCB_EDIT_FRAME::Exchange_Module( MODULE* aOldModule, MODULE* aNewModule, PICKED_ITEMS_LIST* aUndoPickList ) { - wxPoint oldpos; - D_PAD* pad, * old_pad; - - if( ( aOldModule->Type() != PCB_MODULE_T ) || ( aNewModule->Type() != PCB_MODULE_T ) ) - { - wxMessageBox( wxT( "PCB_EDIT_FRAME::Exchange_Module() StuctType error" ) ); - return; - } - aNewModule->SetParent( GetBoard() ); - GetBoard()->m_Status_Pcb = 0; - oldpos = GetCrossHairPosition(); - SetCrossHairPosition( aOldModule->GetPosition(), false ); - /* place module without ratsnest refresh: this will be made later * when all modules are on board */ + wxPoint oldpos = GetCrossHairPosition(); + SetCrossHairPosition( aOldModule->GetPosition(), false ); PlaceModule( aNewModule, NULL, true ); SetCrossHairPosition( oldpos, false ); @@ -539,13 +457,11 @@ void PCB_EDIT_FRAME::Exchange_Module( MODULE* aOldModule, aNewModule->SetPath( aOldModule->GetPath() ); // Update pad netnames ( when possible) - pad = aNewModule->Pads(); - - for( ; pad != NULL; pad = pad->Next() ) + for( D_PAD* pad = aNewModule->Pads(); pad != NULL; pad = pad->Next() ) { pad->SetNetname( wxEmptyString ); pad->SetNet( 0 ); - old_pad = aOldModule->Pads(); + D_PAD* old_pad = aOldModule->Pads(); for( ; old_pad != NULL; old_pad = old_pad->Next() ) { @@ -583,8 +499,8 @@ void DIALOG_EXCHANGE_MODULE::BrowseAndSelectFootprint( wxCommandEvent& event ) { wxString newname; - newname = m_Parent->SelectFootprint( m_Parent, wxEmptyString, wxEmptyString, wxEmptyString, - m_Parent->GetFootprintLibraryTable() ); + newname = m_parent->SelectFootprint( m_parent, wxEmptyString, wxEmptyString, wxEmptyString, + m_parent->GetFootprintLibraryTable() ); if( newname != wxEmptyString ) m_NewModule->SetValue( newname ); @@ -594,8 +510,6 @@ void DIALOG_EXCHANGE_MODULE::BrowseAndSelectFootprint( wxCommandEvent& event ) void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent ) { wxFileName fn; - FILE* FichCmp; - char line[1024]; MODULE* Module = GetBoard()->m_Modules; wxString msg; wxString wildcard; @@ -620,33 +534,43 @@ void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent ) fn = dlg.GetPath(); - FichCmp = wxFopen( fn.GetFullPath(), wxT( "wt" ) ); - - if( FichCmp == NULL ) + if( ! RecreateCmpFile( GetBoard(), fn.GetFullPath() ) ) { - msg = _( "Unable to create file " ) + fn.GetFullPath(); + msg.Printf( _( "Could not create file '%s'" ), GetChars(fn.GetFullPath() ) ); DisplayError( this, msg ); return; } +} - quiet_gcc_4_4_3 = fgets( line, sizeof(line), FichCmp ); - fprintf( FichCmp, "Cmp-Mod V01 Genere par PcbNew le %s\n", TO_UTF8( DateAndTime() ) ); +bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName ) +{ + FILE* cmpFile; - for( ; Module != NULL; Module = Module->Next() ) + cmpFile = wxFopen( aFullCmpFileName, wxT( "wt" ) ); + + if( cmpFile == NULL ) + return false; + + fprintf( cmpFile, "Cmp-Mod V01 Genere par PcbNew le %s\n", TO_UTF8( DateAndTime() ) ); + + MODULE* module = aBrd->m_Modules; + for( ; module != NULL; module = module->Next() ) { - fprintf( FichCmp, "\nBeginCmp\n" ); - fprintf( FichCmp, "TimeStamp = %8.8lX\n", Module->GetTimeStamp() ); - fprintf( FichCmp, "Path = %s\n", TO_UTF8( Module->GetPath() ) ); - fprintf( FichCmp, "Reference = %s;\n", - !Module->GetReference().IsEmpty() ? - TO_UTF8( Module->GetReference() ) : "[NoRef]" ); - fprintf( FichCmp, "ValeurCmp = %s;\n", - !Module->GetValue().IsEmpty() ? - TO_UTF8( Module->GetValue() ) : "[NoVal]" ); - fprintf( FichCmp, "IdModule = %s;\n", Module->GetFPID().Format().c_str() ); - fprintf( FichCmp, "EndCmp\n" ); + fprintf( cmpFile, "\nBeginCmp\n" ); + fprintf( cmpFile, "TimeStamp = %8.8lX\n", module->GetTimeStamp() ); + fprintf( cmpFile, "Path = %s\n", TO_UTF8( module->GetPath() ) ); + fprintf( cmpFile, "Reference = %s;\n", + !module->GetReference().IsEmpty() ? + TO_UTF8( module->GetReference() ) : "[NoRef]" ); + fprintf( cmpFile, "ValeurCmp = %s;\n", + !module->GetValue().IsEmpty() ? + TO_UTF8( module->GetValue() ) : "[NoVal]" ); + fprintf( cmpFile, "IdModule = %s;\n", module->GetFPID().Format().c_str() ); + fprintf( cmpFile, "EndCmp\n" ); } - fprintf( FichCmp, "\nEndListe\n" ); - fclose( FichCmp ); + fprintf( cmpFile, "\nEndListe\n" ); + fclose( cmpFile ); + + return true; } diff --git a/scripts/kicad-install.sh b/scripts/kicad-install.sh index dcee75d64b..1ceac154cf 100755 --- a/scripts/kicad-install.sh +++ b/scripts/kicad-install.sh @@ -4,8 +4,25 @@ # -> a Red Hat # compatible linux system. # -# The "install_prerequisites" step is the only "distro dependent" one. Could modify -# that step for other linux distros. +# The "install_prerequisites" step is the only "distro dependent" one. That step could be modified +# for other linux distros. +# +# There are 3 package groups in a KiCad install: +# 1) Compiled source code in the form of executable programs. +# 2) User manuals and other documentation typically as *.pdf files. +# 3) a) Schematic parts, b) layout footprints, and c) 3D models for footprints. +# +# To achieve 1) source is checked out from its repo and compiled by this script then executables +# are installed using CMake. +# To achieve 2) documentation is checked out from its repo and installed using CMake. +# TO achieve 3a) and 3c) they are checked out from their repos and installed using CMake. +# To achieve 3b) a global fp-lib-table is put into your home directory which points to +# http://github.com/KiCad. No actual footprints are installed locally, internet access is used +# during program operation to fetch footprints from github as if it was a remote drive in the cloud. +# If you want to install those same KiCad footprints locally, you may run a separate script +# named library-repos-install.sh found in this same directory. That script requires that "git" be on +# your system whereas this script does not. The footprints require some means to download them and +# bzr-git seems not up to the task. wget or curl would also work. # Set where the 3 source trees will go, use a full path @@ -19,6 +36,8 @@ OPTS="$OPTS -DBUILD_GITHUB_PLUGIN=ON" # Python scripting, uncomment to enable #OPTS="$OPTS -DKICAD_SCRIPTING=ON -DKICAD_SCRIPTING_MODULES=ON -DKICAD_SCRIPTING_WXPYTHON=ON" +LIB_REPO=~kicad-testing-committers/kicad/library + usage() { @@ -27,9 +46,10 @@ usage() echo "" echo "./kicad-install.sh " echo " where is one of:" - echo " --install-or-update (does full installation or update.)" - echo " --remove-sources (removes source trees for another attempt.)" - echo " --uninstall-libraries (removes KiCad supplied libraries.)" + echo " --install-or-update (does full installation or update.)" + echo " --remove-sources (removes source trees for another attempt.)" + echo " --uninstall-libraries (removes KiCad supplied libraries.)" + echo " --uninstall-kicad (uninstalls all of KiCad but leaves source trees.)" echo "" echo "example:" echo ' $ ./kicad-install.sh --install-or-update' @@ -63,19 +83,20 @@ install_prerequisites() elif [ "$(expr match "$PM" '.*\(yum\)')" == "yum" ]; then #echo "red hat compatible system" # Note: if you find this list not to be accurate, please submit a patch: - sudo yum install + sudo yum groupinstall "Development Tools" + sudo yum install \ bzr \ bzrtools \ - build-essential \ cmake \ - cmake-curses-gui \ + cmake-gui \ doxygen \ - libbz2-dev \ - libcairo2-dev \ - libglew-dev \ - libssl-dev \ - libwxgtk2.8-dev \ - python-wxgtk2.8 + bzip2-libs \ + bzip2-devel \ + cairo-devel \ + glew-devel \ + openssl-devel \ + wxGTK-devel \ + wxPython else echo echo "Incompatible System. Neither 'yum' nor 'apt-get' found. Not possible to continue." @@ -108,8 +129,6 @@ cmake_uninstall() elif [ ! -e install_manifest.txt ]; then echo echo "Missing file $dir/install_manifest.txt." - echo "Libraries may have already been uinstalled, or were not" - echo 'originally installed with an "uninstall" knowledgable CMakeLists.txt file.' else echo "uninstalling from $dir" sudo make uninstall @@ -144,10 +163,8 @@ install_or_update() cd ../ fi - - echo "step 4) checking out the libraries from launchpad repo..." if [ ! -d "$WORKING_TREES/kicad-lib.bzr" ]; then - bzr checkout lp:~kicad-lib-committers/kicad/library kicad-lib.bzr + bzr checkout "lp:$LIB_REPO" kicad-lib.bzr echo ' kicad-lib checked out.' else cd kicad-lib.bzr @@ -175,7 +192,6 @@ install_or_update() cmake $OPTS ../ else cd build - # Although a "make clean" is sometimes needed, more often than not it slows down the update # more than it is worth. Do it manually if you need to in this directory. # make clean @@ -189,13 +205,7 @@ install_or_update() echo " kicad program files installed." - echo "step 8) as non-root, install user configuration files..." - # install ~/fp-lib-table [and friends] - make install_user_configuration_files - echo " kicad user-configuration files installed." - - - echo "step 9) installing libraries..." + echo "step 8) installing libraries..." cd ../../kicad-lib.bzr rm_build_dir build mkdir build && cd build @@ -204,6 +214,12 @@ install_or_update() echo " kicad-lib installed." + echo "step 9) as non-root, install user configuration files..." + # install ~/fp-lib-table + make install_github_fp-lib-table + echo " kicad user-configuration files installed." + + echo "step 10) installing documentation..." cd ../../kicad-doc.bzr rm_build_dir build @@ -214,6 +230,12 @@ install_or_update() echo echo 'All KiCad "--install-or-update" steps completed, you are up to date.' + + if [ -z "${KIGITHUB}" ]; then + echo "Please set an environment variable by adding:" + echo "export KIGITHUB=https://github.com/KiCad" + echo "to your ~/.bashrc file. Then reboot." + fi } @@ -239,4 +261,20 @@ if [ $# -eq 1 -a "$1" == "--uninstall-libraries" ]; then exit fi + +if [ $# -eq 1 -a "$1" == "--uninstall-kicad" ]; then + cd "$WORKING_TREES/kicad.bzr/build" + cmake_uninstall "$WORKING_TREES/kicad.bzr/build" + + cd "$WORKING_TREES/kicad-lib.bzr/build" + cmake_uninstall "$WORKING_TREES/kicad-lib.bzr/build" + + # this may fail since "uninstall" support is a recent feature of this repo: + cd "$WORKING_TREES/kicad-doc.bzr/build" + cmake_uninstall "$WORKING_TREES/kicad-doc.bzr/build" + + exit +fi + + usage diff --git a/scripts/library-repos-install.sh b/scripts/library-repos-install.sh new file mode 100755 index 0000000000..71b3930f8f --- /dev/null +++ b/scripts/library-repos-install.sh @@ -0,0 +1,168 @@ +#!/bin/bash +# Git KiCad library repos: +# +# The "install_prerequisites" step is the only "distro dependent" one. Could modify +# that step for other linux distros. +# This script requires "git". The package bzr-git is not up to the task. +# The first time you run with option --install-or-update that is the slowest, because +# git clone from github.com is slow. +# After that updates should run faster. + +# There are two reasons why you might want to run this script: +# +# 1) You want to contribute to the KiCad library team maintained libraries and have yet to +# discover or have chosen not to use the COW feature in the Github "Plugin Type". +# +# 2) You want to run with local pretty footprint libraries and not those remotely located +# on https://github.com using Github plugin. After running this script you should be able to +# a) $ cp ~/kicad_sources/library-repos/kicad-library/template/fp-lib-table.for-pretty ~/fp-lib-table +# and then +# b) set your environment variable KISYSMOD to "~/kicad_sources/library-repos" +# before starting pcbnew. This will use the KiCad plugin against the *.pretty dirs in that base dir. + + + +# Set where the library repos will go, use a full path +WORKING_TREES=~/kicad_sources + + +usage() +{ + echo "" + echo " usage:" + echo "" + echo "./library-sources-install.sh " + echo " where is one of:" + echo " --install-or-update (of the library sources.)" + echo " --remove-all-sources (remove all source trees.)" + echo " --install-prerequisites (install command tools needed here, run once first.)" +# echo " --uninstall-libraries (remove KiCad supplied libraries which have been installed.)" + echo "" + echo "example:" + echo ' $ ./library-sources-install.sh --install-or-update' +} + + +install_prerequisites() +{ + # Find a package manager, PM + PM=$( command -v yum || command -v apt-get ) + + # assume all these Debian, Mint, Ubuntu systems have same prerequisites + if [ "$(expr match "$PM" '.*\(apt-get\)')" == "apt-get" ]; then + #echo "debian compatible system" + sudo apt-get install \ + git \ + curl \ + sed + + # assume all yum systems have same prerequisites + elif [ "$(expr match "$PM" '.*\(yum\)')" == "yum" ]; then + #echo "red hat compatible system" + # Note: if you find this list not to be accurate, please submit a patch: + sudo yum install \ + git \ + curl \ + sed + else + echo + echo "Incompatible System. Neither 'yum' nor 'apt-get' found. Not possible to continue." + echo + exit 1 + fi +} + + +rm_build_dir() +{ + local dir="$1" + # this file is often created as root, so remove as root + sudo rm "$dir/install_manifest.txt" 2> /dev/null + rm -rf "$dir" +} + + +cmake_uninstall() +{ + # assume caller set the CWD, and is only telling us about it in $1 + local dir="$1" + + cwd=`pwd` + if [ "$cwd" != "$dir" ]; then + echo "missing dir $dir" + elif [ ! -e install_manifest.txt ]; then + echo + echo "Missing file $dir/install_manifest.txt." + else + echo "uninstalling from $dir" + sudo make uninstall + sudo rm install_manifest.txt + fi +} + + +detect_pretty_repos() +{ + # Use github API to list repos for org KiCad, then subset the JSON reply for only + # *.pretty repos + PRETTY_REPOS=`curl https://api.github.com/orgs/KiCad/repos?per_page=2000 2> /dev/null \ + | grep full_name | grep pretty \ + | sed -r 's:.+ "KiCad/(.+)",:\1:'` + + #echo "PRETTY_REPOS:$PRETTY_REPOS" +} + + +checkout_or_update_libraries() +{ + if [ ! -d "$WORKING_TREES" ]; then + sudo mkdir -p "$WORKING_TREES" + echo " mark $WORKING_TREES as owned by me" + sudo chown -R `whoami` "$WORKING_TREES" + fi + cd $WORKING_TREES + + detect_pretty_repos + + if [ ! -e "$WORKING_TREES/library-repos" ]; then + mkdir -p "$WORKING_TREES/library-repos" + fi + + for repo in kicad-library $PRETTY_REPOS; do + # echo "repo:$repo" + + if [ ! -e "$WORKING_TREES/library-repos/$repo" ]; then + + # Be _sure_ and preserve the directory name, we want extension .pretty not .pretty.git. + # That way those repos can serve as pretty libraries directly if need be. + + echo "installing $WORKING_TREES/library-repos/$repo" + git clone "https://github.com/KiCad/$repo" "$WORKING_TREES/library-repos/$repo" + else + echo "updating $WORKING_TREES/library-repos/$repo" + cd "$WORKING_TREES/library-repos/$repo" + git pull + fi + done +} + + +if [ $# -eq 1 -a "$1" == "--install-or-update" ]; then + checkout_or_update_libraries + exit +fi + + +if [ $# -eq 1 -a "$1" == "--remove-all-sources" ]; then + rm -rf "$WORKING_TREES/library-repos" + exit +fi + + +if [ $# -eq 1 -a "$1" == "--install-prerequisites" ]; then + install_prerequisites + exit +fi + + +usage diff --git a/scripts/make_global_table.sh b/scripts/make_global_table.sh deleted file mode 100755 index d82c1f4368..0000000000 --- a/scripts/make_global_table.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh -# Generate a footprint library table which can serve as a sensible initial -# personal/global table assuming you have all the footprint libraries installed -# from the bazaar library repo. -# Copyright (C) 2007-2011 SoftPLC Corporation, Dick Hollenbeck -# License GPLv2 - -# This program makes the table either in s-expression or CSV format. -# The CSV format can be loaded into a spreadsheet and then from there rows -# can be copied into either of the fp_table_dialog's table editors: -# a) personal/global or b) project - - -# Usage: -# $ make_global_table.sh [--csv] > outputfile - -# Library Type: Legacy for now, Kicad in future -libtype="Legacy" - - -# Get a list of modules currently in the launchpad repo: -mods=`bzr ls -d lp:~kicad-lib-committers/kicad/library modules 2>/dev/null` -#echo "$mods" - -mods=`echo "$mods" | egrep '\.mod$' | sort` -#echo "$mods" - -csv=0 - -if [ $# -gt 0 -a "$1" == "--csv" ]; then - csv=1 -fi - -today=`date --rfc-3339=date` - -if [ $csv -eq 1 ]; then - echo "NICKNAME,TYPE,URI,OPTIONS,DESCR,,FP LIB TABLE: made from KiCad's Bazaar 'library' repository on $today" - echo - - echo "$mods" | while read mod; - do - # base filename w/o extension - bfn=`basename $mod .mod` - - printf '%s,%s,${KISYSMOD}/%s,"",""\n' \ - "$bfn" \ - "$libtype" \ - "$bfn.mod" - done - -else - - echo "# FP LIB TABLE: made from KiCad's Bazaar 'library' repository on $today" - echo "(fp_lib_table" - - echo "$mods" | while read mod; - do - # base filename w/o extension - bfn=`basename $mod .mod` - - printf ' (lib (name %s)(type %s)(uri ${KISYSMOD}/%s)(options "")(descr ""))\n' \ - "$bfn" \ - "$libtype" \ - "$bfn.mod" - done - - echo ")" -fi diff --git a/scripts/test_kicad_plugin.py b/scripts/test_kicad_plugin.py new file mode 100755 index 0000000000..fc2934cebb --- /dev/null +++ b/scripts/test_kicad_plugin.py @@ -0,0 +1,87 @@ +#!/usr/bin/python + +# Test the KiCad plugin regarding some expected features. + +# 1) Build target _pcbnew after enabling scripting in cmake. +# $ make _pcbnew + +# 2) Changed dir to pcbnew +# $ cd pcbnew +# $ pwd +# build/pcbnew + +# 3) Entered following command line, script takes no arguments +# $ PYTHONPATH=. /test_kicad_plugin.py + + +from __future__ import print_function +from pcbnew import * +import sys +import os + + +lib_path1='/tmp/lib1.pretty' +lib_path2='/tmp/lib2.pretty' + + +plugin = IO_MGR.PluginFind( IO_MGR.KICAD ) + +# Expecting "KiCad": +print( "Plugin Type", plugin.PluginName() ) + +try: + plugin.FootprintLibDelete( lib_path1 ) +except: + None # ignore, new may not exist if first run + +try: + plugin.FootprintLibDelete( lib_path2 ) +except: + None # ignore, new may not exist if first run + + +plugin.FootprintLibCreate( lib_path1 ) + +# Verify that the same plugin instance can edge trigger on a lib_path change +# for a FootprintLibCreate() +plugin.FootprintLibCreate( lib_path2 ) + + +board = BOARD() + +# The only way to construct a MODULE is to pass it a BOARD? Yep. +module = MODULE( board ) + +fpid=FPID( 'mine' ) + +module.SetFPID( fpid ) + +plugin.FootprintSave( lib_path2, module ) + +# Verify that the same plugin instance can edge trigger on a lib_path change +# for a FootprintSave() +plugin.FootprintSave( lib_path1, module ) + +# create a disparity between the library's name ("footprint"), +# and the module's internal useless name ("mine"). Module is officially named "footprint" now +# but has (module mine ...) internally: +os.rename( '/tmp/lib2.pretty/mine.kicad_mod', '/tmp/lib2.pretty/footprint.kicad_mod' ) + +footprint=plugin.FootprintLoad( lib_path2, 'footprint' ) + +fpid = footprint.GetFPID() + +# Always after a FootprintLoad() the internal name should match the one used to load it. +print( "internal name should be 'footprint':", fpid.GetFootprintName() ) + +# Verify that the same plugin instance can edge trigger on a lib_path change +# for FootprintLoad() +footprint=plugin.FootprintLoad( lib_path1, 'mine' ) + +fpid = footprint.GetFPID() + +# Always after a FootprintLoad() the internal name should match the one used to load it. +print( "internal name should be 'mine':", fpid.GetFootprintName() ) + +# As of 3-Dec-2013 this test is passed by KICAD_PLUGIN and Wayne is owed an atta boy! + diff --git a/template/CMakeLists.txt b/template/CMakeLists.txt index c352be4184..a804e9ed24 100644 --- a/template/CMakeLists.txt +++ b/template/CMakeLists.txt @@ -1,8 +1,5 @@ install( FILES kicad.pro - fp-lib-table - fp-lib-table.csv - fp-lib-table.for-github gost_landscape.kicad_wks gost_portrait.kicad_wks pagelayout_default.kicad_wks diff --git a/template/fp-lib-table b/template/fp-lib-table deleted file mode 100644 index 46c04c5735..0000000000 --- a/template/fp-lib-table +++ /dev/null @@ -1,76 +0,0 @@ -# FP LIB TABLE: made from KiCad's Bazaar 'library' repository on 2013-06-25 -(fp_lib_table - (lib (name Allegro_ACS754_ACS755_ACS756_HallCurrentSensor_RevA)(type Legacy)(uri ${KISYSMOD}/Allegro_ACS754_ACS755_ACS756_HallCurrentSensor_RevA.mod)(options "")(descr "")) - (lib (name capacitors)(type Legacy)(uri ${KISYSMOD}/capacitors.mod)(options "")(descr "")) - (lib (name Capacitors_SMD_RevA)(type Legacy)(uri ${KISYSMOD}/Capacitors_SMD_RevA.mod)(options "")(descr "")) - (lib (name connect)(type Legacy)(uri ${KISYSMOD}/connect.mod)(options "")(descr "")) - (lib (name connectors_molex_serial_53047-A123)(type Legacy)(uri ${KISYSMOD}/connectors_molex_serial_53047-A123.mod)(options "")(descr "")) - (lib (name Crystals_RevB_20Apr2013)(type Legacy)(uri ${KISYSMOD}/Crystals_RevB_20Apr2013.mod)(options "")(descr "")) - (lib (name DCDC-ACDC-Converter_RevC_20Jul2012)(type Legacy)(uri ${KISYSMOD}/DCDC-ACDC-Converter_RevC_20Jul2012.mod)(options "")(descr "")) - (lib (name Dioden_SMD_RevA_31May2013)(type Legacy)(uri ${KISYSMOD}/Dioden_SMD_RevA_31May2013.mod)(options "")(descr "")) - (lib (name Dioden_ThroughHole_RevC)(type Legacy)(uri ${KISYSMOD}/Dioden_ThroughHole_RevC.mod)(options "")(descr "")) - (lib (name dip_sockets)(type Legacy)(uri ${KISYSMOD}/dip_sockets.mod)(options "")(descr "")) - (lib (name discret)(type Legacy)(uri ${KISYSMOD}/discret.mod)(options "")(descr "")) - (lib (name display)(type Legacy)(uri ${KISYSMOD}/display.mod)(options "")(descr "")) - (lib (name divers)(type Legacy)(uri ${KISYSMOD}/divers.mod)(options "")(descr "")) - (lib (name Elko_ThroughHole_RevB-3_30Dec2011)(type Legacy)(uri ${KISYSMOD}/Elko_ThroughHole_RevB-3_30Dec2011.mod)(options "")(descr "")) - (lib (name EuroBoardoutline_RevC)(type Legacy)(uri ${KISYSMOD}/EuroBoardoutline_RevC.mod)(options "")(descr "")) - (lib (name Fiducials_RevC_04Aug2012)(type Legacy)(uri ${KISYSMOD}/Fiducials_RevC_04Aug2012.mod)(options "")(descr "")) - (lib (name Footprint-Symbols_RevD_28Aug2012)(type Legacy)(uri ${KISYSMOD}/Footprint-Symbols_RevD_28Aug2012.mod)(options "")(descr "")) - (lib (name FuseholderAndFuses_RevD_28Aug2012)(type Legacy)(uri ${KISYSMOD}/FuseholderAndFuses_RevD_28Aug2012.mod)(options "")(descr "")) - (lib (name Heatsinks_RevC)(type Legacy)(uri ${KISYSMOD}/Heatsinks_RevC.mod)(options "")(descr "")) - (lib (name inductors)(type Legacy)(uri ${KISYSMOD}/inductors.mod)(options "")(descr "")) - (lib (name IR-directFET_Packages_RevB)(type Legacy)(uri ${KISYSMOD}/IR-directFET_Packages_RevB.mod)(options "")(descr "")) - (lib (name iut)(type Legacy)(uri ${KISYSMOD}/iut.mod)(options "")(descr "")) - (lib (name Label_RevA_21Mar2011)(type Legacy)(uri ${KISYSMOD}/Label_RevA_21Mar2011.mod)(options "")(descr "")) - (lib (name led)(type Legacy)(uri ${KISYSMOD}/led.mod)(options "")(descr "")) - (lib (name libcms)(type Legacy)(uri ${KISYSMOD}/libcms.mod)(options "")(descr "")) - (lib (name Measurement_Point_RevA)(type Legacy)(uri ${KISYSMOD}/Measurement_Point_RevA.mod)(options "")(descr "")) - (lib (name Measurement-Scala_RevA)(type Legacy)(uri ${KISYSMOD}/Measurement-Scala_RevA.mod)(options "")(descr "")) - (lib (name Mechanical_Socket-Plug_DIN41612-Stuff_RevA)(type Legacy)(uri ${KISYSMOD}/Mechanical_Socket-Plug_DIN41612-Stuff_RevA.mod)(options "")(descr "")) - (lib (name MiniUniversalMate-N-LokSockets_13Aug2012)(type Legacy)(uri ${KISYSMOD}/MiniUniversalMate-N-LokSockets_13Aug2012.mod)(options "")(descr "")) - (lib (name MountingHole_RevA)(type Legacy)(uri ${KISYSMOD}/MountingHole_RevA.mod)(options "")(descr "")) - (lib (name muonde)(type Legacy)(uri ${KISYSMOD}/muonde.mod)(options "")(descr "")) - (lib (name Neosid_Air-Coil_SML_HAMxx31A_HDMxx31A_RevA_25Apr2012)(type Legacy)(uri ${KISYSMOD}/Neosid_Air-Coil_SML_HAMxx31A_HDMxx31A_RevA_25Apr2012.mod)(options "")(descr "")) - (lib (name Neosid_Filter_HF-Coil_25Apr2012)(type Legacy)(uri ${KISYSMOD}/Neosid_Filter_HF-Coil_25Apr2012.mod)(options "")(descr "")) - (lib (name Neosid_Inductor_21Apr2012)(type Legacy)(uri ${KISYSMOD}/Neosid_Inductor_21Apr2012.mod)(options "")(descr "")) - (lib (name NF-Transformer_ETAL_RevA_28Aug2012)(type Legacy)(uri ${KISYSMOD}/NF-Transformer_ETAL_RevA_28Aug2012.mod)(options "")(descr "")) - (lib (name Oddities_RevA_10Mar2011)(type Legacy)(uri ${KISYSMOD}/Oddities_RevA_10Mar2011.mod)(options "")(descr "")) - (lib (name Opto-Devices_RevC_03Oct2012)(type Legacy)(uri ${KISYSMOD}/Opto-Devices_RevC_03Oct2012.mod)(options "")(descr "")) - (lib (name Oscillator-Modul_RevA)(type Legacy)(uri ${KISYSMOD}/Oscillator-Modul_RevA.mod)(options "")(descr "")) - (lib (name Pentawatt_RevB_30Apr2011)(type Legacy)(uri ${KISYSMOD}/Pentawatt_RevB_30Apr2011.mod)(options "")(descr "")) - (lib (name pga_sockets)(type Legacy)(uri ${KISYSMOD}/pga_sockets.mod)(options "")(descr "")) - (lib (name pin_array)(type Legacy)(uri ${KISYSMOD}/pin_array.mod)(options "")(descr "")) - (lib (name Potentiometer_RevB_02Aug2010)(type Legacy)(uri ${KISYSMOD}/Potentiometer_RevB_02Aug2010.mod)(options "")(descr "")) - (lib (name powerint)(type Legacy)(uri ${KISYSMOD}/powerint.mod)(options "")(descr "")) - (lib (name Printtrafo_CHK_RevA_04Aug2010)(type Legacy)(uri ${KISYSMOD}/Printtrafo_CHK_RevA_04Aug2010.mod)(options "")(descr "")) - (lib (name Relay_ThroughHole_RevB)(type Legacy)(uri ${KISYSMOD}/Relay_ThroughHole_RevB.mod)(options "")(descr "")) - (lib (name Resistor_SMD_RevA)(type Legacy)(uri ${KISYSMOD}/Resistor_SMD_RevA.mod)(options "")(descr "")) - (lib (name Resistor_ThroughHole_RevB_22Apr2011)(type Legacy)(uri ${KISYSMOD}/Resistor_ThroughHole_RevB_22Apr2011.mod)(options "")(descr "")) - (lib (name Resistor_Universal-Experimental_RevA)(type Legacy)(uri ${KISYSMOD}/Resistor_Universal-Experimental_RevA.mod)(options "")(descr "")) - (lib (name SI570_SI571_Oscillator_RevA_11Jun2012)(type Legacy)(uri ${KISYSMOD}/SI570_SI571_Oscillator_RevA_11Jun2012.mod)(options "")(descr "")) - (lib (name SIP9_Housing_14Jun2013)(type Legacy)(uri ${KISYSMOD}/SIP9_Housing_14Jun2013.mod)(options "")(descr "")) - (lib (name smd_capacitors)(type Legacy)(uri ${KISYSMOD}/smd_capacitors.mod)(options "")(descr "")) - (lib (name smd_crystal_and_oscillator)(type Legacy)(uri ${KISYSMOD}/smd_crystal_and_oscillator.mod)(options "")(descr "")) - (lib (name smd_resistors)(type Legacy)(uri ${KISYSMOD}/smd_resistors.mod)(options "")(descr "")) - (lib (name smd_soic_packages)(type Legacy)(uri ${KISYSMOD}/smd_soic_packages.mod)(options "")(descr "")) - (lib (name smd_ssop_packages)(type Legacy)(uri ${KISYSMOD}/smd_ssop_packages.mod)(options "")(descr "")) - (lib (name smd_transistors)(type Legacy)(uri ${KISYSMOD}/smd_transistors.mod)(options "")(descr "")) - (lib (name Socket_MOLEX-KK-System)(type Legacy)(uri ${KISYSMOD}/Socket_MOLEX-KK-System.mod)(options "")(descr "")) - (lib (name sockets)(type Legacy)(uri ${KISYSMOD}/sockets.mod)(options "")(descr "")) - (lib (name Socket_WAGO734_RevA)(type Legacy)(uri ${KISYSMOD}/Socket_WAGO734_RevA.mod)(options "")(descr "")) - (lib (name SOT126_SOT32_Housings_RevA_22Oct2012)(type Legacy)(uri ${KISYSMOD}/SOT126_SOT32_Housings_RevA_22Oct2012.mod)(options "")(descr "")) - (lib (name SOT23_SOT143_SOT143R_TSOT6_MK06A_SC70-6_Housing_26Jul2012)(type Legacy)(uri ${KISYSMOD}/SOT23_SOT143_SOT143R_TSOT6_MK06A_SC70-6_Housing_26Jul2012.mod)(options "")(descr "")) - (lib (name SOT89-3_SOT89-5_Housing_RevA_02Sep2012)(type Legacy)(uri ${KISYSMOD}/SOT89-3_SOT89-5_Housing_RevA_02Sep2012.mod)(options "")(descr "")) - (lib (name TerminalBlock_WAGO236-RM5mm_RevA2-cache)(type Legacy)(uri ${KISYSMOD}/TerminalBlock_WAGO236-RM5mm_RevA2-cache.mod)(options "")(descr "")) - (lib (name TO-50_Housings_RevA_21Apr2013)(type Legacy)(uri ${KISYSMOD}/TO-50_Housings_RevA_21Apr2013.mod)(options "")(descr "")) - (lib (name TO-78_Housing_RevA_04Jun2013)(type Legacy)(uri ${KISYSMOD}/TO-78_Housing_RevA_04Jun2013.mod)(options "")(descr "")) - (lib (name TO-92_Housings_06Jun2013)(type Legacy)(uri ${KISYSMOD}/TO-92_Housings_06Jun2013.mod)(options "")(descr "")) - (lib (name TransformerSMPS_ThroughHole_RevA)(type Legacy)(uri ${KISYSMOD}/TransformerSMPS_ThroughHole_RevA.mod)(options "")(descr "")) - (lib (name Transistor_TO-220_RevB_03Sep2012)(type Legacy)(uri ${KISYSMOD}/Transistor_TO-220_RevB_03Sep2012.mod)(options "")(descr "")) - (lib (name Transistor_TO-247_RevC)(type Legacy)(uri ${KISYSMOD}/Transistor_TO-247_RevC.mod)(options "")(descr "")) - (lib (name valves)(type Legacy)(uri ${KISYSMOD}/valves.mod)(options "")(descr "")) - (lib (name VML0806_Housing_Rohm_RevA_26Oct2012)(type Legacy)(uri ${KISYSMOD}/VML0806_Housing_Rohm_RevA_26Oct2012.mod)(options "")(descr "")) - (lib (name WireConnections-Bridges_RevA)(type Legacy)(uri ${KISYSMOD}/WireConnections-Bridges_RevA.mod)(options "")(descr "")) - (lib (name WirePads_RevA_15Jun2010)(type Legacy)(uri ${KISYSMOD}/WirePads_RevA_15Jun2010.mod)(options "")(descr "")) -) diff --git a/template/fp-lib-table.csv b/template/fp-lib-table.csv deleted file mode 100644 index 130d38df5d..0000000000 --- a/template/fp-lib-table.csv +++ /dev/null @@ -1,75 +0,0 @@ -NICKNAME,TYPE,URI,OPTIONS,DESCR,,FP LIB TABLE: made from KiCad's Bazaar 'library' repository on 2013-06-25 - -Allegro_ACS754_ACS755_ACS756_HallCurrentSensor_RevA,Legacy,${KISYSMOD}/Allegro_ACS754_ACS755_ACS756_HallCurrentSensor_RevA.mod,"","" -capacitors,Legacy,${KISYSMOD}/capacitors.mod,"","" -Capacitors_SMD_RevA,Legacy,${KISYSMOD}/Capacitors_SMD_RevA.mod,"","" -connect,Legacy,${KISYSMOD}/connect.mod,"","" -connectors_molex_serial_53047-A123,Legacy,${KISYSMOD}/connectors_molex_serial_53047-A123.mod,"","" -Crystals_RevB_20Apr2013,Legacy,${KISYSMOD}/Crystals_RevB_20Apr2013.mod,"","" -DCDC-ACDC-Converter_RevC_20Jul2012,Legacy,${KISYSMOD}/DCDC-ACDC-Converter_RevC_20Jul2012.mod,"","" -Dioden_SMD_RevA_31May2013,Legacy,${KISYSMOD}/Dioden_SMD_RevA_31May2013.mod,"","" -Dioden_ThroughHole_RevC,Legacy,${KISYSMOD}/Dioden_ThroughHole_RevC.mod,"","" -dip_sockets,Legacy,${KISYSMOD}/dip_sockets.mod,"","" -discret,Legacy,${KISYSMOD}/discret.mod,"","" -display,Legacy,${KISYSMOD}/display.mod,"","" -divers,Legacy,${KISYSMOD}/divers.mod,"","" -Elko_ThroughHole_RevB-3_30Dec2011,Legacy,${KISYSMOD}/Elko_ThroughHole_RevB-3_30Dec2011.mod,"","" -EuroBoardoutline_RevC,Legacy,${KISYSMOD}/EuroBoardoutline_RevC.mod,"","" -Fiducials_RevC_04Aug2012,Legacy,${KISYSMOD}/Fiducials_RevC_04Aug2012.mod,"","" -Footprint-Symbols_RevD_28Aug2012,Legacy,${KISYSMOD}/Footprint-Symbols_RevD_28Aug2012.mod,"","" -FuseholderAndFuses_RevD_28Aug2012,Legacy,${KISYSMOD}/FuseholderAndFuses_RevD_28Aug2012.mod,"","" -Heatsinks_RevC,Legacy,${KISYSMOD}/Heatsinks_RevC.mod,"","" -inductors,Legacy,${KISYSMOD}/inductors.mod,"","" -IR-directFET_Packages_RevB,Legacy,${KISYSMOD}/IR-directFET_Packages_RevB.mod,"","" -iut,Legacy,${KISYSMOD}/iut.mod,"","" -Label_RevA_21Mar2011,Legacy,${KISYSMOD}/Label_RevA_21Mar2011.mod,"","" -led,Legacy,${KISYSMOD}/led.mod,"","" -libcms,Legacy,${KISYSMOD}/libcms.mod,"","" -Measurement_Point_RevA,Legacy,${KISYSMOD}/Measurement_Point_RevA.mod,"","" -Measurement-Scala_RevA,Legacy,${KISYSMOD}/Measurement-Scala_RevA.mod,"","" -Mechanical_Socket-Plug_DIN41612-Stuff_RevA,Legacy,${KISYSMOD}/Mechanical_Socket-Plug_DIN41612-Stuff_RevA.mod,"","" -MiniUniversalMate-N-LokSockets_13Aug2012,Legacy,${KISYSMOD}/MiniUniversalMate-N-LokSockets_13Aug2012.mod,"","" -MountingHole_RevA,Legacy,${KISYSMOD}/MountingHole_RevA.mod,"","" -muonde,Legacy,${KISYSMOD}/muonde.mod,"","" -Neosid_Air-Coil_SML_HAMxx31A_HDMxx31A_RevA_25Apr2012,Legacy,${KISYSMOD}/Neosid_Air-Coil_SML_HAMxx31A_HDMxx31A_RevA_25Apr2012.mod,"","" -Neosid_Filter_HF-Coil_25Apr2012,Legacy,${KISYSMOD}/Neosid_Filter_HF-Coil_25Apr2012.mod,"","" -Neosid_Inductor_21Apr2012,Legacy,${KISYSMOD}/Neosid_Inductor_21Apr2012.mod,"","" -NF-Transformer_ETAL_RevA_28Aug2012,Legacy,${KISYSMOD}/NF-Transformer_ETAL_RevA_28Aug2012.mod,"","" -Oddities_RevA_10Mar2011,Legacy,${KISYSMOD}/Oddities_RevA_10Mar2011.mod,"","" -Opto-Devices_RevC_03Oct2012,Legacy,${KISYSMOD}/Opto-Devices_RevC_03Oct2012.mod,"","" -Oscillator-Modul_RevA,Legacy,${KISYSMOD}/Oscillator-Modul_RevA.mod,"","" -Pentawatt_RevB_30Apr2011,Legacy,${KISYSMOD}/Pentawatt_RevB_30Apr2011.mod,"","" -pga_sockets,Legacy,${KISYSMOD}/pga_sockets.mod,"","" -pin_array,Legacy,${KISYSMOD}/pin_array.mod,"","" -Potentiometer_RevB_02Aug2010,Legacy,${KISYSMOD}/Potentiometer_RevB_02Aug2010.mod,"","" -powerint,Legacy,${KISYSMOD}/powerint.mod,"","" -Printtrafo_CHK_RevA_04Aug2010,Legacy,${KISYSMOD}/Printtrafo_CHK_RevA_04Aug2010.mod,"","" -Relay_ThroughHole_RevB,Legacy,${KISYSMOD}/Relay_ThroughHole_RevB.mod,"","" -Resistor_SMD_RevA,Legacy,${KISYSMOD}/Resistor_SMD_RevA.mod,"","" -Resistor_ThroughHole_RevB_22Apr2011,Legacy,${KISYSMOD}/Resistor_ThroughHole_RevB_22Apr2011.mod,"","" -Resistor_Universal-Experimental_RevA,Legacy,${KISYSMOD}/Resistor_Universal-Experimental_RevA.mod,"","" -SI570_SI571_Oscillator_RevA_11Jun2012,Legacy,${KISYSMOD}/SI570_SI571_Oscillator_RevA_11Jun2012.mod,"","" -SIP9_Housing_14Jun2013,Legacy,${KISYSMOD}/SIP9_Housing_14Jun2013.mod,"","" -smd_capacitors,Legacy,${KISYSMOD}/smd_capacitors.mod,"","" -smd_crystal_and_oscillator,Legacy,${KISYSMOD}/smd_crystal_and_oscillator.mod,"","" -smd_resistors,Legacy,${KISYSMOD}/smd_resistors.mod,"","" -smd_soic_packages,Legacy,${KISYSMOD}/smd_soic_packages.mod,"","" -smd_ssop_packages,Legacy,${KISYSMOD}/smd_ssop_packages.mod,"","" -smd_transistors,Legacy,${KISYSMOD}/smd_transistors.mod,"","" -Socket_MOLEX-KK-System,Legacy,${KISYSMOD}/Socket_MOLEX-KK-System.mod,"","" -sockets,Legacy,${KISYSMOD}/sockets.mod,"","" -Socket_WAGO734_RevA,Legacy,${KISYSMOD}/Socket_WAGO734_RevA.mod,"","" -SOT126_SOT32_Housings_RevA_22Oct2012,Legacy,${KISYSMOD}/SOT126_SOT32_Housings_RevA_22Oct2012.mod,"","" -SOT23_SOT143_SOT143R_TSOT6_MK06A_SC70-6_Housing_26Jul2012,Legacy,${KISYSMOD}/SOT23_SOT143_SOT143R_TSOT6_MK06A_SC70-6_Housing_26Jul2012.mod,"","" -SOT89-3_SOT89-5_Housing_RevA_02Sep2012,Legacy,${KISYSMOD}/SOT89-3_SOT89-5_Housing_RevA_02Sep2012.mod,"","" -TerminalBlock_WAGO236-RM5mm_RevA2-cache,Legacy,${KISYSMOD}/TerminalBlock_WAGO236-RM5mm_RevA2-cache.mod,"","" -TO-50_Housings_RevA_21Apr2013,Legacy,${KISYSMOD}/TO-50_Housings_RevA_21Apr2013.mod,"","" -TO-78_Housing_RevA_04Jun2013,Legacy,${KISYSMOD}/TO-78_Housing_RevA_04Jun2013.mod,"","" -TO-92_Housings_06Jun2013,Legacy,${KISYSMOD}/TO-92_Housings_06Jun2013.mod,"","" -TransformerSMPS_ThroughHole_RevA,Legacy,${KISYSMOD}/TransformerSMPS_ThroughHole_RevA.mod,"","" -Transistor_TO-220_RevB_03Sep2012,Legacy,${KISYSMOD}/Transistor_TO-220_RevB_03Sep2012.mod,"","" -Transistor_TO-247_RevC,Legacy,${KISYSMOD}/Transistor_TO-247_RevC.mod,"","" -valves,Legacy,${KISYSMOD}/valves.mod,"","" -VML0806_Housing_Rohm_RevA_26Oct2012,Legacy,${KISYSMOD}/VML0806_Housing_Rohm_RevA_26Oct2012.mod,"","" -WireConnections-Bridges_RevA,Legacy,${KISYSMOD}/WireConnections-Bridges_RevA.mod,"","" -WirePads_RevA_15Jun2010,Legacy,${KISYSMOD}/WirePads_RevA_15Jun2010.mod,"","" diff --git a/template/fp-lib-table.for-github b/template/fp-lib-table.for-github deleted file mode 100644 index 2716610fdc..0000000000 --- a/template/fp-lib-table.for-github +++ /dev/null @@ -1,90 +0,0 @@ -# Set GH environment variable to "https://github.com/CarlPoirier" -# before starting KiCad to use this fp table. - -(fp_lib_table - (lib (name 7Segment_16Sep2013)(type Github)(uri ${GH}/7Segment_16Sep2013)(options "")(descr "")) - (lib (name Allegro_HallCurrentSensor)(type Github)(uri ${GH}/Allegro_ACS754_ACS755_ACS756_HallCurrentSensor_RevA)(options "")(descr "")) - (lib (name BNC-Sockets_RevA)(type Github)(uri ${GH}/BNC-Sockets_RevA)(options "")(descr "")) - (lib (name Buzzer_Beeper_RevA_25Oct2010)(type Github)(uri ${GH}/Buzzer_Beeper_RevA_25Oct2010)(options "")(descr "")) - (lib (name capacitors)(type Github)(uri ${GH}/capacitors)(options "")(descr "")) - (lib (name Capacitors_SMD) (type Github)(uri ${GH}/Capacitors_SMD_RevA)(options "")(descr "")) - (lib (name Capacitors_ThroughHole) (type Github)(uri ${GH}/Capacitors_ThroughHole_RevA)(options "")(descr "")) - (lib (name Choke_Axial_ThroughHole) (type Github)(uri ${GH}/Choke_Axial_ThroughHole_RevB)(options "")(descr "")) - (lib (name Choke_Radial_ThroughHole) (type Github)(uri ${GH}/Choke_Radial_ThroughHole_CD_Bobin_RevA)(options "")(descr "")) - (lib (name Choke_SMD_RevB_28Dez2012) (type Github)(uri ${GH}/Choke_SMD_RevB_28Dez2012)(options "")(descr "")) - (lib (name Choke_Toroid_ThroughHole)(type Github)(uri ${GH}/Choke_Toroid_ThroughHole_RevC_06Aug2010)(options "")(descr "")) - (lib (name CommonModeChoke_Wuerth)(type Github)(uri ${GH}/CommonModeChoke_Wuerth_Type-WE-CMB_RevA_24Oct2010)(options "")(descr "")) - (lib (name connect)(type Github)(uri ${GH}/connect)(options "")(descr "")) - (lib (name connectors_molex_serial)(type Github)(uri ${GH}/connectors_molex_serial_53047-A123)(options "")(descr "")) - (lib (name Crystals)(type Github)(uri ${GH}/Crystals_RevB_20Apr2013)(options "")(descr "")) - (lib (name DCDC-ACDC-Converter)(type Github)(uri ${GH}/DCDC-ACDC-Converter_RevC_20Jul2012)(options "")(descr "")) - (lib (name Dioden_SMD)(type Github)(uri ${GH}/Dioden_SMD_RevA_31May2013)(options "")(descr "")) - (lib (name Dioden_ThroughHole)(type Github)(uri ${GH}/Dioden_ThroughHole_RevC)(options "")(descr "")) - (lib (name dip_sockets)(type Github)(uri ${GH}/dip_sockets)(options "")(descr "")) - (lib (name discret)(type Github)(uri ${GH}/discret)(options "")(descr "")) - (lib (name display)(type Github)(uri ${GH}/display)(options "")(descr "")) - (lib (name divers)(type Github)(uri ${GH}/divers)(options "")(descr "")) - (lib (name Elko_ThroughHole)(type Github)(uri ${GH}/Elko_ThroughHole_RevB-3_30Dec2011)(options "")(descr "")) - (lib (name EuroBoardoutline)(type Github)(uri ${GH}/EuroBoardoutline_RevC)(options "")(descr "")) - (lib (name Fiducials)(type Github)(uri ${GH}/Fiducials_RevC_04Aug2012)(options "")(descr "")) - (lib (name Footprint-Symbols)(type Github)(uri ${GH}/Footprint-Symbols_RevD_28Aug2012)(options "")(descr "")) - (lib (name FuseholderAndFuses)(type Github)(uri ${GH}/FuseholderAndFuses_RevD_28Aug2012)(options "")(descr "")) - (lib (name Heatsinks)(type Github)(uri ${GH}/Heatsinks_RevC)(options "")(descr "")) - (lib (name inductors)(type Github)(uri ${GH}/inductors)(options "")(descr "")) - (lib (name IR-directFET)(type Github)(uri ${GH}/IR-directFET_Packages_RevB)(options "")(descr "")) - (lib (name iut)(type Github)(uri ${GH}/iut)(options "")(descr "")) - (lib (name Label)(type Github)(uri ${GH}/Label_RevA_21Mar2011)(options "")(descr "")) - (lib (name led)(type Github)(uri ${GH}/led)(options "")(descr "")) - (lib (name libcms)(type Github)(uri ${GH}/libcms)(options "")(descr "")) - (lib (name Measurement_Point)(type Github)(uri ${GH}/Measurement_Point_RevA)(options "")(descr "")) - (lib (name Measurement-Scala)(type Github)(uri ${GH}/Measurement-Scala_RevA)(options "")(descr "")) - (lib (name Mechanical_Socket-Plug_DIN41612)(type Github)(uri ${GH}/Mechanical_Socket-Plug_DIN41612-Stuff_RevA)(options "")(descr "")) - (lib (name MiniUniversalMate-N-LokSockets)(type Github)(uri ${GH}/MiniUniversalMate-N-LokSockets_13Aug2012)(options "")(descr "")) - (lib (name MountingHole)(type Github)(uri ${GH}/MountingHole_RevA)(options "")(descr "")) - (lib (name muonde)(type Github)(uri ${GH}/muonde)(options "")(descr "")) - (lib (name Neosid_Air-Coil)(type Github)(uri ${GH}/Neosid_Air-Coil_SML_HAMxx31A_HDMxx31A_RevA_25Apr2012)(options "")(descr "")) - (lib (name Neosid_Filter_HF-Coil)(type Github)(uri ${GH}/Neosid_Filter_HF-Coil_25Apr2012)(options "")(descr "")) - (lib (name Neosid_Inductor)(type Github)(uri ${GH}/Neosid_Inductor_21Apr2012)(options "")(descr "")) - (lib (name NF-Transformer_ETAL)(type Github)(uri ${GH}/NF-Transformer_ETAL_RevA_28Aug2012)(options "")(descr "")) - (lib (name Oddities)(type Github)(uri ${GH}/Oddities_RevA_10Mar2011)(options "")(descr "")) - (lib (name OldSowjetAera_Transistor)(type Github)(uri ${GH}/OldSowjetAera_Transistor_RevA)(options "")(descr "")) - (lib (name Opto-Devices)(type Github)(uri ${GH}/Opto-Devices_RevC_03Oct2012)(options "")(descr "")) - (lib (name Oscillator)(type Github)(uri ${GH}/Oscillator-Modul_RevA)(options "")(descr "")) - (lib (name Pentawatt)(type Github)(uri ${GH}/Pentawatt_RevB_30Apr2011)(options "")(descr "")) - (lib (name pga_sockets)(type Github)(uri ${GH}/pga_sockets)(options "")(descr "")) - (lib (name pin_array)(type Github)(uri ${GH}/pin_array)(options "")(descr "")) - (lib (name Potentiometer)(type Github)(uri ${GH}/Potentiometer_RevB_02Aug2010)(options "")(descr "")) - (lib (name powerint)(type Github)(uri ${GH}/powerint)(options "")(descr "")) - (lib (name Printtrafo)(type Github)(uri ${GH}/Printtrafo_CHK_RevA_04Aug2010)(options "")(descr "")) - (lib (name Relay_ThroughHole)(type Github)(uri ${GH}/Relay_ThroughHole_RevB)(options "")(descr "")) - (lib (name Resistor_SMD)(type Github)(uri ${GH}/Resistor_SMD_RevA)(options "")(descr "")) - (lib (name Resistor_ThroughHole)(type Github)(uri ${GH}/Resistor_ThroughHole_RevB_22Apr2011)(options "")(descr "")) - (lib (name Resistor_Universal)(type Github)(uri ${GH}/Resistor_Universal-Experimental_RevA)(options "")(descr "")) - (lib (name SI570_SI571_Oscillator)(type Github)(uri ${GH}/SI570_SI571_Oscillator_RevA_11Jun2012)(options "")(descr "")) - (lib (name SIP9_Housing)(type Github)(uri ${GH}/SIP9_Housing_14Jun2013)(options "")(descr "")) - (lib (name smd_capacitors)(type Github)(uri ${GH}/smd_capacitors)(options "")(descr "")) - (lib (name smd_crystal_and_oscillator)(type Github)(uri ${GH}/smd_crystal_and_oscillator)(options "")(descr "")) - (lib (name smd_lqfp)(type Github)(uri ${GH}/smd_lqfp)(options "")(descr "")) - (lib (name smd_resistors)(type Github)(uri ${GH}/smd_resistors)(options "")(descr "")) - (lib (name smd_soic_packages)(type Github)(uri ${GH}/smd_soic_packages)(options "")(descr "")) - (lib (name smd_ssop_packages)(type Github)(uri ${GH}/smd_ssop_packages)(options "")(descr "")) - (lib (name smd_transistors)(type Github)(uri ${GH}/smd_transistors)(options "")(descr "")) - (lib (name Socket_MOLEX-KK-System)(type Github)(uri ${GH}/Socket_MOLEX-KK-System)(options "")(descr "")) - (lib (name sockets)(type Github)(uri ${GH}/sockets)(options "")(descr "")) - (lib (name Socket_WAGO734)(type Github)(uri ${GH}/Socket_WAGO734_RevA)(options "")(descr "")) - (lib (name SOT126_SOT32)(type Github)(uri ${GH}/SOT126_SOT32_Housings_RevA_22Oct2012)(options "")(descr "")) - (lib (name SOT23_SOT143_SOT143R_TSOT6_MK06A_SC70)(type Github)(uri ${GH}/SOT23_SOT143_SOT143R_TSOT6_MK06A_SC70-6_Housing_26Jul2012)(options "")(descr "")) - (lib (name SOT89-3_SOT89-5)(type Github)(uri ${GH}/SOT89-3_SOT89-5_Housing_RevA_02Sep2012)(options "")(descr "")) - (lib (name TantalCapacitors_SMD)(type Github)(uri ${GH}/TantalCapacitors_SMD_RevA_28Aug2012)(options "")(descr "")) - (lib (name TerminalBlock_WAGO236-RM5mm)(type Github)(uri ${GH}/TerminalBlock_WAGO236-RM5mm_RevA2)(options "")(descr "")) - (lib (name TO-50)(type Github)(uri ${GH}/TO-50_Housings_RevA_21Apr2013)(options "")(descr "")) - (lib (name TO-78)(type Github)(uri ${GH}/TO-78_Housing_RevA_04Jun2013)(options "")(descr "")) - (lib (name TO-92)(type Github)(uri ${GH}/TO-92_Housings_06Jun2013)(options "")(descr "")) - (lib (name TransformerSMPS_ThroughHole)(type Github)(uri ${GH}/TransformerSMPS_ThroughHole_RevA)(options "")(descr "")) - (lib (name Transistor_TO-220)(type Github)(uri ${GH}/Transistor_TO-220_RevB_03Sep2012)(options "")(descr "")) - (lib (name Transistor_TO-247)(type Github)(uri ${GH}/Transistor_TO-247_RevC)(options "")(descr "")) - (lib (name valves)(type Github)(uri ${GH}/valves)(options "")(descr "")) - (lib (name VML0806_Housing_Rohm)(type Github)(uri ${GH}/VML0806_Housing_Rohm_RevA_26Oct2012)(options "")(descr "")) - (lib (name WireConnections-Bridges)(type Github)(uri ${GH}/WireConnections-Bridges_RevA)(options "")(descr "")) - (lib (name WirePads)(type Github)(uri ${GH}/WirePads_RevA_15Jun2010)(options "")(descr "")) -)