From 0ff0b9b835dd3e721dd77b80cd5b59ea4b3e9902 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 May 2014 08:28:40 +0200 Subject: [PATCH 01/68] Fix issue in bga footprint wizard. --- pcbnew/scripting/plugins/PadArray.py | 9 +++++---- pcbnew/scripting/plugins/bga_wizard.py | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pcbnew/scripting/plugins/PadArray.py b/pcbnew/scripting/plugins/PadArray.py index 99fa70e0dc..3c5d5f7cb1 100644 --- a/pcbnew/scripting/plugins/PadArray.py +++ b/pcbnew/scripting/plugins/PadArray.py @@ -75,13 +75,14 @@ class PadGridArray(PadArray): # handy utility function 1 - A, 2 - B, 26 - AA, etc # aIndex = 0 for 0 - A - def AlphaNameFromNumber(self, n, aIndex = 1): + # alphabet = set of allowable chars if not A-Z, eg ABCDEFGHJKLMNPRTUVWY for BGA + def AlphaNameFromNumber(self, n, aIndex = 1, alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"): - div, mod = divmod(n - aIndex, 26) - alpha = chr(65 + mod) + div, mod = divmod(n - aIndex, len(alphabet)) + alpha = alphabet[mod] if div > 0: - return self.AlphaNameFromNumber(div) + alpha; + return self.AlphaNameFromNumber(div, aIndex, alphabet) + alpha; return alpha; diff --git a/pcbnew/scripting/plugins/bga_wizard.py b/pcbnew/scripting/plugins/bga_wizard.py index 7fd6258f3e..9b68b48ef6 100644 --- a/pcbnew/scripting/plugins/bga_wizard.py +++ b/pcbnew/scripting/plugins/bga_wizard.py @@ -24,7 +24,7 @@ import PadArray as PA class BGAPadGridArray(PA.PadGridArray): def NamingFunction(self, x, y): - return "%s%d" % (self.AlphaNameFromNumber(y + 1), x + 1) + return "%s%d" % (self.AlphaNameFromNumber(y + 1, alphabet="ABCDEFGHJKLMNPRTUVWY"), x + 1) class BGAWizard(HFPW.HelpfulFootprintWizardPlugin): @@ -76,10 +76,10 @@ class BGAWizard(HFPW.HelpfulFootprintWizardPlugin): # add in the pads pad = PA.PadMaker(self.module).SMTRoundPad(pads["pad size"]) - pin1Pos = pcbnew.wxPoint(-((rows - 1) * pad_pitch) / 2, - -((cols - 1) * pad_pitch) / 2) + pin1Pos = pcbnew.wxPoint(-((cols - 1) * pad_pitch) / 2, + -((rows - 1) * pad_pitch) / 2) - array = BGAPadGridArray(pad, rows, cols, pad_pitch, pad_pitch, pin1Pos) + array = BGAPadGridArray(pad, cols, rows, pad_pitch, pad_pitch, pin1Pos) array.AddPadsToModule() #box From c698a1da24492d1314cf7e40330f8362192efe75 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 2 May 2014 19:56:24 +0200 Subject: [PATCH 02/68] Eeschema: fix unwanted creation of noname.pro (or other useless config file), when opening eeschema. Fix also an issue when saving the config (from save config menu) which saved the config file in an unknow folder. --- common/project.cpp | 22 ++++++++++++++-------- eeschema/eeschema.cpp | 1 - eeschema/eeschema_config.cpp | 8 ++++---- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/common/project.cpp b/common/project.cpp index df43e60a5e..df31c81c1b 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -60,9 +60,9 @@ void PROJECT::SetProjectFullName( const wxString& aFullPathAndName ) wxASSERT( m_project_name.GetName() == NAMELESS_PROJECT || m_project_name.IsAbsolute() ); #if 0 - wxASSERT( m_project_name.GetExt() == wxT( ".pro" ) ) + wxASSERT( m_project_name.GetExt() == ProjectFileExtension ) #else - m_project_name.SetExt( wxT( ".pro" ) ); + m_project_name.SetExt( ProjectFileExtension ); #endif // until multiple projects are in play, set an environment variable for the @@ -269,19 +269,21 @@ wxConfigBase* PROJECT::configCreate( const SEARCH_STACK& aSList, const wxString& // No suitable pro file was found, either does not exist, or is too old. // Use the template kicad.pro file. Find it by using caller's SEARCH_STACK. - - wxString kicad_pro_template = aSList.FindValidPath( wxT( "kicad.pro" ) ); + wxString templateFile = wxT( "kicad." ) + ProjectFileExtension; + wxString kicad_pro_template = aSList.FindValidPath( templateFile ); if( !kicad_pro_template ) { - wxLogDebug( wxT( "Template file not found using search paths." ) ); + wxLogDebug( wxT( "Template file <%s> not found using search paths." ), + GetChars( templateFile ) ); wxFileName templ( wxStandardPaths::Get().GetDocumentsDir(), wxT( "kicad" ), ProjectFileExtension ); if( !templ.IsFileReadable() ) { - wxString msg = wxString::Format( _( "Unable to find kicad.pro template file." ) ); + wxString msg = wxString::Format( _( "Unable to find %s template config file." ), + GetChars( templateFile ) ); DisplayError( NULL, msg ); @@ -291,8 +293,12 @@ wxConfigBase* PROJECT::configCreate( const SEARCH_STACK& aSList, const wxString& kicad_pro_template = templ.GetFullPath(); } - // copy the template to cur_pro_fn, and open it at that destination. - wxCopyFile( kicad_pro_template, cur_pro_fn ); + // The project config file is not found (happens for new projects, + // or if the schematic editor is run outside an existing project + // In this case the default template (kicad.pro) is used + cur_pro_fn = kicad_pro_template; + wxLogDebug( wxT( "Use template file '%s' as project file." ), GetChars( cur_pro_fn ) ); + cfg = new wxFileConfig( wxEmptyString, wxEmptyString, cur_pro_fn, wxEmptyString ); cfg->DontCreateOnDemand(); diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index fafcd90ac5..c5e1432036 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -40,7 +40,6 @@ #include #include -//#include #include #include #include diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index ee091ae82c..caa3b2782b 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -139,7 +139,7 @@ void LIB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) switch( id ) { case ID_CONFIG_SAVE: - schFrame->SaveProjectSettings( false ); + schFrame->SaveProjectSettings( true ); break; case ID_CONFIG_READ: @@ -205,7 +205,7 @@ void SCH_EDIT_FRAME::Process_Config( wxCommandEvent& event ) switch( id ) { case ID_CONFIG_SAVE: - SaveProjectSettings( false ); + SaveProjectSettings( true ); break; case ID_CONFIG_READ: @@ -456,8 +456,8 @@ void SCH_EDIT_FRAME::SaveProjectSettings( bool aAskForSave ) if( aAskForSave ) { wxFileDialog dlg( this, _( "Save Project File" ), - fn.GetPath(), fn.GetFullName(), - ProjectFileWildcard, wxFD_SAVE | wxFD_CHANGE_DIR ); + fn.GetPath(), fn.GetFullPath(), + ProjectFileWildcard, wxFD_SAVE ); if( dlg.ShowModal() == wxID_CANCEL ) return; From 25d1ab4008a20bc44e011a910783b68d002d09af Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sat, 3 May 2014 12:40:19 -0500 Subject: [PATCH 03/68] Modular-Kicad milestone B), major portions: *) Rework the set language support, simplify it by using KIWAY. Now any major frame with a "change language" menu can change the language for all KIWAY_PLAYERs in the whole KIWAY. Multiple KIWAYs are not supported yet. *) Simplify "modal wxFrame" support, and add that support exclusively to KIWAY_PLAYER where it is inherited by all derivatives. The function KIWAY_PLAYER::ShowModal() is in the vtable and so is cross module capable. *) Remove the requirements and assumptions that the wxFrame hierarchy always had PCB_EDIT_FRAME and SCH_EDIT_FRAME as immediate parents of their viewers and editors. This is no longer the case, nor required. *) Use KIWAY::Player() everywhere to make KIWAY_PLAYERs, this registers the KIWAY_PLAYER within the KIWAY and makes it very easy to find an open frame quickly. It also gives control to the KIWAY as to frame hierarchical relationships. *) Change single_top to use the KIWAY for loading a KIFACE and instantiating the single KIWAY_PLAYER, see bullet immediately above. *) Add KIWAY::OnKiwayEnd() and call it from PGM_BASE at program termination, this gives the KIFACEs a chance to save their final configuration dope to disk. *) Add dedicated FRAME_T's for the modal frames, so m_Ident can be tested and these modal frames are distinctly different than their non-modal equivalents. KIWAY_PLAYER::IsModal() is !not! a valid test during the wxFrame's constructor, so this is another important reason for having a dedicated FRAME_T for each modal wxFrame. On balance, more lines were deleted than were added to achieve all this. --- bitmap2component/CMakeLists.txt | 2 +- common/basicframe.cpp | 30 +---- common/colors.cpp | 1 + common/draw_frame.cpp | 6 - common/fpid.cpp | 41 +++---- common/kiway.cpp | 99 +++++++++++++--- common/kiway_player.cpp | 148 +++++++++++++++++++++--- common/pgm_base.cpp | 2 +- common/single_top.cpp | 128 +++----------------- cvpcb/cvframe.cpp | 8 -- cvpcb/cvpcb_mainframe.h | 6 - eeschema/block_libedit.cpp | 2 +- eeschema/eeschema.cpp | 10 ++ eeschema/eeschema_config.cpp | 31 ++--- eeschema/getpart.cpp | 24 ++-- eeschema/libeditframe.cpp | 74 +++++------- eeschema/libeditframe.h | 13 --- eeschema/sch_base_frame.cpp | 9 +- eeschema/schedit.cpp | 2 +- eeschema/schframe.cpp | 51 ++++---- eeschema/sheet.cpp | 2 +- eeschema/tool_viewlib.cpp | 4 +- eeschema/viewlib_frame.cpp | 113 +++++++++--------- eeschema/viewlib_frame.h | 27 ++--- gerbview/events_called_functions.cpp | 41 +++---- gerbview/gerbview_frame.h | 6 +- include/draw_frame.h | 7 -- include/fpid.h | 20 ++-- include/frame_type.h | 23 +++- include/kiface_i.h | 2 +- include/kiway.h | 59 +++++++--- include/kiway_player.h | 57 ++++++++- include/wxEeschemaStruct.h | 6 - include/wxPcbStruct.h | 6 +- include/wxstruct.h | 23 +--- kicad/kicad.cpp | 4 +- kicad/kicad.h | 3 +- kicad/mainframe.cpp | 8 ++ kicad/menubar.cpp | 19 +-- kicad/preferences.cpp | 5 - pagelayout_editor/events_functions.cpp | 17 +-- pagelayout_editor/pl_editor_frame.h | 6 - pcb_calculator/CMakeLists.txt | 3 +- pcb_calculator/pcb_calculator_frame.cpp | 1 + pcbnew/block_module_editor.cpp | 2 +- pcbnew/edit.cpp | 28 ++--- pcbnew/editmod.cpp | 12 +- pcbnew/footprint_wizard.cpp | 2 +- pcbnew/footprint_wizard_frame.cpp | 58 +++------- pcbnew/footprint_wizard_frame.h | 28 ++--- pcbnew/gpcb_plugin.cpp | 3 +- pcbnew/kicad_plugin.cpp | 6 +- pcbnew/librairi.cpp | 2 +- pcbnew/loadcmp.cpp | 27 ++--- pcbnew/modedit.cpp | 70 +++++------ pcbnew/module_editor_frame.h | 13 +-- pcbnew/moduleframe.cpp | 15 +-- pcbnew/modview_frame.cpp | 116 +++++++++---------- pcbnew/modview_frame.h | 42 +++---- pcbnew/pcbframe.cpp | 12 +- pcbnew/pcbnew.cpp | 25 ++-- pcbnew/pcbnew_config.cpp | 2 +- pcbnew/tool_modview.cpp | 5 +- 63 files changed, 769 insertions(+), 848 deletions(-) diff --git a/bitmap2component/CMakeLists.txt b/bitmap2component/CMakeLists.txt index 5bf7debd48..489ff8f3f1 100644 --- a/bitmap2component/CMakeLists.txt +++ b/bitmap2component/CMakeLists.txt @@ -14,7 +14,7 @@ set( BITMAP2COMPONENT_SRCS ) set_source_files_properties( ../common/single_top.cpp PROPERTIES - COMPILE_DEFINITIONS "TOP_FRAME=0" + COMPILE_DEFINITIONS "TOP_FRAME=FRAME_BM2CMP" ) set_source_files_properties( bitmap2cmp_gui.cpp PROPERTIES COMPILE_DEFINITIONS "COMPILING_DLL" diff --git a/common/basicframe.cpp b/common/basicframe.cpp index 91a5c0b4ee..37be1fd12c 100644 --- a/common/basicframe.cpp +++ b/common/basicframe.cpp @@ -169,12 +169,8 @@ void EDA_BASE_FRAME::ReCreateMenuBar() } -void EDA_BASE_FRAME::SetLanguage( wxCommandEvent& event ) +void EDA_BASE_FRAME::ShowChangedLanguage() { - int id = event.GetId(); - - Pgm().SetLanguageIdentifier( id ); - Pgm().SetLanguage(); ReCreateMenuBar(); GetMenuBar()->Refresh(); } @@ -717,27 +713,3 @@ void EDA_BASE_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName, } } - -void EDA_BASE_FRAME::SetModalMode( bool aModal ) -{ - // Disable all other windows -#if wxCHECK_VERSION(2, 9, 4) - if( IsTopLevel() ) - { - wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); - - while( node ) - { - wxWindow* win = node->GetData(); - - if( win != this ) - win->Enable( !aModal ); - - node = node->GetNext(); - } - } -#else - // Deprecated since wxWidgets 2.9.4 - MakeModal( aModal ); -#endif -} diff --git a/common/colors.cpp b/common/colors.cpp index ca12867b6e..9016840865 100644 --- a/common/colors.cpp +++ b/common/colors.cpp @@ -122,6 +122,7 @@ EDA_COLOR_T ColorMix( EDA_COLOR_T aColor1, EDA_COLOR_T aColor2 ) // First easy thing: a black gives always the other colour if( aColor1 == BLACK ) return aColor2; + if( aColor2 == BLACK) return aColor1; diff --git a/common/draw_frame.cpp b/common/draw_frame.cpp index 75461e5f22..a79503edd3 100644 --- a/common/draw_frame.cpp +++ b/common/draw_frame.cpp @@ -556,12 +556,6 @@ bool EDA_DRAW_FRAME::HandleBlockEnd( wxDC* DC ) } -void EDA_DRAW_FRAME::SetLanguage( wxCommandEvent& event ) -{ - EDA_BASE_FRAME::SetLanguage( event ); -} - - void EDA_DRAW_FRAME::UpdateStatusBar() { wxString Line; diff --git a/common/fpid.cpp b/common/fpid.cpp index ef9f35b89f..025b7b57e4 100644 --- a/common/fpid.cpp +++ b/common/fpid.cpp @@ -62,6 +62,7 @@ const char* EndsWithRev( const char* start, const char* tail, char separator ) } +#if 0 // Not used int RevCmp( const char* s1, const char* s2 ) { int r = strncmp( s1, s2, 3 ); @@ -76,6 +77,7 @@ int RevCmp( const char* s1, const char* s2 ) return -(rnum1 - rnum2); // swap the sign, higher revs first } +#endif //----------------------------------------- @@ -116,7 +118,7 @@ void FPID::clear() } -int FPID::Parse( const std::string& aId ) +int FPID::Parse( const UTF8& aId ) { clear(); @@ -171,12 +173,6 @@ int FPID::Parse( const std::string& aId ) } -int FPID::Parse( const wxString& aId ) -{ - return Parse( std::string( TO_UTF8( aId ) ) ); -} - - FPID::FPID( const std::string& aId ) throw( PARSE_ERROR ) { int offset = Parse( aId ); @@ -194,14 +190,14 @@ FPID::FPID( const std::string& aId ) throw( PARSE_ERROR ) FPID::FPID( const wxString& aId ) throw( PARSE_ERROR ) { - std::string id = TO_UTF8( aId ); + UTF8 id = aId; int offset = Parse( id ); if( offset != -1 ) { THROW_PARSE_ERROR( _( "Illegal character found in FPID string" ), - wxString::FromUTF8( id.c_str() ), + aId, id.c_str(), 0, offset ); @@ -209,7 +205,7 @@ FPID::FPID( const wxString& aId ) throw( PARSE_ERROR ) } -int FPID::SetLibNickname( const std::string& aLogical ) +int FPID::SetLibNickname( const UTF8& aLogical ) { int offset = okLogical( aLogical ); @@ -222,15 +218,9 @@ int FPID::SetLibNickname( const std::string& aLogical ) } -int FPID::SetLibNickname( const wxString& aLogical ) +int FPID::SetFootprintName( const UTF8& aFootprintName ) { - return SetLibNickname( std::string( TO_UTF8( aLogical ) ) ); -} - - -int FPID::SetFootprintName( const std::string& aFootprintName ) -{ - int separation = int( aFootprintName.find_first_of( "/" ) ); + int separation = int( aFootprintName.find_first_of( "/" ) ); if( separation != -1 ) { @@ -246,13 +236,7 @@ int FPID::SetFootprintName( const std::string& aFootprintName ) } -int FPID::SetFootprintName( const wxString& aFootprintName ) -{ - return SetFootprintName( std::string( TO_UTF8( aFootprintName ) ) ); -} - - -int FPID::SetRevision( const std::string& aRevision ) +int FPID::SetRevision( const UTF8& aRevision ) { int offset = okRevision( aRevision ); @@ -301,8 +285,10 @@ UTF8 FPID::GetFootprintNameAndRev() const } -UTF8 FPID::Format( const std::string& aLogicalLib, const std::string& aFootprintName, - const std::string& aRevision ) +#if 0 // this is broken, it does not output aFootprintName for some reason + +UTF8 FPID::Format( const UTF8& aLogicalLib, const UTF8& aFootprintName, + const UTF8& aRevision ) throw( PARSE_ERROR ) { UTF8 ret; @@ -344,6 +330,7 @@ UTF8 FPID::Format( const std::string& aLogicalLib, const std::string& aFootprint return ret; } +#endif int FPID::compare( const FPID& aFPID ) const diff --git a/common/kiway.cpp b/common/kiway.cpp index 13c0072a92..a599474f06 100644 --- a/common/kiway.cpp +++ b/common/kiway.cpp @@ -23,14 +23,16 @@ */ #include +#include +#include #include #include #include #include +#include #include -#include -#include +#include KIFACE* KIWAY::m_kiface[KIWAY_FACE_COUNT]; @@ -38,22 +40,24 @@ int KIWAY::m_kiface_version[KIWAY_FACE_COUNT]; -KIWAY::KIWAY( PGM_BASE* aProgram, wxFrame* aTop ): +KIWAY::KIWAY( PGM_BASE* aProgram, int aCtlBits, wxFrame* aTop ): m_program( aProgram ), + m_ctl( aCtlBits ), m_top( 0 ) { - SetTop( aTop ); // hook playerDestroyHandler() into aTop. + SetTop( aTop ); // hook player_destroy_handler() into aTop. memset( m_player, 0, sizeof( m_player ) ); } + // Any event types derived from wxCommandEvt, like wxWindowDestroyEvent, are // propogated upwards to parent windows if not handled below. Therefor the // m_top window should receive all wxWindowDestroyEvents originating from -// KIWAY_PLAYERs. It does anyways, but now playerDestroyHandler eavesdrops +// KIWAY_PLAYERs. It does anyways, but now player_destroy_handler eavesdrops // on that event stream looking for KIWAY_PLAYERs being closed. -void KIWAY::playerDestroyHandler( wxWindowDestroyEvent& event ) +void KIWAY::player_destroy_handler( wxWindowDestroyEvent& event ) { wxWindow* w = event.GetWindow(); @@ -62,7 +66,7 @@ void KIWAY::playerDestroyHandler( wxWindowDestroyEvent& event ) // if destroying one of our flock, then mark it as deceased. if( (wxWindow*) m_player[i] == w ) { - // DBG(printf( "%s: marking m_player[%d] as destroyed\n", __func__, i );) + DBG(printf( "%s: marking m_player[%d] as destroyed\n", __func__, i );) m_player[i] = 0; } } @@ -73,12 +77,12 @@ void KIWAY::SetTop( wxFrame* aTop ) { if( m_top ) { - m_top->Disconnect( wxEVT_DESTROY, wxWindowDestroyEventHandler( KIWAY::playerDestroyHandler ), NULL, this ); + m_top->Disconnect( wxEVT_DESTROY, wxWindowDestroyEventHandler( KIWAY::player_destroy_handler ), NULL, this ); } if( aTop ) { - aTop->Connect( wxEVT_DESTROY, wxWindowDestroyEventHandler( KIWAY::playerDestroyHandler ), NULL, this ); + aTop->Connect( wxEVT_DESTROY, wxWindowDestroyEventHandler( KIWAY::player_destroy_handler ), NULL, this ); } m_top = aTop; @@ -91,13 +95,13 @@ const wxString KIWAY::dso_full_path( FACE_T aFaceId ) switch( aFaceId ) { - case FACE_SCH: name = KIFACE_PREFIX wxT( "eeschema" ); break; - case FACE_PCB: name = KIFACE_PREFIX wxT( "pcbnew" ); break; - case FACE_CVPCB: name = KIFACE_PREFIX wxT( "cvpcb" ); break; - case FACE_GERBVIEW: name = KIFACE_PREFIX wxT( "gerbview" ); break; - case FACE_PL_EDITOR: name = KIFACE_PREFIX wxT( "pl_editor" ); break; - - // case FACE_PCB_CALCULATOR: who knows. + case FACE_SCH: name = KIFACE_PREFIX wxT( "eeschema" ); break; + case FACE_PCB: name = KIFACE_PREFIX wxT( "pcbnew" ); break; + case FACE_CVPCB: name = KIFACE_PREFIX wxT( "cvpcb" ); break; + case FACE_GERBVIEW: name = KIFACE_PREFIX wxT( "gerbview" ); break; + case FACE_PL_EDITOR: name = KIFACE_PREFIX wxT( "pl_editor" ); break; + case FACE_PCB_CALCULATOR: name = KIFACE_PREFIX wxT( "pcb_calculator" ); break; + case FACE_BMP2CMP: name = KIFACE_PREFIX wxT( "bitmap2component" ); break; default: wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) ); @@ -172,7 +176,7 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad ) // Give the DSO a single chance to do its "process level" initialization. // "Process level" specifically means stay away from any projects in there. - if( kiface->OnKifaceStart( m_program, KFCTL_PROJECT_SUITE ) ) + if( kiface->OnKifaceStart( m_program, m_ctl ) ) { // Tell dso's wxDynamicLibrary destructor not to Unload() the program image. (void) dso.Detach(); @@ -214,12 +218,14 @@ KIWAY::FACE_T KIWAY::KifaceType( FRAME_T aFrameType ) case FRAME_SCH: case FRAME_SCH_LIB_EDITOR: case FRAME_SCH_VIEWER: + case FRAME_SCH_VIEWER_MODAL: return FACE_SCH; case FRAME_PCB: case FRAME_PCB_MODULE_EDITOR: case FRAME_PCB_MODULE_VIEWER: - case FRAME_PCB_FOOTPRINT_WIZARD: + case FRAME_PCB_MODULE_VIEWER_MODAL: + case FRAME_PCB_FOOTPRINT_WIZARD_MODAL: case FRAME_PCB_DISPLAY3D: return FACE_PCB; @@ -233,6 +239,12 @@ KIWAY::FACE_T KIWAY::KifaceType( FRAME_T aFrameType ) case FRAME_PL_EDITOR: return FACE_PL_EDITOR; + case FRAME_CALC: + return FACE_PCB_CALCULATOR; + + case FRAME_BM2CMP: + return FACE_BMP2CMP; + default: return FACE_T( -1 ); } @@ -266,7 +278,12 @@ KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate ) if( kiface ) { - KIWAY_PLAYER* frame = (KIWAY_PLAYER*) kiface->CreateWindow( m_top, aFrameType, this, KFCTL_PROJECT_SUITE ); + KIWAY_PLAYER* frame = (KIWAY_PLAYER*) kiface->CreateWindow( + m_top, + aFrameType, + this, + m_ctl // questionable need, these same flags where passed to the KIFACE::OnKifaceStart() + ); wxASSERT( frame ); return m_player[aFrameType] = frame; @@ -327,6 +344,39 @@ void KIWAY::ExpressMail( FRAME_T aDestination, } +void KIWAY::SetLanguage( int aLanguage ) +{ + Pgm().SetLanguageIdentifier( aLanguage ); + Pgm().SetLanguage(); + +#if 1 + // This is a risky hack that goes away if we allow the language to be + // set only from the top most frame if !Kiface.IsSingle() + + // Only for the C++ project manager, and not for the python one and not for + // single_top do we look for the EDA_BASE_FRAME as the top level window. + // For single_top this is not needed because that window is registered in + // the array below. + if( m_ctl & KFCTL_CPP_PROJECT_SUITE ) + { + EDA_BASE_FRAME* top = (EDA_BASE_FRAME*) m_top; + if( top ) + top->ShowChangedLanguage(); + } +#endif + + for( unsigned i=0; i < DIM( m_player ); ++i ) + { + KIWAY_PLAYER* frame = m_player[i]; + + if( frame ) + { + frame->ShowChangedLanguage(); + } + } +} + + bool KIWAY::ProcessEvent( wxEvent& aEvent ) { KIWAY_EXPRESS* mail = dynamic_cast( &aEvent ); @@ -351,3 +401,14 @@ bool KIWAY::ProcessEvent( wxEvent& aEvent ) return false; } + + +void KIWAY::OnKiwayEnd() +{ + for( unsigned i=0; i < DIM( m_kiface ); ++i ) + { + if( m_kiface[i] ) + m_kiface[i]->OnKifaceEnd(); + } +} + diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp index 427fdf3a51..31aca7d1d8 100644 --- a/common/kiway_player.cpp +++ b/common/kiway_player.cpp @@ -2,28 +2,26 @@ #include #include +#include +#include #include BEGIN_EVENT_TABLE( KIWAY_PLAYER, EDA_BASE_FRAME ) - /* have not been able to get this to work yet: EVT_KIWAY_EXPRESS( KIWAY_PLAYER::kiway_express ) - Use Connect() in constructor until this can be sorted out. - - OK the problem is KIWAY_PLAYER::wxEVENT_ID not being unique accross all link images. - */ + EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KIWAY_PLAYER::language_change ) END_EVENT_TABLE() - KIWAY_PLAYER::KIWAY_PLAYER( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize, long aStyle, const wxString& aWdoName ) : EDA_BASE_FRAME( aParent, aFrameType, aTitle, aPos, aSize, aStyle, aWdoName ), - KIWAY_HOLDER( aKiway ) + KIWAY_HOLDER( aKiway ), + m_modal_dismissed( 0 ) { DBG( printf("KIWAY_EXPRESS::wxEVENT_ID:%d\n", KIWAY_EXPRESS::wxEVENT_ID );) - Connect( KIWAY_EXPRESS::wxEVENT_ID, wxKiwayExressHandler( KIWAY_PLAYER::kiway_express ) ); + //Connect( KIWAY_EXPRESS::wxEVENT_ID, wxKiwayExressHandler( KIWAY_PLAYER::kiway_express ) ); } @@ -31,10 +29,125 @@ KIWAY_PLAYER::KIWAY_PLAYER( wxWindow* aParent, wxWindowID aId, const wxString& a const wxPoint& aPos, const wxSize& aSize, long aStyle, const wxString& aWdoName ) : EDA_BASE_FRAME( aParent, (FRAME_T) aId, aTitle, aPos, aSize, aStyle, aWdoName ), - KIWAY_HOLDER( 0 ) + KIWAY_HOLDER( 0 ), + m_modal_dismissed( 0 ) { DBG( printf("KIWAY_EXPRESS::wxEVENT_ID:%d\n", KIWAY_EXPRESS::wxEVENT_ID );) - Connect( KIWAY_EXPRESS::wxEVENT_ID, wxKiwayExressHandler( KIWAY_PLAYER::kiway_express ) ); + //Connect( KIWAY_EXPRESS::wxEVENT_ID, wxKiwayExressHandler( KIWAY_PLAYER::kiway_express ) ); +} + + +KIWAY_PLAYER::~KIWAY_PLAYER(){} + + +void KIWAY_PLAYER::KiwayMailIn( KIWAY_EXPRESS& aEvent ) +{ + // override this in derived classes. +} + + +static void makeModal( wxFrame* aFrame, bool IsModal ) +{ + // disable or enable all other top level windows +#if wxCHECK_VERSION(2, 9, 4) + wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); + + while( node ) + { + wxWindow* win = node->GetData(); + + if( win != aFrame ) + win->Enable( !IsModal ); + + node = node->GetNext(); + } +#else + // Deprecated since wxWidgets 2.9.4 + aFrame->MakeModal( IsModal ); +#endif +} + + +/** + * toggle global wxFrame enable/disable state, does the re-enable part even + * if an exception is thrown. + */ +struct ENABLE_DISABLE +{ + wxFrame* m_frame; + + ENABLE_DISABLE( wxFrame* aFrame ) : + m_frame( aFrame ) + { + makeModal( aFrame, true ); + } + + ~ENABLE_DISABLE() + { + // Re-enable all frames, (oops, even if they were previously inactive). + // This is probably why this function was deprecated in wx. + makeModal( m_frame, false ); + } +}; + + +bool KIWAY_PLAYER::ShowModal( wxString* aResult ) +{ + /* + This function has a nice interface but an unsightly implementation. + Now it is encapsulated, making it easier to improve. I am not sure + a wxSemaphore was needed, especially since no blocking happens. It seems + like a volatile bool is sufficient. + + It works in tandem with DismissModal(). But only ShowModal() is in the + vtable and therefore cross-module capable. + */ + + volatile bool dismissed = false; + + // disable all frames except the modal one, re-enable on exit, exception safe. + ENABLE_DISABLE toggle( this ); + + m_modal_dismissed = &dismissed; + + Show( true ); + Raise(); + + // Wait for the one and only active frame to call DismissModal() from + // some concluding event. + while( !dismissed ) + { + wxYield(); + wxMilliSleep( 50 ); + } + + // no longer modal, not to mention that the pointer would be invalid outside this scope. + m_modal_dismissed = NULL; + + if( aResult ) + *aResult = m_modal_string; + + return m_modal_ret_val; +} + + +bool KIWAY_PLAYER::IsDismissed() +{ + // if already dismissed, then m_modal_dismissed may be NULL, and if not, + // it can still be dismissed if the bool is true. + bool ret = !m_modal_dismissed || *m_modal_dismissed; + + return ret; +} + + +void KIWAY_PLAYER::DismissModal( bool aRetVal, const wxString& aResult ) +{ + m_modal_ret_val = aRetVal; + m_modal_string = aResult; + + if( m_modal_dismissed ) + *m_modal_dismissed = true; } @@ -42,17 +155,20 @@ void KIWAY_PLAYER::kiway_express( KIWAY_EXPRESS& aEvent ) { // logging support #if defined(DEBUG) - const char* class_name = typeid(this).name(); + const char* class_name = typeid( this ).name(); - printf( "%s: cmd:%d pay:'%s'\n", class_name, - aEvent.GetEventType(), aEvent.GetPayload().c_str() ); + printf( "%s: received cmd:%d pay:'%s'\n", class_name, + aEvent.Command(), aEvent.GetPayload().c_str() ); #endif - KiwayMailIn( aEvent ); // call the virtual, overload in derived. + KiwayMailIn( aEvent ); // call the virtual, override in derived. } -void KIWAY_PLAYER::KiwayMailIn( KIWAY_EXPRESS& aEvent ) +void KIWAY_PLAYER::language_change( wxCommandEvent& event ) { - // overload this. + int id = event.GetId(); + + // tell all the KIWAY_PLAYERs about the language change. + Kiway().SetLanguage( id ); } diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp index 1789f939ed..d7f923676c 100644 --- a/common/pgm_base.cpp +++ b/common/pgm_base.cpp @@ -622,7 +622,7 @@ bool PGM_BASE::SetLanguage( bool first_time ) void PGM_BASE::SetLanguageIdentifier( int menu_id ) { - wxLogDebug( wxT( "Select language ID %d from %zd possible languages." ), + wxLogDebug( wxT( "Select language ID %d from %d possible languages." ), menu_id, DIM( s_Languages ) ); for( unsigned ii = 0; ii < DIM( s_Languages ); ii++ ) diff --git a/common/single_top.cpp b/common/single_top.cpp index 2632a32eae..7d7c816590 100644 --- a/common/single_top.cpp +++ b/common/single_top.cpp @@ -121,7 +121,7 @@ static const wxString dso_full_path( const wxString& aAbsoluteArgv0 ) // Only a single KIWAY is supported in this single_top top level component, // which is dedicated to loading only a single DSO. -KIWAY Kiway( &Pgm() ); +KIWAY Kiway( &Pgm(), KFCTL_STANDALONE ); // implement a PGM_BASE and a wxApp side by side: @@ -225,82 +225,6 @@ struct APP_SINGLE_TOP : public wxApp IMPLEMENT_APP( APP_SINGLE_TOP ); -/** - * Function get_kiface_getter - * returns a KIFACE_GETTER_FUNC for the current process's main implementation - * link image. - * - * @param aDSOName is an absolute full path to the DSO to load and find - * KIFACE_GETTER_FUNC within. - * - * @return KIFACE_GETTER_FUNC* - a pointer to a function which can be called to - * get the KIFACE or NULL if the getter func was not found. If not found, - * it is possibly not version compatible since the lookup is done by name and - * the name contains the API version. - */ -static KIFACE_GETTER_FUNC* get_kiface_getter( const wxString& aDSOName ) -{ -#if defined(BUILD_KIWAY_DLL) - - // Remember single_top only knows about a single DSO. Using an automatic - // with a defeated destructor, see Detach() below, so that the DSO program - // image stays in RAM until process termination, and specifically - // beyond the point in time at which static destructors are run. Otherwise - // a static wxDynamicLibrary's destructor might create an out of sequence - // problem. This was never detected, so it's only a preventative strategy. - wxDynamicLibrary dso; - - void* addr = NULL; - - if( !dso.Load( aDSOName, wxDL_VERBATIM | wxDL_NOW ) ) - { - // Failure: error reporting UI was done via wxLogSysError(). - // No further reporting required here. - } - - else if( ( addr = dso.GetSymbol( wxT( KIFACE_INSTANCE_NAME_AND_VERSION ) ) ) == NULL ) - { - // Failure: error reporting UI was done via wxLogSysError(). - // No further reporting required here. - } - - else - { - // Tell dso's wxDynamicLibrary destructor not to Unload() the program image. - (void) dso.Detach(); - - return (KIFACE_GETTER_FUNC*) addr; - } - - // There is a file installation bug. We only look for KIFACE_I's which we know - // to exist, and we did not find one. If we do not find one, this is an - // installation bug. - - wxString msg = wxString::Format( wxT( - "Fatal Installation Bug\nmissing file:\n'%s'\n\nargv[0]:\n'%s'" ), - GetChars( aDSOName ), - GetChars( wxStandardPaths::Get().GetExecutablePath() ) - ); - - // This is a fatal error, one from which we cannot recover, nor do we want - // to protect against in client code which would require numerous noisy - // tests in numerous places. So we inform the user that the installation - // is bad. This exception will likely not get caught until way up in the - // wxApp derivative, at which point the process will exit gracefully. - THROW_IO_ERROR( msg ); - -#else - return &KIFACE_GETTER; - -#endif -} - - -static KIFACE* kiface; -static int kiface_version; - - - bool PGM_SINGLE_TOP::OnPgmInit( wxApp* aWxApp ) { // first thing: set m_wx_app @@ -321,44 +245,27 @@ bool PGM_SINGLE_TOP::OnPgmInit( wxApp* aWxApp ) if( !initPgm() ) return false; - wxString dname = dso_full_path( absoluteArgv0 ); +#if !defined(BUILD_KIWAY_DLL) + // Get the getter, it is statically linked into this binary image. + KIFACE_GETTER_FUNC* getter = &KIFACE_GETTER; - // Get the getter. - KIFACE_GETTER_FUNC* getter = get_kiface_getter( dname ); - - if( !getter ) - { - // get_kiface_getter() failed & already showed the UI message. - // Return failure without any further UI. - return false; - } + int kiface_version; // Get the KIFACE. - kiface = getter( &kiface_version, KIFACE_VERSION, this ); + KIFACE* kiface = getter( &kiface_version, KIFACE_VERSION, this ); - // KIFACE_GETTER_FUNC function comment (API) says the non-NULL is unconditional. - wxASSERT_MSG( kiface, wxT( "attempted DSO has a bug, failed to return a KIFACE*" ) ); - - // Give the DSO a single chance to do its "process level" initialization. - // "Process level" specifically means stay away from any projects in there. - if( !kiface->OnKifaceStart( this, KFCTL_STANDALONE ) ) - return false; - - // Use KIFACE to create a top window that the KIFACE knows about. - // TOP_FRAME is passed on compiler command line from CMake, and is one of - // the types in FRAME_T. - // KIFACE::CreateWindow() is a virtual so we don't need to link to it. - // Remember its in the *.kiface DSO. -#if 0 - // this pulls in EDA_DRAW_FRAME type info, which we don't want in - // the single_top link image. - KIWAY_PLAYER* frame = dynamic_cast( kiface->CreateWindow( - NULL, TOP_FRAME, &Kiway, KFCTL_STANDALONE ) ); -#else - KIWAY_PLAYER* frame = (KIWAY_PLAYER*) kiface->CreateWindow( - NULL, TOP_FRAME, &Kiway, KFCTL_STANDALONE ); + // Trick the KIWAY into thinking it loaded a KIFACE, by recording the KIFACE + // in the KIWAY. It needs to be there for KIWAY::OnKiwayEnd() anyways. + Kiway.set_kiface( KIWAY::KifaceType( TOP_FRAME ), kiface ); #endif + // Use KIWAY to create a top window, which registers its existence also. + // "TOP_FRAME" is a macro that is passed on compiler command line from CMake, + // and is one of the types in FRAME_T. + KIWAY_PLAYER* frame = Kiway.Player( TOP_FRAME, true ); + + Kiway.SetTop( frame ); + App().SetTopWindow( frame ); // wxApp gets a face. // Open project or file specified on the command line: @@ -454,8 +361,7 @@ bool PGM_SINGLE_TOP::OnPgmInit( wxApp* aWxApp ) void PGM_SINGLE_TOP::OnPgmExit() { - if( kiface ) - kiface->OnKifaceEnd(); + Kiway.OnKiwayEnd(); saveCommonSettings(); diff --git a/cvpcb/cvframe.cpp b/cvpcb/cvframe.cpp index 74b79b3567..3ffd306b7d 100644 --- a/cvpcb/cvframe.cpp +++ b/cvpcb/cvframe.cpp @@ -76,8 +76,6 @@ BEGIN_EVENT_TABLE( CVPCB_MAINFRAME, EDA_BASE_FRAME ) EVT_MENU( ID_CVPCB_LIB_TABLE_EDIT, CVPCB_MAINFRAME::OnEditFootprintLibraryTable ) - EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, CVPCB_MAINFRAME::SetLanguage ) - // Toolbar events EVT_TOOL( ID_CVPCB_QUIT, CVPCB_MAINFRAME::OnQuit ) EVT_TOOL( ID_CVPCB_READ_INPUT_NETLIST, CVPCB_MAINFRAME::LoadNetList ) @@ -558,12 +556,6 @@ void CVPCB_MAINFRAME::DisplayModule( wxCommandEvent& event ) } -void CVPCB_MAINFRAME::SetLanguage( wxCommandEvent& event ) -{ - EDA_BASE_FRAME::SetLanguage( event ); -} - - void CVPCB_MAINFRAME::DisplayDocFile( wxCommandEvent& event ) { GetAssociatedDocument( this, m_DocModulesFileName, &Kiface().KifaceSearch() ); diff --git a/cvpcb/cvpcb_mainframe.h b/cvpcb/cvpcb_mainframe.h index 8cd8f5c322..3993091dda 100644 --- a/cvpcb/cvpcb_mainframe.h +++ b/cvpcb/cvpcb_mainframe.h @@ -123,12 +123,6 @@ public: void ChangeFocus( bool aMoveRight ); - /** - * Function SetLanguage - * is called on a language menu selection. - */ - void SetLanguage( wxCommandEvent& event ); - void ToFirstNA( wxCommandEvent& event ); void ToPreviousNA( wxCommandEvent& event ); diff --git a/eeschema/block_libedit.cpp b/eeschema/block_libedit.cpp index e9c89d14f5..abf7fc66ed 100644 --- a/eeschema/block_libedit.cpp +++ b/eeschema/block_libedit.cpp @@ -321,7 +321,7 @@ void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& wxPoint move_offset; block = &screen->m_BlockLocate; - LIB_EDIT_FRAME* parent = ( LIB_EDIT_FRAME* ) aPanel->GetParent(); + LIB_EDIT_FRAME* parent = (LIB_EDIT_FRAME*) aPanel->GetParent(); wxASSERT( parent != NULL ); LIB_COMPONENT* component = parent->GetComponent(); diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index c5e1432036..911c1d138d 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -104,6 +105,15 @@ static struct IFACE : public KIFACE_I } break; + + case FRAME_SCH_VIEWER: + case FRAME_SCH_VIEWER_MODAL: + { + LIB_VIEW_FRAME* frame = new LIB_VIEW_FRAME( aKiway, aParent, FRAME_T( aClassId ) ); + return frame; + } + break; + default: return NULL; } diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index caa3b2782b..2a0cccf33b 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -118,7 +118,10 @@ EDA_COLOR_T GetInvisibleItemColor() void LIB_EDIT_FRAME::InstallConfigFrame( wxCommandEvent& event ) { - InvokeEeschemaConfig( (SCH_EDIT_FRAME *)GetParent(), this ); + SCH_EDIT_FRAME* frame = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false ); + wxASSERT( frame ); + + InvokeEeschemaConfig( frame, this ); } @@ -134,7 +137,9 @@ void LIB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) { int id = event.GetId(); wxFileName fn; - SCH_EDIT_FRAME* schFrame = ( SCH_EDIT_FRAME* ) GetParent(); + + SCH_EDIT_FRAME* schFrame = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false ); + wxASSERT( schFrame ); switch( id ) { @@ -143,20 +148,20 @@ void LIB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) break; case ID_CONFIG_READ: - { - fn = g_RootSheet->GetScreen()->GetFileName(); - fn.SetExt( ProjectFileExtension ); + { + fn = g_RootSheet->GetScreen()->GetFileName(); + fn.SetExt( ProjectFileExtension ); - wxFileDialog dlg( this, _( "Read Project File" ), fn.GetPath(), - fn.GetFullName(), ProjectFileWildcard, - wxFD_OPEN | wxFD_FILE_MUST_EXIST ); + wxFileDialog dlg( this, _( "Read Project File" ), fn.GetPath(), + fn.GetFullName(), ProjectFileWildcard, + wxFD_OPEN | wxFD_FILE_MUST_EXIST ); - if( dlg.ShowModal() == wxID_CANCEL ) - break; + if( dlg.ShowModal() == wxID_CANCEL ) + break; - schFrame->LoadProjectFile( dlg.GetPath(), true ); - } - break; + schFrame->LoadProjectFile( dlg.GetPath(), true ); + } + break; // Hotkey IDs diff --git a/eeschema/getpart.cpp b/eeschema/getpart.cpp index fa1f083860..e977eee5c1 100644 --- a/eeschema/getpart.cpp +++ b/eeschema/getpart.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -55,18 +56,14 @@ wxString SCH_BASE_FRAME::SelectComponentFromLibBrowser( LIB_ALIAS* aPreselectedAlias, int* aUnit, int* aConvert ) { - wxSemaphore semaphore( 0, 1 ); - wxString cmpname; - - // Close the current Lib browser, if open, and open a new one, in "modal" mode: - LIB_VIEW_FRAME* viewlibFrame = LIB_VIEW_FRAME::GetActiveLibraryViewer( this ); + // Close the any current non-modal Lib browser if open, and open a new one, in "modal" mode: + LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false ); if( viewlibFrame ) viewlibFrame->Destroy(); - viewlibFrame = new LIB_VIEW_FRAME( &Kiway(), this, NULL, &semaphore, - KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT ); + viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, true ); - if ( aPreselectedAlias ) + if( aPreselectedAlias ) { viewlibFrame->SetSelectedLibrary( aPreselectedAlias->GetLibraryName() ); viewlibFrame->SetSelectedComponent( aPreselectedAlias->GetName() ); @@ -80,15 +77,9 @@ wxString SCH_BASE_FRAME::SelectComponentFromLibBrowser( LIB_ALIAS* aPreselectedA viewlibFrame->Refresh(); - // Show the library viewer frame until it is closed - // Wait for viewer closing event: - while( semaphore.TryWait() == wxSEMA_BUSY ) - { - wxYield(); - wxMilliSleep( 50 ); - } + wxString cmpname; - cmpname = viewlibFrame->GetSelectedComponent(); + viewlibFrame->ShowModal( &cmpname ); if( aUnit ) *aUnit = viewlibFrame->GetUnit(); @@ -101,6 +92,7 @@ wxString SCH_BASE_FRAME::SelectComponentFromLibBrowser( LIB_ALIAS* aPreselectedA return cmpname; } + wxString SCH_BASE_FRAME::SelectComponentFromLibrary( const wxString& aLibname, wxArrayString& aHistoryList, int& aHistoryLastUnit, diff --git a/eeschema/libeditframe.cpp b/eeschema/libeditframe.cpp index 1a79cba67e..49ea88353d 100644 --- a/eeschema/libeditframe.cpp +++ b/eeschema/libeditframe.cpp @@ -99,7 +99,7 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_SIZE( LIB_EDIT_FRAME::OnSize ) EVT_ACTIVATE( LIB_EDIT_FRAME::OnActivate ) - /* Main horizontal toolbar. */ + // Main horizontal toolbar. EVT_TOOL( ID_LIBEDIT_SAVE_CURRENT_LIB, LIB_EDIT_FRAME::OnSaveActiveLibrary ) EVT_TOOL( ID_LIBEDIT_SELECT_CURRENT_LIB, LIB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_LIBEDIT_DELETE_PART, LIB_EDIT_FRAME::DeleteOnePart ) @@ -125,12 +125,12 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_COMBOBOX( ID_LIBEDIT_SELECT_PART_NUMBER, LIB_EDIT_FRAME::OnSelectPart ) EVT_COMBOBOX( ID_LIBEDIT_SELECT_ALIAS, LIB_EDIT_FRAME::OnSelectAlias ) - /* Right vertical toolbar. */ + // Right vertical toolbar. EVT_TOOL( ID_NO_TOOL_SELECTED, LIB_EDIT_FRAME::OnSelectTool ) EVT_TOOL_RANGE( ID_LIBEDIT_PIN_BUTT, ID_LIBEDIT_DELETE_ITEM_BUTT, LIB_EDIT_FRAME::OnSelectTool ) - /* menubar commands */ + // menubar commands EVT_MENU( wxID_EXIT, LIB_EDIT_FRAME::CloseWindow ) EVT_MENU( ID_LIBEDIT_SAVE_CURRENT_LIB_AS, LIB_EDIT_FRAME::OnSaveActiveLibrary ) EVT_MENU( ID_LIBEDIT_GEN_PNG_FILE, LIB_EDIT_FRAME::OnPlotCurrentComponent ) @@ -152,9 +152,7 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_MENU_RANGE( ID_PREFERENCES_HOTKEY_START, ID_PREFERENCES_HOTKEY_END, LIB_EDIT_FRAME::Process_Config ) - EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, LIB_EDIT_FRAME::SetLanguage ) - - /* Context menu events and commands. */ + // Context menu events and commands. EVT_MENU( ID_LIBEDIT_EDIT_PIN, LIB_EDIT_FRAME::OnEditPin ) EVT_MENU( ID_LIBEDIT_ROTATE_ITEM, LIB_EDIT_FRAME::OnRotateItem ) @@ -165,7 +163,7 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE, LIB_EDIT_FRAME::Process_Special_Functions ) - /* Update user interface elements. */ + // Update user interface elements. EVT_UPDATE_UI( ExportPartId, LIB_EDIT_FRAME::OnUpdateEditingPart ) EVT_UPDATE_UI( CreateNewLibAndSavePartId, LIB_EDIT_FRAME::OnUpdateEditingPart ) EVT_UPDATE_UI( ID_LIBEDIT_SAVE_CURRENT_PART, LIB_EDIT_FRAME::OnUpdateEditingPart ) @@ -193,7 +191,7 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, SCH_EDIT_FRAME* aParent ) : SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH_LIB_EDITOR, _( "Library Editor" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, GetLibEditFrameName() ) { - wxASSERT( aParent ); // LIB_EDIT_FRAME needs a parent, since it peeks up there. + wxASSERT( aParent ); m_FrameName = GetLibEditFrameName(); m_showAxis = true; // true to draw axis @@ -204,6 +202,7 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, SCH_EDIT_FRAME* aParent ) : m_tempCopyComponent = NULL; m_HotkeysZoomAndGridList = s_Libedit_Hokeys_Descr; m_editPinsPerPartOrConvert = false; + // Initialize grid id to the default value 50 mils: m_LastGridSizeId = ID_POPUP_GRID_LEVEL_50 - ID_POPUP_GRID_LEVEL_1000; @@ -293,12 +292,6 @@ const wxChar* LIB_EDIT_FRAME::GetLibEditFrameName() } -LIB_EDIT_FRAME* LIB_EDIT_FRAME::GetActiveLibraryEditor() -{ - return (LIB_EDIT_FRAME*) wxWindow::FindWindowByName(GetLibEditFrameName()); -} - - void LIB_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg ) { #if 0 // original @@ -389,12 +382,12 @@ void LIB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) double LIB_EDIT_FRAME::BestZoom() { -/* Please, note: wxMSW before version 2.9 seems have - * problems with zoom values < 1 ( i.e. userscale > 1) and needs to be patched: - * edit file /src/msw/dc.cpp - * search for line static const int VIEWPORT_EXTENT = 1000; - * and replace by static const int VIEWPORT_EXTENT = 10000; - */ + /* Please, note: wxMSW before version 2.9 seems have + * problems with zoom values < 1 ( i.e. userscale > 1) and needs to be patched: + * edit file /src/msw/dc.cpp + * search for line static const int VIEWPORT_EXTENT = 1000; + * and replace by static const int VIEWPORT_EXTENT = 10000; + */ int dx, dy; wxSize size; EDA_RECT BoundaryBox; @@ -750,23 +743,23 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_LIBEDIT_DELETE_CURRENT_POLY_SEGMENT: - { - // Delete the last created segment, while creating a polyline draw item - if( m_drawItem == NULL ) - break; + { + // Delete the last created segment, while creating a polyline draw item + if( m_drawItem == NULL ) + break; - m_canvas->MoveCursorToCrossHair(); - STATUS_FLAGS oldFlags = m_drawItem->GetFlags(); - m_drawItem->ClearFlags(); - m_drawItem->Draw( m_canvas, &dc, wxPoint( 0, 0 ), UNSPECIFIED_COLOR, g_XorMode, NULL, - DefaultTransform ); - ( (LIB_POLYLINE*) m_drawItem )->DeleteSegment( GetCrossHairPosition( true ) ); - m_drawItem->Draw( m_canvas, &dc, wxPoint( 0, 0 ), UNSPECIFIED_COLOR, g_XorMode, NULL, - DefaultTransform ); - m_drawItem->SetFlags( oldFlags ); - m_lastDrawItem = NULL; + m_canvas->MoveCursorToCrossHair(); + STATUS_FLAGS oldFlags = m_drawItem->GetFlags(); + m_drawItem->ClearFlags(); + m_drawItem->Draw( m_canvas, &dc, wxPoint( 0, 0 ), UNSPECIFIED_COLOR, g_XorMode, NULL, + DefaultTransform ); + ( (LIB_POLYLINE*) m_drawItem )->DeleteSegment( GetCrossHairPosition( true ) ); + m_drawItem->Draw( m_canvas, &dc, wxPoint( 0, 0 ), UNSPECIFIED_COLOR, g_XorMode, NULL, + DefaultTransform ); + m_drawItem->SetFlags( oldFlags ); + m_lastDrawItem = NULL; + } break; - } case ID_POPUP_LIBEDIT_DELETE_ITEM: if( m_drawItem ) @@ -918,17 +911,6 @@ void LIB_EDIT_FRAME::EnsureActiveLibExists() } -void LIB_EDIT_FRAME::SetLanguage( wxCommandEvent& event ) -{ - EDA_BASE_FRAME::SetLanguage( event ); - SCH_EDIT_FRAME *parent = (SCH_EDIT_FRAME *)GetParent(); - // Call parent->EDA_BASE_FRAME::SetLanguage and NOT - // parent->SetLanguage because parent->SetLanguage call - // LIB_EDIT_FRAME::SetLanguage - parent->EDA_BASE_FRAME::SetLanguage( event ); -} - - void LIB_EDIT_FRAME::TempCopyComponent() { if( m_tempCopyComponent ) diff --git a/eeschema/libeditframe.h b/eeschema/libeditframe.h index 45582f34d8..07a52b6203 100644 --- a/eeschema/libeditframe.h +++ b/eeschema/libeditframe.h @@ -133,13 +133,6 @@ public: */ static const wxChar* GetLibEditFrameName(); - /** - * Function GetActiveLibraryEditor (static) - * @return a reference to the current opened Library editor - * or NULL if no Library editor currently opened - */ - static LIB_EDIT_FRAME* GetActiveLibraryEditor(); - void ReCreateMenuBar(); /** @@ -149,12 +142,6 @@ public: */ static void EnsureActiveLibExists(); - /** - * Function SetLanguage - * is called on a language menu selection - */ - void SetLanguage( wxCommandEvent& event ); - void InstallConfigFrame( wxCommandEvent& event ); void InstallDimensionsDialog( wxCommandEvent& event ); void OnColorConfig( wxCommandEvent& aEvent ); diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp index 7908defdc1..ca6ac2f9ed 100644 --- a/eeschema/sch_base_frame.cpp +++ b/eeschema/sch_base_frame.cpp @@ -26,6 +26,7 @@ #include #include #include +#include SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, @@ -40,12 +41,10 @@ SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, void SCH_BASE_FRAME::OnOpenLibraryViewer( wxCommandEvent& event ) { - LIB_VIEW_FRAME* viewlibFrame = LIB_VIEW_FRAME::GetActiveLibraryViewer( this ); + LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, true ); - if( viewlibFrame ) - viewlibFrame->Show( true ); - else - new LIB_VIEW_FRAME( &Kiway(), this ); + viewlibFrame->Show( true ); + viewlibFrame->Raise(); } diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp index 8706b5c4b5..ff42fdc9af 100644 --- a/eeschema/schedit.cpp +++ b/eeschema/schedit.cpp @@ -664,7 +664,7 @@ static void abortMoveItem( EDA_DRAW_PANEL* aPanel, wxDC* aDC ) { SCH_SCREEN* screen = (SCH_SCREEN*) aPanel->GetScreen(); SCH_ITEM* item = screen->GetCurItem(); - SCH_EDIT_FRAME* parent = ( SCH_EDIT_FRAME* ) aPanel->GetParent(); + SCH_EDIT_FRAME* parent = (SCH_EDIT_FRAME*) aPanel->GetParent(); parent->SetRepeatItem( NULL ); screen->SetCurItem( NULL ); diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index fe38369fd4..db9e8f50ce 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -96,8 +96,6 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_MENU( ID_COLORS_SETUP, SCH_EDIT_FRAME::OnColorConfig ) EVT_TOOL( wxID_PREFERENCES, SCH_EDIT_FRAME::OnSetOptions ) - EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, SCH_EDIT_FRAME::SetLanguage ) - EVT_TOOL( ID_TO_LIBRARY, SCH_EDIT_FRAME::OnOpenLibraryEditor ) EVT_TOOL( ID_POPUP_SCH_CALL_LIBEDIT_AND_LOAD_CMP, SCH_EDIT_FRAME::OnOpenLibraryEditor ) EVT_TOOL( ID_TO_LIBVIEW, SCH_EDIT_FRAME::OnOpenLibraryViewer ) @@ -442,13 +440,20 @@ void SCH_EDIT_FRAME::SaveUndoItemInUndoList( SCH_ITEM* aItem ) void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent ) { - LIB_EDIT_FRAME * libeditFrame = LIB_EDIT_FRAME::GetActiveLibraryEditor();; - if( libeditFrame && !libeditFrame->Close() ) // Can close component editor? - return; + if( Kiface().IsSingle() ) + { + LIB_EDIT_FRAME* libeditFrame = (LIB_EDIT_FRAME*) Kiway().Player( FRAME_SCH_LIB_EDITOR, false ); + if( libeditFrame && !libeditFrame->Close() ) // Can close component editor? + return; - LIB_VIEW_FRAME* viewlibFrame = LIB_VIEW_FRAME::GetActiveLibraryViewer( this ); - if( viewlibFrame && !viewlibFrame->Close() ) // Can close component viewer? - return; + LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false ); + if( viewlibFrame && !viewlibFrame->Close() ) // Can close component viewer? + return; + + viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, false ); + if( viewlibFrame && !viewlibFrame->Close() ) // Can close modal component viewer? + return; + } SCH_SHEET_LIST SheetList; @@ -829,7 +834,7 @@ void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event ) { SCH_ITEM* item = GetScreen()->GetCurItem(); - if( (item == NULL) || (item->GetFlags() != 0) || ( item->Type() != SCH_COMPONENT_T ) ) + if( !item || (item->GetFlags() != 0) || ( item->Type() != SCH_COMPONENT_T ) ) { wxMessageBox( _( "Error: not a component or no component" ) ); return; @@ -838,9 +843,21 @@ void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event ) component = (SCH_COMPONENT*) item; } - // @todo: should be changed to use Kiway().Player()? + LIB_EDIT_FRAME* libeditFrame = (LIB_EDIT_FRAME*) Kiway().Player( FRAME_SCH_LIB_EDITOR, false ); + if( !libeditFrame ) + { + libeditFrame = (LIB_EDIT_FRAME*) Kiway().Player( FRAME_SCH_LIB_EDITOR, true ); + libeditFrame->Show( true ); + } + else + { + // if( libeditFrame->IsIconized() ) + // libeditFrame->Iconize( false ); + } - LIB_EDIT_FRAME* libeditFrame = LIB_EDIT_FRAME::GetActiveLibraryEditor();; + libeditFrame->Raise(); + +#if 0 if( libeditFrame ) { if( libeditFrame->IsIconized() ) @@ -855,6 +872,8 @@ void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event ) wxWindow* w = kf.CreateWindow( this, FRAME_SCH_LIB_EDITOR, &Kiway(), kf.StartFlags() ); libeditFrame = dynamic_cast( w ); } +#endif + if( component ) { @@ -875,16 +894,6 @@ void SCH_EDIT_FRAME::OnExit( wxCommandEvent& event ) } -void SCH_EDIT_FRAME::SetLanguage( wxCommandEvent& event ) -{ - EDA_BASE_FRAME::SetLanguage( event ); - - LIB_EDIT_FRAME * libeditFrame = LIB_EDIT_FRAME::GetActiveLibraryEditor();; - if( libeditFrame ) - libeditFrame->EDA_BASE_FRAME::SetLanguage( event ); -} - - void SCH_EDIT_FRAME::OnPrint( wxCommandEvent& event ) { wxFileName fn; diff --git a/eeschema/sheet.cpp b/eeschema/sheet.cpp index 62d9fca131..23e9ae5100 100644 --- a/eeschema/sheet.cpp +++ b/eeschema/sheet.cpp @@ -283,7 +283,7 @@ static void ExitSheet( EDA_DRAW_PANEL* aPanel, wxDC* aDC ) SCH_SCREEN* screen = (SCH_SCREEN*) aPanel->GetScreen(); SCH_ITEM* item = screen->GetCurItem(); - SCH_EDIT_FRAME* parent = ( SCH_EDIT_FRAME* ) aPanel->GetParent(); + SCH_EDIT_FRAME* parent = (SCH_EDIT_FRAME*) aPanel->GetParent(); if( (item == NULL) || (item->Type() != SCH_SHEET_T) || (parent == NULL) ) return; diff --git a/eeschema/tool_viewlib.cpp b/eeschema/tool_viewlib.cpp index 5dce538405..f929ad5c28 100644 --- a/eeschema/tool_viewlib.cpp +++ b/eeschema/tool_viewlib.cpp @@ -116,9 +116,9 @@ void LIB_VIEW_FRAME::ReCreateHToolbar() _( "View component documents" ) ); m_mainToolBar->EnableTool( ID_LIBVIEW_VIEWDOC, false ); - if( m_semaphore ) + // if library browser is modal + if( m_Ident == FRAME_SCH_VIEWER_MODAL ) { - // The library browser is called from a "load component" command m_mainToolBar->AddSeparator(); m_mainToolBar->AddTool( ID_LIBVIEW_CMP_EXPORT_TO_SCHEMATIC, wxEmptyString, KiBitmap( export_xpm ), diff --git a/eeschema/viewlib_frame.cpp b/eeschema/viewlib_frame.cpp index 33b05c1bc6..e4af57c174 100644 --- a/eeschema/viewlib_frame.cpp +++ b/eeschema/viewlib_frame.cpp @@ -47,28 +47,25 @@ */ wxString LIB_VIEW_FRAME::m_libraryName; wxString LIB_VIEW_FRAME::m_entryName; + int LIB_VIEW_FRAME::m_unit = 1; int LIB_VIEW_FRAME::m_convert = 1; -/// When the viewer is used to select a component in schematic, the selected component is here. -wxString LIB_VIEW_FRAME::m_exportToEeschemaCmpName; - - BEGIN_EVENT_TABLE( LIB_VIEW_FRAME, EDA_DRAW_FRAME ) - /* Window events */ + // Window events EVT_CLOSE( LIB_VIEW_FRAME::OnCloseWindow ) EVT_SIZE( LIB_VIEW_FRAME::OnSize ) EVT_ACTIVATE( LIB_VIEW_FRAME::OnActivate ) - /* Toolbar events */ + // Toolbar events EVT_TOOL_RANGE( ID_LIBVIEW_NEXT, ID_LIBVIEW_DE_MORGAN_CONVERT_BUTT, LIB_VIEW_FRAME::Process_Special_Functions ) EVT_TOOL( ID_LIBVIEW_CMP_EXPORT_TO_SCHEMATIC, LIB_VIEW_FRAME::ExportToSchematicLibraryPart ) EVT_COMBOBOX( ID_LIBVIEW_SELECT_PART_NUMBER, LIB_VIEW_FRAME::Process_Special_Functions ) - /* listbox events */ + // listbox events EVT_LISTBOX( ID_LIBVIEW_LIB_LIST, LIB_VIEW_FRAME::ClickOnLibList ) EVT_LISTBOX( ID_LIBVIEW_CMP_LIST, LIB_VIEW_FRAME::ClickOnCmpList ) EVT_LISTBOX_DCLICK( ID_LIBVIEW_CMP_LIST, LIB_VIEW_FRAME::DClickOnCmpList ) @@ -95,11 +92,17 @@ static wxAcceleratorEntry accels[] = #define ACCEL_TABLE_CNT ( sizeof( accels ) / sizeof( wxAcceleratorEntry ) ) #define LIB_VIEW_FRAME_NAME wxT( "ViewlibFrame" ) -LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, SCH_BASE_FRAME* aParent, - CMP_LIBRARY* aLibrary, wxSemaphore* aSemaphore, long aStyle ) : - SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH_VIEWER, _( "Library Browser" ), - wxDefaultPosition, wxDefaultSize, aStyle, GetLibViewerFrameName() ) +LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, + CMP_LIBRARY* aLibrary ) : + SCH_BASE_FRAME( aKiway, aParent, aFrameType, _( "Library Browser" ), + wxDefaultPosition, wxDefaultSize, + aFrameType==FRAME_SCH_VIEWER ? + KICAD_DEFAULT_DRAWFRAME_STYLE : + KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT, + GetLibViewerFrameName() ) { + wxASSERT( aFrameType==FRAME_SCH_VIEWER || aFrameType==FRAME_SCH_VIEWER_MODAL ); + wxAcceleratorTable table( ACCEL_TABLE_CNT, accels ); m_FrameName = GetLibViewerFrameName(); @@ -114,12 +117,6 @@ LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, SCH_BASE_FRAME* aParent, m_HotkeysZoomAndGridList = s_Viewlib_Hokeys_Descr; m_cmpList = NULL; m_libList = NULL; - m_semaphore = aSemaphore; - - if( m_semaphore ) - SetModalMode( true ); - - m_exportToEeschemaCmpName.Empty(); SetScreen( new SCH_SCREEN() ); GetScreen()->m_Center = true; // Axis origin centered on screen. @@ -139,10 +136,10 @@ LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, SCH_BASE_FRAME* aParent, wxPoint win_pos( 0, 0 ); - if( aLibrary == NULL ) + if( !aLibrary ) { // Creates the libraries window display - m_libList = new wxListBox( this, ID_LIBVIEW_LIB_LIST, + m_libList = new wxListBox( this, ID_LIBVIEW_LIB_LIST, wxPoint( 0, 0 ), wxSize(m_libListWidth, -1), 0, NULL, wxLB_HSCROLL ); } @@ -243,25 +240,19 @@ const wxChar* LIB_VIEW_FRAME::GetLibViewerFrameName() } -LIB_VIEW_FRAME* LIB_VIEW_FRAME::GetActiveLibraryViewer( const wxWindow* aParent ) -{ - return (LIB_VIEW_FRAME*) wxWindow::FindWindowByName( GetLibViewerFrameName(), aParent ); -} - - void LIB_VIEW_FRAME::OnCloseWindow( wxCloseEvent& Event ) { - if( m_semaphore ) - { - m_semaphore->Post(); - // This window will be destroyed by the calling function, - // if needed - SetModalMode( false ); - } - else + if( !IsModal() ) { Destroy(); } + else if( !IsDismissed() ) + { + // only dismiss modal frame if not already dismissed. + DismissModal( false ); + + // Modal frame will be destroyed by the calling function. + } } @@ -283,12 +274,13 @@ void LIB_VIEW_FRAME::OnSetRelativeOffset( wxCommandEvent& event ) double LIB_VIEW_FRAME::BestZoom() { -/* Please, note: wxMSW before version 2.9 seems have - * problems with zoom values < 1 ( i.e. userscale > 1) and needs to be patched: - * edit file /src/msw/dc.cpp - * search for line static const int VIEWPORT_EXTENT = 1000; - * and replace by static const int VIEWPORT_EXTENT = 10000; - */ + /* Please, note: wxMSW before version 2.9 seems have + * problems with zoom values < 1 ( i.e. userscale > 1) and needs to be patched: + * edit file /src/msw/dc.cpp + * search for line static const int VIEWPORT_EXTENT = 1000; + * and replace by static const int VIEWPORT_EXTENT = 10000; + */ + LIB_COMPONENT* component = NULL; double bestzoom = 16.0; // default value for bestzoom CMP_LIBRARY* lib = CMP_LIBRARY::FindLibrary( m_libraryName ); @@ -344,8 +336,8 @@ void LIB_VIEW_FRAME::ReCreateListLib() } else { - /* If not found, clear current library selection because it can be - * deleted after a config change. */ + // If not found, clear current library selection because it can be + // deleted after a config change. m_libraryName = wxEmptyString; m_entryName = wxEmptyString; m_unit = 1; @@ -417,6 +409,7 @@ void LIB_VIEW_FRAME::SetSelectedLibrary( const wxString& aLibraryName ) m_canvas->Refresh(); DisplayLibInfos(); ReCreateHToolbar(); + // Ensure the corresponding line in m_libList is selected // (which is not necessary the case if SetSelectedLibrary is called // by an other caller than ClickOnLibList. @@ -440,9 +433,10 @@ void LIB_VIEW_FRAME::SetSelectedComponent( const wxString& aComponentName ) if( m_entryName.CmpNoCase( aComponentName ) != 0 ) { m_entryName = aComponentName; + // Ensure the corresponding line in m_cmpList is selected - // (which is not necessary the case if SetSelectedComponent is called - // by an other caller than ClickOnCmpList. + // (which is not necessarily the case if SetSelectedComponent is called + // by another caller than ClickOnCmpList. m_cmpList->SetStringSelection( aComponentName, true ); DisplayLibInfos(); m_unit = 1; @@ -456,14 +450,21 @@ void LIB_VIEW_FRAME::SetSelectedComponent( const wxString& aComponentName ) void LIB_VIEW_FRAME::DClickOnCmpList( wxCommandEvent& event ) { - if( m_semaphore ) + if( IsModal() ) { ExportToSchematicLibraryPart( event ); - // Prevent the double click from being as a single click in the parent - // window which would cause the part to be parked rather than staying - // in drag mode. - ((SCH_BASE_FRAME*) GetParent())->SkipNextLeftButtonReleaseEvent(); + // The schematic editor might not be the parent of the library viewer. + // It could be a python window. + SCH_EDIT_FRAME* schframe = dynamic_cast( GetParent() ); + + if( schframe ) + { + // Prevent the double click from being as a single click in the parent + // window which would cause the part to be parked rather than staying + // in drag mode. + schframe->SkipNextLeftButtonReleaseEvent(); + } } } @@ -473,9 +474,17 @@ void LIB_VIEW_FRAME::ExportToSchematicLibraryPart( wxCommandEvent& event ) int ii = m_cmpList->GetSelection(); if( ii >= 0 ) - m_exportToEeschemaCmpName = m_cmpList->GetString( ii ); + { + wxString part_name = m_cmpList->GetString( ii ); + + // a selection was made, pass true + DismissModal( true, part_name ); + } else - m_exportToEeschemaCmpName.Empty(); + { + // no selection was made, pass false + DismissModal( false ); + } Close( true ); } @@ -524,10 +533,6 @@ void LIB_VIEW_FRAME::OnActivate( wxActivateEvent& event ) { EDA_DRAW_FRAME::OnActivate( event ); - // Ensure we do not have old selection: - if( m_FrameIsActive ) - m_exportToEeschemaCmpName.Empty(); - if( m_libList ) ReCreateListLib(); diff --git a/eeschema/viewlib_frame.h b/eeschema/viewlib_frame.h index bdb304a312..4e67d0eafc 100644 --- a/eeschema/viewlib_frame.h +++ b/eeschema/viewlib_frame.h @@ -38,7 +38,6 @@ class wxSashLayoutWindow; class wxListBox; -class wxSemaphore; class CMP_LIBRARY; @@ -48,9 +47,14 @@ class CMP_LIBRARY; class LIB_VIEW_FRAME : public SCH_BASE_FRAME { public: - LIB_VIEW_FRAME( KIWAY* aKiway, SCH_BASE_FRAME* aParent, - CMP_LIBRARY* aLibrary = NULL, wxSemaphore* aSemaphore = NULL, - long aStyle = KICAD_DEFAULT_DRAWFRAME_STYLE ); + + /** + * Constructor + * @param aFrameType must be given either FRAME_SCH_LIB_VIEWER or + * FRAME_SCH_LIB_VIEWER_MODAL + */ + LIB_VIEW_FRAME( KIWAY* aKiway, wxWindow* aParent, + FRAME_T aFrameType, CMP_LIBRARY* aLibrary = NULL ); ~LIB_VIEW_FRAME(); @@ -61,13 +65,6 @@ public: */ static const wxChar* GetLibViewerFrameName(); - /** - * Function GetActiveLibraryViewer (static) - * @return a reference to the current opened Library viewer - * or NULL if no Library viewer currently opened - */ - static LIB_VIEW_FRAME* GetActiveLibraryViewer( const wxWindow* aParent ); - void OnSize( wxSizeEvent& event ); /** @@ -109,7 +106,6 @@ public: * @param the alias name of the component to be selected. */ void SetSelectedComponent( const wxString& aComponentName ); - const wxString& GetSelectedComponent( void ) const { return m_exportToEeschemaCmpName; } void SetUnit( int aUnit ) { m_unit = aUnit; } int GetUnit( void ) { return m_unit; } @@ -147,8 +143,6 @@ private: wxListBox* m_cmpList; // The list of components int m_cmpListWidth; // Last width of the window - // Flags - wxSemaphore* m_semaphore; // != NULL if the frame must emulate a modal dialog wxString m_configPath; // subpath for configuration // TODO(hzeller): looks like these members were chosen to be static to survive different @@ -156,11 +150,8 @@ private: // ugly hack, and should be solved differently. static wxString m_libraryName; - // TODO(hzeller): figure out what the difference between these is and the motivation to - // have this distinction. Shouldn't these essentially be the same ? static wxString m_entryName; - static wxString m_exportToEeschemaCmpName; // When the viewer is used to select a component - // in schematic, the selected component is here + static int m_unit; static int m_convert; diff --git a/gerbview/events_called_functions.cpp b/gerbview/events_called_functions.cpp index a1021c1fab..6f258ab2b8 100644 --- a/gerbview/events_called_functions.cpp +++ b/gerbview/events_called_functions.cpp @@ -52,8 +52,6 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME ) GERBVIEW_FRAME::OnSelectOptionToolbar ) EVT_MENU( wxID_PREFERENCES, GERBVIEW_FRAME::InstallGerberOptionsDialog ) - EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, EDA_DRAW_FRAME::SetLanguage ) - // menu Postprocess EVT_MENU( ID_GERBVIEW_SHOW_LIST_DCODES, GERBVIEW_FRAME::Process_Special_Functions ) EVT_MENU( ID_GERBVIEW_SHOW_SOURCE, GERBVIEW_FRAME::OnShowGerberSourceFile ) @@ -209,9 +207,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) } -/* Selects the active DCode for the current active layer. - * Items using this DCode are hightlighted - */ void GERBVIEW_FRAME::OnSelectActiveDCode( wxCommandEvent& event ) { GERBER_IMAGE* gerber_image = g_GERBER_List[getActiveLayer()]; @@ -228,10 +223,7 @@ void GERBVIEW_FRAME::OnSelectActiveDCode( wxCommandEvent& event ) } } -/* Selects the active layer: - * - if a file is loaded, it is loaded in this layer - * _ this layer is displayed on top of other layers - */ + void GERBVIEW_FRAME::OnSelectActiveLayer( wxCommandEvent& event ) { LAYER_NUM layer = getActiveLayer(); @@ -246,9 +238,6 @@ void GERBVIEW_FRAME::OnSelectActiveLayer( wxCommandEvent& event ) } -/* Call preferred editor to show (and edit) the gerber source file - * loaded in the active layer - */ void GERBVIEW_FRAME::OnShowGerberSourceFile( wxCommandEvent& event ) { LAYER_NUM layer = getActiveLayer(); @@ -275,9 +264,6 @@ void GERBVIEW_FRAME::OnShowGerberSourceFile( wxCommandEvent& event ) } -/* Function OnSelectDisplayMode: called to select display mode - * (fast display, or exact mode with stacked images or with transparency - */ void GERBVIEW_FRAME::OnSelectDisplayMode( wxCommandEvent& event ) { int oldMode = GetDisplayMode(); @@ -301,20 +287,20 @@ void GERBVIEW_FRAME::OnSelectDisplayMode( wxCommandEvent& event ) m_canvas->Refresh(); } + void GERBVIEW_FRAME::OnQuit( wxCommandEvent& event ) { Close( true ); } -/** - * Function SetLanguage - * called on a language menu selection - * Update Layer manager title and tabs texts - */ -void GERBVIEW_FRAME::SetLanguage( wxCommandEvent& event ) + +void GERBVIEW_FRAME::ShowChangedLanguage() { - EDA_DRAW_FRAME::SetLanguage( event ); + // call my base class + EDA_DRAW_FRAME::ShowChangedLanguage(); + m_LayersManager->SetLayersManagerTabsText(); + wxAuiPaneInfo& pane_info = m_auimgr.GetPane( m_LayersManager ); pane_info.Caption( _( "Visibles" ) ); m_auimgr.Update(); @@ -322,14 +308,12 @@ void GERBVIEW_FRAME::SetLanguage( wxCommandEvent& event ) ReFillLayerWidget(); } -/** - * Function OnSelectOptionToolbar - * called to validate current choices - */ + void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) { - int id = event.GetId(); - bool state; + int id = event.GetId(); + bool state; + switch( id ) { case ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG: @@ -374,6 +358,7 @@ void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) break; case ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR: + // show/hide auxiliary Vertical layers and visibility manager toolbar m_show_layer_manager_tools = state; m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).Show( m_show_layer_manager_tools ); diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h index f703ece8ee..df14fdaa4b 100644 --- a/gerbview/gerbview_frame.h +++ b/gerbview/gerbview_frame.h @@ -462,11 +462,7 @@ public: void SaveSettings( wxConfigBase* aCfg ); // override virtual - /** - * Function SetLanguage - * called on a language menu selection - */ - virtual void SetLanguage( wxCommandEvent& event ); + void ShowChangedLanguage(); // override EDA_BASE_FRAME virtual void Process_Special_Functions( wxCommandEvent& event ); void OnSelectOptionToolbar( wxCommandEvent& event ); diff --git a/include/draw_frame.h b/include/draw_frame.h index 67aba863c1..aaf999edec 100644 --- a/include/draw_frame.h +++ b/include/draw_frame.h @@ -281,13 +281,6 @@ public: void EraseMsgBox(); void Process_PageSettings( wxCommandEvent& event ); - /** - * Function SetLanguage - * called on a language menu selection - * when using a derived function, do not forget to call this one - */ - virtual void SetLanguage( wxCommandEvent& event ); - virtual void ReCreateHToolbar() = 0; virtual void ReCreateVToolbar() = 0; virtual void ReCreateMenuBar(); diff --git a/include/fpid.h b/include/fpid.h index 853983ad51..ec1ab80931 100644 --- a/include/fpid.h +++ b/include/fpid.h @@ -80,9 +80,7 @@ public: * @return int - minus 1 (i.e. -1) means success, >= 0 indicates the character offset into * aId at which an error was detected. */ - int Parse( const std::string& aId ); - - int Parse( const wxString& aId ); + int Parse( const UTF8& aId ); /** * Function GetLibNickname @@ -100,9 +98,7 @@ public: * into the parameter at which an error was detected, usually because it * contained '/' or ':'. */ - int SetLibNickname( const std::string& aNickname ); - - int SetLibNickname( const wxString& aNickname ); + int SetLibNickname( const UTF8& aNickname ); /** * Function GetFootprintName @@ -114,11 +110,9 @@ public: * Function SetFootprintName * overrides the footprint name portion of the FPID to @a aFootprintName */ - int SetFootprintName( const std::string& aFootprintName ); + int SetFootprintName( const UTF8& aFootprintName ); - int SetFootprintName( const wxString& aFootprintName ); - - int SetRevision( const std::string& aRevision ); + int SetRevision( const UTF8& aRevision ); const UTF8& GetRevision() const { return revision; } @@ -136,10 +130,10 @@ public: * aLibNickname, aFootprintName, and aRevision. * * @throw PARSE_ERROR if any of the pieces are illegal. - */ - static UTF8 Format( const std::string& aLibNickname, const std::string& aFootprintName, - const std::string& aRevision ) + static UTF8 Format( const UTF8& aLibNickname, const UTF8& aFootprintName, + const UTF8& aRevision = "" ) throw( PARSE_ERROR ); + */ /** * Function IsValid diff --git a/include/frame_type.h b/include/frame_type.h index 23411168c6..e58f615659 100644 --- a/include/frame_type.h +++ b/include/frame_type.h @@ -11,22 +11,35 @@ enum FRAME_T FRAME_SCH, FRAME_SCH_LIB_EDITOR, FRAME_SCH_VIEWER, + FRAME_SCH_VIEWER_MODAL, + FRAME_PCB, FRAME_PCB_MODULE_EDITOR, FRAME_PCB_MODULE_VIEWER, - FRAME_PCB_FOOTPRINT_WIZARD, + FRAME_PCB_MODULE_VIEWER_MODAL, + FRAME_PCB_FOOTPRINT_WIZARD_MODAL, FRAME_PCB_DISPLAY3D, + FRAME_CVPCB, FRAME_CVPCB_DISPLAY, + FRAME_GERBER, - KIWAY_PLAYER_COUNT, // counts subset of FRAME_T's tracked in class KIWAY - - KICAD_MAIN_FRAME_T = KIWAY_PLAYER_COUNT, FRAME_PL_EDITOR, - //TEXT_EDITOR_FRAME_T, + + FRAME_BM2CMP, + + FRAME_CALC, + + KIWAY_PLAYER_COUNT, // counts subset of FRAME_T's which are KIWAY_PLAYER derivatives + + // C++ project manager is not a KIWAY_PLAYER + KICAD_MAIN_FRAME_T = KIWAY_PLAYER_COUNT, FRAME_T_COUNT }; + //TEXT_EDITOR_FRAME_T, + + #endif // FRAME_T_H_ diff --git a/include/kiface_i.h b/include/kiface_i.h index 9fe034603a..23f053580c 100644 --- a/include/kiface_i.h +++ b/include/kiface_i.h @@ -58,7 +58,7 @@ public: } VTBL_ENTRY wxWindow* CreateWindow( wxWindow* aParent, - int aClassId, KIWAY* aKIWAY, int aCtlBits ) = 0; + int aClassId, KIWAY* aKIWAY, int aCtlBits = 0 ) = 0; VTBL_ENTRY void* IfaceOrAddress( int aDataId ) = 0; diff --git a/include/kiway.h b/include/kiway.h index 9b2ffd6b2d..469a0fde27 100644 --- a/include/kiway.h +++ b/include/kiway.h @@ -150,7 +150,8 @@ struct KIFACE // this interface. #define KFCTL_STANDALONE (1<<0) ///< Am running as a standalone Top. -#define KFCTL_PROJECT_SUITE (1<<1) ///< Am running under a project mgr, possibly with others +#define KFCTL_CPP_PROJECT_SUITE (1<<1) ///< Am running under C++ project mgr, possibly with others +#define KFCTL_PY_PROJECT_SUITE (1<<2) ///< Am running under python project mgr, possibly with others /** @@ -201,7 +202,7 @@ struct KIFACE * not contained in the caller's link image. */ VTBL_ENTRY wxWindow* CreateWindow( wxWindow* aParent, int aClassId, - KIWAY* aKIWAY, int aCtlBits ) = 0; + KIWAY* aKIWAY, int aCtlBits = 0 ) = 0; /** * Function IfaceOrAddress @@ -249,6 +250,7 @@ struct KIFACE */ class KIWAY : public wxEvtHandler { + friend class PGM_SINGLE_TOP; // can use set_kiface() public: /// Known KIFACE implementations @@ -257,16 +259,12 @@ public: FACE_SCH, ///< eeschema DSO FACE_PCB, ///< pcbnew DSO FACE_CVPCB, - - /// count of those above here, which is the subset managed in a KIWAY. - KIWAY_FACE_COUNT, - - FACE_BMP2CMP = KIWAY_FACE_COUNT, FACE_GERBVIEW, FACE_PL_EDITOR, FACE_PCB_CALCULATOR, + FACE_BMP2CMP, - FACE_COUNT + KIWAY_FACE_COUNT }; /** @@ -302,7 +300,7 @@ public: * @return KIWAY_PLAYER* - a valid opened KIWAY_PLAYER or NULL if there * is something wrong or doCreate was false and the player has yet to be created. */ - VTBL_ENTRY KIWAY_PLAYER* Player( FRAME_T aFrameType, bool doCreate = true ); + VTBL_ENTRY KIWAY_PLAYER* Player( FRAME_T aFrameType, bool doCreate = true ); /** * Function PlayerClose @@ -312,7 +310,7 @@ public: * * @return bool - true the window is closed and not vetoed, else false. */ - VTBL_ENTRY bool PlayerClose( FRAME_T aFrameType, bool doForce ); + VTBL_ENTRY bool PlayerClose( FRAME_T aFrameType, bool doForce ); /** * Function PlayersClose @@ -325,7 +323,14 @@ public: */ VTBL_ENTRY bool PlayersClose( bool doForce ); - VTBL_ENTRY void ExpressMail( FRAME_T aDestination, MAIL_T aCommand, const std::string& aPayload, wxWindow* aSource=NULL ); + /** + * Function ExpressMail + * send aPayload to aDestination from aSource. Recipient receives this in its + * KIWAY_PLAYER::KiwayMailIn() function and can efficiently switch() based on + * aCommand in there. + */ + VTBL_ENTRY void ExpressMail( FRAME_T aDestination, MAIL_T aCommand, + const std::string& aPayload, wxWindow* aSource = NULL ); /** * Function Prj @@ -335,11 +340,26 @@ public: */ VTBL_ENTRY PROJECT& Prj() const; - KIWAY( PGM_BASE* aProgram, wxFrame* aTop = NULL ); + /** + * Function SetLanguage + * changes the language and then calls ShowChangedLanguage() on all KIWAY_PLAYERs. + */ + VTBL_ENTRY void SetLanguage( int aLanguage ); - /// In case aTop may not be known at time of KIWAY construction: + KIWAY( PGM_BASE* aProgram, int aCtlBits, wxFrame* aTop = NULL ); + + /** + * Function SetTop + * tells this KIWAY about the top most frame in the program and optionally + * allows it to play the role of one of the KIWAY_PLAYERs if launched from + * single_top.cpp. + * + * @param aTop is the top most wxFrame in the entire program. + */ void SetTop( wxFrame* aTop ); + void OnKiwayEnd(); + bool ProcessEvent( wxEvent& aEvent ); // overload virtual private: @@ -348,12 +368,23 @@ private: static const wxString dso_full_path( FACE_T aFaceId ); /// hooked into m_top in SetTop(), marks child frame as closed. - void playerDestroyHandler( wxWindowDestroyEvent& event ); + void player_destroy_handler( wxWindowDestroyEvent& event ); + + bool set_kiface( FACE_T aFaceType, KIFACE* aKiface ) + { + if( unsigned( aFaceType ) < unsigned( KIWAY_FACE_COUNT ) ) + { + m_kiface[aFaceType] = aKiface; + return true; + } + return false; + } static KIFACE* m_kiface[KIWAY_FACE_COUNT]; static int m_kiface_version[KIWAY_FACE_COUNT]; PGM_BASE* m_program; + int m_ctl; wxFrame* m_top; KIWAY_PLAYER* m_player[KIWAY_PLAYER_COUNT]; // from frame_type.h diff --git a/include/kiway_player.h b/include/kiway_player.h index 75b1189053..8188ad35c8 100644 --- a/include/kiway_player.h +++ b/include/kiway_player.h @@ -35,6 +35,8 @@ class PROJECT; struct KIFACE; class KIFACE_I; +#define VTBL_ENTRY virtual + /** * Class KIWAY_HOLDER @@ -80,7 +82,7 @@ public: private: // private, all setting is done through SetKiway(). - KIWAY* m_kiway; // no ownership. + KIWAY* m_kiway; // no ownership. }; @@ -110,6 +112,9 @@ public: const wxPoint& aPos, const wxSize& aSize, long aStyle, const wxString& aWdoName = wxFrameNameStr ); + ~KIWAY_PLAYER(); + + //--------------------------------------------------------- // For the aCtl argument of OpenProjectFiles() #define KICTL_OPEN_APPEND (1<<0) ///< append the data file, rather than replace @@ -149,7 +154,7 @@ public: * * @return bool - true if all requested files were opened OK, else false. */ - virtual bool OpenProjectFiles( const std::vector& aFileList, int aCtl = 0 ) + VTBL_ENTRY bool OpenProjectFiles( const std::vector& aFileList, int aCtl = 0 ) { // overload me for your wxFrame type. @@ -161,6 +166,25 @@ public: return false; } + /** + * Function ShowModal + * puts up this wxFrame as if it were a modal dialog, with all other instantiated + * wxFrames disabled until this KIWAY_PLAYER derivative calls DismissModal(). + * That is, behavior is similar to a modal dialog window. Not all KIWAY_PLAYERs + * use this interface, so don't call this unless the implementation knows how + * to call DismissModal() on a button click or double click or some special + * event which ends the modal behavior. + * + * @param aResult if not NULL, indicates a place to put a resultant string. + * + * @return bool - true if frame implementation called KIWAY_PLAYER::DismissModal() + * with aRetVal of true. + */ + VTBL_ENTRY bool ShowModal( wxString* aResult ); + + //-------------------------------------------------------- + + /** * Function KiwayMailIn * receives KIWAY_EXPRESS messages from other players. Merely override it @@ -168,12 +192,35 @@ public: */ virtual void KiwayMailIn( KIWAY_EXPRESS& aEvent ); - DECLARE_EVENT_TABLE() +protected: -//private: + bool IsModal() { return m_modal_dismissed; } - /// event handler, routes to virtual KiwayMailIn() + /** + * Function IsDismissed + * returns false only if both the frame is acting in modal mode and it has not been + * dismissed yet with DismissModal(). IOW, it will return true if the dialog is + * not modal or if it is modal and has been dismissed. + */ + bool IsDismissed(); + + void DismissModal( bool aRetVal, const wxString& aResult = wxEmptyString ); + + /// event handler, routes to derivative specific virtual KiwayMailIn() void kiway_express( KIWAY_EXPRESS& aEvent ); + + /** + * Function language_change + * is an event handler called on a language menu selection. + */ + void language_change( wxCommandEvent& event ); + + // variables for modal behavior support, only used by a few derivatives. + volatile bool* m_modal_dismissed; // points to "dismissed state", NULL means not modal + wxString m_modal_string; + bool m_modal_ret_val; // true if a selection was made + + DECLARE_EVENT_TABLE() }; diff --git a/include/wxEeschemaStruct.h b/include/wxEeschemaStruct.h index fea2499c69..171351d321 100644 --- a/include/wxEeschemaStruct.h +++ b/include/wxEeschemaStruct.h @@ -813,12 +813,6 @@ private: void OnUpdateBusOrientation( wxUpdateUIEvent& event ); void OnUpdateSelectTool( wxUpdateUIEvent& aEvent ); - /** - * Function SetLanguage - * called on a language menu selection - */ - void SetLanguage( wxCommandEvent& event ); - /** * Function UpdateTitle * sets the main window title bar text. diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 9ad56f1016..21218d78a9 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -1666,11 +1666,7 @@ public: */ MODULE* Genere_Self( wxDC* DC ); - /** - * Function SetLanguage - * called on a language menu selection - */ - virtual void SetLanguage( wxCommandEvent& event ); + void ShowChangedLanguage(); // override EDA_BASE_FRAME virtual /** * Function UpdateTitle diff --git a/include/wxstruct.h b/include/wxstruct.h index 73363cceed..22153455a2 100644 --- a/include/wxstruct.h +++ b/include/wxstruct.h @@ -113,7 +113,7 @@ class EDA_BASE_FRAME : public wxFrame void windowClosing( wxCloseEvent& event ); protected: - FRAME_T m_Ident; ///< Id Type (pcb, schematic, library..) + FRAME_T m_Ident; ///< Id Type (pcb, schematic, library..) wxPoint m_FramePos; wxSize m_FrameSize; @@ -302,13 +302,6 @@ public: */ void ExportHotkeyConfigToFile( struct EDA_HOTKEY_CONFIG* aDescList ); - /** - * Function SetLanguage - * called on a language menu selection - * when using a derived function, do not forget to call this one - */ - virtual void SetLanguage( wxCommandEvent& event ); - /** * Function GetFileFromHistory * fetches the file name from the file history list. @@ -380,17 +373,10 @@ public: void CheckForAutoSaveFile( const wxFileName& aFileName, const wxString& aBackupFileExtension ); /** - * Function SetModalMode - * Disable or enable all other windows, to emulate a dialog behavior - * Useful when the frame is used to show and selec items - * (see FOOTPRINT_VIEWER_FRAME and LIB_VIEW_FRAME) - * - * @param aModal = true to disable all other opened windows (i.e. - * this windows is in dialog mode - * = false to enable other windows - * This function is analog to MakeModal( aModal ), deprecated since wxWidgets 2.9.4 + * Function ShowChangedLanguage + * redraws the menus and what not in current language. */ - void SetModalMode( bool aModal ); + virtual void ShowChangedLanguage(); }; @@ -415,7 +401,6 @@ public: * then after a //==// break has additional calls to anchor toolbars in a way that matches * present functionality. */ - class EDA_PANEINFO : public wxAuiPaneInfo { diff --git a/kicad/kicad.cpp b/kicad/kicad.cpp index 44e9488e56..5b696f5715 100644 --- a/kicad/kicad.cpp +++ b/kicad/kicad.cpp @@ -197,6 +197,8 @@ bool PGM_KICAD::OnPgmInit( wxApp* aWxApp ) void PGM_KICAD::OnPgmExit() { + Kiway.OnKiwayEnd(); + saveCommonSettings(); // write common settings to disk, and destroy everything in PGM_KICAD, @@ -253,7 +255,7 @@ void PGM_KICAD::destroy() } -KIWAY Kiway( &Pgm() ); +KIWAY Kiway( &Pgm(), KFCTL_CPP_PROJECT_SUITE ); /** diff --git a/kicad/kicad.h b/kicad/kicad.h index ffaac5afdc..ab76ac5cbc 100644 --- a/kicad/kicad.h +++ b/kicad/kicad.h @@ -140,6 +140,8 @@ public: private: int m_leftWinWidth; + void language_change( wxCommandEvent& event ); + public: KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title, const wxPoint& pos, const wxSize& size ); @@ -202,7 +204,6 @@ public: */ void ClearMsg(); - void SetLanguage( wxCommandEvent& event ); void OnRefresh( wxCommandEvent& event ); void OnSelectDefaultPdfBrowser( wxCommandEvent& event ); void OnSelectPreferredPdfBrowser( wxCommandEvent& event ); diff --git a/kicad/mainframe.cpp b/kicad/mainframe.cpp index 32d19c8d37..0d965c0af8 100644 --- a/kicad/mainframe.cpp +++ b/kicad/mainframe.cpp @@ -361,6 +361,14 @@ void KICAD_MANAGER_FRAME::OnRefresh( wxCommandEvent& event ) } +void KICAD_MANAGER_FRAME::language_change( wxCommandEvent& event ) +{ + int id = event.GetId(); + + Kiway.SetLanguage( id ); +} + + void KICAD_MANAGER_FRAME::ClearMsg() { m_MessagesBox->Clear(); diff --git a/kicad/menubar.cpp b/kicad/menubar.cpp index 0e1fce998d..e792987a3c 100644 --- a/kicad/menubar.cpp +++ b/kicad/menubar.cpp @@ -33,20 +33,20 @@ #include #include -/* Menubar and toolbar event table */ +// Menubar and toolbar event table BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME ) - /* Window events */ + // Window events EVT_SIZE( KICAD_MANAGER_FRAME::OnSize ) EVT_CLOSE( KICAD_MANAGER_FRAME::OnCloseWindow ) - /* Toolbar events */ + // Toolbar events EVT_TOOL( ID_NEW_PROJECT, KICAD_MANAGER_FRAME::OnLoadProject ) EVT_TOOL( ID_NEW_PROJECT_FROM_TEMPLATE, KICAD_MANAGER_FRAME::OnLoadProject ) EVT_TOOL( ID_LOAD_PROJECT, KICAD_MANAGER_FRAME::OnLoadProject ) EVT_TOOL( ID_SAVE_PROJECT, KICAD_MANAGER_FRAME::OnSaveProject ) EVT_TOOL( ID_SAVE_AND_ZIP_FILES, KICAD_MANAGER_FRAME::OnArchiveFiles ) - /* Menu events */ + // Menu events EVT_MENU( ID_SAVE_PROJECT, KICAD_MANAGER_FRAME::OnSaveProject ) EVT_MENU( wxID_EXIT, KICAD_MANAGER_FRAME::OnExit ) EVT_MENU( ID_TO_EDITOR, KICAD_MANAGER_FRAME::OnOpenTextEditor ) @@ -63,16 +63,17 @@ BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME ) EVT_MENU( wxID_INDEX, KICAD_MANAGER_FRAME::GetKicadHelp ) EVT_MENU( wxID_ABOUT, KICAD_MANAGER_FRAME::GetKicadAbout ) - /* Range menu events */ - EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KICAD_MANAGER_FRAME::SetLanguage ) + // Range menu events + EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KICAD_MANAGER_FRAME::language_change ) + EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, KICAD_MANAGER_FRAME::OnFileHistory ) // Special functions - #ifdef KICAD_USE_FILES_WATCHER +#ifdef KICAD_USE_FILES_WATCHER EVT_MENU( ID_INIT_WATCHED_PATHS, KICAD_MANAGER_FRAME::OnChangeWatchedPaths ) - #endif +#endif - /* Button events */ + // Button events EVT_BUTTON( ID_TO_PCB, KICAD_MANAGER_FRAME::OnRunPcbNew ) EVT_BUTTON( ID_TO_CVPCB, KICAD_MANAGER_FRAME::OnRunCvpcb ) EVT_BUTTON( ID_TO_EESCHEMA, KICAD_MANAGER_FRAME::OnRunEeschema ) diff --git a/kicad/preferences.cpp b/kicad/preferences.cpp index 19bed9f1d1..2176d628bc 100644 --- a/kicad/preferences.cpp +++ b/kicad/preferences.cpp @@ -88,8 +88,3 @@ void KICAD_MANAGER_FRAME::OnSelectPreferredPdfBrowser( wxCommandEvent& event ) Pgm().WritePdfBrowserInfos(); } - -void KICAD_MANAGER_FRAME::SetLanguage( wxCommandEvent& event ) -{ - EDA_BASE_FRAME::SetLanguage( event ); -} diff --git a/pagelayout_editor/events_functions.cpp b/pagelayout_editor/events_functions.cpp index 0473900644..c2fd6982dc 100644 --- a/pagelayout_editor/events_functions.cpp +++ b/pagelayout_editor/events_functions.cpp @@ -70,12 +70,8 @@ BEGIN_EVENT_TABLE( PL_EDITOR_FRAME, EDA_DRAW_FRAME ) EVT_MENU( wxID_EXIT, PL_EDITOR_FRAME::OnQuit ) // menu Preferences - EVT_MENU_RANGE( ID_PREFERENCES_HOTKEY_START, ID_PREFERENCES_HOTKEY_END, - PL_EDITOR_FRAME::Process_Config ) - EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, - EDA_DRAW_FRAME::SetLanguage ) - EVT_MENU( ID_MENU_PL_EDITOR_SELECT_PREFERED_EDITOR, - EDA_BASE_FRAME::OnSelectPreferredEditor ) + EVT_MENU_RANGE( ID_PREFERENCES_HOTKEY_START, ID_PREFERENCES_HOTKEY_END, PL_EDITOR_FRAME::Process_Config ) + EVT_MENU( ID_MENU_PL_EDITOR_SELECT_PREFERED_EDITOR, EDA_BASE_FRAME::OnSelectPreferredEditor ) EVT_MENU( wxID_PREFERENCES, PL_EDITOR_FRAME::Process_Config ) EVT_MENU( ID_MENU_SWITCH_BGCOLOR, PL_EDITOR_FRAME::Process_Config ) EVT_MENU( ID_MENU_GRID_ONOFF, PL_EDITOR_FRAME::Process_Config ) @@ -473,15 +469,6 @@ void PL_EDITOR_FRAME::OnQuit( wxCommandEvent& event ) Close( true ); } -/** - * Function SetLanguage - * called on a language menu selection - * Update Layer manager title and tabs texts - */ -void PL_EDITOR_FRAME::SetLanguage( wxCommandEvent& event ) -{ - EDA_DRAW_FRAME::SetLanguage( event ); -} void PL_EDITOR_FRAME::ToPlotter(wxCommandEvent& event) { diff --git a/pagelayout_editor/pl_editor_frame.h b/pagelayout_editor/pl_editor_frame.h index 7ba3a8dc15..e675cb9c9b 100644 --- a/pagelayout_editor/pl_editor_frame.h +++ b/pagelayout_editor/pl_editor_frame.h @@ -198,12 +198,6 @@ public: void SaveSettings( wxConfigBase* aCfg ); // override virtual - /** - * Function SetLanguage - * called on a language menu selection - */ - virtual void SetLanguage( wxCommandEvent& event ); - void Process_Special_Functions( wxCommandEvent& event ); void OnSelectOptionToolbar( wxCommandEvent& event ); diff --git a/pcb_calculator/CMakeLists.txt b/pcb_calculator/CMakeLists.txt index fb8e189859..14db6b9ff6 100644 --- a/pcb_calculator/CMakeLists.txt +++ b/pcb_calculator/CMakeLists.txt @@ -75,7 +75,7 @@ if( USE_KIWAY_DLLS ) ${PCB_CALCULATOR_RESOURCES} ) set_source_files_properties( ../common/single_top.cpp PROPERTIES - COMPILE_DEFINITIONS "TOP_FRAME=0;BUILD_KIWAY_DLL" + COMPILE_DEFINITIONS "TOP_FRAME=FRAME_CALC;BUILD_KIWAY_DLL" ) target_link_libraries( pcb_calculator #singletop # replaces common, giving us restrictive control and link warnings. @@ -93,7 +93,6 @@ if( USE_KIWAY_DLLS ) add_library( pcb_calculator_kiface MODULE pcb_calculator.cpp ${PCB_CALCULATOR_SRCS} -# ${PCB_CALCULATOR_RESOURCES} ) set_target_properties( pcb_calculator_kiface PROPERTIES OUTPUT_NAME pcb_calculator diff --git a/pcb_calculator/pcb_calculator_frame.cpp b/pcb_calculator/pcb_calculator_frame.cpp index 7981201e25..3abd3601f2 100644 --- a/pcb_calculator/pcb_calculator_frame.cpp +++ b/pcb_calculator/pcb_calculator_frame.cpp @@ -134,6 +134,7 @@ PCB_CALCULATOR_FRAME::~PCB_CALCULATOR_FRAME() this->Freeze(); } + void PCB_CALCULATOR_FRAME::OnClosePcbCalc( wxCloseEvent& event ) { if( m_RegulatorListChanged ) diff --git a/pcbnew/block_module_editor.cpp b/pcbnew/block_module_editor.cpp index 9fc22bd1e1..abba8d6d01 100644 --- a/pcbnew/block_module_editor.cpp +++ b/pcbnew/block_module_editor.cpp @@ -306,7 +306,7 @@ static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wx bool aErase ) { BASE_SCREEN* screen = aPanel->GetScreen(); - FOOTPRINT_EDIT_FRAME* moduleEditFrame = FOOTPRINT_EDIT_FRAME::GetActiveFootprintEditor( aPanel->GetParent() ); + FOOTPRINT_EDIT_FRAME* moduleEditFrame = dynamic_cast( aPanel->GetParent() ); wxASSERT( moduleEditFrame ); MODULE* currentModule = moduleEditFrame->GetBoard()->m_Modules; diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index 98a3ec4fee..e76623b0e4 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -190,21 +190,21 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_OPEN_MODULE_EDITOR: { - FOOTPRINT_EDIT_FRAME* editor = FOOTPRINT_EDIT_FRAME::GetActiveFootprintEditor( this ); + FOOTPRINT_EDIT_FRAME* editor = (FOOTPRINT_EDIT_FRAME*) Kiway().Player( FRAME_PCB_MODULE_EDITOR, false ); if( !editor ) { - KIFACE_I& kf = Kiface(); - - editor = (FOOTPRINT_EDIT_FRAME*) kf.CreateWindow( this, FRAME_PCB_MODULE_EDITOR, &Kiway(), kf.StartFlags() ); + editor = (FOOTPRINT_EDIT_FRAME*) Kiway().Player( FRAME_PCB_MODULE_EDITOR, true ); editor->Show( true ); editor->Zoom_Automatique( false ); } else { + /* not needed on linux, other platforms need this? if( editor->IsIconized() ) editor->Iconize( false ); + */ editor->Raise(); @@ -218,21 +218,21 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_OPEN_MODULE_VIEWER: { - FOOTPRINT_VIEWER_FRAME* viewer = FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer( this ); + FOOTPRINT_VIEWER_FRAME* viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, false ); if( !viewer ) { - KIFACE_I& kf = Kiface(); - - viewer = (FOOTPRINT_VIEWER_FRAME*) kf.CreateWindow( this, FRAME_PCB_MODULE_VIEWER, &Kiway(), kf.StartFlags() ); + viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, true ); viewer->Show( true ); viewer->Zoom_Automatique( false ); } else { + /* not needed on linux, other platforms need this? if( viewer->IsIconized() ) viewer->Iconize( false ); + */ viewer->Raise(); @@ -848,20 +848,14 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) } { - FOOTPRINT_EDIT_FRAME* editor = FOOTPRINT_EDIT_FRAME::GetActiveFootprintEditor( this ); - - if( !editor ) - { - KIFACE_I& kf = Kiface(); - - editor = (FOOTPRINT_EDIT_FRAME*) kf.CreateWindow( this, FRAME_PCB_MODULE_EDITOR, &Kiway(), kf.StartFlags() ); - } + FOOTPRINT_EDIT_FRAME* editor = (FOOTPRINT_EDIT_FRAME*) Kiway().Player( FRAME_PCB_MODULE_EDITOR, true ); editor->Load_Module_From_BOARD( (MODULE*)GetCurItem() ); SetCurItem( NULL ); // the current module could be deleted by editor->Show( true ); - editor->Iconize( false ); + + editor->Raise(); // Iconize( false ); } m_canvas->MoveCursorToCrossHair(); break; diff --git a/pcbnew/editmod.cpp b/pcbnew/editmod.cpp index 49325bc1eb..4a69ef6a02 100644 --- a/pcbnew/editmod.cpp +++ b/pcbnew/editmod.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -74,20 +75,13 @@ void PCB_EDIT_FRAME::InstallModuleOptionsFrame( MODULE* Module, wxDC* DC ) if( retvalue == 2 ) { - FOOTPRINT_EDIT_FRAME* editor = FOOTPRINT_EDIT_FRAME::GetActiveFootprintEditor( this ); - - if( !editor ) - { - KIFACE_I& kf = Kiface(); - - editor = (FOOTPRINT_EDIT_FRAME*) kf.CreateWindow( this, FRAME_PCB_MODULE_EDITOR, &Kiway(), kf.StartFlags() ); - } + FOOTPRINT_EDIT_FRAME* editor = (FOOTPRINT_EDIT_FRAME*) Kiway().Player( FRAME_PCB_MODULE_EDITOR, true ); editor->Load_Module_From_BOARD( Module ); SetCurItem( NULL ); editor->Show( true ); - editor->Iconize( false ); + editor->Raise(); // Iconize( false ); } } diff --git a/pcbnew/footprint_wizard.cpp b/pcbnew/footprint_wizard.cpp index e82db334fc..ab4023846a 100644 --- a/pcbnew/footprint_wizard.cpp +++ b/pcbnew/footprint_wizard.cpp @@ -145,7 +145,7 @@ MODULE* FOOTPRINT_WIZARD_FRAME::GetBuiltFootprint() { FOOTPRINT_WIZARD* footprintWizard = FOOTPRINT_WIZARDS::GetWizard( m_wizardName ); - if( footprintWizard && m_exportRequest ) + if( footprintWizard && m_modal_ret_val ) { return footprintWizard->GetModule(); } diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp index b09623f074..7fac217892 100644 --- a/pcbnew/footprint_wizard_frame.cpp +++ b/pcbnew/footprint_wizard_frame.cpp @@ -113,18 +113,18 @@ static wxAcceleratorEntry accels[] = #define EXTRA_BORDER_SIZE 2 -/* Function FOOTPRINT_WIZARD_FRAME - * it's the constructor for the footprint wizard frame, it creates everything inside - */ #define FOOTPRINT_WIZARD_FRAME_NAME wxT( "FootprintWizard" ) -FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, FOOTPRINT_EDIT_FRAME* aParent, - wxSemaphore* semaphore, long style ) : - PCB_BASE_FRAME( aKiway, aParent, FRAME_PCB_FOOTPRINT_WIZARD, - _( "Footprint Wizard" ), - wxDefaultPosition, wxDefaultSize, style, FOOTPRINT_WIZARD_FRAME_NAME ) +FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, + wxWindow* aParent, FRAME_T aFrameType ) : + PCB_BASE_FRAME( aKiway, aParent, aFrameType, _( "Footprint Wizard" ), + wxDefaultPosition, wxDefaultSize, + KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT, + FOOTPRINT_WIZARD_FRAME_NAME ) { + wxASSERT( aFrameType==FRAME_PCB_FOOTPRINT_WIZARD_MODAL ); + wxAcceleratorTable table( ACCEL_TABLE_CNT, accels ); m_FrameName = FOOTPRINT_WIZARD_FRAME_NAME; @@ -137,14 +137,10 @@ FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, FOOTPRINT_EDIT_FR SetIcon( icon ); m_HotkeysZoomAndGridList = g_Module_Viewer_Hokeys_Descr; - m_semaphore = semaphore; m_wizardName.Empty(); - m_exportRequest = false; - - if( m_semaphore ) - SetModalMode( true ); SetBoard( new BOARD() ); + // Ensure all layers and items are visible: GetBoard()->SetVisibleAlls(); SetScreen( new PCB_SCREEN( GetPageSizeIU() ) ); @@ -244,17 +240,14 @@ FOOTPRINT_WIZARD_FRAME::~FOOTPRINT_WIZARD_FRAME() } -/* Function OnCloseWindow - * Handles the close event, saving settings an destroying or releasing a semaphore from caller - */ void FOOTPRINT_WIZARD_FRAME::OnCloseWindow( wxCloseEvent& Event ) { - if( m_semaphore ) + if( IsModal() ) { - m_semaphore->Post(); - SetModalMode( false ); - // This window will be destroyed by the calling function, - // to avoid side effects + // Only dismiss a modal frame once, so that the return values set by + // the prior DismissModal() are not bashed for ShowModal(). + if( !IsDismissed() ) + DismissModal( false ); } else { @@ -265,15 +258,11 @@ void FOOTPRINT_WIZARD_FRAME::OnCloseWindow( wxCloseEvent& Event ) void FOOTPRINT_WIZARD_FRAME::ExportSelectedFootprint( wxCommandEvent& aEvent ) { - m_exportRequest = true; + DismissModal( true ); Close(); } -/* Function OnSize - * It handles a dialog resize event, asking for an update - * - */ void FOOTPRINT_WIZARD_FRAME::OnSize( wxSizeEvent& SizeEv ) { if( m_auimgr.GetManagedWindow() ) @@ -283,10 +272,6 @@ void FOOTPRINT_WIZARD_FRAME::OnSize( wxSizeEvent& SizeEv ) } -/* Function OnSetRelativeOffset - * Updates the cursor position and the status bar - * - */ void FOOTPRINT_WIZARD_FRAME::OnSetRelativeOffset( wxCommandEvent& event ) { GetScreen()->m_O_Curseur = GetCrossHairPosition(); @@ -294,10 +279,6 @@ void FOOTPRINT_WIZARD_FRAME::OnSetRelativeOffset( wxCommandEvent& event ) } -/* Function ReCreatePageList - * It recreates the list of pages for a new loaded wizard - * - */ void FOOTPRINT_WIZARD_FRAME::ReCreatePageList() { if( m_pageList == NULL ) @@ -326,11 +307,6 @@ void FOOTPRINT_WIZARD_FRAME::ReCreatePageList() } -/* Function ReCreateParameterList - * It creates the parameter grid for a certain wizard page of the current wizard - * - */ - void FOOTPRINT_WIZARD_FRAME::ReCreateParameterList() { if( m_parameterGrid == NULL ) @@ -620,7 +596,7 @@ void FOOTPRINT_WIZARD_FRAME::ReCreateHToolbar() { wxString msg; - if( m_mainToolBar == NULL ) + if( !m_mainToolBar ) { m_mainToolBar = new wxAuiToolBar( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_HORZ_LAYOUT ); @@ -665,7 +641,7 @@ void FOOTPRINT_WIZARD_FRAME::ReCreateHToolbar() m_mainToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); - if( m_semaphore ) + if( m_Ident == FRAME_PCB_FOOTPRINT_WIZARD_MODAL ) { // The library browser is called from a "load component" command m_mainToolBar->AddSeparator(); diff --git a/pcbnew/footprint_wizard_frame.h b/pcbnew/footprint_wizard_frame.h index c36ecc70c3..d65c309f34 100644 --- a/pcbnew/footprint_wizard_frame.h +++ b/pcbnew/footprint_wizard_frame.h @@ -35,41 +35,37 @@ #include class wxSashLayoutWindow; class wxListBox; -class wxSemaphore; class wxGrid; class wxGridEvent; class FOOTPRINT_EDIT_FRAME; /** - * Component library viewer main window. + * Class FOOTPRINT_WIZARD_FRAME */ class FOOTPRINT_WIZARD_FRAME : public PCB_BASE_FRAME { private: - wxListBox* m_pageList; // < The list of pages - int m_pageListWidth; // < width of the window - wxGrid* m_parameterGrid; // < The list of parameters - int m_parameterGridWidth; // < size of the grid + wxListBox* m_pageList; ///< The list of pages + int m_pageListWidth; ///< width of the window + wxGrid* m_parameterGrid; ///< The list of parameters + int m_parameterGridWidth; ///< size of the grid // Flags - wxSemaphore* m_semaphore; // < != NULL if the frame must emulate a modal dialog - wxString m_configPath; // < subpath for configuration - bool m_exportRequest; // < true if the current footprint should be exported + wxString m_configPath; ///< subpath for configuration protected: - wxString m_wizardName; // < name of the current wizard - wxString m_wizardDescription; // < description of the wizard - wxString m_wizardStatus; // < current wizard status + wxString m_wizardName; ///< name of the current wizard + wxString m_wizardDescription; ///< description of the wizard + wxString m_wizardStatus; ///< current wizard status public: - FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, - FOOTPRINT_EDIT_FRAME* parent, wxSemaphore* semaphore = NULL, - long style = KICAD_DEFAULT_DRAWFRAME_STYLE ); + + FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, wxWindow* parent, FRAME_T aFrameType ); ~FOOTPRINT_WIZARD_FRAME(); - MODULE* GetBuiltFootprint( void ); + MODULE* GetBuiltFootprint(); private: diff --git a/pcbnew/gpcb_plugin.cpp b/pcbnew/gpcb_plugin.cpp index 7585aad4f9..1f207eaaa6 100644 --- a/pcbnew/gpcb_plugin.cpp +++ b/pcbnew/gpcb_plugin.cpp @@ -285,7 +285,7 @@ void GPCB_FPL_CACHE::Load() MODULE* footprint = parseMODULE( &reader ); // The footprint name is the file name without the extension. - footprint->SetFPID( fn.GetName() ); + footprint->SetFPID( FPID( fn.GetName() ) ); m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) ); } while( dir.GetNext( &fpFileName ) ); @@ -299,7 +299,6 @@ void GPCB_FPL_CACHE::Load() void GPCB_FPL_CACHE::Remove( const wxString& aFootprintName ) { - std::string footprintName = TO_UTF8( aFootprintName ); MODULE_CITER it = m_modules.find( footprintName ); diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index fd7059399a..80015dc147 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -279,7 +279,7 @@ void FP_CACHE::Load() MODULE* footprint = (MODULE*) m_owner->m_parser->Parse(); // The footprint name is the file name without the extension. - footprint->SetFPID( fullPath.GetName() ); + footprint->SetFPID( FPID( fullPath.GetName() ) ); m_modules.insert( name, new FP_CACHE_ITEM( footprint, fullPath ) ); } while( dir.GetNext( &fpFileName ) ); @@ -657,14 +657,14 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const m_out->Print( aNestLevel, ")\n\n" ); - // Save net codes and names + // Save net codes and names for( NETINFO_MAPPING::iterator net = m_mapping->begin(), netEnd = m_mapping->end(); net != netEnd; ++net ) { m_out->Print( aNestLevel, "(net %d %s)\n", m_mapping->Translate( net->GetNet() ), m_out->Quotew( net->GetNetname() ).c_str() ); - } + } m_out->Print( 0, "\n" ); diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index d8e47c0e46..487f356e6a 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -620,7 +620,7 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibrary, if( footprintName.IsEmpty() ) { footprintName = wxT("noname"); - aModule->SetFPID( footprintName ); + aModule->SetFPID( FPID( footprintName ) ); } bool module_exists = false; diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index 6c324b4d65..3aca4d620f 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +//#include #include #include #include @@ -118,32 +120,21 @@ bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) wxString PCB_BASE_FRAME::SelectFootprintFromLibBrowser() { - wxString fpname; - wxString fpid; + // Close the current non-modal Lib browser if opened, and open a new one, in "modal" mode: + FOOTPRINT_VIEWER_FRAME* viewer; - wxSemaphore semaphore( 0, 1 ); - - // Close the current Lib browser, if opened, and open a new one, in "modal" mode: - FOOTPRINT_VIEWER_FRAME* viewer = FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer( this ); + viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, false ); if( viewer ) viewer->Destroy(); - viewer = new FOOTPRINT_VIEWER_FRAME( &Kiway(), this, &semaphore ); + viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true ); - // Show the library viewer frame until it is closed - while( semaphore.TryWait() == wxSEMA_BUSY ) // Wait for viewer closing event - { - wxYield(); - wxMilliSleep( 50 ); - } + wxString fpid; - fpname = viewer->GetSelectedFootprint(); + viewer->ShowModal( &fpid ); - if( !!fpname ) - { - fpid = viewer->GetSelectedLibrary() + wxT( ":" ) + fpname; - } + //DBG(printf("%s: fpid:'%s'\n", __func__, TO_UTF8( fpid ) );) viewer->Destroy(); diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index c9198d4a41..73a20509f8 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -262,25 +263,19 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_OPEN_MODULE_VIEWER: { - // Make a _project specific_ PCB_EDIT_FRAME be the start of the search in - // FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer(); - - PCB_EDIT_FRAME* top_project = dynamic_cast( GetParent() ); - wxASSERT( top_project ); // dynamic_cast returns NULL if class mismatch. - - FOOTPRINT_VIEWER_FRAME* viewer = FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer( top_project ); + FOOTPRINT_VIEWER_FRAME* viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, false ); if( !viewer ) { - KIFACE_I& kf = Kiface(); - - viewer = (FOOTPRINT_VIEWER_FRAME*) kf.CreateWindow( this, FRAME_PCB_MODULE_VIEWER, &Kiway(), kf.StartFlags() ); + viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, true ); viewer->Show( true ); viewer->Zoom_Automatique( false ); } else { + /* if( viewer->IsIconized() ) viewer->Iconize( false ); + */ viewer->Raise(); @@ -324,41 +319,37 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_MODEDIT_NEW_MODULE_FROM_WIZARD: { - wxSemaphore semaphore( 0, 1 ); + FOOTPRINT_WIZARD_FRAME* wizard = (FOOTPRINT_WIZARD_FRAME*) Kiway().Player( + FRAME_PCB_FOOTPRINT_WIZARD_MODAL, true ); - FOOTPRINT_WIZARD_FRAME* wizard = new FOOTPRINT_WIZARD_FRAME( &Kiway(), this, &semaphore, - KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT ); - - wizard->Show( true ); wizard->Zoom_Automatique( false ); - while( semaphore.TryWait() == wxSEMA_BUSY ) // Wait for viewer closing event + wxString not_used; + + if( wizard->ShowModal( ¬_used ) ) { - wxYield(); - wxMilliSleep( 50 ); - } + // Creates the new footprint from python script wizard + MODULE* module = wizard->GetBuiltFootprint(); - // Creates the new footprint from python script wizard - MODULE* module = wizard->GetBuiltFootprint(); + if( module ) // i.e. if create module command not aborted + { + Clear_Pcb( true ); + GetScreen()->ClearUndoRedoList(); + SetCurItem( NULL ); + SetCrossHairPosition( wxPoint( 0, 0 ) ); - if( module ) // i.e. if create module command not aborted - { - Clear_Pcb( true ); - GetScreen()->ClearUndoRedoList(); - SetCurItem( NULL ); - SetCrossHairPosition( wxPoint( 0, 0 ) ); + // Add the new object to board + module->SetParent( (EDA_ITEM*)GetBoard() ); + GetBoard()->m_Modules.Append( module ); - // Add the new object to board - module->SetParent( (EDA_ITEM*)GetBoard() ); - GetBoard()->m_Modules.Append( module ); - - // 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->ClearFlags(); + // 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->ClearFlags(); + } } wizard->Destroy(); @@ -378,7 +369,8 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) { // update module in the current board, // not just add it to the board with total disregard for the netlist... - PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) GetParent(); + PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, true ); + BOARD* mainpcb = pcbframe->GetBoard(); MODULE* source_module = NULL; MODULE* module_in_edit = GetBoard()->m_Modules; diff --git a/pcbnew/module_editor_frame.h b/pcbnew/module_editor_frame.h index 4378beac06..438c4ed35e 100644 --- a/pcbnew/module_editor_frame.h +++ b/pcbnew/module_editor_frame.h @@ -53,17 +53,6 @@ public: */ static const wxChar* GetFootprintEditorFrameName(); - /** - * Function GetActiveFootprintEditor (static) - * - * @param aTopOfProject is a PCB_EDIT_FRAME* window which anchors the search in - * a project specific way. - * - * @return a reference to the current opened Footprint editor - * or NULL if no Footprint editor currently opened - */ - static FOOTPRINT_EDIT_FRAME* GetActiveFootprintEditor( const wxWindow* aTopOfProject ); - BOARD_DESIGN_SETTINGS& GetDesignSettings() const; // overload PCB_BASE_FRAME, get parent's void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings ); // overload @@ -415,7 +404,7 @@ public: protected: /// protected so only friend PCB::IFACE::CreateWindow() can act as sole factory. - FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, PCB_EDIT_FRAME* aParent ); + FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ); static BOARD* s_Pcb; ///< retain board across invocations of module editor diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index cb7a0425fc..c2a9b93d4e 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -151,7 +151,7 @@ END_EVENT_TABLE() #define FOOTPRINT_EDIT_FRAME_NAME wxT( "ModEditFrame" ) -FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, PCB_EDIT_FRAME* aParent ) : +FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : PCB_BASE_FRAME( aKiway, aParent, FRAME_PCB_MODULE_EDITOR, wxEmptyString, wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, GetFootprintEditorFrameName() ) @@ -291,19 +291,6 @@ const wxChar* FOOTPRINT_EDIT_FRAME::GetFootprintEditorFrameName() } -/* return a reference to the current opened Footprint editor - * or NULL if no Footprint editor currently opened - */ -FOOTPRINT_EDIT_FRAME* FOOTPRINT_EDIT_FRAME::GetActiveFootprintEditor( const wxWindow* aParent ) -{ - // top_of_project! - wxASSERT( dynamic_cast( aParent ) ); - - wxWindow* ret = wxWindow::FindWindowByName( GetFootprintEditorFrameName(), aParent ); - return (FOOTPRINT_EDIT_FRAME*) ret; -} - - BOARD_DESIGN_SETTINGS& FOOTPRINT_EDIT_FRAME::GetDesignSettings() const { // get the BOARD_DESIGN_SETTINGS from the parent editor, not our BOARD. diff --git a/pcbnew/modview_frame.cpp b/pcbnew/modview_frame.cpp index 30bb30063e..1db99caf30 100644 --- a/pcbnew/modview_frame.cpp +++ b/pcbnew/modview_frame.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -70,12 +71,12 @@ wxString FOOTPRINT_VIEWER_FRAME::m_selectedFootprintName; BEGIN_EVENT_TABLE( FOOTPRINT_VIEWER_FRAME, EDA_DRAW_FRAME ) - /* Window events */ + // Window events EVT_CLOSE( FOOTPRINT_VIEWER_FRAME::OnCloseWindow ) EVT_SIZE( FOOTPRINT_VIEWER_FRAME::OnSize ) EVT_ACTIVATE( FOOTPRINT_VIEWER_FRAME::OnActivate ) - /* Toolbar events */ + // Toolbar events EVT_TOOL( ID_MODVIEW_SELECT_LIB, FOOTPRINT_VIEWER_FRAME::SelectCurrentLibrary ) EVT_TOOL( ID_MODVIEW_SELECT_PART, @@ -88,7 +89,7 @@ BEGIN_EVENT_TABLE( FOOTPRINT_VIEWER_FRAME, EDA_DRAW_FRAME ) FOOTPRINT_VIEWER_FRAME::ExportSelectedFootprint ) EVT_TOOL( ID_MODVIEW_SHOW_3D_VIEW, FOOTPRINT_VIEWER_FRAME::Show3D_Frame ) - /* listbox events */ + // listbox events EVT_LISTBOX( ID_MODVIEW_LIB_LIST, FOOTPRINT_VIEWER_FRAME::ClickOnLibList ) EVT_LISTBOX( ID_MODVIEW_FOOTPRINT_LIST, FOOTPRINT_VIEWER_FRAME::ClickOnFootprintList ) EVT_LISTBOX_DCLICK( ID_MODVIEW_FOOTPRINT_LIST, FOOTPRINT_VIEWER_FRAME::DClickOnFootprintList ) @@ -118,14 +119,16 @@ static wxAcceleratorEntry accels[] = #define FOOTPRINT_VIEWER_FRAME_NAME wxT( "ModViewFrame" ) -FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent, wxSemaphore* aSemaphore ) : - PCB_BASE_FRAME( aKiway, aParent, FRAME_PCB_MODULE_VIEWER, _( "Footprint Library Browser" ), +FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType ) : + PCB_BASE_FRAME( aKiway, aParent, aFrameType, _( "Footprint Library Browser" ), wxDefaultPosition, wxDefaultSize, - !aSemaphore ? - KICAD_DEFAULT_DRAWFRAME_STYLE : - KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT, + aFrameType == FRAME_PCB_MODULE_VIEWER_MODAL ? + KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT : + KICAD_DEFAULT_DRAWFRAME_STYLE, GetFootprintViewerFrameName() ) { + wxASSERT( aFrameType==FRAME_PCB_MODULE_VIEWER || aFrameType==FRAME_PCB_MODULE_VIEWER_MODAL ); + wxAcceleratorTable table( DIM( accels ), accels ); m_FrameName = GetFootprintViewerFrameName(); @@ -145,12 +148,8 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* a m_footprintList = new wxListBox( this, ID_MODVIEW_FOOTPRINT_LIST, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_HSCROLL ); - m_semaphore = aSemaphore; m_selectedFootprintName.Empty(); - if( m_semaphore ) - SetModalMode( true ); - SetBoard( new BOARD() ); // Ensure all layers and items are visible: @@ -237,7 +236,6 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* a } #if 0 // no. - // Set min size (overwrite params read in LoadPerspective(), if any) m_auimgr.GetPane( m_libList ).MinSize( minsize ); m_auimgr.GetPane( m_footprintList ).MinSize( minsize ); @@ -271,45 +269,16 @@ const wxChar* FOOTPRINT_VIEWER_FRAME::GetFootprintViewerFrameName() } -FOOTPRINT_VIEWER_FRAME* FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer( const KIWAY_PLAYER* aParent ) -{ - wxASSERT( aParent ); - - // We search only within the current project, and do so by limiting - // the search scope to a wxWindow hierarchy subset. Find the top most - // KIWAY_PLAYER which is part of this PROJECT by matching its KIWAY* to the - // most immediate parent's. - - // NOTE: an open FOOTPRINT_VIEWER_FRAME may have either the PCB_EDIT_FRAME - // or the FOOTPRINT_EDIT_FRAME as parent. - - KIWAY* kiway = &aParent->Kiway(); - wxWindow* frame; - - while( (frame = aParent->GetParent()) != NULL ) - { - // will go NULL when we reach a non-KIWAY_PLAYER - KIWAY_PLAYER* kwp = dynamic_cast( frame ); - - if( kwp && &kwp->Kiway() == kiway ) - aParent = kwp; - else - break; - } - - return (FOOTPRINT_VIEWER_FRAME*) wxWindow::FindWindowByName( - GetFootprintViewerFrameName(), aParent ); -} - - void FOOTPRINT_VIEWER_FRAME::OnCloseWindow( wxCloseEvent& Event ) { - if( m_semaphore ) + if( IsModal() ) { - m_semaphore->Post(); - SetModalMode( false ); - // This window will be destroyed by the calling function, - // to avoid side effects + // Only dismiss a modal frame once, so that the return values set by + // the prior DismissModal() are not bashed for ShowModal(). + if( !IsDismissed() ) + DismissModal( false ); + + // window will be destroyed by the calling function. } else Destroy(); @@ -464,15 +433,23 @@ void FOOTPRINT_VIEWER_FRAME::ClickOnFootprintList( wxCommandEvent& event ) void FOOTPRINT_VIEWER_FRAME::DClickOnFootprintList( wxCommandEvent& event ) { - if( m_semaphore ) + if( IsModal() ) { + // @todo(DICK) ExportSelectedFootprint( event ); + // Prevent the double click from being as a single mouse button release // event in the parent window which would cause the part to be parked - // rather than staying in mode mode. + // rather than staying in move mode. // Remember the mouse button will be released in the parent window // thus creating a mouse button release event which should be ignored - ((PCB_BASE_FRAME*)GetParent())->SkipNextLeftButtonReleaseEvent(); + PCB_EDIT_FRAME* pcbframe = dynamic_cast( GetParent() ); + + // The parent may not be the board editor: + if( pcbframe ) + { + pcbframe->SkipNextLeftButtonReleaseEvent(); + } } } @@ -482,9 +459,24 @@ void FOOTPRINT_VIEWER_FRAME::ExportSelectedFootprint( wxCommandEvent& event ) int ii = m_footprintList->GetSelection(); if( ii >= 0 ) - m_selectedFootprintName = m_footprintList->GetString( ii ); + { + wxString fp_name = m_footprintList->GetString( ii ); + + // @todo(DICK) assign to static now, later PROJECT retained string. + m_selectedFootprintName = fp_name; + + FPID fpid; + + fpid.SetLibNickname( GetSelectedLibrary() ); + fpid.SetFootprintName( fp_name ); + + DismissModal( true, fpid.Format() ); + } else + { m_selectedFootprintName.Empty(); + DismissModal( false ); + } Close( true ); } @@ -580,25 +572,25 @@ void FOOTPRINT_VIEWER_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition screen->m_O_Curseur = GetCrossHairPosition(); break; - case WXK_NUMPAD8: /* cursor moved up */ + case WXK_NUMPAD8: // cursor moved up case WXK_UP: pos.y -= KiROUND( gridSize.y ); m_canvas->MoveCursor( pos ); break; - case WXK_NUMPAD2: /* cursor moved down */ + case WXK_NUMPAD2: // cursor moved down case WXK_DOWN: pos.y += KiROUND( gridSize.y ); m_canvas->MoveCursor( pos ); break; - case WXK_NUMPAD4: /* cursor moved left */ + case WXK_NUMPAD4: // cursor moved left case WXK_LEFT: pos.x -= KiROUND( gridSize.x ); m_canvas->MoveCursor( pos ); break; - case WXK_NUMPAD6: /* cursor moved right */ + case WXK_NUMPAD6: // cursor moved right case WXK_RIGHT: pos.x += KiROUND( gridSize.x ); m_canvas->MoveCursor( pos ); @@ -621,7 +613,7 @@ void FOOTPRINT_VIEWER_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition } } - UpdateStatusBar(); /* Display new cursor coordinates */ + UpdateStatusBar(); // Display new cursor coordinates } @@ -746,11 +738,13 @@ void FOOTPRINT_VIEWER_FRAME::SelectCurrentLibrary( wxCommandEvent& event ) void FOOTPRINT_VIEWER_FRAME::SelectCurrentFootprint( wxCommandEvent& event ) { - PCB_EDIT_FRAME* parent = (PCB_EDIT_FRAME*) GetParent(); + // The PCB_EDIT_FRAME may not be the FOOTPRINT_VIEW_FRAME's parent, + // so use Kiway().Player() to fetch. + PCB_EDIT_FRAME* parent = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, true ); + wxString libname = m_libraryName + wxT( "." ) + LegacyFootprintLibPathExtension; MODULE* oldmodule = GetBoard()->m_Modules; - MODULE* module = LoadModuleFromLibrary( libname, parent->FootprintLibs(), - false ); + MODULE* module = LoadModuleFromLibrary( libname, parent->FootprintLibs(), false ); if( module ) { diff --git a/pcbnew/modview_frame.h b/pcbnew/modview_frame.h index dab4432f3b..9595866458 100644 --- a/pcbnew/modview_frame.h +++ b/pcbnew/modview_frame.h @@ -34,7 +34,6 @@ class wxSashLayoutWindow; class wxListBox; -class wxSemaphore; class FP_LIB_TABLE; namespace PCB { struct IFACE; } @@ -44,25 +43,13 @@ namespace PCB { struct IFACE; } */ class FOOTPRINT_VIEWER_FRAME : public PCB_BASE_FRAME { - friend struct PCB::IFACE; - -private: - wxListBox* m_libList; // The list of libs names - wxListBox* m_footprintList; // The list of footprint names - - // Flags - wxSemaphore* m_semaphore; // != NULL if the frame emulates a modal dialog - wxString m_configPath; // subpath for configuration + friend struct PCB::IFACE; // constructor called from here only protected: - static wxString m_libraryName; // Current selected library - static wxString m_footprintName; // Current selected footprint - static wxString m_selectedFootprintName; // When the viewer is used to select a footprint - // the selected footprint is here + FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType ); + public: - FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent, wxSemaphore* aSemaphore = NULL ); - ~FOOTPRINT_VIEWER_FRAME(); /** @@ -72,17 +59,6 @@ public: */ static const wxChar* GetFootprintViewerFrameName(); - /** - * Function GetActiveFootprintViewer (static) - * - * @param aParent the KIWAY_PLAYER which is the parent of the calling wxWindow. - * This is used to traverse the window hierarchy upwards to the topmost - * KIWAY_PLAYER which is still part of the same project. - * - * @return Any currently opened Footprint viewer or NULL if none. - */ - static FOOTPRINT_VIEWER_FRAME* GetActiveFootprintViewer( const KIWAY_PLAYER* aParent ); - wxString& GetSelectedFootprint( void ) const { return m_selectedFootprintName; } const wxString GetSelectedLibraryFullName(); @@ -102,8 +78,19 @@ public: */ void ReCreateLibraryList(); + private: + wxListBox* m_libList; // The list of libs names + wxListBox* m_footprintList; // The list of footprint names + + wxString m_configPath; // subpath for configuration + + static wxString m_libraryName; // Current selected library + static wxString m_footprintName; // Current selected footprint + static wxString m_selectedFootprintName; // When the viewer is used to select a footprint + + void OnSize( wxSizeEvent& event ); void ReCreateFootprintList(); @@ -193,7 +180,6 @@ private: void SaveCopyInUndoList( BOARD_ITEM*, UNDO_REDO_T, const wxPoint& ) {} void SaveCopyInUndoList( const PICKED_ITEMS_LIST&, UNDO_REDO_T, const wxPoint &) {} - DECLARE_EVENT_TABLE() }; diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 04ecd6af0b..a95e7804fa 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -152,8 +152,6 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_MENU( ID_PCB_DISPLAY_OPTIONS_SETUP, PCB_EDIT_FRAME::InstallDisplayOptionsDialog ) EVT_MENU( ID_PCB_USER_GRID_SETUP, PCB_EDIT_FRAME::Process_Special_Functions ) - EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, PCB_EDIT_FRAME::SetLanguage ) - // menu Postprocess EVT_MENU( ID_PCB_GEN_POS_MODULES_FILE, PCB_EDIT_FRAME::GenFootprintsPositionFile ) EVT_MENU( ID_PCB_GEN_DRILL_FILE, PCB_EDIT_FRAME::InstallDrillFrame ) @@ -1024,9 +1022,11 @@ void PCB_EDIT_FRAME::SetVisibleAlls() } -void PCB_EDIT_FRAME::SetLanguage( wxCommandEvent& event ) +void PCB_EDIT_FRAME::ShowChangedLanguage() { - EDA_DRAW_FRAME::SetLanguage( event ); + // call my base class + PCB_BASE_FRAME::ShowChangedLanguage(); + m_Layers->SetLayersManagerTabsText(); wxAuiPaneInfo& pane_info = m_auimgr.GetPane( m_Layers ); @@ -1034,10 +1034,6 @@ void PCB_EDIT_FRAME::SetLanguage( wxCommandEvent& event ) pane_info.Caption( _( "Visibles" ) ); m_auimgr.Update(); ReFillLayerWidget(); - - FOOTPRINT_EDIT_FRAME* moduleEditFrame = FOOTPRINT_EDIT_FRAME::GetActiveFootprintEditor( this ); - if( moduleEditFrame ) - moduleEditFrame->EDA_DRAW_FRAME::SetLanguage( event ); } diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 3c47fb7f3d..793a537885 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -60,6 +60,7 @@ #include #include #include +#include // Colors for layers and items @@ -109,7 +110,6 @@ static struct IFACE : public KIFACE_I { switch( aClassId ) { - case FRAME_PCB: { PCB_EDIT_FRAME* frame = new PCB_EDIT_FRAME( aKiway, aParent ); @@ -132,11 +132,7 @@ static struct IFACE : public KIFACE_I case FRAME_PCB_MODULE_EDITOR: { - // yuck: - PCB_EDIT_FRAME* editor = dynamic_cast( aParent ); - wxASSERT( editor ); - - FOOTPRINT_EDIT_FRAME* frame = new FOOTPRINT_EDIT_FRAME( aKiway, editor ); + FOOTPRINT_EDIT_FRAME* frame = new FOOTPRINT_EDIT_FRAME( aKiway, aParent ); frame->Zoom_Automatique( true ); @@ -148,12 +144,10 @@ static struct IFACE : public KIFACE_I break; case FRAME_PCB_MODULE_VIEWER: + case FRAME_PCB_MODULE_VIEWER_MODAL: { - // yuck: - PCB_BASE_FRAME* editor = dynamic_cast( aParent ); - wxASSERT( editor ); - - FOOTPRINT_VIEWER_FRAME* frame = new FOOTPRINT_VIEWER_FRAME( aKiway, editor ); + FOOTPRINT_VIEWER_FRAME* frame = new FOOTPRINT_VIEWER_FRAME( + aKiway, aParent, FRAME_T( aClassId ) ); frame->Zoom_Automatique( true ); @@ -164,6 +158,15 @@ static struct IFACE : public KIFACE_I } break; + case FRAME_PCB_FOOTPRINT_WIZARD_MODAL: + { + FOOTPRINT_WIZARD_FRAME* frame = new FOOTPRINT_WIZARD_FRAME( + aKiway, aParent, FRAME_T( aClassId ) ); + + return frame; + } + break; + default: ; } diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index a9870c279d..df8df9fcc3 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -142,7 +142,7 @@ void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) FOOTPRINT_VIEWER_FRAME* viewer; - if( tableChanged && (viewer = FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer( this )) != NULL ) + if( tableChanged && (viewer = (FOOTPRINT_VIEWER_FRAME*)Kiway().Player( FRAME_PCB_MODULE_VIEWER, false )) != NULL ) { viewer->ReCreateLibraryList(); } diff --git a/pcbnew/tool_modview.cpp b/pcbnew/tool_modview.cpp index 02fccab586..3994a2a96d 100644 --- a/pcbnew/tool_modview.cpp +++ b/pcbnew/tool_modview.cpp @@ -95,9 +95,8 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateHToolbar() m_mainToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); - // Enable this tool only if the library browser is called from - // a "load component" command - if( m_semaphore ) + // Enable this tool only if the library browser is intended for modal use. + if( m_Ident == FRAME_PCB_MODULE_VIEWER_MODAL ) { m_mainToolBar->AddSeparator(); m_mainToolBar->AddTool( ID_MODVIEW_FOOTPRINT_EXPORT_TO_BOARD, wxEmptyString, From f16f248bf96ce56a9b8cd8d68836335f1dd60167 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sat, 3 May 2014 19:44:57 -0500 Subject: [PATCH 04/68] Change order of headers for wx 2.8, use wxWindowDisabler not ENABLE_DISABLE. --- common/kiway.cpp | 5 +- common/kiway_player.cpp | 74 +++++++------------ .../dialog_edit_component_in_schematic.cpp | 35 ++++++++- include/kiway_player.h | 2 +- pcbnew/modedit.cpp | 4 +- 5 files changed, 65 insertions(+), 55 deletions(-) diff --git a/common/kiway.cpp b/common/kiway.cpp index a599474f06..8f2ebf9824 100644 --- a/common/kiway.cpp +++ b/common/kiway.cpp @@ -23,8 +23,6 @@ */ #include -#include -#include #include #include @@ -34,6 +32,9 @@ #include #include +#include +#include + KIFACE* KIWAY::m_kiface[KIWAY_FACE_COUNT]; int KIWAY::m_kiface_version[KIWAY_FACE_COUNT]; diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp index 31aca7d1d8..274e4e564c 100644 --- a/common/kiway_player.cpp +++ b/common/kiway_player.cpp @@ -1,3 +1,27 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2014 KiCad Developers, see CHANGELOG.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 + */ + #include @@ -5,6 +29,7 @@ #include #include #include +#include BEGIN_EVENT_TABLE( KIWAY_PLAYER, EDA_BASE_FRAME ) @@ -46,51 +71,6 @@ void KIWAY_PLAYER::KiwayMailIn( KIWAY_EXPRESS& aEvent ) } -static void makeModal( wxFrame* aFrame, bool IsModal ) -{ - // disable or enable all other top level windows -#if wxCHECK_VERSION(2, 9, 4) - wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); - - while( node ) - { - wxWindow* win = node->GetData(); - - if( win != aFrame ) - win->Enable( !IsModal ); - - node = node->GetNext(); - } -#else - // Deprecated since wxWidgets 2.9.4 - aFrame->MakeModal( IsModal ); -#endif -} - - -/** - * toggle global wxFrame enable/disable state, does the re-enable part even - * if an exception is thrown. - */ -struct ENABLE_DISABLE -{ - wxFrame* m_frame; - - ENABLE_DISABLE( wxFrame* aFrame ) : - m_frame( aFrame ) - { - makeModal( aFrame, true ); - } - - ~ENABLE_DISABLE() - { - // Re-enable all frames, (oops, even if they were previously inactive). - // This is probably why this function was deprecated in wx. - makeModal( m_frame, false ); - } -}; - - bool KIWAY_PLAYER::ShowModal( wxString* aResult ) { /* @@ -103,10 +83,10 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult ) vtable and therefore cross-module capable. */ - volatile bool dismissed = false; + volatile bool dismissed = false; // disable all frames except the modal one, re-enable on exit, exception safe. - ENABLE_DISABLE toggle( this ); + wxWindowDisabler toggle( this ); m_modal_dismissed = &dismissed; diff --git a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp index 9a6644d327..4fc02d14fb 100644 --- a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp +++ b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -435,8 +436,38 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::deleteFieldButtonHandler( wxCommandEven void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::showButtonHandler( wxCommandEvent& event ) { - wxString datasheet_uri = fieldValueTextCtrl->GetValue(); - ::wxLaunchDefaultBrowser( datasheet_uri ); +#if 1 + wxString datasheet_uri = fieldValueTextCtrl->GetValue(); + ::wxLaunchDefaultBrowser( datasheet_uri ); + +#else + unsigned fieldNdx = getSelectedFieldNdx(); + +/* + if( fieldNdx == DATASHEET ) + { + wxString datasheet_uri = fieldValueTextCtrl->GetValue(); + ::wxLaunchDefaultBrowser( datasheet_uri ); + } + else if( fieldNdx == FOOTPRINT ) +*/ + { + // pick a footprint + wxString fpid; + + KIWAY_PLAYER* frame = Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true ); + + if( frame->ShowModal( &fpid ) ) + { + printf( "%s: %s\n", __func__, TO_UTF8( fpid ) ); + } + + frame->Show( false ); // keep the frame open, but hidden. + + Raise(); + } +#endif + } diff --git a/include/kiway_player.h b/include/kiway_player.h index 8188ad35c8..6a08e70ed0 100644 --- a/include/kiway_player.h +++ b/include/kiway_player.h @@ -180,7 +180,7 @@ public: * @return bool - true if frame implementation called KIWAY_PLAYER::DismissModal() * with aRetVal of true. */ - VTBL_ENTRY bool ShowModal( wxString* aResult ); + VTBL_ENTRY bool ShowModal( wxString* aResult = NULL ); //-------------------------------------------------------- diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index 73a20509f8..26e6ca7fde 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -324,9 +324,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) wizard->Zoom_Automatique( false ); - wxString not_used; - - if( wizard->ShowModal( ¬_used ) ) + if( wizard->ShowModal() ) { // Creates the new footprint from python script wizard MODULE* module = wizard->GetBuiltFootprint(); From 85c5aa22c6b2c00c381f326df8a3805cc4856de6 Mon Sep 17 00:00:00 2001 From: Lorenzo Marcantonio Date: Sun, 4 May 2014 19:08:36 +0200 Subject: [PATCH 05/68] Constification of HitTest and GetParent In particular HitTest for zones *do not* select the nearest vertex/edge as a side effect --- 3d-viewer/3d_canvas.h | 2 +- 3d-viewer/3d_viewer.h | 2 +- common/draw_panel.cpp | 2 +- .../page_layout/page_layout_graphic_items.cpp | 12 +++--- cvpcb/cvstruct.h | 2 +- cvpcb/listboxes.cpp | 2 +- eeschema/class_libentry.h | 4 +- eeschema/lib_arc.cpp | 4 +- eeschema/lib_arc.h | 4 +- eeschema/lib_bezier.cpp | 4 +- eeschema/lib_bezier.h | 4 +- eeschema/lib_circle.cpp | 4 +- eeschema/lib_circle.h | 4 +- eeschema/lib_draw_item.h | 6 +-- eeschema/lib_field.cpp | 36 ++++++---------- eeschema/lib_field.h | 6 +-- eeschema/lib_pin.cpp | 4 +- eeschema/lib_pin.h | 4 +- eeschema/lib_polyline.cpp | 4 +- eeschema/lib_polyline.h | 4 +- eeschema/lib_rectangle.cpp | 4 +- eeschema/lib_rectangle.h | 4 +- eeschema/lib_text.cpp | 17 +++----- eeschema/lib_text.h | 6 +-- eeschema/sch_collectors.h | 2 +- gerbview/class_GERBER.h | 2 +- gerbview/class_gerber_draw_item.cpp | 6 +-- gerbview/class_gerber_draw_item.h | 6 +-- include/base_struct.h | 6 +-- include/class_board_item.h | 2 +- include/class_drawpanel.h | 2 +- include/sch_item_struct.h | 5 ++- include/worksheet_shape_builder.h | 14 +++--- kicad/class_treeprojectfiles.h | 2 +- pcbnew/class_dimension.cpp | 2 +- pcbnew/class_dimension.h | 2 +- pcbnew/class_drawsegment.cpp | 2 +- pcbnew/class_drawsegment.h | 2 +- pcbnew/class_marker_pcb.h | 2 +- pcbnew/class_mire.cpp | 2 +- pcbnew/class_mire.h | 2 +- pcbnew/class_module.cpp | 2 +- pcbnew/class_module.h | 2 +- pcbnew/class_pad.cpp | 2 +- pcbnew/class_pad.h | 7 +-- pcbnew/class_pcb_text.h | 2 +- pcbnew/class_text_mod.cpp | 5 ++- pcbnew/class_text_mod.h | 2 +- pcbnew/class_track.cpp | 2 +- pcbnew/class_track.h | 2 +- pcbnew/class_zone.cpp | 43 ++++++++++--------- pcbnew/class_zone.h | 15 ++++--- pcbnew/controle.cpp | 40 +++++++++++------ pcbnew/dialogs/dialog_general_options.h | 2 +- pcbnew/eagle_plugin.cpp | 2 + pcbnew/onrightclick.cpp | 4 +- pcbnew/router/pns_node.cpp | 6 +-- pcbnew/router/pns_node.h | 2 +- pcbnew/zones_by_polygon.cpp | 12 +++--- polygon/polygon_test_point_inside.cpp | 2 +- polygon/polygon_test_point_inside.h | 4 +- 61 files changed, 188 insertions(+), 176 deletions(-) diff --git a/3d-viewer/3d_canvas.h b/3d-viewer/3d_canvas.h index d4ad84cebf..b68541dfdf 100644 --- a/3d-viewer/3d_canvas.h +++ b/3d-viewer/3d_canvas.h @@ -80,7 +80,7 @@ public: EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList = 0 ); ~EDA_3D_CANVAS(); - EDA_3D_FRAME* Parent() { return (EDA_3D_FRAME*)GetParent(); } + EDA_3D_FRAME* Parent() const { return static_cast( GetParent() ); } BOARD* GetBoard() { return Parent()->GetBoard(); } diff --git a/3d-viewer/3d_viewer.h b/3d-viewer/3d_viewer.h index 46c92053b7..c0f950a67a 100644 --- a/3d-viewer/3d_viewer.h +++ b/3d-viewer/3d_viewer.h @@ -81,7 +81,7 @@ public: m_auimgr.UnInit(); }; - PCB_BASE_FRAME* Parent() { return (PCB_BASE_FRAME*)GetParent(); } + PCB_BASE_FRAME* Parent() const { return (PCB_BASE_FRAME*)GetParent(); } BOARD* GetBoard(); diff --git a/common/draw_panel.cpp b/common/draw_panel.cpp index 1e3adb750b..9ac1875616 100644 --- a/common/draw_panel.cpp +++ b/common/draw_panel.cpp @@ -165,7 +165,7 @@ EDA_DRAW_PANEL::~EDA_DRAW_PANEL() } -EDA_DRAW_FRAME* EDA_DRAW_PANEL::GetParent() +EDA_DRAW_FRAME* EDA_DRAW_PANEL::GetParent() const { wxWindow* mom = wxScrolledWindow::GetParent(); return (EDA_DRAW_FRAME*) mom; diff --git a/common/page_layout/page_layout_graphic_items.cpp b/common/page_layout/page_layout_graphic_items.cpp index aeb4b53696..c927e935df 100644 --- a/common/page_layout/page_layout_graphic_items.cpp +++ b/common/page_layout/page_layout_graphic_items.cpp @@ -192,7 +192,7 @@ void WS_DRAW_ITEM_TEXT::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC ) } // return true if the point aPosition is on the text -bool WS_DRAW_ITEM_TEXT::HitTest( const wxPoint& aPosition) +bool WS_DRAW_ITEM_TEXT::HitTest( const wxPoint& aPosition) const { return EDA_TEXT::TextHitTest( aPosition, 0 ); } @@ -221,7 +221,7 @@ void WS_DRAW_ITEM_POLYGON::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC ) // return true if the point aPosition is inside one of polygons #include -bool WS_DRAW_ITEM_POLYGON::HitTest( const wxPoint& aPosition) +bool WS_DRAW_ITEM_POLYGON::HitTest( const wxPoint& aPosition) const { return TestPointInsidePolygon( &m_Corners[0], m_Corners.size(), aPosition ); @@ -249,7 +249,7 @@ void WS_DRAW_ITEM_RECT::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC ) } // return true if the point aPosition is on the rect outline -bool WS_DRAW_ITEM_RECT::HitTest( const wxPoint& aPosition) +bool WS_DRAW_ITEM_RECT::HitTest( const wxPoint& aPosition) const { int dist = GetPenWidth()/2; wxPoint start = GetStart(); @@ -316,7 +316,7 @@ void WS_DRAW_ITEM_LINE::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC ) } // return true if the point aPosition is on the text -bool WS_DRAW_ITEM_LINE::HitTest( const wxPoint& aPosition) +bool WS_DRAW_ITEM_LINE::HitTest( const wxPoint& aPosition) const { return TestSegmentHit( aPosition, GetStart(), GetEnd(), GetPenWidth()/2 ); } @@ -394,9 +394,9 @@ void WS_DRAW_ITEM_BITMAP::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC ) * Virtual function * return true if the point aPosition is on bitmap */ -bool WS_DRAW_ITEM_BITMAP::HitTest( const wxPoint& aPosition) +bool WS_DRAW_ITEM_BITMAP::HitTest( const wxPoint& aPosition) const { - WORKSHEET_DATAITEM_BITMAP* parent = (WORKSHEET_DATAITEM_BITMAP*)GetParent(); + const WORKSHEET_DATAITEM_BITMAP* parent = static_cast( GetParent() ); if( parent->m_ImageBitmap == NULL ) return false; diff --git a/cvpcb/cvstruct.h b/cvpcb/cvstruct.h index 579aa44dc6..7078a8d8a8 100644 --- a/cvpcb/cvstruct.h +++ b/cvpcb/cvstruct.h @@ -52,7 +52,7 @@ public: int GetSelection(); void OnSize( wxSizeEvent& event ); - virtual CVPCB_MAINFRAME* GetParent(); + virtual CVPCB_MAINFRAME* GetParent() const; }; diff --git a/cvpcb/listboxes.cpp b/cvpcb/listboxes.cpp index d36d921625..bc7f364658 100644 --- a/cvpcb/listboxes.cpp +++ b/cvpcb/listboxes.cpp @@ -79,7 +79,7 @@ int ITEMS_LISTBOX_BASE::GetSelection() } -CVPCB_MAINFRAME* ITEMS_LISTBOX_BASE::GetParent() +CVPCB_MAINFRAME* ITEMS_LISTBOX_BASE::GetParent() const { return (CVPCB_MAINFRAME*) wxListView::GetParent(); } diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h index a8c84ade03..a730d9d19b 100644 --- a/eeschema/class_libentry.h +++ b/eeschema/class_libentry.h @@ -654,14 +654,14 @@ public: */ void SetPartCount( int count ); - int GetPartCount() { return m_unitCount; } + int GetPartCount() const { return m_unitCount; } /** * Function IsMulti * @return true if the component has multiple parts per package. * When happens, the reference has a sub reference ti identify part */ - bool IsMulti() { return m_unitCount > 1; } + bool IsMulti() const { return m_unitCount > 1; } /** * Function SubReference diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp index df4fb03f0d..686adbf8c0 100644 --- a/eeschema/lib_arc.cpp +++ b/eeschema/lib_arc.cpp @@ -171,7 +171,7 @@ bool LIB_ARC::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) } -bool LIB_ARC::HitTest( const wxPoint& aRefPoint ) +bool LIB_ARC::HitTest( const wxPoint& aRefPoint ) const { int mindist = GetPenSize() / 2; @@ -183,7 +183,7 @@ bool LIB_ARC::HitTest( const wxPoint& aRefPoint ) } -bool LIB_ARC::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ) +bool LIB_ARC::HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const { if( aThreshold < 0 ) diff --git a/eeschema/lib_arc.h b/eeschema/lib_arc.h index 2c017b9c20..74fc633071 100644 --- a/eeschema/lib_arc.h +++ b/eeschema/lib_arc.h @@ -100,9 +100,9 @@ public: bool Load( LINE_READER& aLineReader, wxString& aErrorMsg ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; - bool HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ); + bool HitTest( const wxPoint& aPosition, int aThreshold, const TRANSFORM& aTransform ) const; const EDA_RECT GetBoundingBox() const; // Virtual diff --git a/eeschema/lib_bezier.cpp b/eeschema/lib_bezier.cpp index b58e11cb6b..3378bb1603 100644 --- a/eeschema/lib_bezier.cpp +++ b/eeschema/lib_bezier.cpp @@ -345,7 +345,7 @@ void LIB_BEZIER::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& } -bool LIB_BEZIER::HitTest( const wxPoint& aRefPos ) +bool LIB_BEZIER::HitTest( const wxPoint& aRefPos ) const { int mindist = GetPenSize() / 2; @@ -357,7 +357,7 @@ bool LIB_BEZIER::HitTest( const wxPoint& aRefPos ) } -bool LIB_BEZIER::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform ) +bool LIB_BEZIER::HitTest( const wxPoint &aPosRef, int aThreshold, const TRANSFORM& aTransform ) const { wxPoint ref, start, end; diff --git a/eeschema/lib_bezier.h b/eeschema/lib_bezier.h index 00a320b43f..0a1be188f1 100644 --- a/eeschema/lib_bezier.h +++ b/eeschema/lib_bezier.h @@ -72,9 +72,9 @@ public: */ unsigned GetCornerCount() const { return m_PolyPoints.size(); } - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; - bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform ); + bool HitTest( const wxPoint& aPosRef, int aThreshold, const TRANSFORM& aTransform ) const; const EDA_RECT GetBoundingBox() const; // Virtual diff --git a/eeschema/lib_circle.cpp b/eeschema/lib_circle.cpp index 204db95d5f..6a249ec740 100644 --- a/eeschema/lib_circle.cpp +++ b/eeschema/lib_circle.cpp @@ -87,7 +87,7 @@ bool LIB_CIRCLE::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) } -bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef ) +bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef ) const { int mindist = GetPenSize() / 2; @@ -99,7 +99,7 @@ bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef ) } -bool LIB_CIRCLE::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform ) +bool LIB_CIRCLE::HitTest( const wxPoint &aPosRef, int aThreshold, const TRANSFORM& aTransform ) const { if( aThreshold < 0 ) aThreshold = GetPenSize() / 2; diff --git a/eeschema/lib_circle.h b/eeschema/lib_circle.h index 49f0f605ac..cbd0b31778 100644 --- a/eeschema/lib_circle.h +++ b/eeschema/lib_circle.h @@ -61,9 +61,9 @@ public: bool Load( LINE_READER& aLineReader, wxString& aErrorMsg ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; - bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform ); + bool HitTest( const wxPoint& aPosRef, int aThreshold, const TRANSFORM& aTransform ) const; int GetPenSize( ) const; diff --git a/eeschema/lib_draw_item.h b/eeschema/lib_draw_item.h index 8efffd827e..10e972eb4a 100644 --- a/eeschema/lib_draw_item.h +++ b/eeschema/lib_draw_item.h @@ -237,12 +237,12 @@ public: virtual bool Load( LINE_READER& aLine, wxString& aErrorMsg ) = 0; - LIB_COMPONENT* GetParent() + LIB_COMPONENT* GetParent() const { return (LIB_COMPONENT *)m_Parent; } - virtual bool HitTest( const wxPoint& aPosition ) + virtual bool HitTest( const wxPoint& aPosition ) const { return EDA_ITEM::HitTest( aPosition ); } @@ -255,7 +255,7 @@ public: * @param aTransform The transform matrix. * @return True if the point \a aPosition is near this object */ - virtual bool HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ) = 0; + virtual bool HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const = 0; /** * @return the boundary box for this, in library coordinates diff --git a/eeschema/lib_field.cpp b/eeschema/lib_field.cpp index 392daecc8c..36f43f8c0d 100644 --- a/eeschema/lib_field.cpp +++ b/eeschema/lib_field.cpp @@ -320,7 +320,7 @@ void LIB_FIELD::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& a } -bool LIB_FIELD::HitTest( const wxPoint& aPosition ) +bool LIB_FIELD::HitTest( const wxPoint& aPosition ) const { // Because HitTest is mainly used to select the field // return always false if this field is void @@ -331,49 +331,37 @@ bool LIB_FIELD::HitTest( const wxPoint& aPosition ) } -bool LIB_FIELD::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ) +bool LIB_FIELD::HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const { if( aThreshold < 0 ) aThreshold = 0; - int extraCharCount = 0; + // Build a temporary copy of the text for hit testing + EDA_TEXT tmp_text( *this ); // Reference designator text has one or 2 additional character (displays // U? or U?A) if( m_id == REFERENCE ) { - extraCharCount++; - m_Text.Append('?'); - LIB_COMPONENT* parent = (LIB_COMPONENT*)m_Parent; + wxString extended_text = tmp_text.GetText(); + extended_text.Append('?'); + const LIB_COMPONENT* parent = static_cast( m_Parent ); if ( parent && ( parent->GetPartCount() > 1 ) ) - { - m_Text.Append('A'); - extraCharCount++; - } + extended_text.Append('A'); + tmp_text.SetText( extended_text ); } - wxPoint physicalpos = aTransform.TransformCoordinate( m_Pos ); - wxPoint tmp = m_Pos; - m_Pos = physicalpos; + tmp_text.SetTextPosition( aTransform.TransformCoordinate( m_Pos ) ); /* The text orientation may need to be flipped if the * transformation matrix causes xy axes to be flipped. * this simple algo works only for schematic matrix (rot 90 or/and mirror) */ int t1 = ( aTransform.x1 != 0 ) ^ ( m_Orient != 0 ); - int orient = t1 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT; - EXCHG( m_Orient, orient ); + tmp_text.SetOrientation( t1 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT ); - bool hit = TextHitTest( aPosition ); - - EXCHG( m_Orient, orient ); - m_Pos = tmp; - - while( extraCharCount-- ) - m_Text.RemoveLast( ); - - return hit; + return tmp_text.TextHitTest( aPosition ); } diff --git a/eeschema/lib_field.h b/eeschema/lib_field.h index 1e475fa913..49e36d8be5 100644 --- a/eeschema/lib_field.h +++ b/eeschema/lib_field.h @@ -151,7 +151,7 @@ public: * Function IsVoid * @return true if the field value is void (no text in this field) */ - bool IsVoid() + bool IsVoid() const { return m_Text.IsEmpty(); } @@ -169,9 +169,9 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; - bool HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ); + bool HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const; void operator=( const LIB_FIELD& field ) { diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp index e4f16b3a8f..29c4aee929 100644 --- a/eeschema/lib_pin.cpp +++ b/eeschema/lib_pin.cpp @@ -525,13 +525,13 @@ void LIB_PIN::EnableEditMode( bool enable, bool editPinByPin ) } -bool LIB_PIN::HitTest( const wxPoint& aPosition ) +bool LIB_PIN::HitTest( const wxPoint& aPosition ) const { return HitTest( aPosition, 0, DefaultTransform ); } -bool LIB_PIN::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ) +bool LIB_PIN::HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const { if( aThreshold < 0 ) aThreshold = 0; diff --git a/eeschema/lib_pin.h b/eeschema/lib_pin.h index bf4c504776..dd85740de6 100644 --- a/eeschema/lib_pin.h +++ b/eeschema/lib_pin.h @@ -131,9 +131,9 @@ public: bool Load( LINE_READER& aLineReader, wxString& aErrorMsg ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; - bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform ); + bool HitTest( const wxPoint &aPosRef, int aThreshold, const TRANSFORM& aTransform ) const; void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); diff --git a/eeschema/lib_polyline.cpp b/eeschema/lib_polyline.cpp index 5b4b1ba49c..75eae61c71 100644 --- a/eeschema/lib_polyline.cpp +++ b/eeschema/lib_polyline.cpp @@ -321,7 +321,7 @@ void LIB_POLYLINE::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint } -bool LIB_POLYLINE::HitTest( const wxPoint& aPosition ) +bool LIB_POLYLINE::HitTest( const wxPoint& aPosition ) const { int mindist = GetPenSize() / 2; @@ -333,7 +333,7 @@ bool LIB_POLYLINE::HitTest( const wxPoint& aPosition ) } -bool LIB_POLYLINE::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ) +bool LIB_POLYLINE::HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const { wxPoint ref, start, end; diff --git a/eeschema/lib_polyline.h b/eeschema/lib_polyline.h index 81a4d8a08e..78a3891613 100644 --- a/eeschema/lib_polyline.h +++ b/eeschema/lib_polyline.h @@ -74,9 +74,9 @@ public: */ unsigned GetCornerCount() const { return m_PolyPoints.size(); } - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; - bool HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ); + bool HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const; const EDA_RECT GetBoundingBox() const; // Virtual diff --git a/eeschema/lib_rectangle.cpp b/eeschema/lib_rectangle.cpp index 7efdb3dbf1..057b049eb1 100644 --- a/eeschema/lib_rectangle.cpp +++ b/eeschema/lib_rectangle.cpp @@ -267,7 +267,7 @@ const EDA_RECT LIB_RECTANGLE::GetBoundingBox() const } -bool LIB_RECTANGLE::HitTest( const wxPoint& aPosition ) +bool LIB_RECTANGLE::HitTest( const wxPoint& aPosition ) const { int mindist = ( GetPenSize() / 2 ) + 1; @@ -279,7 +279,7 @@ bool LIB_RECTANGLE::HitTest( const wxPoint& aPosition ) } -bool LIB_RECTANGLE::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ) +bool LIB_RECTANGLE::HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const { if( aThreshold < 0 ) aThreshold = GetPenSize() / 2; diff --git a/eeschema/lib_rectangle.h b/eeschema/lib_rectangle.h index 739f20b60e..63e182691d 100644 --- a/eeschema/lib_rectangle.h +++ b/eeschema/lib_rectangle.h @@ -65,9 +65,9 @@ public: bool Load( LINE_READER& aLineReader, wxString& aErrorMsg ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; - bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform ); + bool HitTest( const wxPoint &aPosRef, int aThreshold, const TRANSFORM& aTransform ) const; int GetPenSize( ) const; diff --git a/eeschema/lib_text.cpp b/eeschema/lib_text.cpp index d52acdda97..1b51b0f4e9 100644 --- a/eeschema/lib_text.cpp +++ b/eeschema/lib_text.cpp @@ -185,32 +185,27 @@ bool LIB_TEXT::Load( LINE_READER& aLineReader, wxString& errorMsg ) } -bool LIB_TEXT::HitTest( const wxPoint& aPosition ) +bool LIB_TEXT::HitTest( const wxPoint& aPosition ) const { return HitTest( aPosition, 0, DefaultTransform ); } -bool LIB_TEXT::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ) +bool LIB_TEXT::HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const { if( aThreshold < 0 ) aThreshold = 0; - wxPoint physicalpos = aTransform.TransformCoordinate( m_Pos ); - wxPoint tmp = m_Pos; - m_Pos = physicalpos; + EDA_TEXT tmp_text( *this ); + tmp_text.SetTextPosition( aTransform.TransformCoordinate( m_Pos ) ); /* The text orientation may need to be flipped if the * transformation matrix causes xy axes to be flipped. * this simple algo works only for schematic matrix (rot 90 or/and mirror) */ int t1 = ( aTransform.x1 != 0 ) ^ ( m_Orient != 0 ); - int orient = t1 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT; - EXCHG( m_Orient, orient ); - bool hit = TextHitTest( aPosition ); - EXCHG( m_Orient, orient ); - m_Pos = tmp; - return hit; + tmp_text.SetOrientation( t1 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT ); + return tmp_text.TextHitTest( aPosition ); } diff --git a/eeschema/lib_text.h b/eeschema/lib_text.h index 3db14c11a8..8353869226 100644 --- a/eeschema/lib_text.h +++ b/eeschema/lib_text.h @@ -82,11 +82,11 @@ public: bool Load( LINE_READER& aLineReader, wxString& aErrorMsg ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; - bool HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform ); + bool HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const; - bool HitTest( EDA_RECT& aRect ) + bool HitTest( const EDA_RECT& aRect ) const { return TextHitTest( aRect ); } diff --git a/eeschema/sch_collectors.h b/eeschema/sch_collectors.h index 299ea9ec62..4813253919 100644 --- a/eeschema/sch_collectors.h +++ b/eeschema/sch_collectors.h @@ -210,7 +210,7 @@ public: wxString GetSheetPath() const { return m_sheetPath; } - SCH_ITEM* GetParent() { return m_parent; } + SCH_ITEM* GetParent() const { return m_parent; } }; diff --git a/gerbview/class_GERBER.h b/gerbview/class_GERBER.h index 632ac6487c..c975bf0233 100644 --- a/gerbview/class_GERBER.h +++ b/gerbview/class_GERBER.h @@ -148,7 +148,7 @@ public: * Function GetParent * @return the GERBVIEW_FRAME parent of this GERBER_IMAGE */ - GERBVIEW_FRAME* GetParent() + GERBVIEW_FRAME* GetParent() const { return m_Parent; } diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp index c73d8972da..f01f3d5d55 100644 --- a/gerbview/class_gerber_draw_item.cpp +++ b/gerbview/class_gerber_draw_item.cpp @@ -131,7 +131,7 @@ wxPoint GERBER_DRAW_ITEM::GetABPosition( const wxPoint& aXYPosition ) const } -wxPoint GERBER_DRAW_ITEM::GetXYPosition( const wxPoint& aABPosition ) +wxPoint GERBER_DRAW_ITEM::GetXYPosition( const wxPoint& aABPosition ) const { // do the inverse transform made by GetABPosition wxPoint xyPos = aABPosition; @@ -577,7 +577,7 @@ void GERBER_DRAW_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) } -bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) +bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const { // calculate aRefPos in XY gerber axis: wxPoint ref_pos = GetXYPosition( aRefPos ); @@ -592,7 +592,7 @@ bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) } -bool GERBER_DRAW_ITEM::HitTest( EDA_RECT& aRefArea ) +bool GERBER_DRAW_ITEM::HitTest( const EDA_RECT& aRefArea ) const { wxPoint pos = GetABPosition( m_Start ); diff --git a/gerbview/class_gerber_draw_item.h b/gerbview/class_gerber_draw_item.h index 70ad0a1164..c7a0b695cc 100644 --- a/gerbview/class_gerber_draw_item.h +++ b/gerbview/class_gerber_draw_item.h @@ -209,7 +209,7 @@ public: * @param aABPosition = position in A,B plotter axis * @return const wxPoint - The given position in X,Y axis. */ - wxPoint GetXYPosition( const wxPoint& aABPosition ); + wxPoint GetXYPosition( const wxPoint& aABPosition ) const; /** * Function GetDcodeDescr @@ -255,7 +255,7 @@ public: * @param aRefPos a wxPoint to test * @return bool - true if a hit, else false */ - bool HitTest( const wxPoint& aRefPos ); + bool HitTest( const wxPoint& aRefPos ) const; /** * Function HitTest (overloaded) @@ -264,7 +264,7 @@ public: * @param aRefArea a wxPoint to test * @return bool - true if a hit, else false */ - bool HitTest( EDA_RECT& aRefArea ); + bool HitTest( const EDA_RECT& aRefArea ) const; /** * Function GetClass diff --git a/include/base_struct.h b/include/base_struct.h index 9ec7af03c8..38e320ef38 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -456,14 +456,10 @@ public: * Function HitTest * tests if \a aPosition is contained within or on the bounding area of an item. * - * @note This function cannot be const because some of the derive objects perform - * intermediate calculations which change object members. Make sure derived - * objects do not declare this as const. - * * @param aPosition A reference to a wxPoint object containing the coordinates to test. * @return True if \a aPosition is within or on the item bounding area. */ - virtual bool HitTest( const wxPoint& aPosition ) + virtual bool HitTest( const wxPoint& aPosition ) const { return false; // derived classes should override this function } diff --git a/include/class_board_item.h b/include/class_board_item.h index 26a30af896..91fd3ead0c 100644 --- a/include/class_board_item.h +++ b/include/class_board_item.h @@ -254,7 +254,7 @@ public: */ wxString GetLayerName() const; - virtual bool HitTest( const wxPoint& aPosition ) + virtual bool HitTest( const wxPoint& aPosition ) const { return EDA_ITEM::HitTest( aPosition ); } diff --git a/include/class_drawpanel.h b/include/class_drawpanel.h index 3a9c3735b7..d3e69371b3 100644 --- a/include/class_drawpanel.h +++ b/include/class_drawpanel.h @@ -123,7 +123,7 @@ public: BASE_SCREEN* GetScreen(); - EDA_DRAW_FRAME* GetParent(); + EDA_DRAW_FRAME* GetParent() const; void OnPaint( wxPaintEvent& event ); diff --git a/include/sch_item_struct.h b/include/sch_item_struct.h index 5fe90cd69f..6a3d4913ba 100644 --- a/include/sch_item_struct.h +++ b/include/sch_item_struct.h @@ -291,7 +291,10 @@ public: bool IsConnected( const wxPoint& aPoint ) const; /** @copydoc EDA_ITEM::HitTest(const wxPoint&) */ - virtual bool HitTest( const wxPoint& aPosition ) { return HitTest( aPosition, 0 ); } + virtual bool HitTest( const wxPoint& aPosition ) const + { + return HitTest( aPosition, 0 ); + } /** * Function HitTest diff --git a/include/worksheet_shape_builder.h b/include/worksheet_shape_builder.h index de0bb5aa57..718213c9b7 100644 --- a/include/worksheet_shape_builder.h +++ b/include/worksheet_shape_builder.h @@ -59,7 +59,7 @@ public: EDA_COLOR_T GetColor() const { return m_color; } WS_DRAW_TYPE GetType() const { return m_type; }; - WORKSHEET_DATAITEM* GetParent() { return m_parent; } + WORKSHEET_DATAITEM* GetParent() const { return m_parent; } /** The function to draw a WS_DRAW_ITEM */ @@ -69,7 +69,7 @@ public: * Abstract function: should exist for derived items * return true if the point aPosition is on the item */ - virtual bool HitTest( const wxPoint& aPosition) = 0; + virtual bool HitTest( const wxPoint& aPosition) const = 0; /** * Abstract function: should exist for derived items @@ -124,7 +124,7 @@ public: * Virtual function * return true if the point aPosition is on the line */ - virtual bool HitTest( const wxPoint& aPosition); + virtual bool HitTest( const wxPoint& aPosition) const; /** * return true if the point aPosition is on the starting point of this item. @@ -174,7 +174,7 @@ public: * Virtual function * return true if the point aPosition is inside one polygon */ - virtual bool HitTest( const wxPoint& aPosition); + virtual bool HitTest( const wxPoint& aPosition) const; /** * return true if the point aPosition is on the starting point of this item. @@ -202,7 +202,7 @@ public: * Virtual function * return true if the point aPosition is on one edge of the rectangle */ - virtual bool HitTest( const wxPoint& aPosition); + virtual bool HitTest( const wxPoint& aPosition) const; /** * return true if the point aPosition is on the starting point of this item. @@ -239,7 +239,7 @@ public: * Virtual function * return true if the point aPosition is on the text */ - virtual bool HitTest( const wxPoint& aPosition); + virtual bool HitTest( const wxPoint& aPosition) const; /** * return true if the point aPosition is on the starting point of this item. @@ -274,7 +274,7 @@ public: * Virtual function * return true if the point aPosition is on bitmap */ - virtual bool HitTest( const wxPoint& aPosition); + virtual bool HitTest( const wxPoint& aPosition) const; /** * return true if the point aPosition is on the reference point of this item. diff --git a/kicad/class_treeprojectfiles.h b/kicad/class_treeprojectfiles.h index b671a02e0f..6d592d4696 100644 --- a/kicad/class_treeprojectfiles.h +++ b/kicad/class_treeprojectfiles.h @@ -17,7 +17,7 @@ private: public: - TREE_PROJECT_FRAME* GetParent() + TREE_PROJECT_FRAME* GetParent() const { return m_Parent; } diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp index e49ca7e5dd..59ff184ddc 100644 --- a/pcbnew/class_dimension.cpp +++ b/pcbnew/class_dimension.cpp @@ -396,7 +396,7 @@ void DIMENSION::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) } -bool DIMENSION::HitTest( const wxPoint& aPosition ) +bool DIMENSION::HitTest( const wxPoint& aPosition ) const { if( m_Text.TextHitTest( aPosition ) ) return true; diff --git a/pcbnew/class_dimension.h b/pcbnew/class_dimension.h index 1ea29bd8dc..d68fc7770d 100644 --- a/pcbnew/class_dimension.h +++ b/pcbnew/class_dimension.h @@ -127,7 +127,7 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect, * bool aContained = true, int aAccuracy ) const diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index d1e9799258..2c976e90ee 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -475,7 +475,7 @@ const EDA_RECT DRAWSEGMENT::GetBoundingBox() const } -bool DRAWSEGMENT::HitTest( const wxPoint& aPosition ) +bool DRAWSEGMENT::HitTest( const wxPoint& aPosition ) const { switch( m_Shape ) { diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index 64ce5dcb8c..3cae1d9dcf 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -178,7 +178,7 @@ public: virtual const EDA_RECT GetBoundingBox() const; - virtual bool HitTest( const wxPoint& aPosition ); + virtual bool HitTest( const wxPoint& aPosition ) const; /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect, * bool aContained = true, int aAccuracy ) const diff --git a/pcbnew/class_marker_pcb.h b/pcbnew/class_marker_pcb.h index 7728b152c0..5e794a743c 100644 --- a/pcbnew/class_marker_pcb.h +++ b/pcbnew/class_marker_pcb.h @@ -64,7 +64,7 @@ public: const wxPoint& GetPosition() const { return m_Pos; } void SetPosition( const wxPoint& aPos ) { m_Pos = aPos; } - bool HitTest( const wxPoint& aPosition ) + bool HitTest( const wxPoint& aPosition ) const { return HitTestMarker( aPosition ); } diff --git a/pcbnew/class_mire.cpp b/pcbnew/class_mire.cpp index d2fb096755..3abeaf95d0 100644 --- a/pcbnew/class_mire.cpp +++ b/pcbnew/class_mire.cpp @@ -158,7 +158,7 @@ void PCB_TARGET::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE mode_color, } -bool PCB_TARGET::HitTest( const wxPoint& aPosition ) +bool PCB_TARGET::HitTest( const wxPoint& aPosition ) const { int dX = aPosition.x - m_Pos.x; int dY = aPosition.y - m_Pos.y; diff --git a/pcbnew/class_mire.h b/pcbnew/class_mire.h index 0a7186b6b1..9f12ac7d73 100644 --- a/pcbnew/class_mire.h +++ b/pcbnew/class_mire.h @@ -82,7 +82,7 @@ public: void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset = ZeroOffset ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect, * bool aContained = true, int aAccuracy ) const diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index ca343a6333..257f34bd6e 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -549,7 +549,7 @@ void MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) } -bool MODULE::HitTest( const wxPoint& aPosition ) +bool MODULE::HitTest( const wxPoint& aPosition ) const { if( m_BoundaryBox.Contains( aPosition ) ) return true; diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 189abfe6be..3b378c30a6 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -324,7 +324,7 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect, * bool aContained = true, int aAccuracy ) const diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 43b2b17f04..f4a1282ed7 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -637,7 +637,7 @@ bool D_PAD::IsOnLayer( LAYER_NUM aLayer ) const } -bool D_PAD::HitTest( const wxPoint& aPosition ) +bool D_PAD::HitTest( const wxPoint& aPosition ) const { int dx, dy; diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 3cbdcbe82a..41ac5c3913 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -341,7 +341,7 @@ public: * Function GetBoundingRadius * returns the radius of a minimum sized circle which fully encloses this pad. */ - int GetBoundingRadius() + int GetBoundingRadius() const { // Any member function which would affect this calculation should set // m_boundingRadius to -1 to re-trigger the calculation from here. @@ -368,7 +368,7 @@ public: bool IsOnLayer( LAYER_NUM aLayer ) const; - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; wxString GetClass() const { @@ -450,7 +450,8 @@ private: */ int boundingRadius() const; - int m_boundingRadius; ///< radius of the circle containing the pad shape + // Actually computed and cached on demand by the accessor + mutable int m_boundingRadius; ///< radius of the circle containing the pad shape /// Pad name (4 char) or a long identifier (used in pad name /// comparisons because this is faster than string comparison) diff --git a/pcbnew/class_pcb_text.h b/pcbnew/class_pcb_text.h index 0ebd4119bf..7a6d853704 100644 --- a/pcbnew/class_pcb_text.h +++ b/pcbnew/class_pcb_text.h @@ -76,7 +76,7 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); - bool HitTest( const wxPoint& aPosition ) + bool HitTest( const wxPoint& aPosition ) const { return TextHitTest( aPosition ); } diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index e5e7a2d2be..b103869775 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -163,7 +163,7 @@ void TEXTE_MODULE::SetLocalCoord() RotatePoint( &m_Pos0.x, &m_Pos0.y, -angle ); } -bool TEXTE_MODULE::HitTest( const wxPoint& aPosition ) +bool TEXTE_MODULE::HitTest( const wxPoint& aPosition ) const { wxPoint rel_pos; EDA_RECT area = GetTextBox( -1, -1 ); @@ -455,6 +455,9 @@ void TEXTE_MODULE::ViewGetLayers( int aLayers[], int& aCount ) const case LAYER_N_FRONT: aLayers[0] = ITEM_GAL_LAYER( MOD_TEXT_FR_VISIBLE ); // how about SILKSCREEN_N_FRONT? break; + + default: + wxFAIL_MSG( wxT( "Can't tell text layer" ) ); } break; } diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h index bc207e7254..7ab96e516b 100644 --- a/pcbnew/class_text_mod.h +++ b/pcbnew/class_text_mod.h @@ -148,7 +148,7 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); - bool HitTest( const wxPoint& aPosition ); + bool HitTest( const wxPoint& aPosition ) const; wxString GetClass() const { diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index 2dd626a5c8..7a40e066fb 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -1236,7 +1236,7 @@ bool TRACK::HitTest( const wxPoint& aPosition ) return TestSegmentHit( aPosition, m_Start, m_End, m_Width / 2 ); } -bool VIA::HitTest( const wxPoint& aPosition ) +bool VIA::HitTest( const wxPoint& aPosition ) const { int max_dist = m_Width / 2; diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h index 9afc346788..4340c33e6d 100644 --- a/pcbnew/class_track.h +++ b/pcbnew/class_track.h @@ -401,7 +401,7 @@ public: const wxPoint& GetPosition() const { return m_Start; } // was overload void SetPosition( const wxPoint& aPoint ) { m_Start = aPoint; m_End = aPoint; } // was overload - virtual bool HitTest( const wxPoint& aPosition ); + virtual bool HitTest( const wxPoint& aPosition ) const; virtual bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0 ) const; diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 6679fee49a..a6b360f98a 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -440,37 +440,42 @@ int ZONE_CONTAINER::GetThermalReliefCopperBridge( D_PAD* aPad ) const } -bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) +bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) const { - if( HitTestForCorner( aPosition ) ) + if( HitTestForCorner( aPosition ) >= 0 ) return true; - if( HitTestForEdge( aPosition ) ) + if( HitTestForEdge( aPosition ) >= 0 ) return true; return false; } +void ZONE_CONTAINER::SetSelectedCorner( const wxPoint& aPosition ) +{ + m_CornerSelection = HitTestForCorner( aPosition ); + + if( m_CornerSelection < 0 ) + m_CornerSelection = HitTestForEdge( aPosition ); +} + + // Zones outlines have no thickness, so it Hit Test functions // we must have a default distance between the test point // and a corner or a zone edge: #define MAX_DIST_IN_MM 0.25 -bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) +int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) const { int distmax = Millimeter2iu( MAX_DIST_IN_MM ); - m_CornerSelection = m_Poly->HitTestForCorner( refPos, distmax ); - - return m_CornerSelection >= 0; + return m_Poly->HitTestForCorner( refPos, distmax ); } -bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) +int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) const { int distmax = Millimeter2iu( MAX_DIST_IN_MM ); - m_CornerSelection = m_Poly->HitTestForEdge( refPos, distmax ); - - return m_CornerSelection >= 0; + return m_Poly->HitTestForEdge( refPos, distmax ); } @@ -700,25 +705,23 @@ void ZONE_CONTAINER::Move( const wxPoint& offset ) } -void ZONE_CONTAINER::MoveEdge( const wxPoint& offset ) +void ZONE_CONTAINER::MoveEdge( const wxPoint& offset, int aEdge ) { - int ii = m_CornerSelection; - // Move the start point of the selected edge: - SetCornerPosition( ii, GetCornerPosition( ii ) + offset ); + SetCornerPosition( aEdge, GetCornerPosition( aEdge ) + offset ); // Move the end point of the selected edge: - if( m_Poly->m_CornersList.IsEndContour( ii ) || ii == GetNumCorners() - 1 ) + if( m_Poly->m_CornersList.IsEndContour( aEdge ) || aEdge == GetNumCorners() - 1 ) { - int icont = m_Poly->GetContour( ii ); - ii = m_Poly->GetContourStart( icont ); + int icont = m_Poly->GetContour( aEdge ); + aEdge = m_Poly->GetContourStart( icont ); } else { - ii++; + aEdge++; } - SetCornerPosition( ii, GetCornerPosition( ii ) + offset ); + SetCornerPosition( aEdge, GetCornerPosition( aEdge ) + offset ); m_Poly->Hatch(); } diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 6423d85396..2642937d06 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -217,6 +217,10 @@ public: int GetSelectedCorner() const { return m_CornerSelection; } void SetSelectedCorner( int aCorner ) { m_CornerSelection = aCorner; } + /// + // Like HitTest but selects the current corner to be operated on + void SetSelectedCorner( const wxPoint& aPosition ); + int GetLocalFlags() const { return m_localFlgs; } void SetLocalFlags( int aFlags ) { m_localFlgs = aFlags; } @@ -234,7 +238,7 @@ public: * @param aRefPos A wxPoint to test * @return bool - true if a hit, else false */ - virtual bool HitTest( const wxPoint& aPosition ); + virtual bool HitTest( const wxPoint& aPosition ) const; /** * Function HitTest @@ -342,7 +346,7 @@ public: * @return true if found * @param refPos : A wxPoint to test */ - bool HitTestForCorner( const wxPoint& refPos ); + int HitTestForCorner( const wxPoint& refPos ) const; /** * Function HitTestForEdge @@ -351,7 +355,7 @@ public: * @return true if found * @param refPos : A wxPoint to test */ - bool HitTestForEdge( const wxPoint& refPos ); + int HitTestForEdge( const wxPoint& refPos ) const; /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect, * bool aContained = true, int aAccuracy ) const @@ -400,10 +404,11 @@ public: /** * Function MoveEdge - * Move the outline Edge. m_CornerSelection is the start point of the outline edge + * Move the outline Edge * @param offset = moving vector + * @param aEdge = start point of the outline edge */ - void MoveEdge( const wxPoint& offset ); + void MoveEdge( const wxPoint& offset, int aEdge ); /** * Function Rotate diff --git a/pcbnew/controle.cpp b/pcbnew/controle.cpp index d6f8a79583..06f07af712 100644 --- a/pcbnew/controle.cpp +++ b/pcbnew/controle.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -160,8 +161,9 @@ BOARD_ITEM* PCB_BASE_FRAME::PcbGeneralLocateAndDisplay( int aHotKeyCode ) (*m_Collector)[i]->Show( 0, std::cout ); #endif - /* Remove redundancies: sometime, zones are found twice, + /* Remove redundancies: sometime, legacy zones are found twice, * because zones can be filled by overlapping segments (this is a fill option) + * Trigger the selection of the current edge for new-style zones */ time_t timestampzone = 0; @@ -169,18 +171,32 @@ BOARD_ITEM* PCB_BASE_FRAME::PcbGeneralLocateAndDisplay( int aHotKeyCode ) { item = (*m_Collector)[ii]; - if( item->Type() != PCB_ZONE_T ) - continue; + switch( item->Type() ) + { + case PCB_ZONE_T: + // Found a TYPE ZONE + if( item->GetTimeStamp() == timestampzone ) // Remove it, redundant, zone already found + { + m_Collector->Remove( ii ); + ii--; + } + else + { + timestampzone = item->GetTimeStamp(); + } + break; - // Found a TYPE ZONE - if( item->GetTimeStamp() == timestampzone ) // Remove it, redundant, zone already found - { - m_Collector->Remove( ii ); - ii--; - } - else - { - timestampzone = item->GetTimeStamp(); + case PCB_ZONE_AREA_T: + { + /* We need to do the selection now because the menu text + * depends on it */ + ZONE_CONTAINER *zone = static_cast( item ); + zone->SetSelectedCorner( RefPos( true ) ); + } + break; + + default: + break; } } diff --git a/pcbnew/dialogs/dialog_general_options.h b/pcbnew/dialogs/dialog_general_options.h index 7cdefdbe2e..89abaa7b1b 100644 --- a/pcbnew/dialogs/dialog_general_options.h +++ b/pcbnew/dialogs/dialog_general_options.h @@ -16,7 +16,7 @@ public: void OnOkClick( wxCommandEvent& event ); void OnCancelClick( wxCommandEvent& event ); - PCB_EDIT_FRAME* GetParent() { return (PCB_EDIT_FRAME*) wxDialog::GetParent(); } + PCB_EDIT_FRAME* GetParent() const { return (PCB_EDIT_FRAME*) wxDialog::GetParent(); } private: void OnMiddleBtnPanEnbl( wxCommandEvent& event ) diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index a78007761b..4f93574ab2 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -2234,6 +2234,8 @@ void EAGLE_PLUGIN::packageCircle( MODULE* aModule, CPTREE& aTree ) const case ECO1_N: layer = SILKSCREEN_N_FRONT; break; case ECO2_N: layer = SILKSCREEN_N_BACK; break; */ + default: + break; } gr->SetLayer( layer ); diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index c66adc4c64..372538c1b1 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -661,14 +661,14 @@ void PCB_EDIT_FRAME::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu* edge_zone->GetIsKeepout() ? _("Keepout Area") : _( "Zones" ), KiBitmap( add_zone_xpm ) ); - if( edge_zone->HitTestForCorner( RefPos( true ) ) ) + if( edge_zone->HitTestForCorner( RefPos( true ) ) >= 0 ) { AddMenuItem( zones_menu, ID_POPUP_PCB_MOVE_ZONE_CORNER, _( "Move Corner" ), KiBitmap( move_xpm ) ); AddMenuItem( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CORNER, _( "Delete Corner" ), KiBitmap( delete_xpm ) ); } - else if( edge_zone->HitTestForEdge( RefPos( true ) ) ) + else if( edge_zone->HitTestForEdge( RefPos( true ) ) >= 0 ) { AddMenuItem( zones_menu, ID_POPUP_PCB_ADD_ZONE_CORNER, _( "Create Corner" ), KiBitmap( add_corner_xpm ) ); diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index e2349c4800..825be77e57 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -401,9 +401,9 @@ struct hitVisitor { PNS_ITEMSET& m_items; const VECTOR2I& m_point; - PNS_NODE* m_world; + const PNS_NODE* m_world; - hitVisitor( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, PNS_NODE* aWorld ) : + hitVisitor( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, const PNS_NODE* aWorld ) : m_items( aTab ), m_point( aPoint ), m_world( aWorld ) {}; bool operator()( PNS_ITEM* aItem ) @@ -423,7 +423,7 @@ struct hitVisitor }; -const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) +const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) const { PNS_ITEMSET items; // fixme: we treat a point as an infinitely small circle - this is inefficient. diff --git a/pcbnew/router/pns_node.h b/pcbnew/router/pns_node.h index f88b74bd4f..de3e886dc2 100644 --- a/pcbnew/router/pns_node.h +++ b/pcbnew/router/pns_node.h @@ -140,7 +140,7 @@ public: int aKindMask = PNS_ITEM::ANY ); ///> Hit detection - const PNS_ITEMSET HitTest( const VECTOR2I& aPoint ); + const PNS_ITEMSET HitTest( const VECTOR2I& aPoint ) const; void Add( PNS_ITEM* aItem ); void Remove( PNS_ITEM* aItem ); diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index 44f669fce8..7b40a598e8 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -433,9 +433,9 @@ void Abort_Zone_Move_Corner_Or_Outlines( EDA_DRAW_PANEL* Panel, wxDC* DC ) } else if( zone->IsDragging() ) { - wxPoint offset; - offset = s_CornerInitialPosition - s_CursorLastPosition; - zone->MoveEdge( offset ); + wxPoint offset = s_CornerInitialPosition - s_CursorLastPosition; + int selection = zone->GetSelectedCorner(); + zone->MoveEdge( offset, selection ); } else { @@ -485,9 +485,9 @@ void Show_Zone_Corner_Or_Outline_While_Move_Mouse( EDA_DRAW_PANEL* aPanel, wxDC* } else if( zone->IsDragging() ) { - wxPoint offset; - offset = pos - s_CursorLastPosition; - zone->MoveEdge( offset ); + wxPoint offset = pos - s_CursorLastPosition; + int selection = zone->GetSelectedCorner(); + zone->MoveEdge( offset, selection ); s_CursorLastPosition = pos; } else diff --git a/polygon/polygon_test_point_inside.cpp b/polygon/polygon_test_point_inside.cpp index aafade407c..f63d9ba9d7 100644 --- a/polygon/polygon_test_point_inside.cpp +++ b/polygon/polygon_test_point_inside.cpp @@ -96,7 +96,7 @@ bool TestPointInsidePolygon( const CPOLYGONS_LIST& aPolysList, /* Function TestPointInsidePolygon (overlaid) * same as previous, but use wxPoint and aCount corners */ -bool TestPointInsidePolygon( wxPoint *aPolysList, int aCount,wxPoint aRefPoint ) +bool TestPointInsidePolygon( const wxPoint *aPolysList, int aCount, const wxPoint &aRefPoint ) { // count intersection points to right of (refx,refy). If odd number, point (refx,refy) is inside polyline int ics, ice; diff --git a/polygon/polygon_test_point_inside.h b/polygon/polygon_test_point_inside.h index b817380d1c..ff43798159 100644 --- a/polygon/polygon_test_point_inside.h +++ b/polygon/polygon_test_point_inside.h @@ -34,6 +34,6 @@ bool TestPointInsidePolygon( const CPOLYGONS_LIST& aPolysList, * @param aRefPoint: the point coordinate to test * @return true if the point is inside, false for outside */ -bool TestPointInsidePolygon( wxPoint* aPolysList, +bool TestPointInsidePolygon( const wxPoint* aPolysList, int aCount, - wxPoint aRefPoint ); + const wxPoint &aRefPoint ); From fef168aaed9cf6283fadf9eb9de0d0feeee1b301 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 4 May 2014 13:22:27 -0500 Subject: [PATCH 06/68] Modular-Kicad milestone B), minor portions: *) KIWAY_PLAYER::IsModal() is now a retained state, controlled by SetModal() *) Fully re-work the KIWAY_PLAYER::ShowModal() to use a nested event loop. *) Add support to DIALOG_SHIM for a "quasi-modal" dialog presentation and mode. See top of dialog_shim.cpp about that for benefits and need. *) You can now pick footprint from the schematic component field dialog, although if you do this before you open the BOARD, you will only get the global footprint libraries, not also the project specific ones. Opening the BOARD first avoids this problem. This is the first example of cross KIFACE invocation, it is also the first instance of using a TOP_FRAME other than FRAME_PCB as the first thing. It works, but it's missing support for opening the project specific table because historically the FRAME_PCB did that. This is now starting to expose all the near term needs for KIWAY_PLAYER <-> PROJECT interaction, independence and out of sequence usage. A fix for this will be coming in a few days. However it mostly starts to show why the KIWAY is terribly useful and important. --- common/basicframe.cpp | 11 ++ common/dialog_shim.cpp | 126 +++++++++++++++++- common/kiway_player.cpp | 71 +++++----- .../dialog_edit_component_in_schematic.cpp | 35 +++-- eeschema/getpart.cpp | 15 ++- eeschema/tool_viewlib.cpp | 11 +- eeschema/viewlib_frame.cpp | 3 + include/dialog_shim.h | 16 ++- include/kiway_player.h | 7 +- include/wxstruct.h | 4 +- pcbnew/footprint_wizard_frame.cpp | 5 +- pcbnew/modview_frame.cpp | 6 +- pcbnew/tool_modview.cpp | 6 +- 13 files changed, 245 insertions(+), 71 deletions(-) diff --git a/common/basicframe.cpp b/common/basicframe.cpp index 37be1fd12c..2fb7d4c604 100644 --- a/common/basicframe.cpp +++ b/common/basicframe.cpp @@ -151,6 +151,17 @@ bool EDA_BASE_FRAME::ProcessEvent( wxEvent& aEvent ) } +bool EDA_BASE_FRAME::Enable( bool enable ) +{ +#if defined(DEBUG) + const char* type_id = typeid( *this ).name(); + printf( "wxFrame %s: %s\n", type_id, enable ? "enabled" : "disabled" ); +#endif + + return wxFrame::Enable( enable ); +} + + void EDA_BASE_FRAME::onAutoSaveTimer( wxTimerEvent& aEvent ) { if( !doAutoSave() ) diff --git a/common/dialog_shim.cpp b/common/dialog_shim.cpp index 354444c4ff..8c1d94e794 100644 --- a/common/dialog_shim.cpp +++ b/common/dialog_shim.cpp @@ -25,17 +25,45 @@ #include #include +#include + +/* + Quasi-Modal Mode Explained: + + The gtk calls in wxDialog::ShowModal() cause event routing problems if that + modal dialog then tries to use KIWAY_PLAYER::ShowModal(). The latter shows up + and mostly works but does not respond to the window decoration close button. + There is no way to get around this without reversing the gtk calls temporarily. + + Quasi-Modal mode is our own almost modal mode which disables only the parent + of the DIALOG_SHIM, leaving other frames operable and while staying captured in the + nested event loop. This avoids the gtk calls and leaves event routing pure + and sufficient to operate the KIWAY_PLAYER::ShowModal() properly. When using + ShowQuasiModal() you have to use EndQuasiModal() in your dialogs and not + EndModal(). There is also IsQuasiModal() but its value can only be true + when the nested event loop is active. Do not mix the modal and quasi-modal + functions. Use one set or the other. + + You might find this behavior preferable over a pure modal mode, and it was said + that only the Mac has this natively, but now other platforms have something + similar. You CAN use it anywhere for any dialog. But you MUST use it when + you want to use KIWAY_PLAYER::ShowModal() from a dialog event. +*/ + + DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxDialog( aParent, id, title, pos, size, style, name ), - KIWAY_HOLDER( 0 ) + KIWAY_HOLDER( 0 ), + m_qmodal_loop( 0 ), + m_qmodal_showing( false ) { // pray that aParent is either a KIWAY_PLAYER or DIALOG_SHIM derivation. KIWAY_HOLDER* h = dynamic_cast( aParent ); wxASSERT_MSG( h, - wxT( "DIALOG_SHIM's parent not derived from KIWAY_PLAYER nor DIALOG_SHIM" ) ); + wxT( "DIALOG_SHIM's parent is NULL or not derived from KIWAY_PLAYER nor DIALOG_SHIM" ) ); if( h ) SetKiway( this, &h->Kiway() ); @@ -46,6 +74,14 @@ DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& titl } +DIALOG_SHIM::~DIALOG_SHIM() +{ + // if the dialog is quasi-modal, this will end its event loop + if( IsQuasiModal() ) + EndQuasiModal( wxID_CANCEL ); +} + + // our hashtable is an implementation secret, don't need or want it in a header file #include #include // EDA_RECT @@ -92,6 +128,90 @@ bool DIALOG_SHIM::Show( bool show ) } +bool DIALOG_SHIM::Enable( bool enable ) +{ +#if defined(DEBUG) + const char* type_id = typeid( *this ).name(); + printf( "wxDialog %s: %s\n", type_id, enable ? "enabled" : "disabled" ); +#endif + + return wxDialog::Enable( enable ); +} + + +int DIALOG_SHIM::ShowQuasiModal() +{ + // toggle a window's "enable" status to disabled, then enabled on exit. + // exception safe. + struct ENABLE_DISABLE + { + wxWindow* m_win; + ENABLE_DISABLE( wxWindow* aWindow ) : m_win( aWindow ) { if( m_win ) m_win->Disable(); } + ~ENABLE_DISABLE() { if( m_win ) m_win->Enable(); } + }; + + // This is an exception safe way to zero a pointer before returning. + // Yes, even though DismissModal() clears this first normally, this is + // here in case there's an exception before the dialog is dismissed. + struct NULLER + { + void*& m_what; + NULLER( void*& aPtr ) : m_what( aPtr ) {} + ~NULLER() { m_what = 0; } // indeed, set it to NULL on destruction + } clear_this( (void*&) m_qmodal_loop ); + + + // release the mouse if it's currently captured as the window having it + // will be disabled when this dialog is shown -- but will still keep the + // capture making it impossible to do anything in the modal dialog itself + wxWindow* win = wxWindow::GetCapture(); + if( win ) + win->ReleaseMouse(); + + wxWindow* parent = GetParentForModalDialog(); + + ENABLE_DISABLE toggle( parent ); + + Show( true ); + + m_qmodal_showing = true; + + wxGUIEventLoop event_loop; + wxEventLoopActivator event_loop_stacker( &event_loop ); + + m_qmodal_loop = &event_loop; + + event_loop.Run(); + + if( toggle.m_win ) // let's focus back on the parent window + toggle.m_win->SetFocus(); + + return GetReturnCode(); +} + + +void DIALOG_SHIM::EndQuasiModal( int retCode ) +{ + SetReturnCode( retCode ); + + if( !IsQuasiModal() ) + { + wxFAIL_MSG( "either DIALOG_SHIM::EndQuasiModal called twice or ShowQuasiModal wasn't called" ); + return; + } + + m_qmodal_showing = false; + + if( m_qmodal_loop ) + { + m_qmodal_loop->Exit(); + m_qmodal_loop = NULL; + } + + Show( false ); +} + + #if DLGSHIM_USE_SETFOCUS static bool findWindowRecursively( const wxWindowList& children, const wxWindow* wanted ) @@ -113,7 +233,7 @@ static bool findWindowRecursively( const wxWindowList& children, const wxWindow* } -static bool findWindowRecursively( const wxWindow* topmost, const wxWindow* wanted ) +static bool findWindowReursively( const wxWindow* topmost, const wxWindow* wanted ) { // wanted may be NULL and that is ok. diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp index 274e4e564c..d171744227 100644 --- a/common/kiway_player.cpp +++ b/common/kiway_player.cpp @@ -23,13 +23,14 @@ */ - #include #include #include #include +#include #include #include +#include BEGIN_EVENT_TABLE( KIWAY_PLAYER, EDA_BASE_FRAME ) @@ -43,10 +44,10 @@ KIWAY_PLAYER::KIWAY_PLAYER( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType long aStyle, const wxString& aWdoName ) : EDA_BASE_FRAME( aParent, aFrameType, aTitle, aPos, aSize, aStyle, aWdoName ), KIWAY_HOLDER( aKiway ), - m_modal_dismissed( 0 ) + m_modal( false ), + m_modal_loop( 0 ) { - DBG( printf("KIWAY_EXPRESS::wxEVENT_ID:%d\n", KIWAY_EXPRESS::wxEVENT_ID );) - //Connect( KIWAY_EXPRESS::wxEVENT_ID, wxKiwayExressHandler( KIWAY_PLAYER::kiway_express ) ); + // DBG( printf("KIWAY_EXPRESS::wxEVENT_ID:%d\n", KIWAY_EXPRESS::wxEVENT_ID );) } @@ -55,10 +56,10 @@ KIWAY_PLAYER::KIWAY_PLAYER( wxWindow* aParent, wxWindowID aId, const wxString& a const wxString& aWdoName ) : EDA_BASE_FRAME( aParent, (FRAME_T) aId, aTitle, aPos, aSize, aStyle, aWdoName ), KIWAY_HOLDER( 0 ), - m_modal_dismissed( 0 ) + m_modal( false ), + m_modal_loop( 0 ) { - DBG( printf("KIWAY_EXPRESS::wxEVENT_ID:%d\n", KIWAY_EXPRESS::wxEVENT_ID );) - //Connect( KIWAY_EXPRESS::wxEVENT_ID, wxKiwayExressHandler( KIWAY_PLAYER::kiway_express ) ); + // DBG( printf("KIWAY_EXPRESS::wxEVENT_ID:%d\n", KIWAY_EXPRESS::wxEVENT_ID );) } @@ -73,49 +74,54 @@ void KIWAY_PLAYER::KiwayMailIn( KIWAY_EXPRESS& aEvent ) bool KIWAY_PLAYER::ShowModal( wxString* aResult ) { + wxASSERT_MSG( IsModal(), "ShowModal() shouldn't be called on non-modal frame" ); + /* - This function has a nice interface but an unsightly implementation. - Now it is encapsulated, making it easier to improve. I am not sure - a wxSemaphore was needed, especially since no blocking happens. It seems - like a volatile bool is sufficient. + This function has a nice interface but a necessarily unsightly implementation. + Now the implementation is encapsulated, localizing future changes. It works in tandem with DismissModal(). But only ShowModal() is in the vtable and therefore cross-module capable. */ - volatile bool dismissed = false; + // This is an exception safe way to zero a pointer before returning. + // Yes, even though DismissModal() clears this first normally, this is + // here in case there's an exception before the dialog is dismissed. + struct NULLER + { + void*& m_what; + NULLER( void*& aPtr ) : m_what( aPtr ) {} + ~NULLER() { m_what = 0; } // indeed, set it to NULL on destruction + } clear_this( (void*&) m_modal_loop ); - // disable all frames except the modal one, re-enable on exit, exception safe. + // exception safe way to disable all frames except the modal one, + // re-enable on exit wxWindowDisabler toggle( this ); - m_modal_dismissed = &dismissed; - Show( true ); - Raise(); - // Wait for the one and only active frame to call DismissModal() from - // some concluding event. - while( !dismissed ) - { - wxYield(); - wxMilliSleep( 50 ); - } + wxGUIEventLoop event_loop; + wxEventLoopActivator event_loop_stacker( &event_loop ); - // no longer modal, not to mention that the pointer would be invalid outside this scope. - m_modal_dismissed = NULL; + m_modal_loop = &event_loop; + + event_loop.Run(); if( aResult ) *aResult = m_modal_string; + DBG(printf( "~%s: aResult:'%s' ret:%d\n", + __func__, TO_UTF8( m_modal_string ), m_modal_ret_val );) + return m_modal_ret_val; } bool KIWAY_PLAYER::IsDismissed() { - // if already dismissed, then m_modal_dismissed may be NULL, and if not, - // it can still be dismissed if the bool is true. - bool ret = !m_modal_dismissed || *m_modal_dismissed; + bool ret = !m_modal_loop; + + DBG(printf( "%s: ret:%d\n", __func__, ret );) return ret; } @@ -126,8 +132,13 @@ void KIWAY_PLAYER::DismissModal( bool aRetVal, const wxString& aResult ) m_modal_ret_val = aRetVal; m_modal_string = aResult; - if( m_modal_dismissed ) - *m_modal_dismissed = true; + if( m_modal_loop ) + { + m_modal_loop->Exit(); + m_modal_loop = 0; // this marks it as dismissed. + } + + Show( false ); } diff --git a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp index 4fc02d14fb..cb9fcbc4ee 100644 --- a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp +++ b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp @@ -148,10 +148,10 @@ void SCH_EDIT_FRAME::EditComponent( SCH_COMPONENT* aComponent ) // make sure the chipnameTextCtrl is wide enough to hold any unusually long chip names: EnsureTextCtrlWidth( dlg->chipnameTextCtrl ); - dlg->ShowModal(); + dlg->ShowQuasiModal(); - m_canvas->MoveCursorToCrossHair(); m_canvas->SetIgnoreMouseEvents( false ); + m_canvas->MoveCursorToCrossHair(); dlg->Destroy(); } @@ -214,7 +214,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemSelected( wxListEvent& event void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnCancelButtonClick( wxCommandEvent& event ) { - EndModal( 1 ); + EndQuasiModal( 1 ); } @@ -379,7 +379,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event m_Parent->GetScreen()->TestDanglingEnds(); m_Parent->GetCanvas()->Refresh( true ); - EndModal( 0 ); + EndQuasiModal( 0 ); } @@ -436,23 +436,21 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::deleteFieldButtonHandler( wxCommandEven void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::showButtonHandler( wxCommandEvent& event ) { -#if 1 +#if 0 wxString datasheet_uri = fieldValueTextCtrl->GetValue(); ::wxLaunchDefaultBrowser( datasheet_uri ); #else - unsigned fieldNdx = getSelectedFieldNdx(); -/* + unsigned fieldNdx = getSelectedFieldNdx(); if( fieldNdx == DATASHEET ) { wxString datasheet_uri = fieldValueTextCtrl->GetValue(); ::wxLaunchDefaultBrowser( datasheet_uri ); } else if( fieldNdx == FOOTPRINT ) -*/ { - // pick a footprint + // pick a footprint using the footprint picker. wxString fpid; KIWAY_PLAYER* frame = Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true ); @@ -460,11 +458,11 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::showButtonHandler( wxCommandEvent& even if( frame->ShowModal( &fpid ) ) { printf( "%s: %s\n", __func__, TO_UTF8( fpid ) ); + fieldValueTextCtrl->SetValue( fpid ); + } - frame->Show( false ); // keep the frame open, but hidden. - - Raise(); + frame->Destroy(); } #endif @@ -764,7 +762,16 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copySelectedFieldToPanel() fieldValueTextCtrl->SetValue( field.GetText() ); - m_show_datasheet_button->Enable( fieldNdx == DATASHEET ); + m_show_datasheet_button->Enable( fieldNdx == DATASHEET || fieldNdx == FOOTPRINT ); + + if( fieldNdx == DATASHEET ) + m_show_datasheet_button->SetLabel( _( "Show in Browser" ) ); + else if( fieldNdx == FOOTPRINT ) + m_show_datasheet_button->SetLabel( _( "Assign Footprint" ) ); + else + m_show_datasheet_button->SetLabel( wxEmptyString ); + + m_show_datasheet_button->Enable( fieldNdx == DATASHEET || fieldNdx == FOOTPRINT ); // For power symbols, the value is NOR editable, because value and pin // name must be same and can be edited only in library editor @@ -1006,5 +1013,5 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event ) m_Parent->OnModify(); m_Cmp->Draw( m_Parent->GetCanvas(), &dc, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE ); - EndModal( 1 ); + EndQuasiModal( 1 ); } diff --git a/eeschema/getpart.cpp b/eeschema/getpart.cpp index e977eee5c1..e81d028bfa 100644 --- a/eeschema/getpart.cpp +++ b/eeschema/getpart.cpp @@ -56,7 +56,7 @@ wxString SCH_BASE_FRAME::SelectComponentFromLibBrowser( LIB_ALIAS* aPreselectedAlias, int* aUnit, int* aConvert ) { - // Close the any current non-modal Lib browser if open, and open a new one, in "modal" mode: + // Close any open non-modal Lib browser, and open a new one, in "modal" mode: LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false ); if( viewlibFrame ) viewlibFrame->Destroy(); @@ -79,13 +79,14 @@ wxString SCH_BASE_FRAME::SelectComponentFromLibBrowser( LIB_ALIAS* aPreselectedA wxString cmpname; - viewlibFrame->ShowModal( &cmpname ); + if( viewlibFrame->ShowModal( &cmpname ) ) + { + if( aUnit ) + *aUnit = viewlibFrame->GetUnit(); - if( aUnit ) - *aUnit = viewlibFrame->GetUnit(); - - if( aConvert ) - *aConvert = viewlibFrame->GetConvert(); + if( aConvert ) + *aConvert = viewlibFrame->GetConvert(); + } viewlibFrame->Destroy(); diff --git a/eeschema/tool_viewlib.cpp b/eeschema/tool_viewlib.cpp index f929ad5c28..e1982ca1ca 100644 --- a/eeschema/tool_viewlib.cpp +++ b/eeschema/tool_viewlib.cpp @@ -116,8 +116,7 @@ void LIB_VIEW_FRAME::ReCreateHToolbar() _( "View component documents" ) ); m_mainToolBar->EnableTool( ID_LIBVIEW_VIEWDOC, false ); - // if library browser is modal - if( m_Ident == FRAME_SCH_VIEWER_MODAL ) + if( IsModal() ) { m_mainToolBar->AddSeparator(); m_mainToolBar->AddTool( ID_LIBVIEW_CMP_EXPORT_TO_SCHEMATIC, @@ -130,11 +129,11 @@ void LIB_VIEW_FRAME::ReCreateHToolbar() m_mainToolBar->Realize(); } - if( (m_libraryName != wxEmptyString) && (m_entryName != wxEmptyString) ) + if( m_libraryName.size() && m_entryName.size() ) { lib = CMP_LIBRARY::FindLibrary( m_libraryName ); - if( lib != NULL ) + if( lib ) { component = lib->FindComponent( m_entryName ); @@ -161,7 +160,6 @@ void LIB_VIEW_FRAME::ReCreateHToolbar() m_mainToolBar->ToggleTool( ID_LIBVIEW_DE_MORGAN_CONVERT_BUTT, false ); } - int parts_count = 1; if( component ) @@ -171,8 +169,7 @@ void LIB_VIEW_FRAME::ReCreateHToolbar() for( ii = 0; ii < parts_count; ii++ ) { - wxString msg; - msg.Printf( _( "Unit %c" ), 'A' + ii ); + wxString msg = wxString::Format( _( "Unit %c" ), 'A' + ii ); m_selpartBox->Append( msg ); } diff --git a/eeschema/viewlib_frame.cpp b/eeschema/viewlib_frame.cpp index e4af57c174..e8b368c118 100644 --- a/eeschema/viewlib_frame.cpp +++ b/eeschema/viewlib_frame.cpp @@ -103,6 +103,9 @@ LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame { wxASSERT( aFrameType==FRAME_SCH_VIEWER || aFrameType==FRAME_SCH_VIEWER_MODAL ); + if( aFrameType == FRAME_SCH_VIEWER_MODAL ) + SetModal( true ); + wxAcceleratorTable table( ACCEL_TABLE_CNT, accels ); m_FrameName = GetLibViewerFrameName(); diff --git a/include/dialog_shim.h b/include/dialog_shim.h index cab1d5f0f7..ae906dc97b 100644 --- a/include/dialog_shim.h +++ b/include/dialog_shim.h @@ -56,12 +56,26 @@ public: const wxString& name = wxDialogNameStr ); - bool Show( bool show ); // overload wxDialog::Show + ~DIALOG_SHIM(); + int ShowQuasiModal(); // disable only the parent window, otherwise modal. + + void EndQuasiModal( int retCode ); // End quasi-modal mode + + bool IsQuasiModal() { return m_qmodal_showing; } + + bool Show( bool show ); // override wxDialog::Show + + bool Enable( bool enable ); // override wxDialog::Enable virtual protected: std::string m_hash_key; // alternate for class_map when classname re-used. + // variables for quasi-modal behavior support, only used by a few derivatives. + wxGUIEventLoop* m_qmodal_loop; // points to nested event_loop, NULL means not qmodal and dismissed + bool m_qmodal_showing; + + #if DLGSHIM_USE_SETFOCUS private: void onInit( wxInitDialogEvent& aEvent ); diff --git a/include/kiway_player.h b/include/kiway_player.h index 6a08e70ed0..ff20714bbc 100644 --- a/include/kiway_player.h +++ b/include/kiway_player.h @@ -87,6 +87,7 @@ private: class KIWAY_EXPRESS; +class wxGUIEventLoop; /** * Class KIWAY_PLAYER @@ -194,7 +195,8 @@ public: protected: - bool IsModal() { return m_modal_dismissed; } + bool IsModal() { return m_modal; } + void SetModal( bool IsModal ) { m_modal = IsModal; } /** * Function IsDismissed @@ -216,7 +218,8 @@ protected: void language_change( wxCommandEvent& event ); // variables for modal behavior support, only used by a few derivatives. - volatile bool* m_modal_dismissed; // points to "dismissed state", NULL means not modal + bool m_modal; // true if frame is intended to be modal, not modeless + wxGUIEventLoop* m_modal_loop; // points to nested event_loop, NULL means not modal and dismissed wxString m_modal_string; bool m_modal_ret_val; // true if a selection was made diff --git a/include/wxstruct.h b/include/wxstruct.h index 22153455a2..daffa56d67 100644 --- a/include/wxstruct.h +++ b/include/wxstruct.h @@ -190,7 +190,9 @@ public: * @warning If you override this function in a derived class, make sure you call * down to this or the auto save feature will be disabled. */ - bool ProcessEvent( wxEvent& aEvent ); // overload wxFrame::ProcessEvent() + bool ProcessEvent( wxEvent& aEvent ); // override wxFrame::ProcessEvent() + + bool Enable( bool enable ); // override wxFrame::Enable virtual void SetAutoSaveInterval( int aInterval ) { m_autoSaveInterval = aInterval; } diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp index 7fac217892..0cff8d2bb1 100644 --- a/pcbnew/footprint_wizard_frame.cpp +++ b/pcbnew/footprint_wizard_frame.cpp @@ -125,6 +125,9 @@ FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, { wxASSERT( aFrameType==FRAME_PCB_FOOTPRINT_WIZARD_MODAL ); + if( aFrameType == FRAME_PCB_FOOTPRINT_WIZARD_MODAL ) + SetModal( true ); + wxAcceleratorTable table( ACCEL_TABLE_CNT, accels ); m_FrameName = FOOTPRINT_WIZARD_FRAME_NAME; @@ -641,7 +644,7 @@ void FOOTPRINT_WIZARD_FRAME::ReCreateHToolbar() m_mainToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); - if( m_Ident == FRAME_PCB_FOOTPRINT_WIZARD_MODAL ) + if( IsModal() ) { // The library browser is called from a "load component" command m_mainToolBar->AddSeparator(); diff --git a/pcbnew/modview_frame.cpp b/pcbnew/modview_frame.cpp index 1db99caf30..1bcbd5fcd5 100644 --- a/pcbnew/modview_frame.cpp +++ b/pcbnew/modview_frame.cpp @@ -129,6 +129,9 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent { wxASSERT( aFrameType==FRAME_PCB_MODULE_VIEWER || aFrameType==FRAME_PCB_MODULE_VIEWER_MODAL ); + if( aFrameType == FRAME_PCB_MODULE_VIEWER_MODAL ) + SetModal( true ); + wxAcceleratorTable table( DIM( accels ), accels ); m_FrameName = GetFootprintViewerFrameName(); @@ -271,6 +274,7 @@ const wxChar* FOOTPRINT_VIEWER_FRAME::GetFootprintViewerFrameName() void FOOTPRINT_VIEWER_FRAME::OnCloseWindow( wxCloseEvent& Event ) { + DBG(printf( "%s:\n", __func__ );) if( IsModal() ) { // Only dismiss a modal frame once, so that the return values set by @@ -278,7 +282,7 @@ void FOOTPRINT_VIEWER_FRAME::OnCloseWindow( wxCloseEvent& Event ) if( !IsDismissed() ) DismissModal( false ); - // window will be destroyed by the calling function. + // window to be destroyed by the caller of KIWAY_PLAYER::ShowModal() } else Destroy(); diff --git a/pcbnew/tool_modview.cpp b/pcbnew/tool_modview.cpp index 3994a2a96d..3101864a0c 100644 --- a/pcbnew/tool_modview.cpp +++ b/pcbnew/tool_modview.cpp @@ -48,8 +48,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateHToolbar() { m_mainToolBar = new wxAuiToolBar( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE - | wxAUI_TB_OVERFLOW - ); + | wxAUI_TB_OVERFLOW ); // Set up toolbar m_mainToolBar->AddTool( ID_MODVIEW_SELECT_LIB, wxEmptyString, @@ -95,8 +94,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateHToolbar() m_mainToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); - // Enable this tool only if the library browser is intended for modal use. - if( m_Ident == FRAME_PCB_MODULE_VIEWER_MODAL ) + if( IsModal() ) { m_mainToolBar->AddSeparator(); m_mainToolBar->AddTool( ID_MODVIEW_FOOTPRINT_EXPORT_TO_BOARD, wxEmptyString, From 19dd876684c14a674bd3f894a4c1765a0aeeae25 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 4 May 2014 14:57:44 -0500 Subject: [PATCH 07/68] wx 2.8 now builds, but the quasi-modal support seems broken on 2.8. Wanted others to be able to build at least. --- common/basicframe.cpp | 2 + common/dialog_shim.cpp | 87 +++++++++++++++++++++++++++++++++++++---- common/kiway_player.cpp | 2 +- include/dialog_shim.h | 16 +++++++- include/kiway_player.h | 12 +++++- 5 files changed, 108 insertions(+), 11 deletions(-) diff --git a/common/basicframe.cpp b/common/basicframe.cpp index 2fb7d4c604..dbcf15d9f9 100644 --- a/common/basicframe.cpp +++ b/common/basicframe.cpp @@ -153,6 +153,8 @@ bool EDA_BASE_FRAME::ProcessEvent( wxEvent& aEvent ) bool EDA_BASE_FRAME::Enable( bool enable ) { + // so we can do logging of this state change: + #if defined(DEBUG) const char* type_id = typeid( *this ).name(); printf( "wxFrame %s: %s\n", type_id, enable ? "enabled" : "disabled" ); diff --git a/common/dialog_shim.cpp b/common/dialog_shim.cpp index 8c1d94e794..548a91cdb4 100644 --- a/common/dialog_shim.cpp +++ b/common/dialog_shim.cpp @@ -130,6 +130,8 @@ bool DIALOG_SHIM::Show( bool show ) bool DIALOG_SHIM::Enable( bool enable ) { + // so we can do logging of this state change: + #if defined(DEBUG) const char* type_id = typeid( *this ).name(); printf( "wxDialog %s: %s\n", type_id, enable ? "enabled" : "disabled" ); @@ -139,6 +141,73 @@ bool DIALOG_SHIM::Enable( bool enable ) } +#if !wxCHECK_VERSION( 2, 9, 4 ) +wxWindow* DIALOG_SHIM::CheckIfCanBeUsedAsParent( wxWindow* parent ) const +{ + if ( !parent ) + return NULL; + + extern WXDLLIMPEXP_DATA_BASE(wxList) wxPendingDelete; + + if ( wxPendingDelete.Member(parent) || parent->IsBeingDeleted() ) + { + // this window is being deleted and we shouldn't create any children + // under it + return NULL; + } + + if ( parent->GetExtraStyle() & wxWS_EX_TRANSIENT ) + { + // this window is not being deleted yet but it's going to disappear + // soon so still don't parent this window under it + return NULL; + } + + if ( !parent->IsShownOnScreen() ) + { + // using hidden parent won't work correctly neither + return NULL; + } + + // FIXME-VC6: this compiler requires an explicit const cast or it fails + // with error C2446 + if ( const_cast(parent) == this ) + { + // not sure if this can really happen but it doesn't hurt to guard + // against this clearly invalid situation + return NULL; + } + + return parent; +} + + +wxWindow* DIALOG_SHIM::GetParentForModalDialog(wxWindow *parent, long style) const +{ + // creating a parent-less modal dialog will result (under e.g. wxGTK2) + // in an unfocused dialog, so try to find a valid parent for it unless we + // were explicitly asked not to + if ( style & wxDIALOG_NO_PARENT ) + return NULL; + + // first try the given parent + if ( parent ) + parent = CheckIfCanBeUsedAsParent(wxGetTopLevelParent(parent)); + + // then the currently active window + if ( !parent ) + parent = CheckIfCanBeUsedAsParent( + wxGetTopLevelParent(wxGetActiveWindow())); + + // and finally the application main window + if ( !parent ) + parent = CheckIfCanBeUsedAsParent(wxTheApp->GetTopWindow()); + + return parent; +} +#endif + + int DIALOG_SHIM::ShowQuasiModal() { // toggle a window's "enable" status to disabled, then enabled on exit. @@ -147,7 +216,14 @@ int DIALOG_SHIM::ShowQuasiModal() { wxWindow* m_win; ENABLE_DISABLE( wxWindow* aWindow ) : m_win( aWindow ) { if( m_win ) m_win->Disable(); } - ~ENABLE_DISABLE() { if( m_win ) m_win->Enable(); } + ~ENABLE_DISABLE() + { + if( m_win ) + { + m_win->Enable(); + m_win->SetFocus(); // let's focus back on the parent window + } + } }; // This is an exception safe way to zero a pointer before returning. @@ -168,7 +244,7 @@ int DIALOG_SHIM::ShowQuasiModal() if( win ) win->ReleaseMouse(); - wxWindow* parent = GetParentForModalDialog(); + wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() ); ENABLE_DISABLE toggle( parent ); @@ -176,16 +252,13 @@ int DIALOG_SHIM::ShowQuasiModal() m_qmodal_showing = true; - wxGUIEventLoop event_loop; + WX_EVENT_LOOP event_loop; wxEventLoopActivator event_loop_stacker( &event_loop ); m_qmodal_loop = &event_loop; event_loop.Run(); - if( toggle.m_win ) // let's focus back on the parent window - toggle.m_win->SetFocus(); - return GetReturnCode(); } @@ -233,7 +306,7 @@ static bool findWindowRecursively( const wxWindowList& children, const wxWindow* } -static bool findWindowReursively( const wxWindow* topmost, const wxWindow* wanted ) +static bool findWindowRecursively( const wxWindow* topmost, const wxWindow* wanted ) { // wanted may be NULL and that is ok. diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp index d171744227..bd993efa0b 100644 --- a/common/kiway_player.cpp +++ b/common/kiway_player.cpp @@ -100,7 +100,7 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult ) Show( true ); - wxGUIEventLoop event_loop; + WX_EVENT_LOOP event_loop; wxEventLoopActivator event_loop_stacker( &event_loop ); m_modal_loop = &event_loop; diff --git a/include/dialog_shim.h b/include/dialog_shim.h index ae906dc97b..3e2ab62cee 100644 --- a/include/dialog_shim.h +++ b/include/dialog_shim.h @@ -35,6 +35,14 @@ #define DLGSHIM_USE_SETFOCUS 0 #endif +#if wxCHECK_VERSION( 2, 9, 4 ) + #define WX_EVENT_LOOP wxGUIEventLoop +#else + #define WX_EVENT_LOOP wxEventLoop +#endif + +class WX_EVENT_LOOP; + /** * Class DIALOG_SHIM @@ -69,10 +77,16 @@ public: bool Enable( bool enable ); // override wxDialog::Enable virtual protected: + +#if !wxCHECK_VERSION( 2, 9, 4 ) + wxWindow* CheckIfCanBeUsedAsParent( wxWindow* parent ) const; + wxWindow* GetParentForModalDialog( wxWindow *parent, long style ) const; +#endif + std::string m_hash_key; // alternate for class_map when classname re-used. // variables for quasi-modal behavior support, only used by a few derivatives. - wxGUIEventLoop* m_qmodal_loop; // points to nested event_loop, NULL means not qmodal and dismissed + WX_EVENT_LOOP* m_qmodal_loop; // points to nested event_loop, NULL means not qmodal and dismissed bool m_qmodal_showing; diff --git a/include/kiway_player.h b/include/kiway_player.h index ff20714bbc..e62981ab54 100644 --- a/include/kiway_player.h +++ b/include/kiway_player.h @@ -87,7 +87,15 @@ private: class KIWAY_EXPRESS; -class wxGUIEventLoop; + +#if wxCHECK_VERSION( 2, 9, 4 ) + #define WX_EVENT_LOOP wxGUIEventLoop +#else + #define WX_EVENT_LOOP wxEventLoop +#endif + +class WX_EVENT_LOOP; + /** * Class KIWAY_PLAYER @@ -219,7 +227,7 @@ protected: // variables for modal behavior support, only used by a few derivatives. bool m_modal; // true if frame is intended to be modal, not modeless - wxGUIEventLoop* m_modal_loop; // points to nested event_loop, NULL means not modal and dismissed + WX_EVENT_LOOP* m_modal_loop; // points to nested event_loop, NULL means not modal and dismissed wxString m_modal_string; bool m_modal_ret_val; // true if a selection was made From bb374d2616225df7393d3201599aad07d52fb772 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 4 May 2014 15:27:29 -0500 Subject: [PATCH 08/68] typeinfo.h missing in Debug build for wx2.8 --- common/basicframe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/basicframe.cpp b/common/basicframe.cpp index dbcf15d9f9..8f05616062 100644 --- a/common/basicframe.cpp +++ b/common/basicframe.cpp @@ -46,7 +46,7 @@ #include #include - +#include /// The default auto save interval is 10 minutes. #define DEFAULT_AUTO_SAVE_INTERVAL 600 From 74cb23a958f376d6c6b608695ac499892460cb89 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 4 May 2014 19:19:16 -0500 Subject: [PATCH 09/68] Quasimodo is not a monster, he is your friend. --- common/dialog_shim.cpp | 10 ++++++++-- common/kiway_player.cpp | 10 ++++++++-- pcbnew/clean.cpp | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/common/dialog_shim.cpp b/common/dialog_shim.cpp index 548a91cdb4..f8236c1ac6 100644 --- a/common/dialog_shim.cpp +++ b/common/dialog_shim.cpp @@ -246,14 +246,20 @@ int DIALOG_SHIM::ShowQuasiModal() wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() ); - ENABLE_DISABLE toggle( parent ); + ENABLE_DISABLE toggle( parent ); // quasi-modal: disable only my "optimal" parent Show( true ); m_qmodal_showing = true; WX_EVENT_LOOP event_loop; + +#if wxCHECK_VERSION( 2, 9, 4 ) // 2.9.4 is only approximate. + // new code needs this, old code does it in wxEventLoop::Run() and cannot + // tolerate it here. Where that boundary is as a version number, I don't know. + // A closer look at the subversion repo for wx would tell. wxEventLoopActivator event_loop_stacker( &event_loop ); +#endif m_qmodal_loop = &event_loop; @@ -269,7 +275,7 @@ void DIALOG_SHIM::EndQuasiModal( int retCode ) if( !IsQuasiModal() ) { - wxFAIL_MSG( "either DIALOG_SHIM::EndQuasiModal called twice or ShowQuasiModal wasn't called" ); + wxFAIL_MSG( wxT( "either DIALOG_SHIM::EndQuasiModal called twice or ShowQuasiModal wasn't called" ) ); return; } diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp index bd993efa0b..ab0ae3e571 100644 --- a/common/kiway_player.cpp +++ b/common/kiway_player.cpp @@ -74,7 +74,7 @@ void KIWAY_PLAYER::KiwayMailIn( KIWAY_EXPRESS& aEvent ) bool KIWAY_PLAYER::ShowModal( wxString* aResult ) { - wxASSERT_MSG( IsModal(), "ShowModal() shouldn't be called on non-modal frame" ); + wxASSERT_MSG( IsModal(), wxT( "ShowModal() shouldn't be called on non-modal frame" ) ); /* This function has a nice interface but a necessarily unsightly implementation. @@ -95,13 +95,19 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult ) } clear_this( (void*&) m_modal_loop ); // exception safe way to disable all frames except the modal one, - // re-enable on exit + // re-enables only those that were disabled on exit wxWindowDisabler toggle( this ); Show( true ); WX_EVENT_LOOP event_loop; + +#if wxCHECK_VERSION( 2, 9, 4 ) // 2.9.4 is only approximate. + // new code needs this, old code does it in wxEventLoop::Run() and cannot + // tolerate it here. Where that boundary is as a version number, I don't know. + // A closer look at the subversion repo for wx would tell. wxEventLoopActivator event_loop_stacker( &event_loop ); +#endif m_modal_loop = &event_loop; diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index 127f0cbae5..12ca312064 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -203,7 +203,7 @@ bool TRACKS_CLEANER::clean_vias() // Correct via m_End defects (if any), should never happen if( via->GetStart() != via->GetEnd() ) { - wxFAIL_MSG( "Via with mismatching ends" ); + wxFAIL_MSG( wxT( "Via with mismatching ends" ) ); via->SetEnd( via->GetStart() ); } From fc26cdfb7423f1e2b902e3b30b77215b73413a1f Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 5 May 2014 09:46:07 +0200 Subject: [PATCH 10/68] footprint editor: fix crashes. In this fix, I removed the assumption the parent frame is the board editor. However, this assumption is still present here and there in the moduleframe code. --- pcbnew/loadcmp.cpp | 9 ++++++--- pcbnew/moduleframe.cpp | 17 +++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index 3aca4d620f..6e66b00c55 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -65,14 +65,17 @@ static FOOTPRINT_LIST MList; bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) { MODULE* newModule; - PCB_BASE_FRAME* parent = (PCB_BASE_FRAME*) GetParent(); + PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); + + if( frame == NULL ) // happens if no board editor opened + return false; if( aModule == NULL ) { - if( ! parent->GetBoard() || ! parent->GetBoard()->m_Modules ) + if( ! frame->GetBoard() || ! frame->GetBoard()->m_Modules ) return false; - aModule = SelectFootprint( parent->GetBoard() ); + aModule = SelectFootprint( frame->GetBoard() ); } if( aModule == NULL ) diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index c2a9b93d4e..076dc14999 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -50,6 +50,7 @@ #include #include #include +#include static PCB_SCREEN* s_screenModule; // the PCB_SCREEN used by the footprint editor @@ -416,21 +417,21 @@ void FOOTPRINT_EDIT_FRAME::OnUpdateLibAndModuleSelected( wxUpdateUIEvent& aEvent void FOOTPRINT_EDIT_FRAME::OnUpdateLoadModuleFromBoard( wxUpdateUIEvent& aEvent ) { - PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) GetParent(); + PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); - aEvent.Enable( frame->GetBoard()->m_Modules != NULL ); + aEvent.Enable( frame && frame->GetBoard()->m_Modules != NULL ); } void FOOTPRINT_EDIT_FRAME::OnUpdateInsertModuleInBoard( wxUpdateUIEvent& aEvent ) { - PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) GetParent(); + PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); MODULE* module_in_edit = GetBoard()->m_Modules; - bool canInsert = ( module_in_edit && !module_in_edit->GetLink() ); + bool canInsert = frame && module_in_edit && !module_in_edit->GetLink(); // If the source was deleted, the module can inserted but not updated in the board. - if( module_in_edit && module_in_edit->GetLink() ) // this is not a new module + if( frame && module_in_edit && module_in_edit->GetLink() ) // this is not a new module { BOARD* mainpcb = frame->GetBoard(); MODULE* source_module = mainpcb->m_Modules; @@ -451,12 +452,12 @@ void FOOTPRINT_EDIT_FRAME::OnUpdateInsertModuleInBoard( wxUpdateUIEvent& aEvent void FOOTPRINT_EDIT_FRAME::OnUpdateReplaceModuleInBoard( wxUpdateUIEvent& aEvent ) { - PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) GetParent(); + PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); MODULE* module_in_edit = GetBoard()->m_Modules; - bool canReplace = ( module_in_edit && module_in_edit->GetLink() ); + bool canReplace = frame && module_in_edit && module_in_edit->GetLink(); - if( module_in_edit && module_in_edit->GetLink() ) // this is not a new module + if( canReplace ) // this is not a new module, but verify if the source is still on board { BOARD* mainpcb = frame->GetBoard(); MODULE* source_module = mainpcb->m_Modules; From c7dc319737e9677a0061388ba7cc006014e9f2f4 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 5 May 2014 17:15:54 +0200 Subject: [PATCH 11/68] Kicad: fix crash on exit, when Libedit was called during a session. It fixes also a crash if Libedit was called, closed and reopened. Happens only if eeschema was called from the Kicad manager. --- eeschema/eeschema.cpp | 3 +-- eeschema/libeditframe.cpp | 2 +- eeschema/libeditframe.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index 911c1d138d..52da445fd0 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -99,8 +99,7 @@ static struct IFACE : public KIFACE_I case FRAME_SCH_LIB_EDITOR: { - LIB_EDIT_FRAME* frame = new LIB_EDIT_FRAME( aKiway, - dynamic_cast( aParent ) ); + LIB_EDIT_FRAME* frame = new LIB_EDIT_FRAME( aKiway, aParent ); return frame; } break; diff --git a/eeschema/libeditframe.cpp b/eeschema/libeditframe.cpp index 49ea88353d..5edc5badb4 100644 --- a/eeschema/libeditframe.cpp +++ b/eeschema/libeditframe.cpp @@ -187,7 +187,7 @@ END_EVENT_TABLE() #define LIB_EDIT_FRAME_NAME wxT( "LibeditFrame" ) -LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, SCH_EDIT_FRAME* aParent ) : +LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH_LIB_EDITOR, _( "Library Editor" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, GetLibEditFrameName() ) { diff --git a/eeschema/libeditframe.h b/eeschema/libeditframe.h index 07a52b6203..106ef8830b 100644 --- a/eeschema/libeditframe.h +++ b/eeschema/libeditframe.h @@ -122,7 +122,7 @@ class LIB_EDIT_FRAME : public SCH_BASE_FRAME public: - LIB_EDIT_FRAME( KIWAY* aKiway, SCH_EDIT_FRAME* aParent ); + LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ); ~LIB_EDIT_FRAME(); From 55e61bc6e3674b36b39cd4ff8f0f77a1e995a9b9 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Mon, 5 May 2014 12:28:40 -0500 Subject: [PATCH 12/68] Modular-Kicad milestone B), glamorous portions: *) Eeschema can now show the footprint editor. *) Eeschema can now invoke the footprint picker from the library part field editor. *) KIWAY_PLAYER::ShowModal() takes aResultantFocusWindow that tells what window to give the focus to. Required since frames are often near the top of the hierarchy and they are invoked by a peer, not a parent. --- common/basicframe.cpp | 2 +- common/dialog_shim.cpp | 4 ++ common/kiway.cpp | 8 +++- common/kiway_player.cpp | 38 +++++++++++++----- .../dialog_edit_component_in_schematic.cpp | 16 ++------ .../dialog_edit_libentry_fields_in_lib.cpp | 40 ++++++++++++++++--- ...ialog_edit_libentry_fields_in_lib_base.cpp | 2 +- ...ialog_edit_libentry_fields_in_lib_base.fbp | 2 +- .../dialog_edit_libentry_fields_in_lib_base.h | 5 ++- eeschema/getpart.cpp | 2 +- eeschema/schframe.cpp | 18 +++++++++ eeschema/tool_sch.cpp | 10 ++++- include/id.h | 1 + include/kiway_player.h | 3 +- include/wxEeschemaStruct.h | 3 +- pcbnew/loadcmp.cpp | 3 +- 16 files changed, 114 insertions(+), 43 deletions(-) diff --git a/common/basicframe.cpp b/common/basicframe.cpp index 8f05616062..382c9c9164 100644 --- a/common/basicframe.cpp +++ b/common/basicframe.cpp @@ -157,7 +157,7 @@ bool EDA_BASE_FRAME::Enable( bool enable ) #if defined(DEBUG) const char* type_id = typeid( *this ).name(); - printf( "wxFrame %s: %s\n", type_id, enable ? "enabled" : "disabled" ); + printf( "wxFrame %-28s: %s\n", type_id, enable ? "enabled" : "disabled" ); #endif return wxFrame::Enable( enable ); diff --git a/common/dialog_shim.cpp b/common/dialog_shim.cpp index f8236c1ac6..1d3e9b6054 100644 --- a/common/dialog_shim.cpp +++ b/common/dialog_shim.cpp @@ -244,8 +244,12 @@ int DIALOG_SHIM::ShowQuasiModal() if( win ) win->ReleaseMouse(); + // Get the optimal parent wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() ); + // Show the optimal parent + DBG( if( parent ) printf( "%s: optimal parent: %s\n", __func__, typeid(*parent).name() );) + ENABLE_DISABLE toggle( parent ); // quasi-modal: disable only my "optimal" parent Show( true ); diff --git a/common/kiway.cpp b/common/kiway.cpp index 8f2ebf9824..396c5cb417 100644 --- a/common/kiway.cpp +++ b/common/kiway.cpp @@ -53,7 +53,7 @@ KIWAY::KIWAY( PGM_BASE* aProgram, int aCtlBits, wxFrame* aTop ): // Any event types derived from wxCommandEvt, like wxWindowDestroyEvent, are -// propogated upwards to parent windows if not handled below. Therefor the +// propogated upwards to parent windows if not handled below. Therefore the // m_top window should receive all wxWindowDestroyEvents originating from // KIWAY_PLAYERs. It does anyways, but now player_destroy_handler eavesdrops // on that event stream looking for KIWAY_PLAYERs being closed. @@ -67,10 +67,14 @@ void KIWAY::player_destroy_handler( wxWindowDestroyEvent& event ) // if destroying one of our flock, then mark it as deceased. if( (wxWindow*) m_player[i] == w ) { - DBG(printf( "%s: marking m_player[%d] as destroyed\n", __func__, i );) + DBG(printf( "%s: m_player[%d] destroyed: %s\n", + __func__, i, TO_UTF8( m_player[i]->GetName() ) );) + m_player[i] = 0; } } + + // event.Skip(); skip to who, the wxApp? I'm the top window. } diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp index ab0ae3e571..fc0415a702 100644 --- a/common/kiway_player.cpp +++ b/common/kiway_player.cpp @@ -72,7 +72,7 @@ void KIWAY_PLAYER::KiwayMailIn( KIWAY_EXPRESS& aEvent ) } -bool KIWAY_PLAYER::ShowModal( wxString* aResult ) +bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow ) { wxASSERT_MSG( IsModal(), wxT( "ShowModal() shouldn't be called on non-modal frame" ) ); @@ -94,24 +94,30 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult ) ~NULLER() { m_what = 0; } // indeed, set it to NULL on destruction } clear_this( (void*&) m_modal_loop ); - // exception safe way to disable all frames except the modal one, - // re-enables only those that were disabled on exit - wxWindowDisabler toggle( this ); Show( true ); + SetFocus(); - WX_EVENT_LOOP event_loop; + { + // exception safe way to disable all frames except the modal one, + // re-enables only those that were disabled on exit + wxWindowDisabler toggle( this ); + + WX_EVENT_LOOP event_loop; #if wxCHECK_VERSION( 2, 9, 4 ) // 2.9.4 is only approximate. - // new code needs this, old code does it in wxEventLoop::Run() and cannot - // tolerate it here. Where that boundary is as a version number, I don't know. - // A closer look at the subversion repo for wx would tell. - wxEventLoopActivator event_loop_stacker( &event_loop ); + // new code needs this, old code does it in wxEventLoop::Run() and cannot + // tolerate it here. Where that boundary is as a version number, I don't know. + // A closer look at the subversion repo for wx would tell. + wxEventLoopActivator event_loop_stacker( &event_loop ); #endif - m_modal_loop = &event_loop; + m_modal_loop = &event_loop; - event_loop.Run(); + event_loop.Run(); + + } // End of scop for some variables. + // End nesting before setting focus below. if( aResult ) *aResult = m_modal_string; @@ -119,6 +125,16 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult ) DBG(printf( "~%s: aResult:'%s' ret:%d\n", __func__, TO_UTF8( m_modal_string ), m_modal_ret_val );) + if( aResultantFocusWindow ) + { + aResultantFocusWindow->Raise(); + + // have the final say, after wxWindowDisabler reenables my parent and + // the events settle down, set the focus + wxYield(); + aResultantFocusWindow->SetFocus(); + } + return m_modal_ret_val; } diff --git a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp index cb9fcbc4ee..0ea32ac16e 100644 --- a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp +++ b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp @@ -436,13 +436,8 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::deleteFieldButtonHandler( wxCommandEven void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::showButtonHandler( wxCommandEvent& event ) { -#if 0 - wxString datasheet_uri = fieldValueTextCtrl->GetValue(); - ::wxLaunchDefaultBrowser( datasheet_uri ); - -#else - unsigned fieldNdx = getSelectedFieldNdx(); + if( fieldNdx == DATASHEET ) { wxString datasheet_uri = fieldValueTextCtrl->GetValue(); @@ -455,17 +450,14 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::showButtonHandler( wxCommandEvent& even KIWAY_PLAYER* frame = Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true ); - if( frame->ShowModal( &fpid ) ) + if( frame->ShowModal( &fpid, this ) ) { - printf( "%s: %s\n", __func__, TO_UTF8( fpid ) ); + // DBG( printf( "%s: %s\n", __func__, TO_UTF8( fpid ) ); ) fieldValueTextCtrl->SetValue( fpid ); - } frame->Destroy(); } -#endif - } @@ -771,8 +763,6 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copySelectedFieldToPanel() else m_show_datasheet_button->SetLabel( wxEmptyString ); - m_show_datasheet_button->Enable( fieldNdx == DATASHEET || fieldNdx == FOOTPRINT ); - // For power symbols, the value is NOR editable, because value and pin // name must be same and can be edited only in library editor if( fieldNdx == VALUE && m_LibEntry && m_LibEntry->IsPower() ) diff --git a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp index 4036c36cb5..37831227d9 100644 --- a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp +++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -141,7 +142,7 @@ void LIB_EDIT_FRAME::InstallFieldsEditorDialog( wxCommandEvent& event ) DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB dlg( this, m_component ); - int abort = dlg.ShowModal(); + int abort = dlg.ShowQuasiModal(); if( abort ) return; @@ -211,7 +212,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnListItemSelected( wxListEvent& event void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnCancelButtonClick( wxCommandEvent& event ) { - EndModal( 1 ); + EndQuasiModal( 1 ); } @@ -282,7 +283,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnOKButtonClick( wxCommandEvent& event m_parent->OnModify(); - EndModal( 0 ); + EndQuasiModal( 0 ); } @@ -381,8 +382,28 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB:: moveUpButtonHandler( wxCommandEvent& e void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::showButtonHandler( wxCommandEvent& event ) { - wxString datasheet_uri = fieldValueTextCtrl->GetValue(); - ::wxLaunchDefaultBrowser( datasheet_uri ); + unsigned fieldNdx = getSelectedFieldNdx(); + + if( fieldNdx == DATASHEET ) + { + wxString datasheet_uri = fieldValueTextCtrl->GetValue(); + ::wxLaunchDefaultBrowser( datasheet_uri ); + } + else if( fieldNdx == FOOTPRINT ) + { + // pick a footprint using the footprint picker. + wxString fpid; + + KIWAY_PLAYER* frame = Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true ); + + if( frame->ShowModal( &fpid, this ) ) + { + // DBG( printf( "%s: %s\n", __func__, TO_UTF8( fpid ) ); ) + fieldValueTextCtrl->SetValue( fpid ); + } + + frame->Destroy(); + } } @@ -652,7 +673,14 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copySelectedFieldToPanel() textSizeTextCtrl->SetValue( EDA_GRAPHIC_TEXT_CTRL::FormatSize( g_UserUnit, field.GetSize().x ) ); - m_show_datasheet_button->Enable( fieldNdx == DATASHEET ); + m_show_datasheet_button->Enable( fieldNdx == DATASHEET || fieldNdx == FOOTPRINT ); + + if( fieldNdx == DATASHEET ) + m_show_datasheet_button->SetLabel( _( "Show in Browser" ) ); + else if( fieldNdx == FOOTPRINT ) + m_show_datasheet_button->SetLabel( _( "Assign Footprint" ) ); + else + m_show_datasheet_button->SetLabel( wxEmptyString ); wxPoint coord = field.GetTextPosition(); wxPoint zero; 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 a859617859..956e092640 100644 --- a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.cpp +++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.cpp @@ -9,7 +9,7 @@ /////////////////////////////////////////////////////////////////////////// -DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE::DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE::DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) { this->SetSizeHints( wxDefaultSize, wxDefaultSize ); 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 d6a0535ca9..94ef7e29cf 100644 --- a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.fbp +++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.fbp @@ -46,7 +46,7 @@ -1,-1 wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU - + DIALOG_SHIM; dialog_shim.h Field Properties 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 82188f2008..fdd0464897 100644 --- a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.h +++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.h @@ -11,6 +11,9 @@ #include #include #include +class DIALOG_SHIM; + +#include "dialog_shim.h" #include #include #include @@ -33,7 +36,7 @@ /////////////////////////////////////////////////////////////////////////////// /// Class DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE /////////////////////////////////////////////////////////////////////////////// -class DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE : public wxDialog +class DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE : public DIALOG_SHIM { private: diff --git a/eeschema/getpart.cpp b/eeschema/getpart.cpp index e81d028bfa..8821cfb31e 100644 --- a/eeschema/getpart.cpp +++ b/eeschema/getpart.cpp @@ -79,7 +79,7 @@ wxString SCH_BASE_FRAME::SelectComponentFromLibBrowser( LIB_ALIAS* aPreselectedA wxString cmpname; - if( viewlibFrame->ShowModal( &cmpname ) ) + if( viewlibFrame->ShowModal( &cmpname, this ) ) { if( aUnit ) *aUnit = viewlibFrame->GetUnit(); diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index db9e8f50ce..fad9539da9 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -101,6 +101,8 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_TOOL( ID_TO_LIBVIEW, SCH_EDIT_FRAME::OnOpenLibraryViewer ) EVT_TOOL( ID_TO_PCB, SCH_EDIT_FRAME::OnOpenPcbnew ) + EVT_TOOL( ID_TO_PCB_MODULE_EDITOR, SCH_EDIT_FRAME::OnOpenPcbModuleEditor ) + EVT_TOOL( ID_TO_CVPCB, SCH_EDIT_FRAME::OnOpenCvpcb ) EVT_TOOL( ID_SHEET_SET, EDA_DRAW_FRAME::Process_PageSettings ) @@ -794,6 +796,22 @@ void SCH_EDIT_FRAME::OnOpenPcbnew( wxCommandEvent& event ) } +void SCH_EDIT_FRAME::OnOpenPcbModuleEditor( wxCommandEvent& event ) +{ + if( !Kiface().IsSingle() ) + { + wxFileName fn = g_RootSheet->GetScreen()->GetFileName(); + + if( fn.IsOk() ) + { + KIWAY_PLAYER* player = Kiway().Player( FRAME_PCB_MODULE_EDITOR ); + player->Show( true ); + player->Raise(); + } + } +} + + void SCH_EDIT_FRAME::OnOpenCvpcb( wxCommandEvent& event ) { wxFileName fn = g_RootSheet->GetScreen()->GetFileName(); diff --git a/eeschema/tool_sch.cpp b/eeschema/tool_sch.cpp index 2bbed5bd48..962ef3847f 100644 --- a/eeschema/tool_sch.cpp +++ b/eeschema/tool_sch.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -139,10 +140,8 @@ void SCH_EDIT_FRAME::ReCreateHToolbar() m_mainToolBar->AddTool( ID_TO_LIBVIEW, wxEmptyString, KiBitmap( library_browse_xpm ), HELP_RUN_LIB_VIEWER ); - m_mainToolBar->AddSeparator(); - m_mainToolBar->AddTool( ID_GET_ANNOTATE, wxEmptyString, KiBitmap( annotate_xpm ), HELP_ANNOTATE ); @@ -158,6 +157,13 @@ void SCH_EDIT_FRAME::ReCreateHToolbar() m_mainToolBar->AddSeparator(); + // The user must HAVE footprints before he can assign them. So put this before + // the CVPCB. + if( !Kiface().IsSingle() ) // if pcbnew is not a separate process + { + m_mainToolBar->AddTool( ID_TO_PCB_MODULE_EDITOR, wxEmptyString, KiBitmap( module_editor_xpm ), + _( "Footprint Editor" ) ); + } m_mainToolBar->AddTool( ID_TO_CVPCB, wxEmptyString, KiBitmap( cvpcb_xpm ), _( "Run CvPcb to associate components and footprints" ) ); diff --git a/include/id.h b/include/id.h index 0c60acd429..a243491c30 100644 --- a/include/id.h +++ b/include/id.h @@ -45,6 +45,7 @@ enum main_id { ID_TO_PCB = wxID_HIGHEST, + ID_TO_PCB_MODULE_EDITOR, ID_TO_CVPCB, ID_LOAD_PROJECT, ID_APPEND_PROJECT, diff --git a/include/kiway_player.h b/include/kiway_player.h index e62981ab54..48cfeafc4a 100644 --- a/include/kiway_player.h +++ b/include/kiway_player.h @@ -185,11 +185,12 @@ public: * event which ends the modal behavior. * * @param aResult if not NULL, indicates a place to put a resultant string. + * @param aResultantFocusWindow if not NULL, indicates what window to pass focus to on return. * * @return bool - true if frame implementation called KIWAY_PLAYER::DismissModal() * with aRetVal of true. */ - VTBL_ENTRY bool ShowModal( wxString* aResult = NULL ); + VTBL_ENTRY bool ShowModal( wxString* aResult = NULL, wxWindow* aResultantFocusWindow = NULL ); //-------------------------------------------------------- diff --git a/include/wxEeschemaStruct.h b/include/wxEeschemaStruct.h index 171351d321..852b65c3fc 100644 --- a/include/wxEeschemaStruct.h +++ b/include/wxEeschemaStruct.h @@ -368,7 +368,7 @@ public: */ virtual void ExecuteRemoteCommand( const char* cmdline ); - void KiwayMailIn( KIWAY_EXPRESS& aEvent ); // virtual overload from KIWAY_PLAYER + void KiwayMailIn( KIWAY_EXPRESS& aEvent ); // override virtual from KIWAY_PLAYER void OnLeftClick( wxDC* aDC, const wxPoint& aPosition ); void OnLeftDClick( wxDC* aDC, const wxPoint& aPosition ); @@ -793,6 +793,7 @@ private: void OnLoadProject( wxCommandEvent& event ); void OnAppendProject( wxCommandEvent& event ); void OnOpenPcbnew( wxCommandEvent& event ); + void OnOpenPcbModuleEditor( wxCommandEvent& event ); void OnOpenCvpcb( wxCommandEvent& event ); void OnOpenLibraryEditor( wxCommandEvent& event ); void OnSetOptions( wxCommandEvent& event ); diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index 6e66b00c55..dda500664f 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -135,7 +135,7 @@ wxString PCB_BASE_FRAME::SelectFootprintFromLibBrowser() wxString fpid; - viewer->ShowModal( &fpid ); + viewer->ShowModal( &fpid, this ); //DBG(printf("%s: fpid:'%s'\n", __func__, TO_UTF8( fpid ) );) @@ -274,7 +274,6 @@ MODULE* PCB_BASE_FRAME::LoadModuleFromLibrary( const wxString& aLibrary, module->SetTimeStamp( GetNewTimeStamp() ); GetBoard()->m_Status_Pcb = 0; - // Put it on FRONT layer, // (Can be stored flipped if the lib is an archive built from a board) if( module->IsFlipped() ) From 0e8a72dbf08bb4be9ae79c5697a33ffd98422836 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Mon, 5 May 2014 23:58:33 -0500 Subject: [PATCH 13/68] Fix new bug which crashed pcbnew running under kicad.exe while adding a new module in mod editor --- pcbnew/moduleframe.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index 076dc14999..cc83322f50 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -31,7 +31,7 @@ #include #include -//#include +#include #include #include #include @@ -50,7 +50,6 @@ #include #include #include -#include static PCB_SCREEN* s_screenModule; // the PCB_SCREEN used by the footprint editor @@ -296,7 +295,8 @@ BOARD_DESIGN_SETTINGS& FOOTPRINT_EDIT_FRAME::GetDesignSettings() const { // get the BOARD_DESIGN_SETTINGS from the parent editor, not our BOARD. - PCB_BASE_FRAME* parentFrame = (PCB_BASE_FRAME*) GetParent(); + // @todo(DICK) change the routing to some default or the board directly, parent may not exist + PCB_BASE_FRAME* parentFrame = (PCB_BASE_FRAME*) Kiway().Player( FRAME_PCB, true ); wxASSERT( parentFrame ); @@ -308,7 +308,8 @@ void FOOTPRINT_EDIT_FRAME::SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSett { // set the BOARD_DESIGN_SETTINGS into parent editor, not our BOARD. - PCB_BASE_FRAME* parentFrame = (PCB_BASE_FRAME*) GetParent(); + // @todo(DICK) change the routing to some default or the board directly, parent may not exist + PCB_BASE_FRAME* parentFrame = (PCB_BASE_FRAME*) Kiway().Player( FRAME_PCB, true ); wxASSERT( parentFrame ); @@ -320,7 +321,8 @@ const PCB_PLOT_PARAMS& FOOTPRINT_EDIT_FRAME::GetPlotSettings() const { // get the settings from the parent editor, not our BOARD. - PCB_BASE_FRAME* parentFrame = (PCB_BASE_FRAME*) GetParent(); + // @todo(DICK) change the routing to some default or the board directly, parent may not exist + PCB_BASE_FRAME* parentFrame = (PCB_BASE_FRAME*) Kiway().Player( FRAME_PCB, true ); wxASSERT( parentFrame ); @@ -332,7 +334,8 @@ void FOOTPRINT_EDIT_FRAME::SetPlotSettings( const PCB_PLOT_PARAMS& aSettings ) { // set the settings into parent editor, not our BOARD. - PCB_BASE_FRAME* parentFrame = (PCB_BASE_FRAME*) GetParent(); + // @todo(DICK) change the routing to some default or the board directly, parent may not exist + PCB_BASE_FRAME* parentFrame = (PCB_BASE_FRAME*) Kiway().Player( FRAME_PCB, true ); wxASSERT( parentFrame ); From 279f6e2bcf1a4efd1194214c628f166465e34859 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Tue, 6 May 2014 00:23:57 -0500 Subject: [PATCH 14/68] Allow building of a STABLE or TESTING version using kicad-install.sh. --- scripts/kicad-install.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/scripts/kicad-install.sh b/scripts/kicad-install.sh index d5e9877926..b867060b77 100755 --- a/scripts/kicad-install.sh +++ b/scripts/kicad-install.sh @@ -34,6 +34,17 @@ # Set where the 3 source trees will go, use a full path WORKING_TREES=~/kicad_sources +STABLE=tag:pre-kiway # currently the best mix of features and stabilty +TESTING=last:1 # the most recent + + +# Set this to STABLE or TESTING or other know revision number: +REVISION=$STABLE + +# For info on revision syntax: +# $ bzr help revisionspec + + # CMake Options #OPTS="$OPTS -DBUILD_GITHUB_PLUGIN=OFF" @@ -45,9 +56,6 @@ WORKING_TREES=~/kicad_sources # https results in read only access. REPOS=https://code.launchpad.net -# This is no longer maintained, is old -#LEGACY_LIB_REPO=$REPOS/~dickelbeck/kicad/library-read-only - # This branch is a bzr/launchpad import of the Git repository # at https://github.com/KiCad/kicad-library.git. # It has schematic parts and 3D models in it. @@ -216,7 +224,7 @@ install_or_update() echo " source repo to local working tree." else cd kicad.bzr - bzr up + bzr up -r $REVISION echo " local source working tree updated." cd ../ fi From e797c489d150f4fa68af9afc955ef5b5cbcaed8d Mon Sep 17 00:00:00 2001 From: Lorenzo Marcantonio Date: Tue, 6 May 2014 17:14:47 +0200 Subject: [PATCH 15/68] Missing const caused unpickability of tracks --- pcbnew/class_track.cpp | 2 +- pcbnew/class_track.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index 7a40e066fb..02872390bf 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -1231,7 +1231,7 @@ void VIA::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList ) } -bool TRACK::HitTest( const wxPoint& aPosition ) +bool TRACK::HitTest( const wxPoint& aPosition ) const { return TestSegmentHit( aPosition, m_Start, m_End, m_Width / 2 ); } diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h index 4340c33e6d..c5ca9d03d7 100644 --- a/pcbnew/class_track.h +++ b/pcbnew/class_track.h @@ -223,7 +223,7 @@ public: const KICAD_T scanTypes[] ); - virtual bool HitTest( const wxPoint& aPosition ); + virtual bool HitTest( const wxPoint& aPosition ) const; /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect, * bool aContained = true, int aAccuracy ) const From 8c2da5f51c033b46a21bcb3a860f08f0c5d008c0 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Thu, 8 May 2014 17:29:22 -0500 Subject: [PATCH 16/68] peggable checkout version in scripts/kicad-install.sh --- scripts/kicad-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kicad-install.sh b/scripts/kicad-install.sh index b867060b77..e1826fc55a 100755 --- a/scripts/kicad-install.sh +++ b/scripts/kicad-install.sh @@ -220,7 +220,7 @@ install_or_update() echo "step 3) checking out the source code from launchpad repo..." if [ ! -d "$WORKING_TREES/kicad.bzr" ]; then - bzr checkout $SRCS_REPO kicad.bzr + bzr checkout -r $REVISION $SRCS_REPO kicad.bzr echo " source repo to local working tree." else cd kicad.bzr From 190461f8ede5e53a59002999a5a6547ce6587dad Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 9 May 2014 08:32:05 +0200 Subject: [PATCH 17/68] OSX: fix incorrect path to launch pl_editor. fix also a bug in python script round_value_robin.py. --- eeschema/viewlib_frame.h | 1 - include/common.h | 2 +- scripts/bom-in-python/round_value_robin.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/eeschema/viewlib_frame.h b/eeschema/viewlib_frame.h index 4e67d0eafc..e87952a64e 100644 --- a/eeschema/viewlib_frame.h +++ b/eeschema/viewlib_frame.h @@ -36,7 +36,6 @@ #include #include -class wxSashLayoutWindow; class wxListBox; class CMP_LIBRARY; diff --git a/include/common.h b/include/common.h index ef03ea0e6a..f7d222adc6 100644 --- a/include/common.h +++ b/include/common.h @@ -102,7 +102,7 @@ enum pseudokeys { #define GERBVIEW_EXE wxT( "gerbview.app/Contents/MacOS/gerbview" ) #define BITMAPCONVERTER_EXE wxT( "bitmap2component.app/Contents/MacOS/bitmap2component" ) #define PCB_CALCULATOR_EXE wxT( "pcb_calculator.app/Contents/MacOS/pcb_calculator" ) -#define PL_EDITOR_EXE wxT( "pcb_calculator.app/Contents/MacOS/pl_editor" ) +#define PL_EDITOR_EXE wxT( "pl_editor.app/Contents/MacOS/pl_editor" ) # endif #endif diff --git a/scripts/bom-in-python/round_value_robin.py b/scripts/bom-in-python/round_value_robin.py index 536f5a1239..028312fc2a 100644 --- a/scripts/bom-in-python/round_value_robin.py +++ b/scripts/bom-in-python/round_value_robin.py @@ -30,7 +30,7 @@ def checkvalue(self): if v.isdigit(): i = int(v) if (i > 1000000): - i = i / 100000 + i = i / 1000000 v = str(i) + "M" if (i > 1000): i = i / 1000 From ecbe6e0856eef27a554282a766ce332d913c67aa Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Fri, 9 May 2014 09:27:21 -0500 Subject: [PATCH 18/68] Try some new Mac support ideas. --- cvpcb/CMakeLists.txt | 41 +++++------ eeschema/CMakeLists.txt | 24 +++---- eeschema/Info.plist | 80 +++++++++------------ gerbview/CMakeLists.txt | 29 ++++---- gerbview/Info.plist | 116 +++++++++++++------------------ kicad/CMakeLists.txt | 16 +++++ kicad/Info.plist | 80 +++++++++------------ pagelayout_editor/CMakeLists.txt | 56 ++++++--------- pagelayout_editor/Info.plist | 80 +++++++++------------ pcb_calculator/CMakeLists.txt | 29 ++++---- pcbnew/CMakeLists.txt | 19 +++-- pcbnew/Info.plist | 79 +++++++++------------ 12 files changed, 275 insertions(+), 374 deletions(-) diff --git a/cvpcb/CMakeLists.txt b/cvpcb/CMakeLists.txt index f36d47ee56..626c41867b 100644 --- a/cvpcb/CMakeLists.txt +++ b/cvpcb/CMakeLists.txt @@ -100,7 +100,6 @@ if( USE_KIWAY_DLLS ) cvpcb.cpp ${CVPCB_SRCS} ${CVPCB_DIALOGS} -# ${CVPCB_RESOURCES} ) set_target_properties( cvpcb_kiface PROPERTIES OUTPUT_NAME cvpcb @@ -148,12 +147,6 @@ if( USE_KIWAY_DLLS ) target_link_libraries( cvpcb_kiface rt ) endif() - if( APPLE ) - set_target_properties( cvpcb PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist - ) - endif() - set_source_files_properties( cvpcb.cpp PROPERTIES # The KIFACE is in cvpcb.cpp, export it: COMPILE_DEFINITIONS "BUILD_KIWAY_DLL;COMPILING_DLL" @@ -172,18 +165,16 @@ if( USE_KIWAY_DLLS ) DESTINATION ${KICAD_BIN} COMPONENT binary ) - install( TARGETS cvpcb_kiface - DESTINATION ${KICAD_BIN} - COMPONENT binary - ) - if( APPLE ) - # copies kiface into the bundle - add_custom_target( _cvpcb_kiface_copy ALL - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/cvpcb/_cvpcb.kiface "${CMAKE_BINARY_DIR}/cvpcb/cvpcb.app/Contents/MacOS/" - DEPENDS cvpcb_kiface - COMMENT "Copying kiface into cvpcb" - ) + # puts the *.kiface into the *.app bundle while linking + set_target_properties( cvpcb_kiface PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cvpcb.app/Contents/MacOS/ + ) + else() + install( TARGETS cvpcb_kiface + DESTINATION ${KICAD_BIN} + COMPONENT binary + ) endif() else() @@ -228,15 +219,15 @@ else() # Must follow github_plugin target_link_libraries( cvpcb ${Boost_LIBRARIES} ) - if( APPLE ) - set_target_properties( cvpcb PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist - ) - endif() - install( TARGETS cvpcb DESTINATION ${KICAD_BIN} COMPONENT binary ) - +endif() + + +if( APPLE ) + set_target_properties( cvpcb PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist + ) endif() diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index b139726841..a57179691d 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -311,20 +311,18 @@ if( USE_KIWAY_DLLS ) DESTINATION ${KICAD_BIN} COMPONENT binary ) - install( TARGETS eeschema_kiface - # actual filename subject to change at milestone C) - # modular-kicad blueprint. - DESTINATION ${KICAD_BIN} - COMPONENT binary - ) - if( APPLE ) - # copies kiface into the bundle - add_custom_target( _eeschema_kiface_copy ALL - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/eeschema/_eeschema.kiface "${CMAKE_BINARY_DIR}/eeschema/eeschema.app/Contents/MacOS/" - DEPENDS eeschema_kiface - COMMENT "Copying kiface into eeschema" - ) + # puts the *.kiface into the *.app bundle while linking + set_target_properties( eeschema_kiface PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/eeschema.app/Contents/MacOS/ + ) + else() + install( TARGETS eeschema_kiface + # actual filename subject to change at milestone C) + # modular-kicad blueprint. + DESTINATION ${KICAD_BIN} + COMPONENT binary + ) endif() else() diff --git a/eeschema/Info.plist b/eeschema/Info.plist index 80d58bfc7d..d9ad6ea8b2 100644 --- a/eeschema/Info.plist +++ b/eeschema/Info.plist @@ -2,54 +2,36 @@ - CFBundleDocumentTypes - - - CFBundleTypeRole - Editor - CFBundleTypeExtensions - - sch - - CFBundleTypeIconFile - eeschema.icns - CFBundleTypeName - eeschema document - LSHandlerRank - Owner - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - eeschema - CFBundleGetInfoString - - CFBundleIconFile - eeschema.icns - CFBundleIdentifier - org.kicad-eda.eeschema - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - - CFBundleName - EESchema - CFBundlePackageType - APPL - CFBundleShortVersionString - - CFBundleSignature - ???? - CFBundleVersion - - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - - NSHighResolutionCapable - True + CFBundleDocumentTypes + + + CFBundleTypeRole Editor + CFBundleTypeExtensions + + sch + + + CFBundleTypeIconFile eeschema.icns + CFBundleTypeName eeschema document + LSHandlerRank Owner + + + + CFBundleDevelopmentRegion English + CFBundleExecutable eeschema + CFBundleGetInfoString + CFBundleIconFile eeschema.icns + CFBundleIdentifier org.kicad-eda.eeschema + CFBundleInfoDictionaryVersion 6.0 + CFBundleLongVersionString + CFBundleName EESchema + CFBundlePackageType APPL + CFBundleShortVersionString + CFBundleSignature ???? + CFBundleVersion + CSResourcesFileMapped + LSRequiresCarbon + NSHumanReadableCopyright + NSHighResolutionCapable True diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt index 7eff8d254e..4ffae72958 100644 --- a/gerbview/CMakeLists.txt +++ b/gerbview/CMakeLists.txt @@ -81,11 +81,11 @@ endif() if( APPLE ) - set(GERBVIEW_RESOURCES gerbview.icns gerbview_doc.icns) - set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/gerbview.icns" PROPERTIES + set( GERBVIEW_RESOURCES gerbview.icns gerbview_doc.icns ) + set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/gerbview.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) - set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/gerbview_doc.icns" PROPERTIES + set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/gerbview_doc.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) set( MACOSX_BUNDLE_ICON_FILE gerbview.icns ) @@ -120,7 +120,6 @@ if( USE_KIWAY_DLLS ) ${GERBVIEW_SRCS} ${DIALOGS_SRCS} ${GERBVIEW_EXTRA_SRCS} -# ${GERBVIEW_RESOURCES} ) set_target_properties( gerbview_kiface PROPERTIES OUTPUT_NAME gerbview @@ -152,18 +151,16 @@ if( USE_KIWAY_DLLS ) DESTINATION ${KICAD_BIN} COMPONENT binary ) - install( TARGETS gerbview_kiface - DESTINATION ${KICAD_BIN} - COMPONENT binary - ) - if( APPLE ) - # copies kiface into the bundle - add_custom_target( _gerbview_kiface_copy ALL - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/gerbview/_gerbview.kiface "${CMAKE_BINARY_DIR}/gerbview/gerbview.app/Contents/MacOS/" - DEPENDS gerbview_kiface - COMMENT "Copying kiface into gerbview" - ) + # puts the *.kiface into the *.app bundle while linking + set_target_properties( gerbview_kiface PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gerbview.app/Contents/MacOS/ + ) + else() + install( TARGETS gerbview_kiface + DESTINATION ${KICAD_BIN} + COMPONENT binary + ) endif() else() @@ -194,5 +191,3 @@ if( APPLE ) set_target_properties( gerbview PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) endif() - - diff --git a/gerbview/Info.plist b/gerbview/Info.plist index a9d27ad02e..a37434eca2 100644 --- a/gerbview/Info.plist +++ b/gerbview/Info.plist @@ -2,72 +2,54 @@ - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - pen - gba - gbr - gbx - gbo - gbl - gtl - gto - gta - gbp - gbp - gbs - gts - gtp - gbx - lgr - ger - pho - drl - - CFBundleTypeIconFile - gerbview_doc.icns - CFBundleTypeName - gerbview document - LSHandlerRank - Default - CFBundleTypeRole - Viewer - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - gerbview - CFBundleGetInfoString - - CFBundleIconFile - gerbview.icns - CFBundleIdentifier - org.kicad-eda.gerbview - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - - CFBundleName - GerbView - CFBundlePackageType - APPL - CFBundleShortVersionString - - CFBundleSignature - ???? - CFBundleVersion - - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - - NSHighResolutionCapable - True + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + pen + gba + gbr + gbx + gbo + gbl + gtl + gto + gta + gbp + gbp + gbs + gts + gtp + gbx + lgr + ger + pho + drl + + + CFBundleTypeIconFile gerbview_doc.icns + CFBundleTypeName gerbview document + LSHandlerRank Default + CFBundleTypeRole Viewer + + + + CFBundleDevelopmentRegion English + CFBundleExecutable gerbview + CFBundleGetInfoString + CFBundleIconFile gerbview.icns + CFBundleIdentifier org.kicad-eda.gerbview + CFBundleInfoDictionaryVersion 6.0 + CFBundleLongVersionString + CFBundleName GerbView + CFBundlePackageType APPL + CFBundleShortVersionString + CFBundleSignature ???? + CFBundleVersion + CSResourcesFileMapped + LSRequiresCarbon + NSHumanReadableCopyright + NSHighResolutionCapable True diff --git a/kicad/CMakeLists.txt b/kicad/CMakeLists.txt index 1d76b4696b..121c5af247 100644 --- a/kicad/CMakeLists.txt +++ b/kicad/CMakeLists.txt @@ -57,6 +57,22 @@ if( UNIX ) endif() +if( APPLE ) + # In this CMakeLists.txt's build directory, create kiface symlinks should get + # "installed()" as part of the kicad.app bundle. These are pointers on the + # target which point up and over to the stand alone kicad app's *.kiface files. + foreach( symlink pcbnew eeschema cvpcb ) + add_custom_command( TARGET kicad + COMMAND ${CMAKE_COMMAND} -E remove + "${CMAKE_CURRENT_BINARY_DIR}/kicad.app/Contents/MacOS/_${symlink}.kiface" + COMMAND ${CMAKE_COMMAND} -E create_symlink + "../../../${symlink}.app/Contents/MacOS/_${symlink}.kiface" + "${CMAKE_CURRENT_BINARY_DIR}/kicad.app/Contents/MacOS/_${symlink}.kiface" + COMMENT "kicad.app ${symlink} symlink" + ) + endforeach() +endif() + if( APPLE ) set_target_properties( kicad PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist diff --git a/kicad/Info.plist b/kicad/Info.plist index fa990ed54d..d55a08c51a 100644 --- a/kicad/Info.plist +++ b/kicad/Info.plist @@ -2,54 +2,36 @@ - CFBundleDocumentTypes - - - CFBundleTypeRole - Editor - CFBundleTypeIconFile - kicad_doc.icns - CFBundleTypeExtensions - - pro - - CFBundleTypeName - kicad project files - LSHandlerRank - Owner - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - kicad - CFBundleGetInfoString - - CFBundleIconFile - kicad.icns - CFBundleIdentifier - org.kicad-eda.kicad - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - - CFBundleName - KiCad - CFBundlePackageType - APPL - CFBundleShortVersionString - - CFBundleSignature - ???? - CFBundleVersion - - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - - NSHighResolutionCapable - True + CFBundleDocumentTypes + + + CFBundleTypeRole Editor + CFBundleTypeIconFile kicad_doc.icns + + CFBundleTypeExtensions + pro + + + CFBundleTypeName kicad project files + LSHandlerRank Owner + + + + CFBundleDevelopmentRegion English + CFBundleExecutable kicad + CFBundleGetInfoString + CFBundleIconFile kicad.icns + CFBundleIdentifier org.kicad-eda.kicad + CFBundleInfoDictionaryVersion 6.0 + CFBundleLongVersionString + CFBundleName KiCad + CFBundlePackageType APPL + CFBundleShortVersionString + CFBundleSignature ???? + CFBundleVersion + CSResourcesFileMapped + LSRequiresCarbon + NSHumanReadableCopyright + NSHighResolutionCapable True diff --git a/pagelayout_editor/CMakeLists.txt b/pagelayout_editor/CMakeLists.txt index cd6e41acdd..2f6a544db8 100644 --- a/pagelayout_editor/CMakeLists.txt +++ b/pagelayout_editor/CMakeLists.txt @@ -49,7 +49,20 @@ set( PL_EDITOR_EXTRA_SRCS if( MINGW ) # PL_EDITOR_RESOURCES variable is set by the macro. - mingw_resource_compiler(pl_editor) + mingw_resource_compiler( pl_editor ) +endif() + + +if( APPLE ) + set( PL_EDITOR_RESOURCES pl_editor.icns pl_editor_doc.icns ) + set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/pl_editor.icns" PROPERTIES + MACOSX_PACKAGE_LOCATION Resources + ) + set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/pl_editor_doc.icns" PROPERTIES + MACOSX_PACKAGE_LOCATION Resources + ) + set( MACOSX_BUNDLE_ICON_FILE pl_editor.icns ) + set( MACOSX_BUNDLE_GUI_IDENTIFIER org.kicad-eda.pl_editor ) endif() @@ -82,7 +95,6 @@ if( USE_KIWAY_DLLS ) ${PL_EDITOR_SRCS} ${DIALOGS_SRCS} ${PL_EDITOR_EXTRA_SRCS} -# ${PL_EDITOR_RESOURCES} ) target_link_libraries( pl_editor_kiface common @@ -114,18 +126,16 @@ if( USE_KIWAY_DLLS ) DESTINATION ${KICAD_BIN} COMPONENT binary ) - install( TARGETS pl_editor_kiface - DESTINATION ${KICAD_BIN} - COMPONENT binary - ) - if( APPLE ) - # copies kiface into the bundle - add_custom_target( _pleditor_kiface_copy ALL - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/pagelayout_editor/_pl_editor.kiface "${CMAKE_BINARY_DIR}/pagelayout_editor/pl_editor.app/Contents/MacOS/" - DEPENDS pl_editor_kiface - COMMENT "Copying kiface into pleditor" - ) + # puts the *.kiface into the *.app bundle while linking + set_target_properties( pl_editor_kiface PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pl_editor.app/Contents/MacOS/ + ) + else() + install( TARGETS pl_editor_kiface + DESTINATION ${KICAD_BIN} + COMPONENT binary + ) endif() else() @@ -137,13 +147,6 @@ else() ${PL_EDITOR_EXTRA_SRCS} ${PL_EDITOR_RESOURCES} ) - - if( APPLE ) - set_target_properties( pl_editor PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist - ) - endif() - target_link_libraries( pl_editor common polygon @@ -152,28 +155,15 @@ else() ${wxWidgets_LIBRARIES} ${GDI_PLUS_LIBRARIES} ) - install( TARGETS pl_editor DESTINATION ${KICAD_BIN} COMPONENT binary ) - endif() if( APPLE ) - set( PL_EDITOR_RESOURCES pl_editor.icns pl_editor_doc.icns ) - set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/pl_editor.icns" PROPERTIES - MACOSX_PACKAGE_LOCATION Resources - ) - set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/pl_editor_doc.icns" PROPERTIES - MACOSX_PACKAGE_LOCATION Resources - ) - set( MACOSX_BUNDLE_ICON_FILE pl_editor.icns ) - set( MACOSX_BUNDLE_GUI_IDENTIFIER org.kicad-eda.pl_editor ) - set_target_properties( pl_editor PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ) endif() - diff --git a/pagelayout_editor/Info.plist b/pagelayout_editor/Info.plist index 64d9326613..9db98f05b2 100644 --- a/pagelayout_editor/Info.plist +++ b/pagelayout_editor/Info.plist @@ -2,54 +2,36 @@ - CFBundleDocumentTypes - - - CFBundleTypeRole - Editor - CFBundleTypeExtensions - - kicad_wks - - CFBundleTypeIconFile - pl_editor.icns - CFBundleTypeName - pl_editor document - LSHandlerRank - Owner - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - pl_editor - CFBundleGetInfoString - - CFBundleIconFile - pl_editor.icns - CFBundleIdentifier - org.kicad-eda.pl_editor - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - - CFBundleName - pl_editor - CFBundlePackageType - APPL - CFBundleShortVersionString - - CFBundleSignature - ???? - CFBundleVersion - - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - - NSHighResolutionCapable - True + CFBundleDocumentTypes + + + CFBundleTypeRole Editor + CFBundleTypeExtensions + + kicad_wks + + + CFBundleTypeIconFile pl_editor.icns + CFBundleTypeName pl_editor document + LSHandlerRank Owner + + + + CFBundleDevelopmentRegion English + CFBundleExecutable pl_editor + CFBundleGetInfoString + CFBundleIconFile pl_editor.icns + CFBundleIdentifier org.kicad-eda.pl_editor + CFBundleInfoDictionaryVersion 6.0 + CFBundleLongVersionString + CFBundleName pl_editor + CFBundlePackageType APPL + CFBundleShortVersionString + CFBundleSignature ???? + CFBundleVersion + CSResourcesFileMapped + LSRequiresCarbon + NSHumanReadableCopyright + NSHighResolutionCapable True diff --git a/pcb_calculator/CMakeLists.txt b/pcb_calculator/CMakeLists.txt index 14db6b9ff6..8e1dad619c 100644 --- a/pcb_calculator/CMakeLists.txt +++ b/pcb_calculator/CMakeLists.txt @@ -122,14 +122,15 @@ if( USE_KIWAY_DLLS ) DESTINATION ${KICAD_BIN} COMPONENT binary ) - install( TARGETS pcb_calculator_kiface - DESTINATION ${KICAD_BIN} - COMPONENT binary - ) - if( APPLE ) - set_target_properties( pcb_calculator PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist + # puts the *.kiface into the *.app bundle while linking + set_target_properties( pcb_calculator_kiface PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pcb_calculator.app/Contents/MacOS/ + ) + else() + install( TARGETS pcb_calculator_kiface + DESTINATION ${KICAD_BIN} + COMPONENT binary ) endif() @@ -156,13 +157,6 @@ else() set_source_files_properties( pcb_calculator.cpp PROPERTIES COMPILE_DEFINITIONS "COMPILING_DLL" ) - - if( APPLE ) - set_target_properties( pcb_calculator PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist - ) - endif() - target_link_libraries( pcb_calculator common bitmaps @@ -175,3 +169,10 @@ else() ) endif() + + +if( APPLE ) + set_target_properties( pcb_calculator PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist + ) +endif() diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 42350320f5..068f950f39 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -589,17 +589,15 @@ if( USE_KIWAY_DLLS ) DESTINATION ${KICAD_BIN} COMPONENT binary ) - install( TARGETS pcbnew_kiface - DESTINATION ${KICAD_BIN} - COMPONENT binary - ) - if( APPLE ) - # copies kiface into the bundle - add_custom_target( _pcbnew_kiface_copy ALL - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/pcbnew/_pcbnew.kiface "${CMAKE_BINARY_DIR}/pcbnew/pcbnew.app/Contents/MacOS/" - DEPENDS pcbnew_kiface - COMMENT "Copying kiface into pcbnew" + # puts the *.kiface into the *.app bundle while linking + set_target_properties( pcbnew_kiface PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pcbnew.app/Contents/MacOS/ + ) + else() + install( TARGETS pcbnew_kiface + DESTINATION ${KICAD_BIN} + COMPONENT binary ) endif() @@ -763,3 +761,4 @@ if( false ) # haven't been used in years. ) target_link_libraries( layer_widget_test common ${wxWidgets_LIBRARIES} ) endif() + diff --git a/pcbnew/Info.plist b/pcbnew/Info.plist index 1f4b5bfdd5..3f31259d06 100644 --- a/pcbnew/Info.plist +++ b/pcbnew/Info.plist @@ -2,53 +2,36 @@ - CFBundleDocumentTypes - - - CFBundleTypeRole - Editor - CFBundleTypeIconFile - pcbnew_doc.icns - CFBundleTypeExtensions - - kicad_pcb - brd - - CFBundleTypeName - pcbnew board - LSHandlerRank - Owner - - - CFBundleExecutable - pcbnew - CFBundleGetInfoString - - CFBundleIconFile - pcbnew.icns - CFBundleIdentifier - org.kicad-eda.pcbnew - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - - CFBundleName - PCBNew - CFBundlePackageType - APPL - CFBundleShortVersionString - - CFBundleSignature - ???? - CFBundleVersion - - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - - NSHighResolutionCapable - True + CFBundleDocumentTypes + + + CFBundleTypeRole Editor + CFBundleTypeIconFile pcbnew_doc.icns + CFBundleTypeExtensions + + kicad_pcb + brd + + + CFBundleTypeName pcbnew board + LSHandlerRank Owner + + + + CFBundleExecutable pcbnew + CFBundleGetInfoString + CFBundleIconFile pcbnew.icns + CFBundleIdentifier org.kicad-eda.pcbnew + CFBundleInfoDictionaryVersion 6.0 + CFBundleLongVersionString + CFBundleName PCBNew + CFBundlePackageType APPL + CFBundleShortVersionString + CFBundleSignature ???? + CFBundleVersion + CSResourcesFileMapped + LSRequiresCarbon + NSHumanReadableCopyright + NSHighResolutionCapable True From 963029262b17aa57e78748c7c8ed8a2c27c2a997 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 9 May 2014 20:06:18 +0200 Subject: [PATCH 19/68] Fix an annoying behavior of new quasi modal frames on Windows (when closing them, the caller frame was no more on top ) --- common/kiway_player.cpp | 15 +++++++++++++-- include/kiway_player.h | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp index fc0415a702..fda3962d2d 100644 --- a/common/kiway_player.cpp +++ b/common/kiway_player.cpp @@ -45,7 +45,7 @@ KIWAY_PLAYER::KIWAY_PLAYER( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType EDA_BASE_FRAME( aParent, aFrameType, aTitle, aPos, aSize, aStyle, aWdoName ), KIWAY_HOLDER( aKiway ), m_modal( false ), - m_modal_loop( 0 ) + m_modal_loop( 0 ), m_modal_resultant_parent( 0 ) { // DBG( printf("KIWAY_EXPRESS::wxEVENT_ID:%d\n", KIWAY_EXPRESS::wxEVENT_ID );) } @@ -57,7 +57,7 @@ KIWAY_PLAYER::KIWAY_PLAYER( wxWindow* aParent, wxWindowID aId, const wxString& a EDA_BASE_FRAME( aParent, (FRAME_T) aId, aTitle, aPos, aSize, aStyle, aWdoName ), KIWAY_HOLDER( 0 ), m_modal( false ), - m_modal_loop( 0 ) + m_modal_loop( 0 ), m_modal_resultant_parent( 0 ) { // DBG( printf("KIWAY_EXPRESS::wxEVENT_ID:%d\n", KIWAY_EXPRESS::wxEVENT_ID );) } @@ -95,6 +95,7 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow } clear_this( (void*&) m_modal_loop ); + m_modal_resultant_parent = aResultantFocusWindow; Show( true ); SetFocus(); @@ -138,6 +139,16 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow return m_modal_ret_val; } +bool KIWAY_PLAYER::Destroy() +{ + // Needed on Windows to leave the modal parent on top with focus +#ifdef __WINDOWS__ + if( m_modal_resultant_parent && GetParent() != m_modal_resultant_parent ) + Reparent( m_modal_resultant_parent ); +#endif + + return EDA_BASE_FRAME::Destroy(); +} bool KIWAY_PLAYER::IsDismissed() { diff --git a/include/kiway_player.h b/include/kiway_player.h index 48cfeafc4a..0bdc2e8045 100644 --- a/include/kiway_player.h +++ b/include/kiway_player.h @@ -202,6 +202,11 @@ public: */ virtual void KiwayMailIn( KIWAY_EXPRESS& aEvent ); + /** + * Our version of Destroy() which is virtual from wxWidgets + */ + bool Destroy(); + protected: bool IsModal() { return m_modal; } @@ -229,6 +234,7 @@ protected: // variables for modal behavior support, only used by a few derivatives. bool m_modal; // true if frame is intended to be modal, not modeless WX_EVENT_LOOP* m_modal_loop; // points to nested event_loop, NULL means not modal and dismissed + wxWindow* m_modal_resultant_parent; // the window caller in modal mode wxString m_modal_string; bool m_modal_ret_val; // true if a selection was made From e45aadd11baa545170735b4d2049005f9dbe668a Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Fri, 9 May 2014 13:35:48 -0500 Subject: [PATCH 20/68] Modular-Kicad milestone B), minor portion: *) Implement a framework for "Data Load On Demand". *) Implement FP_LIB_TABLE* PROJECT::PcbFootprintLibs(), which is the first prototype. This allows the project specific footprint tables to be part of the Module Editor when invoked from Eeschema. --- common/fp_lib_table.cpp | 15 +- common/project.cpp | 43 ++- cvpcb/cfg.cpp | 19 +- cvpcb/class_DisplayFootprintsFrame.cpp | 3 +- cvpcb/class_library_listbox.cpp | 2 +- cvpcb/cvframe.cpp | 32 +-- cvpcb/cvpcb_mainframe.h | 6 - cvpcb/readwrite_dlgs.cpp | 352 +------------------------ include/fp_lib_table.h | 2 + include/project.h | 69 +++-- include/wxBasePcbFrame.h | 10 +- pcbnew/basepcbframe.cpp | 24 +- pcbnew/files.cpp | 6 +- pcbnew/librairi.cpp | 24 +- pcbnew/loadcmp.cpp | 2 +- pcbnew/modedit.cpp | 2 +- pcbnew/moduleframe.cpp | 6 +- pcbnew/modview_frame.cpp | 13 +- pcbnew/netlist.cpp | 2 +- pcbnew/onleftclick.cpp | 3 +- pcbnew/pcbnew_config.cpp | 17 +- pcbnew/xchgmod.cpp | 3 +- scripts/kicad-install.sh | 2 +- 23 files changed, 176 insertions(+), 481 deletions(-) diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp index f69ccd2ea5..2b5a47aa9c 100644 --- a/common/fp_lib_table.cpp +++ b/common/fp_lib_table.cpp @@ -137,6 +137,12 @@ FP_LIB_TABLE::FP_LIB_TABLE( FP_LIB_TABLE* aFallBackTable ) : } +FP_LIB_TABLE::~FP_LIB_TABLE() +{ + // *fallBack is not owned here. +} + + wxArrayString FP_LIB_TABLE::FootprintEnumerate( const wxString& aNickname ) { const ROW* row = FindRow( aNickname ); @@ -514,9 +520,16 @@ std::vector FP_LIB_TABLE::GetLogicalLibs() } while( ( cur = cur->fallBack ) != 0 ); + ret.reserve( unique.size() ); + + // DBG(printf( "%s: count:%zd\n", __func__, unique.size() );) + // return a sorted, unique set of nicknames in a std::vector to caller for( std::set::const_iterator it = unique.begin(); it!=unique.end(); ++it ) + { + //DBG(printf( " %s\n", TO_UTF8( *it ) );) ret.push_back( *it ); + } return ret; } @@ -738,7 +751,7 @@ wxString FP_LIB_TABLE::GetGlobalTableFileName() void FP_LIB_TABLE::Load( const wxString& aFileName ) throw( IO_ERROR ) { - // Empty footprint library tables are valid. + // It's OK if footprint library tables are missing. if( wxFileName::IsFileReadable( aFileName ) ) { FILE_LINE_READER reader( aFileName ); diff --git a/common/project.cpp b/common/project.cpp index df31c81c1b..2e10d8a661 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -42,15 +42,22 @@ PROJECT::PROJECT() memset( m_elems, 0, sizeof(m_elems) ); } + +void PROJECT::ElemsClear() +{ + // careful here, this should work, but the virtual destructor may not + // be in the same link image as PROJECT. + for( unsigned i = 0; iClear(); - - /* this is done by ConfigLoad(), and that sets the env var too. - prj.SetProjectFullName( fn.GetFullPath() ); - */ - - wxString projectFpLibTableFileName = prj.FootprintLibTblName(); - - try - { - FootprintLibs()->Load( projectFpLibTableFileName ); - } - catch( const IO_ERROR& ioe ) - { - DisplayError( this, ioe.errorText ); - } + // Force it to be loaded on demand. + prj.ElemClear( PROJECT::ELEM_FPTBL ); } diff --git a/cvpcb/class_DisplayFootprintsFrame.cpp b/cvpcb/class_DisplayFootprintsFrame.cpp index e1a0ab36dc..241ecdd861 100644 --- a/cvpcb/class_DisplayFootprintsFrame.cpp +++ b/cvpcb/class_DisplayFootprintsFrame.cpp @@ -488,7 +488,8 @@ MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName ) wxLogDebug( wxT( "Load footprint <%s> from library <%s>." ), fpname.c_str(), nickname.c_str() ); - footprint = FootprintLibs()->FootprintLoad( FROM_UTF8( nickname.c_str() ), FROM_UTF8( fpname.c_str() ) ); + footprint = Prj().PcbFootprintLibs()->FootprintLoad( + FROM_UTF8( nickname.c_str() ), FROM_UTF8( fpname.c_str() ) ); } catch( const IO_ERROR& ioe ) { diff --git a/cvpcb/class_library_listbox.cpp b/cvpcb/class_library_listbox.cpp index db86776145..4149f285ca 100644 --- a/cvpcb/class_library_listbox.cpp +++ b/cvpcb/class_library_listbox.cpp @@ -128,7 +128,7 @@ void LIBRARY_LISTBOX::SetLibraryList( const wxArrayString& aList ) { RefreshItems( 0L, m_libraryList.Count()-1 ); -#if defined (__WXGTK__ ) // && wxMINOR_VERSION == 8 +#if defined (__WXGTK__ ) && wxMINOR_VERSION == 8 // @bug On GTK and wxWidgets 2.8.x, this will assert in debug builds because the // column parameter is -1. This was the only way to prevent GTK3 from // ellipsizing long strings down to a few characters. It still doesn't set diff --git a/cvpcb/cvframe.cpp b/cvpcb/cvframe.cpp index 3ffd306b7d..7079e40287 100644 --- a/cvpcb/cvframe.cpp +++ b/cvpcb/cvframe.cpp @@ -200,24 +200,6 @@ CVPCB_MAINFRAME::~CVPCB_MAINFRAME() } -FP_LIB_TABLE* CVPCB_MAINFRAME::FootprintLibs() const -{ - PROJECT& prj = Prj(); - FP_LIB_TABLE* tbl = dynamic_cast( prj.Elem( PROJECT::FPTBL ) ); - - if( !tbl ) - { - // Stack the project specific FP_LIB_TABLE overlay on top of the global table. - // ~FP_LIB_TABLE() will not touch the fallback table, so multiple projects may - // stack this way, all using the same global fallback table. - tbl = new FP_LIB_TABLE( &GFootprintTable ); - prj.Elem( PROJECT::FPTBL, tbl ); - } - - return tbl; -} - - void CVPCB_MAINFRAME::LoadSettings( wxConfigBase* aCfg ) { EDA_BASE_FRAME::LoadSettings( aCfg ); @@ -493,7 +475,7 @@ void CVPCB_MAINFRAME::ConfigCvpcb( wxCommandEvent& event ) void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent ) { bool tableChanged = false; - int r = InvokePcbLibTableEditor( this, &GFootprintTable, FootprintLibs() ); + int r = InvokePcbLibTableEditor( this, &GFootprintTable, Prj().PcbFootprintLibs() ); if( r & 1 ) { @@ -521,7 +503,7 @@ void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent ) try { - FootprintLibs()->Save( fileName ); + Prj().PcbFootprintLibs()->Save( fileName ); tableChanged = true; } catch( const IO_ERROR& ioe ) @@ -538,7 +520,7 @@ void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent ) if( tableChanged ) { BuildLIBRARY_LISTBOX(); - m_footprints.ReadFootprintFiles( FootprintLibs() ); + m_footprints.ReadFootprintFiles( Prj().PcbFootprintLibs() ); } } @@ -735,7 +717,7 @@ void CVPCB_MAINFRAME::DisplayStatus() bool CVPCB_MAINFRAME::LoadFootprintFiles() { - FP_LIB_TABLE* fptbl = FootprintLibs(); + FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs(); // Check if there are footprint libraries in the footprint library table. if( !fptbl || !fptbl->GetLogicalLibs().size() ) @@ -1012,11 +994,13 @@ void CVPCB_MAINFRAME::BuildLIBRARY_LISTBOX() wxFONTWEIGHT_NORMAL ) ); } - if( FootprintLibs() ) + FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs(); + + if( tbl ) { wxArrayString libNames; - std::vector< wxString > libNickNames = FootprintLibs()->GetLogicalLibs(); + std::vector< wxString > libNickNames = tbl->GetLogicalLibs(); for( unsigned ii = 0; ii < libNickNames.size(); ii++ ) libNames.Add( libNickNames[ii] ); diff --git a/cvpcb/cvpcb_mainframe.h b/cvpcb/cvpcb_mainframe.h index 3993091dda..7b136746a9 100644 --- a/cvpcb/cvpcb_mainframe.h +++ b/cvpcb/cvpcb_mainframe.h @@ -88,12 +88,6 @@ public: bool OpenProjectFiles( const std::vector& aFileSet, int aCtl=0 ); // overload KIWAY_PLAYER - /** - * Function FootprintLibs - * @return the project #FP_LIB_TABLE. - */ - FP_LIB_TABLE* FootprintLibs() const; - /** * @return a pointer on the Footprint Viewer frame, if exists, or NULL */ diff --git a/cvpcb/readwrite_dlgs.cpp b/cvpcb/readwrite_dlgs.cpp index 538fe34841..939abc7acb 100644 --- a/cvpcb/readwrite_dlgs.cpp +++ b/cvpcb/readwrite_dlgs.cpp @@ -119,346 +119,6 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) } -#if 0 - - /* - - This code block was based on two major assumptions that are no longer true: - 1) Footprint library basenames would remain the same. - (But no, basenames have been renamed in the github repo.) - 2) *.mod files would still be around and merely reside in the FP_LIB_TABLE. - (But no, they have been converted to *.pretty.) - - There is a newer replacement code block in the #else region. - - */ - -/** - * Function missingLegacyLibs - * tests the list of \a aLibNames by URI to determine if any of them are missing from - * the #FP_LIB_TABLE. - * - * @note The missing legacy footprint library test is performed by using old library - * file path lookup method. If the library is found, it is compared against all - * of the URIs in the table rather than the nickname. This was done because the - * user could change the nicknames from the default table. Using the full path - * is more reliable. - * - * @param aLibNames is the list of legacy library names. - * @param aErrorMsg is a pointer to a wxString object to store the URIs of any missing - * legacy library paths. Can be NULL. - * @return true if there are missing legacy libraries. Otherwise false. - */ -static bool missingLegacyLibs( FP_LIB_TABLE* aTbl, SEARCH_STACK& aSStack, - const wxArrayString& aLibNames, wxString* aErrorMsg ) -{ - bool missing = false; - - for( unsigned i = 0; i < aLibNames.GetCount(); i++ ) - { - wxFileName fn( wxEmptyString, aLibNames[i], LegacyFootprintLibPathExtension ); - - wxString legacyLibPath = aSStack.FindValidPath( fn.GetFullPath() ); - - /* - if( legacyLibPath.IsEmpty() ) - continue; - */ - - if( !aTbl->FindRowByURI( legacyLibPath ) ) - { - missing = true; - - if( aErrorMsg ) - { - *aErrorMsg += wxChar( '"' ); - - if( !legacyLibPath ) - *aErrorMsg += !legacyLibPath ? aLibNames[i] : legacyLibPath; - - *aErrorMsg += wxT( "\"\n" ); - } - } - } - - return missing; -} - - -/** - * Function convertFromLegacy - * converts the footprint names in \a aNetList from the legacy format to the #FPID format. - * - * @param aNetList is the #NETLIST object to convert. - * @param aLibNames is the list of legacy footprint library names from the currently loaded - * project. - * @param aReporter is the #REPORTER object to dump messages into. - * @return true if all footprint names were successfully converted to a valid FPID. - */ -static bool convertFromLegacy( FP_LIB_TABLE* aTbl, SEARCH_STACK& aSStack, NETLIST& aNetList, - const wxArrayString& aLibNames, REPORTER* aReporter = NULL ) throw( IO_ERROR ) -{ - wxString msg; - FPID lastFPID; - COMPONENT* component; - MODULE* module = 0; - bool retv = true; - - if( aNetList.IsEmpty() ) - return true; - - aNetList.SortByFPID(); - - wxString libPath; - - PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) ); - - for( unsigned ii = 0; ii < aNetList.GetCount(); ii++ ) - { - component = aNetList.GetComponent( ii ); - - // The footprint hasn't been assigned yet so ignore it. - if( component->GetFPID().empty() ) - continue; - - if( component->GetFPID() != lastFPID ) - { - module = NULL; - - for( unsigned ii = 0; ii < aLibNames.GetCount(); ii++ ) - { - wxFileName fn( wxEmptyString, aLibNames[ii], LegacyFootprintLibPathExtension ); - - libPath = aSStack.FindValidPath( fn.GetFullPath() ); - - if( !libPath ) - { - if( aReporter ) - { - msg.Printf( _( "Cannot find footprint library file '%s' in any of the " - "KiCad legacy library search paths.\n" ), - GetChars( fn.GetFullPath() ) ); - aReporter->Report( msg ); - } - - retv = false; - continue; - } - - module = pi->FootprintLoad( libPath, component->GetFPID().GetFootprintName() ); - - if( module ) - { - lastFPID = component->GetFPID(); - break; - } - } - } - - if( !module ) - { - if( aReporter ) - { - msg.Printf( _( "Component '%s' footprint '%s' was not found in any legacy " - "library.\n" ), - GetChars( component->GetReference() ), - GetChars( component->GetFPID().Format() ) ); - aReporter->Report( msg ); - } - - // Clear the footprint assignment since the old library lookup method is no - // longer valid. - FPID emptyFPID; - - component->SetFPID( emptyFPID ); - retv = false; - continue; - } - else - { - wxString libNickname; - - const FP_LIB_TABLE::ROW* row; - - if( ( row = aTbl->FindRowByURI( libPath ) ) != NULL ) - libNickname = row->GetNickName(); - - if( libNickname.IsEmpty() ) - { - if( aReporter ) - { - msg.Printf( _( "Component '%s' with footprint '%s' and legacy library path '%s' " - "was not found in the footprint library table.\n" ), - GetChars( component->GetReference() ), - GetChars( component->GetFPID().Format() ), - GetChars( libPath ) - ); - aReporter->Report( msg ); - } - - retv = false; - } - else - { - FPID newFPID = lastFPID; - newFPID.SetLibNickname( libNickname ); - - if( !newFPID.IsValid() ) - { - if( aReporter ) - { - msg.Printf( _( "Component '%s' FPID '%s' is not valid.\n" ), - GetChars( component->GetReference() ), - GetChars( newFPID.Format() ) ); - aReporter->Report( msg ); - } - - retv = false; - } - else - { - // The footprint name should already be set. - component->SetFPID( newFPID ); - } - } - } - } - - return retv; -} - - -bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() -{ - COMPONENT* component; - wxString msg; - bool isLegacy = true; - - ReadSchematicNetlist(); - - if( m_ListCmp == NULL ) - return false; - - LoadProjectFile( m_NetlistFileName.GetFullPath() ); - LoadFootprintFiles(); - BuildFOOTPRINTS_LISTBOX(); - BuildLIBRARY_LISTBOX(); - - m_ListCmp->Clear(); - m_undefinedComponentCnt = 0; - - if( m_netlist.AnyFootprintsLinked() ) - { - for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) - { - component = m_netlist.GetComponent( i ); - - if( component->GetFPID().empty() ) - continue; - - if( isLegacy ) - { - if( !component->GetFPID().IsLegacy() ) - isLegacy = false; - } - } - } - else - { - isLegacy = false; // None of the components have footprints assigned. - } - - wxString missingLibs; - - // Check if footprint links were generated before the footprint library table was implemented. - if( isLegacy ) - { - if( missingLegacyLibs( FootprintLibs(), Prj().PcbSearchS(), m_ModuleLibNames, &missingLibs ) ) - { - msg = wxT( "The following legacy libraries are defined in the project file " - "but were not found in the footprint library table:\n\n" ) + missingLibs; - msg += wxT( "\nDo you want to update the footprint library table before " - "attempting to update the assigned footprints?" ); - - if( IsOK( this, msg ) ) - { - wxCommandEvent cmd; - - OnEditFootprintLibraryTable( cmd ); - } - } - - msg = wxT( "Some or all of the assigned footprints contain legacy entries. Would you " - "like CvPcb to attempt to convert them to the new footprint library table " - "format?" ); - - if( IsOK( this, msg ) ) - { - msg.Clear(); - WX_STRING_REPORTER reporter( &msg ); - - SEARCH_STACK& search = Prj().SchSearchS(); - - if( !convertFromLegacy( FootprintLibs(), search, m_netlist, m_ModuleLibNames, &reporter ) ) - { - HTML_MESSAGE_BOX dlg( this, wxEmptyString ); - - dlg.MessageSet( wxT( "The following errors occurred attempting to convert the " - "footprint assignments:\n\n" ) ); - dlg.ListSet( msg ); - dlg.MessageSet( wxT( "\nYou will need to reassign them manually if you want them " - "to be updated correctly the next time you import the " - "netlist in Pcbnew." ) ); - dlg.ShowModal(); - } - - m_modified = true; - } - else - { - // Clear the legacy footprint assignments. - for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) - { - FPID emptyFPID; - component = m_netlist.GetComponent( i ); - component->SetFPID( emptyFPID ); - m_modified = true; - } - } - } - - for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) - { - component = m_netlist.GetComponent( i ); - - msg.Printf( CMP_FORMAT, m_ListCmp->GetCount() + 1, - GetChars( component->GetReference() ), - GetChars( component->GetValue() ), - GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); - - m_ListCmp->AppendLine( msg ); - - if( component->GetFPID().empty() ) - { - m_undefinedComponentCnt += 1; - continue; - } - } - - if( !m_netlist.IsEmpty() ) - m_ListCmp->SetSelection( 0, true ); - - DisplayStatus(); - - UpdateTitle(); - - UpdateFileHistory( m_NetlistFileName.GetFullPath() ); - - return true; -} - -#else // new strategy - /// Return true if the resultant FPID has a certain nickname. The guess /// is only made if this footprint resides in only one library. /// @return int - 0 on success, 1 on not found, 2 on ambiguous i.e. multiple matches @@ -503,7 +163,6 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() { wxString msg; bool hasMissingNicks = false; - FP_LIB_TABLE* tbl = FootprintLibs(); ReadSchematicNetlist(); @@ -512,6 +171,7 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() LoadProjectFile( m_NetlistFileName.GetFullPath() ); LoadFootprintFiles(); + BuildFOOTPRINTS_LISTBOX(); BuildLIBRARY_LISTBOX(); @@ -554,6 +214,9 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() if( component->GetFPID().IsLegacy() ) { + // get this first here, it's possibly obsoleted if we get it too soon. + FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs(); + int guess = guessNickname( tbl, (FPID*) &component->GetFPID() ); switch( guess ) @@ -659,9 +322,6 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() } -#endif - - int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName ) { wxFileName fn; @@ -685,7 +345,7 @@ int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName ) fn.SetExt( ComponentFileExtension ); // Save the project specific footprint library table. - if( !FootprintLibs()->IsEmpty( false ) ) + if( !Prj().PcbFootprintLibs()->IsEmpty( false ) ) { wxString fp_lib_tbl = Prj().FootprintLibTblName(); @@ -695,7 +355,7 @@ int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName ) { try { - FootprintLibs()->Save( fp_lib_tbl ); + Prj().PcbFootprintLibs()->Save( fp_lib_tbl ); } catch( const IO_ERROR& ioe ) { diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index 679d437b42..4a2b822137 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -270,6 +270,8 @@ public: */ FP_LIB_TABLE( FP_LIB_TABLE* aFallBackTable = NULL ); + ~FP_LIB_TABLE(); + /// Delete all rows. void Clear() { diff --git a/include/project.h b/include/project.h index a4928f4e5c..c7f7a7f3dd 100644 --- a/include/project.h +++ b/include/project.h @@ -35,7 +35,7 @@ class wxConfigBase; class PARAM_CFG_ARRAY; - +class FP_LIB_TABLE; #define VTBL_ENTRY virtual @@ -49,11 +49,12 @@ class PROJECT { public: - /// Derive PROJECT elements from this, it has a virtual destructor, and - /// Elem*() functions can work with it. Implementation is opaque in - /// class PROJECT. If find you have to include derived class headers in this - /// file, you are doing something wrong. Keep knowledge of derived classes - /// opaque to class PROJECT please. + /// A PROJECT can hold stuff it knows nothing about, in the form of + /// _ELEM derivatives. Derive PROJECT elements from this, it has a virtual + /// destructor, and Elem*() functions can work with it. Implementation is + /// opaque in class PROJECT. If find you have to include derived class headers + /// in this file, you are doing incompatible with the goal of this class. + /// Keep knowledge of derived classes opaque to class PROJECT please. class _ELEM { public: @@ -63,6 +64,8 @@ public: PROJECT(); ~PROJECT(); + //--------------------------------------------------------- + // VTBL_ENTRY bool MaybeLoadProjectSettings( const std::vector& aFileSet ); /** @@ -154,18 +157,12 @@ public: */ enum ELEM_T { - FPTBL, + ELEM_FPTBL, ELEM_COUNT }; /** - * A PROJECT can hold stuff it knows nothing about, in the form of - * _ELEM derivatives. This function gives access to a PROJECT::_ELEM using - * enum ELEM_T as an index. - *

- * Acts as setter iff aElem is not NULL, else getter. - *

* Typically wrapped somewhere else in a more meaningful function wrapper. * This is a cross module API, therefore the _ELEM destructor is virtual and * can point to a destructor function in another link image. Be careful that @@ -174,7 +171,47 @@ public: * Summary: 1) cross module API, 2) PROJECT knows nothing about _ELEM objects, * except how to delete them and set and get pointers to them. */ - VTBL_ENTRY _ELEM* Elem( ELEM_T aIndex, _ELEM* aElem = NULL ); + VTBL_ENTRY _ELEM* GetElem( ELEM_T aIndex ); + VTBL_ENTRY void SetElem( ELEM_T aIndex, _ELEM* aElem ); + + /// Inline, clear the _ELEM at position aIndex + void ElemClear( ELEM_T aIndex ) + { + _ELEM* existing = GetElem( aIndex ); + delete existing; // virtual + SetElem( aIndex, NULL ); + } + + /** + * Function ElemsClear + * deletes all the _ELEMs and set their pointers to NULL. + */ + VTBL_ENTRY void ElemsClear(); + + //-------------------------------------------------------- + + //----------------------------------------------------- + + // These are the non-virtual DATA LOAD ON DEMAND members. They load project related + // data on demand, and do so typicallly into m_elems[] at a particular index using + // SetElem() & GetElem(). That is, they wrap SetElem() and GetElem(). + // To get the data to reload on demand, first SetProjectFullName(), + // then call ElemClear() from client code. + + // non-virtuals resident in PCBNEW link image(s). By being non-virtual, these + // functions can get linked into the KIFACE that needs them, and only there. + // In fact, the other KIFACEs don't even know they exist. +#if defined(PCBNEW) || defined(CVPCB) + // These are all prefaced with "Pcb" + FP_LIB_TABLE* PcbFootprintLibs(); +#endif + + +#if defined(EESCHEMA) + // These are all prefaced with "Sch" +#endif + + //---------------------------------------------------- private: @@ -215,10 +252,6 @@ private: //-------------------------------------------------------------- #if 0 - VTBL_ENTRY int ElemAllocNdx(); - VTBL_ENTRY void ElemSet( int aIndex, ELEMENT_BASE* aBlock ); - VTBL_ENTRY ELEM_BASE* ElemGet( int aIndex ) - /** * Function Value * fetches a project variable @a aVariable and returns true if that variable was diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index e60a969abb..b518af6f12 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -103,7 +103,7 @@ protected: * * @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 the table returned from #FootprintLibs(). + * libraries in the table returned from #Prj().PcbFootprintLibs(). * @throw IO_ERROR if an I/O error occurs or a #PARSE_ERROR if a file parsing error * occurs while reading footprint library files. */ @@ -127,7 +127,7 @@ public: * * @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 table returned from #FootprintLibs(). + * libraries in table returned from #Prj().PcbFootprintLibs(). */ MODULE* LoadFootprint( const FPID& aFootprintId ); @@ -466,12 +466,6 @@ public: */ wxString SelectFootprintFromLibBrowser(); - /** - * Function FootprintLibs - * @return the project #FP_LIB_TABLE. - */ - FP_LIB_TABLE* FootprintLibs() const; - // ratsnest functions /** * Function Compile_Ratsnest diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 2307a5b3c7..af02b79258 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -174,10 +174,15 @@ PCB_BASE_FRAME::~PCB_BASE_FRAME() } -FP_LIB_TABLE* PCB_BASE_FRAME::FootprintLibs() const +FP_LIB_TABLE* PROJECT::PcbFootprintLibs() { - PROJECT& prj = Prj(); - FP_LIB_TABLE* tbl = dynamic_cast( prj.Elem( PROJECT::FPTBL ) ); + // This is a lazy loading function, it loads the project specific table when + // that table is asked for, not before. + + FP_LIB_TABLE* tbl = (FP_LIB_TABLE*) GetElem( ELEM_FPTBL ); + + // its gotta be NULL or a FP_LIB_TABLE, or a bug. + wxASSERT( !tbl || dynamic_cast( tbl ) ); if( !tbl ) { @@ -186,7 +191,18 @@ FP_LIB_TABLE* PCB_BASE_FRAME::FootprintLibs() const // stack this way, all using the same global fallback table. tbl = new FP_LIB_TABLE( &GFootprintTable ); - prj.Elem( PROJECT::FPTBL, tbl ); + SetElem( ELEM_FPTBL, tbl ); + + wxString projectFpLibTableFileName = FootprintLibTblName(); + + try + { + tbl->Load( projectFpLibTableFileName ); + } + catch( const IO_ERROR& ioe ) + { + DisplayError( NULL, ioe.errorText ); + } } return tbl; diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index ec1da8e310..27262d6f38 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -173,7 +173,7 @@ void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event ) Clear_Pcb( true ); // Clear footprint library table for the new board. - FootprintLibs()->Clear(); + Prj().PcbFootprintLibs()->Clear(); wxFileName fn; @@ -603,7 +603,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF return false; // Save the project specific footprint library table. - if( !FootprintLibs()->IsEmpty( false ) ) + if( !Prj().PcbFootprintLibs()->IsEmpty( false ) ) { wxString fp_lib_tbl = Prj().FootprintLibTblName(); @@ -613,7 +613,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF { try { - FootprintLibs()->Save( fp_lib_tbl ); + Prj().PcbFootprintLibs()->Save( fp_lib_tbl ); } catch( const IO_ERROR& ioe ) { diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index 487f356e6a..c55cad44b5 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -469,7 +469,7 @@ bool FOOTPRINT_EDIT_FRAME::DeleteModuleFromCurrentLibrary() { wxString nickname = getLibNickName(); - if( !FootprintLibs()->IsFootprintLibWritable( nickname ) ) + if( !Prj().PcbFootprintLibs()->IsFootprintLibWritable( nickname ) ) { wxString msg = wxString::Format( _( "Library '%s' is read only" ), @@ -481,7 +481,7 @@ bool FOOTPRINT_EDIT_FRAME::DeleteModuleFromCurrentLibrary() } wxString fpid_txt = PCB_BASE_FRAME::SelectFootprint( this, nickname, - wxEmptyString, wxEmptyString, FootprintLibs() ); + wxEmptyString, wxEmptyString, Prj().PcbFootprintLibs() ); if( !fpid_txt ) return false; @@ -497,7 +497,7 @@ bool FOOTPRINT_EDIT_FRAME::DeleteModuleFromCurrentLibrary() try { - FootprintLibs()->FootprintDelete( nickname, fpname ); + Prj().PcbFootprintLibs()->FootprintDelete( nickname, fpname ); } catch( const IO_ERROR& ioe ) { @@ -545,22 +545,24 @@ void PCB_EDIT_FRAME::ArchiveModulesOnBoard( bool aNewModulesOnly ) try { + FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs(); + // Delete old library if we're replacing it entirely. if( !aNewModulesOnly ) { - FootprintLibs()->FootprintLibDelete( nickname ); - FootprintLibs()->FootprintLibCreate( nickname ); + tbl->FootprintLibDelete( nickname ); + tbl->FootprintLibCreate( nickname ); for( MODULE* m = GetBoard()->m_Modules; m; m = m->Next() ) { - FootprintLibs()->FootprintSave( nickname, m, true ); + tbl->FootprintSave( nickname, m, true ); } } else { for( MODULE* m = GetBoard()->m_Modules; m; m = m->Next() ) { - FootprintLibs()->FootprintSave( nickname, m, false ); + tbl->FootprintSave( nickname, m, false ); // Check for request to stop backup (ESCAPE key actuated) if( m_canvas->GetAbortRequest() ) @@ -627,7 +629,9 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibrary, try { - MODULE* m = FootprintLibs()->FootprintLoad( aLibrary, footprintName ); + FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs(); + + MODULE* m = tbl->FootprintLoad( aLibrary, footprintName ); if( m ) { @@ -653,7 +657,7 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibrary, // this always overwrites any existing footprint, but should yell on its // own if the library or footprint is not writable. - FootprintLibs()->FootprintSave( aLibrary, aModule ); + tbl->FootprintSave( aLibrary, aModule ); } catch( const IO_ERROR& ioe ) { @@ -738,7 +742,7 @@ wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting ) headers.Add( _( "Nickname" ) ); headers.Add( _( "Description" ) ); - FP_LIB_TABLE* fptbl = FootprintLibs(); + FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs(); std::vector< wxArrayString > itemsToDisplay; std::vector< wxString > nicknames = fptbl->GetLogicalLibs(); diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index dda500664f..cd3f85d00d 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -315,7 +315,7 @@ MODULE* PCB_BASE_FRAME::LoadFootprint( const FPID& aFootprintId ) MODULE* PCB_BASE_FRAME::loadFootprint( const FPID& aFootprintId ) throw( IO_ERROR, PARSE_ERROR ) { - FP_LIB_TABLE* fptbl = FootprintLibs(); + FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs(); wxCHECK_MSG( fptbl, NULL, wxT( "Cannot look up FPID in NULL FP_LIB_TABLE." ) ); diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index 26e6ca7fde..81b74eebe7 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -491,7 +491,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) Clear_Pcb( true ); SetCrossHairPosition( wxPoint( 0, 0 ) ); - LoadModuleFromLibrary( getLibNickName(), FootprintLibs(), true ); + LoadModuleFromLibrary( getLibNickName(), Prj().PcbFootprintLibs(), true ); redraw = true; if( GetBoard()->m_Modules ) diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index cc83322f50..4ef660f343 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -274,7 +274,7 @@ wxString FOOTPRINT_EDIT_FRAME::getLibPath() { const wxString& nickname = getLibNickName(); - const FP_LIB_TABLE::ROW* row = FootprintLibs()->FindRow( nickname ); + const FP_LIB_TABLE::ROW* row = Prj().PcbFootprintLibs()->FindRow( nickname ); return row->GetFullURI( true ); } @@ -481,7 +481,7 @@ void FOOTPRINT_EDIT_FRAME::OnUpdateReplaceModuleInBoard( wxUpdateUIEvent& aEvent void FOOTPRINT_EDIT_FRAME::OnUpdateSelectCurrentLib( wxUpdateUIEvent& aEvent ) { - FP_LIB_TABLE* fptbl = FootprintLibs(); + FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs(); aEvent.Enable( fptbl && !fptbl->IsEmpty() ); } @@ -621,7 +621,7 @@ void FOOTPRINT_EDIT_FRAME::updateTitle() { try { - bool writable = FootprintLibs()->IsFootprintLibWritable( nickname ); + bool writable = Prj().PcbFootprintLibs()->IsFootprintLibWritable( nickname ); // no exception was thrown, this means libPath is valid, but it may be read only. title = _( "Module Editor (active library: " ) + nickname + wxT( ")" ); diff --git a/pcbnew/modview_frame.cpp b/pcbnew/modview_frame.cpp index 1bcbd5fcd5..dc24cf3208 100644 --- a/pcbnew/modview_frame.cpp +++ b/pcbnew/modview_frame.cpp @@ -309,7 +309,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateLibraryList() { m_libList->Clear(); - std::vector< wxString > nicknames = FootprintLibs()->GetLogicalLibs(); + std::vector< wxString > nicknames = Prj().PcbFootprintLibs()->GetLogicalLibs(); for( unsigned ii = 0; ii < nicknames.size(); ii++ ) m_libList->Append( nicknames[ii] ); @@ -348,7 +348,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList() FOOTPRINT_LIST fp_info_list; - fp_info_list.ReadFootprintFiles( FootprintLibs(), &m_libraryName ); + fp_info_list.ReadFootprintFiles( Prj().PcbFootprintLibs(), &m_libraryName ); if( fp_info_list.GetErrorCount() ) { @@ -509,7 +509,7 @@ void FOOTPRINT_VIEWER_FRAME::OnActivate( wxActivateEvent& event ) m_selectedFootprintName.Empty(); // Ensure we have the right library list: - std::vector< wxString > libNicknames = FootprintLibs()->GetLogicalLibs(); + std::vector< wxString > libNicknames = Prj().PcbFootprintLibs()->GetLogicalLibs(); if( libNicknames.size() == m_libList->GetCount() ) { @@ -742,13 +742,16 @@ void FOOTPRINT_VIEWER_FRAME::SelectCurrentLibrary( wxCommandEvent& event ) void FOOTPRINT_VIEWER_FRAME::SelectCurrentFootprint( wxCommandEvent& event ) { +#if 0 // cannot remember why this is here // The PCB_EDIT_FRAME may not be the FOOTPRINT_VIEW_FRAME's parent, // so use Kiway().Player() to fetch. PCB_EDIT_FRAME* parent = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, true ); + (void*) parent; +#endif wxString libname = m_libraryName + wxT( "." ) + LegacyFootprintLibPathExtension; MODULE* oldmodule = GetBoard()->m_Modules; - MODULE* module = LoadModuleFromLibrary( libname, parent->FootprintLibs(), false ); + MODULE* module = LoadModuleFromLibrary( libname, Prj().PcbFootprintLibs(), false ); if( module ) { @@ -808,7 +811,7 @@ void FOOTPRINT_VIEWER_FRAME::SelectAndViewFootprint( int aMode ) // Delete the current footprint GetBoard()->m_Modules.DeleteAll(); - MODULE* footprint = FootprintLibs()->FootprintLoad( m_libraryName, m_footprintName ); + MODULE* footprint = Prj().PcbFootprintLibs()->FootprintLoad( m_libraryName, m_footprintName ); if( footprint ) GetBoard()->Add( footprint, ADD_APPEND ); diff --git a/pcbnew/netlist.cpp b/pcbnew/netlist.cpp index 8bf18cab7b..af65d26faf 100644 --- a/pcbnew/netlist.cpp +++ b/pcbnew/netlist.cpp @@ -172,7 +172,7 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) MODULE* module = 0; MODULE* fpOnBoard; - if( aNetlist.IsEmpty() || FootprintLibs()->IsEmpty() ) + if( aNetlist.IsEmpty() || Prj().PcbFootprintLibs()->IsEmpty() ) return; aNetlist.SortByFPID(); diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index 78390e52ba..a86324ce5e 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -355,7 +356,7 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) { m_canvas->MoveCursorToCrossHair(); DrawStruct = (BOARD_ITEM*) LoadModuleFromLibrary( - wxEmptyString, FootprintLibs(), true, aDC ); + wxEmptyString, Prj().PcbFootprintLibs(), true, aDC ); SetCurItem( DrawStruct ); diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index df8df9fcc3..00452262ce 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -96,7 +96,7 @@ void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) case ID_PCB_LIB_TABLE_EDIT: { bool tableChanged = false; - int r = InvokePcbLibTableEditor( this, &GFootprintTable, FootprintLibs() ); + int r = InvokePcbLibTableEditor( this, &GFootprintTable, Prj().PcbFootprintLibs() ); if( r & 1 ) { @@ -126,7 +126,7 @@ void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) try { - FootprintLibs()->Save( tblName ); + Prj().PcbFootprintLibs()->Save( tblName ); tableChanged = true; } catch( const IO_ERROR& ioe ) @@ -259,18 +259,7 @@ bool PCB_EDIT_FRAME::LoadProjectSettings( const wxString& aProjectFileName ) SetElementVisibility( RATSNEST_VISIBLE, showRats ); #endif - wxString projectFpLibTableFileName = Prj().FootprintLibTblName(); - - FootprintLibs()->Clear(); - - try - { - FootprintLibs()->Load( projectFpLibTableFileName ); - } - catch( const IO_ERROR& ioe ) - { - DisplayError( this, ioe.errorText ); - } + Prj().ElemClear( PROJECT::ELEM_FPTBL ); // Force it to be reloaded on demand. // Load the page layout decr file, from the filename stored in // BASE_SCREEN::m_PageLayoutDescrFileName, read in config project file diff --git a/pcbnew/xchgmod.cpp b/pcbnew/xchgmod.cpp index 9f3c31f404..7fafc6a914 100644 --- a/pcbnew/xchgmod.cpp +++ b/pcbnew/xchgmod.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -492,7 +493,7 @@ void DIALOG_EXCHANGE_MODULE::BrowseAndSelectFootprint( wxCommandEvent& event ) wxString newname; newname = m_parent->SelectFootprint( m_parent, wxEmptyString, wxEmptyString, wxEmptyString, - m_parent->FootprintLibs() ); + Prj().PcbFootprintLibs() ); if( newname != wxEmptyString ) m_NewModule->SetValue( newname ); diff --git a/scripts/kicad-install.sh b/scripts/kicad-install.sh index e1826fc55a..7ddd906881 100755 --- a/scripts/kicad-install.sh +++ b/scripts/kicad-install.sh @@ -38,7 +38,7 @@ STABLE=tag:pre-kiway # currently the best mix of features and stabilty TESTING=last:1 # the most recent -# Set this to STABLE or TESTING or other know revision number: +# Set this to STABLE or TESTING or other known revision number: REVISION=$STABLE # For info on revision syntax: From f9ba502b72c8e58ac5a4301a5c9bffd08484f8c1 Mon Sep 17 00:00:00 2001 From: Lorenzo Marcantonio Date: Sat, 10 May 2014 14:48:17 +0200 Subject: [PATCH 21/68] More refactoring of the track cleanup code Algorithm is still the same... now need to know what it really meant to do --- pcbnew/clean.cpp | 422 +++++++++++++++++++++++++++-------------------- 1 file changed, 240 insertions(+), 182 deletions(-) diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index 12ca312064..6c50bd1808 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -25,7 +25,7 @@ /** * @file clean.cpp - * @brief functions to clean tracks: remove null lenght and redundant segments + * @brief functions to clean tracks: remove null length and redundant segments */ @@ -43,7 +43,7 @@ class TRACKS_CLEANER: CONNECTIONS { private: - BOARD * m_Brd; + BOARD *m_Brd; public: TRACKS_CLEANER( BOARD * aPcb ); @@ -52,8 +52,8 @@ public: * the cleanup function. * return true if some item was modified */ - bool CleanupBoard(PCB_EDIT_FRAME *aFrame, bool aCleanVias, - bool aMergeSegments, bool aDeleteUnconnected); + bool CleanupBoard( PCB_EDIT_FRAME *aFrame, bool aCleanVias, + bool aMergeSegments, bool aDeleteUnconnected); private: @@ -63,13 +63,30 @@ private: */ bool clean_vias(); + /** + * Removes all the following THT vias on the same position of the + * specified one + */ + bool remove_duplicates_of_via( const VIA *aVia ); + + /** + * Removes all the following duplicates tracks of the specified one + */ + bool remove_duplicates_of_track( const TRACK *aTrack ); + /** * Removes dangling tracks */ bool deleteUnconnectedTracks(); + /// Delete null length track segments + bool delete_null_segments(); + + /// Try to merge the segment to a following collinear one + bool merge_collinear_of_track( TRACK *aSegment ); + /** - * Merge colinear segments and remove null len segments + * Merge collinear segments and remove duplicated and null len segments */ bool clean_segments(); @@ -193,6 +210,28 @@ void TRACKS_CLEANER::buildTrackConnectionInfo() } } +bool TRACKS_CLEANER::remove_duplicates_of_via( const VIA *aVia ) +{ + bool modified = false; + + // Search and delete others vias at same location + VIA* next_via; + for( VIA* alt_via = GetFirstVia( aVia->Next() ); alt_via != NULL; + alt_via = next_via ) + { + next_via = GetFirstVia( alt_via->Next() ); + + if( (alt_via->GetViaType() == VIA_THROUGH) && + (alt_via->GetStart() == aVia->GetStart()) ) + { + // delete via + alt_via->DeleteStructure(); + modified = true; + } + } + return modified; +} + bool TRACKS_CLEANER::clean_vias() { bool modified = false; @@ -211,21 +250,7 @@ bool TRACKS_CLEANER::clean_vias() * (yet) handle high density interconnects */ if( via->GetViaType() != VIA_THROUGH ) { - // Search and delete others vias at same location - VIA* next_via; - for( VIA* alt_via = GetFirstVia( via->Next() ); alt_via != NULL; - alt_via = next_via ) - { - next_via = GetFirstVia( alt_via->Next() ); - - if( (alt_via->GetViaType() == VIA_THROUGH) && - (alt_via->GetStart() == via->GetStart()) ) - { - // delete via - alt_via->DeleteStructure(); - modified = true; - } - } + modified |= remove_duplicates_of_via( via ); /* To delete through Via on THT pads at same location * Examine the list of connected pads: @@ -360,16 +385,14 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() return modified; } - -// Delete null length segments, and intermediate points .. -bool TRACKS_CLEANER::clean_segments() +// Delete null length track segments +bool TRACKS_CLEANER::delete_null_segments() { + TRACK *nextsegment; bool modified = false; - TRACK* segment, * nextsegment; - TRACK* other; // Delete null segments - for( segment = m_Brd->m_Track; segment; segment = nextsegment ) + for( TRACK *segment = m_Brd->m_Track; segment; segment = nextsegment ) { nextsegment = segment->Next(); @@ -379,145 +402,211 @@ bool TRACKS_CLEANER::clean_segments() modified = true; } } + return modified; +} - // Delete redundant segments, i.e. segments having the same end points - // and layers - for( segment = m_Brd->m_Track; segment; segment = segment->Next() ) +bool TRACKS_CLEANER::remove_duplicates_of_track( const TRACK *aTrack ) +{ + bool modified = false; + + TRACK *nextsegment; + for( TRACK *other = aTrack->Next(); other; other = nextsegment ) { - for( other = segment->Next(); other; other = nextsegment ) + nextsegment = other->Next(); + + // New netcode, break out (can't be there any other) + if( aTrack->GetNetCode() != other->GetNetCode() ) + break; + + // Must be of the same type, on the same layer and the endpoints + // must be the same (maybe swapped) + if( (aTrack->Type() != other->Type()) && + (aTrack->GetLayer() != other->GetLayer()) ) { - nextsegment = other->Next(); - bool erase = false; - - if( segment->Type() != other->Type() ) - continue; - - if( segment->GetLayer() != other->GetLayer() ) - continue; - - if( segment->GetNetCode() != other->GetNetCode() ) - break; - - if( ( segment->GetStart() == other->GetStart() ) && - ( segment->GetEnd() == other->GetEnd() ) ) - erase = true; - - if( ( segment->GetStart() == other->GetEnd() ) && - ( segment->GetEnd() == other->GetStart() ) ) - erase = true; - - // Delete redundant point - if( erase ) + if( ((aTrack->GetStart() == other->GetStart()) && + (aTrack->GetEnd() == other->GetEnd())) || + ((aTrack->GetStart() == other->GetEnd()) && + (aTrack->GetEnd() == other->GetStart()))) { other->DeleteStructure(); modified = true; } } } + return modified; +} - // merge collinear segments: - for( segment = m_Brd->m_Track; segment; segment = nextsegment ) +bool TRACKS_CLEANER::merge_collinear_of_track( TRACK *aSegment ) +{ + bool merged_this = false; + bool flag = false; // If there are connections to this on the endpoint + + // search for a possible point connected to the START point of the current segment + TRACK *segStart = aSegment->Next(); + while( true ) { - TRACK* segStart; - TRACK* segEnd; - TRACK* segDelete; + segStart = aSegment->GetTrack( segStart, NULL, ENDPOINT_START ); - nextsegment = segment->Next(); - - if( segment->Type() != PCB_TRACE_T ) - continue; - - unsigned flag = 0; - bool no_inc = false; - - // search for a possible point connected to the START point of the current segment - for( segStart = segment->Next(); ; ) + if( segStart ) { - segStart = segment->GetTrack( segStart, NULL, ENDPOINT_START ); - - if( segStart ) - { - // the two segments must have the same width - if( segment->GetWidth() != segStart->GetWidth() ) - break; - - // it cannot be a via - if( segStart->Type() != PCB_TRACE_T ) - break; - - // We must have only one segment connected - segStart->SetState( BUSY, true ); - other = segment->GetTrack( m_Brd->m_Track, NULL, ENDPOINT_START ); - segStart->SetState( BUSY, false ); - - if( other == NULL ) - flag = 1; // OK - + // the two segments must have the same width + if( aSegment->GetWidth() != segStart->GetWidth() ) break; - } + + // it cannot be a via + if( segStart->Type() != PCB_TRACE_T ) + break; + + // We must have only one segment connected + segStart->SetState( BUSY, true ); + TRACK *other = aSegment->GetTrack( m_Brd->m_Track, NULL, ENDPOINT_START ); + segStart->SetState( BUSY, false ); + + if( other == NULL ) + flag = true; // OK + break; } + break; + } - if( flag ) // We have the starting point of the segment is connected to an other segment + if( flag ) // We have the starting point of the segment is connected to an other segment + { + TRACK *segDelete = mergeCollinearSegmentIfPossible( aSegment, segStart, ENDPOINT_START ); + + if( segDelete ) { - segDelete = mergeCollinearSegmentIfPossible( segment, segStart, ENDPOINT_START ); - - if( segDelete ) - { - no_inc = 1; - segDelete->DeleteStructure(); - modified = true; - } + segDelete->DeleteStructure(); + merged_this = true; } + } - // search for a possible point connected to the END point of the current segment: - for( segEnd = segment->Next(); ; ) + // Do the same with the other endpoint + flag = false; + + // search for a possible point connected to the END point of the current segment: + TRACK *segEnd = aSegment->Next(); + while( true ) + { + segEnd = aSegment->GetTrack( segEnd, NULL, ENDPOINT_END ); + + if( segEnd ) { - segEnd = segment->GetTrack( segEnd, NULL, ENDPOINT_END ); - - if( segEnd ) - { - if( segment->GetWidth() != segEnd->GetWidth() ) - break; - - if( segEnd->Type() != PCB_TRACE_T ) - break; - - // We must have only one segment connected - segEnd->SetState( BUSY, true ); - other = segment->GetTrack( m_Brd->m_Track, NULL, ENDPOINT_END ); - segEnd->SetState( BUSY, false ); - - if( other == NULL ) - flag |= 2; // Ok - + if( aSegment->GetWidth() != segEnd->GetWidth() ) break; - } - else - { + + if( segEnd->Type() != PCB_TRACE_T ) break; - } - } - if( flag & 2 ) // We have the ending point of the segment is connected to an other segment + // We must have only one segment connected + segEnd->SetState( BUSY, true ); + TRACK *other = aSegment->GetTrack( m_Brd->m_Track, NULL, ENDPOINT_END ); + segEnd->SetState( BUSY, false ); + + if( other == NULL ) + flag = true; // Ok + + break; + } + else { - segDelete = mergeCollinearSegmentIfPossible( segment, segEnd, ENDPOINT_END ); - - if( segDelete ) - { - no_inc = true; - segDelete->DeleteStructure(); - modified = true; - } + break; } + } - if( no_inc ) // The current segment was modified, retry to merge it - nextsegment = segment->Next(); + if( flag ) // We have the ending point of the segment is connected to an other segment + { + TRACK *segDelete = mergeCollinearSegmentIfPossible( aSegment, segEnd, ENDPOINT_END ); + + if( segDelete ) + { + segDelete->DeleteStructure(); + merged_this = true; + } + } + return merged_this; +} + +// Delete null length segments, and intermediate points .. +bool TRACKS_CLEANER::clean_segments() +{ + bool modified = false; + + // Easy things first + modified |= delete_null_segments(); + + // Delete redundant segments, i.e. segments having the same end points + // and layers + for( TRACK *segment = m_Brd->m_Track; segment; segment = segment->Next() ) + { + modified |= remove_duplicates_of_track( segment ); + } + + // merge collinear segments: + TRACK *nextsegment; + for( TRACK *segment = m_Brd->m_Track; segment; segment = nextsegment ) + { + nextsegment = segment->Next(); + + if( segment->Type() == PCB_TRACE_T ) + { + bool merged_this = merge_collinear_of_track( segment ); + modified |= merged_this; + + if( merged_this ) // The current segment was modified, retry to merge it + nextsegment = segment->Next(); + } } return modified; } +/* Utility: check for parallelism between two segments */ +static bool parallelism_test( int dx1, int dy1, int dx2, int dy2 ) +{ + // The following condition tree is ugly and repetitive, but I have + // not a better way to express clearly the trivial cases. Hope the + // compiler optimize it better than always doing the product + // below... + + // test for vertical alignment (easy to handle) + if( dx1 == 0 ) + { + if( dx2 != 0 ) + return false; + else + return true; + } + + if( dx2 == 0 ) + { + if( dx1 != 0 ) + return false; + else + return true; + } + + // test for horizontal alignment (easy to handle) + if( dy1 == 0 ) + { + if( dy2 != 0 ) + return false; + else + return true; + } + + if( dy2 == 0 ) + { + if( dy1 != 0 ) + return false; + else + return true; + } + + /* test for alignment in other cases: Do the usual cross product test + * (the same as testing the slope, but without a division) */ + return ((double)dy1 * dx2 == (double)dx1 * dy2); +} /** Function used by clean_segments. * Test if aTrackRef and aCandidate (which must have a common end) are collinear. @@ -534,63 +623,32 @@ bool TRACKS_CLEANER::clean_segments() TRACK* TRACKS_CLEANER::mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aCandidate, ENDPOINT_T aEndType ) { - if( aTrackRef->GetWidth() != aCandidate->GetWidth() ) + // First of all, they must be of the same width and must be both actual tracks + if( (aTrackRef->GetWidth() != aCandidate->GetWidth()) || + (aTrackRef->Type() != PCB_TRACE_T) || + (aCandidate->Type() != PCB_TRACE_T) ) return NULL; - bool is_colinear = false; + // Trivial case: exactly the same track + if( ( aTrackRef->GetStart() == aCandidate->GetStart() ) && + ( aTrackRef->GetEnd() == aCandidate->GetEnd() ) ) + return aCandidate; - // Trivial case: superimposed tracks ( tracks, not vias ): - if( aTrackRef->Type() == PCB_TRACE_T && aCandidate->Type() == PCB_TRACE_T ) - { - if( ( aTrackRef->GetStart() == aCandidate->GetStart() ) && - ( aTrackRef->GetEnd() == aCandidate->GetEnd() ) ) - return aCandidate; + if( ( aTrackRef->GetStart() == aCandidate->GetEnd() ) && + ( aTrackRef->GetEnd() == aCandidate->GetStart() ) ) + return aCandidate; - if( ( aTrackRef->GetStart() == aCandidate->GetEnd() ) && - ( aTrackRef->GetEnd() == aCandidate->GetStart() ) ) - return aCandidate; - } - - int refdx = aTrackRef->GetEnd().x - aTrackRef->GetStart().x; - int refdy = aTrackRef->GetEnd().y - aTrackRef->GetStart().y; - - int segmdx = aCandidate->GetEnd().x - aCandidate->GetStart().x; - int segmdy = aCandidate->GetEnd().y - aCandidate->GetStart().y; - - // test for vertical alignment (easy to handle) - if( refdx == 0 ) - { - if( segmdx != 0 ) - return NULL; - else - is_colinear = true; - } - - // test for horizontal alignment (easy to handle) - if( refdy == 0 ) - { - if( segmdy != 0 ) - return NULL; - else - is_colinear = true; - } - - /* test if alignment in other cases - * We must have refdy/refdx == segmdy/segmdx, (i.e. same slope) - * or refdy * segmdx == segmdy * refdx - */ - if( is_colinear == false ) - { - if( ( double)refdy * segmdx != (double)refdx * segmdy ) - return NULL; - - is_colinear = true; - } + // Weed out non-parallel tracks + if ( !parallelism_test( aTrackRef->GetEnd().x - aTrackRef->GetStart().x, + aTrackRef->GetEnd().y - aTrackRef->GetStart().y, + aCandidate->GetEnd().x - aCandidate->GetStart().x, + aCandidate->GetEnd().y - aCandidate->GetStart().y ) ) + return NULL; /* Here we have 2 aligned segments: * We must change the pt_ref common point only if not on a pad * (this function) is called when there is only 2 connected segments, - *and if this point is not on a pad, it can be removed and the 2 segments will be merged + * and if this point is not on a pad, it can be removed and the 2 segments will be merged */ if( aEndType == ENDPOINT_START ) { From 1cbf03cb606d67a58c401a5b1fa3d320ba41af9d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:50 +0200 Subject: [PATCH 22/68] Ratsnest was not refreshed on board reload - fixed. --- pcbnew/pcbframe.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 3ed5d2583a..ada7b0d8c7 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -544,6 +544,7 @@ void PCB_EDIT_FRAME::ViewReloadBoard( const BOARD* aBoard ) const view->Add( worksheet ); view->Add( aBoard->GetRatsnestViewItem() ); + aBoard->GetRatsnest()->Recalculate(); // Limit panning to the size of worksheet frame GetGalCanvas()->GetViewControls()->SetPanBoundary( aBoard->GetWorksheetViewItem()->ViewBBox() ); @@ -673,9 +674,6 @@ void PCB_EDIT_FRAME::UseGalCanvas( bool aEnable ) { ViewReloadBoard( m_Pcb ); - // Update potential changes in the ratsnest - m_Pcb->GetRatsnest()->Recalculate(); - m_toolManager.SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), GetGalCanvas()->GetViewControls(), this ); m_toolManager.ResetTools( TOOL_BASE::GAL_SWITCH ); From 8bb5eaa434875c0faf0abd58d5b1c666098618cb Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:50 +0200 Subject: [PATCH 23/68] Better way of adding CONTEXT_MENU entries. --- common/tool/context_menu.cpp | 47 ++++++++++++++---------------------- include/tool/context_menu.h | 8 ------ 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index 6dfab27e58..d45bbb3602 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -101,17 +101,28 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction ) { /// ID numbers for tool actions need to have a value higher than m_actionId int id = m_actionId + aAction.GetId(); - wxString menuEntry; + + wxMenuItem* item = new wxMenuItem( &m_menu, id, + wxString( aAction.GetMenuItem().c_str(), wxConvUTF8 ), + wxString( aAction.GetDescription().c_str(), wxConvUTF8 ), wxITEM_NORMAL ); if( aAction.HasHotKey() ) - menuEntry = wxString( ( aAction.GetMenuItem() + '\t' + - getHotKeyDescription( aAction ) ).c_str(), wxConvUTF8 ); - else - menuEntry = wxString( aAction.GetMenuItem().c_str(), wxConvUTF8 ); + { + int key = aAction.GetHotKey() & ~MD_MODIFIER_MASK; + int mod = aAction.GetHotKey() & MD_MODIFIER_MASK; + wxAcceleratorEntryFlags flags = wxACCEL_NORMAL; - m_menu.Append( new wxMenuItem( &m_menu, id, menuEntry, - wxString( aAction.GetDescription().c_str(), wxConvUTF8 ), wxITEM_NORMAL ) ); + switch( mod ) + { + case MD_ALT: flags = wxACCEL_ALT; break; + case MD_CTRL: flags = wxACCEL_CTRL; break; + case MD_SHIFT: flags = wxACCEL_SHIFT; break; + } + item->SetAccel( new wxAcceleratorEntry( flags, key, id, item ) ); + } + + m_menu.Append( item ); m_toolActions[id] = &aAction; } @@ -128,28 +139,6 @@ void CONTEXT_MENU::Clear() } -std::string CONTEXT_MENU::getHotKeyDescription( const TOOL_ACTION& aAction ) const -{ - int hotkey = aAction.GetHotKey(); - - std::string description = ""; - - if( hotkey & MD_ALT ) - description += "ALT+"; - - if( hotkey & MD_CTRL ) - description += "CTRL+"; - - if( hotkey & MD_SHIFT ) - description += "SHIFT+"; - - // TODO dispatch keys such as Fx, TAB, PG_UP/DN, HOME, END, etc. - description += char( hotkey & ~MD_MODIFIER_MASK ); - - return description; -} - - void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent ) { TOOL_EVENT evt; diff --git a/include/tool/context_menu.h b/include/tool/context_menu.h index df6f7cb0b7..e181b576bb 100644 --- a/include/tool/context_menu.h +++ b/include/tool/context_menu.h @@ -128,14 +128,6 @@ private: m_tool = aTool; } - /** - * Function getHotKeyDescription() - * Returns a hot key in the string format accepted by wxMenu. - * @param aAction is the action with hot key to be translated.. - * @return Hot key in the string format compatible with wxMenu. - */ - std::string getHotKeyDescription( const TOOL_ACTION& aAction ) const; - ///> Flag indicating that the menu title was set up. bool m_titleSet; From 7fd9fc4911c08986e99d2e3171cc5afc2e9069c8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 24/68] Ratsnest lines are highlighted together with all items in the same net. --- pcbnew/ratsnest_viewitem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pcbnew/ratsnest_viewitem.cpp b/pcbnew/ratsnest_viewitem.cpp index ffe88c3c7f..1f40f8ed26 100644 --- a/pcbnew/ratsnest_viewitem.cpp +++ b/pcbnew/ratsnest_viewitem.cpp @@ -60,6 +60,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const aGal->SetLineWidth( 1.0 ); RENDER_SETTINGS* rs = m_view->GetPainter()->GetSettings(); COLOR4D color = rs->GetColor( NULL, ITEM_GAL_LAYER( RATSNEST_VISIBLE ) ); + int highlightedNet = rs->GetHighlightNetCode(); for( int i = 1; i < m_data->GetNetCount(); ++i ) { @@ -89,7 +90,8 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const } // Draw the "static" ratsnest - aGal->SetStrokeColor( color ); // using the default ratsnest color + if( i != highlightedNet ) + aGal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted const std::vector* edges = net.GetUnconnected(); if( edges == NULL ) From 6b222d19d5f5872f1d2e2f2d22aca5bfacd8a286 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 25/68] Added preference for selecting tracks/vias/graphics if there is a module present in the selection point. --- pcbnew/tools/selection_tool.cpp | 41 +++++++++++++++++++++++++++++++++ pcbnew/tools/selection_tool.h | 10 ++++++++ 2 files changed, 51 insertions(+) diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 2511cb687e..02068b72c8 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -227,6 +227,7 @@ bool SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere, bool aAllowDisambigua BOARD_ITEM* item; GENERAL_COLLECTORS_GUIDE guide = getEditFrame()->GetCollectorsGuide(); GENERAL_COLLECTOR collector; + const KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, PCB_LINE_T, EOT }; // preferred types collector.Collect( pcb, GENERAL_COLLECTOR::AllBoardItems, wxPoint( aWhere.x, aWhere.y ), guide ); @@ -252,6 +253,14 @@ bool SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere, bool aAllowDisambigua collector.Remove( i ); } + // Check if among the selection candidates there is only one instance of preferred type + if( item = prefer( collector, types ) ) + { + toggleSelection( item ); + + return true; + } + // Let's see if there is still disambiguation in selection.. if( collector.GetCount() == 1 ) { @@ -681,6 +690,38 @@ void SELECTION_TOOL::highlightNet( const VECTOR2I& aPoint ) } +BOARD_ITEM* SELECTION_TOOL::prefer( GENERAL_COLLECTOR& aCollector, const KICAD_T aTypes[] ) const +{ + BOARD_ITEM* preferred = NULL; + + int typesNr = 0; + while( aTypes[typesNr++] != EOT ); // count number of types, excluding the sentinel (EOT) + + for( int i = 0; i < aCollector.GetCount(); ++i ) + { + KICAD_T type = aCollector[i]->Type(); + + for( int j = 0; j < typesNr - 1; ++j ) // Check if the item's type is in our list + { + if( aTypes[j] == type ) + { + if( preferred == NULL ) + { + preferred = aCollector[i]; // save the first matching item + break; + } + else + { + return NULL; // there is more than one preferred item, so there is no clear choice + } + } + } + } + + return preferred; +} + + void SELECTION_TOOL::SELECTION::clear() { items.ClearItemsList(); diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index 609fcafda5..0850286d24 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -229,6 +229,16 @@ private: */ void highlightNet( const VECTOR2I& aPoint ); + /** + * Function prefer() + * Checks if collector's list contains only single entry of asked types. If so, it returns it. + * @param aCollector is the collector that has a list of items to be queried. + * @param aTypes is the list of searched/preferred types. + * @return Pointer to the preferred item, if there is only one entry of given type or NULL + * if there are more entries or no entries at all. + */ + BOARD_ITEM* prefer( GENERAL_COLLECTOR& aCollector, const KICAD_T aTypes[] ) const; + /// Visual representation of selection box SELECTION_AREA* m_selArea; From 50193f175179d33afb90d7dba68afd901f37a5a4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 26/68] Resolved HOME hot key conflict between menu entry (Zoom Page) and event assigned to the hot key in the ACTION_MANAGER. Conflicts: pcbnew/menubar_pcbframe.cpp --- common/tool/tool_manager.cpp | 3 +-- pcbnew/menubar_pcbframe.cpp | 2 +- pcbnew/tools/selection_tool.cpp | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index e83b8fc6d2..0f0ee83533 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -513,8 +513,7 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) if( m_view->IsDirty() ) { PCB_EDIT_FRAME* f = static_cast( GetEditFrame() ); - if( f->IsGalCanvasActive() ) - f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER. + f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER. } return false; diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index 11aa831c27..b95b8529fe 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -315,7 +315,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() AddMenuItem( viewMenu, ID_ZOOM_OUT, text, HELP_ZOOM_OUT, KiBitmap( zoom_out_xpm ) ); text = AddHotkeyName( _( "&Fit on Screen" ), g_Pcbnew_Editor_Hokeys_Descr, - HK_ZOOM_AUTO ); + HK_ZOOM_AUTO, IS_ACCELERATOR ); AddMenuItem( viewMenu, ID_ZOOM_PAGE, text, HELP_ZOOM_FIT, KiBitmap( zoom_fit_in_page_xpm ) ); diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 02068b72c8..b0a333285c 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -254,7 +254,8 @@ bool SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere, bool aAllowDisambigua } // Check if among the selection candidates there is only one instance of preferred type - if( item = prefer( collector, types ) ) + item = prefer( collector, types ); + if( item ) { toggleSelection( item ); From 2f5103bc67ab13cb8f438a047e8f725c37ef528c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 27/68] Fixed jumpy zoom when hotkeys and scroll wheel were used alternatively. --- common/view/wx_view_controls.cpp | 4 ++-- pcbnew/tools/pcbnew_control.cpp | 30 ++++++++++-------------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index 22eb3ee47e..9f51a0f624 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -160,12 +160,12 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent ) // Set scaling speed depending on scroll wheel event interval if( timeDiff < 500 && timeDiff > 0 ) { - zoomScale = ( aEvent.GetWheelRotation() > 0.0 ) ? 2.05 - timeDiff / 500 : + zoomScale = ( aEvent.GetWheelRotation() > 0 ) ? 2.05 - timeDiff / 500 : 1.0 / ( 2.05 - timeDiff / 500 ); } else { - zoomScale = ( aEvent.GetWheelRotation() > 0.0 ) ? 1.05 : 0.95; + zoomScale = ( aEvent.GetWheelRotation() > 0 ) ? 1.05 : 0.95; } VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) ); diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index f01203178f..ec8b086bab 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -61,17 +61,14 @@ bool PCBNEW_CONTROL::Init() int PCBNEW_CONTROL::ZoomInOut( TOOL_EVENT& aEvent ) { KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView(); - KIGFX::GAL* gal = m_frame->GetGalCanvas()->GetGAL(); + double zoomScale = 1.0; if( aEvent.IsAction( &COMMON_ACTIONS::zoomIn ) ) - m_frame->SetPrevZoom(); + zoomScale = 1.3; else if( aEvent.IsAction( &COMMON_ACTIONS::zoomOut ) ) - m_frame->SetNextZoom(); + zoomScale = 0.7; - double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); - double zoom = 1.0 / ( zoomFactor * m_frame->GetZoom() ); - - view->SetScale( zoom, getViewControls()->GetCursorPosition() ); + view->SetScale( view->GetScale() * zoomScale, getViewControls()->GetCursorPosition() ); setTransitions(); return 0; @@ -81,17 +78,14 @@ int PCBNEW_CONTROL::ZoomInOut( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::ZoomInOutCenter( TOOL_EVENT& aEvent ) { KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView(); - KIGFX::GAL* gal = m_frame->GetGalCanvas()->GetGAL(); + double zoomScale = 1.0; - if( aEvent.IsAction( &COMMON_ACTIONS::zoomInCenter ) ) - m_frame->SetPrevZoom(); - else if( aEvent.IsAction( &COMMON_ACTIONS::zoomOutCenter ) ) - m_frame->SetNextZoom(); + if( aEvent.IsAction( &COMMON_ACTIONS::zoomIn ) ) + zoomScale = 1.3; + else if( aEvent.IsAction( &COMMON_ACTIONS::zoomOut ) ) + zoomScale = 0.7; - double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); - double zoom = 1.0 / ( zoomFactor * m_frame->GetZoom() ); - - view->SetScale( zoom ); + view->SetScale( view->GetScale() * zoomScale ); setTransitions(); return 0; @@ -119,10 +113,6 @@ int PCBNEW_CONTROL::ZoomFitScreen( TOOL_EVENT& aEvent ) double iuPerY = screenSize.y ? boardBBox.GetHeight() / screenSize.y : 1.0; double bestZoom = std::max( iuPerX, iuPerY ); - // This is needed to avoid "jumpy" zooms if first hot key was used and then mouse scroll - // (or other way round). - m_frame->GetScreen()->SetZoom( bestZoom ); - double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); double zoom = 1.0 / ( zoomFactor * bestZoom ); From 3eaef97a7d9f83ccdad6b4025b8bebefab8b3d75 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 28/68] Added WX_UNIT_TEXT - wxWidget control for inputing sizes using different units (mm, inch, internal units). --- common/CMakeLists.txt | 1 + common/wxunittext.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++ include/wxunittext.h | 139 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+) create mode 100644 common/wxunittext.cpp create mode 100644 include/wxunittext.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 07da514a8e..b30ac34312 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -202,6 +202,7 @@ set( COMMON_SRCS wildcards_and_files_ext.cpp worksheet.cpp wxwineda.cpp + wxunittext.cpp xnode.cpp zoom.cpp ) diff --git a/common/wxunittext.cpp b/common/wxunittext.cpp new file mode 100644 index 0000000000..5af3c721ea --- /dev/null +++ b/common/wxunittext.cpp @@ -0,0 +1,146 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * Author: Maciej Suminski + * + * 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 + */ + +#include "wxunittext.h" +#include +#include +#include +#include +#include + +WX_UNIT_TEXT::WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel, double aValue, double aStep ) : + wxPanel( aParent, wxID_ANY ), + m_step( aStep ) +{ + // Use the currently selected units + m_units = g_UserUnit; + + wxBoxSizer* sizer; + sizer = new wxBoxSizer( wxHORIZONTAL ); + + // Helper label + m_inputLabel = new wxStaticText( this, wxID_ANY, aLabel, + wxDefaultPosition, wxDefaultSize, 0 ); + wxSize size = m_inputLabel->GetMinSize(); + size.SetWidth( 150 ); + m_inputLabel->SetMinSize( size ); + sizer->Add( m_inputLabel, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 ); + + wxFloatingPointValidator validator( 4, NULL, wxNUM_VAL_NO_TRAILING_ZEROES ); + validator.SetRange( 0.0, std::numeric_limits::max() ); + + // Main input control + m_inputValue = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, + wxTE_PROCESS_ENTER ); + m_inputValue->SetValidator( validator ); + SetValue( aValue ); + sizer->Add( m_inputValue, 0, wxALIGN_CENTER_VERTICAL | wxALL ); + + // Spin buttons for modifying values using the mouse + m_spinButton = new wxSpinButton( this, wxID_ANY ); + m_spinButton->SetRange( std::numeric_limits::min(), std::numeric_limits::max() ); + m_spinButton->SetCanFocus( false ); + sizer->Add( m_spinButton, 0, wxALIGN_CENTER_VERTICAL | wxALL ); + + sizer->AddSpacer( 5 ); + + // Create units label + m_unitLabel = new wxStaticText( this, wxID_ANY, GetUnitsLabel( g_UserUnit ), + wxDefaultPosition, wxDefaultSize, 0 ); + sizer->Add( m_unitLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL ); + + SetSizer( sizer ); + Layout(); + + Connect( wxEVT_SPIN_UP, wxSpinEventHandler( WX_UNIT_TEXT::onSpinUpEvent ), NULL, this ); + Connect( wxEVT_SPIN_DOWN, wxSpinEventHandler( WX_UNIT_TEXT::onSpinDownEvent ), NULL, this ); + Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( WX_UNIT_TEXT::onEnter ), NULL, this ); +} + + +WX_UNIT_TEXT::~WX_UNIT_TEXT() +{ +} + + +void WX_UNIT_TEXT::SetUnits( EDA_UNITS_T aUnits, bool aConvert ) +{ + assert( !aConvert ); // TODO conversion does not work yet + + m_unitLabel->SetLabel( GetUnitsLabel( g_UserUnit ) ); +} + + +void WX_UNIT_TEXT::SetValue( double aValue ) +{ + assert( aValue >= 0.0 ); + + if( aValue >= 0.0 ) + { + m_inputValue->SetValue( Double2Str( aValue ) ); + m_inputValue->MarkDirty(); + } +} + + +double WX_UNIT_TEXT::GetValue( EDA_UNITS_T aUnit ) const +{ + assert( false ); // TODO + + return 0.0; +} + + +double WX_UNIT_TEXT::GetValue() const +{ + wxString text = m_inputValue->GetValue(); + double value; + + if( !text.ToDouble( &value ) ) + value = 0.0; + + return value; +} + + +void WX_UNIT_TEXT::onSpinUpEvent( wxSpinEvent& aEvent ) +{ + SetValue( GetValue() + m_step ); +} + + +void WX_UNIT_TEXT::onSpinDownEvent( wxSpinEvent& aEvent ) +{ + double newValue = GetValue() - m_step; + + if( newValue >= 0.0 ) + SetValue( newValue ); +} + + +void WX_UNIT_TEXT::onEnter( wxCommandEvent& aEvent ) +{ + // Move focus to the next widget + Navigate(); +} diff --git a/include/wxunittext.h b/include/wxunittext.h new file mode 100644 index 0000000000..977002e59a --- /dev/null +++ b/include/wxunittext.h @@ -0,0 +1,139 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * Author: Maciej Suminski + * + * 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 + */ + +#ifndef WXUNITTEXT_H_ +#define WXUNITTEXT_H_ + +#include +#include + +class wxTextCtrl; +class wxSpinButton; +class wxStaticText; + +class WX_UNIT_TEXT : public wxPanel +{ +public: + /** + * Constructor. + * @param aParent is the parent window. + * @param aLabel is the label displayed next to the text input control. + * @param aValue is the initial value for the control. + * @param aStep is the step size when using spin buttons. + */ + WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel = wxString( "Size:" ), + double aValue = 0.0, double aStep = 0.1 ); + + virtual ~WX_UNIT_TEXT(); + + /** + * Function SetUnits + * Changes the units used by the control. + * @param aUnits is the new unit to be used. + * @param aConvert decides if the current value should be converted to the value in new units + * or should it stay the same. + */ + void SetUnits( EDA_UNITS_T aUnits, bool aConvert = false ); + + /** + * Function SetValue + * Sets new value for the control. + * @param aValue is the new value. + */ + virtual void SetValue( double aValue ); + + /** + * Function GetValue + * Returns the current value using specified units (if currently used units are different, then + * they are converted first). + * @param aUnits is the wanted unit. + */ + virtual double GetValue( EDA_UNITS_T aUnits ) const; + + /** + * Function GetValue + * Returns the current value in currently used units. + */ + virtual double GetValue() const; + + /** + * Function GetUnits + * Returns currently used units. + */ + EDA_UNITS_T GetUnits() const + { + return m_units; + } + + /** + * Function SetStep + * Sets the difference introduced by a single spin button click. + * @param aStep is new step size. + */ + void SetStep( double aStep ) + { + assert( aStep > 0.0 ); + + m_step = aStep; + } + + /** + * Function GetStep + * Returns the difference introduced by a single spin button click. + */ + double GetStep() const + { + return m_step; + } + +protected: + ///> Spin up button click event handler. + void onSpinUpEvent( wxSpinEvent& aEvent ); + + ///> Spin down button click event handler. + void onSpinDownEvent( wxSpinEvent& aEvent ); + + ///> On Enter press event handler. + void onEnter( wxCommandEvent& aEvent ); + + ///> Label for the input (e.g. "Size:") + wxStaticText* m_inputLabel; + + ///> Text input control. + wxTextCtrl* m_inputValue; + + ///> Spin buttons for changing the value using mouse. + wxSpinButton* m_spinButton; + + ///> Label showing currently used units. + wxStaticText* m_unitLabel; + + ///> Currently used units. + EDA_UNITS_T m_units; + + ///> Step size (added/subtracted difference if spin buttons are used). + double m_step; +}; + +#endif /* WXUNITTEXT_H_ */ From 761375ddef2e3e75fa203bc360cda135d3a5bcaf Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 29/68] More compatibility fixes. --- common/draw_panel_gal.cpp | 18 +++++-- common/tool/context_menu.cpp | 2 +- common/wxunittext.cpp | 95 +++++++++++++++++++++++++--------- include/class_draw_panel_gal.h | 9 +++- include/wxunittext.h | 14 ++--- pcbnew/basepcbframe.cpp | 3 ++ pcbnew/pcbframe.cpp | 5 +- 7 files changed, 107 insertions(+), 39 deletions(-) diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index 0ec6a1130b..93ad978969 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -67,7 +67,6 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin m_viewControls = new KIGFX::WX_VIEW_CONTROLS( m_view, this ); - Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this ); Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this ); /* Generic events for the Tool Dispatcher */ @@ -184,10 +183,21 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect ) } +void EDA_DRAW_PANEL_GAL::StartDrawing() +{ + m_pendingRefresh = false; + Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this ); + + wxPaintEvent redrawEvent; + wxPostEvent( this, redrawEvent ); +} + + void EDA_DRAW_PANEL_GAL::StopDrawing() { - Disconnect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this ); + m_pendingRefresh = true; m_refreshTimer.Stop(); + Disconnect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this ); } @@ -198,8 +208,7 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) return; // Prevent refreshing canvas during backend switch - m_pendingRefresh = true; - m_refreshTimer.Stop(); + StopDrawing(); delete m_gal; @@ -228,7 +237,6 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) m_view->SetGAL( m_gal ); m_currentGal = aGalType; - m_pendingRefresh = false; } diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index d45bbb3602..580e876a8b 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -110,7 +110,7 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction ) { int key = aAction.GetHotKey() & ~MD_MODIFIER_MASK; int mod = aAction.GetHotKey() & MD_MODIFIER_MASK; - wxAcceleratorEntryFlags flags = wxACCEL_NORMAL; + int flags = wxACCEL_NORMAL; switch( mod ) { diff --git a/common/wxunittext.cpp b/common/wxunittext.cpp index 5af3c721ea..f33be9ec5a 100644 --- a/common/wxunittext.cpp +++ b/common/wxunittext.cpp @@ -26,8 +26,12 @@ #include #include #include -#include +#include #include +#if wxCHECK_VERSION( 2, 9, 0 ) +#include +#endif +#include WX_UNIT_TEXT::WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel, double aValue, double aStep ) : wxPanel( aParent, wxID_ANY ), @@ -47,22 +51,29 @@ WX_UNIT_TEXT::WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel, double aV m_inputLabel->SetMinSize( size ); sizer->Add( m_inputLabel, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 ); - wxFloatingPointValidator validator( 4, NULL, wxNUM_VAL_NO_TRAILING_ZEROES ); - validator.SetRange( 0.0, std::numeric_limits::max() ); - // Main input control m_inputValue = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - m_inputValue->SetValidator( validator ); + SetValue( aValue ); sizer->Add( m_inputValue, 0, wxALIGN_CENTER_VERTICAL | wxALL ); +#if wxCHECK_VERSION( 2, 9, 0 ) // Sorry guys, I am tired of dealing with 2.8 compatibility + wxFloatingPointValidator validator( 4, NULL, wxNUM_VAL_NO_TRAILING_ZEROES ); + validator.SetRange( 0.0, std::numeric_limits::max() ); + m_inputValue->SetValidator( validator ); + // Spin buttons for modifying values using the mouse m_spinButton = new wxSpinButton( this, wxID_ANY ); m_spinButton->SetRange( std::numeric_limits::min(), std::numeric_limits::max() ); + m_spinButton->SetCanFocus( false ); sizer->Add( m_spinButton, 0, wxALIGN_CENTER_VERTICAL | wxALL ); + Connect( wxEVT_SPIN_UP, wxSpinEventHandler( WX_UNIT_TEXT::onSpinUpEvent ), NULL, this ); + Connect( wxEVT_SPIN_DOWN, wxSpinEventHandler( WX_UNIT_TEXT::onSpinDownEvent ), NULL, this ); +#endif + sizer->AddSpacer( 5 ); // Create units label @@ -72,10 +83,6 @@ WX_UNIT_TEXT::WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel, double aV SetSizer( sizer ); Layout(); - - Connect( wxEVT_SPIN_UP, wxSpinEventHandler( WX_UNIT_TEXT::onSpinUpEvent ), NULL, this ); - Connect( wxEVT_SPIN_DOWN, wxSpinEventHandler( WX_UNIT_TEXT::onSpinDownEvent ), NULL, this ); - Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( WX_UNIT_TEXT::onEnter ), NULL, this ); } @@ -98,49 +105,87 @@ void WX_UNIT_TEXT::SetValue( double aValue ) if( aValue >= 0.0 ) { - m_inputValue->SetValue( Double2Str( aValue ) ); + m_inputValue->SetValue( wxString( Double2Str( aValue ).c_str(), wxConvUTF8 ) ); m_inputValue->MarkDirty(); } } -double WX_UNIT_TEXT::GetValue( EDA_UNITS_T aUnit ) const +/*boost::optional WX_UNIT_TEXT::GetValue( EDA_UNITS_T aUnit ) const { - assert( false ); // TODO + if( aUnit == m_units ) + return GetValue(); // no conversion needed + + switch( m_units ) + { + case MILLIMETRES: + switch( aUnit ) + { + case INCHES: + iu = Mils2iu( GetValue() * 1000.0 ); + break; + + case UNSCALED_UNITS: + iu = GetValue(); + break; + } + break; + + case INCHES: + switch( aUnit ) + { + case MILLIMETRES: + return Mils2mm( GetValue() * 1000.0 ); + break; + + case UNSCALED_UNITS: + return Mils2iu( GetValue() * 1000.0 ); + break; + } + break; + + case UNSCALED_UNITS: + switch( aUnit ) + { + case MILLIMETRES: + return Iu2Mils( GetValue() ) / 1000.0; + break; + +// case INCHES: +// return +// break; + } + break; + } + + assert( false ); // seems that there are some conversions missing return 0.0; -} +}*/ -double WX_UNIT_TEXT::GetValue() const +boost::optional WX_UNIT_TEXT::GetValue() const { wxString text = m_inputValue->GetValue(); double value; if( !text.ToDouble( &value ) ) - value = 0.0; + return boost::optional(); - return value; + return boost::optional( value ); } void WX_UNIT_TEXT::onSpinUpEvent( wxSpinEvent& aEvent ) { - SetValue( GetValue() + m_step ); + SetValue( *GetValue() + m_step ); } void WX_UNIT_TEXT::onSpinDownEvent( wxSpinEvent& aEvent ) { - double newValue = GetValue() - m_step; + double newValue = *GetValue() - m_step; if( newValue >= 0.0 ) SetValue( newValue ); } - - -void WX_UNIT_TEXT::onEnter( wxCommandEvent& aEvent ) -{ - // Move focus to the next widget - Navigate(); -} diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h index 4ec05ed65d..766cb5d630 100644 --- a/include/class_draw_panel_gal.h +++ b/include/class_draw_panel_gal.h @@ -111,9 +111,16 @@ public: m_eventDispatcher = aEventDispatcher; } + /** + * Function StartDrawing() + * Begins drawing if it was stopped previously. + */ + void StartDrawing(); + /** * Function StopDrawing() - * Prevents the GAL canvas from further drawing till it is recreated. + * Prevents the GAL canvas from further drawing till it is recreated + * or StartDrawing() is called. */ void StopDrawing(); diff --git a/include/wxunittext.h b/include/wxunittext.h index 977002e59a..92791f09ff 100644 --- a/include/wxunittext.h +++ b/include/wxunittext.h @@ -28,6 +28,11 @@ #include #include +namespace boost +{ + template + class optional; +} class wxTextCtrl; class wxSpinButton; class wxStaticText; @@ -42,7 +47,7 @@ public: * @param aValue is the initial value for the control. * @param aStep is the step size when using spin buttons. */ - WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel = wxString( "Size:" ), + WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel = _( "Size:" ), double aValue = 0.0, double aStep = 0.1 ); virtual ~WX_UNIT_TEXT(); @@ -69,13 +74,13 @@ public: * they are converted first). * @param aUnits is the wanted unit. */ - virtual double GetValue( EDA_UNITS_T aUnits ) const; + //virtual double GetValue( EDA_UNITS_T aUnits ) const; /** * Function GetValue * Returns the current value in currently used units. */ - virtual double GetValue() const; + virtual boost::optional GetValue() const; /** * Function GetUnits @@ -114,9 +119,6 @@ protected: ///> Spin down button click event handler. void onSpinDownEvent( wxSpinEvent& aEvent ); - ///> On Enter press event handler. - void onEnter( wxCommandEvent& aEvent ); - ///> Label for the input (e.g. "Size:") wxStaticText* m_inputLabel; diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 3bbade6770..00fcf088c0 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -159,6 +159,9 @@ PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame this, -1, wxPoint( 0, 0 ), m_FrameSize, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ) ); + // GAL should not be active yet + GetGalCanvas()->StopDrawing(); + // Hide by default, it has to be explicitly shown GetGalCanvas()->Hide(); diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index ada7b0d8c7..9f66d54d21 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -673,10 +673,13 @@ void PCB_EDIT_FRAME::UseGalCanvas( bool aEnable ) if( aEnable ) { ViewReloadBoard( m_Pcb ); + GetGalCanvas()->GetView()->RecacheAllItems(); m_toolManager.SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), GetGalCanvas()->GetViewControls(), this ); - m_toolManager.ResetTools( TOOL_BASE::GAL_SWITCH ); + m_toolManager.ResetTools( TOOL_BASE::MODEL_RELOAD ); + + GetGalCanvas()->StartDrawing(); } } From 929008c6c33133198544c7f9a1a6b168cf84aa5f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 30/68] SELECTION_TOOL updates dragging offset after rotating/flipping. Cursor position is saved as a field in order to avoid drifting of items while they are being dragged and rotated/flipped. --- pcbnew/tools/edit_tool.cpp | 28 ++++++++++++++++------------ pcbnew/tools/edit_tool.h | 6 ++++++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 8dac46385c..36814e541d 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -92,9 +92,6 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) // By default, modified items need to update their geometry m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; - // Offset from the dragged item's center (anchor) - wxPoint offset; - KIGFX::VIEW_CONTROLS* controls = getViewControls(); PCB_EDIT_FRAME* editFrame = static_cast( m_toolMgr->GetEditFrame() ); controls->ShowCursor( true ); @@ -141,18 +138,18 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { - VECTOR2I cursor( controls->GetCursorPosition() ); + m_cursor = controls->GetCursorPosition(); if( m_dragging ) { - wxPoint movement = wxPoint( cursor.x, cursor.y ) - + wxPoint movement = wxPoint( m_cursor.x, m_cursor.y ) - static_cast( selection.items.GetPickedItem( 0 ) )->GetPosition(); // Drag items to the current cursor position for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) { BOARD_ITEM* item = static_cast( selection.items.GetPickedItem( i ) ); - item->Move( movement + offset ); + item->Move( movement + m_offset ); } updateRatsnest( true ); @@ -163,8 +160,9 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); - offset = static_cast( selection.items.GetPickedItem( 0 ) )->GetPosition() - - wxPoint( cursor.x, cursor.y ); + // Update dragging offset (distance between cursor and the first dragged item) + m_offset = static_cast( selection.items.GetPickedItem( 0 ) )->GetPosition() - + wxPoint( m_cursor.x, m_cursor.y ); m_dragging = true; } @@ -227,14 +225,13 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent ) { // Display properties dialog BOARD_ITEM* item = static_cast( selection.items.GetPickedItem( 0 ) ); - VECTOR2I cursor = getViewControls()->GetCursorPosition(); // Check if user wants to edit pad or module properties if( item->Type() == PCB_MODULE_T ) { for( D_PAD* pad = static_cast( item )->Pads(); pad; pad = pad->Next() ) { - if( pad->ViewBBox().Contains( cursor ) ) + if( pad->ViewBBox().Contains( m_cursor ) ) { // Turns out that user wants to edit a pad properties item = pad; @@ -298,6 +295,10 @@ int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent ) updateRatsnest( m_dragging ); + // Update dragging offset (distance between cursor and the first dragged item) + m_offset = static_cast( selection.items.GetPickedItem( 0 ) )->GetPosition() - + rotatePoint; + if( m_dragging ) selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); else @@ -348,6 +349,10 @@ int EDIT_TOOL::Flip( TOOL_EVENT& aEvent ) updateRatsnest( m_dragging ); + // Update dragging offset (distance between cursor and the first dragged item) + m_offset = static_cast( selection.items.GetPickedItem( 0 ) )->GetPosition() - + flipPoint; + if( m_dragging ) selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); else @@ -487,8 +492,7 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION_TOOL::SELECTION& aSelec } else { - VECTOR2I cursor = getViewControls()->GetCursorPosition(); - return wxPoint( cursor.x, cursor.y ); + return wxPoint( m_cursor.x, m_cursor.y ); } } diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index b5f6f1fc0d..d3792766ff 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -98,6 +98,12 @@ private: ///> Flag determining if anything is being dragged right now bool m_dragging; + ///> Offset from the dragged item's center (anchor) + wxPoint m_offset; + + ///> Last cursor position + VECTOR2I m_cursor; + ///> Removes and frees a single BOARD_ITEM. void remove( BOARD_ITEM* aItem ); From a0801e2d8e580c369f085f9f65af5e068f893a07 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 31/68] Pad properties are back. --- pcbnew/tools/edit_tool.cpp | 2 +- pcbnew/tools/edit_tool.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 36814e541d..5f3906e67b 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -231,7 +231,7 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent ) { for( D_PAD* pad = static_cast( item )->Pads(); pad; pad = pad->Next() ) { - if( pad->ViewBBox().Contains( m_cursor ) ) + if( pad->ViewBBox().Contains( getViewControls()->GetCursorPosition() ) ) { // Turns out that user wants to edit a pad properties item = pad; diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index d3792766ff..b23f076e96 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -101,7 +101,8 @@ private: ///> Offset from the dragged item's center (anchor) wxPoint m_offset; - ///> Last cursor position + ///> Last cursor position (needed for getModificationPoint() to avoid changes + ///> of edit reference point). VECTOR2I m_cursor; ///> Removes and frees a single BOARD_ITEM. From 9325a9e74d8a0cc36ca289f965a61247e73afb00 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 32/68] Fixed rotation/flip point. --- pcbnew/tools/edit_tool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 5f3906e67b..b647b2bbf2 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -488,7 +488,7 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION_TOOL::SELECTION& aSelec { if( aSelection.Size() == 1 ) { - return static_cast( aSelection.items.GetPickedItem( 0 ) )->GetPosition(); + return static_cast( aSelection.items.GetPickedItem( 0 ) )->GetPosition() - m_offset; } else { From 089e99b99eff8bb417681ae6f5bbd373b3252680 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 33/68] Fixing memory leaks. --- common/tool/context_menu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index 580e876a8b..827d1080e0 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -119,7 +119,8 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction ) case MD_SHIFT: flags = wxACCEL_SHIFT; break; } - item->SetAccel( new wxAcceleratorEntry( flags, key, id, item ) ); + wxAcceleratorEntry accel( flags, key, id, item ); + item->SetAccel( &accel ); } m_menu.Append( item ); From 05ee03d6b0b739c2a56920277c9919d89a930254 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 34/68] Recursive copy constructor for CONTEXT_MENU. --- common/tool/context_menu.cpp | 142 ++++++++++++++++++++++++----------- common/tool/tool_manager.cpp | 4 +- include/tool/context_menu.h | 50 ++++++------ 3 files changed, 123 insertions(+), 73 deletions(-) diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index 827d1080e0..400193a16b 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -29,41 +29,32 @@ #include CONTEXT_MENU::CONTEXT_MENU() : - m_titleSet( false ), m_selected( -1 ), m_handler( this ), m_tool( NULL ) + m_titleSet( false ), m_selected( -1 ), m_tool( NULL ) { - m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), - NULL, &m_handler ); - m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ), - NULL, &m_handler ); - - // Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu) - wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, &m_menu ); - m_menu.AddPendingEvent( menuEvent ); + setupEvents(); } CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) : - m_titleSet( aMenu.m_titleSet ), m_selected( -1 ), m_handler( this ), m_tool( aMenu.m_tool ) + m_titleSet( aMenu.m_titleSet ), m_selected( -1 ), m_tool( aMenu.m_tool ) { - m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), - NULL, &m_handler ); - m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ), - NULL, &m_handler ); - - // Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu) - wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, &m_menu ); - m_menu.AddPendingEvent( menuEvent ); + setupEvents(); // Copy all the menu entries - for( unsigned i = 0; i < aMenu.m_menu.GetMenuItemCount(); ++i ) - { - wxMenuItem* item = aMenu.m_menu.FindItemByPosition( i ); - m_menu.Append( new wxMenuItem( &m_menu, item->GetId(), item->GetItemLabel(), - wxEmptyString, wxITEM_NORMAL ) ); - } + copyMenu( &aMenu, this ); +} - // Copy tool actions that are available to choose from context menu - m_toolActions = aMenu.m_toolActions; + +void CONTEXT_MENU::setupEvents() +{ + Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CONTEXT_MENU::onMenuEvent ), + NULL, this ); + Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CONTEXT_MENU::onMenuEvent ), + NULL, this ); + + // Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu) + wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, this ); + AddPendingEvent( menuEvent ); } @@ -71,15 +62,16 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle ) { // TODO handle an empty string (remove title and separator) - // Unfortunately wxMenu::SetTitle() does nothing.. + // Unfortunately wxMenu::SetTitle() does nothing.. (at least wxGTK) + if( m_titleSet ) { - m_menu.FindItemByPosition( 0 )->SetItemLabel( aTitle ); + FindItemByPosition( 0 )->SetItemLabel( aTitle ); } else { - m_menu.InsertSeparator( 0 ); - m_menu.Insert( 0, new wxMenuItem( &m_menu, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) ); + InsertSeparator( 0 ); + Insert( 0, new wxMenuItem( this, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) ); m_titleSet = true; } } @@ -89,11 +81,11 @@ void CONTEXT_MENU::Add( const wxString& aLabel, int aId ) { #ifdef DEBUG - if( m_menu.FindItem( aId ) != NULL ) + if( FindItem( aId ) != NULL ) wxLogWarning( wxT( "Adding more than one menu entry with the same ID may result in" "undefined behaviour" ) ); #endif - m_menu.Append( new wxMenuItem( &m_menu, aId, aLabel, wxEmptyString, wxITEM_NORMAL ) ); + Append( new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL ) ); } @@ -102,7 +94,7 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction ) /// ID numbers for tool actions need to have a value higher than m_actionId int id = m_actionId + aAction.GetId(); - wxMenuItem* item = new wxMenuItem( &m_menu, id, + wxMenuItem* item = new wxMenuItem( this, id, wxString( aAction.GetMenuItem().c_str(), wxConvUTF8 ), wxString( aAction.GetDescription().c_str(), wxConvUTF8 ), wxITEM_NORMAL ); @@ -123,7 +115,7 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction ) item->SetAccel( &accel ); } - m_menu.Append( item ); + Append( item ); m_toolActions[id] = &aAction; } @@ -133,14 +125,14 @@ void CONTEXT_MENU::Clear() m_titleSet = false; // Remove all the entries from context menu - for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i ) - m_menu.Destroy( m_menu.FindItemByPosition( 0 ) ); + for( unsigned i = 0; i < GetMenuItemCount(); ++i ) + Destroy( FindItemByPosition( 0 ) ); m_toolActions.clear(); } -void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent ) +void CONTEXT_MENU::onMenuEvent( wxEvent& aEvent ) { TOOL_EVENT evt; wxEventType type = aEvent.GetEventType(); @@ -155,21 +147,83 @@ void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent ) else if( type == wxEVT_COMMAND_MENU_SELECTED ) { // Store the selected position - m_menu->m_selected = aEvent.GetId(); + m_selected = aEvent.GetId(); // Check if there is a TOOL_ACTION for the given ID - if( m_menu->m_toolActions.count( aEvent.GetId() ) == 1 ) + if( m_toolActions.count( aEvent.GetId() ) == 1 ) { - evt = m_menu->m_toolActions[aEvent.GetId()]->MakeEvent(); + evt = m_toolActions[aEvent.GetId()]->MakeEvent(); } else { - // Handling non-action menu entries (e.g. items in clarification list) - evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, aEvent.GetId() ); + OPT_TOOL_EVENT custom = handleCustomEvent( aEvent ); + if(custom) + evt = *custom; + else { + // Handling non-action menu entries (e.g. items in clarification list) + evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, aEvent.GetId() ); + } } } // forward the action/update event to the TOOL_MANAGER - if( m_menu->m_tool ) - m_menu->m_tool->GetManager()->ProcessEvent( evt ); + if( m_tool ) + m_tool->GetManager()->ProcessEvent( evt ); +} + + +void CONTEXT_MENU::copyMenu( const CONTEXT_MENU* aParent, CONTEXT_MENU* aTarget ) const +{ + // Copy all the menu entries + for( unsigned i = 0; i < aParent->GetMenuItemCount(); ++i ) + { + wxMenuItem* item = aParent->FindItemByPosition( i ); + + if( item->IsSubMenu() ) + { +#ifdef DEBUG + // Submenus of a CONTEXT_MENU are supposed to be CONTEXT_MENUs as well + assert( dynamic_cast( item->GetSubMenu() ) ); +#endif + + CONTEXT_MENU* menu = new CONTEXT_MENU; + copyMenu( static_cast( item->GetSubMenu() ), menu ); + aTarget->AppendSubMenu( menu, item->GetItemLabel(), wxT( "" ) ); + } + else + { + wxMenuItem* newItem = new wxMenuItem( aTarget, item->GetId(), item->GetItemLabel(), + wxEmptyString, item->GetKind() ); + + aTarget->Append( newItem ); + copyItem( item, newItem ); + } + } + + // Copy tool actions that are available to choose from context menu + aTarget->m_toolActions = aParent->m_toolActions; +} + + +void CONTEXT_MENU::copyItem( const wxMenuItem* aSource, wxMenuItem* aDest ) const +{ + assert( !aSource->IsSubMenu() ); + + aDest->SetKind( aSource->GetKind() ); + aDest->SetHelp( aSource->GetHelp() ); + aDest->Enable( aSource->IsEnabled() ); + + if( aSource->IsCheckable() ) + aDest->Check( aSource->IsChecked() ); + + if( aSource->GetKind() == wxITEM_NORMAL ) + aDest->SetBitmap( aSource->GetBitmap() ); + + if( aSource->IsSubMenu() ) + { + CONTEXT_MENU* newMenu = new CONTEXT_MENU; + + copyMenu( static_cast( aSource->GetSubMenu() ), newMenu ); + aDest->SetSubMenu( newMenu ); + } } diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index 0f0ee83533..dd77425a0c 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -308,8 +308,6 @@ int TOOL_MANAGER::GetPriority( int aToolId ) const for( std::deque::const_iterator it = m_activeTools.begin(), itEnd = m_activeTools.end(); it != itEnd; ++it ) { - std::cout << FindTool( *it )->GetName() << std::endl; - if( *it == aToolId ) return priority; @@ -497,7 +495,7 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) st->contextMenuTrigger = CMENU_OFF; boost::scoped_ptr menu( new CONTEXT_MENU( *st->contextMenu ) ); - GetEditFrame()->PopupMenu( menu->GetMenu() ); + GetEditFrame()->PopupMenu( menu.get() ); // If nothing was chosen from the context menu, we must notify the tool as well if( menu->GetSelected() < 0 ) diff --git a/include/tool/context_menu.h b/include/tool/context_menu.h index e181b576bb..a0a57b3d0b 100644 --- a/include/tool/context_menu.h +++ b/include/tool/context_menu.h @@ -37,7 +37,7 @@ class TOOL_INTERACTIVE; * Defines the structure of a context (usually right-click) popup menu * for a given tool. */ -class CONTEXT_MENU +class CONTEXT_MENU : public wxMenu { public: ///> Default constructor @@ -71,6 +71,7 @@ public: */ void Add( const TOOL_ACTION& aAction ); + /** * Function Clear() * Removes all the entries from the menu (as well as its title). It leaves the menu in the @@ -89,32 +90,32 @@ public: return m_selected; } - /** - * Function GetMenu() - * Returns the instance of wxMenu object used to display the menu. - */ - wxMenu* GetMenu() const + +protected: + virtual OPT_TOOL_EVENT handleCustomEvent ( wxEvent& aEvent ) { - return const_cast( &m_menu ); - } + return OPT_TOOL_EVENT(); + }; private: - ///> Class CMEventHandler takes care of handling menu events. After reception of particular - ///> events, it translates them to TOOL_EVENTs that may control tools. - class CMEventHandler : public wxEvtHandler - { - public: - ///> Default constructor - ///> aMenu is the CONTEXT_MENU instance for which it handles events. - CMEventHandler( CONTEXT_MENU* aMenu ) : m_menu( aMenu ) {}; + /** + * Function copyMenu + * Copies recursively all entries and submenus. + * @param aParent is the source. + * @param aTarget is the destination. + */ + void copyMenu( const CONTEXT_MENU* aParent, CONTEXT_MENU* aTarget ) const; - ///> Handler for menu events. - void onEvent( wxEvent& aEvent ); + /** + * Function copyItem + * Copies all properties of a menu entry. + */ + void copyItem( const wxMenuItem* aSource, wxMenuItem* aDest ) const; - private: - ///> CONTEXT_MENU instance for which it handles events. - CONTEXT_MENU* m_menu; - }; + void setupEvents(); + + ///> Event handler. + void onMenuEvent( wxEvent& aEvent ); friend class TOOL_INTERACTIVE; @@ -131,14 +132,11 @@ private: ///> Flag indicating that the menu title was set up. bool m_titleSet; - ///> Instance of wxMenu used for display of the context menu. - wxMenu m_menu; - ///> Stores the id number of selected item. int m_selected; ///> Instance of menu event handler. - CMEventHandler m_handler; + //CMEventHandler m_handler; ///> Creator of the menu TOOL_INTERACTIVE* m_tool; From e2feefc08cc85f21c13bf33226eb815fb344e9f4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 35/68] Fixed custom event handlers for CONTEXT_MENU. Moved menuCopy to CONTEXT_MENU copy constructor. --- common/tool/context_menu.cpp | 88 +++++++++++++++--------------------- include/tool/context_menu.h | 25 +++++----- 2 files changed, 50 insertions(+), 63 deletions(-) diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index 400193a16b..8bdcd57536 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -26,22 +26,48 @@ #include #include #include +#include #include CONTEXT_MENU::CONTEXT_MENU() : m_titleSet( false ), m_selected( -1 ), m_tool( NULL ) { + setCustomEventHandler( boost::bind( &CONTEXT_MENU::handleCustomEvent, this, _1 ) ); + setupEvents(); } CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) : - m_titleSet( aMenu.m_titleSet ), m_selected( -1 ), m_tool( aMenu.m_tool ) + m_titleSet( aMenu.m_titleSet ), m_selected( -1 ), m_tool( aMenu.m_tool ), + m_toolActions( aMenu.m_toolActions ), m_customHandler( aMenu.m_customHandler ) { - setupEvents(); - // Copy all the menu entries - copyMenu( &aMenu, this ); + for( unsigned i = 0; i < aMenu.GetMenuItemCount(); ++i ) + { + wxMenuItem* item = aMenu.FindItemByPosition( i ); + + if( item->IsSubMenu() ) + { +#ifdef DEBUG + // Submenus of a CONTEXT_MENU are supposed to be CONTEXT_MENUs as well + assert( dynamic_cast( item->GetSubMenu() ) ); +#endif + + CONTEXT_MENU* menu = new CONTEXT_MENU( static_cast( *item->GetSubMenu() ) ); + AppendSubMenu( menu, item->GetItemLabel(), wxEmptyString ); + } + else + { + wxMenuItem* newItem = new wxMenuItem( this, item->GetId(), item->GetItemLabel(), + wxEmptyString, item->GetKind() ); + + Append( newItem ); + copyItem( item, newItem ); + } + } + + setupEvents(); } @@ -156,10 +182,12 @@ void CONTEXT_MENU::onMenuEvent( wxEvent& aEvent ) } else { - OPT_TOOL_EVENT custom = handleCustomEvent( aEvent ); - if(custom) + OPT_TOOL_EVENT custom = m_customHandler( aEvent ); + + if( custom ) evt = *custom; - else { + else + { // Handling non-action menu entries (e.g. items in clarification list) evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, aEvent.GetId() ); } @@ -167,47 +195,13 @@ void CONTEXT_MENU::onMenuEvent( wxEvent& aEvent ) } // forward the action/update event to the TOOL_MANAGER - if( m_tool ) - m_tool->GetManager()->ProcessEvent( evt ); -} - - -void CONTEXT_MENU::copyMenu( const CONTEXT_MENU* aParent, CONTEXT_MENU* aTarget ) const -{ - // Copy all the menu entries - for( unsigned i = 0; i < aParent->GetMenuItemCount(); ++i ) - { - wxMenuItem* item = aParent->FindItemByPosition( i ); - - if( item->IsSubMenu() ) - { -#ifdef DEBUG - // Submenus of a CONTEXT_MENU are supposed to be CONTEXT_MENUs as well - assert( dynamic_cast( item->GetSubMenu() ) ); -#endif - - CONTEXT_MENU* menu = new CONTEXT_MENU; - copyMenu( static_cast( item->GetSubMenu() ), menu ); - aTarget->AppendSubMenu( menu, item->GetItemLabel(), wxT( "" ) ); - } - else - { - wxMenuItem* newItem = new wxMenuItem( aTarget, item->GetId(), item->GetItemLabel(), - wxEmptyString, item->GetKind() ); - - aTarget->Append( newItem ); - copyItem( item, newItem ); - } - } - - // Copy tool actions that are available to choose from context menu - aTarget->m_toolActions = aParent->m_toolActions; + TOOL_MANAGER::Instance().ProcessEvent( evt ); } void CONTEXT_MENU::copyItem( const wxMenuItem* aSource, wxMenuItem* aDest ) const { - assert( !aSource->IsSubMenu() ); + assert( !aSource->IsSubMenu() ); // it does not transfer submenus aDest->SetKind( aSource->GetKind() ); aDest->SetHelp( aSource->GetHelp() ); @@ -218,12 +212,4 @@ void CONTEXT_MENU::copyItem( const wxMenuItem* aSource, wxMenuItem* aDest ) cons if( aSource->GetKind() == wxITEM_NORMAL ) aDest->SetBitmap( aSource->GetBitmap() ); - - if( aSource->IsSubMenu() ) - { - CONTEXT_MENU* newMenu = new CONTEXT_MENU; - - copyMenu( static_cast( aSource->GetSubMenu() ), newMenu ); - aDest->SetSubMenu( newMenu ); - } } diff --git a/include/tool/context_menu.h b/include/tool/context_menu.h index a0a57b3d0b..709e0d34e7 100644 --- a/include/tool/context_menu.h +++ b/include/tool/context_menu.h @@ -28,6 +28,7 @@ #include #include #include +#include class TOOL_INTERACTIVE; @@ -90,28 +91,25 @@ public: return m_selected; } - protected: - virtual OPT_TOOL_EVENT handleCustomEvent ( wxEvent& aEvent ) + void setCustomEventHandler( boost::function aHandler ) + { + m_customHandler = aHandler; + } + + virtual OPT_TOOL_EVENT handleCustomEvent(const wxEvent& aEvent ) { return OPT_TOOL_EVENT(); - }; + } private: - /** - * Function copyMenu - * Copies recursively all entries and submenus. - * @param aParent is the source. - * @param aTarget is the destination. - */ - void copyMenu( const CONTEXT_MENU* aParent, CONTEXT_MENU* aTarget ) const; - /** * Function copyItem - * Copies all properties of a menu entry. + * Copies all properties of a menu entry to another. */ void copyItem( const wxMenuItem* aSource, wxMenuItem* aDest ) const; + ///> Initializes handlers for events. void setupEvents(); ///> Event handler. @@ -146,6 +144,9 @@ private: /// Associates tool actions with menu item IDs. Non-owning. std::map m_toolActions; + + /// Custom events handler, allows to translate wxEvents to TOOL_EVENTs. + boost::function m_customHandler; }; #endif From 3f2fc340754c543d2f2d7391f840525caf5c89e1 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 36/68] WX_UNIT_TEXT can handle default value. --- common/wxunittext.cpp | 12 ++++++++++-- include/wxunittext.h | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/common/wxunittext.cpp b/common/wxunittext.cpp index f33be9ec5a..743f973dce 100644 --- a/common/wxunittext.cpp +++ b/common/wxunittext.cpp @@ -101,13 +101,15 @@ void WX_UNIT_TEXT::SetUnits( EDA_UNITS_T aUnits, bool aConvert ) void WX_UNIT_TEXT::SetValue( double aValue ) { - assert( aValue >= 0.0 ); - if( aValue >= 0.0 ) { m_inputValue->SetValue( wxString( Double2Str( aValue ).c_str(), wxConvUTF8 ) ); m_inputValue->MarkDirty(); } + else + { + m_inputValue->SetValue( DEFAULT_VALUE ); + } } @@ -169,6 +171,9 @@ boost::optional WX_UNIT_TEXT::GetValue() const wxString text = m_inputValue->GetValue(); double value; + if( text == DEFAULT_VALUE ) + return boost::optional( -1.0 ); + if( !text.ToDouble( &value ) ) return boost::optional(); @@ -189,3 +194,6 @@ void WX_UNIT_TEXT::onSpinDownEvent( wxSpinEvent& aEvent ) if( newValue >= 0.0 ) SetValue( newValue ); } + + +const wxString WX_UNIT_TEXT::DEFAULT_VALUE = _( "default "); diff --git a/include/wxunittext.h b/include/wxunittext.h index 92791f09ff..54c52e14dc 100644 --- a/include/wxunittext.h +++ b/include/wxunittext.h @@ -136,6 +136,9 @@ protected: ///> Step size (added/subtracted difference if spin buttons are used). double m_step; + + ///> Default value (or non-specified) + static const wxString DEFAULT_VALUE; }; #endif /* WXUNITTEXT_H_ */ From 4577aed921f48e5c99b64381adb2288054fec0a8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 37/68] Minor reorganization of handling custom events with CONTEXT_MENU. --- common/tool/context_menu.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index 8bdcd57536..7413761ed3 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -160,7 +160,8 @@ void CONTEXT_MENU::Clear() void CONTEXT_MENU::onMenuEvent( wxEvent& aEvent ) { - TOOL_EVENT evt; + OPT_TOOL_EVENT evt; + wxEventType type = aEvent.GetEventType(); // When the currently chosen item in the menu is changed, an update event is issued. @@ -182,20 +183,16 @@ void CONTEXT_MENU::onMenuEvent( wxEvent& aEvent ) } else { - OPT_TOOL_EVENT custom = m_customHandler( aEvent ); + evt = m_customHandler( aEvent ); - if( custom ) - evt = *custom; - else - { - // Handling non-action menu entries (e.g. items in clarification list) + // Handling non-action menu entries (e.g. items in clarification list) + if( !evt ) evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, aEvent.GetId() ); - } } } // forward the action/update event to the TOOL_MANAGER - TOOL_MANAGER::Instance().ProcessEvent( evt ); + TOOL_MANAGER::Instance().ProcessEvent( *evt ); } From ffe212ea5e8b928bd9f30bf3c26de7142af9541a Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 38/68] Initial support for custom track width & via size. --- pcbnew/class_board.cpp | 6 ++ pcbnew/class_board.h | 125 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 121 insertions(+), 10 deletions(-) diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index a7b4e35987..81399f456f 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -106,6 +106,12 @@ BOARD::BOARD() : SetCurrentNetClass( m_NetClasses.GetDefault()->GetName() ); + // Set sensible initial values for custom track width & via size + m_useCustomTrackVia = false; + m_customTrackWidth = GetCurrentTrackWidth(); + m_customViaSize.m_Diameter = GetCurrentViaSize(); + m_customViaSize.m_Drill = GetCurrentViaDrill(); + // Initialize ratsnest m_ratsnest = new RN_DATA( this ); m_ratsnestViewItem = new KIGFX::RATSNEST_VIEWITEM( m_ratsnest ); diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 308f69a13d..7fc8987198 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -258,6 +258,15 @@ private: // Index for m_TrackWidthList to select the value. unsigned m_trackWidthIndex; + ///> Use custom values for track/via sizes (not specified in net class nor in the size lists). + bool m_useCustomTrackVia; + + ///> Custom track width (used after UseCustomTrackViaSize( true ) was called). + int m_customTrackWidth; + + ///> Custom via size (used after UseCustomTrackViaSize( true ) was called). + VIA_DIMENSION m_customViaSize; + /** * Function chainMarkedSegments * is used by MarkTrace() to set the BUSY flag of connected segments of the trace @@ -303,15 +312,14 @@ public: // the first value is always the value of the current NetClass // The others values are extra values - // The first value is the current netclass via size // TODO verify + // The first value is the current netclass via size /// Vias size and drill list std::vector m_ViasDimensionsList; - // The first value is the current netclass track width // TODO verify + // The first value is the current netclass track width /// Track width list std::vector m_TrackWidthList; - BOARD(); ~BOARD(); @@ -1074,12 +1082,36 @@ public: /** * Function GetCurrentTrackWidth * @return the current track width, according to the selected options - * ( using the default netclass value or a preset value ) + * ( using the default netclass value or a preset/custom value ) * the default netclass is always in m_TrackWidthList[0] */ int GetCurrentTrackWidth() const { - return m_TrackWidthList[m_trackWidthIndex]; + if( m_useCustomTrackVia ) + return m_customTrackWidth; + else + return m_TrackWidthList[m_trackWidthIndex]; + } + + /** + * Function SetCustomTrackWidth + * Sets custom width for track (i.e. not available in netclasses or preset list). To have + * it returned with GetCurrentTrackWidth() you need to enable custom track & via sizes + * (UseCustomTrackViaSize()). + * @param aWidth is the new track width. + */ + void SetCustomTrackWidth( int aWidth ) + { + m_customTrackWidth = aWidth; + } + + /** + * Function GetCustomTrackWidth + * @return Current custom width for a track. + */ + int GetCustomTrackWidth() const + { + return m_customTrackWidth; } /** @@ -1099,24 +1131,76 @@ public: /** * Function GetCurrentViaSize * @return the current via size, according to the selected options - * ( using the default netclass value or a preset value ) + * ( using the default netclass value or a preset/custom value ) * the default netclass is always in m_TrackWidthList[0] */ int GetCurrentViaSize() { - return m_ViasDimensionsList[m_viaSizeIndex].m_Diameter; + if( m_useCustomTrackVia ) + return m_customViaSize.m_Diameter; + else + return m_ViasDimensionsList[m_viaSizeIndex].m_Diameter; } + /** + * Function SetCustomViaSize + * Sets custom size for via diameter (i.e. not available in netclasses or preset list). To have + * it returned with GetCurrentViaSize() you need to enable custom track & via sizes + * (UseCustomTrackViaSize()). + * @param aSize is the new drill diameter. + */ + void SetCustomViaSize( int aSize ) + { + m_customViaSize.m_Diameter = aSize; + } + + /** + * Function GetCustomViaSize + * @return Current custom size for the via diameter. + */ + int GetCustomViaSize() const + { + return m_customViaSize.m_Diameter; + } + + /** * Function GetCurrentViaDrill * @return the current via size, according to the selected options - * ( using the default netclass value or a preset value ) + * ( using the default netclass value or a preset/custom value ) * the default netclass is always in m_TrackWidthList[0] */ int GetCurrentViaDrill() { - return m_ViasDimensionsList[m_viaSizeIndex].m_Drill > 0 ? - m_ViasDimensionsList[m_viaSizeIndex].m_Drill : -1; + int drill; + + if( m_useCustomTrackVia ) + drill = m_customViaSize.m_Drill; + else + drill = m_ViasDimensionsList[m_viaSizeIndex].m_Drill; + + return drill > 0 ? drill : -1; + } + + /** + * Function SetCustomViaDrill + * Sets custom size for via drill (i.e. not available in netclasses or preset list). To have + * it returned with GetCurrentViaDrill() you need to enable custom track & via sizes + * (UseCustomTrackViaSize()). + * @param aDrill is the new drill size. + */ + void SetCustomViaDrill( int aDrill ) + { + m_customViaSize.m_Drill = aDrill; + } + + /** + * Function GetCustomViaDrill + * @return Current custom size for the via drill. + */ + int GetCustomViaDrill() const + { + return m_customViaSize.m_Drill; } /** @@ -1133,6 +1217,27 @@ public: */ int GetCurrentMicroViaDrill(); + /** + * Function UseCustomTrackViaSize + * Enables/disables custom track/via size settings. If enabled, values set with + * SetCustomTrackWidth()/SetCustomViaSize()/SetCustomViaDrill() are used for newly created + * tracks and vias. + * @param aEnabled decides if custom settings should be used for new tracks/vias. + */ + void UseCustomTrackViaSize( bool aEnabled ) + { + m_useCustomTrackVia = aEnabled; + } + + /** + * Function UseCustomTrackViaSize + * @return True if custom sizes of tracks & vias are enabled, false otherwise. + */ + bool UseCustomTrackViaSize() const + { + return m_useCustomTrackVia; + } + /***************************************************************************/ wxString GetClass() const From 917e47397d562315c691cc8cf3f57957b1b27b6d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 39/68] Custom track/via size settings nicely cooperate with other options. --- pcbnew/pcbnew_id.h | 1 + pcbnew/tools/common_actions.cpp | 1 + pcbnew/tools/common_actions.h | 2 ++ pcbnew/tools/pcbnew_control.cpp | 12 ++++++++++++ 4 files changed, 16 insertions(+) diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index 0ceb7ccde8..421aad1e70 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -170,6 +170,7 @@ enum pcbnew_ids ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH, ID_POPUP_PCB_SELECT_WIDTH_START_RANGE, ID_POPUP_PCB_SELECT_WIDTH, + ID_POPUP_PCB_SELECT_CUSTOM, ID_POPUP_PCB_SELECT_AUTO_WIDTH, ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, ID_POPUP_PCB_SELECT_WIDTH1, diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp index 3ff65af56b..539de05ceb 100644 --- a/pcbnew/tools/common_actions.cpp +++ b/pcbnew/tools/common_actions.cpp @@ -241,6 +241,7 @@ TOOL_ACTION COMMON_ACTIONS::viaSizeDec( "pcbnew.viaSizeDec", AS_GLOBAL, '\\', "", "" ); +TOOL_ACTION COMMON_ACTIONS::trackViaSizeChanged( "pcbnew.trackViaSizeChanged", AS_GLOBAL, 0, "", "" ); // Miscellaneous TOOL_ACTION COMMON_ACTIONS::resetCoords( "pcbnew.resetCoords", diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h index 38569af29a..671a509699 100644 --- a/pcbnew/tools/common_actions.h +++ b/pcbnew/tools/common_actions.h @@ -137,6 +137,8 @@ public: static TOOL_ACTION viaSizeInc; static TOOL_ACTION viaSizeDec; + static TOOL_ACTION trackViaSizeChanged; // notification + // Miscellaneous static TOOL_ACTION resetCoords; static TOOL_ACTION switchUnits; diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index ec8b086bab..378ae9a580 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -422,11 +422,14 @@ int PCBNEW_CONTROL::TrackWidthInc( TOOL_EVENT& aEvent ) widthIndex = board->m_TrackWidthList.size() - 1; board->SetTrackWidthIndex( widthIndex ); + board->UseCustomTrackViaSize( false ); wxUpdateUIEvent dummy; getEditFrame()->OnUpdateSelectTrackWidth( dummy ); setTransitions(); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + return 0; } @@ -440,11 +443,14 @@ int PCBNEW_CONTROL::TrackWidthDec( TOOL_EVENT& aEvent ) widthIndex = 0; board->SetTrackWidthIndex( widthIndex ); + board->UseCustomTrackViaSize( false ); wxUpdateUIEvent dummy; getEditFrame()->OnUpdateSelectTrackWidth( dummy ); setTransitions(); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + return 0; } @@ -458,11 +464,14 @@ int PCBNEW_CONTROL::ViaSizeInc( TOOL_EVENT& aEvent ) sizeIndex = board->m_ViasDimensionsList.size() - 1; board->SetViaSizeIndex( sizeIndex ); + board->UseCustomTrackViaSize( false ); wxUpdateUIEvent dummy; getEditFrame()->OnUpdateSelectViaSize( dummy ); setTransitions(); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + return 0; } @@ -476,11 +485,14 @@ int PCBNEW_CONTROL::ViaSizeDec( TOOL_EVENT& aEvent ) sizeIndex = 0; board->SetViaSizeIndex( sizeIndex ); + board->UseCustomTrackViaSize( false ); wxUpdateUIEvent dummy; getEditFrame()->OnUpdateSelectViaSize( dummy ); setTransitions(); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + return 0; } From 7ec1313cbcff4df62c039bb79ef1ef1caa1ce909 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 40/68] Custom width settings taken into account in wxUpdateUIEvent handlers. --- include/wxPcbStruct.h | 1 + pcbnew/pcbframe.cpp | 2 ++ pcbnew/pcbnew_id.h | 2 +- pcbnew/toolbars_update_user_interface.cpp | 16 +++++++++++++--- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 0e19dc8e22..b9321922a8 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -248,6 +248,7 @@ public: void OnUpdateZoneDisplayStyle( wxUpdateUIEvent& aEvent ); void OnUpdateSelectTrackWidth( wxUpdateUIEvent& aEvent ); void OnUpdateSelectAutoTrackWidth( wxUpdateUIEvent& aEvent ); + void OnUpdateSelectCustomTrackWidth( wxUpdateUIEvent& aEvent ); void OnUpdateAutoPlaceModulesMode( wxUpdateUIEvent& aEvent ); void OnUpdateAutoPlaceTracksMode( wxUpdateUIEvent& aEvent ); void OnUpdateMuWaveToolbar( wxUpdateUIEvent& aEvent ); diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 9f66d54d21..212dd6a83c 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -275,6 +275,8 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_UPDATE_UI( ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH, PCB_EDIT_FRAME::OnUpdateSelectAutoTrackWidth ) EVT_UPDATE_UI( ID_POPUP_PCB_SELECT_AUTO_WIDTH, PCB_EDIT_FRAME::OnUpdateSelectAutoTrackWidth ) + EVT_UPDATE_UI( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, + PCB_EDIT_FRAME::OnUpdateSelectCustomTrackWidth ) EVT_UPDATE_UI( ID_AUX_TOOLBAR_PCB_VIA_SIZE, PCB_EDIT_FRAME::OnUpdateSelectViaSize ) EVT_UPDATE_UI( ID_TOOLBARH_PCB_MODE_MODULE, PCB_EDIT_FRAME::OnUpdateAutoPlaceModulesMode ) EVT_UPDATE_UI( ID_TOOLBARH_PCB_MODE_TRACKS, PCB_EDIT_FRAME::OnUpdateAutoPlaceTracksMode ) diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index 421aad1e70..785c92417f 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -170,7 +170,7 @@ enum pcbnew_ids ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH, ID_POPUP_PCB_SELECT_WIDTH_START_RANGE, ID_POPUP_PCB_SELECT_WIDTH, - ID_POPUP_PCB_SELECT_CUSTOM, + ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, ID_POPUP_PCB_SELECT_AUTO_WIDTH, ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, ID_POPUP_PCB_SELECT_WIDTH1, diff --git a/pcbnew/toolbars_update_user_interface.cpp b/pcbnew/toolbars_update_user_interface.cpp index ac2f65a490..78b44145bb 100644 --- a/pcbnew/toolbars_update_user_interface.cpp +++ b/pcbnew/toolbars_update_user_interface.cpp @@ -62,7 +62,9 @@ void PCB_EDIT_FRAME::OnUpdateSelectTrackWidth( wxUpdateUIEvent& aEvent ) { bool check = ( ( ( ID_POPUP_PCB_SELECT_WIDTH1 + (int) GetBoard()->GetTrackWidthIndex() ) == aEvent.GetId() ) && - !GetDesignSettings().m_UseConnectedTrackWidth ); + !GetDesignSettings().m_UseConnectedTrackWidth && + !GetBoard()->UseCustomTrackViaSize() ); + aEvent.Check( check ); } } @@ -70,7 +72,14 @@ void PCB_EDIT_FRAME::OnUpdateSelectTrackWidth( wxUpdateUIEvent& aEvent ) void PCB_EDIT_FRAME::OnUpdateSelectAutoTrackWidth( wxUpdateUIEvent& aEvent ) { - aEvent.Check( GetDesignSettings().m_UseConnectedTrackWidth ); + aEvent.Check( GetDesignSettings().m_UseConnectedTrackWidth && + !GetBoard()->UseCustomTrackViaSize() ); +} + + +void PCB_EDIT_FRAME::OnUpdateSelectCustomTrackWidth( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( GetBoard()->UseCustomTrackViaSize() ); } @@ -87,7 +96,8 @@ void PCB_EDIT_FRAME::OnUpdateSelectViaSize( wxUpdateUIEvent& aEvent ) { bool check = ( ( ( ID_POPUP_PCB_SELECT_VIASIZE1 + (int) GetBoard()->GetViaSizeIndex() ) == aEvent.GetId() ) && - !GetDesignSettings().m_UseConnectedTrackWidth ); + !GetDesignSettings().m_UseConnectedTrackWidth && + !GetBoard()->UseCustomTrackViaSize() ); aEvent.Check( check ); } From cd8aaee160cda2189ce27522b91cb32a9aac0f7c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 41/68] Moved most of the board design rules related fields & methods to BOARD_DESIGN_SETTINGS class. --- include/class_board_design_settings.h | 208 ++++++++++++++- pcbnew/autorouter/solve.cpp | 10 +- pcbnew/class_board.cpp | 54 ++-- pcbnew/class_board.h | 241 +----------------- pcbnew/class_board_design_settings.cpp | 33 ++- pcbnew/dialogs/dialog_design_rules.cpp | 8 +- .../dialog_global_edit_tracks_and_vias.cpp | 12 +- pcbnew/edit_track_width.cpp | 6 +- pcbnew/editrack-part2.cpp | 4 +- pcbnew/editrack.cpp | 18 +- pcbnew/event_handlers_tracks_vias_sizes.cpp | 12 +- pcbnew/hotkeys_board_editor.cpp | 12 +- pcbnew/kicad_plugin.cpp | 12 +- pcbnew/legacy_plugin.cpp | 37 +-- pcbnew/muonde.cpp | 10 +- pcbnew/onrightclick.cpp | 23 +- pcbnew/pcb_parser.cpp | 6 +- pcbnew/tool_pcb.cpp | 24 +- pcbnew/toolbars_update_user_interface.cpp | 22 +- pcbnew/tools/pcbnew_control.cpp | 32 +-- 20 files changed, 393 insertions(+), 391 deletions(-) diff --git a/include/class_board_design_settings.h b/include/class_board_design_settings.h index 67e0c73a88..70ba89f4ae 100644 --- a/include/class_board_design_settings.h +++ b/include/class_board_design_settings.h @@ -10,6 +10,41 @@ #include #include +/** + * Struct VIA_DIMENSION + * is a small helper container to handle a stock of specific vias each with + * unique diameter and drill sizes in the BOARD class. + */ +struct VIA_DIMENSION +{ + int m_Diameter; // <= 0 means use Netclass via diameter + int m_Drill; // <= 0 means use Netclass via drill + + VIA_DIMENSION() + { + m_Diameter = 0; + m_Drill = 0; + } + + VIA_DIMENSION( int aDiameter, int aDrill ) + { + m_Diameter = aDiameter; + m_Drill = aDrill; + } + + bool operator==( const VIA_DIMENSION& aOther ) const + { + return ( m_Diameter == aOther.m_Diameter ) && ( m_Drill == aOther.m_Drill ); + } + + bool operator<( const VIA_DIMENSION& aOther ) const + { + if( m_Diameter != aOther.m_Diameter ) + return m_Diameter < aOther.m_Diameter; + + return m_Drill < aOther.m_Drill; + } +}; /** * Class BOARD_DESIGN_SETTINGS @@ -18,6 +53,14 @@ class BOARD_DESIGN_SETTINGS { public: + // The first value is the current netclass via size + /// Vias size and drill list + std::vector m_ViasDimensionsList; + + // The first value is the current netclass track width + /// Track width list + std::vector m_TrackWidthList; + bool m_MicroViasAllowed; ///< true to allow micro vias bool m_BlindBuriedViaAllowed; ///< true to allow blind/buried vias VIATYPE_T m_CurrentViaType; ///< via type (VIA_BLIND_BURIED, VIA_THROUGH VIA_MICROVIA) @@ -52,9 +95,155 @@ public: D_PAD m_Pad_Master; -public: BOARD_DESIGN_SETTINGS(); + /** + * Function GetTrackWidthIndex + * @return the current track width list index. + */ + unsigned GetTrackWidthIndex() const { return m_trackWidthIndex; } + + /** + * Function SetTrackWidthIndex + * sets the current track width list index to \a aIndex. + * + * @param aIndex is the track width list index. + */ + void SetTrackWidthIndex( unsigned aIndex ); + + /** + * Function GetCurrentTrackWidth + * @return the current track width, according to the selected options + * ( using the default netclass value or a preset/custom value ) + * the default netclass is always in m_TrackWidthList[0] + */ + int GetCurrentTrackWidth() const + { + return m_useCustomTrackVia ? m_customTrackWidth : m_TrackWidthList[m_trackWidthIndex]; + } + + /** + * Function SetCustomTrackWidth + * Sets custom width for track (i.e. not available in netclasses or preset list). To have + * it returned with GetCurrentTrackWidth() you need to enable custom track & via sizes + * (UseCustomTrackViaSize()). + * @param aWidth is the new track width. + */ + void SetCustomTrackWidth( int aWidth ) + { + m_customTrackWidth = aWidth; + } + + /** + * Function GetCustomTrackWidth + * @return Current custom width for a track. + */ + int GetCustomTrackWidth() const + { + return m_customTrackWidth; + } + + /** + * Function GetViaSizeIndex + * @return the current via size list index. + */ + unsigned GetViaSizeIndex() const { return m_viaSizeIndex; } + + /** + * Function SetViaSizeIndex + * sets the current via size list index to \a aIndex. + * + * @param aIndex is the via size list index. + */ + void SetViaSizeIndex( unsigned aIndex ); + + /** + * Function GetCurrentViaSize + * @return the current via size, according to the selected options + * ( using the default netclass value or a preset/custom value ) + * the default netclass is always in m_TrackWidthList[0] + */ + int GetCurrentViaSize() const + { + if( m_useCustomTrackVia ) + return m_customViaSize.m_Diameter; + else + return m_ViasDimensionsList[m_viaSizeIndex].m_Diameter; + } + + /** + * Function SetCustomViaSize + * Sets custom size for via diameter (i.e. not available in netclasses or preset list). To have + * it returned with GetCurrentViaSize() you need to enable custom track & via sizes + * (UseCustomTrackViaSize()). + * @param aSize is the new drill diameter. + */ + void SetCustomViaSize( int aSize ) + { + m_customViaSize.m_Diameter = aSize; + } + + /** + * Function GetCustomViaSize + * @return Current custom size for the via diameter. + */ + int GetCustomViaSize() const + { + return m_customViaSize.m_Diameter; + } + + /** + * Function GetCurrentViaDrill + * @return the current via size, according to the selected options + * ( using the default netclass value or a preset/custom value ) + * the default netclass is always in m_TrackWidthList[0] + */ + int GetCurrentViaDrill() const; + + /** + * Function SetCustomViaDrill + * Sets custom size for via drill (i.e. not available in netclasses or preset list). To have + * it returned with GetCurrentViaDrill() you need to enable custom track & via sizes + * (UseCustomTrackViaSize()). + * @param aDrill is the new drill size. + */ + void SetCustomViaDrill( int aDrill ) + { + m_customViaSize.m_Drill = aDrill; + } + + /** + * Function GetCustomViaDrill + * @return Current custom size for the via drill. + */ + int GetCustomViaDrill() const + { + return m_customViaSize.m_Drill; + } + + // TODO microvia methods should go here + + /** + * Function UseCustomTrackViaSize + * Enables/disables custom track/via size settings. If enabled, values set with + * SetCustomTrackWidth()/SetCustomViaSize()/SetCustomViaDrill() are used for newly created + * tracks and vias. + * @param aEnabled decides if custom settings should be used for new tracks/vias. + */ + void UseCustomTrackViaSize( bool aEnabled ) + { + m_useCustomTrackVia = aEnabled; + } + + /** + * Function UseCustomTrackViaSize + * @return True if custom sizes of tracks & vias are enabled, false otherwise. + */ + bool UseCustomTrackViaSize() const + { + return m_useCustomTrackVia; + } + /** * Function GetVisibleLayers * returns a bit-mask of all the layers that are visible @@ -196,6 +385,23 @@ public: void SetBoardThickness( int aThickness ) { m_boardThickness = aThickness; } private: + /// Index for #m_ViasDimensionsList to select the current via size. + /// 0 is the index selection of the default value Netclass + unsigned m_viaSizeIndex; + + // Index for m_TrackWidthList to select the value. + /// 0 is the index selection of the default value Netclass + unsigned m_trackWidthIndex; + + ///> Use custom values for track/via sizes (not specified in net class nor in the size lists). + bool m_useCustomTrackVia; + + ///> Custom track width (used after UseCustomTrackViaSize( true ) was called). + int m_customTrackWidth; + + ///> Custom via size (used after UseCustomTrackViaSize( true ) was called). + VIA_DIMENSION m_customViaSize; + int m_CopperLayerCount; ///< Number of copper layers for this design LAYER_MSK m_EnabledLayers; ///< Bit-mask for layer enabling LAYER_MSK m_VisibleLayers; ///< Bit-mask for layer visibility diff --git a/pcbnew/autorouter/solve.cpp b/pcbnew/autorouter/solve.cpp index 8ddf52f040..9da2804e9f 100644 --- a/pcbnew/autorouter/solve.cpp +++ b/pcbnew/autorouter/solve.cpp @@ -428,7 +428,7 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, result = NOSUCCESS; - marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentTrackWidth() / 2 ); + marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 ); /* clear direction flags */ i = RoutingMatrix.m_Nrows * RoutingMatrix.m_Ncols * sizeof(DIR_CELL); @@ -1174,7 +1174,7 @@ static void OrCell_Trace( BOARD* pcb, int col, int row, ( RoutingMatrix.m_GridRouting * col ))); g_CurrentTrackSegment->SetEnd( g_CurrentTrackSegment->GetStart() ); - g_CurrentTrackSegment->SetWidth( pcb->GetCurrentViaSize() ); + g_CurrentTrackSegment->SetWidth( pcb->GetDesignSettings().GetCurrentViaSize() ); newVia->SetViaType( pcb->GetDesignSettings().m_CurrentViaType ); g_CurrentTrackSegment->SetNetCode( current_net_code ); @@ -1233,7 +1233,7 @@ static void OrCell_Trace( BOARD* pcb, int col, int row, } } - g_CurrentTrackSegment->SetWidth( pcb->GetCurrentTrackWidth() ); + g_CurrentTrackSegment->SetWidth( pcb->GetDesignSettings().GetCurrentTrackWidth() ); if( g_CurrentTrackSegment->GetStart() != g_CurrentTrackSegment->GetEnd() ) { @@ -1275,8 +1275,8 @@ static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) EDA_DRAW_PANEL* panel = pcbframe->GetCanvas(); PCB_SCREEN* screen = pcbframe->GetScreen(); - marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentTrackWidth() / 2 ); - via_marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentViaSize() / 2 ); + marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 ); + via_marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentViaSize() / 2 ); dx1 = g_CurrentTrackSegment->GetEnd().x - g_CurrentTrackSegment->GetStart().x; dy1 = g_CurrentTrackSegment->GetEnd().y - g_CurrentTrackSegment->GetStart().y; diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 81399f456f..c5784848d7 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -94,8 +94,8 @@ BOARD::BOARD() : m_NetClasses.GetDefault()->SetDescription( _( "This is the default net class." ) ); - m_viaSizeIndex = 0; - m_trackWidthIndex = 0; + m_designSettings.SetViaSizeIndex( 0 ); + m_designSettings.SetTrackWidthIndex( 0 ); /* Dick 5-Feb-2012: this seems unnecessary. I don't believe the comment near line 70 of class_netclass.cpp. I stepped through with debugger. @@ -107,10 +107,10 @@ BOARD::BOARD() : SetCurrentNetClass( m_NetClasses.GetDefault()->GetName() ); // Set sensible initial values for custom track width & via size - m_useCustomTrackVia = false; - m_customTrackWidth = GetCurrentTrackWidth(); - m_customViaSize.m_Diameter = GetCurrentViaSize(); - m_customViaSize.m_Drill = GetCurrentViaDrill(); + m_designSettings.UseCustomTrackViaSize( false ); + m_designSettings.SetCustomTrackWidth( m_designSettings.GetCurrentTrackWidth() ); + m_designSettings.SetCustomViaSize( m_designSettings.GetCurrentViaSize() ); + m_designSettings.SetCustomViaDrill( m_designSettings.GetCurrentViaDrill() ); // Initialize ratsnest m_ratsnest = new RN_DATA( this ); @@ -331,37 +331,37 @@ bool BOARD::SetCurrentNetClass( const wxString& aNetClassName ) m_currentNetClassName = netClass->GetName(); // Initialize others values: - if( m_ViasDimensionsList.size() == 0 ) + if( m_designSettings.m_ViasDimensionsList.size() == 0 ) { VIA_DIMENSION viadim; lists_sizes_modified = true; - m_ViasDimensionsList.push_back( viadim ); + m_designSettings.m_ViasDimensionsList.push_back( viadim ); } - if( m_TrackWidthList.size() == 0 ) + if( m_designSettings.m_TrackWidthList.size() == 0 ) { lists_sizes_modified = true; - m_TrackWidthList.push_back( 0 ); + m_designSettings.m_TrackWidthList.push_back( 0 ); } /* note the m_ViasDimensionsList[0] and m_TrackWidthList[0] values * are always the Netclass values */ - if( m_ViasDimensionsList[0].m_Diameter != netClass->GetViaDiameter() ) + if( m_designSettings.m_ViasDimensionsList[0].m_Diameter != netClass->GetViaDiameter() ) lists_sizes_modified = true; - m_ViasDimensionsList[0].m_Diameter = netClass->GetViaDiameter(); + m_designSettings.m_ViasDimensionsList[0].m_Diameter = netClass->GetViaDiameter(); - if( m_TrackWidthList[0] != netClass->GetTrackWidth() ) + if( m_designSettings.m_TrackWidthList[0] != netClass->GetTrackWidth() ) lists_sizes_modified = true; - m_TrackWidthList[0] = netClass->GetTrackWidth(); + m_designSettings.m_TrackWidthList[0] = netClass->GetTrackWidth(); - if( m_viaSizeIndex >= m_ViasDimensionsList.size() ) - m_viaSizeIndex = m_ViasDimensionsList.size(); + if( m_designSettings.GetViaSizeIndex() >= m_designSettings.m_ViasDimensionsList.size() ) + m_designSettings.SetViaSizeIndex( m_designSettings.m_ViasDimensionsList.size() ); - if( m_trackWidthIndex >= m_TrackWidthList.size() ) - m_trackWidthIndex = m_TrackWidthList.size(); + if( m_designSettings.GetTrackWidthIndex() >= m_designSettings.m_TrackWidthList.size() ) + m_designSettings.SetTrackWidthIndex( m_designSettings.m_TrackWidthList.size() ); return lists_sizes_modified; } @@ -2200,24 +2200,6 @@ TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS } -void BOARD::SetViaSizeIndex( unsigned aIndex ) -{ - if( aIndex >= m_ViasDimensionsList.size() ) - m_viaSizeIndex = m_ViasDimensionsList.size(); - else - m_viaSizeIndex = aIndex; -} - - -void BOARD::SetTrackWidthIndex( unsigned aIndex ) -{ - if( aIndex >= m_TrackWidthList.size() ) - m_trackWidthIndex = m_TrackWidthList.size(); - else - m_trackWidthIndex = aIndex; -} - - ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, LAYER_NUM aLayer, wxPoint aStartPointPosition, int aHatch ) { diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 7fc8987198..a728061ba0 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -111,8 +111,6 @@ public: /** The type of the layer */ LAYER_T m_Type; -// int m_Color; - /** * Function ShowType * converts a LAYER_T enum to a const char* @@ -136,52 +134,15 @@ private: }; -/** - * Struct VIA_DIMENSION - * is a small helper container to handle a stock of specific vias each with - * unique diameter and drill sizes in the BOARD class. - */ -struct VIA_DIMENSION -{ - int m_Diameter; // <= 0 means use Netclass via diameter - int m_Drill; // <= 0 means use Netclass via drill - - VIA_DIMENSION() - { - m_Diameter = 0; - m_Drill = 0; - } - - VIA_DIMENSION( int aDiameter, int aDrill ) - { - m_Diameter = aDiameter; - m_Drill = aDrill; - } - - bool operator == ( const VIA_DIMENSION& other ) const - { - return (m_Diameter == other.m_Diameter) && (m_Drill == other.m_Drill); - } - - bool operator < ( const VIA_DIMENSION& other ) const - { - if( m_Diameter != other.m_Diameter ) - return m_Diameter < other.m_Diameter; - - return m_Drill < other.m_Drill; - } -}; - - // Helper class to handle high light nets class HIGH_LIGHT_INFO { friend class BOARD; + protected: int m_netCode; // net selected for highlight (-1 when no net selected ) bool m_highLightOn; // highlight active -protected: void Clear() { m_netCode = -1; @@ -251,22 +212,6 @@ private: /// This is also the last used netclass after starting a track. wxString m_currentNetClassName; - /// Index for #m_ViasDimensionsList to select the current via size. - /// 0 is the index selection of the default value Netclass - unsigned m_viaSizeIndex; - - // Index for m_TrackWidthList to select the value. - unsigned m_trackWidthIndex; - - ///> Use custom values for track/via sizes (not specified in net class nor in the size lists). - bool m_useCustomTrackVia; - - ///> Custom track width (used after UseCustomTrackViaSize( true ) was called). - int m_customTrackWidth; - - ///> Custom via size (used after UseCustomTrackViaSize( true ) was called). - VIA_DIMENSION m_customViaSize; - /** * Function chainMarkedSegments * is used by MarkTrace() to set the BUSY flag of connected segments of the trace @@ -308,18 +253,6 @@ public: /// List of current netclasses. There is always the default netclass. NETCLASSES m_NetClasses; - // handling of vias and tracks size: - // the first value is always the value of the current NetClass - // The others values are extra values - - // The first value is the current netclass via size - /// Vias size and drill list - std::vector m_ViasDimensionsList; - - // The first value is the current netclass track width - /// Track width list - std::vector m_TrackWidthList; - BOARD(); ~BOARD(); @@ -647,7 +580,10 @@ public: * Function SetDesignSettings * @param aDesignSettings the new BOARD_DESIGN_SETTINGS to use */ - void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aDesignSettings ) { m_designSettings = aDesignSettings; } + void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aDesignSettings ) + { + m_designSettings = aDesignSettings; + } const PAGE_INFO& GetPageSettings() const { return m_paper; } void SetPageSettings( const PAGE_INFO& aPageSettings ) { m_paper = aPageSettings; } @@ -778,7 +714,6 @@ public: return m_FullRatsnest.size(); } - /** * Function GetNodesCount * @return the number of pads members of nets (i.e. with netcode > 0) @@ -1029,10 +964,9 @@ public: */ int SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount ); - /**************************************/ - /** - * Function relative to NetClasses: **/ - /**************************************/ + /************************************** + * Functions related to NetClasses: + **************************************/ /** * Function SynchronizeNetsAndNetClasses @@ -1065,144 +999,6 @@ public: */ int GetSmallestClearanceValue(); - /** - * Function GetTrackWidthIndex - * @return the current track width list index. - */ - unsigned GetTrackWidthIndex() const { return m_trackWidthIndex; } - - /** - * Function SetTrackWidthIndex - * sets the current track width list index to \a aIndex. - * - * @param aIndex is the track width list index. - */ - void SetTrackWidthIndex( unsigned aIndex ); - - /** - * Function GetCurrentTrackWidth - * @return the current track width, according to the selected options - * ( using the default netclass value or a preset/custom value ) - * the default netclass is always in m_TrackWidthList[0] - */ - int GetCurrentTrackWidth() const - { - if( m_useCustomTrackVia ) - return m_customTrackWidth; - else - return m_TrackWidthList[m_trackWidthIndex]; - } - - /** - * Function SetCustomTrackWidth - * Sets custom width for track (i.e. not available in netclasses or preset list). To have - * it returned with GetCurrentTrackWidth() you need to enable custom track & via sizes - * (UseCustomTrackViaSize()). - * @param aWidth is the new track width. - */ - void SetCustomTrackWidth( int aWidth ) - { - m_customTrackWidth = aWidth; - } - - /** - * Function GetCustomTrackWidth - * @return Current custom width for a track. - */ - int GetCustomTrackWidth() const - { - return m_customTrackWidth; - } - - /** - * Function GetViaSizeIndex - * @return the current via size list index. - */ - unsigned GetViaSizeIndex() const { return m_viaSizeIndex; } - - /** - * Function SetViaSizeIndex - * sets the current via size list index to \a aIndex. - * - * @param aIndex is the via size list index. - */ - void SetViaSizeIndex( unsigned aIndex ); - - /** - * Function GetCurrentViaSize - * @return the current via size, according to the selected options - * ( using the default netclass value or a preset/custom value ) - * the default netclass is always in m_TrackWidthList[0] - */ - int GetCurrentViaSize() - { - if( m_useCustomTrackVia ) - return m_customViaSize.m_Diameter; - else - return m_ViasDimensionsList[m_viaSizeIndex].m_Diameter; - } - - /** - * Function SetCustomViaSize - * Sets custom size for via diameter (i.e. not available in netclasses or preset list). To have - * it returned with GetCurrentViaSize() you need to enable custom track & via sizes - * (UseCustomTrackViaSize()). - * @param aSize is the new drill diameter. - */ - void SetCustomViaSize( int aSize ) - { - m_customViaSize.m_Diameter = aSize; - } - - /** - * Function GetCustomViaSize - * @return Current custom size for the via diameter. - */ - int GetCustomViaSize() const - { - return m_customViaSize.m_Diameter; - } - - - /** - * Function GetCurrentViaDrill - * @return the current via size, according to the selected options - * ( using the default netclass value or a preset/custom value ) - * the default netclass is always in m_TrackWidthList[0] - */ - int GetCurrentViaDrill() - { - int drill; - - if( m_useCustomTrackVia ) - drill = m_customViaSize.m_Drill; - else - drill = m_ViasDimensionsList[m_viaSizeIndex].m_Drill; - - return drill > 0 ? drill : -1; - } - - /** - * Function SetCustomViaDrill - * Sets custom size for via drill (i.e. not available in netclasses or preset list). To have - * it returned with GetCurrentViaDrill() you need to enable custom track & via sizes - * (UseCustomTrackViaSize()). - * @param aDrill is the new drill size. - */ - void SetCustomViaDrill( int aDrill ) - { - m_customViaSize.m_Drill = aDrill; - } - - /** - * Function GetCustomViaDrill - * @return Current custom size for the via drill. - */ - int GetCustomViaDrill() const - { - return m_customViaSize.m_Drill; - } - /** * Function GetCurrentMicroViaSize * @return the current micro via size, @@ -1217,27 +1013,6 @@ public: */ int GetCurrentMicroViaDrill(); - /** - * Function UseCustomTrackViaSize - * Enables/disables custom track/via size settings. If enabled, values set with - * SetCustomTrackWidth()/SetCustomViaSize()/SetCustomViaDrill() are used for newly created - * tracks and vias. - * @param aEnabled decides if custom settings should be used for new tracks/vias. - */ - void UseCustomTrackViaSize( bool aEnabled ) - { - m_useCustomTrackVia = aEnabled; - } - - /** - * Function UseCustomTrackViaSize - * @return True if custom sizes of tracks & vias are enabled, false otherwise. - */ - bool UseCustomTrackViaSize() const - { - return m_useCustomTrackVia; - } - /***************************************************************************/ wxString GetClass() const diff --git a/pcbnew/class_board_design_settings.cpp b/pcbnew/class_board_design_settings.cpp index 31ef22a23f..79fa3ce42f 100644 --- a/pcbnew/class_board_design_settings.cpp +++ b/pcbnew/class_board_design_settings.cpp @@ -81,7 +81,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() : m_PcbTextSize = wxSize( DEFAULT_TEXT_PCB_SIZE, DEFAULT_TEXT_PCB_SIZE ); // current Pcb (not module) Text size - m_TrackMinWidth = DMils2iu( 100 ); // track min value for width ((min copper size value + m_TrackMinWidth = DMils2iu( 100 ); // track min value for width (min copper size value) m_ViasMinSize = DMils2iu( 350 ); // vias (not micro vias) min diameter m_ViasMinDrill = DMils2iu( 200 ); // vias (not micro vias) min drill diameter m_MicroViasMinSize = DMils2iu( 200 ); // micro vias (not vias) min diameter @@ -171,6 +171,37 @@ void BOARD_DESIGN_SETTINGS::AppendConfigs( PARAM_CFG_ARRAY* aResult ) } +void BOARD_DESIGN_SETTINGS::SetViaSizeIndex( unsigned aIndex ) +{ + if( aIndex >= m_ViasDimensionsList.size() ) + m_viaSizeIndex = m_ViasDimensionsList.size(); + else + m_viaSizeIndex = aIndex; +} + + +int BOARD_DESIGN_SETTINGS::GetCurrentViaDrill() const +{ + int drill; + + if( m_useCustomTrackVia ) + drill = m_customViaSize.m_Drill; + else + drill = m_ViasDimensionsList[m_viaSizeIndex].m_Drill; + + return drill > 0 ? drill : -1; +} + + +void BOARD_DESIGN_SETTINGS::SetTrackWidthIndex( unsigned aIndex ) +{ + if( aIndex >= m_TrackWidthList.size() ) + m_trackWidthIndex = m_TrackWidthList.size(); + else + m_trackWidthIndex = aIndex; +} + + // see pcbstruct.h LAYER_MSK BOARD_DESIGN_SETTINGS::GetVisibleLayers() const { diff --git a/pcbnew/dialogs/dialog_design_rules.cpp b/pcbnew/dialogs/dialog_design_rules.cpp index f83be84b9e..35b687de13 100644 --- a/pcbnew/dialogs/dialog_design_rules.cpp +++ b/pcbnew/dialogs/dialog_design_rules.cpp @@ -276,9 +276,9 @@ void DIALOG_DESIGN_RULES::InitGlobalRules() // Initialize Vias and Tracks sizes lists. // note we display only extra values, never the current netclass value. // (the first value in history list) - m_TracksWidthList = m_Parent->GetBoard()->m_TrackWidthList; + m_TracksWidthList = m_BrdSettings.m_TrackWidthList; m_TracksWidthList.erase( m_TracksWidthList.begin() ); // remove the netclass value - m_ViasDimensionsList = m_Parent->GetBoard()->m_ViasDimensionsList; + m_ViasDimensionsList = m_BrdSettings.m_ViasDimensionsList; m_ViasDimensionsList.erase( m_ViasDimensionsList.begin() ); // remove the netclass value InitDimensionsLists(); } @@ -634,12 +634,12 @@ void DIALOG_DESIGN_RULES::CopyDimensionsListsToBoard() // Sort new list by by increasing value sort( m_ViasDimensionsList.begin(), m_ViasDimensionsList.end() ); - std::vector * tlist = &m_Parent->GetBoard()->m_TrackWidthList; + std::vector* tlist = &m_BrdSettings.m_TrackWidthList; tlist->erase( tlist->begin() + 1, tlist->end() ); // Remove old "custom" sizes tlist->insert( tlist->end(), m_TracksWidthList.begin(), m_TracksWidthList.end() ); //Add new "custom" sizes // Reinitialize m_ViaSizeList - std::vector * vialist = &m_Parent->GetBoard()->m_ViasDimensionsList; + std::vector* vialist = &m_BrdSettings.m_ViasDimensionsList; vialist->erase( vialist->begin() + 1, vialist->end() ); vialist->insert( vialist->end(), m_ViasDimensionsList.begin(), m_ViasDimensionsList.end() ); } diff --git a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp index 02577075cd..71904a927e 100644 --- a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp @@ -60,7 +60,7 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit() /* Disable the option "copy current to net" if we have only default netclass values * i.e. when m_TrackWidthSelector and m_ViaSizeSelector are set to 0 */ - if( !board->GetTrackWidthIndex() && !board->GetViaSizeIndex() ) + if( !board->GetDesignSettings().GetTrackWidthIndex() && !board->GetDesignSettings().GetViaSizeIndex() ) { m_Net2CurrValueButton->Enable( false ); m_OptionID = ID_NETCLASS_VALUES_TO_CURRENT_NET; @@ -77,9 +77,9 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit() msg = StringFromValue( g_UserUnit, value, true ); m_gridDisplayCurrentSettings->SetCellValue( 0, 0, msg ); - if( board->GetTrackWidthIndex() ) + if( board->GetDesignSettings().GetTrackWidthIndex() ) { - value = board->GetCurrentTrackWidth(); + value = board->GetDesignSettings().GetCurrentTrackWidth(); msg = StringFromValue( g_UserUnit, value, true ); } else @@ -91,9 +91,9 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit() msg = StringFromValue( g_UserUnit, value, true ); m_gridDisplayCurrentSettings->SetCellValue( 0, 1, msg ); - if( board->GetViaSizeIndex() ) + if( board->GetDesignSettings().GetViaSizeIndex() ) { - value = board->GetCurrentViaSize(); + value = board->GetDesignSettings().GetCurrentViaSize(); msg = StringFromValue( g_UserUnit, value, true ); } else @@ -103,7 +103,7 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit() value = netclass->GetViaDrill(); // Display via drill msg = StringFromValue( g_UserUnit, value, true ); m_gridDisplayCurrentSettings->SetCellValue( 0, 2, msg ); - value = board->GetCurrentViaDrill(); + value = board->GetDesignSettings().GetCurrentViaDrill(); if( value >= 0 ) msg = StringFromValue( g_UserUnit, value, true ); else diff --git a/pcbnew/edit_track_width.cpp b/pcbnew/edit_track_width.cpp index c371ee0978..f19c8216e1 100644 --- a/pcbnew/edit_track_width.cpp +++ b/pcbnew/edit_track_width.cpp @@ -43,7 +43,7 @@ bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem, if( net ) new_width = net->GetTrackWidth(); else - new_width = GetBoard()->GetCurrentTrackWidth(); + new_width = GetDesignSettings().GetCurrentTrackWidth(); if( aTrackItem->Type() == PCB_VIA_T ) { @@ -58,8 +58,8 @@ bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem, } else { - new_width = GetBoard()->GetCurrentViaSize(); - new_drill = GetBoard()->GetCurrentViaDrill(); + new_width = GetDesignSettings().GetCurrentViaSize(); + new_drill = GetDesignSettings().GetCurrentViaDrill(); } if( via->GetViaType() == VIA_MICROVIA ) diff --git a/pcbnew/editrack-part2.cpp b/pcbnew/editrack-part2.cpp index ef7ed1642f..07967de9c9 100644 --- a/pcbnew/editrack-part2.cpp +++ b/pcbnew/editrack-part2.cpp @@ -98,7 +98,7 @@ bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC ) VIA* via = new VIA( GetBoard() ); via->SetFlags( IS_NEW ); via->SetViaType( GetDesignSettings().m_CurrentViaType ); - via->SetWidth( GetBoard()->GetCurrentViaSize()); + via->SetWidth( GetDesignSettings().GetCurrentViaSize()); via->SetNetCode( GetBoard()->GetHighLightNetCode() ); via->SetEnd( g_CurrentTrackSegment->GetEnd() ); via->SetStart( g_CurrentTrackSegment->GetEnd() ); @@ -106,7 +106,7 @@ bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC ) // Usual via is from copper to component. // layer pair is LAYER_N_BACK and LAYER_N_FRONT. via->SetLayerPair( LAYER_N_BACK, LAYER_N_FRONT ); - via->SetDrill( GetBoard()->GetCurrentViaDrill() ); + via->SetDrill( GetDesignSettings().GetCurrentViaDrill() ); LAYER_NUM first_layer = GetActiveLayer(); LAYER_NUM last_layer; diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index 220668148c..ddd1356705 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -170,9 +170,9 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) GetBoard()->SetCurrentNetClass( g_CurrentTrackSegment->GetNetClassName() ); g_CurrentTrackSegment->SetLayer( GetScreen()->m_Active_Layer ); - g_CurrentTrackSegment->SetWidth( GetBoard()->GetCurrentTrackWidth() ); + g_CurrentTrackSegment->SetWidth( GetDesignSettings().GetCurrentTrackWidth() ); - if( GetBoard()->GetDesignSettings().m_UseConnectedTrackWidth ) + if( GetDesignSettings().m_UseConnectedTrackWidth ) { if( TrackOnStartPoint && TrackOnStartPoint->Type() == PCB_TRACE_T ) g_CurrentTrackSegment->SetWidth( TrackOnStartPoint->GetWidth()); @@ -282,8 +282,8 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) newTrack->SetLayer( GetScreen()->m_Active_Layer ); - if( !GetBoard()->GetDesignSettings().m_UseConnectedTrackWidth ) - newTrack->SetWidth( GetBoard()->GetCurrentTrackWidth() ); + if( !GetDesignSettings().m_UseConnectedTrackWidth ) + newTrack->SetWidth( GetDesignSettings().GetCurrentTrackWidth() ); DBG( g_CurrentTrackList.VerifyListIntegrity(); ); @@ -691,7 +691,7 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo DisplayOpt.ShowTrackClearanceMode = SHOW_CLEARANCE_ALWAYS; // Values to Via circle - int boardViaRadius = frame->GetBoard()->GetCurrentViaSize()/2; + int boardViaRadius = frame->GetDesignSettings().GetCurrentViaSize()/2; int viaRadiusWithClearence = boardViaRadius+netclass->GetClearance(); EDA_RECT* panelClipBox=aPanel->GetClipBox(); @@ -718,8 +718,8 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo // Set track parameters, that can be modified while creating the track g_CurrentTrackSegment->SetLayer( screen->m_Active_Layer ); - if( !frame->GetBoard()->GetDesignSettings().m_UseConnectedTrackWidth ) - g_CurrentTrackSegment->SetWidth( frame->GetBoard()->GetCurrentTrackWidth() ); + if( !frame->GetDesignSettings().m_UseConnectedTrackWidth ) + g_CurrentTrackSegment->SetWidth( frame->GetDesignSettings().GetCurrentTrackWidth() ); if( g_TwoSegmentTrackBuild ) { @@ -729,8 +729,8 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo { previous_track->SetLayer( screen->m_Active_Layer ); - if( !frame->GetBoard()->GetDesignSettings().m_UseConnectedTrackWidth ) - previous_track->SetWidth( frame->GetBoard()->GetCurrentTrackWidth() ); + if( !frame->GetDesignSettings().m_UseConnectedTrackWidth ) + previous_track->SetWidth( frame->GetDesignSettings().GetCurrentTrackWidth() ); } } diff --git a/pcbnew/event_handlers_tracks_vias_sizes.cpp b/pcbnew/event_handlers_tracks_vias_sizes.cpp index 52428a3834..0ccd13a6a5 100644 --- a/pcbnew/event_handlers_tracks_vias_sizes.cpp +++ b/pcbnew/event_handlers_tracks_vias_sizes.cpp @@ -41,8 +41,8 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) case ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES: GetDesignSettings().m_UseConnectedTrackWidth = false; - GetBoard()->SetTrackWidthIndex( 0 ); - GetBoard()->SetViaSizeIndex( 0 ); + GetDesignSettings().SetTrackWidthIndex( 0 ); + GetDesignSettings().SetViaSizeIndex( 0 ); break; case ID_POPUP_PCB_SELECT_AUTO_WIDTH: @@ -69,7 +69,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) m_canvas->MoveCursorToCrossHair(); GetDesignSettings().m_UseConnectedTrackWidth = false; ii = id - ID_POPUP_PCB_SELECT_WIDTH1; - GetBoard()->SetTrackWidthIndex( ii ); + GetDesignSettings().SetTrackWidthIndex( ii ); break; case ID_POPUP_PCB_SELECT_VIASIZE1: // this is the default Netclass selection @@ -91,17 +91,17 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) // select the new current value for via size (via diameter) m_canvas->MoveCursorToCrossHair(); ii = id - ID_POPUP_PCB_SELECT_VIASIZE1; - GetBoard()->SetViaSizeIndex( ii ); + GetDesignSettings().SetViaSizeIndex( ii ); break; case ID_AUX_TOOLBAR_PCB_TRACK_WIDTH: ii = m_SelTrackWidthBox->GetCurrentSelection(); - GetBoard()->SetTrackWidthIndex( ii ); + GetDesignSettings().SetTrackWidthIndex( ii ); break; case ID_AUX_TOOLBAR_PCB_VIA_SIZE: ii = m_SelViaSizeBox->GetCurrentSelection(); - GetBoard()->SetViaSizeIndex( ii ); + GetDesignSettings().SetViaSizeIndex( ii ); break; default: diff --git a/pcbnew/hotkeys_board_editor.cpp b/pcbnew/hotkeys_board_editor.cpp index 14931a0fa4..1cffe09577 100644 --- a/pcbnew/hotkeys_board_editor.cpp +++ b/pcbnew/hotkeys_board_editor.cpp @@ -199,10 +199,10 @@ void PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit if( GetCanvas()->IsMouseCaptured() ) GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false ); - if( GetBoard()->GetTrackWidthIndex() < GetBoard()->m_TrackWidthList.size() - 1 ) - GetBoard()->SetTrackWidthIndex( GetBoard()->GetTrackWidthIndex() + 1 ); + if( GetDesignSettings().GetTrackWidthIndex() < GetDesignSettings().m_TrackWidthList.size() - 1 ) + GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().GetTrackWidthIndex() + 1 ); else - GetBoard()->SetTrackWidthIndex( 0 ); + GetDesignSettings().SetTrackWidthIndex( 0 ); if( GetCanvas()->IsMouseCaptured() ) GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false ); @@ -213,10 +213,10 @@ void PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit if( GetCanvas()->IsMouseCaptured() ) GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false ); - if( GetBoard()->GetTrackWidthIndex() <= 0 ) - GetBoard()->SetTrackWidthIndex( GetBoard()->m_TrackWidthList.size() -1 ); + if( GetDesignSettings().GetTrackWidthIndex() <= 0 ) + GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().m_TrackWidthList.size() -1 ); else - GetBoard()->SetTrackWidthIndex( GetBoard()->GetTrackWidthIndex() - 1 ); + GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().GetTrackWidthIndex() - 1 ); if( GetCanvas()->IsMouseCaptured() ) GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false ); diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 5c4b280dda..fd2cf976dc 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -551,12 +551,12 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const // Save current default track width, for compatibility with older Pcbnew version; m_out->Print( aNestLevel+1, "(last_trace_width %s)\n", - FMTIU( aBoard->GetCurrentTrackWidth() ).c_str() ); + FMTIU( aBoard->GetDesignSettings().GetCurrentTrackWidth() ).c_str() ); // Save custom tracks width list (the first is not saved here: this is the netclass value - for( unsigned ii = 1; ii < aBoard->m_TrackWidthList.size(); ii++ ) + for( unsigned ii = 1; ii < aBoard->GetDesignSettings().m_TrackWidthList.size(); ii++ ) m_out->Print( aNestLevel+1, "(user_trace_width %s)\n", - FMTIU( aBoard->m_TrackWidthList[ii] ).c_str() ); + FMTIU( aBoard->GetDesignSettings().m_TrackWidthList[ii] ).c_str() ); m_out->Print( aNestLevel+1, "(trace_clearance %s)\n", FMTIU( aBoard->m_NetClasses.GetDefault()->GetClearance() ).c_str() ); @@ -587,10 +587,10 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const // Save custom vias diameters list (the first is not saved here: this is // the netclass value - for( unsigned ii = 1; ii < aBoard->m_ViasDimensionsList.size(); ii++ ) + for( unsigned ii = 1; ii < aBoard->GetDesignSettings().m_ViasDimensionsList.size(); ii++ ) m_out->Print( aNestLevel+1, "(user_via %s %s)\n", - FMTIU( aBoard->m_ViasDimensionsList[ii].m_Diameter ).c_str(), - FMTIU( aBoard->m_ViasDimensionsList[ii].m_Drill ).c_str() ); + FMTIU( aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Diameter ).c_str(), + FMTIU( aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Drill ).c_str() ); // for old versions compatibility: if( aBoard->GetDesignSettings().m_BlindBuriedViaAllowed ) diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index d94852db4c..cf0aca69fe 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -633,6 +633,8 @@ void LEGACY_PLUGIN::loadSHEET() void LEGACY_PLUGIN::loadSETUP() { NETCLASS* netclass_default = m_board->m_NetClasses.GetDefault(); + // TODO Orson: is it really necessary to first operate on a copy and then apply it? + // would not it be better to use reference here and apply all the changes instantly? BOARD_DESIGN_SETTINGS bds = m_board->GetDesignSettings(); ZONE_SETTINGS zs = m_board->GetZoneSettings(); char* line; @@ -692,7 +694,7 @@ void LEGACY_PLUGIN::loadSETUP() else if( TESTLINE( "TrackWidthList" ) ) { BIU tmp = biuParse( line + SZ( "TrackWidthList" ) ); - m_board->m_TrackWidthList.push_back( tmp ); + bds.m_TrackWidthList.push_back( tmp ); } else if( TESTLINE( "TrackClearence" ) ) @@ -754,7 +756,8 @@ void LEGACY_PLUGIN::loadSETUP() if( data ) // DRILL may not be present ? drill = biuParse( data ); - m_board->m_ViasDimensionsList.push_back( VIA_DIMENSION( diameter, drill ) ); + bds.m_ViasDimensionsList.push_back( VIA_DIMENSION( diameter, + drill ) ); } else if( TESTLINE( "ViaDrill" ) ) @@ -907,23 +910,24 @@ void LEGACY_PLUGIN::loadSETUP() * Sort lists by by increasing value and remove duplicates * (the first value is not tested, because it is the netclass value */ - sort( m_board->m_ViasDimensionsList.begin() + 1, m_board->m_ViasDimensionsList.end() ); - sort( m_board->m_TrackWidthList.begin() + 1, m_board->m_TrackWidthList.end() ); + BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings(); + sort( designSettings.m_ViasDimensionsList.begin() + 1, designSettings.m_ViasDimensionsList.end() ); + sort( designSettings.m_TrackWidthList.begin() + 1, designSettings.m_TrackWidthList.end() ); - for( unsigned ii = 1; ii < m_board->m_ViasDimensionsList.size() - 1; ii++ ) + for( unsigned ii = 1; ii < designSettings.m_ViasDimensionsList.size() - 1; ii++ ) { - if( m_board->m_ViasDimensionsList[ii] == m_board->m_ViasDimensionsList[ii + 1] ) + if( designSettings.m_ViasDimensionsList[ii] == designSettings.m_ViasDimensionsList[ii + 1] ) { - m_board->m_ViasDimensionsList.erase( m_board->m_ViasDimensionsList.begin() + ii ); + designSettings.m_ViasDimensionsList.erase( designSettings.m_ViasDimensionsList.begin() + ii ); ii--; } } - for( unsigned ii = 1; ii < m_board->m_TrackWidthList.size() - 1; ii++ ) + for( unsigned ii = 1; ii < designSettings.m_TrackWidthList.size() - 1; ii++ ) { - if( m_board->m_TrackWidthList[ii] == m_board->m_TrackWidthList[ii + 1] ) + if( designSettings.m_TrackWidthList[ii] == designSettings.m_TrackWidthList[ii + 1] ) { - m_board->m_TrackWidthList.erase( m_board->m_TrackWidthList.begin() + ii ); + designSettings.m_TrackWidthList.erase( designSettings.m_TrackWidthList.begin() + ii ); ii--; } } @@ -3005,11 +3009,12 @@ void LEGACY_PLUGIN::saveSETUP( const BOARD* aBoard ) const } // Save current default track width, for compatibility with older Pcbnew version; - fprintf( m_fp, "TrackWidth %s\n", fmtBIU( aBoard->GetCurrentTrackWidth() ).c_str() ); + fprintf( m_fp, "TrackWidth %s\n", + fmtBIU( aBoard->GetDesignSettings().GetCurrentTrackWidth() ).c_str() ); // Save custom tracks width list (the first is not saved here: this is the netclass value - for( unsigned ii = 1; ii < aBoard->m_TrackWidthList.size(); ii++ ) - fprintf( m_fp, "TrackWidthList %s\n", fmtBIU( aBoard->m_TrackWidthList[ii] ).c_str() ); + for( unsigned ii = 1; ii < aBoard->GetDesignSettings().m_TrackWidthList.size(); ii++ ) + fprintf( m_fp, "TrackWidthList %s\n", fmtBIU( aBoard->GetDesignSettings().m_TrackWidthList[ii] ).c_str() ); fprintf( m_fp, "TrackClearence %s\n", fmtBIU( netclass_default->GetClearance() ).c_str() ); @@ -3030,10 +3035,10 @@ void LEGACY_PLUGIN::saveSETUP( const BOARD* aBoard ) const // Save custom vias diameters list (the first is not saved here: this is // the netclass value - for( unsigned ii = 1; ii < aBoard->m_ViasDimensionsList.size(); ii++ ) + for( unsigned ii = 1; ii < aBoard->GetDesignSettings().m_ViasDimensionsList.size(); ii++ ) fprintf( m_fp, "ViaSizeList %s %s\n", - fmtBIU( aBoard->m_ViasDimensionsList[ii].m_Diameter ).c_str(), - fmtBIU( aBoard->m_ViasDimensionsList[ii].m_Drill ).c_str() ); + fmtBIU( aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Diameter ).c_str(), + fmtBIU( aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Drill ).c_str() ); // for old versions compatibility: fprintf( m_fp, "MicroViaSize %s\n", fmtBIU( netclass_default->GetuViaDiameter() ).c_str() ); diff --git a/pcbnew/muonde.cpp b/pcbnew/muonde.cpp index f943b13c42..ba2be9e2b4 100644 --- a/pcbnew/muonde.cpp +++ b/pcbnew/muonde.cpp @@ -215,7 +215,7 @@ MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC ) } // Calculate the elements. - Mself.m_Width = GetBoard()->GetCurrentTrackWidth(); + Mself.m_Width = GetDesignSettings().GetCurrentTrackWidth(); std::vector buffer; ll = BuildCornersList_S_Shape( buffer, Mself.m_Start, Mself.m_End, Mself.lng, Mself.m_Width ); @@ -561,7 +561,7 @@ MODULE* PCB_EDIT_FRAME::Create_MuWaveBasicShape( const wxString& name, int pad_c module->Pads().PushFront( pad ); - int tw = GetBoard()->GetCurrentTrackWidth(); + int tw = GetDesignSettings().GetCurrentTrackWidth(); pad->SetSize( wxSize( tw, tw ) ); pad->SetPosition( module->GetPosition() ); @@ -588,7 +588,7 @@ MODULE* PCB_EDIT_FRAME::Create_MuWaveComponent( int shape_type ) int angle = 0; // Enter the size of the gap or stub - int gap_size = GetBoard()->GetCurrentTrackWidth(); + int gap_size = GetDesignSettings().GetCurrentTrackWidth(); switch( shape_type ) { @@ -1104,7 +1104,7 @@ void PCB_EDIT_FRAME::Edit_Gap( wxDC* DC, MODULE* aModule ) gap_size = ValueFromString( g_UserUnit, msg ); // Updating sizes of pads forming the gap. - int tw = GetBoard()->GetCurrentTrackWidth(); + int tw = GetDesignSettings().GetCurrentTrackWidth(); pad->SetSize( wxSize( tw, tw ) ); pad->SetY0( 0 ); @@ -1118,7 +1118,7 @@ void PCB_EDIT_FRAME::Edit_Gap( wxDC* DC, MODULE* aModule ) pad->SetPosition( padpos ); - tw = GetBoard()->GetCurrentTrackWidth(); + tw = GetDesignSettings().GetCurrentTrackWidth(); next_pad->SetSize( wxSize( tw, tw ) ); next_pad->SetY0( 0 ); diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index 372538c1b1..ec8157d17e 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -532,7 +532,7 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu ) AddMenuItem( PopMenu, ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_THROUGH_VIA, msg, KiBitmap( select_w_layer_xpm ) ); - if( GetBoard()->GetDesignSettings().m_BlindBuriedViaAllowed ) + if( GetDesignSettings().m_BlindBuriedViaAllowed ) { msg = AddHotkeyName( _( "Place Blind/Buried Via" ), g_Board_Editor_Hokeys_Descr, HK_ADD_BLIND_BURIED_VIA ); @@ -957,17 +957,17 @@ static wxMenu* Append_Track_Width_List( BOARD* aBoard ) if( aBoard->GetDesignSettings().m_UseConnectedTrackWidth ) trackwidth_menu->Check( ID_POPUP_PCB_SELECT_AUTO_WIDTH, true ); - if( aBoard->GetViaSizeIndex() != 0 - || aBoard->GetTrackWidthIndex() != 0 + if( aBoard->GetDesignSettings().GetViaSizeIndex() != 0 + || aBoard->GetDesignSettings().GetTrackWidthIndex() != 0 || aBoard->GetDesignSettings().m_UseConnectedTrackWidth ) trackwidth_menu->Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Netclass Values" ), _( "Use track and via sizes from their Netclass values" ), true ); - for( unsigned ii = 0; ii < aBoard->m_TrackWidthList.size(); ii++ ) + for( unsigned ii = 0; ii < aBoard->GetDesignSettings().m_TrackWidthList.size(); ii++ ) { - value = StringFromValue( g_UserUnit, aBoard->m_TrackWidthList[ii], true ); + value = StringFromValue( g_UserUnit, aBoard->GetDesignSettings().m_TrackWidthList[ii], true ); msg.Printf( _( "Track %s" ), GetChars( value ) ); if( ii == 0 ) @@ -978,15 +978,16 @@ static wxMenu* Append_Track_Width_List( BOARD* aBoard ) trackwidth_menu->AppendSeparator(); - for( unsigned ii = 0; ii < aBoard->m_ViasDimensionsList.size(); ii++ ) + for( unsigned ii = 0; ii < aBoard->GetDesignSettings().m_ViasDimensionsList.size(); ii++ ) { - value = StringFromValue( g_UserUnit, aBoard->m_ViasDimensionsList[ii].m_Diameter, - true ); + value = StringFromValue( g_UserUnit, + aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Diameter, + true ); wxString drill = StringFromValue( g_UserUnit, - aBoard->m_ViasDimensionsList[ii].m_Drill, - true ); + aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Drill, + true ); - if( aBoard->m_ViasDimensionsList[ii].m_Drill <= 0 ) + if( aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Drill <= 0 ) { msg.Printf( _( "Via %s" ), GetChars( value ) ); } diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index bfa1ea337d..59ef3cb88f 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -809,6 +809,8 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) T token; NETCLASS* defaultNetclass = m_board->m_NetClasses.GetDefault(); + // TODO Orson: is it really necessary to first operate on a copy and then apply it? + // would not it be better to use reference here and apply all the changes instantly? BOARD_DESIGN_SETTINGS designSettings = m_board->GetDesignSettings(); ZONE_SETTINGS zoneSettings = m_board->GetZoneSettings(); @@ -827,7 +829,7 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) break; case T_user_trace_width: - m_board->m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) ); + designSettings.m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) ); NeedRIGHT(); break; @@ -885,7 +887,7 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) { int viaSize = parseBoardUnits( "user via size" ); int viaDrill = parseBoardUnits( "user via drill" ); - m_board->m_ViasDimensionsList.push_back( VIA_DIMENSION( viaSize, viaDrill ) ); + designSettings.m_ViasDimensionsList.push_back( VIA_DIMENSION( viaSize, viaDrill ) ); NeedRIGHT(); } break; diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp index ec4d07df7d..c115cbcc37 100644 --- a/pcbnew/tool_pcb.cpp +++ b/pcbnew/tool_pcb.cpp @@ -620,9 +620,9 @@ void PCB_EDIT_FRAME::updateTraceWidthSelectBox() m_SelTrackWidthBox->Clear(); - for( unsigned ii = 0; ii < GetBoard()->m_TrackWidthList.size(); ii++ ) + for( unsigned ii = 0; ii < GetDesignSettings().m_TrackWidthList.size(); ii++ ) { - msg = _( "Track " ) + CoordinateToString( GetBoard()->m_TrackWidthList[ii], true ); + msg = _( "Track " ) + CoordinateToString( GetDesignSettings().m_TrackWidthList[ii], true ); if( ii == 0 ) msg << _( " *" ); @@ -630,10 +630,10 @@ void PCB_EDIT_FRAME::updateTraceWidthSelectBox() m_SelTrackWidthBox->Append( msg ); } - if( GetBoard()->GetTrackWidthIndex() >= GetBoard()->m_TrackWidthList.size() ) - GetBoard()->SetTrackWidthIndex( 0 ); + if( GetDesignSettings().GetTrackWidthIndex() >= GetDesignSettings().m_TrackWidthList.size() ) + GetDesignSettings().SetTrackWidthIndex( 0 ); - m_SelTrackWidthBox->SetSelection( GetBoard()->GetTrackWidthIndex() ); + m_SelTrackWidthBox->SetSelection( GetDesignSettings().GetTrackWidthIndex() ); } @@ -646,14 +646,14 @@ void PCB_EDIT_FRAME::updateViaSizeSelectBox() m_SelViaSizeBox->Clear(); - for( unsigned ii = 0; ii < GetBoard()->m_ViasDimensionsList.size(); ii++ ) + for( unsigned ii = 0; ii < GetDesignSettings().m_ViasDimensionsList.size(); ii++ ) { msg = _( "Via " ); - msg << CoordinateToString( GetBoard()->m_ViasDimensionsList[ii].m_Diameter, true ); + msg << CoordinateToString( GetDesignSettings().m_ViasDimensionsList[ii].m_Diameter, true ); - if( GetBoard()->m_ViasDimensionsList[ii].m_Drill ) + if( GetDesignSettings().m_ViasDimensionsList[ii].m_Drill ) msg << wxT("/ ") - << CoordinateToString( GetBoard()->m_ViasDimensionsList[ii].m_Drill, true ); + << CoordinateToString( GetDesignSettings().m_ViasDimensionsList[ii].m_Drill, true ); if( ii == 0 ) msg << _( " *" ); @@ -661,10 +661,10 @@ void PCB_EDIT_FRAME::updateViaSizeSelectBox() m_SelViaSizeBox->Append( msg ); } - if( GetBoard()->GetViaSizeIndex() >= GetBoard()->m_ViasDimensionsList.size() ) - GetBoard()->SetViaSizeIndex( 0 ); + if( GetDesignSettings().GetViaSizeIndex() >= GetDesignSettings().m_ViasDimensionsList.size() ) + GetDesignSettings().SetViaSizeIndex( 0 ); - m_SelViaSizeBox->SetSelection( GetBoard()->GetViaSizeIndex() ); + m_SelViaSizeBox->SetSelection( GetDesignSettings().GetViaSizeIndex() ); } diff --git a/pcbnew/toolbars_update_user_interface.cpp b/pcbnew/toolbars_update_user_interface.cpp index 78b44145bb..b94bc75d59 100644 --- a/pcbnew/toolbars_update_user_interface.cpp +++ b/pcbnew/toolbars_update_user_interface.cpp @@ -55,15 +55,15 @@ void PCB_EDIT_FRAME::OnUpdateSelectTrackWidth( wxUpdateUIEvent& aEvent ) { if( aEvent.GetId() == ID_AUX_TOOLBAR_PCB_TRACK_WIDTH ) { - if( m_SelTrackWidthBox->GetSelection() != (int) GetBoard()->GetTrackWidthIndex() ) - m_SelTrackWidthBox->SetSelection( GetBoard()->GetTrackWidthIndex() ); + if( m_SelTrackWidthBox->GetSelection() != (int) GetDesignSettings().GetTrackWidthIndex() ) + m_SelTrackWidthBox->SetSelection( GetDesignSettings().GetTrackWidthIndex() ); } else { bool check = ( ( ( ID_POPUP_PCB_SELECT_WIDTH1 + - (int) GetBoard()->GetTrackWidthIndex() ) == aEvent.GetId() ) && - !GetDesignSettings().m_UseConnectedTrackWidth && - !GetBoard()->UseCustomTrackViaSize() ); + (int) GetDesignSettings().GetTrackWidthIndex() ) == aEvent.GetId() ) && + !GetDesignSettings().m_UseConnectedTrackWidth && + !GetDesignSettings().UseCustomTrackViaSize() ); aEvent.Check( check ); } @@ -73,13 +73,13 @@ void PCB_EDIT_FRAME::OnUpdateSelectTrackWidth( wxUpdateUIEvent& aEvent ) void PCB_EDIT_FRAME::OnUpdateSelectAutoTrackWidth( wxUpdateUIEvent& aEvent ) { aEvent.Check( GetDesignSettings().m_UseConnectedTrackWidth && - !GetBoard()->UseCustomTrackViaSize() ); + !GetDesignSettings().UseCustomTrackViaSize() ); } void PCB_EDIT_FRAME::OnUpdateSelectCustomTrackWidth( wxUpdateUIEvent& aEvent ) { - aEvent.Check( GetBoard()->UseCustomTrackViaSize() ); + aEvent.Check( GetDesignSettings().UseCustomTrackViaSize() ); } @@ -89,15 +89,15 @@ void PCB_EDIT_FRAME::OnUpdateSelectViaSize( wxUpdateUIEvent& aEvent ) if( aEvent.GetId() == ID_AUX_TOOLBAR_PCB_VIA_SIZE ) { - if( m_SelViaSizeBox->GetSelection() != (int) GetBoard()->GetViaSizeIndex() ) - m_SelViaSizeBox->SetSelection( GetBoard()->GetViaSizeIndex() ); + if( m_SelViaSizeBox->GetSelection() != (int) GetDesignSettings().GetViaSizeIndex() ) + m_SelViaSizeBox->SetSelection( GetDesignSettings().GetViaSizeIndex() ); } else { bool check = ( ( ( ID_POPUP_PCB_SELECT_VIASIZE1 + - (int) GetBoard()->GetViaSizeIndex() ) == aEvent.GetId() ) && + (int) GetDesignSettings().GetViaSizeIndex() ) == aEvent.GetId() ) && !GetDesignSettings().m_UseConnectedTrackWidth && - !GetBoard()->UseCustomTrackViaSize() ); + !GetDesignSettings().UseCustomTrackViaSize() ); aEvent.Check( check ); } diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index 378ae9a580..3fb689e71f 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -416,13 +416,13 @@ int PCBNEW_CONTROL::GridPrev( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::TrackWidthInc( TOOL_EVENT& aEvent ) { BOARD* board = getModel( PCB_T ); - int widthIndex = board->GetTrackWidthIndex() + 1; + int widthIndex = board->GetDesignSettings().GetTrackWidthIndex() + 1; - if( widthIndex >= (int) board->m_TrackWidthList.size() ) - widthIndex = board->m_TrackWidthList.size() - 1; + if( widthIndex >= (int) board->GetDesignSettings().m_TrackWidthList.size() ) + widthIndex = board->GetDesignSettings().m_TrackWidthList.size() - 1; - board->SetTrackWidthIndex( widthIndex ); - board->UseCustomTrackViaSize( false ); + board->GetDesignSettings().SetTrackWidthIndex( widthIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); wxUpdateUIEvent dummy; getEditFrame()->OnUpdateSelectTrackWidth( dummy ); @@ -437,13 +437,13 @@ int PCBNEW_CONTROL::TrackWidthInc( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::TrackWidthDec( TOOL_EVENT& aEvent ) { BOARD* board = getModel( PCB_T ); - int widthIndex = board->GetTrackWidthIndex() - 1; + int widthIndex = board->GetDesignSettings().GetTrackWidthIndex() - 1; if( widthIndex < 0 ) widthIndex = 0; - board->SetTrackWidthIndex( widthIndex ); - board->UseCustomTrackViaSize( false ); + board->GetDesignSettings().SetTrackWidthIndex( widthIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); wxUpdateUIEvent dummy; getEditFrame()->OnUpdateSelectTrackWidth( dummy ); @@ -458,13 +458,13 @@ int PCBNEW_CONTROL::TrackWidthDec( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::ViaSizeInc( TOOL_EVENT& aEvent ) { BOARD* board = getModel( PCB_T ); - int sizeIndex = board->GetViaSizeIndex() + 1; + int sizeIndex = board->GetDesignSettings().GetViaSizeIndex() + 1; - if( sizeIndex >= (int) board->m_ViasDimensionsList.size() ) - sizeIndex = board->m_ViasDimensionsList.size() - 1; + if( sizeIndex >= (int) board->GetDesignSettings().m_ViasDimensionsList.size() ) + sizeIndex = board->GetDesignSettings().m_ViasDimensionsList.size() - 1; - board->SetViaSizeIndex( sizeIndex ); - board->UseCustomTrackViaSize( false ); + board->GetDesignSettings().SetViaSizeIndex( sizeIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); wxUpdateUIEvent dummy; getEditFrame()->OnUpdateSelectViaSize( dummy ); @@ -479,13 +479,13 @@ int PCBNEW_CONTROL::ViaSizeInc( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::ViaSizeDec( TOOL_EVENT& aEvent ) { BOARD* board = getModel( PCB_T ); - int sizeIndex = board->GetViaSizeIndex() - 1; + int sizeIndex = board->GetDesignSettings().GetViaSizeIndex() - 1; if( sizeIndex < 0 ) sizeIndex = 0; - board->SetViaSizeIndex( sizeIndex ); - board->UseCustomTrackViaSize( false ); + board->GetDesignSettings().SetViaSizeIndex( sizeIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); wxUpdateUIEvent dummy; getEditFrame()->OnUpdateSelectViaSize( dummy ); From 5af454c28b7b673054702f372b84915028938686 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 42/68] Fixed namecase for private fields in BOARD_DESIGN_SETTINGS class. Moved a few one-liners of BOARD_DESIGN_SETTINGS class to the header file. --- include/class_board_design_settings.h | 32 ++++++++++-------- pcbnew/class_board_design_settings.cpp | 45 +++++++++----------------- 2 files changed, 35 insertions(+), 42 deletions(-) diff --git a/include/class_board_design_settings.h b/include/class_board_design_settings.h index 70ba89f4ae..9fce5db845 100644 --- a/include/class_board_design_settings.h +++ b/include/class_board_design_settings.h @@ -249,7 +249,10 @@ public: * returns a bit-mask of all the layers that are visible * @return int - the visible layers in bit-mapped form. */ - LAYER_MSK GetVisibleLayers() const; + LAYER_MSK GetVisibleLayers() const + { + return m_visibleLayers; + } /** * Function SetVisibleAlls @@ -263,7 +266,10 @@ public: * changes the bit-mask of visible layers * @param aMask = The new bit-mask of visible layers */ - void SetVisibleLayers( LAYER_MSK aMask ); + void SetVisibleLayers( LAYER_MSK aMask ) + { + m_visibleLayers = aMask & m_enabledLayers & FULL_LAYERS; + } /** * Function IsLayerVisible @@ -274,7 +280,7 @@ public: bool IsLayerVisible( LAYER_NUM aLayer ) const { // If a layer is disabled, it is automatically invisible - return m_VisibleLayers & m_EnabledLayers & GetLayerMask( aLayer ); + return m_visibleLayers & m_enabledLayers & GetLayerMask( aLayer ); } /** @@ -292,7 +298,7 @@ public: */ int GetVisibleElements() const { - return m_VisibleElements; + return m_visibleElements; } /** @@ -302,7 +308,7 @@ public: */ void SetVisibleElements( int aMask ) { - m_VisibleElements = aMask; + m_visibleElements = aMask; } /** @@ -317,7 +323,7 @@ public: { assert( aElementCategory >= 0 && aElementCategory < END_PCB_VISIBLE_LIST ); - return ( m_VisibleElements & ( 1 << aElementCategory ) ); + return ( m_visibleElements & ( 1 << aElementCategory ) ); } /** @@ -336,7 +342,7 @@ public: */ inline LAYER_MSK GetEnabledLayers() const { - return m_EnabledLayers; + return m_enabledLayers; } /** @@ -354,7 +360,7 @@ public: */ bool IsLayerEnabled( LAYER_NUM aLayer ) const { - return m_EnabledLayers & GetLayerMask( aLayer ); + return m_enabledLayers & GetLayerMask( aLayer ); } /** @@ -363,7 +369,7 @@ public: */ int GetCopperLayerCount() const { - return m_CopperLayerCount; + return m_copperLayerCount; } /** @@ -402,10 +408,10 @@ private: ///> Custom via size (used after UseCustomTrackViaSize( true ) was called). VIA_DIMENSION m_customViaSize; - int m_CopperLayerCount; ///< Number of copper layers for this design - LAYER_MSK m_EnabledLayers; ///< Bit-mask for layer enabling - LAYER_MSK m_VisibleLayers; ///< Bit-mask for layer visibility - int m_VisibleElements; ///< Bit-mask for element category visibility + int m_copperLayerCount; ///< Number of copper layers for this design + LAYER_MSK m_enabledLayers; ///< Bit-mask for layer enabling + LAYER_MSK m_visibleLayers; ///< Bit-mask for layer visibility + int m_visibleElements; ///< Bit-mask for element category visibility int m_boardThickness; ///< Board thickness for 3D viewer }; diff --git a/pcbnew/class_board_design_settings.cpp b/pcbnew/class_board_design_settings.cpp index 79fa3ce42f..a727c904f9 100644 --- a/pcbnew/class_board_design_settings.cpp +++ b/pcbnew/class_board_design_settings.cpp @@ -54,13 +54,13 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() : m_Pad_Master( NULL ) { - m_EnabledLayers = ALL_LAYERS; // All layers enabled at first. + m_enabledLayers = ALL_LAYERS; // All layers enabled at first. // SetCopperLayerCount() will adjust this. SetVisibleLayers( FULL_LAYERS ); // set all but hidden text as visible. - m_VisibleElements = ~( 1 << MOD_TEXT_INVISIBLE ); + m_visibleElements = ~( 1 << MOD_TEXT_INVISIBLE ); SetCopperLayerCount( 2 ); // Default design is a double sided board @@ -202,32 +202,19 @@ void BOARD_DESIGN_SETTINGS::SetTrackWidthIndex( unsigned aIndex ) } -// see pcbstruct.h -LAYER_MSK BOARD_DESIGN_SETTINGS::GetVisibleLayers() const -{ - return m_VisibleLayers; -} - - void BOARD_DESIGN_SETTINGS::SetVisibleAlls() { SetVisibleLayers( FULL_LAYERS ); - m_VisibleElements = -1; -} - - -void BOARD_DESIGN_SETTINGS::SetVisibleLayers( LAYER_MSK aMask ) -{ - m_VisibleLayers = aMask & m_EnabledLayers & FULL_LAYERS; + m_visibleElements = -1; } void BOARD_DESIGN_SETTINGS::SetLayerVisibility( LAYER_NUM aLayer, bool aNewState ) { if( aNewState && IsLayerEnabled( aLayer ) ) - m_VisibleLayers |= GetLayerMask( aLayer ); + m_visibleLayers |= GetLayerMask( aLayer ); else - m_VisibleLayers &= ~GetLayerMask( aLayer ); + m_visibleLayers &= ~GetLayerMask( aLayer ); } @@ -237,9 +224,9 @@ void BOARD_DESIGN_SETTINGS::SetElementVisibility( int aElementCategory, bool aNe return; if( aNewState ) - m_VisibleElements |= 1 << aElementCategory; + m_visibleElements |= 1 << aElementCategory; else - m_VisibleElements &= ~( 1 << aElementCategory ); + m_visibleElements &= ~( 1 << aElementCategory ); } @@ -247,17 +234,17 @@ void BOARD_DESIGN_SETTINGS::SetCopperLayerCount( int aNewLayerCount ) { // if( aNewLayerCount < 2 ) aNewLayerCount = 2; - m_CopperLayerCount = aNewLayerCount; + m_copperLayerCount = aNewLayerCount; // ensure consistency with the m_EnabledLayers member - m_EnabledLayers &= ~ALL_CU_LAYERS; - m_EnabledLayers |= LAYER_BACK; + m_enabledLayers &= ~ALL_CU_LAYERS; + m_enabledLayers |= LAYER_BACK; - if( m_CopperLayerCount > 1 ) - m_EnabledLayers |= LAYER_FRONT; + if( m_copperLayerCount > 1 ) + m_enabledLayers |= LAYER_FRONT; for( LAYER_NUM ii = LAYER_N_2; ii < aNewLayerCount - 1; ++ii ) - m_EnabledLayers |= GetLayerMask( ii ); + m_enabledLayers |= GetLayerMask( ii ); } @@ -266,13 +253,13 @@ void BOARD_DESIGN_SETTINGS::SetEnabledLayers( LAYER_MSK aMask ) // Back and front layers are always enabled. aMask |= LAYER_BACK | LAYER_FRONT; - m_EnabledLayers = aMask; + m_enabledLayers = aMask; // A disabled layer cannot be visible - m_VisibleLayers &= aMask; + m_visibleLayers &= aMask; // update m_CopperLayerCount to ensure its consistency with m_EnabledLayers - m_CopperLayerCount = LayerMaskCountSet( aMask & ALL_CU_LAYERS); + m_copperLayerCount = LayerMaskCountSet( aMask & ALL_CU_LAYERS); } From d9eb15c9fa7c00741565308c612f4bc6fb5b3850 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 43/68] Moved NETCLASSES to BOARD_DESIGN_SETTINGS. Most of the changes are just adding GetDesignSettings() before every occurence of m_NetClasses. More complex changes: class_netclass.cpp - NETCLASS does not store the pointer to the parent BOARD anymore. Added function SetParams( BOARD_DESIGN_SETTINGS& ). class_netclass.h - Removed GetTrackMinWidth(), GetViaMinDiameter(), GetViaMinDrill(), GetuViaMinDiameter(), GetuViaMinDrill() as they were refering to BOARD_DESIGN_SETTINGS anyway (they are not net class specific). kicad_plugin.cpp - filters out empty nets (that are anyway not saved) when storing net class information. Previously it was done in NETCLASS::Format() function. --- include/class_board_design_settings.h | 61 ++++++++ pcbnew/autorouter/routing_matrix.cpp | 2 +- pcbnew/autorouter/solve.cpp | 2 +- pcbnew/class_board.cpp | 112 +-------------- pcbnew/class_board.h | 65 --------- pcbnew/class_board_connected_item.cpp | 4 +- pcbnew/class_board_design_settings.cpp | 97 +++++++++++++ pcbnew/class_module.cpp | 2 +- pcbnew/class_netclass.cpp | 130 +++++------------- pcbnew/class_netclass.h | 50 ++++--- pcbnew/dialogs/dialog_design_rules.cpp | 67 ++++----- pcbnew/dialogs/dialog_design_rules.h | 2 +- .../dialog_global_edit_tracks_and_vias.cpp | 21 +-- pcbnew/dialogs/dialog_plot.cpp | 4 +- pcbnew/drc.cpp | 2 +- pcbnew/drc_clearance_test_functions.cpp | 7 +- pcbnew/eagle_plugin.cpp | 4 +- pcbnew/edit_track_width.cpp | 2 +- pcbnew/editrack.cpp | 2 +- pcbnew/files.cpp | 6 +- pcbnew/kicad_plugin.cpp | 107 ++++++++------ pcbnew/legacy_plugin.cpp | 16 +-- pcbnew/legacy_plugin.h | 2 +- pcbnew/onleftclick.cpp | 2 +- pcbnew/onrightclick.cpp | 6 +- pcbnew/pcb_parser.cpp | 18 +-- pcbnew/router/pns_router.cpp | 2 +- pcbnew/router/router_tool.cpp | 4 +- pcbnew/specctra_export.cpp | 9 +- ...nvert_brd_items_to_polygons_with_Boost.cpp | 2 +- ...ones_convert_to_polygons_aux_functions.cpp | 2 +- 31 files changed, 378 insertions(+), 434 deletions(-) diff --git a/include/class_board_design_settings.h b/include/class_board_design_settings.h index 9fce5db845..a22f3c5bb6 100644 --- a/include/class_board_design_settings.h +++ b/include/class_board_design_settings.h @@ -8,6 +8,7 @@ #include // NB_COLORS #include #include +#include #include /** @@ -61,6 +62,9 @@ public: /// Track width list std::vector m_TrackWidthList; + /// List of current netclasses. There is always the default netclass. + NETCLASSES m_NetClasses; + bool m_MicroViasAllowed; ///< true to allow micro vias bool m_BlindBuriedViaAllowed; ///< true to allow blind/buried vias VIATYPE_T m_CurrentViaType; ///< via type (VIA_BLIND_BURIED, VIA_THROUGH VIA_MICROVIA) @@ -97,6 +101,56 @@ public: BOARD_DESIGN_SETTINGS(); + /** + * Function SetCurrentNetClassName + * sets the current net class name to \a aName. + * + * @param aName is a reference to a wxString object containing the current net class name. + */ + void SetCurrentNetClassName( const wxString& aName ) { m_currentNetClassName = aName; } + + /** + * Function GetCurrentNetClassName + * @return the current net class name. + */ + const wxString& GetCurrentNetClassName() const { return m_currentNetClassName; } + + /** + * Function SetCurrentNetClass + * Must be called after a netclass selection (or after a netclass parameter change + * Initialize vias and tracks values displayed in comb boxes of the auxiliary toolbar + * and some others parameters (netclass name ....) + * @param aNetClassName = the new netclass name + * @return true if lists of tracks and vias sizes are modified + */ + bool SetCurrentNetClass( const wxString& aNetClassName ); + + /** + * Function GetBiggestClearanceValue + * @return the biggest clearance value found in NetClasses list + */ + int GetBiggestClearanceValue(); + + /** + * Function GetSmallestClearanceValue + * @return the smallest clearance value found in NetClasses list + */ + int GetSmallestClearanceValue(); + + /** + * Function GetCurrentMicroViaSize + * @return the current micro via size, + * that is the current netclass value + */ + int GetCurrentMicroViaSize(); + + /** + * Function GetCurrentMicroViaDrill + * @return the current micro via drill, + * that is the current netclass value + */ + int GetCurrentMicroViaDrill(); + /** * Function GetTrackWidthIndex * @return the current track width list index. @@ -413,6 +467,13 @@ private: LAYER_MSK m_visibleLayers; ///< Bit-mask for layer visibility int m_visibleElements; ///< Bit-mask for element category visibility int m_boardThickness; ///< Board thickness for 3D viewer + + /// Current net class name used to display netclass info. + /// This is also the last used netclass after starting a track. + wxString m_currentNetClassName; + + void formatNetClass( NETCLASS* aNetClass, OUTPUTFORMATTER* aFormatter, int aNestLevel, + int aControlBits ) const throw( IO_ERROR ); }; #endif // BOARD_DESIGN_SETTINGS_H_ diff --git a/pcbnew/autorouter/routing_matrix.cpp b/pcbnew/autorouter/routing_matrix.cpp index 8449c90bc1..9d87b52bda 100644 --- a/pcbnew/autorouter/routing_matrix.cpp +++ b/pcbnew/autorouter/routing_matrix.cpp @@ -201,7 +201,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) LAYER_MSK layerMask; // use the default NETCLASS? - NETCLASS* nc = aPcb->m_NetClasses.GetDefault(); + NETCLASS* nc = aPcb->GetDesignSettings().m_NetClasses.GetDefault(); int trackWidth = nc->GetTrackWidth(); int clearance = nc->GetClearance(); diff --git a/pcbnew/autorouter/solve.cpp b/pcbnew/autorouter/solve.cpp index 9da2804e9f..c1f66b5423 100644 --- a/pcbnew/autorouter/solve.cpp +++ b/pcbnew/autorouter/solve.cpp @@ -280,7 +280,7 @@ int PCB_EDIT_FRAME::Solve( wxDC* DC, int aLayersCount ) m_canvas->SetAbortRequest( false ); - s_Clearance = GetBoard()->m_NetClasses.GetDefault()->GetClearance(); + s_Clearance = GetBoard()->GetDesignSettings().m_NetClasses.GetDefault()->GetClearance(); // Prepare the undo command info s_ItemsListPicker.ClearListAndDeleteItems(); // Should not be necessary, but... diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index c5784848d7..c05474d29f 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -66,8 +66,7 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 ); BOARD::BOARD() : BOARD_ITEM( (BOARD_ITEM*) NULL, PCB_T ), m_NetInfo( this ), - m_paper( PAGE_INFO::A4 ), - m_NetClasses( this ) + m_paper( PAGE_INFO::A4 ) { // we have not loaded a board yet, assume latest until then. m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION; @@ -92,19 +91,12 @@ BOARD::BOARD() : m_Layer[layer].m_Type = LT_UNDEFINED; } - m_NetClasses.GetDefault()->SetDescription( _( "This is the default net class." ) ); + NETCLASS* defaultClass = m_designSettings.m_NetClasses.GetDefault(); + defaultClass->SetDescription( _( "This is the default net class." ) ); - m_designSettings.SetViaSizeIndex( 0 ); - m_designSettings.SetTrackWidthIndex( 0 ); - - /* Dick 5-Feb-2012: this seems unnecessary. I don't believe the comment - near line 70 of class_netclass.cpp. I stepped through with debugger. - Perhaps something else is at work, it is not a constructor race. // Initialize default values in default netclass. - */ - m_NetClasses.GetDefault()->SetParams(); - - SetCurrentNetClass( m_NetClasses.GetDefault()->GetName() ); + defaultClass->SetParams( m_designSettings ); + m_designSettings.SetCurrentNetClass( defaultClass->GetName() ); // Set sensible initial values for custom track width & via size m_designSettings.UseCustomTrackViaSize( false ); @@ -319,100 +311,6 @@ void BOARD::PopHighLight() } -bool BOARD::SetCurrentNetClass( const wxString& aNetClassName ) -{ - NETCLASS* netClass = m_NetClasses.Find( aNetClassName ); - bool lists_sizes_modified = false; - - // if not found (should not happen) use the default - if( netClass == NULL ) - netClass = m_NetClasses.GetDefault(); - - m_currentNetClassName = netClass->GetName(); - - // Initialize others values: - if( m_designSettings.m_ViasDimensionsList.size() == 0 ) - { - VIA_DIMENSION viadim; - lists_sizes_modified = true; - m_designSettings.m_ViasDimensionsList.push_back( viadim ); - } - - if( m_designSettings.m_TrackWidthList.size() == 0 ) - { - lists_sizes_modified = true; - m_designSettings.m_TrackWidthList.push_back( 0 ); - } - - /* note the m_ViasDimensionsList[0] and m_TrackWidthList[0] values - * are always the Netclass values - */ - if( m_designSettings.m_ViasDimensionsList[0].m_Diameter != netClass->GetViaDiameter() ) - lists_sizes_modified = true; - - m_designSettings.m_ViasDimensionsList[0].m_Diameter = netClass->GetViaDiameter(); - - if( m_designSettings.m_TrackWidthList[0] != netClass->GetTrackWidth() ) - lists_sizes_modified = true; - - m_designSettings.m_TrackWidthList[0] = netClass->GetTrackWidth(); - - if( m_designSettings.GetViaSizeIndex() >= m_designSettings.m_ViasDimensionsList.size() ) - m_designSettings.SetViaSizeIndex( m_designSettings.m_ViasDimensionsList.size() ); - - if( m_designSettings.GetTrackWidthIndex() >= m_designSettings.m_TrackWidthList.size() ) - m_designSettings.SetTrackWidthIndex( m_designSettings.m_TrackWidthList.size() ); - - return lists_sizes_modified; -} - - -int BOARD::GetBiggestClearanceValue() -{ - int clearance = m_NetClasses.GetDefault()->GetClearance(); - - //Read list of Net Classes - for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ ) - { - NETCLASS* netclass = nc->second; - clearance = std::max( clearance, netclass->GetClearance() ); - } - - return clearance; -} - - -int BOARD::GetSmallestClearanceValue() -{ - int clearance = m_NetClasses.GetDefault()->GetClearance(); - - //Read list of Net Classes - for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ ) - { - NETCLASS* netclass = nc->second; - clearance = std::min( clearance, netclass->GetClearance() ); - } - - return clearance; -} - - -int BOARD::GetCurrentMicroViaSize() -{ - NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName ); - - return netclass->GetuViaDiameter(); -} - - -int BOARD::GetCurrentMicroViaDrill() -{ - NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName ); - - return netclass->GetuViaDrill(); -} - - bool BOARD::SetLayer( LAYER_NUM aIndex, const LAYER& aLayer ) { if( aIndex < NB_COPPER_LAYERS ) diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index a728061ba0..ccb3589ccf 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -208,10 +208,6 @@ private: /// Number of unconnected nets in the current rats nest. int m_unconnectedNetCount; - /// Current net class name used to display netclass info. - /// This is also the last used netclass after starting a track. - wxString m_currentNetClassName; - /** * Function chainMarkedSegments * is used by MarkTrace() to set the BUSY flag of connected segments of the trace @@ -223,10 +219,6 @@ private: */ void chainMarkedSegments( wxPoint aPosition, LAYER_MSK aLayerMask, TRACK_PTRS* aList ); - void formatNetClass( NETCLASS* aNetClass, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - public: void SetFileName( const wxString& aFileName ) { m_fileName = aFileName; } @@ -250,9 +242,6 @@ public: /// zone contour currently in progress ZONE_CONTAINER* m_CurrentZoneContour; - /// List of current netclasses. There is always the default netclass. - NETCLASSES m_NetClasses; - BOARD(); ~BOARD(); @@ -742,20 +731,6 @@ public: */ void SetUnconnectedNetCount( unsigned aCount ) { m_unconnectedNetCount = aCount; } - /** - * Function SetCurrentNetClassName - * sets the current net class name to \a aName. - * - * @param aName is a reference to a wxString object containing the current net class name. - */ - void SetCurrentNetClassName( const wxString& aName ) { m_currentNetClassName = aName; } - - /** - * Function GetCurrentNetClassName - * @return the current net class name. - */ - const wxString& GetCurrentNetClassName() const { return m_currentNetClassName; } - /** * Function GetPadCount * @return the number of pads in board @@ -964,10 +939,6 @@ public: */ int SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount ); - /************************************** - * Functions related to NetClasses: - **************************************/ - /** * Function SynchronizeNetsAndNetClasses * copies NETCLASS info to each NET, based on NET membership in a NETCLASS. @@ -977,42 +948,6 @@ public: */ void SynchronizeNetsAndNetClasses(); - /** - * Function SetCurrentNetClass - * Must be called after a netclass selection (or after a netclass parameter change - * Initialize vias and tracks values displayed in comb boxes of the auxiliary toolbar - * and some others parameters (netclass name ....) - * @param aNetClassName = the new netclass name - * @return true if lists of tracks and vias sizes are modified - */ - bool SetCurrentNetClass( const wxString& aNetClassName ); - - /** - * Function GetBiggestClearanceValue - * @return the biggest clearance value found in NetClasses list - */ - int GetBiggestClearanceValue(); - - /** - * Function GetSmallestClearanceValue - * @return the smallest clearance value found in NetClasses list - */ - int GetSmallestClearanceValue(); - - /** - * Function GetCurrentMicroViaSize - * @return the current micro via size, - * that is the current netclass value - */ - int GetCurrentMicroViaSize(); - - /** - * Function GetCurrentMicroViaDrill - * @return the current micro via drill, - * that is the current netclass value - */ - int GetCurrentMicroViaDrill(); - /***************************************************************************/ wxString GetClass() const diff --git a/pcbnew/class_board_connected_item.cpp b/pcbnew/class_board_connected_item.cpp index 0248131d35..9aaa6d14ad 100644 --- a/pcbnew/class_board_connected_item.cpp +++ b/pcbnew/class_board_connected_item.cpp @@ -144,7 +144,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const if( netclass ) return netclass; else - return board->m_NetClasses.GetDefault(); + return board->GetDesignSettings().m_NetClasses.GetDefault(); } @@ -158,7 +158,7 @@ wxString BOARD_CONNECTED_ITEM::GetNetClassName() const else { BOARD* board = GetBoard(); - name = board->m_NetClasses.GetDefault()->GetName(); + name = board->GetDesignSettings().m_NetClasses.GetDefault()->GetName(); } return name; diff --git a/pcbnew/class_board_design_settings.cpp b/pcbnew/class_board_design_settings.cpp index a727c904f9..aac977d827 100644 --- a/pcbnew/class_board_design_settings.cpp +++ b/pcbnew/class_board_design_settings.cpp @@ -102,6 +102,9 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() : // Layer thickness for 3D viewer m_boardThickness = Millimeter2iu( DEFAULT_BOARD_THICKNESS_MM ); + + m_viaSizeIndex = 0; + m_trackWidthIndex = 0; } // Add parameters to save in project config. @@ -171,6 +174,100 @@ void BOARD_DESIGN_SETTINGS::AppendConfigs( PARAM_CFG_ARRAY* aResult ) } +bool BOARD_DESIGN_SETTINGS::SetCurrentNetClass( const wxString& aNetClassName ) +{ + NETCLASS* netClass = m_NetClasses.Find( aNetClassName ); + bool lists_sizes_modified = false; + + // if not found (should not happen) use the default + if( netClass == NULL ) + netClass = m_NetClasses.GetDefault(); + + m_currentNetClassName = netClass->GetName(); + + // Initialize others values: + if( m_ViasDimensionsList.size() == 0 ) + { + VIA_DIMENSION viadim; + lists_sizes_modified = true; + m_ViasDimensionsList.push_back( viadim ); + } + + if( m_TrackWidthList.size() == 0 ) + { + lists_sizes_modified = true; + m_TrackWidthList.push_back( 0 ); + } + + /* note the m_ViasDimensionsList[0] and m_TrackWidthList[0] values + * are always the Netclass values + */ + if( m_ViasDimensionsList[0].m_Diameter != netClass->GetViaDiameter() ) + lists_sizes_modified = true; + + m_ViasDimensionsList[0].m_Diameter = netClass->GetViaDiameter(); + + if( m_TrackWidthList[0] != netClass->GetTrackWidth() ) + lists_sizes_modified = true; + + m_TrackWidthList[0] = netClass->GetTrackWidth(); + + if( GetViaSizeIndex() >= m_ViasDimensionsList.size() ) + SetViaSizeIndex( m_ViasDimensionsList.size() ); + + if( GetTrackWidthIndex() >= m_TrackWidthList.size() ) + SetTrackWidthIndex( m_TrackWidthList.size() ); + + return lists_sizes_modified; +} + + +int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue() +{ + int clearance = m_NetClasses.GetDefault()->GetClearance(); + + //Read list of Net Classes + for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ ) + { + NETCLASS* netclass = nc->second; + clearance = std::max( clearance, netclass->GetClearance() ); + } + + return clearance; +} + + +int BOARD_DESIGN_SETTINGS::GetSmallestClearanceValue() +{ + int clearance = m_NetClasses.GetDefault()->GetClearance(); + + //Read list of Net Classes + for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ ) + { + NETCLASS* netclass = nc->second; + clearance = std::min( clearance, netclass->GetClearance() ); + } + + return clearance; +} + + +int BOARD_DESIGN_SETTINGS::GetCurrentMicroViaSize() +{ + NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName ); + + return netclass->GetuViaDiameter(); +} + + +int BOARD_DESIGN_SETTINGS::GetCurrentMicroViaDrill() +{ + NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName ); + + return netclass->GetuViaDrill(); +} + + void BOARD_DESIGN_SETTINGS::SetViaSizeIndex( unsigned aIndex ) { if( aIndex >= m_ViasDimensionsList.size() ) diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index bc55907cb3..5673c06f2d 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -447,7 +447,7 @@ const EDA_RECT MODULE::GetBoundingBox() const // Add the Clearance shape size: (shape around the pads when the // clearance is shown. Not optimized, but the draw cost is small // (perhaps smaller than optimization). - int biggest_clearance = GetBoard()->GetBiggestClearanceValue(); + int biggest_clearance = GetBoard()->GetDesignSettings().GetBiggestClearanceValue(); area.Inflate( biggest_clearance ); return area; diff --git a/pcbnew/class_netclass.cpp b/pcbnew/class_netclass.cpp index 73729324ef..daa72ff32b 100644 --- a/pcbnew/class_netclass.cpp +++ b/pcbnew/class_netclass.cpp @@ -39,59 +39,43 @@ const wxChar NETCLASS::Default[] = wxT( "Default" ); // Initial values for netclass initialization -int NETCLASS::DEFAULT_CLEARANCE = DMils2iu( 100 ); // track to track and track to pads clearance -int NETCLASS::DEFAULT_VIA_DRILL = DMils2iu( 250 ); // default via drill -int NETCLASS::DEFAULT_UVIA_DRILL = DMils2iu( 50 ); // micro via drill +const int NETCLASS::DEFAULT_CLEARANCE = DMils2iu( 100 ); // track to track and track to pads clearance +const int NETCLASS::DEFAULT_VIA_DRILL = DMils2iu( 250 ); // default via drill +const int NETCLASS::DEFAULT_UVIA_DRILL = DMils2iu( 50 ); // micro via drill -NETCLASS::NETCLASS( BOARD* aParent, const wxString& aName, const NETCLASS* initialParameters ) : - m_Parent( aParent ), +NETCLASS::NETCLASS( const wxString& aName ) : m_Name( aName ) { - // use initialParameters if not NULL, else set the initial - // parameters from boardDesignSettings (try to change this) - SetParams( initialParameters ); + // Default settings + SetClearance( DEFAULT_CLEARANCE ); + SetViaDrill( DEFAULT_VIA_DRILL ); + SetuViaDrill( DEFAULT_UVIA_DRILL ); } -void NETCLASS::SetParams( const NETCLASS* defaults ) +void NETCLASS::SetParams( const NETCLASS& aDefaults ) { - if( defaults ) - { - SetClearance( defaults->GetClearance() ); - SetTrackWidth( defaults->GetTrackWidth() ); - SetViaDiameter( defaults->GetViaDiameter() ); - SetViaDrill( defaults->GetViaDrill() ); - SetuViaDiameter( defaults->GetuViaDiameter() ); - SetuViaDrill( defaults->GetuViaDrill() ); - } - else - { + SetClearance( aDefaults.GetClearance() ); + SetTrackWidth( aDefaults.GetTrackWidth() ); + SetViaDiameter( aDefaults.GetViaDiameter() ); + SetViaDrill( aDefaults.GetViaDrill() ); + SetuViaDiameter( aDefaults.GetuViaDiameter() ); + SetuViaDrill( aDefaults.GetuViaDrill() ); +} -/* Dick 5-Feb-2012: I do not believe this comment to be true with current code. - It is certainly not a constructor race. Normally items are initialized - within a class according to the order of their appearance. - // Note: - // We use m_Parent->GetDesignSettings() to get some default values - // But when this function is called when instantiating a BOARD class, - // by the NETCLASSES constructor that calls NETCLASS constructor, - // the BOARD constructor (see BOARD::BOARD) is not yet run, - // and BOARD::m_designSettings contains not yet initialized values. - // So inside the BOARD constructor itself, you SHOULD recall SetParams -*/ +void NETCLASS::SetParams( const BOARD_DESIGN_SETTINGS& aSettings ) +{ + SetTrackWidth( aSettings.m_TrackMinWidth ); + SetViaDiameter( aSettings.m_ViasMinSize ); + SetuViaDiameter( aSettings.m_MicroViasMinSize ); - const BOARD_DESIGN_SETTINGS& g = m_Parent->GetDesignSettings(); - - SetTrackWidth( g.m_TrackMinWidth ); - SetViaDiameter( g.m_ViasMinSize ); - SetuViaDiameter( g.m_MicroViasMinSize ); - - // Use default values for next parameters: - SetClearance( DEFAULT_CLEARANCE ); - SetViaDrill( DEFAULT_VIA_DRILL ); - SetuViaDrill( DEFAULT_UVIA_DRILL ); - } + // TODO: BOARD_DESIGN_SETTINGS may provide the following parameters - should it? + // Use default values for next parameters: + SetClearance( DEFAULT_CLEARANCE ); + SetViaDrill( DEFAULT_VIA_DRILL ); + SetuViaDrill( DEFAULT_UVIA_DRILL ); } @@ -100,9 +84,8 @@ NETCLASS::~NETCLASS() } -NETCLASSES::NETCLASSES( BOARD* aParent ) : - m_Parent( aParent ), - m_Default( aParent, NETCLASS::Default ) +NETCLASSES::NETCLASSES() : + m_Default( NETCLASS::Default ) { } @@ -198,7 +181,7 @@ NETCLASS* NETCLASSES::Find( const wxString& aName ) const void BOARD::SynchronizeNetsAndNetClasses() { - // D(printf("start\n");) // simple performance/timing indicator. + NETCLASSES& netClasses = m_designSettings.m_NetClasses; // set all NETs to the default NETCLASS, then later override some // as we go through the NETCLASSes. @@ -206,19 +189,19 @@ void BOARD::SynchronizeNetsAndNetClasses() for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() ); net != netEnd; ++net ) { - net->SetClass( m_NetClasses.GetDefault() ); + net->SetClass( netClasses.GetDefault() ); } // Add netclass name and pointer to nets. If a net is in more than one netclass, // set the net's name and pointer to only the first netclass. Subsequent // and therefore bogus netclass memberships will be deleted in logic below this loop. - for( NETCLASSES::iterator clazz=m_NetClasses.begin(); clazz!=m_NetClasses.end(); ++clazz ) + for( NETCLASSES::iterator clazz = netClasses.begin(); clazz != netClasses.end(); ++clazz ) { NETCLASS* netclass = clazz->second; - for( NETCLASS::iterator member = netclass->begin(); member!=netclass->end(); ++member ) + for( NETCLASS::iterator member = netclass->begin(); member != netclass->end(); ++member ) { - const wxString& netname = *member; + const wxString& netname = *member; // although this overall function seems to be adequately fast, // FindNet( wxString ) uses now a fast binary search and is fast @@ -237,14 +220,14 @@ void BOARD::SynchronizeNetsAndNetClasses() // contain netnames that do not exist, by deleting all netnames from // every netclass and re-adding them. - for( NETCLASSES::iterator clazz=m_NetClasses.begin(); clazz!=m_NetClasses.end(); ++clazz ) + for( NETCLASSES::iterator clazz = netClasses.begin(); clazz != netClasses.end(); ++clazz ) { NETCLASS* netclass = clazz->second; netclass->Clear(); } - m_NetClasses.GetDefault()->Clear(); + netClasses.GetDefault()->Clear(); for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() ); net != netEnd; ++net ) @@ -253,14 +236,12 @@ void BOARD::SynchronizeNetsAndNetClasses() // because of the std:map<> this should be fast, and because of // prior logic, netclass should not be NULL. - NETCLASS* netclass = m_NetClasses.Find( classname ); + NETCLASS* netclass = netClasses.Find( classname ); wxASSERT( netclass ); netclass->Add( net->GetNetname() ); } - - // D(printf("stop\n");) } @@ -286,36 +267,6 @@ void NETCLASS::Show( int nestLevel, std::ostream& os ) const #endif -int NETCLASS::GetTrackMinWidth() const -{ - return m_Parent->GetDesignSettings().m_TrackMinWidth; -} - - -int NETCLASS::GetViaMinDiameter() const -{ - return m_Parent->GetDesignSettings().m_ViasMinSize; -} - - -int NETCLASS::GetViaMinDrill() const -{ - return m_Parent->GetDesignSettings().m_ViasMinDrill; -} - - -int NETCLASS::GetuViaMinDiameter() const -{ - return m_Parent->GetDesignSettings().m_MicroViasMinSize; -} - - -int NETCLASS::GetuViaMinDrill() const -{ - return m_Parent->GetDesignSettings().m_MicroViasMinDrill; -} - - void NETCLASS::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ) { @@ -333,14 +284,7 @@ void NETCLASS::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControl aFormatter->Print( aNestLevel+1, "(uvia_drill %s)\n", FMT_IU( GetuViaDrill() ).c_str() ); for( NETCLASS::const_iterator it = begin(); it != end(); ++it ) - { - NETINFO_ITEM* netinfo = m_Parent->FindNet( *it ); - - if( netinfo && netinfo->GetNodesCount() > 0 ) - { - aFormatter->Print( aNestLevel+1, "(add_net %s)\n", aFormatter->Quotew( *it ).c_str() ); - } - } + aFormatter->Print( aNestLevel+1, "(add_net %s)\n", aFormatter->Quotew( *it ).c_str() ); aFormatter->Print( aNestLevel, ")\n\n" ); } diff --git a/pcbnew/class_netclass.h b/pcbnew/class_netclass.h index d5e0005357..7085b3ebe3 100644 --- a/pcbnew/class_netclass.h +++ b/pcbnew/class_netclass.h @@ -41,6 +41,7 @@ class LINE_READER; class BOARD; +class BOARD_DESIGN_SETTINGS; /** @@ -53,17 +54,15 @@ class NETCLASS { private: // Default values used to init a NETCLASS - static int DEFAULT_CLEARANCE; - static int DEFAULT_VIA_DRILL; - static int DEFAULT_UVIA_DRILL; + const static int DEFAULT_CLEARANCE; + const static int DEFAULT_VIA_DRILL; + const static int DEFAULT_UVIA_DRILL; protected: - - BOARD* m_Parent; wxString m_Name; ///< Name of the net class wxString m_Description; ///< what this NETCLASS is for. - typedef std::set STRINGSET; + typedef std::set STRINGSET; STRINGSET m_Members; ///< names of NET members of this class @@ -85,12 +84,9 @@ public: /** * Constructor * stuffs a NETCLASS instance with aParent, aName, and optionally the initialParameters - * @param aParent = the parent board * @param aName = the name of this new netclass - * @param initialParameters is a NETCLASS to copy parameters from, or if - * NULL tells me to copy default settings from BOARD::m_designSettings. */ - NETCLASS( BOARD* aParent, const wxString& aName, const NETCLASS* initialParameters = NULL ); + NETCLASS( const wxString& aName ); ~NETCLASS(); @@ -115,7 +111,6 @@ public: return m_Members.size(); } - /** * Function Clear * empties the collection of members. @@ -125,7 +120,6 @@ public: m_Members.clear(); } - /** * Function AddMember * adds \a aNetname to this NETCLASS if it is not already in this NETCLASS. @@ -169,34 +163,35 @@ public: void SetClearance( int aClearance ) { m_Clearance = aClearance; } int GetTrackWidth() const { return m_TrackWidth; } - int GetTrackMinWidth() const; void SetTrackWidth( int aWidth ) { m_TrackWidth = aWidth; } int GetViaDiameter() const { return m_ViaDia; } - int GetViaMinDiameter() const; void SetViaDiameter( int aDia ) { m_ViaDia = aDia; } int GetViaDrill() const { return m_ViaDrill; } - int GetViaMinDrill() const; void SetViaDrill( int aSize ) { m_ViaDrill = aSize; } int GetuViaDiameter() const { return m_uViaDia; } - int GetuViaMinDiameter() const; void SetuViaDiameter( int aSize ) { m_uViaDia = aSize; } int GetuViaDrill() const { return m_uViaDrill; } - int GetuViaMinDrill() const; void SetuViaDrill( int aSize ) { m_uViaDrill = aSize; } - /** * Function SetParams * will set all the parameters by copying them from \a defaults. * Parameters are the values like m_ViaSize, etc, but do not include m_Description. - * @param defaults is another NETCLASS to copy from. If NULL, then copy - * from global preferences instead. + * @param aDefaults is another NETCLASS object to copy from. */ - void SetParams( const NETCLASS* defaults = NULL ); + void SetParams( const NETCLASS& aDefaults ); + + /** + * Function SetParams + * will set all the parameters by copying them from board design settings. + * @param aSettings is a BOARD_DESIGN_SETTINGS object to copy from. Clearance, via drill and + * microvia drill values are taken from the defaults. + */ + void SetParams( const BOARD_DESIGN_SETTINGS& aSettings ); /** * Function Format @@ -225,9 +220,7 @@ public: class NETCLASSES { private: - BOARD* m_Parent; - - typedef std::map NETCLASSMAP; + typedef std::map NETCLASSMAP; /// all the NETCLASSes except the default one. NETCLASSMAP m_NetClasses; @@ -236,7 +229,7 @@ private: NETCLASS m_Default; public: - NETCLASSES( BOARD* aParent = NULL ); + NETCLASSES(); ~NETCLASSES(); /** @@ -245,7 +238,7 @@ public: */ void Clear(); - typedef NETCLASSMAP::iterator iterator; + typedef NETCLASSMAP::iterator iterator; iterator begin() { return m_NetClasses.begin(); } iterator end() { return m_NetClasses.end(); } @@ -253,7 +246,6 @@ public: const_iterator begin() const { return m_NetClasses.begin(); } const_iterator end() const { return m_NetClasses.end(); } - /** * Function GetCount * @return the number of netclasses, excluding the default one. @@ -263,6 +255,10 @@ public: return m_NetClasses.size(); } + /** + * Function GetDefault + * @return the default net class. + */ NETCLASS* GetDefault() const { return (NETCLASS*) &m_Default; diff --git a/pcbnew/dialogs/dialog_design_rules.cpp b/pcbnew/dialogs/dialog_design_rules.cpp index 35b687de13..13f6da13c9 100644 --- a/pcbnew/dialogs/dialog_design_rules.cpp +++ b/pcbnew/dialogs/dialog_design_rules.cpp @@ -190,15 +190,15 @@ void DIALOG_DESIGN_RULES::PrintCurrentSettings() m_MessagesList->AppendToPage( _( "Current general settings:
" ) ); // Display min values: - value = StringFromValue( g_UserUnit, m_BrdSettings.m_TrackMinWidth, true ); + value = StringFromValue( g_UserUnit, m_BrdSettings->m_TrackMinWidth, true ); msg.Printf( _( "Minimum value for tracks width: %s
\n" ), GetChars( value ) ); m_MessagesList->AppendToPage( msg ); - value = StringFromValue( g_UserUnit, m_BrdSettings.m_ViasMinSize, true ); + value = StringFromValue( g_UserUnit, m_BrdSettings->m_ViasMinSize, true ); msg.Printf( _( "Minimum value for vias diameter: %s
\n" ), GetChars( value ) ); m_MessagesList->AppendToPage( msg ); - value = StringFromValue( g_UserUnit, m_BrdSettings.m_MicroViasMinSize, true ); + value = StringFromValue( g_UserUnit, m_BrdSettings->m_MicroViasMinSize, true ); msg.Printf( _( "Minimum value for microvias diameter: %s
\n" ), GetChars( value ) ); m_MessagesList->AppendToPage( msg ); } @@ -212,7 +212,7 @@ void DIALOG_DESIGN_RULES::InitDialogRules() SetReturnCode( 0 ); m_Pcb = m_Parent->GetBoard(); - m_BrdSettings = m_Pcb->GetDesignSettings(); + m_BrdSettings = &m_Pcb->GetDesignSettings(); // Initialize the Rules List InitRulesList(); @@ -220,13 +220,8 @@ void DIALOG_DESIGN_RULES::InitDialogRules() // copy all NETs into m_AllNets by adding them as NETCUPs. // @todo go fix m_Pcb->SynchronizeNetsAndNetClasses() so that the netcode==0 is not present in the BOARD::m_NetClasses - - - NETCLASS* netclass; - - NETCLASSES& netclasses = m_Pcb->m_NetClasses; - - netclass = netclasses.GetDefault(); + NETCLASSES& netclasses = m_BrdSettings->m_NetClasses; + NETCLASS* netclass = netclasses.GetDefault(); // Initialize list of nets for Default Net Class for( NETCLASS::const_iterator name = netclass->begin(); name != netclass->end(); ++name ) @@ -262,23 +257,23 @@ void DIALOG_DESIGN_RULES::InitGlobalRules() AddUnitSymbol( *m_MicroViaMinDrillTitle ); AddUnitSymbol( *m_TrackMinWidthTitle ); - PutValueInLocalUnits( *m_SetViasMinSizeCtrl, m_BrdSettings.m_ViasMinSize ); - PutValueInLocalUnits( *m_SetViasMinDrillCtrl, m_BrdSettings.m_ViasMinDrill ); + PutValueInLocalUnits( *m_SetViasMinSizeCtrl, m_BrdSettings->m_ViasMinSize ); + PutValueInLocalUnits( *m_SetViasMinDrillCtrl, m_BrdSettings->m_ViasMinDrill ); - if( m_BrdSettings.m_BlindBuriedViaAllowed ) + if( m_BrdSettings->m_BlindBuriedViaAllowed ) m_OptViaType->SetSelection( 1 ); - m_AllowMicroViaCtrl->SetSelection( m_BrdSettings.m_MicroViasAllowed ? 1 : 0 ); - PutValueInLocalUnits( *m_SetMicroViasMinSizeCtrl, m_BrdSettings.m_MicroViasMinSize ); - PutValueInLocalUnits( *m_SetMicroViasMinDrillCtrl, m_BrdSettings.m_MicroViasMinDrill ); - PutValueInLocalUnits( *m_SetTrackMinWidthCtrl, m_BrdSettings.m_TrackMinWidth ); + m_AllowMicroViaCtrl->SetSelection( m_BrdSettings->m_MicroViasAllowed ? 1 : 0 ); + PutValueInLocalUnits( *m_SetMicroViasMinSizeCtrl, m_BrdSettings->m_MicroViasMinSize ); + PutValueInLocalUnits( *m_SetMicroViasMinDrillCtrl, m_BrdSettings->m_MicroViasMinDrill ); + PutValueInLocalUnits( *m_SetTrackMinWidthCtrl, m_BrdSettings->m_TrackMinWidth ); // Initialize Vias and Tracks sizes lists. // note we display only extra values, never the current netclass value. // (the first value in history list) - m_TracksWidthList = m_BrdSettings.m_TrackWidthList; + m_TracksWidthList = m_BrdSettings->m_TrackWidthList; m_TracksWidthList.erase( m_TracksWidthList.begin() ); // remove the netclass value - m_ViasDimensionsList = m_BrdSettings.m_ViasDimensionsList; + m_ViasDimensionsList = m_BrdSettings->m_ViasDimensionsList; m_ViasDimensionsList.erase( m_ViasDimensionsList.begin() ); // remove the netclass value InitDimensionsLists(); } @@ -484,7 +479,7 @@ static void class2gridRow( wxGrid* grid, int row, NETCLASS* nc ) */ void DIALOG_DESIGN_RULES::InitRulesList() { - NETCLASSES& netclasses = m_Pcb->m_NetClasses; + NETCLASSES& netclasses = m_BrdSettings->m_NetClasses; // the +1 is for the Default NETCLASS. if( netclasses.GetCount() + 1 > (unsigned) m_grid->GetNumberRows() ) @@ -524,7 +519,7 @@ static void gridRow2class( wxGrid* grid, int row, NETCLASS* nc ) */ void DIALOG_DESIGN_RULES::CopyRulesListToBoard() { - NETCLASSES& netclasses = m_Pcb->m_NetClasses; + NETCLASSES& netclasses = m_BrdSettings->m_NetClasses; // Remove all netclasses from board. We'll copy new list after netclasses.Clear(); @@ -535,9 +530,9 @@ void DIALOG_DESIGN_RULES::CopyRulesListToBoard() // Copy other NetClasses : for( int row = 1; row < m_grid->GetNumberRows(); ++row ) { - NETCLASS* nc = new NETCLASS( m_Pcb, m_grid->GetRowLabelValue( row ) ); + NETCLASS* nc = new NETCLASS( m_grid->GetRowLabelValue( row ) ); - if( !m_Pcb->m_NetClasses.Add( nc ) ) + if( !m_BrdSettings->m_NetClasses.Add( nc ) ) { // this netclass cannot be added because an other netclass with the same name exists // Should not occur because OnAddNetclassClick() tests for existing NetClass names @@ -568,20 +563,20 @@ void DIALOG_DESIGN_RULES::CopyRulesListToBoard() void DIALOG_DESIGN_RULES::CopyGlobalRulesToBoard() /*************************************************/ { - m_BrdSettings.m_BlindBuriedViaAllowed = m_OptViaType->GetSelection() > 0; + m_BrdSettings->m_BlindBuriedViaAllowed = m_OptViaType->GetSelection() > 0; // Update vias minimum values for DRC - m_BrdSettings.m_ViasMinSize = ValueFromTextCtrl( *m_SetViasMinSizeCtrl ); - m_BrdSettings.m_ViasMinDrill = ValueFromTextCtrl( *m_SetViasMinDrillCtrl ); + m_BrdSettings->m_ViasMinSize = ValueFromTextCtrl( *m_SetViasMinSizeCtrl ); + m_BrdSettings->m_ViasMinDrill = ValueFromTextCtrl( *m_SetViasMinDrillCtrl ); - m_BrdSettings.m_MicroViasAllowed = m_AllowMicroViaCtrl->GetSelection() == 1; + m_BrdSettings->m_MicroViasAllowed = m_AllowMicroViaCtrl->GetSelection() == 1; // Update microvias minimum values for DRC - m_BrdSettings.m_MicroViasMinSize = ValueFromTextCtrl( *m_SetMicroViasMinSizeCtrl ); - m_BrdSettings.m_MicroViasMinDrill = ValueFromTextCtrl( *m_SetMicroViasMinDrillCtrl ); + m_BrdSettings->m_MicroViasMinSize = ValueFromTextCtrl( *m_SetMicroViasMinSizeCtrl ); + m_BrdSettings->m_MicroViasMinDrill = ValueFromTextCtrl( *m_SetMicroViasMinDrillCtrl ); // Update tracks minimum values for DRC - m_BrdSettings.m_TrackMinWidth = ValueFromTextCtrl( *m_SetTrackMinWidthCtrl ); + m_BrdSettings->m_TrackMinWidth = ValueFromTextCtrl( *m_SetTrackMinWidthCtrl ); } @@ -634,12 +629,12 @@ void DIALOG_DESIGN_RULES::CopyDimensionsListsToBoard() // Sort new list by by increasing value sort( m_ViasDimensionsList.begin(), m_ViasDimensionsList.end() ); - std::vector* tlist = &m_BrdSettings.m_TrackWidthList; + std::vector* tlist = &m_BrdSettings->m_TrackWidthList; tlist->erase( tlist->begin() + 1, tlist->end() ); // Remove old "custom" sizes tlist->insert( tlist->end(), m_TracksWidthList.begin(), m_TracksWidthList.end() ); //Add new "custom" sizes // Reinitialize m_ViaSizeList - std::vector* vialist = &m_BrdSettings.m_ViasDimensionsList; + std::vector* vialist = &m_BrdSettings->m_ViasDimensionsList; vialist->erase( vialist->begin() + 1, vialist->end() ); vialist->insert( vialist->end(), m_ViasDimensionsList.begin(), m_ViasDimensionsList.end() ); } @@ -671,11 +666,9 @@ void DIALOG_DESIGN_RULES::OnOkButtonClick( wxCommandEvent& event ) CopyGlobalRulesToBoard(); CopyDimensionsListsToBoard(); - m_Pcb->SetDesignSettings( m_BrdSettings ); - EndModal( wxID_OK ); - m_Pcb->SetCurrentNetClass( NETCLASS::Default ); + m_BrdSettings->SetCurrentNetClass( NETCLASS::Default ); } @@ -755,7 +748,7 @@ void DIALOG_DESIGN_RULES::OnRemoveNetclassClick( wxCommandEvent& event ) for( unsigned ii = 0; ii < select.GetCount(); ii++ ) { int grid_row = select[ii]; - if( grid_row != 0 ) // Do not remove the default class + if( grid_row != 0 ) // Do not remove the default class { wxString classname = m_grid->GetRowLabelValue( grid_row ); m_grid->DeleteRows( grid_row ); diff --git a/pcbnew/dialogs/dialog_design_rules.h b/pcbnew/dialogs/dialog_design_rules.h index 3bfbfd8d57..f7206b5175 100644 --- a/pcbnew/dialogs/dialog_design_rules.h +++ b/pcbnew/dialogs/dialog_design_rules.h @@ -40,7 +40,7 @@ private: PCB_EDIT_FRAME* m_Parent; BOARD* m_Pcb; - BOARD_DESIGN_SETTINGS m_BrdSettings; + BOARD_DESIGN_SETTINGS* m_BrdSettings; static int s_LastTabSelection; ///< which tab user had open last diff --git a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp index 71904a927e..5f3afd55f1 100644 --- a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp @@ -46,21 +46,22 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit() // Display current setup for tracks and vias BOARD* board = m_Parent->GetBoard(); - NETCLASSES& netclasses = board->m_NetClasses; - NETINFO_ITEM* net = board->FindNet( m_Netcode ); + BOARD_DESIGN_SETTINGS& dsnSettings = board->GetDesignSettings(); + NETCLASSES& netclasses = dsnSettings.m_NetClasses; NETCLASS* netclass = netclasses.GetDefault(); + NETINFO_ITEM* net = board->FindNet( m_Netcode ); if( net ) { m_CurrentNetName->SetLabel( net->GetNetname() ); - m_CurrentNetclassName->SetLabel( board->GetCurrentNetClassName() ); - netclass = netclasses.Find( board->GetCurrentNetClassName() ); + m_CurrentNetclassName->SetLabel( dsnSettings.GetCurrentNetClassName() ); + netclass = netclasses.Find( dsnSettings.GetCurrentNetClassName() ); } /* Disable the option "copy current to net" if we have only default netclass values * i.e. when m_TrackWidthSelector and m_ViaSizeSelector are set to 0 */ - if( !board->GetDesignSettings().GetTrackWidthIndex() && !board->GetDesignSettings().GetViaSizeIndex() ) + if( !dsnSettings.GetTrackWidthIndex() && !dsnSettings.GetViaSizeIndex() ) { m_Net2CurrValueButton->Enable( false ); m_OptionID = ID_NETCLASS_VALUES_TO_CURRENT_NET; @@ -77,9 +78,9 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit() msg = StringFromValue( g_UserUnit, value, true ); m_gridDisplayCurrentSettings->SetCellValue( 0, 0, msg ); - if( board->GetDesignSettings().GetTrackWidthIndex() ) + if( dsnSettings.GetTrackWidthIndex() ) { - value = board->GetDesignSettings().GetCurrentTrackWidth(); + value = dsnSettings.GetCurrentTrackWidth(); msg = StringFromValue( g_UserUnit, value, true ); } else @@ -91,9 +92,9 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit() msg = StringFromValue( g_UserUnit, value, true ); m_gridDisplayCurrentSettings->SetCellValue( 0, 1, msg ); - if( board->GetDesignSettings().GetViaSizeIndex() ) + if( dsnSettings.GetViaSizeIndex() ) { - value = board->GetDesignSettings().GetCurrentViaSize(); + value = dsnSettings.GetCurrentViaSize(); msg = StringFromValue( g_UserUnit, value, true ); } else @@ -103,7 +104,7 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit() value = netclass->GetViaDrill(); // Display via drill msg = StringFromValue( g_UserUnit, value, true ); m_gridDisplayCurrentSettings->SetCellValue( 0, 2, msg ); - value = board->GetDesignSettings().GetCurrentViaDrill(); + value = dsnSettings.GetCurrentViaDrill(); if( value >= 0 ) msg = StringFromValue( g_UserUnit, value, true ); else diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp index 3b2550e931..0c59845187 100644 --- a/pcbnew/dialogs/dialog_plot.cpp +++ b/pcbnew/dialogs/dialog_plot.cpp @@ -70,8 +70,8 @@ void DIALOG_PLOT::Init_Dialog() // The reasonable width correction value must be in a range of // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils. - m_widthAdjustMinValue = -(m_board->GetDesignSettings().m_TrackMinWidth - 1); - m_widthAdjustMaxValue = m_board->GetSmallestClearanceValue() - 1; + m_widthAdjustMinValue = -( m_board->GetDesignSettings().m_TrackMinWidth - 1 ); + m_widthAdjustMaxValue = m_board->GetDesignSettings().GetSmallestClearanceValue() - 1; switch( m_plotOpts.GetFormat() ) { diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp index b32ddb65b4..67c451c721 100644 --- a/pcbnew/drc.cpp +++ b/pcbnew/drc.cpp @@ -403,7 +403,7 @@ bool DRC::testNetClasses() { bool ret = true; - NETCLASSES& netclasses = m_pcb->m_NetClasses; + NETCLASSES& netclasses = m_pcb->GetDesignSettings().m_NetClasses; wxString msg; // construct this only once here, not in a loop, since somewhat expensive. diff --git a/pcbnew/drc_clearance_test_functions.cpp b/pcbnew/drc_clearance_test_functions.cpp index 04394d2d08..ed48f149ab 100644 --- a/pcbnew/drc_clearance_test_functions.cpp +++ b/pcbnew/drc_clearance_test_functions.cpp @@ -154,6 +154,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) wxPoint shape_pos; NETCLASS* netclass = aRefSeg->GetNetClass(); + BOARD_DESIGN_SETTINGS& dsnSettings = m_pcb->GetDesignSettings(); /* In order to make some calculations more easier or faster, * pads and tracks coordinates will be made relative to the reference segment origin @@ -173,7 +174,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) // test if the via size is smaller than minimum if( refvia->GetViaType() == VIA_MICROVIA ) { - if( refvia->GetWidth() < netclass->GetuViaMinDiameter() ) + if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize ) { m_currentMarker = fillMarker( refvia, NULL, DRCE_TOO_SMALL_MICROVIA, m_currentMarker ); @@ -182,7 +183,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) } else { - if( refvia->GetWidth() < netclass->GetViaMinDiameter() ) + if( refvia->GetWidth() < dsnSettings.m_ViasMinSize ) { m_currentMarker = fillMarker( refvia, NULL, DRCE_TOO_SMALL_VIA, m_currentMarker ); @@ -231,7 +232,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) } else // This is a track segment { - if( aRefSeg->GetWidth() < netclass->GetTrackMinWidth() ) + if( aRefSeg->GetWidth() < dsnSettings.m_TrackMinWidth ) { m_currentMarker = fillMarker( aRefSeg, NULL, DRCE_TOO_SMALL_TRACK_WIDTH, m_currentMarker ); diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index 4f93574ab2..b1da39fc6f 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -1133,7 +1133,7 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const loadAllSections( doc ); - BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings(); + BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings(); if( m_min_trace < designSettings.m_TrackMinWidth ) designSettings.m_TrackMinWidth = m_min_trace; @@ -1146,7 +1146,7 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const if( m_rules->mdWireWire ) { - NETCLASS* defaultNetclass = m_board->m_NetClasses.GetDefault(); + NETCLASS* defaultNetclass = designSettings.m_NetClasses.GetDefault(); int clearance = KiROUND( m_rules->mdWireWire ); if( clearance < defaultNetclass->GetClearance() ) diff --git a/pcbnew/edit_track_width.cpp b/pcbnew/edit_track_width.cpp index f19c8216e1..b0ec02eb13 100644 --- a/pcbnew/edit_track_width.cpp +++ b/pcbnew/edit_track_width.cpp @@ -67,7 +67,7 @@ bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem, if( net ) new_width = net->GetMicroViaSize(); else - new_width = GetBoard()->GetCurrentMicroViaSize(); + new_width = GetDesignSettings().GetCurrentMicroViaSize(); } } diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index ddd1356705..715ac98f8d 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -167,7 +167,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) // Display info about track Net class, and init track and vias sizes: g_CurrentTrackSegment->SetNetCode( GetBoard()->GetHighLightNetCode() ); - GetBoard()->SetCurrentNetClass( g_CurrentTrackSegment->GetNetClassName() ); + GetDesignSettings().SetCurrentNetClass( g_CurrentTrackSegment->GetNetClassName() ); g_CurrentTrackSegment->SetLayer( GetScreen()->m_Active_Layer ); g_CurrentTrackSegment->SetWidth( GetDesignSettings().GetCurrentTrackWidth() ); diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 27262d6f38..89671c066b 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -356,7 +356,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in } else { - GetBoard()->m_NetClasses.Clear(); + GetDesignSettings().m_NetClasses.Clear(); } BOARD* loadedBoard = 0; // it will be set to non-NULL if loaded OK @@ -485,7 +485,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in #endif // Update info shown by the horizontal toolbars - GetBoard()->SetCurrentNetClass( NETCLASS::Default ); + GetDesignSettings().SetCurrentNetClass( NETCLASS::Default ); ReFillLayerWidget(); ReCreateLayerBox(); @@ -678,7 +678,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF // Select default Netclass before writing file. // Useful to save default values in headers - GetBoard()->SetCurrentNetClass( GetBoard()->m_NetClasses.GetDefault()->GetName() ); + GetDesignSettings().SetCurrentNetClass( GetDesignSettings().m_NetClasses.GetDefault()->GetName() ); try { diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index fd2cf976dc..adf5ce76eb 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -60,6 +60,17 @@ */ static const wxString traceFootprintLibrary( wxT( "KicadFootprintLib" ) ); +///> Removes empty nets (i.e. with node count equal zero) from net classes +void filterNetClass( const BOARD& aBoard, NETCLASS& aNetClass ) +{ + for( NETCLASS::const_iterator it = aNetClass.begin(); it != aNetClass.end(); ++it ) + { + NETINFO_ITEM* netinfo = aBoard.FindNet( *it ); + + if( netinfo && netinfo->GetNodesCount() <= 0 ) // hopefully there are no nets with negative + aNetClass.Remove( it ); // node count, but you never know.. + } +} /** * Class FP_CACHE_ITEM @@ -483,6 +494,8 @@ void PCB_IO::formatLayer( const BOARD_ITEM* aItem ) const void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const throw( IO_ERROR ) { + const BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings(); + m_out->Print( 0, "\n" ); m_out->Print( aNestLevel, "(general\n" ); @@ -496,7 +509,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const FMTIU( aBoard->GetBoundingBox().GetRight() ).c_str(), FMTIU( aBoard->GetBoundingBox().GetBottom() ).c_str() ); m_out->Print( aNestLevel+1, "(thickness %s)\n", - FMTIU( aBoard->GetDesignSettings().GetBoardThickness() ).c_str() ); + FMTIU( dsnSettings.GetBoardThickness() ).c_str() ); m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->m_Drawings.GetCount() ); m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() ); @@ -551,15 +564,15 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const // Save current default track width, for compatibility with older Pcbnew version; m_out->Print( aNestLevel+1, "(last_trace_width %s)\n", - FMTIU( aBoard->GetDesignSettings().GetCurrentTrackWidth() ).c_str() ); + FMTIU( dsnSettings.GetCurrentTrackWidth() ).c_str() ); // Save custom tracks width list (the first is not saved here: this is the netclass value - for( unsigned ii = 1; ii < aBoard->GetDesignSettings().m_TrackWidthList.size(); ii++ ) + for( unsigned ii = 1; ii < dsnSettings.m_TrackWidthList.size(); ii++ ) m_out->Print( aNestLevel+1, "(user_trace_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_TrackWidthList[ii] ).c_str() ); + FMTIU( dsnSettings.m_TrackWidthList[ii] ).c_str() ); m_out->Print( aNestLevel+1, "(trace_clearance %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetClearance() ).c_str() ); + FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetClearance() ).c_str() ); // ZONE_SETTINGS m_out->Print( aNestLevel+1, "(zone_clearance %s)\n", @@ -568,78 +581,79 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const aBoard->GetZoneSettings().m_Zone_45_Only ? "yes" : "no" ); m_out->Print( aNestLevel+1, "(trace_min %s)\n", - FMTIU( aBoard->GetDesignSettings().m_TrackMinWidth ).c_str() ); + FMTIU( dsnSettings.m_TrackMinWidth ).c_str() ); m_out->Print( aNestLevel+1, "(segment_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_DrawSegmentWidth ).c_str() ); + FMTIU( dsnSettings.m_DrawSegmentWidth ).c_str() ); m_out->Print( aNestLevel+1, "(edge_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_EdgeSegmentWidth ).c_str() ); + FMTIU( dsnSettings.m_EdgeSegmentWidth ).c_str() ); // Save current default via size, for compatibility with older Pcbnew version; m_out->Print( aNestLevel+1, "(via_size %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetViaDiameter() ).c_str() ); + FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetViaDiameter() ).c_str() ); m_out->Print( aNestLevel+1, "(via_drill %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetViaDrill() ).c_str() ); + FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetViaDrill() ).c_str() ); m_out->Print( aNestLevel+1, "(via_min_size %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ViasMinSize ).c_str() ); + FMTIU( dsnSettings.m_ViasMinSize ).c_str() ); m_out->Print( aNestLevel+1, "(via_min_drill %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ViasMinDrill ).c_str() ); + FMTIU( dsnSettings.m_ViasMinDrill ).c_str() ); // Save custom vias diameters list (the first is not saved here: this is // the netclass value - for( unsigned ii = 1; ii < aBoard->GetDesignSettings().m_ViasDimensionsList.size(); ii++ ) + for( unsigned ii = 1; ii < dsnSettings.m_ViasDimensionsList.size(); ii++ ) m_out->Print( aNestLevel+1, "(user_via %s %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Diameter ).c_str(), - FMTIU( aBoard->GetDesignSettings().m_ViasDimensionsList[ii].m_Drill ).c_str() ); + FMTIU( dsnSettings.m_ViasDimensionsList[ii].m_Diameter ).c_str(), + FMTIU( dsnSettings.m_ViasDimensionsList[ii].m_Drill ).c_str() ); // for old versions compatibility: - if( aBoard->GetDesignSettings().m_BlindBuriedViaAllowed ) + if( dsnSettings.m_BlindBuriedViaAllowed ) m_out->Print( aNestLevel+1, "(blind_buried_vias_allowed yes)\n" ); + m_out->Print( aNestLevel+1, "(uvia_size %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDiameter() ).c_str() ); + FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetuViaDiameter() ).c_str() ); m_out->Print( aNestLevel+1, "(uvia_drill %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDrill() ).c_str() ); + FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetuViaDrill() ).c_str() ); m_out->Print( aNestLevel+1, "(uvias_allowed %s)\n", - ( aBoard->GetDesignSettings().m_MicroViasAllowed ) ? "yes" : "no" ); + ( dsnSettings.m_MicroViasAllowed ) ? "yes" : "no" ); m_out->Print( aNestLevel+1, "(uvia_min_size %s)\n", - FMTIU( aBoard->GetDesignSettings().m_MicroViasMinSize ).c_str() ); + FMTIU( dsnSettings.m_MicroViasMinSize ).c_str() ); m_out->Print( aNestLevel+1, "(uvia_min_drill %s)\n", - FMTIU( aBoard->GetDesignSettings().m_MicroViasMinDrill ).c_str() ); + FMTIU( dsnSettings.m_MicroViasMinDrill ).c_str() ); m_out->Print( aNestLevel+1, "(pcb_text_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_PcbTextWidth ).c_str() ); + FMTIU( dsnSettings.m_PcbTextWidth ).c_str() ); m_out->Print( aNestLevel+1, "(pcb_text_size %s %s)\n", - FMTIU( aBoard->GetDesignSettings().m_PcbTextSize.x ).c_str(), - FMTIU( aBoard->GetDesignSettings().m_PcbTextSize.y ).c_str() ); + FMTIU( dsnSettings.m_PcbTextSize.x ).c_str(), + FMTIU( dsnSettings.m_PcbTextSize.y ).c_str() ); m_out->Print( aNestLevel+1, "(mod_edge_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ModuleSegmentWidth ).c_str() ); + FMTIU( dsnSettings.m_ModuleSegmentWidth ).c_str() ); m_out->Print( aNestLevel+1, "(mod_text_size %s %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ModuleTextSize.x ).c_str(), - FMTIU( aBoard->GetDesignSettings().m_ModuleTextSize.y ).c_str() ); + FMTIU( dsnSettings.m_ModuleTextSize.x ).c_str(), + FMTIU( dsnSettings.m_ModuleTextSize.y ).c_str() ); m_out->Print( aNestLevel+1, "(mod_text_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ModuleTextWidth ).c_str() ); + FMTIU( dsnSettings.m_ModuleTextWidth ).c_str() ); m_out->Print( aNestLevel+1, "(pad_size %s %s)\n", - FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetSize().x ).c_str(), - FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetSize().y ).c_str() ); + FMTIU( dsnSettings.m_Pad_Master.GetSize().x ).c_str(), + FMTIU( dsnSettings.m_Pad_Master.GetSize().y ).c_str() ); m_out->Print( aNestLevel+1, "(pad_drill %s)\n", - FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetDrillSize().x ).c_str() ); + FMTIU( dsnSettings.m_Pad_Master.GetDrillSize().x ).c_str() ); m_out->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n", - FMTIU( aBoard->GetDesignSettings().m_SolderMaskMargin ).c_str() ); + FMTIU( dsnSettings.m_SolderMaskMargin ).c_str() ); - if( aBoard->GetDesignSettings().m_SolderMaskMinWidth ) + if( dsnSettings.m_SolderMaskMinWidth ) m_out->Print( aNestLevel+1, "(solder_mask_min_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_SolderMaskMinWidth ).c_str() ); + FMTIU( dsnSettings.m_SolderMaskMinWidth ).c_str() ); - if( aBoard->GetDesignSettings().m_SolderPasteMargin != 0 ) + if( dsnSettings.m_SolderPasteMargin != 0 ) m_out->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n", - FMTIU( aBoard->GetDesignSettings().m_SolderPasteMargin ).c_str() ); + FMTIU( dsnSettings.m_SolderPasteMargin ).c_str() ); - if( aBoard->GetDesignSettings().m_SolderPasteMarginRatio != 0 ) + if( dsnSettings.m_SolderPasteMarginRatio != 0 ) m_out->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %s)\n", - Double2Str( aBoard->GetDesignSettings().m_SolderPasteMarginRatio ).c_str() ); + Double2Str( dsnSettings.m_SolderPasteMarginRatio ).c_str() ); m_out->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n", FMTIU( aBoard->GetAuxOrigin().x ).c_str(), @@ -651,7 +665,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const FMTIU( aBoard->GetGridOrigin().y ).c_str() ); m_out->Print( aNestLevel+1, "(visible_elements %X)\n", - aBoard->GetDesignSettings().GetVisibleElements() ); + dsnSettings.GetVisibleElements() ); aBoard->GetPlotOptions().Format( m_out, aNestLevel+1 ); @@ -669,15 +683,18 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const m_out->Print( 0, "\n" ); // Save the default net class first. - aBoard->m_NetClasses.GetDefault()->Format( m_out, aNestLevel, m_ctl ); + NETCLASS defaultNC = *dsnSettings.m_NetClasses.GetDefault(); + filterNetClass( *aBoard, defaultNC ); // Remove empty nets (from a copy of a netclass) + defaultNC.Format( m_out, aNestLevel, m_ctl ); // Save the rest of the net classes alphabetically. - for( NETCLASSES::const_iterator it = aBoard->m_NetClasses.begin(); - it != aBoard->m_NetClasses.end(); + for( NETCLASSES::const_iterator it = dsnSettings.m_NetClasses.begin(); + it != dsnSettings.m_NetClasses.end(); ++it ) { - NETCLASS* netclass = it->second; - netclass->Format( m_out, aNestLevel, m_ctl ); + NETCLASS netclass = *it->second; + filterNetClass( *aBoard, netclass ); // Remove empty nets (from a copy of a netclass) + netclass.Format( m_out, aNestLevel, m_ctl ); } // Save the modules. @@ -707,7 +724,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const /// will not be saved. // Save the polygon (which are the newer technology) zones. - for( int i=0; i < aBoard->GetAreaCount(); ++i ) + for( int i = 0; i < aBoard->GetAreaCount(); ++i ) Format( aBoard->GetArea( i ), aNestLevel ); } diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index cf0aca69fe..77a4d14a0e 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -632,7 +632,7 @@ void LEGACY_PLUGIN::loadSHEET() void LEGACY_PLUGIN::loadSETUP() { - NETCLASS* netclass_default = m_board->m_NetClasses.GetDefault(); + NETCLASS* netclass_default = m_board->GetDesignSettings().m_NetClasses.GetDefault(); // TODO Orson: is it really necessary to first operate on a copy and then apply it? // would not it be better to use reference here and apply all the changes instantly? BOARD_DESIGN_SETTINGS bds = m_board->GetDesignSettings(); @@ -897,7 +897,7 @@ void LEGACY_PLUGIN::loadSETUP() // at all, the global defaults should go into a preferences // file instead so they are there to start new board // projects. - m_board->m_NetClasses.GetDefault()->SetParams(); + m_board->GetDesignSettings().m_NetClasses.GetDefault()->SetParams( m_board->GetDesignSettings() ); return; // preferred exit } @@ -2113,7 +2113,7 @@ void LEGACY_PLUGIN::loadNETCLASS() // yet since that would bypass duplicate netclass name checking within the BOARD. // store it temporarily in an auto_ptr until successfully inserted into the BOARD // just before returning. - auto_ptr nc( new NETCLASS( m_board, wxEmptyString ) ); + auto_ptr nc( new NETCLASS( wxEmptyString ) ); while( ( line = READLINE( m_reader ) ) != NULL ) { @@ -2175,7 +2175,7 @@ void LEGACY_PLUGIN::loadNETCLASS() else if( TESTLINE( "$EndNCLASS" ) ) { - if( m_board->m_NetClasses.Add( nc.get() ) ) + if( m_board->GetDesignSettings().m_NetClasses.Add( nc.get() ) ) { nc.release(); } @@ -2984,8 +2984,8 @@ void LEGACY_PLUGIN::saveSHEET( const BOARD* aBoard ) const void LEGACY_PLUGIN::saveSETUP( const BOARD* aBoard ) const { - NETCLASS* netclass_default = aBoard->m_NetClasses.GetDefault(); const BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings(); + NETCLASS* netclass_default = bds.m_NetClasses.GetDefault(); fprintf( m_fp, "$SETUP\n" ); @@ -3098,7 +3098,7 @@ void LEGACY_PLUGIN::saveBOARD_ITEMS( const BOARD* aBoard ) const } // Saved nets do not include netclass names, so save netclasses after nets. - saveNETCLASSES( &aBoard->m_NetClasses ); + saveNETCLASSES( &aBoard->GetDesignSettings().m_NetClasses ); // save the modules for( MODULE* m = aBoard->m_Modules; m; m = (MODULE*) m->Next() ) @@ -3119,7 +3119,7 @@ void LEGACY_PLUGIN::saveBOARD_ITEMS( const BOARD* aBoard ) const savePCB_TARGET( (PCB_TARGET*) gr ); break; case PCB_DIMENSION_T: - saveDIMENTION( (DIMENSION*) gr ); + saveDIMENSION( (DIMENSION*) gr ); break; default: THROW_IO_ERROR( wxString::Format( UNKNOWN_GRAPHIC_FORMAT, gr->Type() ) ); @@ -3763,7 +3763,7 @@ void LEGACY_PLUGIN::saveZONE_CONTAINER( const ZONE_CONTAINER* me ) const } -void LEGACY_PLUGIN::saveDIMENTION( const DIMENSION* me ) const +void LEGACY_PLUGIN::saveDIMENSION( const DIMENSION* me ) const { // note: COTATION was the previous name of DIMENSION // this old keyword is used here for compatibility diff --git a/pcbnew/legacy_plugin.h b/pcbnew/legacy_plugin.h index dec3bfcbac..a9efbaa053 100644 --- a/pcbnew/legacy_plugin.h +++ b/pcbnew/legacy_plugin.h @@ -261,7 +261,7 @@ protected: void savePCB_TEXT( const TEXTE_PCB* aText ) const; void savePCB_TARGET( const PCB_TARGET* aTarget ) const; void savePCB_LINE( const DRAWSEGMENT* aStroke ) const; - void saveDIMENTION( const DIMENSION* aDimension ) const; + void saveDIMENSION( const DIMENSION* aDimension ) const; void saveTRACK( const TRACK* aTrack ) const; /** diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index dc5b0b97ee..922d04e727 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -161,7 +161,7 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) case PCB_TRACE_T: case PCB_VIA_T: case PCB_PAD_T: - GetBoard()->SetCurrentNetClass( + GetDesignSettings().SetCurrentNetClass( ((BOARD_CONNECTED_ITEM*)DrawStruct)->GetNetClassName() ); updateTraceWidthSelectBox(); updateViaSizeSelectBox(); diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index ec8157d17e..ffb14ac90a 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -464,7 +464,7 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu ) wxPoint cursorPosition = GetCrossHairPosition(); wxString msg; - GetBoard()->SetCurrentNetClass( Track->GetNetClassName() ); + GetDesignSettings().SetCurrentNetClass( Track->GetNetClassName() ); updateTraceWidthSelectBox(); updateViaSizeSelectBox(); @@ -834,9 +834,9 @@ void PCB_EDIT_FRAME::createPopUpMenuForFpPads( D_PAD* Pad, wxMenu* menu ) if( flags ) // Currently in edit, no others commands possible return; - if( GetBoard()->GetCurrentNetClassName() != Pad->GetNetClassName() ) + if( GetDesignSettings().GetCurrentNetClassName() != Pad->GetNetClassName() ) { - GetBoard()->SetCurrentNetClass( Pad->GetNetClassName() ); + GetDesignSettings().SetCurrentNetClass( Pad->GetNetClassName() ); updateTraceWidthSelectBox(); updateViaSizeSelectBox(); } diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 59ef3cb88f..77586e843f 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -808,7 +808,7 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) ); T token; - NETCLASS* defaultNetclass = m_board->m_NetClasses.GetDefault(); + NETCLASS* defaultNetClass = m_board->GetDesignSettings().m_NetClasses.GetDefault(); // TODO Orson: is it really necessary to first operate on a copy and then apply it? // would not it be better to use reference here and apply all the changes instantly? BOARD_DESIGN_SETTINGS designSettings = m_board->GetDesignSettings(); @@ -834,7 +834,7 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) break; case T_trace_clearance: - defaultNetclass->SetClearance( parseBoardUnits( T_trace_clearance ) ); + defaultNetClass->SetClearance( parseBoardUnits( T_trace_clearance ) ); NeedRIGHT(); break; @@ -864,12 +864,12 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) break; case T_via_size: - defaultNetclass->SetViaDiameter( parseBoardUnits( T_via_size ) ); + defaultNetClass->SetViaDiameter( parseBoardUnits( T_via_size ) ); NeedRIGHT(); break; case T_via_drill: - defaultNetclass->SetViaDrill( parseBoardUnits( T_via_drill ) ); + defaultNetClass->SetViaDrill( parseBoardUnits( T_via_drill ) ); NeedRIGHT(); break; @@ -893,12 +893,12 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) break; case T_uvia_size: - defaultNetclass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) ); + defaultNetClass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) ); NeedRIGHT(); break; case T_uvia_drill: - defaultNetclass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) ); + defaultNetClass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) ); NeedRIGHT(); break; @@ -1048,7 +1048,7 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) // at all, the global defaults should go into a preferences // file instead so they are there to start new board // projects. - m_board->m_NetClasses.GetDefault()->SetParams(); + defaultNetClass->SetParams( m_board->GetDesignSettings() ); } @@ -1082,7 +1082,7 @@ void PCB_PARSER::parseNETCLASS() throw( IO_ERROR, PARSE_ERROR ) T token; - std::auto_ptr nc( new NETCLASS( m_board, wxEmptyString ) ); + std::auto_ptr nc( new NETCLASS( wxEmptyString ) ); // Read netclass name (can be a name or just a number like track width) NeedSYMBOLorNUMBER(); @@ -1135,7 +1135,7 @@ void PCB_PARSER::parseNETCLASS() throw( IO_ERROR, PARSE_ERROR ) NeedRIGHT(); } - if( m_board->m_NetClasses.Add( nc.get() ) ) + if( m_board->GetDesignSettings().m_NetClasses.Add( nc.get() ) ) { nc.release(); } diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 9a57b50b16..104aeaa05e 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -70,7 +70,7 @@ public: continue; wxString netClassName = ni->GetClassName(); - NETCLASS* nc = aBoard->m_NetClasses.Find( netClassName ); + NETCLASS* nc = aBoard->GetDesignSettings().m_NetClasses.Find( netClassName ); int clearance = nc->GetClearance(); m_clearanceCache[i] = clearance; TRACE( 1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() % diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 8fe733fb8c..e270a0a5e8 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -115,11 +115,11 @@ void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth, if( ni ) { wxString netClassName = ni->GetClassName(); - netClass = board->m_NetClasses.Find( netClassName ); + netClass = board->GetDesignSettings().m_NetClasses.Find( netClassName ); } if( !netClass ) - netClass = board->m_NetClasses.GetDefault(); + netClass = board->GetDesignSettings().m_NetClasses.GetDefault(); aWidth = netClass->GetTrackWidth(); aViaDiameter = netClass->GetViaDiameter(); diff --git a/pcbnew/specctra_export.cpp b/pcbnew/specctra_export.cpp index ef452ce66d..089925576c 100644 --- a/pcbnew/specctra_export.cpp +++ b/pcbnew/specctra_export.cpp @@ -1476,9 +1476,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) //------------------------------------------------------------- { char rule[80]; + NETCLASS* defaultClass = aBoard->GetDesignSettings().m_NetClasses.GetDefault(); - int defaultTrackWidth = aBoard->m_NetClasses.GetDefault()->GetTrackWidth(); - int defaultClearance = aBoard->m_NetClasses.GetDefault()->GetClearance(); + int defaultTrackWidth = defaultClass->GetTrackWidth(); + int defaultClearance = defaultClass->GetClearance(); double clearance = scale( defaultClearance ); @@ -1829,7 +1830,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) //-----< output vias used in netclasses >----------------------------------- { - NETCLASSES& nclasses = aBoard->m_NetClasses; + NETCLASSES& nclasses = aBoard->GetDesignSettings().m_NetClasses; // Assume the netclass vias are all the same kind of thru, blind, or buried vias. // This is in lieu of either having each netclass via have its own layer pair in @@ -2039,7 +2040,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) //--------------------------------------------------------- - NETCLASSES& nclasses = aBoard->m_NetClasses; + NETCLASSES& nclasses = aBoard->GetDesignSettings().m_NetClasses; exportNETCLASS( nclasses.GetDefault(), aBoard ); diff --git a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp index c51da1fc1c..b41d859b65 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -176,7 +176,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) */ EDA_RECT item_boundingbox; EDA_RECT zone_boundingbox = GetBoundingBox(); - int biggest_clearance = aPcb->GetBiggestClearanceValue(); + int biggest_clearance = aPcb->GetDesignSettings().GetBiggestClearanceValue(); biggest_clearance = std::max( biggest_clearance, zone_clearance ); zone_boundingbox.Inflate( biggest_clearance ); diff --git a/pcbnew/zones_convert_to_polygons_aux_functions.cpp b/pcbnew/zones_convert_to_polygons_aux_functions.cpp index be02fd0d40..9861b0d120 100644 --- a/pcbnew/zones_convert_to_polygons_aux_functions.cpp +++ b/pcbnew/zones_convert_to_polygons_aux_functions.cpp @@ -138,7 +138,7 @@ void BuildUnconnectedThermalStubsPolygonList( CPOLYGONS_LIST& aCornerBuffer, EDA_RECT item_boundingbox; EDA_RECT zone_boundingbox = aZone->GetBoundingBox(); - int biggest_clearance = aPcb->GetBiggestClearanceValue(); + int biggest_clearance = aPcb->GetDesignSettings().GetBiggestClearanceValue(); biggest_clearance = std::max( biggest_clearance, zone_clearance ); zone_boundingbox.Inflate( biggest_clearance ); From 562beafcde6ebc1a34ff241f37dd7ae58ccc80e9 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 May 2014 11:22:51 +0200 Subject: [PATCH 44/68] Fixed modification point for EDIT_TOOL when the tool is not active. --- pcbnew/tools/edit_tool.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index b647b2bbf2..c0e30627dc 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -492,6 +492,11 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION_TOOL::SELECTION& aSelec } else { + // If EDIT_TOOL is not currently active then it means that the cursor position is not + // updated, so we have to fetch the latest value + if( m_toolMgr->GetCurrentToolId() != m_toolId ) + m_cursor = getViewControls()->GetCursorPosition(); + return wxPoint( m_cursor.x, m_cursor.y ); } } From 129e26d512588c8322a0010fc294fbcaf67039cc Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 09:42:16 +0200 Subject: [PATCH 45/68] Disable autopanning when GAL panel does not have focus. --- common/view/wx_view_controls.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index 9f51a0f624..acd88316fa 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -217,6 +217,11 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent ) { case AUTO_PANNING: { +#if wxCHECK_VERSION( 3, 0, 0 ) + if( !m_parentPanel->HasFocus() ) + break; +#endif + double borderSize = std::min( m_autoPanMargin * m_view->GetScreenPixelSize().x, m_autoPanMargin * m_view->GetScreenPixelSize().y ); From 27bb059aafd00348f19dee3754c7fea55a5693f4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 09:48:29 +0200 Subject: [PATCH 46/68] Via holes were always visible in GAL canvas - fixed. --- pcbnew/basepcbframe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 00fcf088c0..caa1194fc8 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -835,7 +835,7 @@ void PCB_BASE_FRAME::LoadSettings( wxConfigBase* aCfg ) } // Some more required layers settings - view->SetRequired( ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( VIAS_VISIBLE ) ); + view->SetRequired( ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ) ); view->SetRequired( ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ) ); view->SetRequired( NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ) ); From 2cba91f9749bdefc0b1ca2542a93fb847f05157f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 09:56:35 +0200 Subject: [PATCH 47/68] Holding shift always activates extend current selection mode (in GAL canvas). --- pcbnew/tools/selection_tool.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index b0a333285c..1917076f59 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -147,8 +147,13 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them else if( evt->IsDrag( BUT_LEFT ) ) { - if( m_selection.Empty() || m_additive ) + if( m_additive ) { + selectMultiple(); + } + else if( m_selection.Empty() ) + { + // There is nothing selected, so try to select something if( !selectSingle( getView()->ToWorld( getViewControls()->GetMousePosition() ), false ) ) { // If nothings has been selected or user wants to select more From d27ea7895d5b4c1e30ba7ae96bf6ff0587a2f26c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 10:35:12 +0200 Subject: [PATCH 48/68] Moved background color settings from GAL to RENDER_SETTINGS. Added RENDER_SETTINGS::TranslateColor() to convert between EDA_COLOR_T and COLOR4D. --- common/draw_panel_gal.cpp | 5 ++-- common/gal/cairo/cairo_gal.cpp | 8 +++--- common/gal/opengl/opengl_gal.cpp | 4 +-- include/class_draw_panel_gal.h | 2 +- include/gal/cairo/cairo_gal.h | 5 ++-- include/gal/graphics_abstraction_layer.h | 18 ++++--------- include/gal/opengl/opengl_gal.h | 2 +- include/painter.h | 32 ++++++++++++++++++++++++ pcbnew/pcb_painter.cpp | 2 ++ 9 files changed, 52 insertions(+), 26 deletions(-) diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index 93ad978969..1b293c63ac 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * @author Tomasz Wlostowski * * This program is free software; you can redistribute it and/or @@ -124,7 +124,7 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) m_view->UpdateItems(); m_gal->BeginDrawing(); - m_gal->ClearScreen(); + m_gal->ClearScreen( m_painter->GetSettings()->GetBackgroundColor() ); if( m_view->IsDirty() ) { @@ -228,7 +228,6 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) wxSize size = GetClientSize(); m_gal->ResizeScreen( size.GetX(), size.GetY() ); - m_gal->SetBackgroundColor( KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) ); if( m_painter ) m_painter->SetGAL( m_gal ); diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index 13055c7aed..a6f1429721 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -315,10 +315,10 @@ void CAIRO_GAL::Flush() } -void CAIRO_GAL::ClearScreen() +void CAIRO_GAL::ClearScreen( const COLOR4D& aColor ) { - cairo_set_source_rgb( currentContext, - backgroundColor.r, backgroundColor.g, backgroundColor.b ); + backgroundColor = aColor; + cairo_set_source_rgb( currentContext, aColor.r, aColor.g, aColor.b ); cairo_rectangle( currentContext, 0.0, 0.0, screenSize.x, screenSize.y ); cairo_fill( currentContext ); } @@ -973,7 +973,7 @@ void CAIRO_GAL::initSurface() cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL ); // Clear the screen - ClearScreen(); + ClearScreen( backgroundColor ); // Compute the world <-> screen transformations ComputeWorldScreenMatrix(); diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 5bd59303a2..568772f96a 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -589,10 +589,10 @@ void OPENGL_GAL::Flush() } -void OPENGL_GAL::ClearScreen() +void OPENGL_GAL::ClearScreen( const COLOR4D& aColor ) { // Clear screen - glClearColor( backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a ); + glClearColor( aColor.r, aColor.g, aColor.b, aColor.a ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h index 766cb5d630..16de3a139c 100644 --- a/include/class_draw_panel_gal.h +++ b/include/class_draw_panel_gal.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * @author Tomasz Wlostowski * * This program is free software; you can redistribute it and/or diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h index 352e262931..6b44b1d476 100644 --- a/include/gal/cairo/cairo_gal.h +++ b/include/gal/cairo/cairo_gal.h @@ -135,7 +135,7 @@ public: virtual void Flush(); /// @copydoc GAL::ClearScreen() - virtual void ClearScreen(); + virtual void ClearScreen( const COLOR4D& aColor ); // ----------------- // Attribute setting @@ -309,7 +309,7 @@ private: /// Type definition for an graphics group element typedef struct { - GRAPHICS_COMMAND command; ///< Command to execute + GRAPHICS_COMMAND command; ///< Command to execute double arguments[MAX_CAIRO_ARGUMENTS]; ///< Arguments for Cairo commands bool boolArgument; ///< A bool argument int intArgument; ///< An int argument @@ -333,6 +333,7 @@ private: unsigned int* bitmapBufferBackup; ///< Backup storage of the cairo image int stride; ///< Stride value for Cairo bool isInitialized; ///< Are Cairo image & surface ready to use + COLOR4D backgroundColor; ///< Background color // Methods void storePath(); ///< Store the actual path diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 50b5c355c7..6d904d2016 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -168,8 +168,11 @@ public: /// @brief Force all remaining objects to be drawn. virtual void Flush() = 0; - /// @brief Clear the screen. - virtual void ClearScreen() = 0; + /** + * @brief Clear the screen. + * @param aColor is the color used for clearing. + */ + virtual void ClearScreen( const COLOR4D& aColor ) = 0; // ----------------- // Attribute setting @@ -225,16 +228,6 @@ public: return strokeColor; } - /** - * @brief Set the background color. - * - * @param aColor is the color for background filling. - */ - inline virtual void SetBackgroundColor( const COLOR4D& aColor ) - { - backgroundColor = aColor; - } - /** * @brief Set the line width. * @@ -849,7 +842,6 @@ protected: bool isFillEnabled; ///< Is filling of graphic objects enabled ? bool isStrokeEnabled; ///< Are the outlines stroked ? - COLOR4D backgroundColor; ///< The background color COLOR4D fillColor; ///< The fill color COLOR4D strokeColor; ///< The color of the outlines diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h index d5c97aada9..10c4fea54d 100644 --- a/include/gal/opengl/opengl_gal.h +++ b/include/gal/opengl/opengl_gal.h @@ -143,7 +143,7 @@ public: virtual void Flush(); /// @copydoc GAL::ClearScreen() - virtual void ClearScreen(); + virtual void ClearScreen( const COLOR4D& aColor ); // -------------- // Transformation diff --git a/include/painter.h b/include/painter.h index 34376d985d..afa74aa482 100644 --- a/include/painter.h +++ b/include/painter.h @@ -177,6 +177,36 @@ public: return m_worksheetLineWidth; } + /** + * Function TranslateColor + * Returns the color responding to the one of EDA_COLOR_T enum values. + * @param EDA_COLOR_T color equivalent. + */ + const COLOR4D& TranslateColor( EDA_COLOR_T aColor ) + { + return m_legacyColorMap[aColor]; + } + + /** + * Function GetBackgroundColor + * Returns current background color settings. + * @return Background color. + */ + const COLOR4D& GetBackgroundColor() const + { + return m_backgroundColor; + } + + /** + * Function SetBackgroundColor + * Sets new color for background. + * @param aColor is the new background color. + */ + void SetBackgroundColor( const COLOR4D& aColor ) + { + m_backgroundColor = aColor; + } + protected: /** * Function update @@ -203,6 +233,8 @@ protected: float m_outlineWidth; ///< Line width used when drawing outlines float m_worksheetLineWidth; ///< Line width used when drawing worksheet + COLOR4D m_backgroundColor; ///< The background color + /// Map of colors that were usually used for display std::map m_legacyColorMap; }; diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 0465f450aa..7b72b47497 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -43,6 +43,8 @@ using namespace KIGFX; PCB_RENDER_SETTINGS::PCB_RENDER_SETTINGS() { + m_backgroundColor = COLOR4D( 0.0, 0.0, 0.0, 1.0 ); + // By default everything should be displayed as filled for( unsigned int i = 0; i < END_PCB_VISIBLE_LIST; ++i ) { From cce6e270963f7761a85a10c17fcd150618d76b14 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 11:45:01 +0200 Subject: [PATCH 49/68] Various fixes to geometry & math library. --- common/geometry/shape_collisions.cpp | 273 ++++++++++++++++++--------- common/geometry/shape_line_chain.cpp | 90 +++++---- include/geometry/seg.h | 14 +- include/geometry/shape_circle.h | 11 ++ include/geometry/shape_line_chain.h | 20 ++ include/geometry/shape_rect.h | 24 ++- include/math/math_util.h | 5 + include/math/vector2d.h | 3 +- 8 files changed, 299 insertions(+), 141 deletions(-) diff --git a/common/geometry/shape_collisions.cpp b/common/geometry/shape_collisions.cpp index 604335b43e..52db4ecb81 100644 --- a/common/geometry/shape_collisions.cpp +++ b/common/geometry/shape_collisions.cpp @@ -23,11 +23,13 @@ */ #include +#include #include #include #include #include +#include typedef VECTOR2I::extended_type ecoord; @@ -45,25 +47,21 @@ static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_CIRCLE& aB, int return false; if( aNeedMTV ) - aMTV = delta.Resize( sqrt( abs( min_dist_sq - dist_sq ) ) + 1 ); + aMTV = delta.Resize( min_dist - sqrt( dist_sq ) + 3 ); // fixme: apparent rounding error return true; } -static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int aClearance, - bool aNeedMTV, VECTOR2I& aMTV ) +static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int aClearance, + bool aNeedMTV, VECTOR2I& aMTV ) { const VECTOR2I c = aB.GetCenter(); const VECTOR2I p0 = aA.GetPosition(); const VECTOR2I size = aA.GetSize(); - const ecoord r = aB.GetRadius(); - const ecoord min_dist = aClearance + r; - const ecoord min_dist_sq = min_dist * min_dist; - - if( aA.BBox( 0 ).Contains( c ) ) - return true; - + const int r = aB.GetRadius(); + const int min_dist = aClearance + r; + const VECTOR2I vts[] = { VECTOR2I( p0.x, p0.y ), @@ -73,33 +71,35 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int a VECTOR2I( p0.x, p0.y ) }; - ecoord nearest_seg_dist_sq = VECTOR2I::ECOORD_MAX; + int nearest_seg_dist = INT_MAX; VECTOR2I nearest; bool inside = c.x >= p0.x && c.x <= ( p0.x + size.x ) && c.y >= p0.y && c.y <= ( p0.y + size.y ); - if( !inside ) - { - for( int i = 0; i < 4; i++ ) - { - const SEG seg( vts[i], vts[i + 1] ); - ecoord dist_sq = seg.SquaredDistance( c ); - if( dist_sq < min_dist_sq ) - { - if( !aNeedMTV ) - return true; - else - { - nearest = seg.NearestPoint( c ); - nearest_seg_dist_sq = dist_sq; - } - } + if( !aNeedMTV && inside ) + return true; + + for( int i = 0; i < 4; i++ ) + { + const SEG seg( vts[i], vts[i + 1] ); + + VECTOR2I pn = seg.NearestPoint( c ); + + int d = ( pn - c ).EuclideanNorm(); + + if( ( d < min_dist ) && !aNeedMTV ) + return true; + + if( d < nearest_seg_dist ) + { + nearest = pn; + nearest_seg_dist = d; } } - if( nearest_seg_dist_sq >= min_dist_sq && !inside ) + if( nearest_seg_dist >= min_dist && !inside ) return false; VECTOR2I delta = c - nearest; @@ -107,25 +107,77 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int a if( !aNeedMTV ) return true; + if( inside ) - aMTV = -delta.Resize( sqrt( abs( r * r + nearest_seg_dist_sq ) + 1 ) ); + aMTV = -delta.Resize( abs( min_dist + 1 + nearest_seg_dist ) + 1 ); else - aMTV = delta.Resize( sqrt( abs( r * r - nearest_seg_dist_sq ) + 1 ) ); + aMTV = delta.Resize( abs( min_dist + 1 - nearest_seg_dist ) + 1 ); + return true; } +static VECTOR2I pushoutForce( const SHAPE_CIRCLE& aA, const SEG& aB, int aClearance ) +{ + VECTOR2I nearest = aB.NearestPoint( aA.GetCenter() ); + VECTOR2I f (0, 0); + + int dist = ( nearest - aA.GetCenter() ).EuclideanNorm(); + int min_dist = aClearance + aA.GetRadius(); + + if( dist < min_dist ) + f = ( aA.GetCenter() - nearest ).Resize ( min_dist - dist + 10 ); + + return f; +} + + static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) { + bool found = false; + VECTOR2I::extended_type clSq = (VECTOR2I::extended_type) aClearance * aClearance; + + for( int s = 0; s < aB.SegmentCount(); s++ ) { + if( aA.Collide( aB.CSegment( s ), aClearance ) ) - return true; + { + found = true; + break; + } } - return false; + if( !aNeedMTV || !found ) + return found; + + SHAPE_CIRCLE cmoved( aA ); + VECTOR2I f_total( 0, 0 ); + + for( int s = 0; s < aB.SegmentCount(); s++ ) + { + VECTOR2I f = pushoutForce( cmoved, aB.CSegment( s ), aClearance ); + cmoved.SetCenter( cmoved.GetCenter() + f ); + f_total += f; + } + + aMTV = f_total; + return found; +} + + +static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_SEGMENT& aSeg, int aClearance, + bool aNeedMTV, VECTOR2I& aMTV ) +{ + bool col = aA.Collide( aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2); + + if( col && aNeedMTV ) + { + aMTV = pushoutForce( aA, aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2); + } + return col; } @@ -155,74 +207,123 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, in } -bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance, - bool aNeedMTV, VECTOR2I& aMTV ) +static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_SEGMENT& aSeg, int aClearance, + bool aNeedMTV, VECTOR2I& aMTV ) { - switch( aA->Type() ) - { - case SH_RECT: - switch( aB->Type() ) - { - case SH_CIRCLE: - return Collide( *static_cast( aA ), - *static_cast( aB ), aClearance, aNeedMTV, aMTV ); + return aA.Collide( aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2 ); +} - case SH_LINE_CHAIN: - return Collide( *static_cast( aA ), - *static_cast( aB ), aClearance, aNeedMTV, aMTV ); - default: - break; - } - break; +static inline bool Collide( const SHAPE_SEGMENT& aA, const SHAPE_SEGMENT& aB, int aClearance, + bool aNeedMTV, VECTOR2I& aMTV ) +{ + return aA.Collide( aB.GetSeg(), aClearance + aB.GetWidth() / 2 ); +} - case SH_CIRCLE: - switch( aB->Type() ) - { - case SH_RECT: - return Collide( *static_cast( aB ), - *static_cast( aA ), aClearance, aNeedMTV, aMTV ); - case SH_CIRCLE: - return Collide( *static_cast( aA ), - *static_cast( aB ), aClearance, aNeedMTV, aMTV ); +static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_SEGMENT& aB, int aClearance, + bool aNeedMTV, VECTOR2I& aMTV ) +{ + if( aA.Collide( aB.GetSeg(), aClearance + aB.GetWidth() / 2 ) ) + return true; - case SH_LINE_CHAIN: - return Collide( *static_cast( aA ), - *static_cast( aB ), aClearance, aNeedMTV, aMTV ); + return false; +} - default: - break; - } - break; - case SH_LINE_CHAIN: - switch( aB->Type() ) - { - case SH_RECT: - return Collide( *static_cast( aB ), - *static_cast( aA ), aClearance, aNeedMTV, aMTV ); +template bool +CollCase( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) +{ + return Collide (*static_cast( aA ), + *static_cast( aB ), + aClearance, aNeedMTV, aMTV); +} - case SH_CIRCLE: - return Collide( *static_cast( aB ), - *static_cast( aA ), aClearance, aNeedMTV, aMTV ); +bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) +{ + switch( aA->Type() ) + { + case SH_RECT: + switch( aB->Type() ) + { + case SH_CIRCLE: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); - case SH_LINE_CHAIN: - return Collide( *static_cast( aA ), - *static_cast( aB ), aClearance, aNeedMTV, aMTV ); + case SH_LINE_CHAIN: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); - default: - break; - } - break; + case SH_SEGMENT: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); - default: - break; - } + default: + break; + } - assert( 0 ); // unsupported_collision + case SH_CIRCLE: + switch( aB->Type() ) + { + case SH_RECT: + return CollCase( aB, aA, aClearance, aNeedMTV, aMTV ); - return false; + case SH_CIRCLE: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); + + case SH_LINE_CHAIN: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); + + case SH_SEGMENT: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); + default: + break; + } + + case SH_LINE_CHAIN: + switch( aB->Type() ) + { + case SH_RECT: + return CollCase( aB, aA, aClearance, aNeedMTV, aMTV ); + + case SH_CIRCLE: + return CollCase( aB, aA, aClearance, aNeedMTV, aMTV ); + + case SH_LINE_CHAIN: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); + + case SH_SEGMENT: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); + + default: + break; + } + + case SH_SEGMENT: + switch( aB->Type() ) + { + case SH_RECT: + return CollCase( aB, aA, aClearance, aNeedMTV, aMTV ); + + case SH_CIRCLE: + return CollCase( aB, aA, aClearance, aNeedMTV, aMTV ); + + case SH_LINE_CHAIN: + return CollCase( aB, aA, aClearance, aNeedMTV, aMTV ); + + case SH_SEGMENT: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); + + default: + break; + } + + default: + break; + } + + bool unsupported_collision = true; + + assert( unsupported_collision == false ); + + return false; } diff --git a/common/geometry/shape_line_chain.cpp b/common/geometry/shape_line_chain.cpp index 7ac8c10eae..e442fcd503 100644 --- a/common/geometry/shape_line_chain.cpp +++ b/common/geometry/shape_line_chain.cpp @@ -135,6 +135,9 @@ int SHAPE_LINE_CHAIN::Distance( const VECTOR2I& aP ) const { int d = INT_MAX; + if( IsClosed() && PointInside( aP ) ) + return 0; + for( int s = 0; s < SegmentCount(); s++ ) d = std::min( d, CSegment( s ).Distance( aP ) ); @@ -179,7 +182,7 @@ int SHAPE_LINE_CHAIN::Split( const VECTOR2I& aP ) int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const { - for( int s = 0; s< PointCount(); s++ ) + for( int s = 0; s < PointCount(); s++ ) if( CPoint( s ) == aP ) return s; @@ -187,6 +190,16 @@ int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const } +int SHAPE_LINE_CHAIN::FindSegment( const VECTOR2I& aP ) const +{ + for( int s = 0; s < SegmentCount(); s++ ) + if( CSegment( s ).Distance( aP ) <= 1 ) + return s; + + return -1; +} + + const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const { SHAPE_LINE_CHAIN rv; @@ -261,6 +274,9 @@ int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& if( a.Collinear( b ) ) { + is.our = a; + is.their = b; + if( a.Contains( b.A ) ) { is.p = b.A; aIp.push_back( is ); } if( a.Contains( b.B ) ) { is.p = b.B; aIp.push_back( is ); } if( b.Contains( a.A ) ) { is.p = a.A; aIp.push_back( is ); } @@ -282,44 +298,6 @@ int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& } return aIp.size(); - - for( int s1 = 0; s1 < SegmentCount(); s1++ ) - { - for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ ) - { - const SEG& a = CSegment( s1 ); - const SEG& b = aChain.CSegment( s2 ); - OPT_VECTOR2I p = a.Intersect( b ); - INTERSECTION is; - - if( p ) - { - is.p = *p; - is.our = a; - is.their = b; - aIp.push_back( is ); - } - else if( a.Collinear( b ) ) - { - if( a.A != b.A && a.A != b.B && b.Contains( a.A ) ) - { - is.p = a.A; - is.our = a; - is.their = b; - aIp.push_back( is ); - } - else if( a.B != b.A && a.B != b.B && b.Contains( a.B ) ) - { - is.p = a.B; - is.our = a; - is.their = b; - aIp.push_back( is ); - } - } - } - } - - return aIp.size(); } @@ -372,10 +350,13 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const { - if( SegmentCount() < 1 ) + if( !PointCount() ) + return false; + + else if( PointCount() == 1 ) return m_points[0] == aP; - for( int i = 1; i < SegmentCount(); i++ ) + for( int i = 0; i < SegmentCount(); i++ ) { const SEG s = CSegment( i ); @@ -534,3 +515,30 @@ const std::string SHAPE_LINE_CHAIN::Format() const return ss.str(); } + + +bool SHAPE_LINE_CHAIN::CompareGeometry ( const SHAPE_LINE_CHAIN & aOther ) const +{ + SHAPE_LINE_CHAIN a(*this), b(aOther); + a.Simplify(); + b.Simplify(); + + if(a.m_points.size() != b.m_points.size()) + return false; + + for(int i = 0; i < a.PointCount(); i++) + if(a.CPoint(i) != b.CPoint(i)) + return false; + return true; +} + +bool SHAPE_LINE_CHAIN::Intersects( const SHAPE_LINE_CHAIN& aChain ) const +{ + INTERSECTIONS dummy; + return Intersect(aChain, dummy) != 0; +} + +SHAPE* SHAPE_LINE_CHAIN::Clone() const +{ + return new SHAPE_LINE_CHAIN( *this ); +} diff --git a/include/geometry/seg.h b/include/geometry/seg.h index cf5b8d50c9..7e789f9d21 100644 --- a/include/geometry/seg.h +++ b/include/geometry/seg.h @@ -244,14 +244,14 @@ public: */ bool Collinear( const SEG& aSeg ) const { - ecoord qa = A.y - B.y; - ecoord qb = B.x - A.x; - ecoord qc = -qa * A.x - qb * A.y; + ecoord qa1 = A.y - B.y; + ecoord qb1 = B.x - A.x; + ecoord qc1 = -qa1 * A.x - qb1 * A.y; + ecoord qa2 = aSeg.A.y - aSeg.B.y; + ecoord qb2 = aSeg.B.x - aSeg.A.x; + ecoord qc2 = -qa2 * aSeg.A.x - qb2 * aSeg.A.y; - ecoord d1 = std::abs( aSeg.A.x * qa + aSeg.A.y * qb + qc ); - ecoord d2 = std::abs( aSeg.B.x * qa + aSeg.B.y * qb + qc ); - - return ( d1 <= 1 && d2 <= 1 ); + return ( qa1 == qa2 ) && ( qb1 == qb2 ) && ( qc1 == qc2 ); } /** diff --git a/include/geometry/shape_circle.h b/include/geometry/shape_circle.h index a11cd4da8f..e4b668b68c 100644 --- a/include/geometry/shape_circle.h +++ b/include/geometry/shape_circle.h @@ -38,9 +38,20 @@ public: SHAPE( SH_CIRCLE ), m_radius( aRadius ), m_center( aCenter ) {} + SHAPE_CIRCLE ( const SHAPE_CIRCLE& aOther ) : + SHAPE( SH_CIRCLE ), + m_radius( aOther.m_radius ), + m_center( aOther.m_center ) + {}; + ~SHAPE_CIRCLE() {} + SHAPE* Clone() const + { + return new SHAPE_CIRCLE( *this ); + } + const BOX2I BBox( int aClearance = 0 ) const { const VECTOR2I rc( m_radius + aClearance, m_radius + aClearance ); diff --git a/include/geometry/shape_line_chain.h b/include/geometry/shape_line_chain.h index da6494e91a..b91e6a566c 100644 --- a/include/geometry/shape_line_chain.h +++ b/include/geometry/shape_line_chain.h @@ -116,6 +116,8 @@ public: ~SHAPE_LINE_CHAIN() {} + SHAPE *Clone() const; + /** * Function Clear() * Removes all points from the line chain. @@ -366,6 +368,11 @@ public: } } + void Insert( int aVertex, const VECTOR2I& aP ) + { + m_points.insert( m_points.begin() + aVertex, aP ); + } + /** * Function Replace() * @@ -417,6 +424,15 @@ public: */ int Find( const VECTOR2I& aP ) const; + /** + * Function FindSegment() + * + * Searches for segment containing point aP. + * @param aP the point to be looked for + * @return index of the correspoinding segment in the line chain or negative when not found. + */ + int FindSegment( const VECTOR2I& aP ) const; + /** * Function Slice() * @@ -441,6 +457,8 @@ public: VECTOR2I m_origin; }; + bool Intersects( const SHAPE_LINE_CHAIN& aChain ) const; + /** * Function Intersect() * @@ -533,6 +551,8 @@ public: return false; } + bool CompareGeometry( const SHAPE_LINE_CHAIN & aOther ) const; + private: /// array of vertices std::vector m_points; diff --git a/include/geometry/shape_rect.h b/include/geometry/shape_rect.h index d2c5f22a33..bc3ba44d17 100644 --- a/include/geometry/shape_rect.h +++ b/include/geometry/shape_rect.h @@ -53,10 +53,22 @@ public: * Constructor * Creates a rectangle defined by top-left corner aP0, width aW and height aH. */ - SHAPE_RECT( const VECTOR2I& aP0, int aW, int aH ) : + SHAPE_RECT( const VECTOR2I& aP0, int aW, int aH ) : SHAPE( SH_RECT ), m_p0( aP0 ), m_w( aW ), m_h( aH ) {} + SHAPE_RECT ( const SHAPE_RECT& aOther ) : + SHAPE( SH_RECT ), + m_p0( aOther.m_p0 ), + m_w( aOther.m_w ), + m_h( aOther.m_h ) + {}; + + SHAPE* Clone() const + { + return new SHAPE_RECT( *this ); + } + /// @copydoc SHAPE::BBox() const BOX2I BBox( int aClearance = 0 ) const { @@ -90,11 +102,11 @@ public: if( BBox( 0 ).Contains( aSeg.A ) || BBox( 0 ).Contains( aSeg.B ) ) return true; - VECTOR2I vts[] = { VECTOR2I( m_p0.x, m_p0.y ), - VECTOR2I( m_p0.x, m_p0.y + m_h ), - VECTOR2I( m_p0.x + m_w, m_p0.y + m_h ), - VECTOR2I( m_p0.x + m_w, m_p0.y ), - VECTOR2I( m_p0.x, m_p0.y ) }; + VECTOR2I vts[] = { VECTOR2I( m_p0.x, m_p0.y ), + VECTOR2I( m_p0.x, m_p0.y + m_h ), + VECTOR2I( m_p0.x + m_w, m_p0.y + m_h ), + VECTOR2I( m_p0.x + m_w, m_p0.y ), + VECTOR2I( m_p0.x, m_p0.y ) }; for( int i = 0; i < 4; i++ ) { diff --git a/include/math/math_util.h b/include/math/math_util.h index 812b52fba8..cb3ce50460 100644 --- a/include/math/math_util.h +++ b/include/math/math_util.h @@ -40,6 +40,11 @@ T rescale( T aNumerator, T aValue, T aDenominator ) return aNumerator * aValue / aDenominator; } +template +int sign( T val ) +{ + return ( T( 0 ) < val) - ( val < T( 0 ) ); +} // explicit specializations for integer types, taking care of overflow. template <> diff --git a/include/math/vector2d.h b/include/math/vector2d.h index feee5ff060..5bb43e5872 100644 --- a/include/math/vector2d.h +++ b/include/math/vector2d.h @@ -28,6 +28,7 @@ #ifndef VECTOR2D_H_ #define VECTOR2D_H_ +#include #include #include #include @@ -376,7 +377,7 @@ VECTOR2 VECTOR2::Resize( T aNewLength ) const return VECTOR2 ( ( x < 0 ? -1 : 1 ) * sqrt( rescale( l_sq_new, (extended_type) x * x, l_sq_current ) ), - ( y < 0 ? -1 : 1 ) * sqrt( rescale( l_sq_new, (extended_type) y * y, l_sq_current ) ) ); + ( y < 0 ? -1 : 1 ) * sqrt( rescale( l_sq_new, (extended_type) y * y, l_sq_current ) ) ) * sign( aNewLength ); } From 0ae6b4412e8ebf3dbfb263a6fa2a57a56bc45477 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 11:47:17 +0200 Subject: [PATCH 50/68] Added a missing file. --- include/geometry/shape_segment.h | 90 ++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 include/geometry/shape_segment.h diff --git a/include/geometry/shape_segment.h b/include/geometry/shape_segment.h new file mode 100644 index 0000000000..5f18760bd7 --- /dev/null +++ b/include/geometry/shape_segment.h @@ -0,0 +1,90 @@ +/* + * 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 + */ + +#ifndef __SHAPE_SEGMENT_H +#define __SHAPE_SEGMENT_H + +#include +#include + +class SHAPE_SEGMENT : public SHAPE { + +public: + SHAPE_SEGMENT(): + SHAPE( SH_SEGMENT ), m_width( 0 ) {}; + + SHAPE_SEGMENT( const VECTOR2I& aA, const VECTOR2I& aB, int aWidth = 0 ): + SHAPE( SH_SEGMENT ), m_seg( aA, aB ), m_width( aWidth ) {}; + + SHAPE_SEGMENT( const SEG& aSeg, int aWidth = 0 ): + SHAPE( SH_SEGMENT ), m_seg( aSeg ), m_width( aWidth ) {}; + + ~SHAPE_SEGMENT() {}; + + SHAPE* Clone() const + { + return new SHAPE_SEGMENT( m_seg, m_width ); + } + + const BOX2I BBox( int aClearance = 0 ) const + { + return BOX2I( m_seg.A, m_seg.B - m_seg.A ).Inflate( aClearance + m_width / 2 ); + } + + bool Collide( const SEG& aSeg, int aClearance = 0 ) const + { + return m_seg.Distance( aSeg ) <= m_width / 2 + aClearance; + } + + bool Collide( const VECTOR2I& aP, int aClearance = 0 ) const + { + return m_seg.Distance( aP ) <= m_width / 2 + aClearance; + } + + void SetSeg ( const SEG& aSeg ) + { + m_seg = aSeg; + } + + const SEG& GetSeg () const + { + return m_seg; + } + + void SetWidth ( int aWidth ) + { + m_width = aWidth; + } + + int GetWidth() const + { + return m_width; + } + +private: + SEG m_seg; + int m_width; +}; + +#endif From 922bf1ddeaffc6da1d58f0437e23914c7a693d10 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 12:08:29 +0200 Subject: [PATCH 51/68] Fixed freezing of GAL canvas if user chooses Cancel in the on close dialog. --- pcbnew/pcbframe.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 212dd6a83c..9695d39bb6 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -591,7 +591,6 @@ void PCB_EDIT_FRAME::OnQuit( wxCommandEvent& event ) void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) { m_canvas->SetAbortRequest( true ); - GetGalCanvas()->StopDrawing(); if( GetScreen()->IsModify() ) { @@ -615,6 +614,8 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) } } + GetGalCanvas()->StopDrawing(); + // Delete the auto save file if it exists. wxFileName fn = GetBoard()->GetFileName(); From 5bf50ee910cdd86104679428ab89dfb6aef44a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Wed, 14 May 2014 13:48:29 +0200 Subject: [PATCH 52/68] VIEW: added CalculateExtents() method --- common/view/view.cpp | 35 +++++++++++++++++++++++++++++++++++ include/view/view.h | 4 ++++ 2 files changed, 39 insertions(+) diff --git a/common/view/view.cpp b/common/view/view.cpp index 4bf71ec638..5e213c0c1d 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -1019,3 +1019,38 @@ void VIEW::UpdateItems() m_needsUpdate.clear(); } + +struct VIEW::extentsVisitor { + BOX2I extents; + bool first; + + extentsVisitor() + { + first = true; + } + + bool operator()( VIEW_ITEM* aItem ) + { + if(first) + extents = aItem->ViewBBox(); + else + extents.Merge ( aItem->ViewBBox() ); + return false; + } + }; + +const BOX2I VIEW::CalculateExtents() +{ + + extentsVisitor v; + BOX2I fullScene; + fullScene.SetMaximum(); + + + BOOST_FOREACH( VIEW_LAYER* l, m_orderedLayers ) + { + l->items->Query( fullScene, v ); + } + + return v.extents; +} diff --git a/include/view/view.h b/include/view/view.h index 694042724f..2930af1844 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -507,6 +507,8 @@ public: */ void UpdateItems(); + const BOX2I CalculateExtents() ; + static const int VIEW_MAX_LAYERS = 128; ///< maximum number of layers that may be shown private: @@ -534,6 +536,8 @@ private: struct unlinkItem; struct updateItemsColor; struct changeItemsDepth; + struct extentsVisitor; + ///* Redraws contents within rect aRect void redrawRect( const BOX2I& aRect ); From 5a51d11b781eb34d8a46599a0c5731f44cdea414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Wed, 14 May 2014 13:52:29 +0200 Subject: [PATCH 53/68] geometry: get rid of useless vertex references in SEG class --- include/geometry/seg.h | 58 ++++++----------------------- include/geometry/shape_line_chain.h | 2 +- 2 files changed, 12 insertions(+), 48 deletions(-) diff --git a/include/geometry/seg.h b/include/geometry/seg.h index 7e789f9d21..af8161bb80 100644 --- a/include/geometry/seg.h +++ b/include/geometry/seg.h @@ -46,17 +46,14 @@ public: * to an object the segment belongs to (e.g. a line chain) or references to locally stored * points (m_a, m_b). */ - VECTOR2I& A; - VECTOR2I& B; + VECTOR2I A; + VECTOR2I B; /** Default constructor * Creates an empty (0, 0) segment, locally-referenced */ - SEG() : A( m_a ), B( m_b ) + SEG() { - A = m_a; - B = m_b; - m_is_local = true; m_index = -1; } @@ -64,13 +61,10 @@ public: * Constructor * Creates a segment between (aX1, aY1) and (aX2, aY2), locally referenced */ - SEG( int aX1, int aY1, int aX2, int aY2 ) : A( m_a ), B( m_b ) + SEG( int aX1, int aY1, int aX2, int aY2 ) : + A ( VECTOR2I( aX1, aY1 ) ), + B ( VECTOR2I( aX2, aY2 ) ) { - m_a = VECTOR2I( aX1, aY1 ); - m_b = VECTOR2I( aX2, aY2 ); - A = m_a; - B = m_b; - m_is_local = true; m_index = -1; } @@ -78,11 +72,8 @@ public: * Constructor * Creates a segment between (aA) and (aB), locally referenced */ - SEG( const VECTOR2I& aA, const VECTOR2I& aB ) : A( m_a ), B( m_b ), m_a( aA ), m_b( aB ) + SEG( const VECTOR2I& aA, const VECTOR2I& aB ) : A( aA ), B( aB ) { - A = m_a; - B = m_b; - m_is_local = true; m_index = -1; } @@ -93,44 +84,24 @@ public: * @param aB reference to the end point in the parent shape * @param aIndex index of the segment within the parent shape */ - SEG ( VECTOR2I& aA, VECTOR2I& aB, int aIndex ) : A( aA ), B( aB ) + SEG ( const VECTOR2I& aA, const VECTOR2I& aB, int aIndex ) : A( aA ), B( aB ) { - m_is_local = false; m_index = aIndex; } /** * Copy constructor */ - SEG ( const SEG& aSeg ) : A( m_a ), B( m_b ) + SEG ( const SEG& aSeg ) : A( aSeg.A ), B( aSeg.B ), m_index ( aSeg.m_index ) { - if( aSeg.m_is_local ) - { - m_a = aSeg.m_a; - m_b = aSeg.m_b; - A = m_a; - B = m_b; - m_is_local = true; - m_index = -1; - } - else - { - A = aSeg.A; - B = aSeg.B; - m_index = aSeg.m_index; - m_is_local = false; - } } SEG& operator=( const SEG& aSeg ) { A = aSeg.A; B = aSeg.B; - m_a = aSeg.m_a; - m_b = aSeg.m_b; m_index = aSeg.m_index; - m_is_local = aSeg.m_is_local; - + return *this; } @@ -289,14 +260,8 @@ public: private: bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const; - ///> locally stored start/end coordinates (used when m_is_local == true) - VECTOR2I m_a, m_b; - ///> index withing the parent shape (used when m_is_local == false) int m_index; - - ///> locality flag - bool m_is_local; }; @@ -344,8 +309,7 @@ inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const inline std::ostream& operator<<( std::ostream& aStream, const SEG& aSeg ) { - if( aSeg.m_is_local ) - aStream << "[ local " << aSeg.A << " - " << aSeg.B << " ]"; + aStream << "[ " << aSeg.A << " - " << aSeg.B << " ]"; return aStream; } diff --git a/include/geometry/shape_line_chain.h b/include/geometry/shape_line_chain.h index b91e6a566c..0ff020bd32 100644 --- a/include/geometry/shape_line_chain.h +++ b/include/geometry/shape_line_chain.h @@ -445,7 +445,7 @@ public: struct compareOriginDistance { - compareOriginDistance( VECTOR2I& aOrigin ): + compareOriginDistance( const VECTOR2I& aOrigin ): m_origin( aOrigin ) {} From dd5558f65380df571ae7eb3e80f079766368bee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Wed, 14 May 2014 13:53:02 +0200 Subject: [PATCH 54/68] geometry: GetShape()->Shape() in indexed shape containers --- include/geometry/shape_index.h | 2 +- include/geometry/shape_index_list.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/geometry/shape_index.h b/include/geometry/shape_index.h index 24b174e1fa..49b0e124f9 100644 --- a/include/geometry/shape_index.h +++ b/include/geometry/shape_index.h @@ -43,7 +43,7 @@ template static const SHAPE* shapeFunctor( T aItem ) { - return aItem->GetShape(); + return aItem->Shape(); } diff --git a/include/geometry/shape_index_list.h b/include/geometry/shape_index_list.h index 0d0e644803..194ae5ffd9 100644 --- a/include/geometry/shape_index_list.h +++ b/include/geometry/shape_index_list.h @@ -30,7 +30,7 @@ template const SHAPE* defaultShapeFunctor( const T aItem ) { - return aItem->GetShape(); + return aItem->Shape(); } template > From e9afb10a9dc0034d4a6c8ae1ebb9e78729a139b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Wed, 14 May 2014 13:54:59 +0200 Subject: [PATCH 55/68] Switching top layer should update the layer widget --- pcbnew/pcbframe.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 9695d39bb6..b873ef95f7 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -591,6 +591,7 @@ void PCB_EDIT_FRAME::OnQuit( wxCommandEvent& event ) void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) { m_canvas->SetAbortRequest( true ); + GetGalCanvas()->StopDrawing(); if( GetScreen()->IsModify() ) { @@ -614,8 +615,6 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) } } - GetGalCanvas()->StopDrawing(); - // Delete the auto save file if it exists. wxFileName fn = GetBoard()->GetFileName(); @@ -914,6 +913,7 @@ void PCB_EDIT_FRAME::SetActiveLayer( LAYER_NUM aLayer, bool doLayerWidgetUpdate ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer = aLayer; SetHighContrastLayer( aLayer ); + SetTopLayer( aLayer ); if( doLayerWidgetUpdate ) syncLayerWidgetLayer(); From 061660e9e4a8cfb1aa43880c10087716352eaba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Wed, 14 May 2014 15:53:54 +0200 Subject: [PATCH 56/68] Long-awaited new version of the P&S router --- pcbnew/dialogs/dialog_pns_settings.cpp | 75 + pcbnew/dialogs/dialog_pns_settings.h | 45 + pcbnew/dialogs/dialog_pns_settings_base.cpp | 127 ++ pcbnew/dialogs/dialog_pns_settings_base.fbp | 1414 +++++++++++++++++ pcbnew/dialogs/dialog_pns_settings_base.h | 67 + pcbnew/dialogs/dialog_track_via_size.cpp | 91 ++ pcbnew/dialogs/dialog_track_via_size.h | 52 + pcbnew/dialogs/dialog_track_via_size_base.cpp | 59 + pcbnew/dialogs/dialog_track_via_size_base.fbp | 539 +++++++ pcbnew/dialogs/dialog_track_via_size_base.h | 54 + pcbnew/router/CMakeLists.txt | 64 +- pcbnew/router/direction.h | 77 +- pcbnew/router/pns_algo_base.cpp | 32 + pcbnew/router/pns_algo_base.h | 60 + pcbnew/router/pns_dragger.cpp | 301 ++++ pcbnew/router/pns_dragger.h | 135 ++ pcbnew/router/pns_index.h | 132 +- pcbnew/router/pns_item.cpp | 11 +- pcbnew/router/pns_item.h | 276 +++- pcbnew/router/pns_itemset.cpp | 26 +- pcbnew/router/pns_itemset.h | 30 +- pcbnew/router/pns_joint.h | 48 +- pcbnew/router/pns_layerset.h | 4 +- pcbnew/router/pns_line.cpp | 1135 +++++++------ pcbnew/router/pns_line.h | 264 +-- pcbnew/router/pns_line_placer.cpp | 720 ++++++--- pcbnew/router/pns_line_placer.h | 297 +++- pcbnew/router/pns_logger.cpp | 173 ++ pcbnew/router/pns_logger.h | 58 + pcbnew/router/pns_node.cpp | 469 ++++-- pcbnew/router/pns_node.h | 309 +++- pcbnew/router/pns_optimizer.cpp | 151 +- pcbnew/router/pns_optimizer.h | 15 +- pcbnew/router/pns_router.cpp | 554 ++++--- pcbnew/router/pns_router.h | 101 +- pcbnew/router/pns_routing_settings.cpp | 49 + pcbnew/router/pns_routing_settings.h | 134 +- pcbnew/router/pns_segment.h | 82 +- pcbnew/router/pns_shove.cpp | 1294 +++++++++++---- pcbnew/router/pns_shove.h | 109 +- pcbnew/router/pns_solid.cpp | 23 +- pcbnew/router/pns_solid.h | 34 +- pcbnew/router/pns_utils.cpp | 54 +- pcbnew/router/pns_utils.h | 14 +- pcbnew/router/pns_via.cpp | 132 +- pcbnew/router/pns_via.h | 46 +- pcbnew/router/pns_walkaround.cpp | 64 +- pcbnew/router/pns_walkaround.h | 37 +- pcbnew/router/range.h | 91 ++ pcbnew/router/router_preview_item.cpp | 235 ++- pcbnew/router/router_preview_item.h | 50 +- pcbnew/router/router_tool.cpp | 568 +++++-- pcbnew/router/router_tool.h | 26 +- pcbnew/router/time_limit.cpp | 46 + pcbnew/router/time_limit.h | 44 + pcbnew/router/trace.h | 16 +- 56 files changed, 8596 insertions(+), 2517 deletions(-) create mode 100644 pcbnew/dialogs/dialog_pns_settings.cpp create mode 100644 pcbnew/dialogs/dialog_pns_settings.h create mode 100644 pcbnew/dialogs/dialog_pns_settings_base.cpp create mode 100644 pcbnew/dialogs/dialog_pns_settings_base.fbp create mode 100644 pcbnew/dialogs/dialog_pns_settings_base.h create mode 100644 pcbnew/dialogs/dialog_track_via_size.cpp create mode 100644 pcbnew/dialogs/dialog_track_via_size.h create mode 100644 pcbnew/dialogs/dialog_track_via_size_base.cpp create mode 100644 pcbnew/dialogs/dialog_track_via_size_base.fbp create mode 100644 pcbnew/dialogs/dialog_track_via_size_base.h create mode 100644 pcbnew/router/pns_algo_base.cpp create mode 100644 pcbnew/router/pns_algo_base.h create mode 100644 pcbnew/router/pns_dragger.cpp create mode 100644 pcbnew/router/pns_dragger.h create mode 100644 pcbnew/router/pns_logger.cpp create mode 100644 pcbnew/router/pns_logger.h create mode 100644 pcbnew/router/pns_routing_settings.cpp create mode 100644 pcbnew/router/range.h create mode 100644 pcbnew/router/time_limit.cpp create mode 100644 pcbnew/router/time_limit.h diff --git a/pcbnew/dialogs/dialog_pns_settings.cpp b/pcbnew/dialogs/dialog_pns_settings.cpp new file mode 100644 index 0000000000..0368294ab1 --- /dev/null +++ b/pcbnew/dialogs/dialog_pns_settings.cpp @@ -0,0 +1,75 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2014 CERN + * Author: Maciej Suminski + * + * 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 3 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, see . + */ + +/** + * Push and Shove router settings dialog. + */ + +#include "dialog_pns_settings.h" +#include + +DIALOG_PNS_SETTINGS::DIALOG_PNS_SETTINGS( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ) : + DIALOG_PNS_SETTINGS_BASE( aParent ), m_settings( aSettings ) +{ + // "Figure out what's best" is not available yet + m_mode->Enable( RM_Smart, false ); + + // Load widgets' values from settings + m_mode->SetSelection( m_settings.Mode() ); + m_shoveVias->SetValue( m_settings.ShoveVias() ); + m_backPressure->SetValue( m_settings.JumpOverObstacles() ); + m_removeLoops->SetValue( m_settings.RemoveLoops() ); + m_suggestEnding->SetValue( m_settings.SuggestFinish() ); + m_autoNeckdown->SetValue( m_settings.SmartPads() ); + m_effort->SetValue( m_settings.OptimizerEffort() ); + m_smoothDragged->SetValue( m_settings.SmoothDraggedSegments() ); + m_violateDrc->SetValue( m_settings.CanViolateDRC() ); +} + + +void DIALOG_PNS_SETTINGS::OnClose( wxCloseEvent& aEvent ) +{ + // Do nothing, it is result of ESC pressing + EndModal( 0 ); +} + + +void DIALOG_PNS_SETTINGS::OnOkClick( wxCommandEvent& aEvent ) +{ + // Save widgets' values to settings + m_settings.SetMode( (PNS_MODE) m_mode->GetSelection() ); + m_settings.SetShoveVias( m_shoveVias->GetValue() ); + m_settings.SetJumpOverObstacles( m_backPressure->GetValue() ); + m_settings.SetRemoveLoops( m_removeLoops->GetValue() ); + m_settings.SetSuggestFinish ( m_suggestEnding->GetValue() ); + m_settings.SetSmartPads( m_autoNeckdown->GetValue() ); + m_settings.SetOptimizerEffort( (PNS_OPTIMIZATION_EFFORT) m_effort->GetValue() ); + m_settings.SetSmoothDraggedSegments( m_smoothDragged->GetValue() ); + m_settings.SetCanViolateDRC( m_violateDrc->GetValue() ); + + EndModal( 1 ); +} + + +void DIALOG_PNS_SETTINGS::OnCancelClick( wxCommandEvent& aEvent ) +{ + // Do nothing + EndModal( 0 ); +} diff --git a/pcbnew/dialogs/dialog_pns_settings.h b/pcbnew/dialogs/dialog_pns_settings.h new file mode 100644 index 0000000000..2241ed60dc --- /dev/null +++ b/pcbnew/dialogs/dialog_pns_settings.h @@ -0,0 +1,45 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2014 CERN + * Author: Maciej Suminski + * + * 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 3 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, see . + */ + +/** + * Push and Shove router settings dialog. + */ + +#ifndef __dialog_pns_settings__ +#define __dialog_pns_settings__ + +#include "dialog_pns_settings_base.h" + +class PNS_ROUTING_SETTINGS; + +class DIALOG_PNS_SETTINGS : public DIALOG_PNS_SETTINGS_BASE +{ + public: + DIALOG_PNS_SETTINGS( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ); + + virtual void OnClose( wxCloseEvent& aEvent ); + virtual void OnOkClick( wxCommandEvent& aEvent ); + virtual void OnCancelClick( wxCommandEvent& aEvent ); + + private: + PNS_ROUTING_SETTINGS& m_settings; +}; + +#endif // __dialog_pns_settings__ diff --git a/pcbnew/dialogs/dialog_pns_settings_base.cpp b/pcbnew/dialogs/dialog_pns_settings_base.cpp new file mode 100644 index 0000000000..b675f8fd9d --- /dev/null +++ b/pcbnew/dialogs/dialog_pns_settings_base.cpp @@ -0,0 +1,127 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 30 2013) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_pns_settings_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_PNS_SETTINGS_BASE::DIALOG_PNS_SETTINGS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bMainSizer; + bMainSizer = new wxBoxSizer( wxVERTICAL ); + + wxString m_modeChoices[] = { _("Highlight collisions"), _("Shove"), _("Walk around"), _("Figure out what's best") }; + int m_modeNChoices = sizeof( m_modeChoices ) / sizeof( wxString ); + m_mode = new wxRadioBox( this, wxID_ANY, _("Mode"), wxDefaultPosition, wxDefaultSize, m_modeNChoices, m_modeChoices, 1, wxRA_SPECIFY_COLS ); + m_mode->SetSelection( 1 ); + bMainSizer->Add( m_mode, 0, wxALL, 5 ); + + wxStaticBoxSizer* bOptions; + bOptions = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options") ), wxVERTICAL ); + + m_shoveVias = new wxCheckBox( this, wxID_ANY, _("Shove vias"), wxDefaultPosition, wxDefaultSize, 0 ); + bOptions->Add( m_shoveVias, 0, wxALL, 5 ); + + m_backPressure = new wxCheckBox( this, wxID_ANY, _("Jump over obstacles"), wxDefaultPosition, wxDefaultSize, 0 ); + bOptions->Add( m_backPressure, 0, wxALL, 5 ); + + m_removeLoops = new wxCheckBox( this, wxID_ANY, _("Remove redundant tracks"), wxDefaultPosition, wxDefaultSize, 0 ); + bOptions->Add( m_removeLoops, 0, wxALL, 5 ); + + m_autoNeckdown = new wxCheckBox( this, wxID_ANY, _("Automatic neckdown"), wxDefaultPosition, wxDefaultSize, 0 ); + bOptions->Add( m_autoNeckdown, 0, wxALL, 5 ); + + m_smoothDragged = new wxCheckBox( this, wxID_ANY, _("Smooth dragged segments"), wxDefaultPosition, wxDefaultSize, 0 ); + bOptions->Add( m_smoothDragged, 0, wxALL, 5 ); + + m_violateDrc = new wxCheckBox( this, wxID_ANY, _("Allow DRC violations"), wxDefaultPosition, wxDefaultSize, 0 ); + bOptions->Add( m_violateDrc, 0, wxALL, 5 ); + + m_suggestEnding = new wxCheckBox( this, wxID_ANY, _("Suggest track finish"), wxDefaultPosition, wxDefaultSize, 0 ); + m_suggestEnding->Enable( false ); + + bOptions->Add( m_suggestEnding, 0, wxALL, 5 ); + + wxBoxSizer* bEffort; + bEffort = new wxBoxSizer( wxHORIZONTAL ); + + m_effortLabel = new wxStaticText( this, wxID_ANY, _("Optimizer effort"), wxDefaultPosition, wxDefaultSize, 0 ); + m_effortLabel->Wrap( -1 ); + bEffort->Add( m_effortLabel, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bEffort->Add( 0, 0, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSlider; + bSlider = new wxBoxSizer( wxVERTICAL ); + + m_effort = new wxSlider( this, wxID_ANY, 1, 0, 2, wxDefaultPosition, wxDefaultSize, wxSL_AUTOTICKS|wxSL_BOTTOM|wxSL_HORIZONTAL|wxSL_TOP ); + bSlider->Add( m_effort, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSliderLabels; + bSliderLabels = new wxBoxSizer( wxHORIZONTAL ); + + m_lowLabel = new wxStaticText( this, wxID_ANY, _("low"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lowLabel->Wrap( -1 ); + m_lowLabel->SetFont( wxFont( 8, 70, 90, 90, false, wxEmptyString ) ); + + bSliderLabels->Add( m_lowLabel, 0, 0, 5 ); + + + bSliderLabels->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_highLabel = new wxStaticText( this, wxID_ANY, _("high"), wxDefaultPosition, wxDefaultSize, 0 ); + m_highLabel->Wrap( -1 ); + m_highLabel->SetFont( wxFont( 8, 70, 90, 90, false, wxEmptyString ) ); + + bSliderLabels->Add( m_highLabel, 0, 0, 5 ); + + + bSlider->Add( bSliderLabels, 1, wxEXPAND, 5 ); + + + bEffort->Add( bSlider, 1, wxEXPAND, 5 ); + + + bOptions->Add( bEffort, 1, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bButtons; + bButtons = new wxBoxSizer( wxHORIZONTAL ); + + m_ok = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ok->SetDefault(); + bButtons->Add( m_ok, 1, wxALL, 5 ); + + m_cancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + bButtons->Add( m_cancel, 1, wxALL, 5 ); + + + bOptions->Add( bButtons, 1, wxEXPAND, 5 ); + + + bMainSizer->Add( bOptions, 1, wxEXPAND, 5 ); + + + this->SetSizer( bMainSizer ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PNS_SETTINGS_BASE::OnClose ) ); + m_ok->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnOkClick ), NULL, this ); + m_cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnCancelClick ), NULL, this ); +} + +DIALOG_PNS_SETTINGS_BASE::~DIALOG_PNS_SETTINGS_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PNS_SETTINGS_BASE::OnClose ) ); + m_ok->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnOkClick ), NULL, this ); + m_cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnCancelClick ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_pns_settings_base.fbp b/pcbnew/dialogs/dialog_pns_settings_base.fbp new file mode 100644 index 0000000000..dd008e9e25 --- /dev/null +++ b/pcbnew/dialogs/dialog_pns_settings_base.fbp @@ -0,0 +1,1414 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_pns_settings_base + 1000 + none + 1 + DIALOG_PNS_SETTINGS_BASE + + . + + 1 + 1 + 1 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_PNS_SETTINGS_BASE + + 289,504 + wxDEFAULT_DIALOG_STYLE + + Interactive Router settings + + + + + + + + + + + + + + OnClose + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bMainSizer + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "Highlight collisions" "Shove" "Walk around" "Figure out what's best" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Mode + 1 + + 0 + + + 0 + + 1 + m_mode + 1 + + + protected + 1 + + Resizable + 1 + 1 + + wxRA_SPECIFY_COLS + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + wxID_ANY + Options + + bOptions + wxVERTICAL + none + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shove vias + + 0 + + + 0 + + 1 + m_shoveVias + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Jump over obstacles + + 0 + + + 0 + + 1 + m_backPressure + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Remove redundant tracks + + 0 + + + 0 + + 1 + m_removeLoops + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Automatic neckdown + + 0 + + + 0 + + 1 + m_autoNeckdown + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Smooth dragged segments + + 0 + + + 0 + + 1 + m_smoothDragged + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Allow DRC violations + + 0 + + + 0 + + 1 + m_violateDrc + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + + 1 + + 0 + 0 + wxID_ANY + Suggest track finish + + 0 + + + 0 + + 1 + m_suggestEnding + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + + bEffort + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Optimizer effort + + 0 + + + 0 + + 1 + m_effortLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + 0 + protected + 0 + + + + 5 + wxEXPAND + 1 + + + bSlider + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + 2 + + 1 + + 0 + + 0 + + 1 + m_effort + 1 + + + protected + 1 + + Resizable + 1 + + wxSL_AUTOTICKS|wxSL_BOTTOM|wxSL_HORIZONTAL|wxSL_TOP + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bSliderLabels + wxHORIZONTAL + none + + 5 + + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,90,8,70,0 + 0 + 0 + wxID_ANY + low + + 0 + + + 0 + + 1 + m_lowLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 5 + + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,90,8,70,0 + 0 + 0 + wxID_ANY + high + + 0 + + + 0 + + 1 + m_highLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bButtons + wxHORIZONTAL + none + + 5 + wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_OK + OK + + 0 + + + 0 + + 1 + m_ok + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnOkClick + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_CANCEL + Cancel + + 0 + + + 0 + + 1 + m_cancel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnCancelClick + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_pns_settings_base.h b/pcbnew/dialogs/dialog_pns_settings_base.h new file mode 100644 index 0000000000..ceb135dc58 --- /dev/null +++ b/pcbnew/dialogs/dialog_pns_settings_base.h @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 30 2013) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_PNS_SETTINGS_BASE_H__ +#define __DIALOG_PNS_SETTINGS_BASE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_PNS_SETTINGS_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_PNS_SETTINGS_BASE : public wxDialog +{ + private: + + protected: + wxRadioBox* m_mode; + wxCheckBox* m_shoveVias; + wxCheckBox* m_backPressure; + wxCheckBox* m_removeLoops; + wxCheckBox* m_autoNeckdown; + wxCheckBox* m_smoothDragged; + wxCheckBox* m_violateDrc; + wxCheckBox* m_suggestEnding; + wxStaticText* m_effortLabel; + wxSlider* m_effort; + wxStaticText* m_lowLabel; + wxStaticText* m_highLabel; + wxButton* m_ok; + wxButton* m_cancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } + virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_PNS_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Interactive Router settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 289,504 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~DIALOG_PNS_SETTINGS_BASE(); + +}; + +#endif //__DIALOG_PNS_SETTINGS_BASE_H__ diff --git a/pcbnew/dialogs/dialog_track_via_size.cpp b/pcbnew/dialogs/dialog_track_via_size.cpp new file mode 100644 index 0000000000..8a51cafdb4 --- /dev/null +++ b/pcbnew/dialogs/dialog_track_via_size.cpp @@ -0,0 +1,91 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2014 CERN + * Author: Maciej Suminski + * + * 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 3 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, see . + */ + +/** + * Push and Shove router track width and via size dialog. + */ + +#include "dialog_track_via_size.h" +#include +#include +#include + +DIALOG_TRACK_VIA_SIZE::DIALOG_TRACK_VIA_SIZE( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ) : + DIALOG_TRACK_VIA_SIZE_BASE( aParent ), + m_settings( aSettings ) +{ + // Load router settings to dialog fields + m_trackWidth->SetValue( To_User_Unit( m_trackWidth->GetUnits(), m_settings.GetTrackWidth() ) ); + m_viaDiameter->SetValue( To_User_Unit( m_viaDiameter->GetUnits(), m_settings.GetViaDiameter() ) ); + m_viaDrill->SetValue( To_User_Unit( m_viaDrill->GetUnits(), m_settings.GetViaDrill() ) ); + + m_trackWidth->SetFocus(); + + // Pressing ENTER when any of the text input fields is active applies changes + #if wxCHECK_VERSION( 3, 0, 0 ) + Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE::onOkClick ), NULL, this ); + #else + Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE::onOkClick ), NULL, this ); + #endif +} + + +bool DIALOG_TRACK_VIA_SIZE::check() +{ + // Wrong input + if( !m_trackWidth->GetValue() || !m_viaDiameter->GetValue() || !m_viaDrill->GetValue() ) + return false; + + // Via drill should be smaller than via diameter + if( *m_viaDrill->GetValue() >= m_viaDiameter->GetValue() ) + return false; + + return true; +} + + +void DIALOG_TRACK_VIA_SIZE::onClose( wxCloseEvent& aEvent ) +{ + EndModal( 0 ); +} + + +void DIALOG_TRACK_VIA_SIZE::onOkClick( wxCommandEvent& aEvent ) +{ + if( check() ) + { + // Store dialog values to the router settings + m_settings.SetTrackWidth( From_User_Unit( m_trackWidth->GetUnits(), *m_trackWidth->GetValue() ) ); + m_settings.SetViaDiameter( From_User_Unit( m_viaDiameter->GetUnits(), *m_viaDiameter->GetValue() ) ); + m_settings.SetViaDrill( From_User_Unit( m_viaDrill->GetUnits(), *m_viaDrill->GetValue() ) ); + EndModal( 1 ); + } + else + { + DisplayError( GetParent(), _( "Settings are incorrect" ) ); + m_trackWidth->SetFocus(); + } +} + + +void DIALOG_TRACK_VIA_SIZE::onCancelClick( wxCommandEvent& aEvent ) +{ + EndModal( 0 ); +} diff --git a/pcbnew/dialogs/dialog_track_via_size.h b/pcbnew/dialogs/dialog_track_via_size.h new file mode 100644 index 0000000000..92a03e8ec6 --- /dev/null +++ b/pcbnew/dialogs/dialog_track_via_size.h @@ -0,0 +1,52 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2014 CERN + * Author: Maciej Suminski + * + * 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 3 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, see . + */ + +/** + * Push and Shove router track width and via size dialog. + */ + +#ifndef __dialog_track_via_size__ +#define __dialog_track_via_size__ + +#include "dialog_track_via_size_base.h" + +class PNS_ROUTING_SETTINGS; + +/** Implementing DIALOG_TRACK_VIA_SIZE_BASE */ +class DIALOG_TRACK_VIA_SIZE : public DIALOG_TRACK_VIA_SIZE_BASE +{ + public: + /** Constructor */ + DIALOG_TRACK_VIA_SIZE( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ); + + protected: + // Routings settings that are modified by the dialog. + PNS_ROUTING_SETTINGS& m_settings; + + ///> Checks if values given in the dialog are sensible. + bool check(); + + // Handlers for DIALOG_TRACK_VIA_SIZE_BASE events. + void onClose( wxCloseEvent& aEvent ); + void onOkClick( wxCommandEvent& aEvent ); + void onCancelClick( wxCommandEvent& aEvent ); +}; + +#endif // __dialog_track_via_size__ diff --git a/pcbnew/dialogs/dialog_track_via_size_base.cpp b/pcbnew/dialogs/dialog_track_via_size_base.cpp new file mode 100644 index 0000000000..a402009da1 --- /dev/null +++ b/pcbnew/dialogs/dialog_track_via_size_base.cpp @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 30 2013) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_track_via_size_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_TRACK_VIA_SIZE_BASE::DIALOG_TRACK_VIA_SIZE_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizes; + bSizes = new wxBoxSizer( wxVERTICAL ); + + m_trackWidth = new WX_UNIT_TEXT( this, _("Track width:") ); + bSizes->Add( m_trackWidth, 0, wxALL, 5 ); + + m_viaDiameter = new WX_UNIT_TEXT( this, _("Via diameter:") ); + bSizes->Add( m_viaDiameter, 0, wxALL, 5 ); + + m_viaDrill = new WX_UNIT_TEXT( this, _("Via drill:") ); + bSizes->Add( m_viaDrill, 0, wxALL, 5 ); + + wxBoxSizer* bButtons; + bButtons = new wxBoxSizer( wxHORIZONTAL ); + + m_ok = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + bButtons->Add( m_ok, 1, wxALL, 5 ); + + m_cancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + bButtons->Add( m_cancel, 1, wxALL, 5 ); + + + bSizes->Add( bButtons, 0, wxEXPAND, 5 ); + + + this->SetSizer( bSizes ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onClose ) ); + m_ok->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onOkClick ), NULL, this ); + m_cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onCancelClick ), NULL, this ); +} + +DIALOG_TRACK_VIA_SIZE_BASE::~DIALOG_TRACK_VIA_SIZE_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onClose ) ); + m_ok->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onOkClick ), NULL, this ); + m_cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onCancelClick ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_track_via_size_base.fbp b/pcbnew/dialogs/dialog_track_via_size_base.fbp new file mode 100644 index 0000000000..61462d3330 --- /dev/null +++ b/pcbnew/dialogs/dialog_track_via_size_base.fbp @@ -0,0 +1,539 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_track_via_size_base + 1000 + none + 1 + DIALOG_TRACK_VIA_SIZE_BASE + + . + + 1 + 1 + 1 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_TRACK_VIA_SIZE_BASE + + 388,164 + wxDEFAULT_DIALOG_STYLE + + Track width and via size + + + + + + + + + + + + + + onClose + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bSizes + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + WX_UNIT_TEXT + 1 + m_trackWidth = new WX_UNIT_TEXT( this, _("Track width:") ); + + 1 + WX_UNIT_TEXT* m_trackWidth; + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + #include <wxunittext.h> + + 0 + + + 0 + + 1 + m_trackWidth + 1 + + + protected + 1 + + Resizable + + 1 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + WX_UNIT_TEXT + 1 + m_viaDiameter = new WX_UNIT_TEXT( this, _("Via diameter:") ); + + 1 + WX_UNIT_TEXT* m_viaDiameter; + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + #include <wxunittext.h> + + 0 + + + 0 + + 1 + m_viaDiameter + 1 + + + protected + 1 + + Resizable + + 1 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + WX_UNIT_TEXT + 1 + m_viaDrill = new WX_UNIT_TEXT( this, _("Via drill:") ); + + 1 + WX_UNIT_TEXT* m_viaDrill; + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + #include <wxunittext.h> + + 0 + + + 0 + + 1 + m_viaDrill + 1 + + + protected + 1 + + Resizable + + 1 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + bButtons + wxHORIZONTAL + none + + 5 + wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_OK + OK + + 0 + + + 0 + + 1 + m_ok + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onOkClick + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_CANCEL + Cancel + + 0 + + + 0 + + 1 + m_cancel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onCancelClick + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_track_via_size_base.h b/pcbnew/dialogs/dialog_track_via_size_base.h new file mode 100644 index 0000000000..de4f0e43a1 --- /dev/null +++ b/pcbnew/dialogs/dialog_track_via_size_base.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 30 2013) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_TRACK_VIA_SIZE_BASE_H__ +#define __DIALOG_TRACK_VIA_SIZE_BASE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_TRACK_VIA_SIZE_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_TRACK_VIA_SIZE_BASE : public wxDialog +{ + private: + + protected: + WX_UNIT_TEXT* m_trackWidth; + WX_UNIT_TEXT* m_viaDiameter; + WX_UNIT_TEXT* m_viaDrill; + wxButton* m_ok; + wxButton* m_cancel; + + // Virtual event handlers, overide them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onOkClick( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancelClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_TRACK_VIA_SIZE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Track width and via size"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 388,164 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~DIALOG_TRACK_VIA_SIZE_BASE(); + +}; + +#endif //__DIALOG_TRACK_VIA_SIZE_BASE_H__ diff --git a/pcbnew/router/CMakeLists.txt b/pcbnew/router/CMakeLists.txt index 329714658b..94d89b771c 100644 --- a/pcbnew/router/CMakeLists.txt +++ b/pcbnew/router/CMakeLists.txt @@ -11,40 +11,50 @@ include_directories( set( PCBNEW_PNS_SRCS direction.h - pns_via.h - pns_routing_settings.h - pns_shove.cpp - pns_line.cpp - pns_utils.h - pns_layerset.h + time_limit.h + time_limit.cpp trace.h - pns_line.h - pns_walkaround.cpp - pns_node.h - pns_line_placer.cpp - pns_utils.cpp - pns_solid.h - pns_item.cpp - pns_via.cpp - pns_node.cpp - pns_solid.cpp - pns_line_placer.h - pns_optimizer.h - pns_walkaround.h - pns_shove.h - pns_router.h - pns_router.cpp + + pns_algo_base.h + pns_algo_base.cpp + pns_dragger.cpp + pns_dragger.h pns_index.h pns_item.h - pns_optimizer.cpp - pns_joint.h - pns_segment.h + pns_item.cpp pns_itemset.h pns_itemset.cpp - router_tool.cpp - router_tool.h + pns_joint.h + pns_layerset.h + pns_line.h + pns_line.cpp + pns_line_placer.h + pns_line_placer.cpp + pns_logger.h + pns_logger.cpp + pns_node.h + pns_node.cpp + pns_optimizer.h + pns_optimizer.cpp + pns_router.h + pns_router.cpp + pns_routing_settings.h + pns_routing_settings.cpp + pns_segment.h + pns_shove.h + pns_shove.cpp + pns_solid.h + pns_solid.cpp + pns_utils.h + pns_utils.cpp + pns_via.h + pns_via.cpp + pns_walkaround.h + pns_walkaround.cpp router_preview_item.cpp router_preview_item.h + router_tool.cpp + router_tool.h ) add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} ) diff --git a/pcbnew/router/direction.h b/pcbnew/router/direction.h index ad38fcbdef..646c681cd2 100644 --- a/pcbnew/router/direction.h +++ b/pcbnew/router/direction.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -180,6 +180,11 @@ public: return ( m_dir % 2 ) == 1; } + bool IsDefined() const + { + return m_dir != UNDEFINED; + } + /** * Function BuildInitialTrace() * @@ -244,32 +249,75 @@ public: return aOther.m_dir != m_dir; } + /** + * Function Right() + * + * Returns the direction on the right side of this (i.e. turns right + * by 45 deg) + */ const DIRECTION_45 Right() const { DIRECTION_45 r; - r.m_dir = (Directions) (m_dir + 1); - - if( r.m_dir == NW ) - r.m_dir = N; + if ( m_dir != UNDEFINED ) + r.m_dir = static_cast( ( m_dir + 1 ) % 8 ); return r; } -private: - - template - int sign( T val ) const + /** + * Function Left() + * + * Returns the direction on the left side of this (i.e. turns left + * by 45 deg) + */ + const DIRECTION_45 Left() const { - return (T( 0 ) < val) - ( val < T( 0 ) ); + DIRECTION_45 l; + + if (m_dir == UNDEFINED) + return l; + + if(m_dir == N) + l.m_dir = NW; + else + l.m_dir = static_cast (m_dir - 1); + + return l; } + + + /** + * Function ToVector() + * + * Returns a unit vector corresponding to our direction. + */ + const VECTOR2I ToVector() const + { + switch(m_dir) + { + case N: return VECTOR2I(0, 1); + case S: return VECTOR2I(0, -1); + case E: return VECTOR2I(1, 0); + case W: return VECTOR2I(-1, 0); + case NE: return VECTOR2I(1, 1); + case NW: return VECTOR2I(-1, 1); + case SE: return VECTOR2I(1, -1); + case SW: return VECTOR2I(-1, -1); + + default: + return VECTOR2I(0, 0); + } + } + +private: + /** * Function construct() * Calculates the direction from a vector. If the vector's angle is not a multiple of 45 * degrees, the direction is rounded to the nearest octant. - * @param aVec our vector - */ + * @param aVec our vector */ void construct( const VECTOR2I& aVec ) { m_dir = UNDEFINED; @@ -321,8 +369,9 @@ private: m_dir = S; } } - - Directions m_dir; ///> our actual direction + + ///> our actual direction + Directions m_dir; }; #endif // __DIRECTION_H diff --git a/pcbnew/router/pns_algo_base.cpp b/pcbnew/router/pns_algo_base.cpp new file mode 100644 index 0000000000..7008665428 --- /dev/null +++ b/pcbnew/router/pns_algo_base.cpp @@ -0,0 +1,32 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#include "pns_algo_base.h" +#include "pns_router.h" + +PNS_ROUTING_SETTINGS& PNS_ALGO_BASE::Settings() const +{ + return m_router->Settings(); +} + +PNS_LOGGER *PNS_ALGO_BASE::Logger() +{ + return NULL; +} \ No newline at end of file diff --git a/pcbnew/router/pns_algo_base.h b/pcbnew/router/pns_algo_base.h new file mode 100644 index 0000000000..c274c15116 --- /dev/null +++ b/pcbnew/router/pns_algo_base.h @@ -0,0 +1,60 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#ifndef __PNS_ALGO_BASE_H +#define __PNS_ALGO_BASE_H + +#include "pns_routing_settings.h" + +class PNS_ROUTER; +class PNS_LOGGER; + +/** + * Class PNS_ALGO_BASE + * + * Base class for all P&S algorithms (shoving, walkaround, line placement, dragging, etc.) + * Holds a bunch of objects commonly used by all algorithms (P&S settings, parent router instance, logging) + **/ + +class PNS_ALGO_BASE { + +public: + PNS_ALGO_BASE ( PNS_ROUTER *aRouter ): + m_router ( aRouter ) + {}; + + virtual ~PNS_ALGO_BASE() {} + + ///> Returns the instance of our router + PNS_ROUTER *Router() const { + return m_router; + } + + ///> Returns current router settings + PNS_ROUTING_SETTINGS& Settings() const; + + ///> Returns the logger object, allowing to dump geometry to a file. + virtual PNS_LOGGER *Logger(); + +private: + PNS_ROUTER *m_router; +}; + +#endif diff --git a/pcbnew/router/pns_dragger.cpp b/pcbnew/router/pns_dragger.cpp new file mode 100644 index 0000000000..5361c641ec --- /dev/null +++ b/pcbnew/router/pns_dragger.cpp @@ -0,0 +1,301 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#include + +#include "pns_dragger.h" +#include "pns_shove.h" +#include "pns_router.h" + +PNS_DRAGGER::PNS_DRAGGER( PNS_ROUTER* aRouter ) : + PNS_ALGO_BASE ( aRouter ) +{ + m_world = NULL; + m_shove = NULL; +}; + +PNS_DRAGGER::~PNS_DRAGGER() +{ + if( m_shove ) + delete m_shove; +} + +void PNS_DRAGGER::SetWorld ( PNS_NODE *aWorld ) +{ + m_world = aWorld; +} + +bool PNS_DRAGGER::startDragSegment( const VECTOR2D& aP, PNS_SEGMENT *aSeg ) +{ + int w2 = aSeg->Width() / 2; + + m_draggedLine = m_world->AssembleLine ( aSeg, &m_draggedSegmentIndex ); + m_shove->SetInitialLine (m_draggedLine); + m_lastValidDraggedLine = *m_draggedLine; + m_lastValidDraggedLine.ClearSegmentLinks(); + + if( (aP - aSeg->Seg().A).EuclideanNorm() <= w2 ) + m_mode = CORNER; + else if( (aP - aSeg->Seg().B).EuclideanNorm() <= w2 ) + { + m_draggedSegmentIndex ++; + m_mode = CORNER; + } else + m_mode = SEGMENT; + return true; +} + +bool PNS_DRAGGER::startDragVia( const VECTOR2D& aP, PNS_VIA *aVia ) +{ + m_draggedVia = aVia; + m_initialVia = aVia; + m_mode = VIA; + + VECTOR2I p0 ( aVia->Pos() ); + PNS_JOINT *jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() ); + + BOOST_FOREACH(PNS_ITEM *item, jt->LinkList() ) + { + if(item->OfKind( PNS_ITEM::SEGMENT )) + { + int segIndex; + PNS_SEGMENT *seg = (PNS_SEGMENT *) item; + std::auto_ptr l ( m_world->AssembleLine(seg, &segIndex) ); + + if(segIndex != 0) + l->Reverse(); + + m_origViaConnections.push_back (*l); + + } + } + + + return true; +} + +bool PNS_DRAGGER::Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem ) +{ + m_shove = new PNS_SHOVE ( m_world, Router() ); + m_lastNode = NULL; + m_draggedItems.Clear(); + m_currentMode = Settings().Mode(); + + TRACE(2, "StartDragging: item %p [kind %d]", aStartItem % aStartItem->Kind()); + + switch( aStartItem->Kind() ) + { + case PNS_ITEM::SEGMENT: + return startDragSegment ( aP, static_cast (aStartItem) ); + case PNS_ITEM::VIA: + return startDragVia ( aP, static_cast (aStartItem) ); + default: + return false; + } +} + +bool PNS_DRAGGER::dragMarkObstacles(const VECTOR2I& aP) +{ + if(m_lastNode) + { + delete m_lastNode; + m_lastNode = NULL; + } + + switch(m_mode) + { + case SEGMENT: + case CORNER: + { + int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0; + PNS_LINE tmp (*m_draggedLine); + + if(m_mode == SEGMENT) + tmp.DragSegment ( aP, m_draggedSegmentIndex, thresh ); + else + tmp.DragCorner ( aP, m_draggedSegmentIndex, thresh ); + + m_lastNode = m_shove->CurrentNode()->Branch(); + + m_lastValidDraggedLine = tmp; + m_lastValidDraggedLine.ClearSegmentLinks(); + m_lastValidDraggedLine.Unmark(); + + m_lastNode->Add ( &m_lastValidDraggedLine ); + m_draggedItems = PNS_ITEMSET ( &m_lastValidDraggedLine ); + + break; + } + case VIA: // fixme... + { + m_lastNode = m_shove->CurrentNode()->Branch(); + dumbDragVia ( m_initialVia, m_lastNode, aP ); + + + break; + } + } + + if (Settings().CanViolateDRC()) + m_dragStatus = true; + else + m_dragStatus = !m_world->CheckColliding( m_draggedItems ); + + return true; +} + +void PNS_DRAGGER::dumbDragVia ( PNS_VIA *aVia, PNS_NODE *aNode, const VECTOR2I& aP ) +{ + // fixme: this is awful. + m_draggedVia = aVia->Clone(); + m_draggedVia->SetPos( aP ); + m_draggedItems.Clear(); + m_draggedItems.Add(m_draggedVia); + + m_lastNode->Remove ( aVia ); + m_lastNode->Add ( m_draggedVia ); + + BOOST_FOREACH(PNS_LINE &l, m_origViaConnections) + { + PNS_LINE origLine (l); + PNS_LINE *draggedLine = l.Clone(); + + draggedLine->DragCorner( aP, 0 ); + draggedLine->ClearSegmentLinks(); + + m_draggedItems.AddOwned( draggedLine ); + + m_lastNode->Remove ( &origLine ); + m_lastNode->Add ( draggedLine ); + } +} + +bool PNS_DRAGGER::dragShove(const VECTOR2I& aP) +{ + bool ok = false; + + + if(m_lastNode) + { + delete m_lastNode; + m_lastNode = NULL; + } + + switch(m_mode) + { + case SEGMENT: + case CORNER: + { + int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0; + PNS_LINE tmp (*m_draggedLine); + if(m_mode == SEGMENT) + tmp.DragSegment ( aP, m_draggedSegmentIndex, thresh ); + else + tmp.DragCorner ( aP, m_draggedSegmentIndex, thresh ); + + PNS_SHOVE::ShoveStatus st = m_shove->ShoveLines( tmp ); + + if(st == PNS_SHOVE::SH_OK) + ok = true; + else if (st == PNS_SHOVE::SH_HEAD_MODIFIED) + { + tmp = m_shove->NewHead(); + ok = true; + } + + m_lastNode = m_shove->CurrentNode()->Branch(); + + if(ok) + m_lastValidDraggedLine = tmp; + + m_lastValidDraggedLine.ClearSegmentLinks(); + m_lastValidDraggedLine.Unmark(); + m_lastNode->Add ( &m_lastValidDraggedLine ); + m_draggedItems = PNS_ITEMSET ( &m_lastValidDraggedLine ); + + break; + } + case VIA: + { + PNS_VIA *newVia; + PNS_SHOVE::ShoveStatus st = m_shove -> ShoveDraggingVia ( m_draggedVia, aP, &newVia ); + + if(st == PNS_SHOVE::SH_OK || st == PNS_SHOVE::SH_HEAD_MODIFIED) + ok = true; + + m_lastNode = m_shove->CurrentNode()->Branch(); + + if( ok ) + { + m_draggedVia = newVia; + m_draggedItems.Clear(); + } + + break; + } + + } + + m_dragStatus = ok; + return ok; +} + +bool PNS_DRAGGER::FixRoute( ) +{ + if(m_dragStatus) + { + Router()->CommitRouting( CurrentNode() ); + return true; + } + + return false; +} + +bool PNS_DRAGGER::Drag ( const VECTOR2I& aP ) +{ + switch ( m_currentMode ) + { + case RM_MarkObstacles: + return dragMarkObstacles (aP); + case RM_Shove: + case RM_Walkaround: + case RM_Smart: + return dragShove ( aP ); + default: + return false; + } +} + +PNS_NODE *PNS_DRAGGER::CurrentNode() const +{ + return m_lastNode; +} + +const PNS_ITEMSET PNS_DRAGGER::Traces() +{ + return m_draggedItems; +} + +PNS_LOGGER *PNS_DRAGGER::Logger() +{ + if(m_shove) + return m_shove->Logger(); + return NULL; +} diff --git a/pcbnew/router/pns_dragger.h b/pcbnew/router/pns_dragger.h new file mode 100644 index 0000000000..73d206589d --- /dev/null +++ b/pcbnew/router/pns_dragger.h @@ -0,0 +1,135 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#ifndef __PNS_DRAGGER_H +#define __PNS_DRAGGER_H + +#include + +#include "pns_node.h" +#include "pns_via.h" +#include "pns_line.h" +#include "pns_algo_base.h" +#include "pns_itemset.h" + +class PNS_ROUTER; +class PNS_SHOVE; +class PNS_OPTIMIZER; +class PNS_ROUTER_BASE; + +/** + * Class PNS_DRAGGER + * + * Via, segment and corner dragging algorithm. + */ + +class PNS_DRAGGER : public PNS_ALGO_BASE +{ +public: + + PNS_DRAGGER( PNS_ROUTER *aRouter ); + ~PNS_DRAGGER(); + + /** + * Function SetWorld() + * + * Sets the board to work on. + */ + void SetWorld ( PNS_NODE *aWorld ); + + + /** + * Function Start() + * + * Starts routing a single track at point aP, taking item aStartItem as anchor + * (unless NULL). Returns true if a dragging operation has started. + */ + bool Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem ); + + /** + * Function Drag() + * + * Drags the current segment/corner/via to the point aP. + * @return true, if dragging finished with success. + */ + bool Drag ( const VECTOR2I& aP ); + + /** + * Function FixRoute() + * + * Checks if the result of current dragging operation is correct + * and eventually commits it to the world. + * @return true, if dragging finished with success. + */ + bool FixRoute ( ); + + /** + * Function CurrentNode() + * + * Returns the most recent world state, including all + * items changed due to dragging operation. + */ + + PNS_NODE* CurrentNode() const; + + /** + * Function Traces() + * + * Returns the set of dragged items. + */ + const PNS_ITEMSET Traces(); + + /// @copydoc PNS_ALGO_BASE::Logger() + virtual PNS_LOGGER *Logger(); + +private: + + typedef std::pair LinePair; + typedef std::vector LinePairVec; + + enum DragMode { + CORNER = 0, + SEGMENT, + VIA + }; + + bool dragMarkObstacles(const VECTOR2I& aP); + bool dragShove(const VECTOR2I& aP); + bool startDragSegment( const VECTOR2D& aP, PNS_SEGMENT *aSeg ); + bool startDragVia( const VECTOR2D& aP, PNS_VIA *aVia ); + void dumbDragVia ( PNS_VIA *aVia, PNS_NODE *aNode, const VECTOR2I& aP ); + + PNS_NODE * m_world; + PNS_NODE * m_lastNode; + DragMode m_mode; + PNS_LINE * m_draggedLine; + PNS_VIA * m_draggedVia; + PNS_LINE m_lastValidDraggedLine; + PNS_SHOVE * m_shove; + int m_draggedSegmentIndex; + bool m_dragStatus; + PNS_MODE m_currentMode; + std::vector m_origViaConnections; + std::vector m_draggedViaConnections; + PNS_VIA * m_initialVia; + PNS_ITEMSET m_draggedItems; +}; + +#endif diff --git a/pcbnew/router/pns_index.h b/pcbnew/router/pns_index.h index 05d612e597..841f61bc1a 100644 --- a/pcbnew/router/pns_index.h +++ b/pcbnew/router/pns_index.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,12 +15,15 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_INDEX_H #define __PNS_INDEX_H +#include +#include + #include #include @@ -33,7 +36,7 @@ * Class PNS_INDEX * * Custom spatial index, holding our board items and allowing for very fast searches. Items - * are assigned to separate R-Tree subundices depending on their type and spanned layers, reducing + * are assigned to separate R-Tree subindices depending on their type and spanned layers, reducing * overlap and improving search time. **/ @@ -47,30 +50,93 @@ public: PNS_INDEX(); ~PNS_INDEX(); + /** + * Function Add() + * + * Adds item to the spatial index. + */ void Add( PNS_ITEM* aItem ); + + /** + * Function Remove() + * + * Removes an item from the spatial index. + */ void Remove( PNS_ITEM* aItem ); + + /** + * Function Add() + * + * Replaces one item with another. + */ void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ); + /** + * Function Query() + * + * Searches items in the index that are in proximity of aItem. + * For each item, function object aVisitor is called. Only items on + * overlapping layers are considered. + * + * @param aItem item to search against + * @param aMinDistance proximity distance (wrs to the item's shape) + * @param aVisitor function object called on each found item. Return + false from the visitor to stop searching. + * @return number of items found. + */ template - int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ); + int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& aVisitor ); + /** + * Function Query() + * + * Searches items in the index that are in proximity of aShape. + * For each item, function object aVisitor is called. Treats all + * layers as colliding. + * + * @param aShape shape to search against + * @param aMinDistance proximity distance (wrs to the item's shape) + * @param aVisitor function object called on each found item. Return + false from the visitor to stop searching. + * @return number of items found. + */ template - int Query( const SHAPE* aShape, int aMinDistance, Visitor& v ); + int Query( const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ); + /** + * Function Clear() + * + * Removes all items from the index. + */ void Clear(); + /** + * Function GetItemsForNet() + * + * Returns list of all items in a given net. + */ NetItemsList* GetItemsForNet( int aNet ); - - ItemSet::iterator begin() { return m_allItems.begin(); } - ItemSet::iterator end() { return m_allItems.end(); } - + + /** + * Function Contains() + * + * Returns true if item aItem exists in the index. + */ bool Contains( PNS_ITEM* aItem ) const { return m_allItems.find( aItem ) != m_allItems.end(); } + /** + * Function Size() + * + * Returns number of items stored in the index. + */ int Size() const { return m_allItems.size(); } + ItemSet::iterator begin() { return m_allItems.begin(); } + ItemSet::iterator end() { return m_allItems.end(); } + private: static const int MaxSubIndices = 64; static const int SI_Multilayer = 2; @@ -81,7 +147,7 @@ private: static const int SI_PadsBottom = 1; template - int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ); + int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ); ItemShapeIndex* getSubindex( const PNS_ITEM* aItem ); @@ -101,9 +167,9 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) { int idx_n = -1; - const PNS_LAYERSET l = aItem->GetLayers(); + const PNS_LAYERSET l = aItem->Layers(); - switch( aItem->GetKind() ) + switch( aItem->Kind() ) { case PNS_ITEM::VIA: idx_n = SI_Multilayer; @@ -113,9 +179,9 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) { if( l.IsMultilayer() ) idx_n = SI_Multilayer; - else if( l.Start() == 0 ) // fixme: use kicad layer codes + else if( l.Start() == LAYER_N_BACK) // fixme: use kicad layer codes idx_n = SI_PadsTop; - else if( l.Start() == 15 ) + else if( l.Start() == LAYER_N_FRONT ) idx_n = SI_PadsBottom; break; @@ -143,9 +209,11 @@ void PNS_INDEX::Add( PNS_ITEM* aItem ) { ItemShapeIndex* idx = getSubindex( aItem ); + + idx->Add( aItem ); m_allItems.insert( aItem ); - int net = aItem->GetNet(); + int net = aItem->Net(); if( net >= 0 ) { @@ -161,7 +229,7 @@ void PNS_INDEX::Remove( PNS_ITEM* aItem ) idx->Remove( aItem ); m_allItems.erase( aItem ); - int net = aItem->GetNet(); + int net = aItem->Net(); if( net >= 0 && m_netMap.find( net ) != m_netMap.end() ) m_netMap[net].remove( aItem ); @@ -176,43 +244,43 @@ void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) template -int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ) +int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ) { if( !m_subIndices[index] ) return 0; - return m_subIndices[index]->Query( aShape, aMinDistance, v, false ); + return m_subIndices[index]->Query( aShape, aMinDistance, aVisitor, false ); } template -int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) +int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& aVisitor ) { - const SHAPE* shape = aItem->GetShape(); + const SHAPE* shape = aItem->Shape(); int total = 0; - total += querySingle( SI_Multilayer, shape, aMinDistance, v ); + total += querySingle( SI_Multilayer, shape, aMinDistance, aVisitor ); - const PNS_LAYERSET layers = aItem->GetLayers(); + const PNS_LAYERSET layers = aItem->Layers(); if( layers.IsMultilayer() ) { - total += querySingle( SI_PadsTop, shape, aMinDistance, v ); - total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); + total += querySingle( SI_PadsTop, shape, aMinDistance, aVisitor ); + total += querySingle( SI_PadsBottom, shape, aMinDistance, aVisitor ); for( int i = layers.Start(); i <= layers.End(); ++i ) - total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v ); + total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, aVisitor ); } else { int l = layers.Start(); - if( l == 0 ) - total += querySingle( SI_PadsTop, shape, aMinDistance, v ); - else if( l == 15 ) - total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); + if( l == LAYER_N_BACK ) + total += querySingle( SI_PadsTop, shape, aMinDistance, aVisitor ); + else if( l == LAYER_N_FRONT ) + total += querySingle( SI_PadsBottom, shape, aMinDistance, aVisitor ); - total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v ); + total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, aVisitor ); } return total; @@ -220,12 +288,12 @@ int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) template -int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v ) +int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ) { int total = 0; for( int i = 0; i < MaxSubIndices; i++ ) - total += querySingle( i, aShape, aMinDistance, v ); + total += querySingle( i, aShape, aMinDistance, aVisitor ); return total; } diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp index 68e04a41c0..6ec4b77989 100644 --- a/pcbnew/router/pns_item.cpp +++ b/pcbnew/router/pns_item.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include "pns_item.h" @@ -32,7 +32,7 @@ bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeed if( !m_layers.Overlaps( aOther->m_layers ) ) return false; - return GetShape()->Collide( aOther->GetShape(), aClearance ); + return Shape()->Collide( aOther->Shape(), aClearance ); // fixme: MTV } @@ -50,7 +50,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, const PNS_LINE* line = static_cast( aOther ); if( line->EndsWithVia() ) - return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, + return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV, aMTV ); } @@ -58,7 +58,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, } -const std::string PNS_ITEM::GetKindStr() const +const std::string PNS_ITEM::KindStr() const { switch( m_kind ) { @@ -85,4 +85,5 @@ const std::string PNS_ITEM::GetKindStr() const PNS_ITEM::~PNS_ITEM() { + } diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index c375a7ada5..0bc03b8ba7 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_ITEM_H @@ -26,18 +26,25 @@ #include #include +#include "trace.h" + #include "pns_layerset.h" class BOARD_CONNECTED_ITEM; class PNS_NODE; +enum LineMarker { + MK_HEAD = ( 1 << 0 ), + MK_VIOLATION = ( 1 << 3 ), + MK_LOCKED = ( 1 << 4 ) +}; + /** * Class PNS_ITEM * * Base class for PNS router board items. Implements the shared properties of all PCB items - * net, spanned layers, geometric shape & refererence to owning model. */ - class PNS_ITEM { public: @@ -60,8 +67,9 @@ public: m_movable = true; m_kind = aKind; m_parent = NULL; - m_world = NULL; m_owner = NULL; + m_marker = 0; + m_rank = -1; } PNS_ITEM( const PNS_ITEM& aOther ) @@ -70,61 +78,203 @@ public: m_net = aOther.m_net; m_movable = aOther.m_movable; m_kind = aOther.m_kind; - m_world = aOther.m_world; m_parent = aOther.m_parent; m_owner = NULL; + m_marker = aOther.m_marker; + m_rank = aOther.m_rank; } virtual ~PNS_ITEM(); - virtual PNS_ITEM* Clone() const = 0; + /** + * Function Clone() + * + * Returns a deep copy of the item + */ + virtual PNS_ITEM* Clone( ) const = 0; - ///> Returns a convex polygon "hull" of a the item, that is used as the walkaround - /// path. - /// aClearance defines how far from the body of the item the hull should be, - /// aWalkaroundThickness is the width of the line that walks around this hull. + /* + * Function Hull() + * + * Returns a convex polygon "hull" of a the item, that is used as the walk-around + * path. + * @param aClearance defines how far from the body of the item the hull should be, + * @param aWalkaroundThickness is the width of the line that walks around this hull. + */ virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const { return SHAPE_LINE_CHAIN(); }; - PnsKind GetKind() const { return m_kind; } - bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; } + /** + * Function Kind() + * + * Returns the type (kind) of the item + */ + PnsKind Kind() const + { + return m_kind; + } + + /** + * Function OfKind() + * + * Returns true if the item's type matches the mask aKindMask. + */ + bool OfKind( int aKindMask ) const + { + return (aKindMask & m_kind) != 0; + } - const std::string GetKindStr() const; + /** + * Function KindStr() + * + * Returns the kind of the item, as string + */ + const std::string KindStr() const; - ///> Gets/Sets the corresponding parent object in the host application's model (pcbnew) - void SetParent( BOARD_CONNECTED_ITEM* aParent ) { m_parent = aParent; } - BOARD_CONNECTED_ITEM* GetParent() const { return m_parent; } + /** + * Function SetParent() + * + * Sets the corresponding parent object in the host application's model. + */ + void SetParent( BOARD_CONNECTED_ITEM* aParent ) + { + m_parent = aParent; + } + + /** + * Function Parent() + * + * Returns the corresponding parent object in the host application's model. + */ + BOARD_CONNECTED_ITEM* Parent() const + { + return m_parent; + } - ///> Net accessors - int GetNet() const { return m_net; } - void SetNet( int aNet ) { m_net = aNet; } + /** + * Function SetNet() + * + * Sets the item's net to aNet + */ + void SetNet( int aNet ) + { + m_net = aNet; + } - ///> Layers accessors - const PNS_LAYERSET& GetLayers() const { return m_layers; } - void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; } + /** + * Function Net() + * + * Returns the item's net. + */ + int Net() const + { + return m_net; + } + + /** + * Function SetLayers() + * + * Sets the layers spanned by the item to aLayers. + */ + void SetLayers( const PNS_LAYERSET& aLayers ) + { + m_layers = aLayers; + } + + /** + * Function SetLayer() + * + * Sets the layers spanned by the item to a single layer aLayer. + */ void SetLayer( int aLayer ) { m_layers = PNS_LAYERSET( aLayer, aLayer ); } - ///> Ownership management. An item can belong to a single PNS_NODE or stay unowned. - void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; } - bool BelongsTo( PNS_NODE* aNode ) const { return m_owner == aNode; } - PNS_NODE* GetOwner() const { return m_owner; } + /** + * Function Layers() + * + * Returns the contiguous set of layers spanned by the item. + */ + const PNS_LAYERSET& Layers() const + { + return m_layers; + } + + /** + * Function Layer() + * + * Returns the item's layer, for single-layered items only. + */ + virtual int Layer() const + { + return Layers().Start(); + } - ///> Sets the world that is used for collision resolution. - void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; } - PNS_NODE* GetWorld() const { return m_world; } + /** + * Function LayersOverlap() + * + * Returns true if the set of layers spanned by aOther overlaps our + * layers. + */ + bool LayersOverlap( const PNS_ITEM *aOther ) const + { + return Layers().Overlaps( aOther->Layers() ); + } - ///> Collision function. Checks if the item aOther is closer to us than - /// aClearance and returns true if so. It can also calculate a minimum translation vector that - /// resolves the collision if needed. + /** + * Functon SetOwner() + * + * Sets the node that owns this item. An item can belong to a single + * PNS_NODE or stay unowned. + */ + void SetOwner( PNS_NODE* aOwner ) + { + m_owner = aOwner; + } + + /** + * Function BelongsTo() + * + * Returns true if the item is owned by the node aNode. + */ + bool BelongsTo( PNS_NODE* aNode ) const + { + return m_owner == aNode; + } + + /** + * Function Owner() + * + * Returns the owner of this item, or NULL if there's none. + */ + PNS_NODE* Owner() const { return m_owner; } + + + /** + * Function Collide() + * + * Checks for a collision (clearance violation) with between us and item aOther. + * Collision checking takes all PCB stuff into accound (layers, nets, DRC rules). + * Optionally returns a minimum translation vector for force propagation + * algorithm. + * + * @param aOther item to check collision against + * @param aClearance desired clearance + * @param aNeedMTV when true, the minimum translation vector is calculated + * @param aMTV the minimum translation vector + * @param true, if a collision was found. + */ virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; - ///> A shortcut without MTV calculation + /** + * Function Collide() + * + * A shortcut for PNS_ITEM::Colllide() without MTV stuff. + */ bool Collide( const PNS_ITEM* aOther, int aClearance ) const { VECTOR2I dummy; @@ -132,26 +282,68 @@ public: return Collide( aOther, aClearance, false, dummy ); } - ///> Returns the geometric shape of the item - virtual const SHAPE* GetShape() const + /** + * Function Shape() + * + * Returns the geometrical shape of the item. Used + * for collision detection & spatial indexing. + */ + virtual const SHAPE* Shape() const { return NULL; } + virtual void Mark(int aMarker) + { + m_marker = aMarker; + } + + virtual void Unmark () + { + m_marker = 0; + } + + virtual int Marker() const + { + return m_marker; + } + + virtual void SetRank ( int aRank ) + { + m_rank = aRank; + } + + virtual int Rank() const + { + return m_rank; + } + + virtual VECTOR2I Anchor(int n) const + { + return VECTOR2I (); + }; + + virtual int AnchorCount() const + { + return 0; + } + private: + bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; protected: - PnsKind m_kind; + PnsKind m_kind; - BOARD_CONNECTED_ITEM* m_parent; - PNS_NODE* m_world; - PNS_NODE* m_owner; - PNS_LAYERSET m_layers; + BOARD_CONNECTED_ITEM *m_parent; + PNS_NODE *m_owner; + PNS_LAYERSET m_layers; - bool m_movable; - int m_net; + bool m_movable; + int m_net; + int m_marker; + int m_rank; }; #endif // __PNS_ITEM_H diff --git a/pcbnew/router/pns_itemset.cpp b/pcbnew/router/pns_itemset.cpp index ebe69dc555..fccc5eccae 100644 --- a/pcbnew/router/pns_itemset.cpp +++ b/pcbnew/router/pns_itemset.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include @@ -23,16 +23,30 @@ #include "pns_itemset.h" -PNS_ITEMSET::PNS_ITEMSET() +PNS_ITEMSET::PNS_ITEMSET( PNS_ITEM *aInitialItem ) { + if(aInitialItem) + m_items.push_back(aInitialItem); } PNS_ITEMSET::~PNS_ITEMSET() { + Clear(); } +void PNS_ITEMSET::Clear() +{ + BOOST_FOREACH(PNS_ITEM *item, m_ownedItems) + { + delete item; + } + + m_items.clear(); + m_ownedItems.clear(); +} + PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd ) { ItemVector newItems; @@ -45,7 +59,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd ) BOOST_FOREACH( PNS_ITEM * item, m_items ) - if( item->GetLayers().Overlaps( l ) ) + if( item->Layers().Overlaps( l ) ) newItems.push_back( item ); m_items = newItems; @@ -59,7 +73,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask ) BOOST_FOREACH( PNS_ITEM * item, m_items ) - if( item->GetKind() & aKindMask ) + if( item->OfKind ( aKindMask ) ) newItems.push_back( item ); m_items = newItems; @@ -73,7 +87,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet ) BOOST_FOREACH( PNS_ITEM * item, m_items ) - if( item->GetNet() == aNet ) + if( item->Net() == aNet ) newItems.push_back( item ); m_items = newItems; diff --git a/pcbnew/router/pns_itemset.h b/pcbnew/router/pns_itemset.h index da2c4a6634..9a6aaab3a8 100644 --- a/pcbnew/router/pns_itemset.h +++ b/pcbnew/router/pns_itemset.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_ITEMSET_H @@ -37,10 +37,25 @@ class PNS_ITEMSET public: typedef std::vector ItemVector; - PNS_ITEMSET(); + PNS_ITEMSET( PNS_ITEM *aInitialItem = NULL ); + + PNS_ITEMSET (const PNS_ITEMSET &aOther ) + { + m_items = aOther.m_items; + m_ownedItems = ItemVector(); + } + + const PNS_ITEMSET& operator= (const PNS_ITEMSET &aOther) + { + m_items = aOther.m_items; + m_ownedItems = ItemVector(); + return *this; + } + ~PNS_ITEMSET(); ItemVector& Items() { return m_items; } + const ItemVector& CItems() const { return m_items; } PNS_ITEMSET& FilterLayers( int aStart, int aEnd = -1 ); PNS_ITEMSET& FilterKinds( int aKindMask ); @@ -55,8 +70,17 @@ public: PNS_ITEM* Get( int index ) const { return m_items[index]; } + void Clear(); + + void AddOwned ( PNS_ITEM *aItem ) + { + m_items.push_back( aItem ); + m_ownedItems.push_back( aItem ); + } + private: ItemVector m_items; + ItemVector m_ownedItems; }; #endif diff --git a/pcbnew/router/pns_joint.h b/pcbnew/router/pns_joint.h index 4fd63e177a..699481538f 100644 --- a/pcbnew/router/pns_joint.h +++ b/pcbnew/router/pns_joint.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_JOINT_H @@ -72,7 +72,7 @@ public: m_layers = b.m_layers; } - PNS_ITEM* Clone() const + PNS_ITEM* Clone ( ) const { assert( false ); return NULL; @@ -85,15 +85,15 @@ public: if( m_linkedItems.size() != 2 ) return false; - if( m_linkedItems[0]->GetKind() != SEGMENT || - m_linkedItems[1]->GetKind() != SEGMENT ) + if( m_linkedItems[0]->Kind() != SEGMENT || + m_linkedItems[1]->Kind() != SEGMENT ) return false; PNS_SEGMENT* seg1 = static_cast( m_linkedItems[0] ); PNS_SEGMENT* seg2 = static_cast( m_linkedItems[1] ); - // joints between segments of different widths are not trivial. - return seg1->GetWidth() == seg2->GetWidth(); + // joints between segments of different widths are not considered trivial. + return seg1->Width() == seg2->Width(); } ///> Links the joint to a given board item (when it's added to the PNS_NODE) @@ -131,11 +131,35 @@ public: return static_cast( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] ); } + PNS_VIA *Via() + { + for( LinkedItems::iterator i = m_linkedItems.begin(); + i != m_linkedItems.end(); ++i ) + if( (*i)->Kind() == PNS_ITEM::VIA ) + return (PNS_VIA *)(*i); + return NULL; + } + /// trivial accessors - const HashTag& GetTag() const { return m_tag; } - const VECTOR2I& GetPos() const { return m_tag.pos; } - int GetNet() const { return m_tag.net; } - LinkedItems& GetLinkList() { return m_linkedItems; }; + const HashTag& Tag() const + { + return m_tag; + } + + const VECTOR2I& Pos() const + { + return m_tag.pos; + } + + int Net() const + { + return m_tag.net; + } + + LinkedItems& LinkList() + { + return m_linkedItems; + } ///> Returns the number of linked items of types listed in aMask. int LinkCount( int aMask = -1 ) const @@ -144,7 +168,7 @@ public: for( LinkedItems::const_iterator i = m_linkedItems.begin(); i != m_linkedItems.end(); ++i ) - if( (*i)->GetKind() & aMask ) + if( (*i)->Kind() & aMask ) n++; return n; diff --git a/pcbnew/router/pns_layerset.h b/pcbnew/router/pns_layerset.h index eedc00e31e..d99ef57040 100644 --- a/pcbnew/router/pns_layerset.h +++ b/pcbnew/router/pns_layerset.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_LAYERSET_H diff --git a/pcbnew/router/pns_line.cpp b/pcbnew/router/pns_line.cpp index 63011b6b75..8cc7bcea87 100644 --- a/pcbnew/router/pns_line.cpp +++ b/pcbnew/router/pns_line.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include @@ -29,262 +29,117 @@ #include "pns_utils.h" #include "pns_router.h" +#include + using boost::optional; -PNS_LINE* PNS_LINE::Clone() const +PNS_LINE::PNS_LINE( const PNS_LINE& aOther ) : + PNS_ITEM( aOther ), + m_line( aOther.m_line ), + m_width( aOther.m_width ) { - PNS_LINE* l = new PNS_LINE(); + m_net = aOther.m_net; + m_movable = aOther.m_movable; + m_layers = aOther.m_layers; + m_owner = aOther.m_owner; + m_via = aOther.m_via; + m_hasVia = aOther.m_hasVia; + m_marker = aOther.m_marker; + m_rank = aOther.m_rank; - l->m_line = m_line; - l->m_width = m_width; - l->m_layers = m_layers; - l->m_net = m_net; - l->m_movable = m_movable; - l->m_segmentRefs = NULL; - l->m_hasVia = m_hasVia; - l->m_via = m_via; + copyLinks ( &aOther ); +} +PNS_LINE::~PNS_LINE() +{ + if( m_segmentRefs ) + delete m_segmentRefs; +}; + + +const PNS_LINE& PNS_LINE :: operator= (const PNS_LINE& aOther) +{ + m_line = aOther.m_line; + m_width = aOther.m_width; + m_net = aOther.m_net; + m_movable = aOther.m_movable; + m_owner = aOther.m_owner; + m_layers = aOther.m_layers; + m_via = aOther.m_via; + m_hasVia = aOther.m_hasVia; + m_marker = aOther.m_marker; + m_rank = aOther.m_rank; + + copyLinks ( &aOther ); + + return *this; +} + +PNS_LINE* PNS_LINE::Clone( ) const +{ + PNS_LINE* l = new PNS_LINE( *this ); return l; } - -PNS_LINE* PNS_LINE::CloneProperties() const +void PNS_LINE::Mark(int aMarker) { - PNS_LINE* l = new PNS_LINE(); + m_marker = aMarker; + + if(m_segmentRefs) + { + BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) + s->Mark(aMarker); + } +} - l->m_width = m_width; - l->m_layers = m_layers; - l->m_net = m_net; - l->m_movable = m_movable; +void PNS_LINE::Unmark () +{ + if(m_segmentRefs) + { + BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) + s->Unmark(); + } + m_marker = 0; +} - return l; +int PNS_LINE::Marker()const +{ + int marker = m_marker; + if(m_segmentRefs) + { + BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) + marker |= s->Marker(); + } + return marker; +} + +void PNS_LINE::copyLinks( const PNS_LINE *aParent ) +{ + if(aParent->m_segmentRefs == NULL) + { + m_segmentRefs = NULL; + return; + } + + m_segmentRefs = new SegmentRefs(); + *m_segmentRefs = *aParent->m_segmentRefs; } -PNS_SEGMENT* PNS_SEGMENT::Clone() const +PNS_SEGMENT* PNS_SEGMENT::Clone( ) const { PNS_SEGMENT* s = new PNS_SEGMENT; - s->m_width = m_width; + s->m_seg = m_seg; s->m_net = m_net; - s->m_shape = m_shape; s->m_layers = m_layers; + s->m_marker = m_marker; + s->m_rank = m_rank; + s->m_owner = m_owner; - return s; // assert(false); + return s; } - -#if 1 -bool PNS_LINE::MergeObtuseSegments() -{ - int step = m_line.PointCount() - 3; - int iter = 0; - - int segs_pre = m_line.SegmentCount(); - - if( step < 0 ) - return false; - - SHAPE_LINE_CHAIN current_path( m_line ); - - while( 1 ) - { - iter++; - int n_segs = current_path.SegmentCount(); - int max_step = n_segs - 2; - - if( step > max_step ) - step = max_step; - - if( step < 2 ) - { - m_line = current_path; - return current_path.SegmentCount() < segs_pre; - } - - bool found_anything = false; - int n = 0; - - while( n < n_segs - step ) - { - const SEG s1 = current_path.CSegment( n ); - const SEG s2 = current_path.CSegment( n + step ); - SEG s1opt, s2opt; - - if( DIRECTION_45( s1 ).IsObtuse( DIRECTION_45( s2 ) ) ) - { - VECTOR2I ip = *s1.IntersectLines( s2 ); - - if( s1.Distance( ip ) <= 1 || s2.Distance( ip ) <= 1 ) - { - s1opt = SEG( s1.A, ip ); - s2opt = SEG( ip, s2.B ); - } - else - { - s1opt = SEG( s1.A, ip ); - s2opt = SEG( ip, s2.B ); - } - - - if( DIRECTION_45( s1opt ).IsObtuse( DIRECTION_45( s2opt ) ) ) - { - SHAPE_LINE_CHAIN opt_path; - opt_path.Append( s1opt.A ); - opt_path.Append( s1opt.B ); - opt_path.Append( s2opt.B ); - - PNS_LINE opt_track( *this, opt_path ); - - if( !m_world->CheckColliding( &opt_track, PNS_ITEM::ANY ) ) - { - current_path.Replace( s1.Index() + 1, s2.Index(), ip ); - n_segs = current_path.SegmentCount(); - found_anything = true; - break; - } - } - } - - n++; - } - - if( !found_anything ) - { - if( step <= 2 ) - { - m_line = current_path; - return m_line.SegmentCount() < segs_pre; - } - - step--; - } - } - - return m_line.SegmentCount() < segs_pre; -} - - -bool PNS_LINE::MergeSegments() -{ - int step = m_line.PointCount() - 3; - int iter = 0; - - int segs_pre = m_line.SegmentCount(); - - if( step < 0 ) - return false; - - SHAPE_LINE_CHAIN current_path( m_line ); - - while( 1 ) - { - iter++; - int n_segs = current_path.SegmentCount(); - int max_step = n_segs - 2; - - if( step > max_step ) - step = max_step; - - if( step < 2 ) - { - m_line = current_path; - return current_path.SegmentCount() < segs_pre; - } - - bool found_anything = false; - int n = 0; - - while( n < n_segs - step ) - { - const SEG s1 = current_path.CSegment( n ); - const SEG s2 = current_path.CSegment( n + step ); - SEG s1opt, s2opt; - - if( n > 0 ) - { - SHAPE_LINE_CHAIN path_straight = DIRECTION_45().BuildInitialTrace( s1.A, - s2.A, false ); - SHAPE_LINE_CHAIN path_diagonal = DIRECTION_45().BuildInitialTrace( s1.A, - s2.A, true ); - } - - if( DIRECTION_45( s1 ) == DIRECTION_45( s2 ) ) - { - if( s1.Collinear( s2 ) ) - { - // printf("Colinear: np %d step %d n1 %d n2 %d\n", n_segs, step, n, n+step); - - SHAPE_LINE_CHAIN opt_path; - opt_path.Append( s1.A ); - opt_path.Append( s2.B ); - - PNS_LINE tmp( *this, opt_path ); - - if( !m_world->CheckColliding( &tmp, PNS_ITEM::ANY ) ) - { - current_path.Remove( s1.Index() + 1, s2.Index() ); - n_segs = current_path.SegmentCount(); - found_anything = true; - break; - } - } - } - else if( DIRECTION_45( s1 ).IsObtuse( DIRECTION_45( s2 ) ) ) - { - VECTOR2I ip = *s1.IntersectLines( s2 ); - - if( s1.Distance( ip ) <= 1 || s2.Distance( ip ) <= 1 ) - { - s1opt = SEG( s1.A, ip ); - s2opt = SEG( ip, s2.B ); - } - else - { - s1opt = SEG( s1.A, ip ); - s2opt = SEG( ip, s2.B ); - } - - - if( DIRECTION_45( s1opt ).IsObtuse( DIRECTION_45( s2opt ) ) ) - { - SHAPE_LINE_CHAIN opt_path; - opt_path.Append( s1opt.A ); - opt_path.Append( s1opt.B ); - opt_path.Append( s2opt.B ); - - PNS_LINE opt_track( *this, opt_path ); - - if( !m_world->CheckColliding( &opt_track, PNS_ITEM::ANY ) ) - { - current_path.Replace( s1.Index() + 1, s2.Index(), ip ); - n_segs = current_path.SegmentCount(); - found_anything = true; - break; - } - } - } - - n++; - } - - if( !found_anything ) - { - if( step <= 2 ) - { - m_line = current_path; - return m_line.SegmentCount() < segs_pre; - } - - step--; - } - } - - return m_line.SegmentCount() < segs_pre; -} -#endif - - int PNS_LINE::CountCorners( int aAngles ) { int count = 0; @@ -306,247 +161,12 @@ int PNS_LINE::CountCorners( int aAngles ) return count; } - -// #define DUMP_TEST_CASES - -// fixme: damn f*****g inefficient and incredibly crappily written -void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle, - SHAPE_LINE_CHAIN& aPrePath, - SHAPE_LINE_CHAIN& aWalkaroundPath, - SHAPE_LINE_CHAIN& aPostPath, - bool aCw ) const -{ - typedef SHAPE_LINE_CHAIN::INTERSECTION INTERSECTION; - - SHAPE_LINE_CHAIN l_orig( m_line ); - SHAPE_LINE_CHAIN l_hull; - std::vector outside, on_edge, inside; - SHAPE_LINE_CHAIN path; - - std::vector isects; - - // don't calculate walkaround for empty lines - if( m_line.PointCount() < 2 ) - return; - -#ifdef DUMP_TEST_CASES - printf( "%s\n", m_line.Format().c_str() ); - printf( "%s\n", aObstacle.Format().c_str() ); -#endif - - aObstacle.Intersect( m_line, isects ); - - // printf("NewWalk intersectiosn :%d\n" ,isects.size()); - if( !aCw ) - l_hull = aObstacle.Reverse(); - else - l_hull = aObstacle; - - BOOST_FOREACH( INTERSECTION isect, isects ) { - l_orig.Split( isect.p ); - l_hull.Split( isect.p ); - } - - -#ifdef DUMP_TEST_CASES - printf( "%s\n", m_line.Format().c_str() ); - printf( "%s\n", aObstacle.Format().c_str() ); - printf( "%s\n", l_orig.Format().c_str() ); - printf( "%s\n", l_hull.Format().c_str() ); -#endif - - - // printf("Pts: line %d hull %d\n", l_orig.PointCount(), l_hull.PointCount()); - - int first_post = -1; - int last_pre = -1; - - for( int i = 0; i < l_orig.PointCount(); i++ ) - { - int ei = l_hull.Find( l_orig.CPoint( i ) ); - bool edge = ei >= 0; - bool in = l_hull.PointInside( l_orig.CPoint( i ) ) && !edge; - bool out = !( in || edge); - - outside.push_back( out ); - on_edge.push_back( edge ); - inside.push_back( in ); - } - - for( int i = l_orig.PointCount() - 1; i >= 1; i-- ) - if( inside[i] && outside[i - 1] ) - { - SHAPE_LINE_CHAIN::INTERSECTIONS ips; - l_hull.Intersect( SEG( l_orig.CPoint( i ), l_orig.CPoint( i - 1 ) ), ips ); - l_orig.Remove( i, -1 ); - l_orig.Append( ips[0].p ); - break; - } - else if( inside[i] && on_edge[i - 1] ) - { - l_orig.Remove( i, -1 ); - // n = i; - } - else if( !inside[i] ) - break; - - if( !outside.size() && on_edge.size() < 2 ) - return; - - for( int i = 0; i < l_orig.PointCount(); i++ ) - { - const VECTOR2I p = l_orig.Point( i ); - - if( outside[i] || ( on_edge[i] && i == ( l_orig.PointCount() - 1 ) ) ) - { - if( last_pre < 0 ) - aPrePath.Append( p ); - - path.Append( p ); - } - else if( on_edge[i] ) - { - int li = -1; - - if( last_pre < 0 ) - { - aPrePath.Append( p ); - last_pre = path.PointCount(); - } - - if( i == l_orig.PointCount() - 1 || outside[i + 1] ) - { - path.Append( p ); - } - else - { - int vi2 = l_hull.Find( l_orig.CPoint( i ) ); - - path.Append( l_hull.CPoint( vi2 ) ); - - for( int j = (vi2 + 1) % l_hull.PointCount(); - j != vi2; - j = (j + 1) % l_hull.PointCount() ) - { - path.Append( l_hull.CPoint( j ) ); - li = l_orig.Find( l_hull.CPoint( j ) ); - - if( li >= 0 && ( li == ( l_orig.PointCount() - 1 ) || - outside[li + 1] ) ) - break; - } - - if( li >= 0 ) - { - if( i >= li ) - break; - else - i = li; - } - } - - first_post = path.PointCount() - 1; - } - } - - if( last_pre < 0 && first_post < 0 ) - return; - - aWalkaroundPath = path.Slice( last_pre, first_post ); - - if( first_post >= 0 ) - aPostPath = path.Slice( first_post, -1 ); -} - - -bool PNS_LINE::onEdge( const SHAPE_LINE_CHAIN& obstacle, VECTOR2I p, int& ei, - bool& is_vertex ) const -{ - int vtx = obstacle.Find( p ); - - if( vtx >= 0 ) - { - ei = vtx; - is_vertex = true; - return true; - } - - for( int s = 0; s < obstacle.SegmentCount(); s++ ) - { - if( obstacle.CSegment( s ).Contains( p ) ) - { - ei = s; - is_vertex = false; - return true; - } - } - - return false; -} - - -bool PNS_LINE::walkScan( const SHAPE_LINE_CHAIN& aLine, const SHAPE_LINE_CHAIN& aObstacle, - bool aReverse, VECTOR2I& aIp, int& aIndexO, int& aIndexL, bool& aIsVertex ) const -{ - int sc = aLine.SegmentCount(); - - for( int i = 0; i < aLine.SegmentCount(); i++ ) - { - printf( "check-seg rev %d %d/%d %d\n", aReverse, i, sc, sc - 1 - i ); - SEG tmp = aLine.CSegment( aReverse ? sc - 1 - i : i ); - SEG s( tmp.A, tmp.B ); - - if( aReverse ) - { - s.A = tmp.B; - s.B = tmp.A; - } - - if( onEdge( aObstacle, s.A, aIndexO, aIsVertex ) ) - { - aIndexL = (aReverse ? sc - 1 - i : i); - aIp = s.A; - printf( "vertex %d on-%s %d\n", aIndexL, - aIsVertex ? "vertex" : "edge", aIndexO ); - return true; - } - - if( onEdge( aObstacle, s.B, aIndexO, aIsVertex ) ) - { - aIndexL = (aReverse ? sc - 1 - i - 1 : i + 1); - aIp = s.B; - printf( "vertex %d on-%s %d\n", aIndexL, - aIsVertex ? "vertex" : "edge", aIndexO ); - return true; - } - - SHAPE_LINE_CHAIN::INTERSECTIONS ips; - int n_is = aObstacle.Intersect( s, ips ); - - if( n_is > 0 ) - { - aIndexO = ips[0].our.Index(); - aIndexL = aReverse ? sc - 1 - i : i; - printf( "segment-%d intersects edge-%d\n", aIndexL, aIndexO ); - aIp = ips[0].p; - return true; - } - } - - return false; -} - - bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, SHAPE_LINE_CHAIN& aWalk, SHAPE_LINE_CHAIN& aPost, bool aCw ) const { - const SHAPE_LINE_CHAIN& line = GetCLine(); + const SHAPE_LINE_CHAIN& line ( CLine() ); VECTOR2I ip_start; - int index_o_start, index_l_start; VECTOR2I ip_end; - int index_o_end, index_l_end; - - bool is_vertex_start, is_vertex_end; if( line.SegmentCount() < 1 ) return false; @@ -555,92 +175,83 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, aObstacle.PointInside( line.CPoint( -1 ) ) ) return false; -// printf("forward:\n"); - bool found = walkScan( line, aObstacle, false, ip_start, index_o_start, - index_l_start, is_vertex_start ); - // printf("reverse:\n"); - found |= walkScan( line, aObstacle, true, ip_end, index_o_end, index_l_end, is_vertex_end ); + SHAPE_LINE_CHAIN::INTERSECTIONS ips, ips2; - if( !found || ip_start == ip_end ) + line.Intersect(aObstacle, ips); + + int nearest_dist = INT_MAX; + int farthest_dist = 0; + + SHAPE_LINE_CHAIN::INTERSECTION nearest, farthest; + + for(int i = 0; i < (int) ips.size(); i++) + { + const VECTOR2I p = ips[i].p; + int dist = line.PathLength(p); + + if(dist <= nearest_dist) + { + nearest_dist = dist; + nearest = ips[i]; + } + + if(dist >= farthest_dist) + { + farthest_dist = dist; + farthest = ips[i]; + } + } + + if(ips.size() <= 1 || nearest.p == farthest.p) { aPre = line; return true; } - aPre = line.Slice( 0, index_l_start ); - aPre.Append( ip_start ); + aPre = line.Slice( 0, nearest.our.Index() ); + aPre.Append( nearest.p ); + aPre.Simplify(); + aWalk.Clear(); - aWalk.Append( ip_start ); + aWalk.SetClosed(false); + aWalk.Append( nearest.p ); - if( aCw ) + int i = nearest.their.Index(); + + assert ( nearest.their.Index() >= 0 ); + assert ( farthest.their.Index() >= 0 ); + + assert( nearest_dist <= farthest_dist ); + + aObstacle.Split( nearest.p ); + aObstacle.Split( farthest.p ); + + int i_first = aObstacle.Find( nearest.p ); + int i_last = aObstacle.Find( farthest.p ); + + i = i_first; + + while (i != i_last) { - int is = ( index_o_start + 1 ) % aObstacle.PointCount(); - int ie = ( is_vertex_end ? index_o_end : index_o_end + 1 ) % aObstacle.PointCount(); - - while( 1 ) - { - printf( "is %d\n", is ); - aWalk.Append( aObstacle.CPoint( is ) ); - - if( is == ie ) - break; - - is++; - - if( is == aObstacle.PointCount() ) - is = 0; - } + aWalk.Append(aObstacle.CPoint(i)); + i += (aCw ? 1 : -1); + + if (i < 0) + i = aObstacle.PointCount() - 1; + else if (i == aObstacle.PointCount()) + i = 0; } - else - { - int is = index_o_start; - int ie = ( is_vertex_end ? index_o_end : index_o_end ) % aObstacle.PointCount(); - - while( 1 ) - { - printf( "is %d\n", is ); - aWalk.Append( aObstacle.CPoint( is ) ); - - if( is == ie ) - break; - - is--; - - if( is < 0 ) - is = aObstacle.PointCount() - 1; - } - } - - aWalk.Append( ip_end ); + + aWalk.Append( farthest.p ); + aWalk.Simplify(); aPost.Clear(); - aPost.Append( ip_end ); - aPost.Append( line.Slice( is_vertex_end ? index_l_end : index_l_end + 1, -1 ) ); - - // for(int i = (index_o_start + 1) % obstacle.PointCount(); - // i != (index_o_end + 1) % obstacle.PointCount(); i=(i+1) % obstacle.PointCount()) - // { - // printf("append %d\n", i); - // walk.Append(obstacle.CPoint(i)); - // } - + aPost.Append( farthest.p ); + aPost.Append( line.Slice( farthest.our.Index() + 1, -1 ) ); + aPost.Simplify(); return true; } - -void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle, - SHAPE_LINE_CHAIN& aPath, - bool aCw ) const -{ - SHAPE_LINE_CHAIN walk, post; - - NewWalkaround( aObstacle, aPath, walk, post, aCw ); - aPath.Append( walk ); - aPath.Append( post ); - aPath.Simplify(); -} - - void PNS_LINE::Walkaround( const SHAPE_LINE_CHAIN& aObstacle, SHAPE_LINE_CHAIN& aPath, bool aCw ) const @@ -656,38 +267,7 @@ void PNS_LINE::Walkaround( const SHAPE_LINE_CHAIN& aObstacle, const SHAPE_LINE_CHAIN PNS_SEGMENT::Hull( int aClearance, int aWalkaroundThickness ) const { - int d = aClearance + 10; - int x = (int)( 2.0 / ( 1.0 + M_SQRT2 ) * d ) + 2; - - const VECTOR2I a = m_shape.CPoint( 0 ); - const VECTOR2I b = m_shape.CPoint( 1 ); - - VECTOR2I dir = b - a; - - VECTOR2I p0 = dir.Perpendicular().Resize( d ); - - VECTOR2I ds = dir.Perpendicular().Resize( x / 2 ); - VECTOR2I pd = dir.Resize( x / 2 ); - VECTOR2I dp = dir.Resize( d ); - - SHAPE_LINE_CHAIN s; - - s.SetClosed( true ); - - s.Append( b + p0 + pd ); - s.Append( b + dp + ds ); - s.Append( b + dp - ds ); - s.Append( b - p0 + pd ); - s.Append( a - p0 - pd ); - s.Append( a - dp - ds ); - s.Append( a - dp + ds ); - s.Append( a + p0 - pd ); - - // make sure the hull outline is always clockwise - if( s.CSegment( 0 ).Side( a ) < 0 ) - return s.Reverse(); - else - return s; + return SegmentHull ( m_seg, aClearance, aWalkaroundThickness ); } @@ -723,8 +303,8 @@ const PNS_LINE PNS_LINE::ClipToNearestObstacle( PNS_NODE* aNode ) const if( obs ) { l.RemoveVia(); - int p = l.GetLine().Split( obs->ip_first ); - l.GetLine().Remove( p + 1, -1 ); + int p = l.Line().Split( obs->ip_first ); + l.Line().Remove( p + 1, -1 ); } return l; @@ -744,3 +324,404 @@ void PNS_LINE::ShowLinks() for( int i = 0; i < (int) m_segmentRefs->size(); i++ ) printf( "seg %d: %p\n", i, (*m_segmentRefs)[i] ); } + +SHAPE_LINE_CHAIN dragCornerInternal ( const SHAPE_LINE_CHAIN& origin, const VECTOR2I& aP ) +{ + optional picked; + int i; + + int d = 2; + + if(origin.CSegment(-1).Length() > 100000 * 30) // fixme: constant/parameter? + d = 1; + + for(i = origin.SegmentCount() - d; i >= 0; i--) + { + + DIRECTION_45 d_start (origin.CSegment(i)); + VECTOR2I p_start = origin.CPoint(i); + SHAPE_LINE_CHAIN paths [2]; + DIRECTION_45 dirs[2]; + DIRECTION_45 d_prev = (i > 0 ? DIRECTION_45(origin.CSegment(i-1)) : DIRECTION_45()); + + for(int j = 0; j < 2; j++) + { + paths [j] = d_start.BuildInitialTrace( p_start, aP, j ); + dirs [j] = DIRECTION_45(paths[j].CSegment(0)); + } + + + for( int j = 0; j < 2; j++) + if(dirs[j] == d_start) + { + picked = paths[j]; + break; + } + + if(picked) + break; + + for(int j = 0; j < 2; j++) + if (dirs[j].IsObtuse(d_prev)) + { + picked = paths[j]; + break; + } + if(picked) + break; + } + + if(picked) + { + SHAPE_LINE_CHAIN path = origin.Slice(0, i); + path.Append(*picked); + return path; + + } + + return DIRECTION_45().BuildInitialTrace(origin.CPoint(0), aP, true); +} + + + +void PNS_LINE::DragCorner ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) +{ + SHAPE_LINE_CHAIN path; + + VECTOR2I snapped = snapDraggedCorner( m_line, aP, aIndex, aSnappingThreshold ); + + if( aIndex == 0) + path = dragCornerInternal( m_line.Reverse(), snapped ).Reverse(); + else if ( aIndex == m_line.SegmentCount() ) + path = dragCornerInternal( m_line, snapped ); + else { + // fixme: awkward behaviour for "outwards" drags + path = dragCornerInternal( m_line.Slice (0, aIndex), snapped ); + SHAPE_LINE_CHAIN path_rev = dragCornerInternal( m_line.Slice (aIndex, -1).Reverse(), snapped ).Reverse(); + path.Append(path_rev); + } + path.Simplify(); + m_line = path; +} + +VECTOR2I PNS_LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const +{ + int s_start = std::max(aIndex - 2, 0); + int s_end = std::min(aIndex + 2, aPath.SegmentCount() - 1); + + int i, j; + int best_dist = INT_MAX; + VECTOR2I best_snap = aP; + + if(aThreshold <= 0) + return aP; + + for(i = s_start; i <= s_end; i++) + { + const SEG& a = aPath.CSegment(i); + + for(j = s_start; j < i; j++) + { + const SEG& b = aPath.CSegment(j); + + if( ! (DIRECTION_45(a).IsObtuse(DIRECTION_45(b))) ) + continue; + + OPT_VECTOR2I ip = a.IntersectLines(b); + + if(ip) + { + int dist = (*ip - aP).EuclideanNorm(); + if( dist < aThreshold && dist < best_dist ) + { + best_dist = dist; + best_snap = *ip; + } + } + } + } + + return best_snap; +} + +VECTOR2I PNS_LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const +{ + VECTOR2I snap_p[2]; + DIRECTION_45 dragDir ( aPath.CSegment(aIndex) ); + int snap_d[2] = {-1, -1}; + + if( aThreshold == 0 ) + return aP; + + if(aIndex >= 2) + { + SEG s = aPath.CSegment(aIndex - 2); + if(DIRECTION_45(s) == dragDir) + snap_d[0] = s.LineDistance(aP); + snap_p[0] = s.A; + } + + if(aIndex < aPath.SegmentCount() - 2) + { + SEG s = aPath.CSegment(aIndex + 2); + if(DIRECTION_45(s) == dragDir) + snap_d[1] = s.LineDistance(aP); + snap_p[1] = s.A; + } + + VECTOR2I best = aP; + int minDist = INT_MAX; + + for(int i = 0; i < 2; i++) + if(snap_d[i] >= 0 && snap_d[i] < minDist && snap_d[i] <= aThreshold) + { + minDist = snap_d[i]; + best = snap_p[i]; + } + + return best; +} + + +void PNS_LINE::DragSegment ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) +{ + SHAPE_LINE_CHAIN path (m_line); + VECTOR2I target (aP) ; + + SEG guideA[2], guideB[2]; + int index = aIndex; + + target = snapToNeighbourSegments( path, aP, aIndex, aSnappingThreshold ); + + if(index == 0) + { + path.Insert (0, path.CPoint(0)); + index++; + } + + if(index == path.SegmentCount()-1) + { + path.Insert(path.PointCount() - 1, path.CPoint(-1)); + } + + SEG dragged = path.CSegment(index); + DIRECTION_45 drag_dir (dragged); + + SEG s_prev = path.CSegment(index - 1); + SEG s_next = path.CSegment(index + 1); + + DIRECTION_45 dir_prev (s_prev); + DIRECTION_45 dir_next (s_next); + + if(dir_prev == drag_dir) + { + dir_prev = dir_prev.Left(); + path.Insert( index, path.CPoint(index) ); + index++; + } + + if(dir_next == drag_dir) + { + dir_next = dir_next.Right(); + path.Insert( index + 1, path.CPoint(index + 1) ); + } + + + s_prev = path.CSegment(index - 1); + s_next = path.CSegment(index + 1); + dragged = path.CSegment(index); + + bool lockEndpointA = true; + bool lockEndpointB = true; + + if(aIndex == 0) + { + if(!lockEndpointA) + guideA[0] = guideA[1] = SEG( dragged.A, dragged.A + drag_dir.Right().Right().ToVector() ); + else { + guideA[0] = SEG( dragged.A, dragged.A + drag_dir.Right().ToVector() ); + guideA[1] = SEG( dragged.A, dragged.A + drag_dir.Left().ToVector() ); + } + } else { + if(dir_prev.IsObtuse(drag_dir)) + { + guideA[0] = SEG( s_prev.A, s_prev.A + drag_dir.Left().ToVector() ); + guideA[1] = SEG( s_prev.A, s_prev.A + drag_dir.Right().ToVector() ); + } else + guideA[0] = guideA[1] = SEG( dragged.A, dragged.A + dir_prev.ToVector() ); + } + + if(aIndex == m_line.SegmentCount() - 1) + { + if(!lockEndpointB) + guideB[0] = guideB[1] = SEG( dragged.B, dragged.B + drag_dir.Right().Right().ToVector() ); + else { + guideB[0] = SEG( dragged.B, dragged.B + drag_dir.Right().ToVector() ); + guideB[1] = SEG( dragged.B, dragged.B + drag_dir.Left().ToVector() ); + } + } else { + if(dir_next.IsObtuse(drag_dir)) + { + guideB[0] = SEG( s_next.B, s_next.B + drag_dir.Left().ToVector() ); + guideB[1] = SEG( s_next.B, s_next.B + drag_dir.Right().ToVector() ); + } else + guideB[0] = guideB[1] = SEG( dragged.B, dragged.B + dir_next.ToVector() ); + } + + SEG s_current (target, target + drag_dir.ToVector()); + + int best_len = INT_MAX; + SHAPE_LINE_CHAIN best; + + for(int i = 0; i < 2; i++) + { + for(int j = 0; j < 2; j++) + { + OPT_VECTOR2I ip1 = s_current.IntersectLines(guideA[i]); + OPT_VECTOR2I ip2 = s_current.IntersectLines(guideB[j]); + + SHAPE_LINE_CHAIN np; + + if(!ip1 || !ip2) + continue; + + SEG s1 ( s_prev.A, *ip1 ); + SEG s2 ( *ip1, *ip2 ); + SEG s3 ( *ip2, s_next.B ); + + OPT_VECTOR2I ip; + + if(ip = s1.Intersect(s_next)) + { + np.Append ( s1.A ); + np.Append ( *ip ); + np.Append ( s_next.B ); + } else if(ip = s3.Intersect(s_prev)) + { + np.Append ( s_prev.A ); + np.Append ( *ip ); + np.Append ( s3.B ); + } else if(ip = s1.Intersect(s3)) + { + np.Append( s_prev.A ); + np.Append( *ip ); + np.Append( s_next.B ); + } else { + np.Append( s_prev.A ); + np.Append( *ip1 ); + np.Append( *ip2 ); + np.Append( s_next.B ); + } + + if(np.Length() < best_len) + { + best_len = np.Length(); + best = np; + } + + } + } + + if(!lockEndpointA && aIndex == 0) + best.Remove(0, 0); + if(!lockEndpointB && aIndex == m_line.SegmentCount() - 1) + best.Remove(-1, -1); + + + if(m_line.PointCount() == 1) + m_line = best; + else if (aIndex == 0) + m_line.Replace(0, 1, best); + else if (aIndex == m_line.SegmentCount() - 1) + m_line.Replace(-2, -1, best); + else + m_line.Replace(aIndex, aIndex + 1, best); + + m_line.Simplify(); +} + + +bool PNS_LINE::CompareGeometry( const PNS_LINE& aOther ) +{ + return m_line.CompareGeometry(aOther.m_line); +} + +void PNS_LINE::Reverse() +{ + m_line = m_line.Reverse(); + if(m_segmentRefs) + std::reverse(m_segmentRefs->begin(), m_segmentRefs->end() ); +} + +void PNS_LINE::AppendVia(const PNS_VIA& aVia) +{ + if(aVia.Pos() == m_line.CPoint(0)) + { + + Reverse(); + } + + m_hasVia = true; + m_via = aVia; + m_via.SetNet( m_net ); +} + +void PNS_LINE::SetRank(int aRank) +{ + m_rank = aRank; + if(m_segmentRefs) + { + BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) + s->SetRank(aRank); + } +} + +int PNS_LINE::Rank() const +{ + int min_rank = INT_MAX; + int rank; + if(m_segmentRefs) + { + BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) + min_rank = std::min(min_rank, s->Rank()); + rank = (min_rank == INT_MAX) ? -1 : min_rank; + } else { + rank = m_rank; + } + + return rank; +} + +void PNS_LINE::ClipVertexRange ( int aStart, int aEnd ) +{ + m_line = m_line.Slice (aStart, aEnd); + + if(m_segmentRefs) + { + SegmentRefs *snew = new SegmentRefs( m_segmentRefs->begin() + aStart, m_segmentRefs->begin() + aEnd ); + + delete m_segmentRefs; + m_segmentRefs = snew; + } +} + +bool PNS_LINE::HasLoops() const +{ + + for(int i = 0; i < PointCount(); i++) + for(int j = 0; j < PointCount(); j++) + { + if( (std::abs(i-j) > 1) && CPoint(i) == CPoint(j)) + return true; + } + + return false; +} + +void PNS_LINE::ClearSegmentLinks() +{ + if(m_segmentRefs) + delete m_segmentRefs; + m_segmentRefs = NULL; +} + diff --git a/pcbnew/router/pns_line.h b/pcbnew/router/pns_line.h index ebd07750cf..520409d937 100644 --- a/pcbnew/router/pns_line.h +++ b/pcbnew/router/pns_line.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_LINE_H @@ -42,60 +42,42 @@ class PNS_VIA; * vias, pads, junctions between multiple traces or two traces different widths * and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE). * Instead, they are assembled on-the-fly, based on a via/pad/segment that - * belongs/begins them. + * belongs to/starts/ends them. * * PNS_LINEs can be either loose (consisting of segments that do not belong to * any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are * returned by PNS_NODE::AssembleLine and friends. * - * A PNS_LINE may have a PNS_VIA attached at its and - this is used by via + * A PNS_LINE may have a PNS_VIA attached at its end (i.e. the last point) - this is used by via * dragging/force propagation stuff. */ +#define PNS_HULL_MARGIN 10 + class PNS_LINE : public PNS_ITEM { public: - typedef std::vector LinkedSegments; - - PNS_LINE() : - PNS_ITEM( LINE ) - { - m_segmentRefs = NULL; - m_hasVia = false; - m_affectedRangeStart = -1; - }; - - PNS_LINE( int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine ) : - PNS_ITEM( LINE ) - { - m_line = aLine; - m_width = aWidth; - m_segmentRefs = NULL; - m_hasVia = false; - m_affectedRangeStart = -1; - SetLayer( aLayer ); - } - - PNS_LINE( const PNS_LINE& aOther ) : - PNS_ITEM( aOther ), - m_line( aOther.m_line ), - m_width( aOther.m_width ) - { - m_net = aOther.m_net; - m_movable = aOther.m_movable; - m_world = aOther.m_world; - m_layers = aOther.m_layers; - m_segmentRefs = NULL; - m_via = aOther.m_via; - m_hasVia = aOther.m_hasVia; - m_affectedRangeStart = -1; - } + typedef std::vector SegmentRefs; /** * Constructor - * copies properties (net, layers from a base line), and replaces the shape - * by aLine + * Makes an empty line. + */ + PNS_LINE() : PNS_ITEM (LINE) + { + m_segmentRefs = NULL; + m_hasVia = false; + } + + + PNS_LINE( const PNS_LINE& aOther ) ; + + /** + * Constructor + * Copies properties (net, layers, etc.) from a base line and replaces the shape + * by another **/ + PNS_LINE( const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine ) : PNS_ITEM( aBase ), m_line( aLine ), @@ -105,49 +87,101 @@ public: m_layers = aBase.m_layers; m_segmentRefs = NULL; m_hasVia = false; - m_affectedRangeStart = -1; } - ~PNS_LINE() + ~PNS_LINE(); + + /// @copydoc PNS_ITEM::Clone() + virtual PNS_LINE* Clone( ) const; + + const PNS_LINE& operator= (const PNS_LINE& aOther); + + ///> Assigns a shape to the line (a polyline/line chain) + void SetShape ( const SHAPE_LINE_CHAIN& aLine ) + { + m_line = aLine; + } + + ///> Returns the shape of the line + const SHAPE* Shape() const + { + return &m_line; + } + + ///> Modifiable accessor to the underlying shape + SHAPE_LINE_CHAIN& Line() + { + return m_line; + } + + ///> Const accessor to the underlying shape + const SHAPE_LINE_CHAIN& CLine() const + { + return m_line; + } + + ///> Returns the number of segments in the line + int SegmentCount() const { - if( m_segmentRefs ) - delete m_segmentRefs; - }; + return m_line.SegmentCount(); + } - virtual PNS_LINE* Clone() const; + ///> Returns the number of points in the line + int PointCount() const + { + return m_line.PointCount(); + } - ///> clones the line without cloning the shape - ///> (just the properties - net, width, layers, etc.) - PNS_LINE* CloneProperties() const; + ///> Returns the aIdx-th point of the line + const VECTOR2I& CPoint( int aIdx ) const + { + return m_line.CPoint(aIdx); + } - int GetLayer() const { return GetLayers().Start(); } + ///> Returns the aIdx-th segment of the line + const SEG CSegment (int aIdx ) const + { + return m_line.CSegment(aIdx); + } - ///> Geometry accessors - void SetShape( const SHAPE_LINE_CHAIN& aLine ) { m_line = aLine; } - const SHAPE* GetShape() const { return &m_line; } - SHAPE_LINE_CHAIN& GetLine() { return m_line; } - const SHAPE_LINE_CHAIN& GetCLine() const { return m_line; } + ///> Sets line width + void SetWidth( int aWidth ) + { + m_width = aWidth; + } + + ///> Returns line width + int Width() const + { + return m_width; + } - ///> Width accessors - void SetWidth( int aWidth ) { m_width = aWidth; } - int GetWidth() const { return m_width; } + ///> Returns true if the line is geometrically identical as line aOther + bool CompareGeometry( const PNS_LINE& aOther ); - ///> Links a segment from a PNS_NODE to this line, making it owned by the node + ///> Reverses the point/vertex order + void Reverse(); + + + /* Linking functions */ + + ///> Adds a reference to a segment registered in a PNS_NODE that is a part of this line. void LinkSegment( PNS_SEGMENT* aSeg ) { if( !m_segmentRefs ) - m_segmentRefs = new std::vector (); + m_segmentRefs = new SegmentRefs(); m_segmentRefs->push_back( aSeg ); } - ///> Returns a list of segments from the owning node that constitute this - ///> line (or NULL if the line is loose) - LinkedSegments* GetLinkedSegments() + ///> Returns the list of segments from the owning node that constitute this + ///> line (or NULL if the line is not linked) + SegmentRefs* LinkedSegments() { return m_segmentRefs; } + ///> Checks if the segment aSeg is a part of the line. bool ContainsSegment( PNS_SEGMENT* aSeg ) const { if( !m_segmentRefs ) @@ -157,13 +191,23 @@ public: aSeg ) != m_segmentRefs->end(); } - ///> Returns this line, but clipped to the nearest obstacle - ///> along, to avoid collision. + ///> Erases the linking information. Used to detach the line from the owning node. + void ClearSegmentLinks(); + + ///> Returns the number of segments that were assembled together to form this line. + int LinkCount() const { + if(!m_segmentRefs) + return -1; + return m_segmentRefs->size(); + } + + ///> Clips the line to the nearest obstacle, traversing from the line's start vertex (0). + ///> Returns the clipped line. const PNS_LINE ClipToNearestObstacle( PNS_NODE* aNode ) const; - ///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER) - bool MergeObtuseSegments(); - bool MergeSegments(); + ///> Clips the line to a given range of vertices. + void ClipVertexRange ( int aStart, int aEnd ); + ///> Returns the number of corners of angles specified by mask aAngles. int CountCorners( int aAngles ); @@ -173,17 +217,7 @@ public: ///> aPrePath = path from origin to the obstacle ///> aWalkaroundPath = path around the obstacle ///> aPostPath = past from obstacle till the end - ///> aCW = whether to walkaround in clockwise or counter-clockwise direction. - void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle, - SHAPE_LINE_CHAIN& aPrePath, - SHAPE_LINE_CHAIN& aWalkaroundPath, - SHAPE_LINE_CHAIN& aPostPath, - bool aCw ) const; - - void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle, - SHAPE_LINE_CHAIN& aPath, - bool aCw ) const; - + ///> aCW = whether to walk around in clockwise or counter-clockwise direction. bool Walkaround( SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN& pre, @@ -202,62 +236,46 @@ public: bool EndsWithVia() const { return m_hasVia; } - void AppendVia( const PNS_VIA& aVia ) - { - m_hasVia = true; - m_via = aVia; - m_via.SetNet( m_net ); - } - + void AppendVia( const PNS_VIA& aVia ); void RemoveVia() { m_hasVia = false; } - const PNS_VIA& GetVia() const { return m_via; } - void SetAffectedRange( int aStart, int aEnd ) - { - m_affectedRangeStart = aStart; - m_affectedRangeEnd = aEnd; - } + const PNS_VIA& Via() const { return m_via; } + + virtual void Mark(int aMarker); + virtual void Unmark (); + virtual int Marker() const; + + void DragSegment ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 ); + void DragCorner ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 ); - void ClearAffectedRange() - { - m_affectedRangeStart = -1; - } - - bool GetAffectedRange( int& aStart, int& aEnd ) - { - if( m_affectedRangeStart >= 0 ) - { - aStart = m_affectedRangeStart; - aEnd = m_affectedRangeEnd; - return true; - } - else - { - aStart = 0; - aEnd = m_line.PointCount(); - return false; - } - } + void SetRank ( int aRank ); + int Rank() const; + + bool HasLoops() const; private: - bool onEdge( const SHAPE_LINE_CHAIN& obstacle, VECTOR2I p, int& ei, bool& is_vertex ) const; - bool walkScan( const SHAPE_LINE_CHAIN& line, const SHAPE_LINE_CHAIN& obstacle, - bool reverse, VECTOR2I& ip, int& index_o, int& index_l, bool& is_vertex ) const; - ///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line. - LinkedSegments* m_segmentRefs; + VECTOR2I snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold) const; + VECTOR2I snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const; - ///> Shape of the line + ///> Copies m_segmentRefs from the line aParent. + void copyLinks( const PNS_LINE *aParent ) ; + + ///> List of segments in the owning PNS_NODE (PNS_ITEM::m_owner) that constitute this line, or NULL + ///> if the line is not a part of any node. + SegmentRefs* m_segmentRefs; + + ///> The actual shape of the line SHAPE_LINE_CHAIN m_line; + ///> our width int m_width; - ///> Via at the end and a flag indicating if it's enabled. - PNS_VIA m_via; + ///> If true, the line ends with a via bool m_hasVia; - int m_affectedRangeStart; - int m_affectedRangeEnd; + ///> Via at the end point, if m_hasVia == true + PNS_VIA m_via; }; #endif // __PNS_LINE_H diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index 4b9b616f3e..16f3ea1429 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,12 +15,14 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include #include +#include + #include "trace.h" #include "pns_node.h" @@ -28,44 +30,46 @@ #include "pns_walkaround.h" #include "pns_shove.h" #include "pns_utils.h" +#include "pns_router.h" + +#include using boost::optional; -const double PNS_LINE_PLACER::m_shoveLengthThreshold = 1.7; - -PNS_LINE_PLACER::PNS_LINE_PLACER( PNS_NODE* aWorld ) +PNS_LINE_PLACER::PNS_LINE_PLACER( PNS_ROUTER* aRouter ) : + PNS_ALGO_BASE ( aRouter ) { - m_initial_direction = DIRECTION_45( DIRECTION_45::N ); - m_follow_mouse = false; - m_smoothing_step = 100000; - m_smooth_mouse = false; + m_initial_direction = DIRECTION_45::N; m_iteration = 0; - m_world = aWorld; - m_mode = RM_Smart; - m_follow_mouse = true; + m_world = NULL; m_shove = NULL; + m_currentNode = NULL; }; - PNS_LINE_PLACER::~PNS_LINE_PLACER() { if( m_shove ) delete m_shove; } - -void PNS_LINE_PLACER::ApplySettings( const PNS_ROUTING_SETTINGS& aSettings ) +void PNS_LINE_PLACER::setWorld ( PNS_NODE *aWorld ) { - m_follow_mouse = aSettings.m_followMouse; - m_mode = aSettings.m_routingMode; - m_walkaroundIterationLimit = aSettings.m_walkaroundIterationLimit; - m_smartPads = aSettings.m_smartPads; + m_world = aWorld; } +void PNS_LINE_PLACER::AddVia( bool aEnabled, int aDiameter, int aDrill ) +{ + m_viaDiameter = aDiameter; + m_viaDrill = aDrill; + m_placingVia = aEnabled; +} -void PNS_LINE_PLACER::StartPlacement( const VECTOR2I& aStart, int aNet, +void PNS_LINE_PLACER::startPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer ) { + + assert(m_world != NULL); + m_direction = m_initial_direction; TRACE( 1, "world %p, intitial-direction %s layer %d\n", m_world % m_direction.Format().c_str() % aLayer ); @@ -73,27 +77,37 @@ void PNS_LINE_PLACER::StartPlacement( const VECTOR2I& aStart, int aNet, m_tail.SetNet( aNet ); m_head.SetWidth( aWidth ); m_tail.SetWidth( aWidth ); - m_head.GetLine().Clear(); - m_tail.GetLine().Clear(); + m_head.Line().Clear(); + m_tail.Line().Clear(); m_head.SetLayer( aLayer ); m_tail.SetLayer( aLayer ); m_iteration = 0; m_p_start = aStart; - m_currentNode = m_world->Branch(); - m_head.SetWorld( m_currentNode ); - m_tail.SetWorld( m_currentNode ); - // if(m_shove) - // delete m_shove; - m_shove = new PNS_SHOVE( m_currentNode ); + + m_lastNode = NULL; + m_currentNode = m_world; + + m_currentMode = Settings().Mode(); + + if(m_shove) + delete m_shove; + + m_shove = NULL; + + if(m_currentMode == RM_Shove || m_currentMode == RM_Smart) + { + m_shove = new PNS_SHOVE( m_world -> Branch(), Router() ); + } + m_placingVia = false; } -void PNS_LINE_PLACER::SetInitialDirection( const DIRECTION_45& aDirection ) +void PNS_LINE_PLACER::setInitialDirection( const DIRECTION_45& aDirection ) { m_initial_direction = aDirection; - if( m_tail.GetCLine().SegmentCount() == 0 ) +if( m_tail.SegmentCount() == 0 ) m_direction = aDirection; } @@ -101,8 +115,8 @@ void PNS_LINE_PLACER::SetInitialDirection( const DIRECTION_45& aDirection ) bool PNS_LINE_PLACER::handleSelfIntersections() { SHAPE_LINE_CHAIN::INTERSECTIONS ips; - SHAPE_LINE_CHAIN& head = m_head.GetLine(); - SHAPE_LINE_CHAIN& tail = m_tail.GetLine(); + SHAPE_LINE_CHAIN& head = m_head.Line(); + SHAPE_LINE_CHAIN& tail = m_tail.Line(); // if there is no tail, there is nothing to intersect with if( tail.PointCount() < 2 ) @@ -159,8 +173,11 @@ bool PNS_LINE_PLACER::handleSelfIntersections() bool PNS_LINE_PLACER::handlePullback() { - SHAPE_LINE_CHAIN& head = m_head.GetLine(); - SHAPE_LINE_CHAIN& tail = m_tail.GetLine(); + SHAPE_LINE_CHAIN& head = m_head.Line(); + SHAPE_LINE_CHAIN& tail = m_tail.Line(); + + if(head.PointCount() < 2) + return false; int n = tail.PointCount(); @@ -173,8 +190,8 @@ bool PNS_LINE_PLACER::handlePullback() return true; } - DIRECTION_45 first_head( head.Segment( 0 ) ); - DIRECTION_45 last_tail( tail.Segment( -1 ) ); + DIRECTION_45 first_head( head.CSegment( 0 ) ); + DIRECTION_45 last_tail( tail.CSegment( -1 ) ); DIRECTION_45::AngleType angle = first_head.Angle( last_tail ); // case 1: we have a defined routing direction, and the currently computed @@ -215,11 +232,14 @@ bool PNS_LINE_PLACER::handlePullback() bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd ) { - SHAPE_LINE_CHAIN& head = m_head.GetLine(); - SHAPE_LINE_CHAIN& tail = m_tail.GetLine(); + SHAPE_LINE_CHAIN& head = m_head.Line(); + SHAPE_LINE_CHAIN& tail = m_tail.Line(); int n = tail.SegmentCount(); + if(head.SegmentCount() < 1) + return false; + // Don't attempt this for too short tails if( n < 2 ) return false; @@ -231,7 +251,7 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd ) VECTOR2I new_start; int reduce_index = -1; - DIRECTION_45 head_dir( head.Segment( 0 ) ); + DIRECTION_45 head_dir( head.CSegment( 0 ) ); for( int i = tail.SegmentCount() - 1; i >= 0; i-- ) { @@ -247,7 +267,7 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd ) if( m_currentNode->CheckColliding( &tmp, PNS_ITEM::ANY ) ) break; - if( DIRECTION_45( replacement.Segment( 0 ) ) == dir ) + if( DIRECTION_45( replacement.CSegment( 0 ) ) == dir ) { new_start = s.A; new_direction = dir; @@ -285,8 +305,8 @@ bool PNS_LINE_PLACER::checkObtusity( const SEG& a, const SEG& b ) const bool PNS_LINE_PLACER::mergeHead() { - SHAPE_LINE_CHAIN& head = m_head.GetLine(); - SHAPE_LINE_CHAIN& tail = m_tail.GetLine(); + SHAPE_LINE_CHAIN& head = m_head.Line(); + SHAPE_LINE_CHAIN& tail = m_tail.Line(); const int ForbiddenAngles = DIRECTION_45::ANG_ACUTE | DIRECTION_45::ANG_HALF_FULL | @@ -357,146 +377,157 @@ bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead ) return true; PNS_LAYERSET allLayers( 0, 15 ); - PNS_VIA v( aHead.GetCLine().CPoint( -1 ), allLayers, m_viaDiameter, aHead.GetNet() ); + PNS_VIA v( aHead.CPoint( -1 ), allLayers, m_viaDiameter, aHead.Net() ); v.SetDrill( m_viaDrill ); VECTOR2I force; - VECTOR2I lead = aHead.GetCLine().CPoint( -1 ) - aHead.GetCLine().CPoint( 0 ); + VECTOR2I lead = aHead.CPoint( -1 ) - aHead.CPoint( 0 ); - if( v.PushoutForce( m_shove->GetCurrentNode(), lead, force, true, 20 ) ) + bool solidsOnly = ( m_currentMode != RM_Walkaround ); + + if( v.PushoutForce( m_currentNode, lead, force, solidsOnly, 40 ) ) { SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( - aHead.GetCLine().CPoint( 0 ), - aHead.GetCLine().CPoint( -1 ) + force ); + aHead.CPoint( 0 ), + aHead.CPoint( -1 ) + force ); aHead = PNS_LINE( aHead, line ); - v.SetPos( v.GetPos() + force ); + v.SetPos( v.Pos() + force ); return true; } return false; } - -bool PNS_LINE_PLACER::routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead, - bool aCwWalkaround ) +bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) { - // STAGE 1: route a simple two-segment trace between m_p_start and aP... SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP ); + PNS_LINE initTrack( m_head, line ), walkFull; + int effort = 0; + bool viaOk = handleViaPlacement( initTrack ); + bool rv = true; - PNS_LINE initTrack( m_head, line ); - PNS_LINE walkFull, walkSolids; + PNS_WALKAROUND walkaround( m_currentNode, Router() ); - if( m_mode == RM_Ignore ) + walkaround.SetSolidsOnly( false ); + walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() ); + + PNS_WALKAROUND::WalkaroundStatus wf = walkaround.Route( initTrack, walkFull, false ); + + switch(Settings().OptimizerEffort()) { - aNewHead = initTrack; - return true; + case OE_Low: + effort = 0; + break; + case OE_Medium: + case OE_Full: + effort = PNS_OPTIMIZER::MERGE_SEGMENTS; + break; } + if(Settings().SmartPads()) + effort |= PNS_OPTIMIZER::SMART_PADS; + + if( wf == PNS_WALKAROUND::STUCK ) + { + walkFull = walkFull.ClipToNearestObstacle( m_currentNode ); + rv = true; + + } else if( m_placingVia && viaOk ) { + PNS_LAYERSET allLayers( 0, 15 ); + PNS_VIA v1( walkFull.CPoint( -1 ), allLayers, m_viaDiameter ); + walkFull.AppendVia( v1 ); + } + + PNS_OPTIMIZER::Optimize( &walkFull, effort, m_currentNode ); + + if( m_currentNode->CheckColliding(&walkFull) ) + { + TRACEn(0, "strange, walk line colliding\n"); + } + + m_head = walkFull; + aNewHead = walkFull; + + return rv; +} + +bool PNS_LINE_PLACER::rhMarkObstacles ( const VECTOR2I& aP, PNS_LINE& aNewHead ) +{ + m_head.SetShape ( m_direction.BuildInitialTrace( m_p_start, aP ) ); + + if( m_placingVia ) + { + PNS_LAYERSET allLayers( 0, 15 ); + PNS_VIA v1( m_head.CPoint( -1 ), allLayers, m_viaDiameter ); + m_head.AppendVia( v1 ); + } + + aNewHead = m_head; + + return m_currentNode->CheckColliding( &m_head ); +} + +bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) +{ + SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP ); + PNS_LINE initTrack( m_head, line ); + PNS_LINE walkSolids, l2; handleViaPlacement( initTrack ); - m_currentNode = m_shove->GetCurrentNode(); - + m_currentNode = m_shove->CurrentNode(); PNS_OPTIMIZER optimizer( m_currentNode ); - PNS_WALKAROUND walkaround( m_currentNode ); - walkaround.SetSolidsOnly( false ); - walkaround.SetIterationLimit( m_mode == RM_Walkaround ? 8 : 5 ); - // walkaround.SetApproachCursor(true, aP); + PNS_WALKAROUND walkaround( m_currentNode, Router() ); - PNS_WALKAROUND::WalkaroundStatus wf = walkaround.Route( initTrack, walkFull ); - -#if 0 - - if( m_mode == RM_Walkaround ) - { - // walkaround. -// PNSDisplayDebugLine (walkFull.GetCLine(), 4); - - if( wf == PNS_WALKAROUND::STUCK ) - { - aNewHead = m_head; - aNewHead.SetShape( walkFull.GetCLine() ); - aNewHead = aNewHead.ClipToNearestObstacle( m_currentNode ); - return false; - } - - aNewHead = m_head; - aNewHead.SetShape( walkFull.GetCLine() ); - -// printf("nh w %d l %d\n", aNewHead.GetWidth(), aNewHead.GetLayers().Start()); - return true; - } - -#endif - - PNS_COST_ESTIMATOR cost_walk, cost_orig; - - walkaround.SetApproachCursor( false, aP ); walkaround.SetSolidsOnly( true ); walkaround.SetIterationLimit( 10 ); PNS_WALKAROUND::WalkaroundStatus stat_solids = walkaround.Route( initTrack, walkSolids ); optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_SEGMENTS ); - optimizer.SetCollisionMask( PNS_ITEM::SOLID ); + optimizer.SetCollisionMask ( PNS_ITEM::SOLID ); optimizer.Optimize( &walkSolids ); - #if 0 - optimizer.SetCollisionMask( -1 ); - optimizer.Optimize( &walkFull ); - #endif - cost_orig.Add( initTrack ); - cost_walk.Add( walkFull ); - if( m_mode == RM_Smart || m_mode == RM_Shove ) - { - PNS_LINE l2; - - bool walk_better = cost_orig.IsBetter( cost_walk, 1.5, 10.0 ); - walk_better = false; - -#if 0 - printf( "RtTrk width %d %d %d", initTrack.GetWidth(), - walkFull.GetWidth(), walkSolids.GetWidth() ); - printf( "init-coll %d\n", m_currentNode->CheckColliding( &initTrack ) ? 1 : 0 ); - printf( "total cost: walk cor %.0f len %.0f orig cor %.0f len %.0f walk-better %d\n", - cost_walk.GetCornerCost(), cost_walk.GetLengthCost(), - cost_orig.GetCornerCost(), cost_orig.GetLengthCost(), - walk_better ); -#endif - - if( m_mode == RM_Smart && wf == PNS_WALKAROUND::DONE && walk_better - && walkFull.GetCLine().CPoint( -1 ) == initTrack.GetCLine().CPoint( -1 ) ) - l2 = walkFull; - else if( stat_solids == PNS_WALKAROUND::DONE ) + if( stat_solids == PNS_WALKAROUND::DONE ) l2 = walkSolids; else - l2 = initTrack.ClipToNearestObstacle( m_shove->GetCurrentNode() ); + l2 = initTrack.ClipToNearestObstacle( m_shove->CurrentNode() ); - PNS_LINE l( m_tail ); - l.GetLine().Append( l2.GetCLine() ); - l.GetLine().Simplify(); + PNS_LINE l( m_tail ); + l.Line().Append( l2.CLine() ); + l.Line().Simplify(); - if( m_placingVia ) - { - PNS_LAYERSET allLayers( 0, 15 ); - PNS_VIA v1( l.GetCLine().CPoint( -1 ), allLayers, m_viaDiameter ); - PNS_VIA v2( l2.GetCLine().CPoint( -1 ), allLayers, m_viaDiameter ); - v1.SetDrill( m_viaDrill ); - v2.SetDrill( m_viaDrill ); + if( m_placingVia ) + { + PNS_LAYERSET allLayers( 0, 15 ); + PNS_VIA v1( l.CPoint( -1 ), allLayers, m_viaDiameter ); + PNS_VIA v2( l2.CPoint( -1 ), allLayers, m_viaDiameter ); + v1.SetDrill( m_viaDrill ); + v2.SetDrill( m_viaDrill ); - l.AppendVia( v1 ); - l2.AppendVia( v2 ); - } + l.AppendVia( v1 ); + l2.AppendVia( v2 ); + } - PNS_SHOVE::ShoveStatus status = m_shove->ShoveLines( &l ); - m_currentNode = m_shove->GetCurrentNode(); + l.Line().Simplify(); - if( status == PNS_SHOVE::SH_OK ) + // in certain, uncommon cases there may be loops in the head+tail, In such case, we don't shove to avoid + // screwing up the database. + if ( l.HasLoops() ) + { + aNewHead = m_head; + return false; + } + + PNS_SHOVE::ShoveStatus status = m_shove->ShoveLines( l ); + + m_currentNode = m_shove->CurrentNode(); + + if( status == PNS_SHOVE::SH_OK ) { optimizer.SetWorld( m_currentNode ); - optimizer.ClearCache(); optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS ); - optimizer.SetCollisionMask( -1 ); + optimizer.SetCollisionMask( PNS_ITEM::ANY ); optimizer.Optimize( &l2 ); aNewHead = l2; @@ -510,25 +541,59 @@ bool PNS_LINE_PLACER::routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead, walkaround.SetIterationLimit( 10 ); walkaround.SetApproachCursor( true, aP ); walkaround.Route( initTrack, l2 ); - aNewHead = l2.ClipToNearestObstacle( m_shove->GetCurrentNode() ); - // aNewHead = l2; + aNewHead = l2.ClipToNearestObstacle( m_shove->CurrentNode() ); return false; } - } + + return false; +} + +bool PNS_LINE_PLACER::routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead ) +{ + switch( m_currentMode ) + { + case RM_MarkObstacles: + return rhMarkObstacles( aP, aNewHead ); + case RM_Walkaround: + return rhWalkOnly ( aP, aNewHead ); + case RM_Shove: + return rhShoveOnly ( aP, aNewHead ); + default: + break; + } + return false; } bool PNS_LINE_PLACER::optimizeTailHeadTransition() { - SHAPE_LINE_CHAIN& head = m_head.GetLine(); - SHAPE_LINE_CHAIN& tail = m_tail.GetLine(); + + PNS_LINE tmp = Trace(); - const int TailLookbackSegments = 5; + if(PNS_OPTIMIZER::Optimize(&tmp, PNS_OPTIMIZER::FANOUT_CLEANUP, m_currentNode)) + { + if(tmp.SegmentCount() < 1) + return false; - int threshold = std::min( tail.PointCount(), TailLookbackSegments + 1 ); + m_head = tmp; + m_p_start = tmp.CLine().CPoint( 0 ); + m_direction = DIRECTION_45( tmp.CSegment( 0 ) ); + m_tail.Line().Clear(); + return true; + } + + SHAPE_LINE_CHAIN& head = m_head.Line(); + SHAPE_LINE_CHAIN& tail = m_tail.Line(); + + int tailLookbackSegments = 3; + + //if(m_currentMode() == RM_Walkaround) + // tailLookbackSegments = 10000; + + int threshold = std::min( tail.PointCount(), tailLookbackSegments + 1 ); if( tail.SegmentCount() < 3 ) return false; @@ -536,8 +601,9 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition() // assemble TailLookbackSegments tail segments with the current head SHAPE_LINE_CHAIN opt_line = tail.Slice( -threshold, -1 ); - opt_line.Append( head ); -// opt_line.Simplify(); + int end = std::min(2, head.PointCount() - 1 ); + + opt_line.Append( head.Slice( 0, end ) ); PNS_LINE new_head( m_tail, opt_line ); @@ -545,20 +611,18 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition() // If so, replace the (threshold) last tail points and the head with // the optimized line - // if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_SEGMENTS)) - - if( new_head.MergeSegments() ) + if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_OBTUSE, m_currentNode)) { PNS_LINE tmp( m_tail, opt_line ); TRACE( 0, "Placer: optimize tail-head [%d]", threshold ); head.Clear(); - tail.Replace( -threshold, -1, new_head.GetCLine() ); + tail.Replace( -threshold, -1, new_head.CLine() ); tail.Simplify(); - m_p_start = new_head.GetCLine().CPoint( -1 ); - m_direction = DIRECTION_45( new_head.GetCLine().CSegment( -1 ) ); + m_p_start = new_head.CLine().CPoint( -1 ); + m_direction = DIRECTION_45( new_head.CSegment( -1 ) ); return true; } @@ -576,26 +640,24 @@ void PNS_LINE_PLACER::routeStep( const VECTOR2I& aP ) PNS_LINE new_head; - m_follow_mouse = true; - TRACE( 2, "INIT-DIR: %s head: %d, tail: %d segs\n", - m_initial_direction.Format().c_str() % m_head.GetCLine().SegmentCount() % - m_tail.GetCLine().SegmentCount() ); + m_initial_direction.Format().c_str() % m_head.SegmentCount() % + m_tail.SegmentCount() ); for( i = 0; i < n_iter; i++ ) { - if( !go_back && m_follow_mouse ) + if( !go_back && Settings().FollowMouse() ) reduceTail( aP ); go_back = false; - if( !routeHead( aP, new_head, true ) ) + if( !routeHead( aP, new_head ) ) fail = true; if( !new_head.Is45Degree() ) fail = true; - if( !m_follow_mouse ) + if( !Settings().FollowMouse() ) return; m_head = new_head; @@ -615,48 +677,36 @@ void PNS_LINE_PLACER::routeStep( const VECTOR2I& aP ) if( !fail ) { - if( optimizeTailHeadTransition() ) - return; + if( optimizeTailHeadTransition() ) + return; mergeHead(); } } -bool PNS_LINE_PLACER::Route( const VECTOR2I& aP ) +bool PNS_LINE_PLACER::route( const VECTOR2I& aP ) { - if( m_smooth_mouse ) - { - VECTOR2I p_cur = m_p_start; - VECTOR2I step = (aP - m_p_start).Resize( m_smoothing_step ); - - do - { - if( (p_cur - aP).EuclideanNorm() <= m_smoothing_step ) - p_cur = aP; - else - p_cur += step; - - routeStep( p_cur ); - } while( p_cur != aP ); - } - else - routeStep( aP ); - + routeStep( aP ); return CurrentEnd() == aP; } -const PNS_LINE PNS_LINE_PLACER::GetTrace() const +const PNS_LINE PNS_LINE_PLACER::Trace() const { PNS_LINE tmp( m_head ); - tmp.SetShape( m_tail.GetCLine() ); - tmp.GetLine().Append( m_head.GetCLine() ); - tmp.GetLine().Simplify(); + tmp.SetShape( m_tail.CLine() ); + tmp.Line().Append( m_head.CLine() ); + tmp.Line().Simplify(); return tmp; } +const PNS_ITEMSET PNS_LINE_PLACER::Traces() +{ + m_currentTrace = Trace(); + return PNS_ITEMSET( &m_currentTrace ); +} void PNS_LINE_PLACER::FlipPosture() { @@ -664,15 +714,301 @@ void PNS_LINE_PLACER::FlipPosture() m_direction = m_direction.Right(); } - -void PNS_LINE_PLACER::GetUpdatedItems( PNS_NODE::ItemVector& aRemoved, - PNS_NODE::ItemVector& aAdded ) +PNS_NODE* PNS_LINE_PLACER::CurrentNode(bool aLoopsRemoved) const { - return m_shove->GetCurrentNode()->GetUpdatedItems( aRemoved, aAdded ); + if(aLoopsRemoved && m_lastNode) + return m_lastNode; + return m_currentNode; } -PNS_NODE* PNS_LINE_PLACER::GetCurrentNode() const +void PNS_LINE_PLACER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP ) { - return m_shove->GetCurrentNode(); + if( aSeg && aSeg->OfKind( PNS_ITEM::SEGMENT ) ) + { + PNS_JOINT *jt = aNode->FindJoint( aP, aSeg ); + + if( jt && jt->LinkCount() >= 1 ) + return; + + PNS_SEGMENT* s_old = static_cast( aSeg ); + + PNS_SEGMENT* s_new[2]; + + s_new[0] = s_old->Clone(); + s_new[1] = s_old->Clone(); + + s_new[0]->SetEnds( s_old->Seg().A, aP ); + s_new[1]->SetEnds( aP, s_old->Seg().B ); + + aNode->Remove( s_old ); + aNode->Add( s_new[0], true ); + aNode->Add( s_new[1], true ); + } } + +void PNS_LINE_PLACER::SetLayer(int aLayer) +{ + m_currentLayer = aLayer; +} + +void PNS_LINE_PLACER::SetWidth(int aWidth) +{ + m_currentWidth = aWidth; +} + +void PNS_LINE_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) +{ + VECTOR2I p( aP ); + + static int unknowNetIdx = 0; // -10000; + int net = -1; + + m_lastNode = NULL; + m_placingVia = false; + m_startsOnVia = false; + + bool splitSeg = false; + + if( Router()->SnappingEnabled() ) + p = Router()->SnapToItem( aStartItem, aP, splitSeg ); + + if( !aStartItem || aStartItem->Net() < 0 ) + net = unknowNetIdx--; + else + net = aStartItem->Net(); + + m_currentStart = p; + m_originalStart = p; + m_currentEnd = p; + m_currentNet = net; + + + PNS_NODE *rootNode = Router()->GetWorld()->Branch(); + + if( splitSeg ) + splitAdjacentSegments( rootNode, aStartItem, p ); + + setWorld ( rootNode ); + setInitialDirection( Settings().InitialDirection() ); + startPlacement( p, m_currentNet, m_currentWidth, m_currentLayer ); +} + + +void PNS_LINE_PLACER::Move( const VECTOR2I& aP, PNS_ITEM* aEndItem ) +{ + PNS_LINE current; + VECTOR2I p = aP; + int eiDepth = -1; + + if(aEndItem && aEndItem->Owner()) + eiDepth = aEndItem->Owner()->Depth(); + + if( m_lastNode ) + { + delete m_lastNode; + m_lastNode = NULL; + } + + route( p ); + + current = Trace(); + + if(!current.PointCount()) + m_currentEnd = m_p_start; + else + m_currentEnd = current.CLine().CPoint(-1); + + + PNS_NODE *latestNode = m_currentNode; + m_lastNode = latestNode->Branch(); + + + if(eiDepth >= 0 && aEndItem && latestNode->Depth() > eiDepth && current.SegmentCount() && current.CPoint(-1) == aP) + { + splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint(-1) ); + if(Settings().RemoveLoops()) + removeLoops( m_lastNode, ¤t ); + } + + updateLeadingRatLine(); +} + +bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) +{ + bool realEnd = false; + int lastV; + + PNS_LINE pl = Trace(); + + if (m_currentMode == RM_MarkObstacles && + !Settings().CanViolateDRC() && + m_world->CheckColliding( &pl ) ) + return false; + + const SHAPE_LINE_CHAIN& l = pl.CLine(); + + if( !l.SegmentCount() ) + return true; + + VECTOR2I p_pre_last = l.CPoint( -1 ); + const VECTOR2I p_last = l.CPoint( -1 ); + DIRECTION_45 d_last( l.CSegment( -1 ) ); + + if( l.PointCount() > 2 ) + p_pre_last = l.CPoint( -2 ); + + if( aEndItem && m_currentNet >= 0 && m_currentNet == aEndItem->Net() ) + realEnd = true; + + + if(realEnd || m_placingVia) + lastV = l.SegmentCount(); + else + lastV = std::max( 1, l.SegmentCount() - 1 ); + + + PNS_SEGMENT* lastSeg = NULL; + + for( int i = 0; i < lastV; i++ ) + { + const SEG& s = pl.CSegment( i ); + PNS_SEGMENT* seg = new PNS_SEGMENT( s, m_currentNet ); + seg->SetWidth( pl.Width() ); + seg->SetLayer( m_currentLayer ); + m_lastNode->Add( seg ); + lastSeg = seg; + } + + if( pl.EndsWithVia() ) + m_lastNode->Add( pl.Via().Clone() ); + + if(realEnd) + simplifyNewLine ( m_lastNode, lastSeg ); + + Router()->CommitRouting ( m_lastNode ); + + m_lastNode = NULL; + + if(!realEnd) + { + setInitialDirection( d_last ); + VECTOR2I p_start = m_placingVia ? p_last : p_pre_last; + + if( m_placingVia ) + m_currentLayer = Router()->NextCopperLayer( true ); + + setWorld ( Router()->GetWorld()->Branch() ); + startPlacement( p_start, m_head.Net(), m_head.Width(), m_currentLayer ); + + m_startsOnVia = m_placingVia; + m_placingVia = false; + } + + return realEnd; +} + +void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest ) +{ + if(!aLatest->SegmentCount()) + return; + + aNode->Add( aLatest, true ); + + for(int s = 0; s < aLatest->SegmentCount(); s++ ) + { + PNS_SEGMENT *seg = (*aLatest->LinkedSegments())[s]; + + PNS_LINE* ourLine = aNode->AssembleLine( seg ) ; + PNS_JOINT a, b; + + std::vector lines; + + aNode->FindLineEnds( ourLine, a, b ); + + if( a == b ) + { + aNode->FindLineEnds( aLatest, a, b); + } + + aNode->FindLinesBetweenJoints( a, b, lines ); + + int removedCount = 0; + int total = 0; + + BOOST_FOREACH( PNS_LINE* line, lines ) + { + total++; + + if( !( line->ContainsSegment( seg ) ) && line->SegmentCount() ) + { + Router()->DisplayDebugLine ( line->CLine(), -1, 10000 ); + + for(int i = 0; i < line->PointCount(); i++ ) + Router()->DisplayDebugPoint ( line->CPoint(i), -1 ); + + aNode->Remove( line ); + removedCount ++; + } + } + + TRACE(0, "total segs removed: %d/%d\n", removedCount % total); + + delete ourLine; + } + + aNode->Remove( aLatest ); +} + +void PNS_LINE_PLACER::simplifyNewLine ( PNS_NODE *aNode, PNS_SEGMENT *aLatest ) +{ + PNS_LINE *l = aNode->AssembleLine( aLatest) ; + SHAPE_LINE_CHAIN simplified ( l->CLine() ); + simplified.Simplify(); + + if(simplified.PointCount() != l->PointCount()) + { + std::auto_ptr lnew ( l->Clone() ); + aNode -> Remove(l); + lnew->SetShape(simplified); + aNode -> Add( lnew.get() ); + } +} + +void PNS_LINE_PLACER::UpdateSizes( const PNS_ROUTING_SETTINGS& aSettings ) +{ + int trackWidth = aSettings.GetTrackWidth(); + + m_head.SetWidth( trackWidth ); + m_tail.SetWidth( trackWidth ); + + m_viaDiameter = aSettings.GetViaDiameter(); + m_viaDrill = aSettings.GetViaDrill(); +} + +void PNS_LINE_PLACER::updateLeadingRatLine() +{ + PNS_LINE current = Trace(); + + if(! current.PointCount() ) + return; + + std::auto_ptr tmpNode ( m_lastNode->Branch() ); + tmpNode->Add( ¤t ); + + PNS_JOINT *jt = tmpNode->FindJoint( current.CPoint(-1), current.Layers().Start(), current.Net() ); + + if(!jt) + return; + + int anchor; + PNS_ITEM *it = tmpNode->NearestUnconnectedItem ( jt, &anchor ); + + if(it) + { + SHAPE_LINE_CHAIN lc; + lc.Append ( current.CPoint(-1) ); + lc.Append ( it->Anchor(anchor) ); + Router()->DisplayDebugLine( lc, 5, 10000 ); + } +} \ No newline at end of file diff --git a/pcbnew/router/pns_line_placer.h b/pcbnew/router/pns_line_placer.h index 625e6451b2..ddbeb23c74 100644 --- a/pcbnew/router/pns_line_placer.h +++ b/pcbnew/router/pns_line_placer.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_LINE_PLACER_H @@ -29,7 +29,7 @@ #include "pns_node.h" #include "pns_via.h" #include "pns_line.h" -#include "pns_routing_settings.h" +#include "pns_algo_base.h" class PNS_ROUTER; class PNS_SHOVE; @@ -39,29 +39,156 @@ class PNS_ROUTER_BASE; /** * Class PNS_LINE_PLACER * - * Interactively routes a single track. Runs shove and walkaround - * algorithms when needed. + * Single track placement algorithm. Interactively routes a track. + * Applies shove and walkaround algorithms when needed. */ -class PNS_LINE_PLACER +class PNS_LINE_PLACER : public PNS_ALGO_BASE { public: - PNS_LINE_PLACER( PNS_NODE* aWorld ); + PNS_LINE_PLACER( PNS_ROUTER *aRouter ); ~PNS_LINE_PLACER(); - ///> Appends a via at the end of currently placed line. - void AddVia( bool aEnabled, int aDiameter, int aDrill ) - { - m_viaDiameter = aDiameter; - m_viaDrill = aDrill; - m_placingVia = aEnabled; - } - - ///> Starts placement of a line at point aStart. - void StartPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer ); + /** + * Function Start() + * + * Starts routing a single track at point aP, taking item aStartItem as anchor + * (unless NULL). + */ + void Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem ); + + /** + * Function Move() + * + * Moves the end of the currently routed trace to the point aP, taking + * aEndItem as anchor (if not NULL). + * (unless NULL). + */ + void Move( const VECTOR2I& aP, PNS_ITEM* aEndItem ); /** - * Function Route() + * Function FixRoute() + * + * Commits the currently routed track to the parent node, taking + * aP as the final end point and aEndItem as the final anchor (if provided). + * @return true, if route has been commited. May return false if the routing + * result is violating design rules - in such case, the track is only committed + * if Settings.CanViolateDRC() is on. + */ + bool FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ); + + /** + * Function AddVia() + * + * Enables/disables a via at the end of currently routed trace. + * @param aEnabled if true, a via is attached during placement + * @param aDiameter diameter of the via + * @param aDrill drill of the via + */ + void AddVia( bool aEnabled, int aDiameter, int aDrill ); + + /** + * Function SetLayer() + * + * Sets the current routing layer. + */ + void SetLayer ( int aLayer ); + + /** + * Function SetWidth() + * + * Sets the current track width. + */ + void SetWidth ( int aWidth ); + + /** + * Function Head() + * + * Returns the "head" of the line being placed, that is the volatile part + * that has not "settled" yet. + */ + const PNS_LINE& Head() const { return m_head; } + + /** + * Function Tail() + * + * Returns the "tail" of the line being placed, the part which has already wrapped around + * and shoved some obstacles. + */ + const PNS_LINE& Tail() const { return m_tail; } + + /** + * Function Trace() + * + * Returns the complete routed line. + */ + const PNS_LINE Trace() const; + + /** + * Function Traces() + * + * Returns the complete routed line, as a single-member PNS_ITEMSET. + */ + const PNS_ITEMSET Traces(); + + /** + * Function CurrentEnd() + * + * Returns the current end of the line being placed. It may not be equal + * to the cursor position due to collisions. + */ + const VECTOR2I& CurrentEnd() const + { + return m_currentEnd; + } + + /** + * Function CurrentNet() + * + * Returns the net code of currently routed track. + */ + int CurrentNet() const + { + return m_currentNet; + } + + /** + * Function CurrentLayer() + * + * Returns the layer of currently routed track. + */ + int CurrentLayer() const + { + return m_currentLayer; + } + + /** + * Function CurrentNode() + * + * Returns the most recent world state. + */ + PNS_NODE* CurrentNode(bool aLoopsRemoved = false) const; + + /** + * Function FlipPosture() + * + * Toggles the current posture (straight/diagonal) of the trace head. + */ + void FlipPosture(); + + /** + * Function UpdateSizes() + * + * Performs on-the-fly update of the width, via diameter & drill size from + * a settings class. Used to dynamically change these parameters as + * the track is routed. + */ + void UpdateSizes( const PNS_ROUTING_SETTINGS& aSettings ); + + +private: + /** + * Function route() * * Re-routes the current track to point aP. Returns true, when routing has * completed successfully (i.e. the trace end has reached point aP), and false @@ -70,55 +197,76 @@ public: * @param aP ending point of current route. * @return true, if the routing is complete. */ - bool Route( const VECTOR2I& aP ); - ///> Sets initial routing direction/posture - void SetInitialDirection( const DIRECTION_45& aDirection ); + bool route( const VECTOR2I& aP ); - void ApplySettings( const PNS_ROUTING_SETTINGS& aSettings ); + /** + * Function updateLeadingRatLine() + * + * Draws the "leading" ratsnest line, which connects the end of currently + * routed track and the nearest yet unrouted item. If the routing for + * current net is complete, draws nothing. + */ + void updateLeadingRatLine(); + + /** + * Function setWorld() + * + * Sets the board to route. + */ + void setWorld ( PNS_NODE *aWorld ); + + /** + * Function startPlacement() + * + * Initializes placement of a new line with given parameters. + */ + void startPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer ); - ///> Returns the "head" of the line being placed, that is the volatile part - ///> that has not been settled yet - const PNS_LINE& GetHead() const { return m_head; } - ///> Returns the "tail" of the line being placed the part that has been - ///> fixed already (follow mouse mode only) - const PNS_LINE& GetTail() const { return m_tail; } + /** + * Function setInitialDirection() + * + * Sets preferred direction of the very first track segment to be laid. + * Used by posture switching mechanism. + */ + void setInitialDirection( const DIRECTION_45& aDirection ); - ///> Returns the whole routed line - const PNS_LINE GetTrace() const; + /** + * Function splitAdjacentSegments() + * + * Checks if point aP lies on segment aSeg. If so, splits the segment in two, + * forming a joint at aP and stores updated topology in node aNode. + */ + void splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP ); - ///> Returns the current end of the line being placed. It may not be equal - ///> to the cursor position due to collisions. - const VECTOR2I& CurrentEnd() const - { - if( m_head.GetCLine().PointCount() > 0 ) - return m_head.GetCLine().CPoint( -1 ); - else if( m_tail.GetCLine().PointCount() > 0 ) - return m_tail.GetCLine().CPoint( -1 ); - else - return m_p_start; - } + /** + * Function removeLoops() + * + * Searches aNode for traces concurrent to aLatest and removes them. Updated + * topology is stored in aNode. + */ + void removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest ); - ///> Returns all items in the world that have been affected by the routing - ///> operation. Used to update data structures of the host application - void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved, - PNS_NODE::ItemVector& aAdded ); - - ///> Toggles the current posture (straight/diagonal) of the trace head. - void FlipPosture(); - - ///> Returns the most recent world state - PNS_NODE* GetCurrentNode() const; - -private: - static const double m_shoveLengthThreshold; + /** + * Function simplifyNewLine() + * + * Assembles a line starting from segment aLatest, removes collinear segments + * and redundant vertexes. If a simplification bhas been found, replaces the + * old line with the simplified one in aNode. + */ + void simplifyNewLine ( PNS_NODE *aNode, PNS_SEGMENT *aLatest ); + /** + * Function handleViaPlacement() + * + * Attempts to find a spot to place the via at the end of line aHead. + */ bool handleViaPlacement( PNS_LINE& aHead ); /** * Function checkObtusity() * - * Helper that checks if segments a and b form an obtuse angle + * Helper function, checking if segments a and b form an obtuse angle * (in 45-degree regime). * @return true, if angle (a, b) is obtuse */ @@ -163,8 +311,6 @@ private: */ bool reduceTail( const VECTOR2I& aEnd ); - void fixHeadPosture(); - /** * Function optimizeTailHeadTransition() * @@ -182,8 +328,7 @@ private: * around all colliding solid or non-movable items. Movable segments are * ignored, as they'll be handled later by the shove algorithm. */ - bool routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead, - bool aCwWalkaround = true ); + bool routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead); /** * Function routeStep() @@ -194,18 +339,15 @@ private: */ void routeStep( const VECTOR2I& aP ); - ///> routing mode (walkaround, shove, etc.) - PNS_MODE m_mode; + ///< route step, walkaround mode + bool rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead); - ///> follow mouse trail by attaching new segments to the head - ///> as the cursor moves - bool m_follow_mouse; + ///< route step, shove mode + bool rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead); - ///> mouse smoothing active - bool m_smooth_mouse; - - ///> mouse smoothing step (in world units) - int m_smoothing_step; + ///< route step, mark obstacles mode + bool rhMarkObstacles ( const VECTOR2I& aP, PNS_LINE& aNewHead ); + ///> current routing direction DIRECTION_45 m_direction; @@ -235,6 +377,9 @@ private: ///> Current world state PNS_NODE* m_currentNode; + ///> Postprocessed world state (including marked collisions & removed loops) + PNS_NODE* m_lastNode; + ///> Are we placing a via? bool m_placingVia; @@ -244,11 +389,17 @@ private: ///> current via drill int m_viaDrill; - ///> walkaround algorithm iteration limit - int m_walkaroundIterationLimit; + int m_currentWidth; + int m_currentNet; + int m_currentLayer; + + bool m_startsOnVia; + + VECTOR2I m_originalStart, m_currentEnd, m_currentStart; + PNS_LINE m_currentTrace; + + PNS_MODE m_currentMode; - ///> smart pads optimizer enabled. - bool m_smartPads; }; #endif // __PNS_LINE_PLACER_H diff --git a/pcbnew/router/pns_logger.cpp b/pcbnew/router/pns_logger.cpp new file mode 100644 index 0000000000..e20577b6b9 --- /dev/null +++ b/pcbnew/router/pns_logger.cpp @@ -0,0 +1,173 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#include "pns_logger.h" +#include "pns_item.h" +#include "pns_via.h" +#include "pns_line.h" +#include "pns_segment.h" +#include "pns_solid.h" + +#include +#include +#include +#include + +PNS_LOGGER::PNS_LOGGER( ) +{ + m_groupOpened = false; +} + + +PNS_LOGGER::~PNS_LOGGER() +{ + +} + +void PNS_LOGGER::Clear() +{ + m_theLog.str(std::string()); + m_groupOpened = false; +} + +void PNS_LOGGER::NewGroup ( const std::string& name, int iter) +{ + if(m_groupOpened) + m_theLog << "endgroup" << std::endl; + m_theLog << "group " << name << " " << iter << std::endl; + m_groupOpened = true; +} + +void PNS_LOGGER::EndGroup() +{ + if(!m_groupOpened) + return; + + m_groupOpened = false; + m_theLog << "endgroup" << std::endl; +} + +void PNS_LOGGER::Log ( const PNS_ITEM *item, int kind, const std::string name ) +{ + m_theLog << "item " << kind << " " << name << " "; + m_theLog << item->Net() << " " << item->Layers().Start() << " " << item->Layers().End() << " " << item->Marker() << " " << item->Rank(); + + switch(item->Kind()) + { + case PNS_ITEM::LINE: + { + PNS_LINE *l = (PNS_LINE *) item; + m_theLog << " line "; + m_theLog << l->Width() << " " << (l->EndsWithVia() ? 1 : 0) << " "; + dumpShape ( l->Shape() ); + m_theLog << std::endl; + break; + } + case PNS_ITEM::VIA: + { + m_theLog << " via 0 0 "; + dumpShape ( item->Shape() ); + m_theLog << std::endl; + break; + } + + case PNS_ITEM::SEGMENT: + { + PNS_SEGMENT *s =(PNS_SEGMENT *) item; + m_theLog << " line "; + m_theLog << s->Width() << " 0 linechain 2 0 " << s->Seg().A.x << " " <Seg().A.y << " " << s->Seg().B.x << " " <Seg().B.y << std::endl; + break; + } + + case PNS_ITEM::SOLID: + { + PNS_SOLID *s = (PNS_SOLID*) item; + m_theLog << " solid 0 0 "; + dumpShape ( s->Shape() ); + m_theLog << std::endl; + break; + } + + default: + break; + } +} + +void PNS_LOGGER::Log ( const SHAPE_LINE_CHAIN *l, int kind, const std::string name ) +{ + m_theLog << "item " << kind << " " << name << " "; + m_theLog << 0 << " " << 0 << " " << 0 << " " << 0 << " " << 0; + m_theLog << " line "; + m_theLog << 0 << " " << 0 << " "; + dumpShape ( l ); + m_theLog << std::endl; +} + +void PNS_LOGGER::Log ( const VECTOR2I& start, const VECTOR2I& end, int kind , const std::string name) +{ + +} + +void PNS_LOGGER::dumpShape ( const SHAPE * sh ) +{ + switch(sh->Type()) + { + case SH_LINE_CHAIN: + { + const SHAPE_LINE_CHAIN *lc = (const SHAPE_LINE_CHAIN *) sh; + m_theLog << "linechain " << lc->PointCount() << " " << (lc->IsClosed() ? 1 : 0) << " "; + for(int i = 0; i < lc->PointCount(); i++) + m_theLog << lc->CPoint(i).x << " " << lc->CPoint(i).y << " "; + break; + } + case SH_CIRCLE: + { + const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE *) sh; + m_theLog << "circle " << c->GetCenter().x << " " << c->GetCenter().y << " " << c->GetRadius(); + break; + } + case SH_RECT: + { + const SHAPE_RECT *r = (const SHAPE_RECT *) sh; + m_theLog << "rect " << r->GetPosition().x << " " << r->GetPosition().y << " " << r->GetSize().x << " " <GetSize().y; + break; + } + case SH_SEGMENT: + { + const SHAPE_SEGMENT *s = (const SHAPE_SEGMENT *) sh; + m_theLog << "linechain 2 0 " << s->GetSeg().A.x << " " << s->GetSeg().A.y << " " << s->GetSeg().B.x << " " << s->GetSeg().B.y; + break; + } + default: + break; + } +} + +void PNS_LOGGER::Save ( const std::string& filename ) +{ + + EndGroup(); + + FILE *f=fopen(filename.c_str(),"wb"); + printf("Saving to '%s' [%p]\n", filename.c_str(), f); + const std::string s = m_theLog.str(); + fwrite(s.c_str(), 1, s.length(), f); + fclose(f); +} diff --git a/pcbnew/router/pns_logger.h b/pcbnew/router/pns_logger.h new file mode 100644 index 0000000000..cc112908ae --- /dev/null +++ b/pcbnew/router/pns_logger.h @@ -0,0 +1,58 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#ifndef __PNS_LOGGER_H +#define __PNS_LOGGER_H + +#include +#include +#include +#include + +#include + +class PNS_ITEM; +class SHAPE_LINE_CHAIN; +class SHAPE; + +class PNS_LOGGER { + +public: + PNS_LOGGER(); + ~PNS_LOGGER(); + + void Save ( const std::string& filename ); + + void Clear(); + void NewGroup ( const std::string& name, int iter = 0); + void EndGroup(); + void Log ( const PNS_ITEM *item, int kind = 0, const std::string name = std::string () ); + void Log ( const SHAPE_LINE_CHAIN *l, int kind = 0, const std::string name = std::string () ); + void Log ( const VECTOR2I& start, const VECTOR2I& end, int kind = 0, const std::string name = std::string () ); + +private: + + void dumpShape ( const SHAPE* sh ); + + bool m_groupOpened; + std::stringstream m_theLog; +}; + +#endif diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index 825be77e57..4413289dfb 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include @@ -36,31 +36,40 @@ #include "pns_solid.h" #include "pns_joint.h" #include "pns_index.h" +#include "pns_router.h" using boost::unordered_set; using boost::unordered_map; +#ifdef DEBUG static boost::unordered_set allocNodes; +#endif PNS_NODE::PNS_NODE() { - // printf("MakeNode [%p, total = %d]\n", this, allocNodes.size()); + TRACE( 0, "PNS_NODE::create %p", this ); + m_depth = 0; m_root = this; m_parent = NULL; m_maxClearance = 800000; // fixme: depends on how thick traces are. m_index = new PNS_INDEX; +#ifdef DEBUG allocNodes.insert( this ); +#endif } - PNS_NODE::~PNS_NODE() { + TRACE( 0, "PNS_NODE::delete %p", this ); + if( !m_children.empty() ) { TRACEn( 0, "attempting to free a node that has kids.\n" ); assert( false ); } +#ifdef DEBUG + if( allocNodes.find( this ) == allocNodes.end() ) { TRACEn( 0, "attempting to free an already-free'd node.\n" ); @@ -69,6 +78,8 @@ PNS_NODE::~PNS_NODE() allocNodes.erase( this ); +#endif + for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i ) if( (*i)->BelongsTo( this ) ) @@ -81,30 +92,19 @@ PNS_NODE::~PNS_NODE() int PNS_NODE::GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const { - int clearance = (*m_clearanceFunctor)( a, b ); - - if( a->OfKind( PNS_ITEM::SEGMENT ) ) - clearance += static_cast(a)->GetWidth() / 2; - - if( a->OfKind( PNS_ITEM::LINE ) ) - clearance += static_cast(a)->GetWidth() / 2; - - if( b->OfKind( PNS_ITEM::SEGMENT ) ) - clearance += static_cast(b)->GetWidth() / 2; - - if( b->OfKind( PNS_ITEM::LINE ) ) - clearance += static_cast(b)->GetWidth() / 2; - - return clearance; + return (*m_clearanceFunctor)( a, b ); } - PNS_NODE* PNS_NODE::Branch() { PNS_NODE* child = new PNS_NODE; + TRACE( 0, "PNS_NODE::branch %p (parent %p)", child % this ); + + m_children.push_back( child ); + child->m_depth = m_depth + 1; child->m_parent = this; child->m_clearanceFunctor = m_clearanceFunctor; child->m_root = isRoot() ? this : m_root; @@ -173,14 +173,21 @@ struct PNS_NODE::obstacleVisitor ///> number of items found so far int m_matchCount; + ///> additional clearance + int m_extraClearance; + obstacleVisitor( PNS_NODE::Obstacles& aTab, const PNS_ITEM* aItem, int aKindMask ) : m_tab( aTab ), m_item( aItem ), m_kindMask( aKindMask ), m_limitCount( -1 ), - m_matchCount( 0 ) - {}; + m_matchCount( 0 ), + m_extraClearance( 0 ) + { + if(aItem->Kind() == PNS_ITEM::LINE) + m_extraClearance += static_cast(aItem)->Width() / 2; + }; void SetCountLimit( int aLimit ) { @@ -203,7 +210,10 @@ struct PNS_NODE::obstacleVisitor if( m_override && m_override->overrides( aItem ) ) return true; - int clearance = m_node->GetClearance( aItem, m_item ); + int clearance = m_extraClearance + m_node->GetClearance( aItem, m_item ); + + if(aItem->Kind() == PNS_ITEM::LINE) + clearance += static_cast(aItem)->Width() / 2; if( !aItem->Collide( m_item, clearance ) ) return true; @@ -228,12 +238,14 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem, { obstacleVisitor visitor( aObstacles, aItem, aKindMask ); +#ifdef DEBUG assert( allocNodes.find( this ) != allocNodes.end() ); +#endif visitor.SetCountLimit( aLimitCount ); visitor.SetWorld( this, NULL ); - // first, look for colliding items ourselves + // first, look for colliding items in the local index m_index->Query( aItem, m_maxClearance, visitor ); // if we haven't found enough items, look in the root branch as well. @@ -252,7 +264,7 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin Obstacles obs_list; bool found_isects = false; - const SHAPE_LINE_CHAIN& line = aItem->GetCLine(); + const SHAPE_LINE_CHAIN& line = aItem->CLine(); obs_list.reserve( 100 ); @@ -265,7 +277,7 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin } if( aItem->EndsWithVia() ) - n += QueryColliding( &aItem->GetVia(), obs_list, aKindMask ); + n += QueryColliding( &aItem->Via(), obs_list, aKindMask ); // if(! QueryColliding ( aItem, obs_list, aKindMask )) if( !n ) @@ -286,20 +298,20 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin int clearance = GetClearance( obs.item, &aLine ); - SHAPE_LINE_CHAIN hull = obs.item->Hull( clearance ); + SHAPE_LINE_CHAIN hull = obs.item->Hull( clearance, aItem->Width() ); if( aLine.EndsWithVia() ) { - int clearance = GetClearance( obs.item, &aLine.GetVia() ); + int clearance = GetClearance( obs.item, &aLine.Via() ); - SHAPE_LINE_CHAIN viaHull = aLine.GetVia().Hull( clearance ); + SHAPE_LINE_CHAIN viaHull = aLine.Via().Hull( clearance, aItem->Width() ); viaHull.Intersect( hull, isect_list ); BOOST_FOREACH( SHAPE_LINE_CHAIN::INTERSECTION isect, isect_list ) { - int dist = aLine.GetCLine().Length() + - ( isect.p - aLine.GetVia().GetPos() ).EuclideanNorm(); + int dist = aLine.CLine().Length() + + ( isect.p - aLine.Via().Pos() ).EuclideanNorm(); if( dist < nearest.dist_first ) { @@ -320,11 +332,11 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin isect_list.clear(); - hull.Intersect( aLine.GetCLine(), isect_list ); + hull.Intersect( aLine.CLine(), isect_list ); BOOST_FOREACH( SHAPE_LINE_CHAIN::INTERSECTION isect, isect_list ) { - int dist = aLine.GetCLine().PathLength( isect.p ); + int dist = aLine.CLine().PathLength( isect.p ); if( dist < nearest.dist_first ) { @@ -346,9 +358,22 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin nearest.dist_last = dist_max; } - return found_isects ? nearest : OptObstacle(); + if(!found_isects) + nearest.item = obs_list[0].item; + + return nearest; } +PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEMSET& aSet, int aKindMask ) +{ + BOOST_FOREACH( const PNS_ITEM *item, aSet.CItems() ) + { + OptObstacle obs = CheckColliding(item, aKindMask); + if(obs) + return obs; + } + return OptObstacle(); +} PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKindMask ) { @@ -356,11 +381,11 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKin obs.reserve( 100 ); - if( aItemA->GetKind() == PNS_ITEM::LINE ) + if( aItemA->Kind() == PNS_ITEM::LINE ) { int n = 0; const PNS_LINE* line = static_cast(aItemA); - const SHAPE_LINE_CHAIN& l = line->GetCLine(); + const SHAPE_LINE_CHAIN& l = line->CLine(); for( int i = 0; i < l.SegmentCount(); i++ ) { @@ -373,7 +398,7 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKin if( line->EndsWithVia() ) { - n += QueryColliding( &line->GetVia(), obs, aKindMask, 1 ); + n += QueryColliding( &line->Via(), obs, aKindMask, 1 ); if( n ) return OptObstacle( obs[0] ); @@ -388,12 +413,16 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKin bool PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, const PNS_ITEM* aItemB, int aKindMask ) { - Obstacles dummy; - assert( aItemB ); - // return QueryColliding(aItemA, dummy, aKindMask, 1) > 0; + int clearance = GetClearance( aItemA, aItemB ); - return aItemA->Collide( aItemB, GetClearance( aItemA, aItemB ) ); + // fixme: refactor + if(aItemA->Kind() == PNS_ITEM::LINE) + clearance += static_cast(aItemA)->Width() / 2; + if(aItemB->Kind() == PNS_ITEM::LINE) + clearance += static_cast(aItemB)->Width() / 2; + + return aItemA->Collide( aItemB, clearance ); } @@ -412,10 +441,7 @@ struct hitVisitor int cl = 0; - if( aItem->GetKind() == PNS_ITEM::SEGMENT ) - cl += static_cast(aItem)->GetWidth() / 2; - - if( aItem->GetShape()->Collide( &cp, cl ) ) + if( aItem->Shape()->Collide( &cp, cl ) ) m_items.Add( aItem ); return true; @@ -426,6 +452,7 @@ struct hitVisitor const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) const { PNS_ITEMSET items; + // fixme: we treat a point as an infinitely small circle - this is inefficient. SHAPE_CIRCLE s( aPoint, 0 ); hitVisitor visitor( items, aPoint, this ); @@ -451,21 +478,21 @@ const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) const void PNS_NODE::addSolid( PNS_SOLID* aSolid ) { - linkJoint( aSolid->GetCenter(), aSolid->GetLayers(), aSolid->GetNet(), aSolid ); + linkJoint( aSolid->Pos(), aSolid->Layers(), aSolid->Net(), aSolid ); m_index->Add( aSolid ); } void PNS_NODE::addVia( PNS_VIA* aVia ) { - linkJoint( aVia->GetPos(), aVia->GetLayers(), aVia->GetNet(), aVia ); + linkJoint( aVia->Pos(), aVia->Layers(), aVia->Net(), aVia ); m_index->Add( aVia ); } -void PNS_NODE::addLine( PNS_LINE* aLine ) +void PNS_NODE::addLine( PNS_LINE* aLine, bool aAllowRedundant ) { - const SHAPE_LINE_CHAIN& l = aLine->GetLine(); + SHAPE_LINE_CHAIN& l = aLine->Line(); for( int i = 0; i < l.SegmentCount(); i++ ) { @@ -474,53 +501,65 @@ void PNS_NODE::addLine( PNS_LINE* aLine ) if( s.A != s.B ) { PNS_SEGMENT* pseg = new PNS_SEGMENT( *aLine, s ); + PNS_SEGMENT* psegR = NULL; - pseg->SetOwner( this ); + if ( !aAllowRedundant ) + psegR = findRedundantSegment( pseg ); - linkJoint( s.A, pseg->GetLayers(), aLine->GetNet(), pseg ); - linkJoint( s.B, pseg->GetLayers(), aLine->GetNet(), pseg ); + if(psegR) + aLine->LinkSegment(psegR); + else { + + pseg->SetOwner( this ); - aLine->LinkSegment( pseg ); + linkJoint( s.A, pseg->Layers(), aLine->Net(), pseg ); + linkJoint( s.B, pseg->Layers(), aLine->Net(), pseg ); - m_index->Add( pseg ); - } + aLine->LinkSegment( pseg ); + + m_index->Add( pseg ); + } + } } } -void PNS_NODE::addSegment( PNS_SEGMENT* aSeg ) +void PNS_NODE::addSegment( PNS_SEGMENT* aSeg, bool aAllowRedundant ) { - if( aSeg->GetSeg().A == aSeg->GetSeg().B ) + if( aSeg->Seg().A == aSeg->Seg().B ) { TRACEn( 0, "attempting to add a segment with same end coordinates, ignoring." ) return; } + if ( !aAllowRedundant && findRedundantSegment ( aSeg ) ) + return; + aSeg->SetOwner( this ); - linkJoint( aSeg->GetSeg().A, aSeg->GetLayers(), aSeg->GetNet(), aSeg ); - linkJoint( aSeg->GetSeg().B, aSeg->GetLayers(), aSeg->GetNet(), aSeg ); + linkJoint( aSeg->Seg().A, aSeg->Layers(), aSeg->Net(), aSeg ); + linkJoint( aSeg->Seg().B, aSeg->Layers(), aSeg->Net(), aSeg ); m_index->Add( aSeg ); } -void PNS_NODE::Add( PNS_ITEM* aItem ) +void PNS_NODE::Add( PNS_ITEM* aItem, bool aAllowRedundant ) { aItem->SetOwner( this ); - switch( aItem->GetKind() ) + switch( aItem->Kind() ) { case PNS_ITEM::SOLID: addSolid( static_cast( aItem ) ); break; case PNS_ITEM::SEGMENT: - addSegment( static_cast( aItem ) ); + addSegment( static_cast( aItem ), aAllowRedundant ); break; case PNS_ITEM::LINE: - addLine( static_cast (aItem) ); + addLine( static_cast (aItem), aAllowRedundant ); break; case PNS_ITEM::VIA: @@ -535,6 +574,9 @@ void PNS_NODE::Add( PNS_ITEM* aItem ) void PNS_NODE::doRemove( PNS_ITEM* aItem ) { + + // assert(m_root->m_index->Contains(aItem) || m_index->Contains(aItem)); + // case 1: removing an item that is stored in the root node from any branch: // mark it as overridden, but do not remove if( aItem->BelongsTo( m_root ) && !isRoot() ) @@ -553,8 +595,8 @@ void PNS_NODE::doRemove( PNS_ITEM* aItem ) void PNS_NODE::removeSegment( PNS_SEGMENT* aSeg ) { - unlinkJoint( aSeg->GetSeg().A, aSeg->GetLayers(), aSeg->GetNet(), aSeg ); - unlinkJoint( aSeg->GetSeg().B, aSeg->GetLayers(), aSeg->GetNet(), aSeg ); + unlinkJoint( aSeg->Seg().A, aSeg->Layers(), aSeg->Net(), aSeg ); + unlinkJoint( aSeg->Seg().B, aSeg->Layers(), aSeg->Net(), aSeg ); doRemove( aSeg ); } @@ -562,12 +604,18 @@ void PNS_NODE::removeSegment( PNS_SEGMENT* aSeg ) void PNS_NODE::removeLine( PNS_LINE* aLine ) { - std::vector* segRefs = aLine->GetLinkedSegments(); + std::vector* segRefs = aLine->LinkedSegments(); - if( !segRefs ) + if(! aLine->SegmentCount() ) return; - assert( aLine->GetOwner() ); + assert (segRefs != NULL); + assert (aLine->Owner()); + + if ( (int)segRefs->size() != aLine->SegmentCount()) + { + //printf("******weird deletion: segrefs %d segcount %d hasloops %d\n", segRefs->size(), aLine->SegmentCount(), aLine->HasLoops()); + } BOOST_FOREACH( PNS_SEGMENT* seg, *segRefs ) { @@ -575,17 +623,60 @@ void PNS_NODE::removeLine( PNS_LINE* aLine ) } aLine->SetOwner( NULL ); + aLine->ClearSegmentLinks(); } + void PNS_NODE::removeVia( PNS_VIA* aVia ) { - unlinkJoint( aVia->GetPos(), aVia->GetLayers(), aVia->GetNet(), aVia ); + // We have to split a single joint (associated with a via, binding together multiple layers) + // into multiple independent joints. As I'm a lazy bastard, I simply delete the via and all its links and re-insert them. - doRemove( aVia ); + PNS_JOINT::HashTag tag; + + VECTOR2I p ( aVia->Pos() ); + PNS_LAYERSET vLayers ( aVia->Layers() ); + int net = aVia->Net(); + + PNS_JOINT *jt = FindJoint( p, vLayers.Start(), net ); + PNS_JOINT::LinkedItems links ( jt->LinkList() ); + + tag.net = net; + tag.pos = p; + + bool split; + do + { + split = false; + std::pair range = m_joints.equal_range( tag ); + + if( range.first == m_joints.end() ) + break; + + // find and remove all joints containing the via to be removed + + for( JointMap::iterator f = range.first; f != range.second; ++f ) + { + if( aVia->LayersOverlap ( &f->second ) ) + { + m_joints.erase( f ); + split = true; + break; + } + } + } while (split); + + // and re-link them, using the former via's link list + BOOST_FOREACH(PNS_ITEM *item, links) + { + if( item != aVia ) + linkJoint ( p, item->Layers(), net, item ); + } + + doRemove( aVia ); } - void PNS_NODE::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) { Remove( aOldItem ); @@ -595,10 +686,11 @@ void PNS_NODE::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) void PNS_NODE::Remove( PNS_ITEM* aItem ) { - switch( aItem->GetKind() ) + switch( aItem->Kind() ) { case PNS_ITEM::SOLID: - assert( false ); + // fixme: this fucks up the joints, but it's only used for marking colliding obstacles for the moment, so we don't care. + doRemove ( aItem ); break; case PNS_ITEM::SEGMENT: @@ -627,13 +719,13 @@ void PNS_NODE::followLine( PNS_SEGMENT* current, bool scanDirection, int& pos, for( ; ; ) { const VECTOR2I p = - (scanDirection ^ prevReversed) ? current->GetSeg().B : current->GetSeg().A; - const OptJoint jt = FindJoint( p, current->GetLayer(), current->GetNet() ); + (scanDirection ^ prevReversed) ? current->Seg().B : current->Seg().A; + const PNS_JOINT *jt = FindJoint( p, current ); assert( jt ); assert( pos > 0 && pos < limit ); - corners[pos] = jt->GetPos(); + corners[pos] = jt->Pos(); segments[pos] = current; pos += (scanDirection ? 1 : -1); @@ -642,13 +734,14 @@ void PNS_NODE::followLine( PNS_SEGMENT* current, bool scanDirection, int& pos, break; current = jt->NextSegment( current ); + prevReversed = - ( jt->GetPos() == (scanDirection ? current->GetSeg().B : current->GetSeg().A ) ); + ( jt->Pos() == (scanDirection ? current->Seg().B : current->Seg().A ) ); } } -PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, const OptJoint& a, const OptJoint& b ) +PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex) { const int MaxVerts = 1024; @@ -658,61 +751,151 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, const OptJoint& a, const Op PNS_LINE* pl = new PNS_LINE; int i_start = MaxVerts / 2, i_end = i_start + 1; - pl->SetWidth( aSeg->GetWidth() ); - pl->SetLayers( aSeg->GetLayers() ); - pl->SetNet( aSeg->GetNet() ); + pl->SetWidth( aSeg->Width() ); + pl->SetLayers( aSeg->Layers() ); + pl->SetNet( aSeg->Net() ); pl->SetOwner( this ); - // pl->LinkSegment(aSeg); - followLine( aSeg, false, i_start, MaxVerts, corners, segs ); followLine( aSeg, true, i_end, MaxVerts, corners, segs ); + int n = 0; - int clip_start = -1, clip_end = -1; + PNS_SEGMENT *prev_seg = NULL; for( int i = i_start + 1; i < i_end; i++ ) { const VECTOR2I& p = corners[i]; - if( a && ( p == a->GetPos() || p == b->GetPos() ) ) + pl->Line().Append( p ); + + if( prev_seg != segs[i] ) { - clip_start = std::min( clip_start, i ); - clip_end = std::max( clip_end, i ); + pl->LinkSegment( segs[i] ); + + if(segs[i] == aSeg && aOriginSegmentIndex) + *aOriginSegmentIndex = n; + n++; } - pl->GetLine().Append( p ); - - if( segs[i - 1] != segs[i] ) - pl->LinkSegment( segs[i] ); + prev_seg = segs[i]; } + + assert (pl->SegmentCount() != 0); + assert (pl->SegmentCount() == (int) pl->LinkedSegments()->size()); + return pl; } void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b ) { - a = *FindJoint( aLine->GetCLine().CPoint( 0 ), aLine->GetLayers().Start(), aLine->GetNet() ); - b = *FindJoint( aLine->GetCLine().CPoint( -1 ), aLine->GetLayers().Start(), aLine->GetNet() ); + a = *FindJoint( aLine->CPoint( 0 ), aLine ); + b = *FindJoint( aLine->CPoint( -1 ), aLine ); } +void PNS_NODE::MapConnectivity ( PNS_JOINT* aStart, std::vector & aFoundJoints ) +{ + std::deque searchQueue; + std::set processed; + + searchQueue.push_back(aStart); + processed.insert ( aStart ); + + while(!searchQueue.empty()) + { + PNS_JOINT *current = searchQueue.front(); + searchQueue.pop_front(); + + BOOST_FOREACH ( PNS_ITEM *item, current->LinkList() ) + if ( item->OfKind( PNS_ITEM::SEGMENT ) ) + { + PNS_SEGMENT *seg = static_cast(item); + PNS_JOINT *a = FindJoint( seg->Seg().A, seg ); + PNS_JOINT *b = FindJoint( seg->Seg().B, seg ); + PNS_JOINT *next = (*a == *current) ? b : a; + + if( processed.find( next ) == processed.end() ) + { + processed.insert ( next ); + searchQueue.push_back( next ); + } + } + } + + BOOST_FOREACH(PNS_JOINT *jt, processed) + aFoundJoints.push_back( jt ); +} + +PNS_ITEM *PNS_NODE::NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor, int aKindMask ) +{ + std::set disconnected; + std::vector joints; + + AllItemsInNet( aStart->Net(), disconnected ); + MapConnectivity ( aStart, joints ); + + BOOST_FOREACH(PNS_JOINT *jt, joints) + { + BOOST_FOREACH (PNS_ITEM *link, jt->LinkList() ) + { + if(disconnected.find(link) != disconnected.end() ) + disconnected.erase(link); + } + } + + int best_dist = INT_MAX; + PNS_ITEM *best = NULL; + + BOOST_FOREACH (PNS_ITEM *item, disconnected ) + { + if( item->OfKind ( aKindMask ) ) + { + for(int i = 0; i < item->AnchorCount(); i++) + { + VECTOR2I p = item->Anchor ( i ); + int d = (p - aStart->Pos()).EuclideanNorm(); + + if(d < best_dist) + { + best_dist = d; + best = item; + if(aAnchor) + *aAnchor = i; + } + } + } + } + + return best; +} int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, std::vector& aLines ) { - BOOST_FOREACH( PNS_ITEM* item, a.GetLinkList() ) + BOOST_FOREACH( PNS_ITEM* item, a.LinkList() ) { - if( item->GetKind() == PNS_ITEM::SEGMENT ) + if( item->Kind() == PNS_ITEM::SEGMENT ) { PNS_SEGMENT* seg = static_cast(item); PNS_LINE* line = AssembleLine( seg ); PNS_JOINT j_start, j_end; + FindLineEnds( line, j_start, j_end ); - if( (j_start == a && j_end == b )|| (j_end == a && j_start == b) ) + + int id_start = line->CLine().Find (a.Pos()); + int id_end = line->CLine().Find (b.Pos()); + + if(id_end < id_start) + std::swap(id_end, id_start); + + if(id_start >= 0 && id_end >= 0) + { + line->ClipVertexRange ( id_start, id_end ); aLines.push_back( line ); - else + } else delete line; } } @@ -721,7 +904,7 @@ int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, std::vectorsecond.GetLayers().Overlaps( aLayer ) ) - return f->second; + if( f->second.Layers().Overlaps( aLayer ) ) + return &f->second; ++f; } - return OptJoint(); + return NULL; } @@ -787,7 +970,7 @@ PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLaye for( f = range.first; f != range.second; ++f ) { - if( aLayers.Overlaps( f->second.GetLayers() ) ) + if( aLayers.Overlaps( f->second.Layers() ) ) { jt.Merge( f->second ); m_joints.erase( f ); @@ -949,7 +1132,11 @@ void PNS_NODE::Commit( PNS_NODE* aNode ) for( PNS_INDEX::ItemSet::iterator i = aNode->m_index->begin(); i != aNode->m_index->end(); ++i ) + { + (*i)->SetRank ( -1 ); + (*i)->Unmark (); Add( *i ); + } releaseChildren(); } @@ -957,29 +1144,81 @@ void PNS_NODE::Commit( PNS_NODE* aNode ) void PNS_NODE::KillChildren() { - assert( isRoot() ); - + assert ( isRoot() ); releaseChildren(); } -void PNS_NODE::AllItemsInNet( int aNet, std::list& aItems ) +void PNS_NODE::AllItemsInNet( int aNet, std::set& aItems ) { PNS_INDEX::NetItemsList* l_cur = m_index->GetItemsForNet( aNet ); - if( !l_cur ) - return; - - std::copy( aItems.begin(), l_cur->begin(), l_cur->end() ); + if(l_cur) + { + BOOST_FOREACH (PNS_ITEM *item, *l_cur ) + aItems.insert ( item ); + } + if( !isRoot() ) { PNS_INDEX::NetItemsList* l_root = m_root->m_index->GetItemsForNet( aNet ); - for( PNS_INDEX::NetItemsList::iterator i = l_root->begin(); i!= l_root->end(); ++i ) - if( !overrides( *i ) ) - aItems.push_back( *i ); - - + if(l_root) + for( PNS_INDEX::NetItemsList::iterator i = l_root->begin(); i!= l_root->end(); ++i ) + if( !overrides( *i ) ) + aItems.insert( *i ); } } + +void PNS_NODE::ClearRanks() +{ + for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i ) + { + (*i)->SetRank(-1); + (*i)->Mark(0); + } +} + +int PNS_NODE::FindByMarker ( int aMarker, PNS_ITEMSET& aItems ) +{ + for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i ) + if ( (*i)->Marker() & aMarker ) aItems.Add(*i); + return 0; +} + +int PNS_NODE::RemoveByMarker ( int aMarker ) +{ + for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i ) + if ( (*i)->Marker() & aMarker ) + { + Remove (*i); + } + return 0; +} + +PNS_SEGMENT* PNS_NODE::findRedundantSegment ( PNS_SEGMENT *aSeg ) +{ + PNS_JOINT *jtStart = FindJoint ( aSeg->Seg().A, aSeg ); + + if(!jtStart) + return NULL; + + BOOST_FOREACH( PNS_ITEM *item, jtStart->LinkList() ) + if(item->OfKind(PNS_ITEM::SEGMENT)) + { + PNS_SEGMENT *seg2 = (PNS_SEGMENT *) item; + + const VECTOR2I a1 ( aSeg->Seg().A ); + const VECTOR2I b1 ( aSeg->Seg().B ); + + const VECTOR2I a2 ( seg2->Seg().A ); + const VECTOR2I b2 ( seg2->Seg().B ); + + if( seg2->Layers().Start() == aSeg->Layers().Start() && + ((a1 == a2 && b1 == b2) || (a1 == b2 && a2 == b1))) + return seg2; + } + + return NULL; +} diff --git a/pcbnew/router/pns_node.h b/pcbnew/router/pns_node.h index de3e886dc2..4242f8d614 100644 --- a/pcbnew/router/pns_node.h +++ b/pcbnew/router/pns_node.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,8 +15,9 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ + #ifndef __PNS_NODE_H #define __PNS_NODE_H @@ -26,7 +27,6 @@ #include #include #include -#include #include #include @@ -43,8 +43,12 @@ class PNS_VIA; class PNS_RATSNEST; class PNS_INDEX; -using boost::shared_ptr; +/** + * Class PNS_CLEARANCE_FUNC + * + * An abstract function object, returning a required clearance between two items. + **/ class PNS_CLEARANCE_FUNC { public: @@ -84,7 +88,7 @@ struct PNS_OBSTACLE * hierarchical and indexed way. * Features: * - spatial-indexed container for PCB item shapes - * - collision search (with clearance checking) + * - collision search & clearance checking * - assembly of lines connecting joints, finding loops and unique paths * - lightweight cloning/branching (for recursive optimization and shove * springback) @@ -96,101 +100,236 @@ public: typedef boost::optional OptObstacle; typedef std::vector ItemVector; typedef std::vector Obstacles; - typedef boost::optional OptJoint; - - PNS_NODE(); - ~PNS_NODE(); + + PNS_NODE (); + ~PNS_NODE (); ///> Returns the expected clearance between items a and b. - int GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const; + int GetClearance ( const PNS_ITEM* a, const PNS_ITEM* b ) const; ///> Returns the pre-set worst case clearance between any pair of items - int GetMaxClearance() const + int GetMaxClearance () const { return m_maxClearance; } - void SetMaxClearance( int aClearance ) + ///> Sets the worst-case clerance between any pair of items + void SetMaxClearance ( int aClearance ) { m_maxClearance = aClearance; } - void SetClearanceFunctor( PNS_CLEARANCE_FUNC* aFunc ) + ///> Assigns a clerance resolution function object + void SetClearanceFunctor ( PNS_CLEARANCE_FUNC* aFunc ) { m_clearanceFunctor = aFunc; } - ///> Finds items that collide with aItem and stores collision information - ///> in aObstacles. - int QueryColliding( const PNS_ITEM* aItem, - Obstacles& aObstacles, - int aKindMask = PNS_ITEM::ANY, - int aLimitCount = -1 ); - - ///> Finds the nearest item that collides with aItem. - OptObstacle NearestObstacle( const PNS_LINE* aItem, int aKindMask = PNS_ITEM::ANY ); - - ///> Checks if the item collides with anything else in the world, - ///> and returns it if so. - OptObstacle CheckColliding( const PNS_ITEM* aItem, int aKindMask = PNS_ITEM::ANY ); - - ///> Checks if two items collide [deprecated]. - bool CheckColliding( const PNS_ITEM* aItemA, - const PNS_ITEM* aItemB, - int aKindMask = PNS_ITEM::ANY ); - - ///> Hit detection - const PNS_ITEMSET HitTest( const VECTOR2I& aPoint ) const; - - void Add( PNS_ITEM* aItem ); - void Remove( PNS_ITEM* aItem ); - void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ); - - ///> Creates a lightweight copy ("branch") of self. Note that if there are - ///> any branches in use, their parents must NOT be deleted. - PNS_NODE* Branch(); - - ///> Assembles a line connecting two non-trivial joints the - ///> segment aSeg belongs to. - PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg, - const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint() ); - - ///> Dumps the contents and joints structure - void Dump( bool aLong = false ); - ///> Returns the number of joints int JointCount() const { return m_joints.size(); } - ///> Returns the lists of items removed and added in this branch, with - ///> respect to the root. + ///> Returns the number of nodes in the inheritance chain (wrs to the root node) + int Depth() const + { + return m_depth; + } + + /** + * Function QueryColliding() + * + * Finds items collliding (closer than clearance) with the item aItem. + * @param aItem item to check collisions against + * @param aObstacles set of colliding objects found + * @param aKindMask mask of obstacle types to take into account + * @param aLimitCount stop looking for collisions after finding this number of colliding items + * @return number of obstacles found + */ + int QueryColliding ( const PNS_ITEM* aItem, + Obstacles& aObstacles, + int aKindMask = PNS_ITEM::ANY, + int aLimitCount = -1 ); + + + /** + * Function NearestObstacle() + * + * Follows the line in search of an obstacle that is nearest to the starting to the line's starting + * point. + * @param aItem the item to find collisions with + * @param aKindMask mask of obstacle types to take into account + * @return the obstacle, if found, otherwise empty. + */ + OptObstacle NearestObstacle ( const PNS_LINE* aItem, + int aKindMask = PNS_ITEM::ANY ); + + /** + * Function CheckColliding() + * + * Checks if the item collides with anything else in the world, + * and if found, returns the obstacle. + * @param aItem the item to find collisions with + * @param aKindMask mask of obstacle types to take into account + * @return the obstacle, if found, otherwise empty. + */ + OptObstacle CheckColliding ( const PNS_ITEM* aItem, + int aKindMask = PNS_ITEM::ANY ); + + + /** + * Function CheckColliding() + * + * Checks if any item in the set collides with anything else in the world, + * and if found, returns the obstacle. + * @param aSet set of items to find collisions with + * @param aKindMask mask of obstacle types to take into account + * @return the obstacle, if found, otherwise empty. + */ + OptObstacle CheckColliding ( const PNS_ITEMSET& aSet, + int aKindMask = PNS_ITEM::ANY ); + + + /** + * Function CheckColliding() + * + * Checks if any item in the set collides with anything else in the world, + * and if found, returns the obstacle. + * @param aSet set of items to find collisions with + * @param aKindMask mask of obstacle types to take into account + * @return the obstacle, if found, otherwise empty. + */ + bool CheckColliding ( const PNS_ITEM* aItemA, + const PNS_ITEM* aItemB, + int aKindMask = PNS_ITEM::ANY ); + + /** + * Function HitTest() + * + * Finds all items that contain the point aPoint. + * @param aPoint the point + * @return the items + */ + const PNS_ITEMSET HitTest ( const VECTOR2I& aPoint ) const; + + /** + * Function Add() + * + * Adds an item to the current node. + * @param aItem item to add + * @param aAllowRedundant if true, duplicate items are allowed (e.g. a segment or via + * at the same coordinates as an existing one) + */ + void Add ( PNS_ITEM* aItem, bool aAllowRedundant = false ); + + /** + * Function Remove() + * + * Just as the name says, removes an item from this branch. + * @param aItem item to remove + */ + void Remove ( PNS_ITEM* aItem ); + + /** + * Function Replace() + * + * Just as the name says, replaces an item with another one. + * @param aOldItem item to be removed + * @param aNewItem item add instead + */ + void Replace ( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ); + + /** + * Function Branch() + * + * Creates a lightweight copy (called branch) of self that tracks + * the changes (added/removed items) wrs to the root. Note that if there are + * any branches in use, their parents must NOT be deleted. + * @return the new branch + */ + PNS_NODE* Branch ( ); + + /** + * Function AssembleLine() + * + * Follows the joint map to assemble a line connecting two non-trivial + * joints starting from segment aSeg. + * @param aSeg the initial segment + * @param aOriginSegmentIndex index of aSeg in the resulting line + * @return the line + */ + + PNS_LINE* AssembleLine ( PNS_SEGMENT* aSeg, + int *aOriginSegmentIndex = NULL ); + + ///> Prints the contents and joints structure + void Dump ( bool aLong = false ); + + + + /** + * Function GetUpdatedItems() + * + * Returns the lists of items removed and added in this branch, with + * respect to the root branch. + * @param aRemoved removed items + * @param aAdded added items + */ void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded ); - ///> Copies the changes from a given branch (aNode) to the root. Called on - ///> a non-root branch will fail. + + /** + * Function Commit() + * + * Applies the changes from a given branch (aNode) to the root branch. Called on + * a non-root branch will fail. Calling commit also kills all children nodes of the root branch. + * @param aNode node to commit changes from + */ void Commit( PNS_NODE* aNode ); - ///> finds a joint at a given position, layer and nets - const OptJoint FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ); + /** + * Function FindJoint() + * + * Searches for a joint at a given position, layer and belonging to given net. + * @return the joint, if found, otherwise empty + */ + PNS_JOINT* FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ); - ///> finds all linest between a pair of joints. Used by the loop removal engine. - int FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, - std::vector& aLines ); + /** + * Function FindJoint() + * + * Searches for a joint at a given position, linked to given item. + * @return the joint, if found, otherwise empty + */ + PNS_JOINT* FindJoint( const VECTOR2I& aPos, PNS_ITEM *aItem ) + { + return FindJoint( aPos, aItem->Layers().Start(), aItem->Net() ); + } + + void MapConnectivity ( PNS_JOINT* aStart, std::vector & aFoundJoints ); + + PNS_ITEM *NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor = NULL, int aKindMask = PNS_ITEM::ANY); + + + ///> finds all lines between a pair of joints. Used by the loop removal procedure. + int FindLinesBetweenJoints( PNS_JOINT& a, + PNS_JOINT& b, + std::vector& aLines ); ///> finds the joints corresponding to the ends of line aLine void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b ); - - ///> finds all joints that have an (in)direct connection(s) - ///> (i.e. segments/vias) with the joint aJoint. - void FindConnectedJoints( const PNS_JOINT& aJoint, - std::vector& aConnectedJoints ); - + ///> Destroys all child nodes. Applicable only to the root node. void KillChildren(); - void AllItemsInNet( int aNet, std::list& aItems ); + void AllItemsInNet( int aNet, std::set& aItems ); + + void ClearRanks(); + + + int FindByMarker ( int aMarker, PNS_ITEMSET& aItems ); + int RemoveByMarker ( int aMarker ); private: struct obstacleVisitor; @@ -198,12 +337,13 @@ private: typedef JointMap::value_type TagJointPair; /// nodes are not copyable - PNS_NODE( const PNS_NODE& b ); - PNS_NODE& operator=( const PNS_NODE& b ); + PNS_NODE ( const PNS_NODE& b ); + PNS_NODE& operator= ( const PNS_NODE& b ); ///> tries to find matching joint and creates a new one if not found - PNS_JOINT& touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, - int aNet ); + PNS_JOINT& touchJoint( const VECTOR2I& aPos, + const PNS_LAYERSET& aLayers, + int aNet ); ///> touches a joint and links it to an item void linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, @@ -215,8 +355,8 @@ private: ///> helpers for adding/removing items void addSolid( PNS_SOLID* aSeg ); - void addSegment( PNS_SEGMENT* aSeg ); - void addLine( PNS_LINE* aLine ); + void addSegment( PNS_SEGMENT* aSeg, bool aAllowRedundant ); + void addLine( PNS_LINE* aLine, bool aAllowRedundant ); void addVia( PNS_VIA* aVia ); void removeSolid( PNS_SOLID* aSeg ); void removeLine( PNS_LINE* aLine ); @@ -239,16 +379,15 @@ private: return m_override.find( aItem ) != m_override.end(); } - ///> scans the joint map, forming a line starting from segment (current). - void followLine( PNS_SEGMENT* current, - bool scanDirection, - int& pos, - int limit, - VECTOR2I* corners, - PNS_SEGMENT** segments ); + PNS_SEGMENT *findRedundantSegment ( PNS_SEGMENT *aSeg ); - ///> spatial index of all items - // SHAPE_INDEX_LIST m_items; + ///> scans the joint map, forming a line starting from segment (current). + void followLine ( PNS_SEGMENT* current, + bool scanDirection, + int& pos, + int limit, + VECTOR2I* corners, + PNS_SEGMENT** segments ); ///> hash table with the joints, linking the items. Joints are hashed by ///> their position, layer set and net. @@ -263,7 +402,7 @@ private: ///> list of nodes branched from this one std::vector m_children; - ///> hash of root's items that are more recent in this node + ///> hash of root's items that have been changed in this node boost::unordered_set m_override; ///> worst case item-item clearance @@ -275,8 +414,8 @@ private: ///> Geometric/Net index of the items PNS_INDEX* m_index; - ///> list of currently processed obstacles. - Obstacles m_obstacleList; + ///> depth of the node (number of parent nodes in the inheritance chain) + int m_depth; }; #endif diff --git a/pcbnew/router/pns_optimizer.cpp b/pcbnew/router/pns_optimizer.cpp index 48e84207e5..e6aab0e9a1 100644 --- a/pcbnew/router/pns_optimizer.cpp +++ b/pcbnew/router/pns_optimizer.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include @@ -27,12 +27,13 @@ #include "pns_node.h" #include "pns_optimizer.h" #include "pns_utils.h" +#include "pns_router.h" /** * * Cost Estimator Methods * - **/ + */ int PNS_COST_ESTIMATOR::CornerCost( const SEG& a, const SEG& b ) { @@ -74,29 +75,29 @@ int PNS_COST_ESTIMATOR::CornerCost( const SHAPE_LINE_CHAIN& aLine ) int PNS_COST_ESTIMATOR::CornerCost( const PNS_LINE& aLine ) { - return CornerCost( aLine.GetCLine() ); + return CornerCost( aLine.CLine() ); } void PNS_COST_ESTIMATOR::Add( PNS_LINE& aLine ) { - m_lengthCost += aLine.GetCLine().Length(); + m_lengthCost += aLine.CLine().Length(); m_cornerCost += CornerCost( aLine ); } void PNS_COST_ESTIMATOR::Remove( PNS_LINE& aLine ) { - m_lengthCost -= aLine.GetCLine().Length(); + m_lengthCost -= aLine.CLine().Length(); m_cornerCost -= CornerCost( aLine ); } void PNS_COST_ESTIMATOR::Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine ) { - m_lengthCost -= aOldLine.GetCLine().Length(); + m_lengthCost -= aOldLine.CLine().Length(); m_cornerCost -= CornerCost( aOldLine ); - m_lengthCost += aNewLine.GetCLine().Length(); + m_lengthCost += aNewLine.CLine().Length(); m_cornerCost += CornerCost( aNewLine ); } @@ -145,7 +146,7 @@ struct PNS_OPTIMIZER::CacheVisitor bool operator()( PNS_ITEM* aOtherItem ) { - if( !m_mask & aOtherItem->GetKind() ) + if( !m_mask & aOtherItem->Kind() ) return true; int clearance = m_node->GetClearance( aOtherItem, m_ourItem ); @@ -177,13 +178,13 @@ void PNS_OPTIMIZER::cacheAdd( PNS_ITEM* aItem, bool aIsStatic = false ) void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int aEndVertex ) { - std::vector* segs = aLine->GetLinkedSegments(); + PNS_LINE::SegmentRefs* segs = aLine->LinkedSegments(); if( !segs ) return; if( aEndVertex < 0 ) - aEndVertex += aLine->GetCLine().PointCount(); + aEndVertex += aLine->PointCount(); for( int i = aStartVertex; i < aEndVertex - 1; i++ ) { @@ -196,7 +197,7 @@ void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int void PNS_OPTIMIZER::CacheRemove( PNS_ITEM* aItem ) { - if( aItem->GetKind() == PNS_ITEM::LINE ) + if( aItem->Kind() == PNS_ITEM::LINE ) removeCachedSegments( static_cast (aItem) ); } @@ -234,7 +235,7 @@ bool PNS_OPTIMIZER::checkColliding( PNS_ITEM* aItem, bool aUpdateCache ) return m_world->CheckColliding( aItem ); // something is wrong with the cache, need to investigate. - m_cache.Query( aItem->GetShape(), m_world->GetMaxClearance(), v, false ); + m_cache.Query( aItem->Shape(), m_world->GetMaxClearance(), v, false ); if( !v.m_collidingItem ) { @@ -268,7 +269,7 @@ bool PNS_OPTIMIZER::checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOp bool PNS_OPTIMIZER::mergeObtuse( PNS_LINE* aLine ) { - SHAPE_LINE_CHAIN& line = aLine->GetLine(); + SHAPE_LINE_CHAIN& line = aLine->Line(); int step = line.PointCount() - 3; int iter = 0; @@ -360,7 +361,7 @@ bool PNS_OPTIMIZER::mergeObtuse( PNS_LINE* aLine ) bool PNS_OPTIMIZER::mergeFull( PNS_LINE* aLine ) { - SHAPE_LINE_CHAIN& line = aLine->GetLine(); + SHAPE_LINE_CHAIN& line = aLine->Line(); int step = line.SegmentCount() - 1; int segs_pre = line.SegmentCount(); @@ -395,7 +396,7 @@ bool PNS_OPTIMIZER::mergeFull( PNS_LINE* aLine ) } -bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, PNS_LINE* aResult, int aStartVertex, int aEndVertex ) +bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, PNS_LINE* aResult )//, int aStartVertex, int aEndVertex ) { if( !aResult ) aResult = aLine; @@ -415,6 +416,9 @@ bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, PNS_LINE* aResult, int aStartVert if( m_effortLevel & SMART_PADS ) rv |= runSmartPads( aResult ); + if( m_effortLevel & FANOUT_CLEANUP ) + rv |= fanoutCleanup( aResult ); + return rv; } @@ -427,11 +431,11 @@ bool PNS_OPTIMIZER::mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath, int cost_orig = PNS_COST_ESTIMATOR::CornerCost( aCurrentPath ); - if( aLine->GetCLine().SegmentCount() < 4 ) + if( aLine->SegmentCount() < 4 ) return false; - DIRECTION_45 orig_start( aLine->GetCLine().CSegment( 0 ) ); - DIRECTION_45 orig_end( aLine->GetCLine().CSegment( -1 ) ); + DIRECTION_45 orig_start( aLine->CSegment( 0 ) ); + DIRECTION_45 orig_end( aLine->CSegment( -1 ) ); while( n < n_segs - step ) { @@ -559,23 +563,30 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth, const PNS_ITEM* aItem, bool aPermitDiagonal ) const { - switch( aItem->GetKind() ) + switch( aItem->Kind() ) { case PNS_ITEM::VIA: { const PNS_VIA* via = static_cast( aItem ); - return circleBreakouts( aWidth, via->GetShape(), aPermitDiagonal ); + return circleBreakouts( aWidth, via->Shape(), aPermitDiagonal ); } case PNS_ITEM::SOLID: { - const SHAPE* shape = aItem->GetShape(); + const SHAPE* shape = aItem->Shape(); switch( shape->Type() ) { case SH_RECT: return rectBreakouts( aWidth, shape, aPermitDiagonal ); + case SH_SEGMENT: + { + const SHAPE_SEGMENT *seg = static_cast (shape); + const SHAPE_RECT rect = ApproximateSegmentAsRect ( *seg ); + return rectBreakouts( aWidth, &rect, aPermitDiagonal ); + } + case SH_CIRCLE: return circleBreakouts( aWidth, shape, aPermitDiagonal ); @@ -594,14 +605,14 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth, PNS_ITEM* PNS_OPTIMIZER::findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const { - PNS_NODE::OptJoint jt = m_world->FindJoint( aP, aLayer, aNet ); + PNS_JOINT *jt = m_world->FindJoint( aP, aLayer, aNet ); if( !jt ) return NULL; - BOOST_FOREACH( PNS_ITEM* item, jt->GetLinkList() ) + BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() ) { - if( item->GetKind() == PNS_ITEM::VIA || item->GetKind() == PNS_ITEM::SOLID ) + if( item->OfKind (PNS_ITEM::VIA | PNS_ITEM::SOLID ) ) return item; } @@ -621,19 +632,16 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, typedef std::pair RtVariant; std::vector variants; - BreakoutList breakouts = computeBreakouts( aLine->GetWidth(), aPad, true ); + BreakoutList breakouts = computeBreakouts( aLine->Width(), aPad, true ); - SHAPE_LINE_CHAIN line = ( aEnd ? aLine->GetCLine().Reverse() : aLine->GetCLine() ); + SHAPE_LINE_CHAIN line = ( aEnd ? aLine->CLine().Reverse() : aLine->CLine() ); - // bool startDiagonal = DIRECTION_45( line.CSegment(0) ).IsDiagonal(); int p_end = std::min( aEndVertex, std::min( 3, line.PointCount() - 1 ) ); for( int p = 1; p <= p_end; p++ ) { BOOST_FOREACH( SHAPE_LINE_CHAIN & l, breakouts ) { - // PNSDisplayDebugLine (l, 0); - for( int diag = 0; diag < 2; diag++ ) { @@ -642,11 +650,12 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, line.CPoint( p ), diag == 0 ); DIRECTION_45 dir_bkout( l.CSegment( -1 ) ); - // DIRECTION_45 dir_head ( line.CSegment(p + 1)); + if(!connect.SegmentCount()) + continue; + int ang1 = dir_bkout.Angle( DIRECTION_45( connect.CSegment( 0 ) ) ); int ang2 = 0; - // int ang2 = dir_head.Angle ( DIRECTION_45(connect.CSegment(-1) )); if( (ang1 | ang2) & ForbiddenAngles ) continue; @@ -662,7 +671,6 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, v.Append( line.CPoint( i ) ); PNS_LINE tmp( *aLine, v ); - // tmp.GetLine().Simplify(); int cc = tmp.CountCorners( ForbiddenAngles ); if( cc == 0 ) @@ -689,18 +697,12 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, if( !checkColliding( &tmp ) ) { -/* if(aEnd) - * PNSDisplayDebugLine (l_best, 6); - * else - * PNSDisplayDebugLine (l_best, 5);*/ - if( cost < min_cost || ( cost == min_cost && len < min_len ) ) { l_best = vp.second; p_best = vp.first; found = true; - // if(cost == min_cost) if( cost == min_cost ) min_len = std::min( len, min_len ); @@ -711,12 +713,6 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, if( found ) { -// printf("end: %d, p-best: %d, p-end: %d, p-total: %d\n", aEnd, p_best, p_end, l_best.PointCount()); - -// if(!aEnd) -// PNSDisplayDebugLine (l_best, 5); -// else - aLine->SetShape( l_best ); return p_best; } @@ -724,18 +720,17 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, return -1; } - bool PNS_OPTIMIZER::runSmartPads( PNS_LINE* aLine ) { - SHAPE_LINE_CHAIN& line = aLine->GetLine(); - + SHAPE_LINE_CHAIN& line = aLine->Line(); + if( line.PointCount() < 3 ) return false; VECTOR2I p_start = line.CPoint( 0 ), p_end = line.CPoint( -1 ); - PNS_ITEM* startPad = findPadOrVia( aLine->GetLayer(), aLine->GetNet(), p_start ); - PNS_ITEM* endPad = findPadOrVia( aLine->GetLayer(), aLine->GetNet(), p_end ); + PNS_ITEM* startPad = findPadOrVia( aLine->Layer(), aLine->Net(), p_start ); + PNS_ITEM* endPad = findPadOrVia( aLine->Layer(), aLine->Net(), p_end ); int vtx = -1; @@ -746,16 +741,68 @@ bool PNS_OPTIMIZER::runSmartPads( PNS_LINE* aLine ) smartPadsSingle( aLine, endPad, true, vtx < 0 ? line.PointCount() - 1 : line.PointCount() - 1 - vtx ); - aLine->GetLine().Simplify(); + aLine->Line().Simplify(); return true; } bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld ) { - PNS_OPTIMIZER opt( aWorld ? aWorld : aLine->GetWorld() ); + PNS_OPTIMIZER opt( aWorld ); opt.SetEffortLevel( aEffortLevel ); opt.SetCollisionMask( -1 ); return opt.Optimize( aLine ); } + + +bool PNS_OPTIMIZER::fanoutCleanup( PNS_LINE * aLine ) +{ + if( aLine->PointCount() < 3 ) + return false; + + VECTOR2I p_start = aLine->CPoint( 0 ), p_end = aLine->CPoint( -1 ); + + PNS_ITEM* startPad = findPadOrVia( aLine->Layer(), aLine->Net(), p_start ); + PNS_ITEM* endPad = findPadOrVia( aLine->Layer(), aLine->Net(), p_end ); + + int thr = aLine->Width() * 10; + int len = aLine->CLine().Length(); + + + if(!startPad) + return false; + + + bool startMatch = startPad->OfKind(PNS_ITEM::VIA | PNS_ITEM::SOLID); + bool endMatch = false; + + if(endPad) + { + endMatch = endPad->OfKind(PNS_ITEM::VIA | PNS_ITEM::SOLID); + } else { + endMatch = aLine->EndsWithVia(); + } + + + if(startMatch && endMatch && len < thr) + { + + for(int i = 0; i < 2; i++ ) + { + SHAPE_LINE_CHAIN l2 = DIRECTION_45().BuildInitialTrace(p_start, p_end, i); + PNS_ROUTER::GetInstance()->DisplayDebugLine (l2, 4, 10000); + PNS_LINE repl; + repl = PNS_LINE (*aLine, l2 ); + + + + if (!m_world->CheckColliding(&repl)) + { + aLine->SetShape(repl.CLine()); + return true; + } + } + } + return false; +} diff --git a/pcbnew/router/pns_optimizer.h b/pcbnew/router/pns_optimizer.h index 916e77bb69..3e1d9b211c 100644 --- a/pcbnew/router/pns_optimizer.h +++ b/pcbnew/router/pns_optimizer.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_OPTIMIZER_H @@ -27,6 +27,8 @@ #include #include +#include "range.h" + class PNS_NODE; class PNS_LINE; class PNS_ROUTER; @@ -90,17 +92,17 @@ public: { MERGE_SEGMENTS = 0x01, SMART_PADS = 0x02, - MERGE_OBTUSE = 0x04 + MERGE_OBTUSE = 0x04, + FANOUT_CLEANUP = 0x08 }; PNS_OPTIMIZER( PNS_NODE* aWorld ); ~PNS_OPTIMIZER(); ///> a quick shortcut to optmize a line without creating and setting up an optimizer - static bool Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld = NULL ); + static bool Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld); - bool Optimize( PNS_LINE* aLine, PNS_LINE* aResult = NULL, - int aStartVertex = 0, int aEndVertex = -1 ); + bool Optimize( PNS_LINE* aLine, PNS_LINE* aResult = NULL ); void SetWorld( PNS_NODE* aNode ) { m_world = aNode; } void CacheStaticItem( PNS_ITEM* aItem ); @@ -135,6 +137,7 @@ private: bool removeUglyCorners( PNS_LINE* aLine ); bool runSmartPads( PNS_LINE* aLine ); bool mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step ); + bool fanoutCleanup( PNS_LINE * aLine ); bool checkColliding( PNS_ITEM* aItem, bool aUpdateCache = true ); bool checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath ); diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 104aeaa05e..a08b0f0fc7 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include @@ -42,11 +42,13 @@ #include "pns_solid.h" #include "pns_utils.h" #include "pns_router.h" +#include "pns_shove.h" +#include "pns_dragger.h" #include #include -#include +#include #include #include #include @@ -80,13 +82,29 @@ public: m_defaultClearance = 254000; // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance(); } + int localPadClearance( const PNS_ITEM * item ) const + { + if(!item->Parent() || item->Parent()->Type() != PCB_PAD_T ) + return 0; + + const D_PAD *pad = static_cast( item->Parent() ); + + return pad->GetLocalClearance(); + } + int operator()( const PNS_ITEM* a, const PNS_ITEM* b ) { - int net_a = a->GetNet(); + int net_a = a->Net(); int cl_a = (net_a >= 0 ? m_clearanceCache[net_a] : m_defaultClearance); - int net_b = b->GetNet(); + int net_b = b->Net(); int cl_b = (net_b >= 0 ? m_clearanceCache[net_b] : m_defaultClearance); + int pad_a = localPadClearance( a ); + int pad_b = localPadClearance( b ); + + cl_a = std::max(cl_a, pad_a); + cl_b = std::max(cl_b, pad_b); + return std::max( cl_a, cl_b ); } @@ -97,11 +115,12 @@ private: PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) { - PNS_LAYERSET layers( 0, 15 ); + PNS_LAYERSET layers ( 0, 15 ); switch( aPad->GetAttribute() ) { case PAD_STANDARD: + layers = PNS_LAYERSET( 0, 15 ); break; case PAD_SMD: @@ -130,49 +149,64 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) solid->SetLayers( layers ); solid->SetNet( aPad->GetNetCode() ); + solid->SetParent( aPad ); + wxPoint wx_c = aPad->GetPosition(); wxSize wx_sz = aPad->GetSize(); VECTOR2I c( wx_c.x, wx_c.y ); VECTOR2I sz( wx_sz.x, wx_sz.y ); - solid->SetCenter( c ); + solid->SetPos( c ); double orient = aPad->GetOrientation() / 10.0; + bool nonOrtho = false; + if( orient == 90.0 || orient == 270.0 ) sz = VECTOR2I( sz.y, sz.x ); else if( orient != 0.0 && orient != 180.0 ) { - TRACEn( 0, "non-orthogonal pad rotations not supported yet" ); - delete solid; - return NULL; + // rotated pads are replaced by for the moment by circles due to my laziness ;) + solid->SetShape ( new SHAPE_CIRCLE (c, std::min(sz.x, sz.y) / 2 ) ); + nonOrtho = true; } - switch( aPad->GetShape() ) + if(!nonOrtho) { - case PAD_CIRCLE: - solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); - break; - - case PAD_OVAL: - if( sz.x == sz.y ) + switch( aPad->GetShape() ) + { + case PAD_CIRCLE: solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); - else + break; + + case PAD_OVAL: + if( sz.x == sz.y ) + solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); + else { + VECTOR2I delta; + + if (sz.x > sz.y) + delta = VECTOR2I((sz.x - sz.y) / 2, 0); + else + delta = VECTOR2I(0, (sz.y - sz.x) / 2); + + SHAPE_SEGMENT *shape = new SHAPE_SEGMENT( c - delta, c + delta, std::min(sz.x, sz.y) ); + solid->SetShape( shape ); + } + break; + + case PAD_RECT: solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) ); - break; + break; - case PAD_RECT: - solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) ); - break; - - default: - TRACEn( 0, "unsupported pad shape" ); - delete solid; - return NULL; + default: + TRACEn( 0, "unsupported pad shape" ); + delete solid; + return NULL; + } } - solid->SetParent( aPad ); return solid; } @@ -197,7 +231,9 @@ PNS_ITEM* PNS_ROUTER::syncVia( VIA* aVia ) aVia->GetWidth(), aVia->GetNetCode() ); + v->SetDrill ( aVia->GetDrill() ); v->SetParent( aVia ); + return v; } @@ -233,7 +269,6 @@ int PNS_ROUTER::NextCopperLayer( bool aUp ) void PNS_ROUTER::SyncWorld() { - std::vector pads; if( !m_board ) { @@ -243,11 +278,12 @@ void PNS_ROUTER::SyncWorld() ClearWorld(); + int worstClearance = m_board->GetDesignSettings().GetBiggestClearanceValue(); + m_clearanceFunc = new PCBNEW_CLEARANCE_FUNC( m_board ); m_world = new PNS_NODE(); m_world->SetClearanceFunctor( m_clearanceFunc ); - m_world->SetMaxClearance( 1000000 ); // m_board->GetBiggestClearanceValue()); - pads = m_board->GetPads(); + m_world->SetMaxClearance( 4 * worstClearance ); for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) { @@ -273,8 +309,6 @@ void PNS_ROUTER::SyncWorld() if( item ) m_world->Add( item ); } - - m_placer = new PNS_LINE_PLACER( m_world ); } @@ -291,10 +325,8 @@ PNS_ROUTER::PNS_ROUTER() m_world = NULL; m_placer = NULL; m_previewItems = NULL; - m_start_diagonal = false; m_board = NULL; - - TRACE( 1, "m_board = %p\n", m_board ); + m_dragger = NULL; } @@ -351,11 +383,11 @@ void PNS_ROUTER::ClearWorld() } -void PNS_ROUTER::SetCurrentWidth( int w ) +/*void PNS_ROUTER::SetCurrentWidth( int w ) { // fixme: change width while routing m_currentWidth = w; -} +}*/ bool PNS_ROUTER::RoutingInProgress() const @@ -369,7 +401,11 @@ const PNS_ITEMSET PNS_ROUTER::QueryHoverItems( const VECTOR2I& aP ) if( m_state == IDLE ) return m_world->HitTest( aP ); else - return m_placer->GetCurrentNode()->HitTest( aP ); + { + //assert ( m_placer->GetCurrentNode()->checkExists() ); + //TRACE(0,"query-hover [%p]", m_placer->GetCurrentNode()); + return m_placer->CurrentNode()->HitTest( aP ); + } } @@ -383,23 +419,23 @@ const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplit return aP; } - switch( item->GetKind() ) + switch( item->Kind() ) { case PNS_ITEM::SOLID: - anchor = static_cast(item)->GetCenter(); + anchor = static_cast(item)->Pos(); aSplitsSegment = false; break; case PNS_ITEM::VIA: - anchor = static_cast(item)->GetPos(); + anchor = static_cast(item)->Pos(); aSplitsSegment = false; break; case PNS_ITEM::SEGMENT: { PNS_SEGMENT* seg = static_cast( item ); - const SEG& s = seg->GetSeg(); - int w = seg->GetWidth(); + const SEG& s = seg->Seg(); + int w = seg->Width(); aSplitsSegment = false; @@ -423,50 +459,52 @@ const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplit return anchor; } - -void PNS_ROUTER::StartRouting( const VECTOR2I& aP, PNS_ITEM* aStartItem ) +bool PNS_ROUTER::StartDragging( const VECTOR2I& aP, PNS_ITEM* aStartItem ) { - VECTOR2I p; - - static int unknowNetIdx = 0; // -10000; - - m_placingVia = false; - m_startsOnVia = false; - m_currentNet = -1; - - bool splitSeg = false; - - p = SnapToItem( aStartItem, aP, splitSeg ); - - if( !aStartItem || aStartItem->GetNet() < 0 ) - m_currentNet = unknowNetIdx--; - else - m_currentNet = aStartItem->GetNet(); - - m_currentStart = p; - m_originalStart = p; - m_currentEnd = p; - - m_placer->SetInitialDirection( m_start_diagonal ? DIRECTION_45( - DIRECTION_45::NE ) : DIRECTION_45( DIRECTION_45::N ) ); - m_placer->StartPlacement( m_originalStart, m_currentNet, m_currentWidth, m_currentLayer ); - m_state = ROUTE_TRACK; - - if( splitSeg ) - splitAdjacentSegments( m_placer->GetCurrentNode(), aStartItem, p ); + if(!aStartItem || aStartItem->OfKind(PNS_ITEM::SOLID)) + return false; + + m_dragger = new PNS_DRAGGER ( this ); + m_dragger->SetWorld( m_world ); + if( m_dragger->Start ( aP, aStartItem ) ) + m_state = DRAG_SEGMENT; + else { + delete m_dragger; + m_state = IDLE; + return false; + } + + return true; } -const VECTOR2I PNS_ROUTER::GetCurrentEnd() const +bool PNS_ROUTER::StartRouting( const VECTOR2I& aP, PNS_ITEM* aStartItem ) +{ + + + m_state = ROUTE_TRACK; + + m_placer = new PNS_LINE_PLACER( this ); + m_placer->SetLayer( m_currentLayer ); + m_placer->SetWidth ( m_settings.GetTrackWidth() ); + m_placer->Start( aP, aStartItem ); + m_currentEnd = aP; + m_currentEndItem = NULL; + + return true; +} + + +const VECTOR2I PNS_ROUTER::CurrentEnd() const { return m_currentEnd; } -void PNS_ROUTER::EraseView() +void PNS_ROUTER::eraseView() { BOOST_FOREACH( BOARD_ITEM* item, m_hiddenItems ) - { + { item->ViewSetVisible( true ); } @@ -480,71 +518,131 @@ void PNS_ROUTER::EraseView() } -void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, bool aIsHead ) +void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, int aColor, int aClearance ) { ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems ); - m_previewItems->Add( pitem ); + if(aColor >= 0) + pitem->SetColor ( KIGFX::COLOR4D ( aColor )); - if( aIsHead ) - pitem->MarkAsHead(); + if(aClearance >= 0) + pitem->SetClearance ( aClearance ); + + m_previewItems->Add( pitem ); pitem->ViewSetVisible( true ); m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); } +void PNS_ROUTER::DisplayItems( const PNS_ITEMSET& aItems ) +{ + BOOST_FOREACH(const PNS_ITEM *item, aItems.CItems()) + DisplayItem(item); +} void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth ) { ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); - pitem->DebugLine( aLine, aWidth, aType ); + pitem->Line( aLine, aWidth, aType ); m_previewItems->Add( pitem ); pitem->ViewSetVisible( true ); m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); } -void PNS_ROUTER::DisplayDebugBox( const BOX2I& aBox, int aType, int aWidth ) -{ -} +void PNS_ROUTER::DisplayDebugPoint( const VECTOR2I pos, int aType ) +{ + ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); + + pitem->Point( pos, aType ); + m_previewItems->Add( pitem ); + pitem->ViewSetVisible( true ); + m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); + +} void PNS_ROUTER::Move( const VECTOR2I& aP, PNS_ITEM* endItem ) { - PNS_NODE::ItemVector removed, added; - VECTOR2I p = aP; + m_currentEnd = aP; + m_currentEndItem = endItem; - if( m_state == IDLE ) - return; - - // TODO is something missing here? - if( m_state == START_ROUTING ) + switch( m_state ) { + case ROUTE_TRACK: + movePlacing( aP, endItem ); + break; + + case DRAG_SEGMENT: + moveDragging (aP, endItem ); + break; + default: + break; } +} - EraseView(); +void PNS_ROUTER::moveDragging( const VECTOR2I& aP, PNS_ITEM* endItem ) +{ + eraseView(); - m_currentEnd = p; - m_placer->Route( p ); + m_dragger->Drag( aP ); + PNS_ITEMSET dragged = m_dragger->Traces(); - PNS_LINE current = m_placer->GetTrace(); + updateView ( m_dragger->CurrentNode ( ), dragged ); +} - DisplayItem( ¤t, true ); +void PNS_ROUTER::markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ItemVector& aRemoved ) +{ + + BOOST_FOREACH(PNS_ITEM *item, aCurrent.Items()) + { + PNS_NODE::Obstacles obstacles; - if( current.EndsWithVia() ) - DisplayItem( ¤t.GetVia(), true ); + aNode->QueryColliding( item, obstacles, PNS_ITEM::ANY ); + + if ( item->OfKind(PNS_ITEM::LINE ) ) + { + PNS_LINE *l = static_cast (item); + if (l->EndsWithVia()) + { + PNS_VIA v ( l->Via() ); + aNode->QueryColliding(&v , obstacles, PNS_ITEM::ANY ); + } + } - m_placer->GetCurrentNode()->GetUpdatedItems( removed, added ); + BOOST_FOREACH(PNS_OBSTACLE& obs, obstacles) + { + int clearance = aNode->GetClearance( item, obs.item ); + std::auto_ptr tmp ( obs.item->Clone() ); + tmp->Mark ( MK_VIOLATION ); + DisplayItem( tmp.get(), -1, clearance ); + aRemoved.push_back(obs.item); + } + } +} + +void PNS_ROUTER::updateView( PNS_NODE *aNode, PNS_ITEMSET& aCurrent ) +{ + PNS_NODE::ItemVector removed, added; + PNS_NODE::Obstacles obstacles; + + if(!aNode) + return; + + if( Settings().Mode() == RM_MarkObstacles ) + markViolations(aNode, aCurrent, removed); + + aNode->GetUpdatedItems( removed, added ); BOOST_FOREACH( PNS_ITEM* item, added ) - { + { DisplayItem( item ); } BOOST_FOREACH( PNS_ITEM* item, removed ) { - BOARD_ITEM* parent = item->GetParent(); + BOARD_CONNECTED_ITEM* parent = item->Parent(); if( parent ) { @@ -558,32 +656,36 @@ void PNS_ROUTER::Move( const VECTOR2I& aP, PNS_ITEM* endItem ) } -void PNS_ROUTER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP ) +void PNS_ROUTER::ApplySettings() { - if( aSeg && aSeg->OfKind( PNS_ITEM::SEGMENT ) ) + // Change track/via size settings + if( m_state == ROUTE_TRACK) { - PNS_NODE::OptJoint jt = aNode->FindJoint( aP, aSeg->GetLayers().Start(), aSeg->GetNet() ); - - if( jt && jt->LinkCount() >= 1 ) - return; - - PNS_SEGMENT* s_old = static_cast( aSeg ); - PNS_SEGMENT* s_new[2]; - - s_new[0] = s_old->Clone(); - s_new[1] = s_old->Clone(); - - s_new[0]->SetEnds( s_old->GetSeg().A, aP ); - s_new[1]->SetEnds( aP, s_old->GetSeg().B ); - - aNode->Remove( s_old ); - aNode->Add( s_new[0] ); - aNode->Add( s_new[1] ); + m_placer->UpdateSizes( m_settings ); + m_placer->Move( m_currentEnd, m_currentEndItem ); + movePlacing( m_currentEnd, m_currentEndItem ); } + + // TODO handle mode/optimization/other options change } +void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* endItem ) +{ + eraseView(); -void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) + m_placer->Move( aP, endItem ); + PNS_LINE current = m_placer->Trace(); + + DisplayItem( ¤t ); + + if( current.EndsWithVia() ) + DisplayItem( ¤t.Via() ); + + PNS_ITEMSET tmp ( ¤t ); + updateView ( m_placer->CurrentNode ( true ), tmp ); +} + +void PNS_ROUTER::CommitRouting( PNS_NODE* aNode ) { PNS_NODE::ItemVector removed, added; @@ -591,13 +693,13 @@ void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) for( unsigned int i = 0; i < removed.size(); i++ ) { - BOARD_CONNECTED_ITEM* parent = removed[i]->GetParent(); + BOARD_CONNECTED_ITEM* parent = removed[i]->Parent(); if( parent ) { - m_undoBuffer.PushItem( ITEM_PICKER( parent, UR_DELETED ) ); - m_board->Remove( parent ); m_view->Remove( parent ); + m_board->Remove( parent ); + m_undoBuffer.PushItem( ITEM_PICKER( parent, UR_DELETED ) ); } } @@ -605,19 +707,19 @@ void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) { BOARD_CONNECTED_ITEM* newBI = NULL; - switch( item->GetKind() ) + switch( item->Kind() ) { case PNS_ITEM::SEGMENT: { PNS_SEGMENT* seg = static_cast( item ); TRACK* track = new TRACK( m_board ); - const SEG& s = seg->GetSeg(); + const SEG& s = seg->Seg(); track->SetStart( wxPoint( s.A.x, s.A.y ) ); track->SetEnd( wxPoint( s.B.x, s.B.y ) ); - track->SetWidth( seg->GetWidth() ); - track->SetLayer( seg->GetLayers().Start() ); - track->SetNetCode( seg->GetNet() ); + track->SetWidth( seg->Width() ); + track->SetLayer( seg->Layers().Start() ); + track->SetNetCode( seg->Net() ); newBI = track; break; } @@ -626,9 +728,10 @@ void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) { VIA* via_board = new VIA( m_board ); PNS_VIA* via = static_cast( item ); - via_board->SetPosition( wxPoint( via->GetPos().x, via->GetPos().y ) ); - via_board->SetWidth( via->GetDiameter() ); - via_board->SetNetCode( via->GetNet() ); + via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) ); + via_board->SetWidth( via->Diameter() ); + via_board->SetDrill( via->Drill() ); + via_board->SetNetCode( via->Net() ); newBI = via_board; break; } @@ -657,12 +760,12 @@ PNS_VIA* PNS_ROUTER::checkLoneVia( PNS_JOINT* aJoint ) const PNS_VIA* theVia = NULL; PNS_LAYERSET l; - BOOST_FOREACH( PNS_ITEM* item, aJoint->GetLinkList() ) + BOOST_FOREACH( PNS_ITEM* item, aJoint->LinkList() ) { - if( item->GetKind() == PNS_ITEM::VIA ) + if( item->Kind() == PNS_ITEM::VIA ) theVia = static_cast( item ); - l.Merge( item->GetLayers() ); + l.Merge( item->Layers() ); } if( l.Start() == l.End() ) @@ -671,103 +774,34 @@ PNS_VIA* PNS_ROUTER::checkLoneVia( PNS_JOINT* aJoint ) const return NULL; } - -PNS_NODE* PNS_ROUTER::removeLoops( PNS_NODE* aNode, PNS_SEGMENT* aLatestSeg ) -{ - PNS_LINE* ourLine = aNode->AssembleLine( aLatestSeg ); - PNS_NODE* cleaned = aNode->Branch(); - PNS_JOINT a, b; - - std::vector lines; - - cleaned->FindLineEnds( ourLine, a, b ); - cleaned->FindLinesBetweenJoints( a, b, lines ); - - BOOST_FOREACH( PNS_LINE* line, lines ) - { - if( !( line->ContainsSegment( aLatestSeg ) ) ) - { - cleaned->Remove( line ); - } - } - - return cleaned; -} - - bool PNS_ROUTER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { - bool real_end = false; + bool rv = false; - PNS_LINE pl = m_placer->GetTrace(); - const SHAPE_LINE_CHAIN& l = pl.GetCLine(); - - if( !l.SegmentCount() ) - return true; - - VECTOR2I p_pre_last = l.CPoint( -1 ); - const VECTOR2I p_last = l.CPoint( -1 ); - DIRECTION_45 d_last( l.CSegment( -1 ) ); - - if( l.PointCount() > 2 ) - p_pre_last = l.CPoint( -2 ); - - if( aEndItem && m_currentNet >= 0 && m_currentNet == aEndItem->GetNet() ) - real_end = true; - - int last = ( real_end || m_placingVia ) ? l.SegmentCount() : std::max( 1, l.SegmentCount() - 1 ); - - PNS_NODE* latest = m_placer->GetCurrentNode(); - - if( real_end ) - splitAdjacentSegments( latest, aEndItem, aP ); - - PNS_SEGMENT* lastSeg = NULL; - - for( int i = 0; i < last; i++ ) + switch(m_state) { - const SEG& s = pl.GetCLine().CSegment( i ); - PNS_SEGMENT* seg = new PNS_SEGMENT( s, m_currentNet ); - seg->SetWidth( pl.GetWidth() ); - seg->SetLayer( m_currentLayer ); - latest->Add( seg ); - lastSeg = seg; - } + case ROUTE_TRACK: + rv = m_placer->FixRoute (aP, aEndItem); + m_placingVia = false; + + break; + case DRAG_SEGMENT: + rv = m_dragger->FixRoute (); + break; + + default: + break; + } - if( pl.EndsWithVia() ) - latest->Add( pl.GetVia().Clone() ); - - if( real_end ) - latest = removeLoops( latest, lastSeg ); - - commitRouting( latest ); - - EraseView(); - - if( real_end ) - { - m_state = IDLE; - // m_world->KillChildren(); - } - else - { - m_state = ROUTE_TRACK; - m_placer->SetInitialDirection( d_last ); - m_currentStart = m_placingVia ? p_last : p_pre_last; - - if( m_placingVia ) - m_currentLayer = NextCopperLayer( true ); - - m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth, m_currentLayer ); - - m_startsOnVia = m_placingVia; - m_placingVia = false; - } - - return real_end; + + if(rv) + StopRouting(); + + return rv; } + void PNS_ROUTER::StopRouting() { // Update the ratsnest with new changes @@ -776,25 +810,30 @@ void PNS_ROUTER::StopRouting() if( !RoutingInProgress() ) return; - EraseView(); + if(m_placer) + delete m_placer; + + if(m_dragger) + delete m_dragger; + + m_placer = NULL; + m_dragger = NULL; + + eraseView(); m_state = IDLE; m_world->KillChildren(); + m_world->ClearRanks(); } void PNS_ROUTER::FlipPosture() { - if( m_placer->GetTail().GetCLine().SegmentCount() == 0 ) + if(m_state == ROUTE_TRACK) { - m_start_diagonal = !m_start_diagonal; - m_placer->SetInitialDirection( m_start_diagonal ? - DIRECTION_45( DIRECTION_45::NE ) : DIRECTION_45( DIRECTION_45::N ) ); - } - else m_placer->FlipPosture(); - - Move( m_currentEnd, NULL ); + m_placer->Move ( m_currentEnd, m_currentEndItem ); + } } @@ -810,10 +849,10 @@ void PNS_ROUTER::SwitchLayer( int layer ) if( m_startsOnVia ) { m_currentLayer = layer; - m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth, - m_currentLayer ); + //m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth, + // m_currentLayer ); } - + break; default: break; } @@ -825,6 +864,45 @@ void PNS_ROUTER::ToggleViaPlacement() if( m_state == ROUTE_TRACK ) { m_placingVia = !m_placingVia; - m_placer->AddVia( m_placingVia, m_currentViaDiameter, m_currentViaDrill ); + m_placer->AddVia( m_placingVia, m_settings.GetViaDiameter(), m_settings.GetViaDrill() ); } } + +int PNS_ROUTER::GetCurrentNet() const +{ + switch(m_state) + { + case ROUTE_TRACK: + return m_placer->CurrentNet(); + default: + return m_currentNet; + } +} + +int PNS_ROUTER::GetCurrentLayer() const +{ + switch(m_state) + { + case ROUTE_TRACK: + return m_placer->CurrentLayer(); + default: + return m_currentLayer; + } +} + +void PNS_ROUTER::DumpLog() +{ + PNS_LOGGER *logger = NULL; + switch(m_state) + { + case DRAG_SEGMENT: + logger = m_dragger->Logger(); + break; + + default: + break; + } + + if(logger) + logger->Save ( "/tmp/shove.log" ); +} diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index e5fabbeec2..53c0905487 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_ROUTER_H @@ -32,6 +32,7 @@ #include "pns_routing_settings.h" #include "pns_item.h" #include "pns_itemset.h" +#include "pns_node.h" class BOARD; class BOARD_ITEM; @@ -47,7 +48,8 @@ class PNS_SEGMENT; class PNS_JOINT; class PNS_VIA; class PNS_CLEARANCE_FUNC; -class VIEW_GROUP; +class PNS_SHOVE; +class PNS_DRAGGER; namespace KIGFX { class VIEW; @@ -67,9 +69,8 @@ private: enum RouterState { IDLE, - START_ROUTING, - ROUTE_TRACK, - FINISH_TRACK + DRAG_SEGMENT, + ROUTE_TRACK }; public: @@ -85,13 +86,13 @@ public: void SetView( KIGFX::VIEW* aView ); bool RoutingInProgress() const; - void StartRouting( const VECTOR2I& aP, PNS_ITEM* aItem ); + bool StartRouting( const VECTOR2I& aP, PNS_ITEM* aItem ); void Move( const VECTOR2I& aP, PNS_ITEM* aItem ); bool FixRoute( const VECTOR2I& aP, PNS_ITEM* aItem ); void StopRouting(); - const VECTOR2I GetCurrentEnd() const; + const VECTOR2I CurrentEnd() const; int GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const; @@ -102,25 +103,22 @@ public: void FlipPosture(); - void DisplayItem( const PNS_ITEM* aItem, bool aIsHead = false ); + void DisplayItem( const PNS_ITEM* aItem, int aColor = -1, int aClearance = -1 ); + void DisplayItems( const PNS_ITEMSET& aItems ); + void DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType = 0, int aWidth = 0 ); + void DisplayDebugPoint( const VECTOR2I aPos, int aType = 0); void DisplayDebugBox( const BOX2I& aBox, int aType = 0, int aWidth = 0 ); - void EraseView(); void SwitchLayer( int layer ); - int GetCurrentLayer() const { return m_currentLayer; } void ToggleViaPlacement(); - void SetCurrentWidth( int w ); - - void SetCurrentViaDiameter( int d ) { m_currentViaDiameter = d; } - void SetCurrentViaDrill( int d ) { m_currentViaDrill = d; } - int GetCurrentWidth() const { return m_currentWidth; } - int GetCurrentViaDiameter() const { return m_currentViaDiameter; } - int GetCurrentViaDrill() const { return m_currentViaDrill; } - int GetCurrentNet() const { return m_currentNet; } + int GetCurrentLayer() const;// { return m_currentLayer; } + int GetCurrentNet() const;// { return m_currentNet; } + void DumpLog(); + PNS_CLEARANCE_FUNC* GetClearanceFunc() const { return m_clearanceFunc; @@ -138,11 +136,24 @@ public: const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP ); const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment ); + bool StartDragging( const VECTOR2I& aP, PNS_ITEM* aItem ); + + void SetIterLimit( int aX ) { m_iterLimit = aX; } + int GetIterLimit() const { return m_iterLimit; }; + + void SetShowIntermediateSteps(bool aX, int aSnapshotIter = -1 ) { m_showInterSteps = aX; m_snapshotIter = aSnapshotIter; } + bool GetShowIntermediateSteps() const { return m_showInterSteps; } + int GetShapshotIter() const { return m_snapshotIter; } + + PNS_ROUTING_SETTINGS& Settings() { return m_settings; } + + void CommitRouting( PNS_NODE* aNode ); + /** * Returns the last changes introduced by the router (since the last time ClearLastChanges() * was called or a new track has been started). */ - const PICKED_ITEMS_LIST& GetLastChanges() const + const PICKED_ITEMS_LIST& GetUndoBuffer() const { return m_undoBuffer; } @@ -150,21 +161,41 @@ public: /** * Clears the list of recent changes, saved to be stored in the undo buffer. */ - void ClearLastChanges() + void ClearUndoBuffer() { m_undoBuffer.ClearItemsList(); } + /** + * Applies stored settings. + * \see Settings() + */ + void ApplySettings(); + + void EnableSnapping ( bool aEnable ) + { + m_snappingEnabled = aEnable; + } + + bool SnappingEnabled () const + { + return m_snappingEnabled; + } + + private: + void movePlacing ( const VECTOR2I& aP, PNS_ITEM* aItem ); + void moveDragging ( const VECTOR2I& aP, PNS_ITEM* aItem ); + + void eraseView(); + void updateView( PNS_NODE *aNode, PNS_ITEMSET &aCurrent ); //PNS_LINE *aCurrent = NULL ); + void clearViewFlags(); // optHoverItem queryHoverItemEx(const VECTOR2I& aP); PNS_ITEM* pickSingleItem( PNS_ITEMSET& aItems ) const; // std::vector aItems) const; void splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP ); // optHoverItem& aItem); - void commitRouting( PNS_NODE* aNode ); - PNS_NODE* removeLoops( PNS_NODE* aNode, PNS_SEGMENT* aLatestSeg ); - PNS_NODE* removeLoops( PNS_NODE* aNode, PNS_LINE* aNewLine ); PNS_VIA* checkLoneVia( PNS_JOINT* aJoint ) const; PNS_ITEM* syncPad( D_PAD* aPad ); @@ -177,35 +208,45 @@ private: void highlightCurrent( bool enabled ); + void markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ItemVector& aRemoved ); + int m_currentLayer; int m_currentNet; - int m_currentWidth; - int m_currentViaDiameter; - int m_currentViaDrill; - - bool m_start_diagonal; RouterState m_state; BOARD* m_board; PNS_NODE* m_world; + PNS_NODE* m_lastNode; PNS_LINE_PLACER* m_placer; + PNS_DRAGGER *m_dragger; + PNS_LINE* m_draggedLine; + PNS_SHOVE* m_shove; + int m_draggedSegmentIndex; + int m_iterLimit; + bool m_showInterSteps; + int m_snapshotIter; KIGFX::VIEW* m_view; KIGFX::VIEW_GROUP* m_previewItems; + + PNS_ITEM *m_currentEndItem; + VECTOR2I m_currentEnd; VECTOR2I m_currentStart; VECTOR2I m_originalStart; bool m_placingVia; bool m_startsOnVia; + bool m_snappingEnabled; + bool m_violation; // optHoverItem m_startItem, m_endItem; PNS_ROUTING_SETTINGS m_settings; PNS_CLEARANCE_FUNC* m_clearanceFunc; - boost::unordered_set m_hiddenItems; + boost::unordered_set m_hiddenItems; ///> Stores list of modified items in the current operation PICKED_ITEMS_LIST m_undoBuffer; diff --git a/pcbnew/router/pns_routing_settings.cpp b/pcbnew/router/pns_routing_settings.cpp new file mode 100644 index 0000000000..cddc110311 --- /dev/null +++ b/pcbnew/router/pns_routing_settings.cpp @@ -0,0 +1,49 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#include "pns_routing_settings.h" + +PNS_ROUTING_SETTINGS::PNS_ROUTING_SETTINGS() +{ + m_routingMode = RM_Walkaround; + m_optimizerEffort = OE_Full; + m_removeLoops = true; + m_smartPads = true; + m_shoveVias = true; + m_suggestFinish = false; + m_followMouse = true; + m_startDiagonal = false; + m_shoveIterationLimit = 250; + m_shoveTimeLimit = 1000; + m_walkaroundIterationLimit = 40; + m_jumpOverObstacles = false; + m_smoothDraggedSegments = true; + m_canViolateDRC = false; +} + +TIME_LIMIT PNS_ROUTING_SETTINGS::ShoveTimeLimit() const +{ + return TIME_LIMIT ( m_shoveTimeLimit ); +} + +int PNS_ROUTING_SETTINGS::ShoveIterationLimit() const +{ + return m_shoveIterationLimit; +} diff --git a/pcbnew/router/pns_routing_settings.h b/pcbnew/router/pns_routing_settings.h index 72a4babef0..02eab2a352 100644 --- a/pcbnew/router/pns_routing_settings.h +++ b/pcbnew/router/pns_routing_settings.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,39 +15,147 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ -#ifndef __PNS_ROUTER_SETTINGS -#define __PNS_ROUTER_SETTINGS +#ifndef __PNS_ROUTING_SETTINGS +#define __PNS_ROUTING_SETTINGS +#include "direction.h" +#include "time_limit.h" + ///> Routing modes enum PNS_MODE { - RM_Ignore = 0, ///> Ignore collisions - RM_Shove, ///> Only shove - RM_Walkaround, ///> Only walkaround - RM_Smart ///> Guess what's better + RM_MarkObstacles = 0, ///> Ignore collisions, mark obstacles + RM_Shove, ///> Only shove + RM_Walkaround, ///> Only walkaround + RM_Smart ///> Guess what's better, try to make least mess on the PCB }; +///> Optimization effort +enum PNS_OPTIMIZATION_EFFORT +{ + OE_Low = 0, + OE_Medium = 1, + OE_Full = 2 +}; + +/** + * Class PNS_ROUTING_SETTINGS + * + * Contains all persistent settings of the router, such as the mode, optimization effort, etc. + */ + class PNS_ROUTING_SETTINGS { public: - PNS_MODE m_routingMode; + PNS_ROUTING_SETTINGS(); + ///> Returns the routing mode. + PNS_MODE Mode() const { return m_routingMode; } + + ///> Sets the routing mode. + void SetMode( PNS_MODE aMode ) { m_routingMode = aMode; } + + ///> Returns the optimizer effort. Bigger means cleaner traces, but slower routing. + PNS_OPTIMIZATION_EFFORT OptimizerEffort() const { return m_optimizerEffort; } + + ///> Sets the optimizer effort. Bigger means cleaner traces, but slower routing. + void SetOptimizerEffort( PNS_OPTIMIZATION_EFFORT aEffort ) { m_optimizerEffort = aEffort; } + + ///> Returns true if shoving vias is enbled. + bool ShoveVias() const { return m_shoveVias; } + + ///> Enables/disables shoving vias. + void SetShoveVias( bool aShoveVias ) { m_shoveVias = aShoveVias; } + + ///> Returns true if loop (redundant track) removal is on. + bool RemoveLoops() const { return m_removeLoops; } + + ///> Enables/disables loop (redundant track) removal. + void SetRemoveLoops( bool aRemoveLoops ) { m_removeLoops = aRemoveLoops; } + + ///> Returns true if suggesting the finish of currently placed track is on. + bool SuggestFinish() { return m_suggestFinish; } + + ///> Enables displaying suggestions for finishing the currently placed track. + void SetSuggestFinish( bool aSuggestFinish ) { m_suggestFinish = aSuggestFinish; } + + ///> Returns true if Smart Pads (automatic neckdown) is enabled. + bool SmartPads () const { return m_smartPads; } + + ///> Enables/disables Smart Pads (automatic neckdown). + void SetSmartPads( bool aSmartPads ) { m_smartPads = aSmartPads; } + + ///> Returns true if follow mouse mode is active (permanently on for the moment). + bool FollowMouse() const + { + return m_followMouse && !(Mode() == RM_MarkObstacles); + } + + ///> Returns true if smoothing segments durign dragging is enabled. + bool SmoothDraggedSegments() const { return m_smoothDraggedSegments; } + + ///> Enables/disabled smoothing segments during dragging. + void SetSmoothDraggedSegments( bool aSmooth ) { m_smoothDraggedSegments = aSmooth; } + + ///> Returns true if jumping over unmovable obstacles is on. + bool JumpOverObstacles() const { return m_jumpOverObstacles; } + + ///> Enables/disables jumping over unmovable obstacles. + void SetJumpOverObstacles( bool aJumpOverObstacles ) { m_jumpOverObstacles = aJumpOverObstacles; } + + void SetStartDiagonal(bool aStartDiagonal) { m_startDiagonal = aStartDiagonal; } + + bool CanViolateDRC() const { return m_canViolateDRC; } + void SetCanViolateDRC( bool aViolate ) { m_canViolateDRC = aViolate; } + + void SetTrackWidth( int aWidth ) { m_trackWidth = aWidth; } + int GetTrackWidth() const { return m_trackWidth; } + void SetViaDiameter( int aDiameter ) { m_viaDiameter = aDiameter; } + int GetViaDiameter() const { return m_viaDiameter; } + void SetViaDrill( int aDrill ) { m_viaDrill = aDrill; } + int GetViaDrill() const { return m_viaDrill; } + + const DIRECTION_45 InitialDirection() const + { + if(m_startDiagonal) + return DIRECTION_45 (DIRECTION_45::NE); + else + return DIRECTION_45 (DIRECTION_45::N); + } + + int ShoveIterationLimit() const; + TIME_LIMIT ShoveTimeLimit() const; + + int WalkaroundIterationLimit() const { return m_walkaroundIterationLimit; }; + TIME_LIMIT WalkaroundTimeLimit() const; + +private: + + bool m_shoveVias; + bool m_startDiagonal; bool m_removeLoops; bool m_smartPads; - bool m_suggestEnding; - bool m_shoveOnRequest; - bool m_changePostures; + bool m_suggestFinish; bool m_followMouse; + bool m_jumpOverObstacles; + bool m_smoothDraggedSegments; + bool m_canViolateDRC; - int m_lineWidth; + PNS_MODE m_routingMode; + PNS_OPTIMIZATION_EFFORT m_optimizerEffort; + + int m_trackWidth; int m_viaDiameter; int m_viaDrill; + int m_preferredLayer; int m_walkaroundIterationLimit; int m_shoveIterationLimit; + TIME_LIMIT m_shoveTimeLimit; + TIME_LIMIT m_walkaroundTimeLimit; }; #endif diff --git a/pcbnew/router/pns_segment.h b/pcbnew/router/pns_segment.h index 06ab41dfa0..0ebc4bc767 100644 --- a/pcbnew/router/pns_segment.h +++ b/pcbnew/router/pns_segment.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_SEGMENT_H @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include "pns_item.h" @@ -40,31 +40,27 @@ public: {}; PNS_SEGMENT( const SEG& aSeg, int aNet ) : - PNS_ITEM( SEGMENT ) + PNS_ITEM( SEGMENT ), m_seg(aSeg, 0) { m_net = aNet; - m_shape.Clear(); - m_shape.Append( aSeg.A ); - m_shape.Append( aSeg.B ); }; PNS_SEGMENT( const PNS_LINE& aParentLine, const SEG& aSeg ) : - PNS_ITEM( SEGMENT ) + PNS_ITEM( SEGMENT ), + m_seg(aSeg, aParentLine.Width()) { - m_net = aParentLine.GetNet(); - m_layers = aParentLine.GetLayers(); - m_width = aParentLine.GetWidth(); - m_shape.Clear(); - m_shape.Append( aSeg.A ); - m_shape.Append( aSeg.B ); + m_net = aParentLine.Net(); + m_layers = aParentLine.Layers(); + m_marker = aParentLine.Marker(); + m_rank = aParentLine.Rank(); }; - PNS_SEGMENT* Clone() const; + PNS_SEGMENT* Clone( ) const; - const SHAPE* GetShape() const + const SHAPE* Shape() const { - return static_cast( &m_shape ); + return static_cast( &m_seg ); } void SetLayer( int aLayer ) @@ -72,53 +68,59 @@ public: SetLayers( PNS_LAYERSET( aLayer ) ); } - int GetLayer() const + int Layer() const { - return GetLayers().Start(); - } - - const SHAPE_LINE_CHAIN& GetCLine() const - { - return m_shape; + return Layers().Start(); } void SetWidth( int aWidth ) { - m_width = aWidth; + m_seg.SetWidth(aWidth); } - int GetWidth() const + int Width() const { - return m_width; + return m_seg.GetWidth(); } - const SEG GetSeg() const + const SEG& Seg() const { - assert( m_shape.PointCount() >= 1 ); + return m_seg.GetSeg(); + } - if( m_shape.PointCount() == 1 ) - return SEG( m_shape.CPoint( 0 ), m_shape.CPoint( 0 ) ); - - return SEG( m_shape.CPoint( 0 ), m_shape.CPoint( 1 ) ); + const SHAPE_LINE_CHAIN CLine() const + { + return SHAPE_LINE_CHAIN( m_seg.GetSeg().A, m_seg.GetSeg().B ); } void SetEnds( const VECTOR2I& a, const VECTOR2I& b ) { - m_shape.Clear(); - m_shape.Append( a ); - m_shape.Append( b ); - } + m_seg.SetSeg( SEG ( a, b ) ); + } void SwapEnds() { - m_shape = m_shape.Reverse(); + SEG tmp = m_seg.GetSeg(); + m_seg.SetSeg( SEG (tmp.B , tmp.A )); } const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const; + virtual VECTOR2I Anchor(int n) const + { + if(n == 0) + return m_seg.GetSeg().A; + else + return m_seg.GetSeg().B; + } + + virtual int AnchorCount() const + { + return 2; + } + private: - SHAPE_LINE_CHAIN m_shape; - int m_width; + SHAPE_SEGMENT m_seg; }; #endif diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index ad58ee1feb..491f3327f3 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,477 +15,1067 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include #include -#include +#include #include "trace.h" +#include "range.h" #include "pns_line.h" #include "pns_node.h" #include "pns_walkaround.h" #include "pns_shove.h" +#include "pns_solid.h" #include "pns_optimizer.h" #include "pns_via.h" #include "pns_utils.h" +#include "pns_router.h" +#include "pns_shove.h" + +#include "time_limit.h" #include -PNS_SHOVE::PNS_SHOVE( PNS_NODE* aWorld ) +static void sanityCheck (PNS_LINE *l_old, PNS_LINE *l_new) +{ + assert (l_old->CPoint(0) == l_new->CPoint(0) ); + assert (l_old->CPoint(-1) == l_new->CPoint(-1 )); +} + +PNS_SHOVE::PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER *aRouter ) : + PNS_ALGO_BASE ( aRouter ) { m_root = aWorld; - m_iterLimit = 100; }; PNS_SHOVE::~PNS_SHOVE() { +// free all the stuff we've created during routing/dragging operation. + BOOST_FOREACH(PNS_ITEM *item, m_gcItems) + delete item; } - -struct range +// garbage-collected line assembling +PNS_LINE* PNS_SHOVE::assembleLine ( const PNS_SEGMENT *aSeg, int *aIndex ) { - range() - { - min_v = max_v = -1; - } + PNS_LINE *l = m_currentNode->AssembleLine( const_cast (aSeg), aIndex); - void add( int x ) - { - if( min_v < 0 ) min_v = x; + m_gcItems.push_back(l); + return l; +} - if( max_v < 0 ) max_v = x; - - if( x < min_v ) - min_v = x; - else if( x > max_v ) - max_v = x; - } - - int start() - { - return min_v; - } - - int end() - { - return max_v; - } - - int min_v, max_v; -}; - -// fixme: this is damn f***ing inefficient. And fails much too often due to broken direction finding algorithm. -bool PNS_SHOVE::tryShove( PNS_NODE* aNode, PNS_LINE* aHead, PNS_LINE* aObstacle, - PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult, bool aInvertWinding ) +// garbage-collected line cloning +PNS_LINE *PNS_SHOVE::cloneLine ( const PNS_LINE *aLine ) { - const SHAPE_LINE_CHAIN& head = aHead->GetCLine(); - bool cw = false; - int i; + PNS_LINE *l = aLine->Clone(); - if( aHead->EndsWithVia() && !aHead->GetLayers().Overlaps( aObstacle->GetLayers() ) ) + m_gcItems.push_back(l); + return l; +} + +// A dumb function that checks if the shoved line is shoved the right way, e.g. +// visually "outwards" of the line/via applying pressure on it. Unfortunately there's no +// mathematical concept of orientation of an open curve, so we use some primitive heuristics: +// if the shoved line wraps around the start of the "pusher", it's likely shoved in wrong direction. +bool PNS_SHOVE::checkBumpDirection ( PNS_LINE *aCurrent, PNS_LINE *aShoved ) const +{ + const SEG ss = aCurrent->CSegment(0); + + int dist = m_currentNode->GetClearance(aCurrent, aShoved) + PNS_HULL_MARGIN; + + dist += aCurrent->Width() / 2; + dist += aShoved->Width() / 2; + + const VECTOR2I ps = ss.A - (ss.B - ss.A).Resize(dist); + + return !aShoved->CLine().PointOnEdge(ps); +} + +PNS_SHOVE::ShoveStatus PNS_SHOVE::walkaroundLoneVia ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved ) +{ + int clearance = m_currentNode->GetClearance( aCurrent, aObstacle ); + const SHAPE_LINE_CHAIN hull = aCurrent->Via().Hull( clearance, aObstacle->Width() ); + SHAPE_LINE_CHAIN path_cw, path_ccw; + + aObstacle->Walkaround( hull, path_cw, true ); + aObstacle->Walkaround( hull, path_ccw, false ); + + const SHAPE_LINE_CHAIN& shortest = path_ccw.Length() < path_cw.Length() ? path_ccw : path_cw; + + if(shortest.PointCount() < 2) + return SH_INCOMPLETE; + if(aObstacle->CPoint(-1) != shortest.CPoint(-1)) + return SH_INCOMPLETE; + if(aObstacle->CPoint(0) != shortest.CPoint(0)) + return SH_INCOMPLETE; + + aShoved->SetShape( shortest ); + + if( m_currentNode->CheckColliding( aShoved, aCurrent ) ) + return SH_INCOMPLETE; + + return SH_OK; +} + +PNS_SHOVE::ShoveStatus PNS_SHOVE::processHullSet ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved, const HullSet& hulls ) +{ + const SHAPE_LINE_CHAIN& obs = aObstacle->CLine(); + bool failingDirCheck = false; + int attempt; + + for(attempt = 0; attempt < 4; attempt++) { - int clearance = aNode->GetClearance( aHead, aObstacle ); - SHAPE_LINE_CHAIN hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2 ); + bool invertTraversal = (attempt >= 2); + bool clockwise = attempt % 2; + int vFirst = -1, vLast = -1; - // SHAPE_LINE_CHAIN path_pre, path_walk_cw, path_walk_ccw, path_post; + SHAPE_LINE_CHAIN path; + PNS_LINE l ( *aObstacle ); - SHAPE_LINE_CHAIN path_cw, path_ccw, * path; - - aObstacle->NewWalkaround( hull, path_cw, true ); - aObstacle->NewWalkaround( hull, path_ccw, false ); - - path = path_ccw.Length() < path_cw.Length() ? &path_ccw : &path_cw; - aResult->SetShape( *path ); - - // PNSDisplayDebugLine (*path, 5); - - if( !aResult->Is45Degree() ) + for(int i = 0; i < (int)hulls.size(); i++ ) { - // printf("polyset non-45\npoly %s\nendpolyset\n", aResult->GetCLine().Format().c_str()); + const SHAPE_LINE_CHAIN& hull = hulls[invertTraversal ? hulls.size() - 1 - i : i]; + + l.Walkaround( hull, path, clockwise ); + path.Simplify(); + l.SetShape( path ); + } + + for(int i = 0; i < std::min ( path.PointCount(), obs.PointCount() ); i++) + { + if(path.CPoint(i) != obs.CPoint(i)) + { + vFirst = i; + break; + } } - /*... special case for vias? */ + int k = obs.PointCount() - 1; + for(int i = path.PointCount() - 1; i >= 0 && k >= 0; i--, k--) + { + if(path.CPoint(i) != obs.CPoint(k)) + { + vLast = i; + break; + } + } - return !aNode->CheckColliding( aResult, aHead ); + if( ( vFirst < 0 || vLast < 0) && !path.CompareGeometry( aObstacle->CLine() )) + { + TRACE( 100, "attempt %d fail vfirst-last", attempt ); + continue; + } + + if(path.CPoint(-1) != obs.CPoint(-1) || path.CPoint(0) != obs.CPoint(0)) + { + TRACE(100, "attempt %d fail vend-start\n", attempt); + continue; + } + + if(!checkBumpDirection(aCurrent, &l)) + { + TRACE( 100, "attempt %d fail direction-check", attempt ); + failingDirCheck = true; + aShoved->SetShape(l.CLine()); + continue; + } + + if(path.SelfIntersecting()) + { + TRACE( 100, "attempt %d fail self-intersect", attempt ); + continue; + } + + bool colliding = m_currentNode->CheckColliding( &l, aCurrent ); + + if( (aCurrent->Marker() & MK_HEAD) && !colliding) + { + PNS_JOINT *jtStart = m_currentNode->FindJoint ( aCurrent->CPoint(0), aCurrent ); + + BOOST_FOREACH( PNS_ITEM *item, jtStart->LinkList() ) + { + if(m_currentNode->CheckColliding(item, &l)) + colliding = true; + } + } + + if( colliding ) + { + TRACE( 100, "attempt %d fail coll-check", attempt ); + continue; + } + + aShoved->SetShape( l.CLine() ); + + return SH_OK; } - int ns = head.SegmentCount(); + return failingDirCheck ? SH_OK : SH_INCOMPLETE; +} - if( aHead->EndsWithVia() ) - ns++; +PNS_SHOVE::ShoveStatus PNS_SHOVE::processSingleLine ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved ) +{ + aShoved->ClearSegmentLinks(); - for( i = 0; i < head.SegmentCount(); i++ ) + bool obstacleIsHead = false; + + if( aObstacle->LinkedSegments() ) { - const PNS_SEGMENT hs( *aHead, head.CSegment( i ) ); - - - if( aNode->CheckColliding( &hs, aObstacle ) ) + BOOST_FOREACH( PNS_SEGMENT *s, *aObstacle->LinkedSegments() ) + if(s->Marker() & MK_HEAD) { - VECTOR2I v1 = hs.GetSeg().B - hs.GetSeg().A; - VECTOR2I v2 = aObstacleSeg.GetSeg().B - aObstacleSeg.GetSeg().A; - - VECTOR2I::extended_type det = v1.Cross( v2 ); - - if( det > 0 ) - cw = true; - else - cw = false; - + obstacleIsHead = true; break; } } - if( aInvertWinding ) + ShoveStatus rv; + + bool viaOnEnd = aCurrent->EndsWithVia(); + + if( viaOnEnd && ( !aCurrent->LayersOverlap( aObstacle ) || aCurrent->SegmentCount() == 0 ) ) { - if( cw ) - cw = false; - else - cw = true; - } + rv = walkaroundLoneVia( aCurrent, aObstacle, aShoved ); + } else { + int w = aObstacle->Width(); + int n_segs = aCurrent->SegmentCount(); + int clearance = m_currentNode->GetClearance( aCurrent, aObstacle ); - PNS_LINE shoved( *aObstacle ); + HullSet hulls; - int clearance = aNode->GetClearance( aHead, aObstacle ); + hulls.reserve( n_segs + 1 ); - range r; - - for( i = 0; i < ns; i++ ) - { - SHAPE_LINE_CHAIN hull; - - if( i < head.SegmentCount() ) + for( int i = 0; i < n_segs; i++ ) { - const PNS_SEGMENT hs( *aHead, head.CSegment( i ) ); - hull = hs.Hull( clearance, 0 ); + PNS_SEGMENT seg ( *aCurrent, aCurrent->CSegment(i) ); + hulls.push_back ( seg.Hull( clearance, w ) ); } - else - hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2 ); - SHAPE_LINE_CHAIN path_pre, path_walk, path_post, tmp; - SHAPE_LINE_CHAIN path_pre2, path_walk2, path_post2; + if( viaOnEnd ) + hulls.push_back ( aCurrent->Via().Hull( clearance, w ) ); - // shoved.NewWalkaround(hull, path_pre, path_walk, path_post, cw); - shoved.NewWalkaround( hull, path_pre, path_walk, path_post, cw ); - - /*if(path_pre != path_pre2 || path_post != path_post2 || path_walk != path_walk2 ) - * { - * TRACE(5, "polyset orig\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre.Format().c_str() % path_walk.Format().c_str() % path_post.Format().c_str()); - * TRACE(5, "polyset err\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre2.Format().c_str() % path_walk2.Format().c_str() % path_post2.Format().c_str()); - * }*/ - - tmp = shoved.GetCLine(); - - if( path_walk.SegmentCount() ) - r.add( i ); - - path_pre.Append( path_walk ); - path_pre.Append( path_post ); - path_pre.Simplify(); - shoved.SetShape( path_pre ); -// shoved.SetAffectedRange ( start, end ); - *aResult = shoved; - - if( !aResult->Is45Degree() ) - { - // TRACE(5, "polyset non-45\npoly %s\npoly %s\npoly %s\nendpolyset\n", tmp.Format().c_str() % hull.Format().c_str() % aResult->GetCLine().Format().c_str()); - } + rv = processHullSet ( aCurrent, aObstacle, aShoved, hulls); } + + if(obstacleIsHead) + aShoved->Mark( aShoved->Marker() | MK_HEAD ); - TRACE( 2, "CW %d affectedRange %d-%d [total %d]", (cw ? 1 : 0) % r.start() % r.end() % ns ); - - return !aNode->CheckColliding( aResult, aHead ); + return rv; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine( PNS_NODE* aNode, PNS_LINE* aCurrent, - PNS_LINE* aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult ) +PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingSegment( PNS_LINE *aCurrent, PNS_SEGMENT *aObstacleSeg ) { - bool rv = tryShove( aNode, aCurrent, aObstacle, aObstacleSeg, aResult, false ); + int segIndex; + PNS_LINE *obstacleLine = assembleLine (aObstacleSeg, &segIndex); + PNS_LINE *shovedLine = cloneLine ( obstacleLine ); + + ShoveStatus rv = processSingleLine ( aCurrent, obstacleLine, shovedLine ); - if( !rv ) - rv = tryShove( aNode, aCurrent, aObstacle, aObstacleSeg, aResult, true ); + assert ( obstacleLine->LayersOverlap (shovedLine) ); - if( !rv ) + + if(rv == SH_OK) { - TRACEn( 2, "Shove failed" ); - return SH_INCOMPLETE; + if ( shovedLine->Marker() & MK_HEAD ) + m_newHead = *shovedLine; + + sanityCheck(obstacleLine, shovedLine); + m_currentNode->Replace (obstacleLine, shovedLine); + sanityCheck(obstacleLine, shovedLine); + + int rank = aCurrent->Rank(); + shovedLine->SetRank ( rank - 1 ); + + pushLine(shovedLine); } - aResult->GetLine().Simplify(); +#ifdef DEBUG + m_logger.NewGroup ("on-colliding-segment", m_iter); + m_logger.Log ( aObstacleSeg, 0, "obstacle-segment"); + m_logger.Log ( aCurrent, 1, "current-line"); + m_logger.Log ( obstacleLine, 2, "obstacle-line"); + m_logger.Log ( shovedLine, 3, "shoved-line"); +#endif - const SHAPE_LINE_CHAIN& sh_shoved = aResult->GetCLine(); - const SHAPE_LINE_CHAIN& sh_orig = aObstacle->GetCLine(); + return rv; +} - if( sh_shoved.SegmentCount() > 1 && sh_shoved.CPoint( 0 ) == sh_orig.CPoint( 0 ) - && sh_shoved.CPoint( -1 ) == sh_orig.CPoint( -1 ) ) - return SH_OK; - else if( !sh_shoved.SegmentCount() ) - return SH_NULL; - else +PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingLine( PNS_LINE *aCurrent, PNS_LINE *aObstacle ) +{ + PNS_LINE *shovedLine = cloneLine(aObstacle); + + ShoveStatus rv = processSingleLine ( aCurrent, aObstacle, shovedLine ); + + if(rv == SH_OK) + { + if ( shovedLine->Marker() & MK_HEAD ) + m_newHead = *shovedLine; + + sanityCheck(aObstacle,shovedLine); + m_currentNode->Replace( aObstacle, shovedLine ); + sanityCheck(aObstacle,shovedLine); + + int rank = aObstacle->Rank(); + shovedLine->SetRank ( rank ); + + pushLine(shovedLine); + + #ifdef DEBUG + m_logger.NewGroup ("on-colliding-line", m_iter); + m_logger.Log ( aObstacle, 0, "obstacle-line"); + m_logger.Log ( aCurrent, 1, "current-line"); + m_logger.Log ( shovedLine, 3, "shoved-line"); + #endif + + + } + + + return rv; +} + +PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingSolid( PNS_LINE *aCurrent, PNS_SOLID *aObstacleSolid ) +{ + PNS_WALKAROUND walkaround( m_currentNode, Router() ); + PNS_LINE* walkaroundLine = cloneLine(aCurrent); + + + if(aCurrent->EndsWithVia()) + { + PNS_VIA vh = aCurrent->Via(); + PNS_VIA *via = NULL; + PNS_JOINT *jtStart = m_currentNode->FindJoint ( vh.Pos(), aCurrent ); + + if(!jtStart) + return SH_INCOMPLETE; + + BOOST_FOREACH( PNS_ITEM *item, jtStart->LinkList() ) + if(item->OfKind(PNS_ITEM::VIA)) + { + via = (PNS_VIA *) item; + break; + } + + if( via && m_currentNode->CheckColliding(via, aObstacleSolid) ) + return onCollidingVia ( aObstacleSolid, via ); + } + + walkaround.SetSolidsOnly( true ); + walkaround.SetIterationLimit ( 8 ); // fixme: make configurable + + int currentRank = aCurrent->Rank(); + int nextRank; + + if (!Settings().JumpOverObstacles() ) + { + nextRank = currentRank + 10000; + walkaround.SetSingleDirection( false ); + } else { + nextRank = currentRank - 1; + walkaround.SetSingleDirection( true ); + } + + + if (walkaround.Route( *aCurrent, *walkaroundLine, false ) != PNS_WALKAROUND::DONE ) return SH_INCOMPLETE; + + walkaroundLine->ClearSegmentLinks(); + walkaroundLine->Unmark(); + walkaroundLine->Line().Simplify(); + + if(walkaroundLine->HasLoops()) + return SH_INCOMPLETE; + + if (aCurrent->Marker() & MK_HEAD) + { + walkaroundLine->Mark(MK_HEAD); + m_newHead = *walkaroundLine; + } + + + m_currentNode->Replace( aCurrent, walkaroundLine ); + walkaroundLine->SetRank ( nextRank ); + +#ifdef DEBUG + m_logger.NewGroup ("on-colliding-solid", m_iter); + m_logger.Log ( aObstacleSolid, 0, "obstacle-solid"); + m_logger.Log ( aCurrent, 1, "current-line"); + m_logger.Log ( walkaroundLine, 3, "walk-line"); +#endif + + popLine(); + pushLine(walkaroundLine); + + return SH_OK; } -bool PNS_SHOVE::reduceSpringback( PNS_LINE* aHead ) +bool PNS_SHOVE::reduceSpringback( const PNS_ITEMSET& aHeadSet ) { bool rv = false; while( !m_nodeStack.empty() ) { - SpringbackTag st_stack = m_nodeStack.back(); - bool tail_ok = true; + SpringbackTag spTag = m_nodeStack.back(); - if( !st_stack.node->CheckColliding( aHead ) && tail_ok ) + if( !spTag.node->CheckColliding( aHeadSet ) ) { rv = true; - delete st_stack.node; + + delete spTag.node; m_nodeStack.pop_back(); } else - break; + break; } return rv; } -bool PNS_SHOVE::pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost ) + +bool PNS_SHOVE::pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET& aHeadItems, const PNS_COST_ESTIMATOR& aCost ) { - BOX2I headBB = aHead->GetCLine().BBox(); SpringbackTag st; st.node = aNode; st.cost = aCost; - st.length = std::max( headBB.GetWidth(), headBB.GetHeight() );; + st.headItems = aHeadItems; m_nodeStack.push_back( st ); return true; } -const PNS_COST_ESTIMATOR PNS_SHOVE::TotalCost() const +PNS_SHOVE::ShoveStatus PNS_SHOVE::pushVia ( PNS_VIA *aVia, const VECTOR2I& aForce, int aCurrentRank ) { - if( m_nodeStack.empty() ) - return PNS_COST_ESTIMATOR(); - else - return m_nodeStack.back().cost; + + LinePairVec draggedLines; + VECTOR2I p0 ( aVia->Pos() ); + PNS_JOINT *jt = m_currentNode->FindJoint( p0, 1, aVia->Net() ); + PNS_VIA *pushedVia = aVia -> Clone(); + + pushedVia->SetPos( p0 + aForce ); + pushedVia->Mark( aVia->Marker() ) ; + + if(aVia->Marker() & MK_HEAD) + { + m_draggedVia = pushedVia; + } + + if(!jt) + { + TRACEn(1, "weird, can't find the center-of-via joint\n"); + return SH_INCOMPLETE; + } + + BOOST_FOREACH(PNS_ITEM *item, jt->LinkList() ) + { + if(item->OfKind( PNS_ITEM::SEGMENT )) + { + PNS_SEGMENT *seg = (PNS_SEGMENT *) item; + LinePair lp; + int segIndex; + + lp.first = assembleLine(seg, &segIndex); + + assert(segIndex == 0 || (segIndex == (lp.first->SegmentCount() - 1) )); + + if(segIndex == 0) + lp.first->Reverse(); + + lp.second = cloneLine( lp.first ); + lp.second->ClearSegmentLinks(); + lp.second->DragCorner( p0 + aForce, lp.second->CLine().Find( p0 )); + lp.second->AppendVia ( *pushedVia ); + draggedLines.push_back(lp); + } + } + + m_currentNode->Remove( aVia ); + m_currentNode->Add ( pushedVia ); + + if(aVia->BelongsTo(m_currentNode)) + delete aVia; + + pushedVia -> SetRank (aCurrentRank - 1); + +#ifdef DEBUG + m_logger.Log ( aVia, 0, "obstacle-via"); + m_logger.Log ( pushedVia, 1, "pushed-via"); +#endif + + BOOST_FOREACH( LinePair lp, draggedLines ) + { + if(lp.first->Marker() & MK_HEAD) + { + lp.second->Mark ( MK_HEAD ); + m_newHead = *lp.second; + } + + unwindStack(lp.first); + + if(lp.second->SegmentCount()) + { + m_currentNode->Replace ( lp.first, lp.second ); + lp.second->SetRank( aCurrentRank - 1); + pushLine(lp.second); + } else + m_currentNode->Remove(lp.first); + +#ifdef DEBUG + m_logger.Log ( lp.first, 2, "fan-pre"); + m_logger.Log ( lp.second, 3, "fan-post"); +#endif + } + + return SH_OK; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead ) +PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingVia (PNS_ITEM *aCurrent, PNS_VIA *aObstacleVia ) { - std::stack lineStack; - PNS_NODE* node, * parent; + int clearance = m_currentNode->GetClearance( aCurrent, aObstacleVia ) ; + LinePairVec draggedLines; + VECTOR2I p0 ( aObstacleVia->Pos() ); + bool colLine = false, colVia = false; + PNS_LINE *currentLine = NULL; + VECTOR2I mtvLine, mtvVia, mtv, mtvSolid; + int rank = -1; + + if( aCurrent->OfKind (PNS_ITEM::LINE)) + { + +#ifdef DEBUG + m_logger.NewGroup ("push-via-by-line", m_iter); + m_logger.Log(aCurrent, 4, "current"); +#endif + + currentLine = (PNS_LINE*) aCurrent; + colLine = CollideShapes( aObstacleVia->Shape(), currentLine->Shape(), clearance + currentLine->Width() / 2 + PNS_HULL_MARGIN, true, mtvLine ); + + if(currentLine->EndsWithVia()) + colVia = CollideShapes (currentLine->Via().Shape(), aObstacleVia->Shape(), clearance + PNS_HULL_MARGIN, true, mtvVia); + + if(!colLine && !colVia) + return SH_OK; + + if(colLine && colVia) + mtv = mtvVia.EuclideanNorm() > mtvLine.EuclideanNorm() ? mtvVia : mtvLine; + else if (colLine) + mtv = mtvLine; + else + mtv = mtvVia; + rank = currentLine->Rank(); + } + else if (aCurrent->OfKind(PNS_ITEM::SOLID)) + { + CollideShapes( aObstacleVia->Shape(), aCurrent->Shape(), clearance + PNS_HULL_MARGIN, true, mtvSolid ); + mtv = mtvSolid; + rank = aCurrent->Rank() + 10000; + } + + return pushVia ( aObstacleVia, mtv, rank ); +} + +PNS_SHOVE::ShoveStatus PNS_SHOVE::onReverseCollidingVia (PNS_LINE *aCurrent, PNS_VIA *aObstacleVia ) +{ + std::vector steps; + int n = 0; + PNS_LINE *cur = cloneLine( aCurrent ); + cur->ClearSegmentLinks(); + + PNS_JOINT *jt = m_currentNode->FindJoint ( aObstacleVia->Pos(), aObstacleVia ); + PNS_LINE *shoved = cloneLine( aCurrent ); + shoved->ClearSegmentLinks(); + + + cur->RemoveVia(); + unwindStack(aCurrent); + + BOOST_FOREACH( PNS_ITEM *item, jt->LinkList() ) + { + + if (item->OfKind(PNS_ITEM::SEGMENT) && item->LayersOverlap (aCurrent) ) + { + PNS_SEGMENT *seg = (PNS_SEGMENT *) item; + PNS_LINE *head = assembleLine( seg ); + + head->AppendVia( *aObstacleVia ); + + ShoveStatus st = processSingleLine ( head, cur, shoved ); + + if( st != SH_OK ) + { +#ifdef DEBUG + m_logger.NewGroup ("on-reverse-via-fail-shove", m_iter); + m_logger.Log ( aObstacleVia, 0, "the-via"); + m_logger.Log ( aCurrent, 1, "current-line"); + m_logger.Log ( shoved, 3, "shoved-line"); +#endif + + return st; + } + cur->SetShape ( shoved->CLine() ); + n++; + } + } + + if(!n) + { +#ifdef DEBUG + m_logger.NewGroup ("on-reverse-via-fail-lonevia", m_iter); + m_logger.Log ( aObstacleVia, 0, "the-via"); + m_logger.Log ( aCurrent, 1, "current-line"); +#endif + + PNS_LINE head(*aCurrent); + head.Line().Clear(); + head.AppendVia( *aObstacleVia ); + head.ClearSegmentLinks(); + + ShoveStatus st = processSingleLine ( &head, aCurrent, shoved ); + + if( st != SH_OK ) + return st; + + cur->SetShape ( shoved->CLine() ); + } + + if(aCurrent->EndsWithVia()) + shoved->AppendVia( aCurrent->Via( )); + +#ifdef DEBUG + m_logger.NewGroup ("on-reverse-via", m_iter); + m_logger.Log ( aObstacleVia, 0, "the-via"); + m_logger.Log ( aCurrent, 1, "current-line"); + m_logger.Log ( shoved, 3, "shoved-line"); +#endif + int currentRank = aCurrent->Rank(); + m_currentNode->Replace ( aCurrent, shoved ); + + pushLine(shoved); + shoved->SetRank( currentRank ); + + return SH_OK; +} + + +void PNS_SHOVE::unwindStack ( PNS_SEGMENT *seg ) +{ + for (std::vector::iterator i = m_lineStack.begin(); i != m_lineStack.end(); ) + { + if( (*i)->ContainsSegment ( seg ) ) + i = m_lineStack.erase( i ); + else + i++; + } + + for (std::vector::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ) + { + if( (*i)->ContainsSegment ( seg ) ) + i = m_optimizerQueue.erase( i ); + else + i++; + } +} + +void PNS_SHOVE::unwindStack ( PNS_ITEM *item ) +{ + if (item->OfKind(PNS_ITEM::SEGMENT)) + unwindStack(static_cast(item)); + else if (item->OfKind(PNS_ITEM::LINE)) { + PNS_LINE *l = static_cast( item ); + + if (!l->LinkedSegments()) + return; + + BOOST_FOREACH(PNS_SEGMENT *seg, *l->LinkedSegments() ) + unwindStack(seg); + } +} + +void PNS_SHOVE::pushLine (PNS_LINE *l) +{ + if(l->LinkCount() >= 0 && (l->LinkCount() != l->SegmentCount())) + assert(false); + + m_lineStack.push_back(l); + m_optimizerQueue.push_back(l); +} + +void PNS_SHOVE::popLine( ) +{ + PNS_LINE *l = m_lineStack.back(); + + for (std::vector::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ) + { + if( (*i) == l ) + { + i = m_optimizerQueue.erase( i ); + } else + i++; + } + + m_lineStack.pop_back(); +} + +PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveIteration(int aIter) +{ + PNS_LINE* currentLine = m_lineStack.back(); + PNS_NODE::OptObstacle nearest; + ShoveStatus st; + + PNS_ITEM::PnsKind search_order[] = { PNS_ITEM::SOLID, PNS_ITEM::VIA, PNS_ITEM::SEGMENT }; + + for(int i = 0; i < 3; i++) + { + nearest = m_currentNode->NearestObstacle( currentLine, search_order[i] ); + if(nearest) + break; + } + + if( !nearest ) + { + m_lineStack.pop_back(); + return SH_OK; + } + + PNS_ITEM *ni = nearest->item; + + unwindStack(ni); + + if( !ni->OfKind(PNS_ITEM::SOLID) && ni->Rank() >= 0 && ni->Rank() > currentLine->Rank() ) + { + switch( ni->Kind() ) + { + case PNS_ITEM::VIA: + { + PNS_VIA *revVia = (PNS_VIA *) ni; + TRACE( 2, "iter %d: reverse-collide-via", aIter ); + + if (currentLine->EndsWithVia() && m_currentNode->CheckColliding(¤tLine->Via(), revVia)) + { + st = SH_INCOMPLETE; + } else { + st = onReverseCollidingVia ( currentLine, revVia ); + } + + break; + } + + case PNS_ITEM::SEGMENT: + { + PNS_SEGMENT *seg = (PNS_SEGMENT* ) ni; + TRACE( 2, "iter %d: reverse-collide-segment ", aIter ); + PNS_LINE *revLine = assembleLine ( seg ); + + popLine(); + st = onCollidingLine( revLine, currentLine ); + pushLine(revLine); + break; + } + + default: + assert(false); + } + } else { // "forward" collisoins + switch( ni->Kind() ) + { + case PNS_ITEM::SEGMENT: + TRACE( 2, "iter %d: collide-segment ", aIter ); + st = onCollidingSegment( currentLine, (PNS_SEGMENT* ) ni ); + break; + + case PNS_ITEM::VIA: + TRACE( 2, "iter %d: shove-via ", aIter ); + st = onCollidingVia ( currentLine, (PNS_VIA *) ni ); + break; + + case PNS_ITEM::SOLID: + TRACE( 2, "iter %d: walk-solid ", aIter ); + st = onCollidingSolid ( currentLine, (PNS_SOLID *) ni ); + break; + + default: + break; + } + } + + return st; +} + +PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveMainLoop() +{ + ShoveStatus st = SH_OK; + + TRACE( 1, "ShoveStart [root: %d jts, current: %d jts]", m_root->JointCount() % + m_currentNode->JointCount() ); + + int iterLimit = Settings().ShoveIterationLimit(); + TIME_LIMIT timeLimit = Settings().ShoveTimeLimit(); + + m_iter = 0; + + timeLimit.Restart(); + + while( !m_lineStack.empty() ) + { + st = shoveIteration(m_iter); + + m_iter++; + + if( st == SH_INCOMPLETE || timeLimit.Expired() || m_iter >= iterLimit ) + { + st = SH_INCOMPLETE; + break; + } + } + + return st; +} + + +PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead ) +{ + ShoveStatus st = SH_OK; + + // empty head? nothing to shove... + if( ! aCurrentHead.SegmentCount() ) + return SH_INCOMPLETE; + + PNS_LINE* head = cloneLine ( &aCurrentHead ); + head->ClearSegmentLinks(); + + m_lineStack.clear(); + m_optimizerQueue.clear(); + m_newHead = OptLine(); + m_logger.Clear(); + + PNS_ITEMSET headSet ( cloneLine( &aCurrentHead ) ); + + reduceSpringback( headSet ); + + PNS_NODE *parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().node; + + m_currentNode = parent->Branch(); + m_currentNode->ClearRanks(); + m_currentNode->Add( head ); + + head->Mark ( MK_HEAD ); + head->SetRank ( 100000 ); + + m_logger.NewGroup ("initial", 0); + m_logger.Log ( head, 0, "head"); + PNS_VIA* headVia = NULL; - bool fail = false; - int iter = 0; - - PNS_LINE* head = aCurrentHead->Clone(); - - reduceSpringback( aCurrentHead ); - - parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().node; - node = parent->Branch(); - - lineStack.push( head ); - - // node->Add(tail); - node->Add( head ); if( head->EndsWithVia() ) { - headVia = head->GetVia().Clone(); - node->Add( headVia ); + headVia = head->Via().Clone(); + m_currentNode->Add( headVia ); + headVia->Mark( MK_HEAD ); + headVia->SetRank ( 100000 ); + m_logger.Log ( headVia, 0, "head-via"); + } - PNS_OPTIMIZER optimizer( node ); + pushLine (head); + st = shoveMainLoop(); + runOptimizer ( m_currentNode, head ); - optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_SEGMENTS | PNS_OPTIMIZER::SMART_PADS ); - optimizer.SetCollisionMask( -1 ); - PNS_NODE::OptObstacle nearest; - - optimizer.CacheStaticItem( head ); - - if( headVia ) - optimizer.CacheStaticItem( headVia ); - - TRACE( 1, "ShoveStart [root: %d jts, node: %d jts]", m_root->JointCount() % - node->JointCount() ); - - // PNS_ITEM *lastWalkSolid = NULL; - prof_counter totalRealTime; - - wxLongLong t_start = wxGetLocalTimeMillis(); - - while( !lineStack.empty() ) + if( m_newHead && st == SH_OK ) { - wxLongLong t_cur = wxGetLocalTimeMillis(); + st = SH_HEAD_MODIFIED; + Router()->DisplayDebugLine ( m_newHead->CLine(), 3, 20000 ); + } - if( (t_cur - t_start).ToLong() > ShoveTimeLimit ) - { - fail = true; - break; - } + m_currentNode->RemoveByMarker ( MK_HEAD ); - iter++; + TRACE( 1, "Shove status : %s after %d iterations", ((st == SH_OK || st == SH_HEAD_MODIFIED) ? "OK" : "FAILURE") % m_iter ); - if( iter > m_iterLimit ) - { - fail = true; - break; - } - - PNS_LINE* currentLine = lineStack.top(); - - prof_start( &totalRealTime ); - nearest = node->NearestObstacle( currentLine, PNS_ITEM::ANY ); - prof_end( &totalRealTime ); - - TRACE( 2, "t-nearestObstacle %lld us", totalRealTime.usecs() ); - - if( !nearest ) - { - if( lineStack.size() > 1 ) - { - PNS_LINE* original = lineStack.top(); - PNS_LINE optimized; - int r_start, r_end; - - original->GetAffectedRange( r_start, r_end ); - - TRACE( 1, "Iter %d optimize-line [range %d-%d, total %d]", - iter % r_start % r_end % original->GetCLine().PointCount() ); - // lastWalkSolid = NULL; - prof_start( &totalRealTime ); - - if( optimizer.Optimize( original, &optimized ) ) - { - node->Remove( original ); - optimizer.CacheRemove( original ); - node->Add( &optimized ); - - if( original->BelongsTo( node ) ) - delete original; - } - - prof_end( &totalRealTime ); - - TRACE( 2, "t-optimizeObstacle %lld us", totalRealTime.usecs() ); - } - - lineStack.pop(); - } - else - { - switch( nearest->item->GetKind() ) - { - case PNS_ITEM::SEGMENT: - { - TRACE( 1, "Iter %d shove-line", iter ); - - PNS_SEGMENT* pseg = static_cast(nearest->item); - PNS_LINE* collidingLine = node->AssembleLine( pseg ); - PNS_LINE* shovedLine = collidingLine->CloneProperties(); - - prof_start( &totalRealTime ); - ShoveStatus st = shoveSingleLine( node, currentLine, collidingLine, - *pseg, shovedLine ); - prof_end( &totalRealTime ); - - TRACE( 2, "t-shoveSingle %lld us", totalRealTime.usecs() ); - - if( st == SH_OK ) - { - node->Replace( collidingLine, shovedLine ); - - if( collidingLine->BelongsTo( node ) ) - delete collidingLine; - - optimizer.CacheRemove( collidingLine ); - lineStack.push( shovedLine ); - } - else - fail = true; - - // lastWalkSolid = NULL; - - break; - } // case SEGMENT - - case PNS_ITEM::SOLID: - case PNS_ITEM::VIA: - { - TRACE( 1, "Iter %d walkaround-solid [%p]", iter % nearest->item ); - - if( lineStack.size() == 1 ) - { - fail = true; - break; - } - -/* if(lastWalkSolid == nearest->item) - * { - * fail = true; - * break; - * }*/ - - PNS_WALKAROUND walkaround( node ); - PNS_LINE* walkaroundLine = currentLine->CloneProperties(); - - walkaround.SetSolidsOnly( true ); - walkaround.SetSingleDirection( true ); - - prof_start( &totalRealTime ); - walkaround.Route( *currentLine, *walkaroundLine, false ); - prof_end( &totalRealTime ); - - TRACE( 2, "t-walkSolid %lld us", totalRealTime.usecs() ); - - - node->Replace( currentLine, walkaroundLine ); - - if( currentLine->BelongsTo( node ) ) - delete currentLine; - - optimizer.CacheRemove( currentLine ); - lineStack.top() = walkaroundLine; - - // lastWalkSolid = nearest->item; - break; - } - - default: - break; - } // switch - - if( fail ) - break; - } - } - - node->Remove( head ); - delete head; - - if( headVia ) + if( st == SH_OK || st == SH_HEAD_MODIFIED ) { - node->Remove( headVia ); - delete headVia; - } - - TRACE( 1, "Shove status : %s after %d iterations", (fail ? "FAILED" : "OK") % iter ); - - if( !fail ) - { - pushSpringback( node, aCurrentHead, PNS_COST_ESTIMATOR() ); - return SH_OK; + pushSpringback( m_currentNode, headSet, PNS_COST_ESTIMATOR() ); } else { - delete node; - return SH_INCOMPLETE; + delete m_currentNode; + + m_currentNode = parent; + m_newHead = OptLine(); } + + return st; +} + + +PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveDraggingVia ( PNS_VIA *aVia, const VECTOR2I& aWhere, PNS_VIA **aNewVia ) +{ + ShoveStatus st = SH_OK; + + m_lineStack.clear(); + m_optimizerQueue.clear(); + m_newHead = OptLine(); + m_draggedVia = NULL; + + //reduceSpringback( aCurrentHead ); + + PNS_NODE *parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().node; + m_currentNode = parent->Branch(); + m_currentNode->ClearRanks(); + + aVia->Mark( MK_HEAD ); + + + st = pushVia ( aVia, (aWhere - aVia->Pos()), 0 ); + st = shoveMainLoop(); + runOptimizer ( m_currentNode, NULL ); + + if( st == SH_OK || st == SH_HEAD_MODIFIED ) + { + pushSpringback( m_currentNode, PNS_ITEMSET(), PNS_COST_ESTIMATOR() ); + } + else + { + delete m_currentNode; + m_currentNode = parent; + } + + if(aNewVia) + *aNewVia = m_draggedVia; + + return st; +} + +void PNS_SHOVE::runOptimizer ( PNS_NODE *node, PNS_LINE *head ) +{ + PNS_OPTIMIZER optimizer( node ); + int optFlags = 0, n_passes = 0, extend = 0; + + PNS_OPTIMIZATION_EFFORT effort = Settings().OptimizerEffort(); + + + switch(effort) + { + case OE_Low: + optFlags = PNS_OPTIMIZER::MERGE_OBTUSE; + n_passes = 1; + extend = 0; + break; + case OE_Medium: + optFlags = PNS_OPTIMIZER::MERGE_OBTUSE; + n_passes = 2; + extend = 1; + break; + case OE_Full: + optFlags = PNS_OPTIMIZER::MERGE_SEGMENTS; + n_passes = 2; + break; + default: + break; + } + + if(Settings().SmartPads()) + optFlags |= PNS_OPTIMIZER::SMART_PADS ; + + optimizer.SetEffortLevel( optFlags ); + optimizer.SetCollisionMask( PNS_ITEM::ANY ); + + for(int pass = 0; pass < n_passes; pass ++) + { + std::reverse ( m_optimizerQueue.begin(), m_optimizerQueue.end() ); + for(std::vector::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ++i) + { + PNS_LINE *line = *i; + + if( ! (line -> Marker() & MK_HEAD ) ) + { + if(effort == OE_Medium || effort == OE_Low ) + { + RANGE r = findShovedVertexRange ( line ); + + if (r.Defined()) + { + int start_v = std::max(0, r.MinV() - extend); + int end_v = std::min(line->PointCount() - 1 , r.MaxV() + extend ); + line->ClipVertexRange ( start_v, end_v ); + } + } + + PNS_LINE optimized; + + if( optimizer.Optimize( line, &optimized ) ) + { + node->Remove( line ); + line->SetShape(optimized.CLine()); + node->Add( line ); + } + } + } + } + + +} + +const RANGE PNS_SHOVE::findShovedVertexRange ( PNS_LINE *l ) +{ + RANGE r; + + for(int i = 0; i < l->SegmentCount(); i++) + { + PNS_SEGMENT *s = (*l->LinkedSegments())[i]; + PNS_JOINT *jt = m_root->FindJoint( s->Seg().A, s->Layer(), s->Net() ); + bool found = false; + + if(jt) + { + BOOST_FOREACH( PNS_ITEM *item, jt->LinkList() ) + { + if(item->OfKind(PNS_ITEM::SEGMENT)) + { + PNS_SEGMENT *s_old = (PNS_SEGMENT *) item; + + if( s_old->Net() == s->Net() && + s_old->Layer() == s->Layer() && + s_old->Seg().A == s->Seg().A && + s_old->Seg().B == s->Seg().B ) + { + found = true; + break; + } + } + } + } + + if(!found) + { + r.Grow(i); + r.Grow(i + 1); + } + } + return r; +} + +PNS_NODE* PNS_SHOVE::CurrentNode() +{ + return m_nodeStack.empty() ? m_root : m_nodeStack.back().node; +} + +const PNS_LINE PNS_SHOVE::NewHead() const +{ + assert(m_newHead); + return *m_newHead; +} + +void PNS_SHOVE::SetInitialLine ( PNS_LINE *aInitial ) +{ + m_root = m_root->Branch(); + m_root->Remove ( aInitial ); } diff --git a/pcbnew/router/pns_shove.h b/pcbnew/router/pns_shove.h index 581d2f49f9..d070e89790 100644 --- a/pcbnew/router/pns_shove.h +++ b/pcbnew/router/pns_shove.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_SHOVE_H @@ -25,61 +25,114 @@ #include #include "pns_optimizer.h" +#include "pns_routing_settings.h" +#include "pns_algo_base.h" +#include "pns_logger.h" +#include "range.h" class PNS_LINE; class PNS_NODE; class PNS_ROUTER; -class PNS_SHOVE +/** + * Class PNS_SHOVE + * + * The actual Push and Shove algorithm. + */ + +class PNS_SHOVE : public PNS_ALGO_BASE { public: - PNS_SHOVE( PNS_NODE* aWorld ); - ~PNS_SHOVE(); enum ShoveStatus { SH_OK = 0, SH_NULL, - SH_INCOMPLETE + SH_INCOMPLETE, + SH_HEAD_MODIFIED }; - ShoveStatus ShoveLines( PNS_LINE* aCurrentHead ); + PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER *aRouter ); + ~PNS_SHOVE(); - PNS_NODE* GetCurrentNode() + virtual PNS_LOGGER *Logger() { - return m_nodeStack.empty() ? m_root : m_nodeStack.back().node; + return &m_logger; } - const PNS_COST_ESTIMATOR TotalCost() const; + ShoveStatus ShoveLines( const PNS_LINE& aCurrentHead ); + ShoveStatus ShoveDraggingVia ( PNS_VIA *aVia, const VECTOR2I& aWhere, PNS_VIA **aNewVia ); - void Reset(); - void KillChildNodes(); + PNS_NODE* CurrentNode(); + + const PNS_LINE NewHead() const; + + void SetInitialLine ( PNS_LINE *aInitial ); private: - static const int ShoveTimeLimit = 3000; - - bool tryShove( PNS_NODE* aWorld, PNS_LINE* aTrack, PNS_LINE* aObstacle, - PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult, bool aInvertWinding ); - - ShoveStatus shoveSingleLine( PNS_NODE* aNode, PNS_LINE* aCurrent, PNS_LINE* aObstacle, - PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult ); - - bool reduceSpringback( PNS_LINE* aHead ); - bool pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost ); + typedef std::vector HullSet; + typedef boost::optional OptLine; + typedef std::pair LinePair; + typedef std::vector LinePairVec; struct SpringbackTag { int64_t length; int segments; VECTOR2I p; - PNS_NODE* node; + PNS_NODE *node; + PNS_ITEMSET headItems; PNS_COST_ESTIMATOR cost; }; - std::vector m_nodeStack; - PNS_NODE* m_root; - PNS_NODE* m_currentNode; - int m_iterLimit; + ShoveStatus processSingleLine(PNS_LINE *aCurrent, PNS_LINE* aObstacle, PNS_LINE *aShoved ); + ShoveStatus processHullSet ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved, const HullSet& hulls ); + + bool reduceSpringback( const PNS_ITEMSET &aHeadItems ); + bool pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET &aHeadItems, const PNS_COST_ESTIMATOR& aCost ); + + ShoveStatus walkaroundLoneVia ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved ); + bool checkBumpDirection ( PNS_LINE *aCurrent, PNS_LINE *aShoved ) const; + + ShoveStatus onCollidingLine( PNS_LINE *aCurrent, PNS_LINE *aObstacle ); + ShoveStatus onCollidingSegment( PNS_LINE *aCurrent, PNS_SEGMENT *aObstacleSeg ); + ShoveStatus onCollidingSolid( PNS_LINE *aCurrent, PNS_SOLID *aObstacleSolid ); + ShoveStatus onCollidingVia( PNS_ITEM *aCurrent, PNS_VIA *aObstacleVia ); + ShoveStatus onReverseCollidingVia( PNS_LINE *aCurrent, PNS_VIA *aObstacleVia ); + ShoveStatus pushVia ( PNS_VIA *aVia, const VECTOR2I& aForce, int aCurrentRank ); + + void unwindStack ( PNS_SEGMENT *seg ); + void unwindStack ( PNS_ITEM *item ); + + void runOptimizer ( PNS_NODE *node, PNS_LINE *head ); + + void pushLine ( PNS_LINE *l ); + void popLine(); + + const RANGE findShovedVertexRange ( PNS_LINE *l ); + + PNS_LINE *assembleLine ( const PNS_SEGMENT *aSeg, int *aIndex = NULL ); + PNS_LINE *cloneLine ( const PNS_LINE *aLine ); + + ShoveStatus shoveIteration(int aIter); + ShoveStatus shoveMainLoop(); + + std::vector m_nodeStack; + std::vector m_lineStack; + std::vector m_optimizerQueue; + std::vector m_gcItems; + + PNS_NODE* m_root; + PNS_NODE* m_currentNode; + PNS_LINE* m_currentHead; + PNS_LINE* m_collidingLine; + + OptLine m_newHead; + + PNS_LOGGER m_logger; + PNS_VIA* m_draggedVia; + + int m_iter; }; -#endif +#endif // __PNS_SHOVE_H diff --git a/pcbnew/router/pns_solid.cpp b/pcbnew/router/pns_solid.cpp index 807f9faa0b..da4fab064d 100644 --- a/pcbnew/router/pns_solid.cpp +++ b/pcbnew/router/pns_solid.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include @@ -30,13 +30,15 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness ) const { + int cl = aClearance + aWalkaroundThickness / 2; + switch( m_shape->Type() ) { case SH_RECT: { SHAPE_RECT* rect = static_cast( m_shape ); return OctagonalHull( rect->GetPosition(), rect->GetSize(), - aClearance + 1, 0.2 * aClearance ); + cl + 1, 0.2 * cl ); } case SH_CIRCLE: @@ -44,7 +46,12 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness SHAPE_CIRCLE* circle = static_cast( m_shape ); int r = circle->GetRadius(); return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ), - aClearance + 1, 0.52 * (r + aClearance) ); + cl + 1, 0.52 * (r + cl) ); + } + case SH_SEGMENT: + { + SHAPE_SEGMENT *seg = static_cast ( m_shape ); + return SegmentHull (*seg, aClearance, aWalkaroundThickness ); } default: @@ -55,10 +62,8 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness } -PNS_ITEM* PNS_SOLID::Clone() const +PNS_ITEM* PNS_SOLID::Clone ( ) const { - // solids are never cloned as the shove algorithm never moves them - assert( false ); - - return NULL; + PNS_ITEM *solid = new PNS_SOLID ( *this ); + return solid; } diff --git a/pcbnew/router/pns_solid.h b/pcbnew/router/pns_solid.h index b6f38a2851..d1e725a461 100644 --- a/pcbnew/router/pns_solid.h +++ b/pcbnew/router/pns_solid.h @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_SOLID_H @@ -42,9 +42,16 @@ public: delete m_shape; } - PNS_ITEM* Clone() const; + PNS_SOLID( const PNS_SOLID& aSolid ) : + PNS_ITEM ( aSolid ) + { + m_shape = aSolid.m_shape->Clone(); + m_pos = aSolid.m_pos; + } + + PNS_ITEM* Clone( ) const; - const SHAPE* GetShape() const { return m_shape; } + const SHAPE* Shape() const { return m_shape; } const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const; @@ -56,18 +63,29 @@ public: m_shape = shape; } - const VECTOR2I& GetCenter() const + const VECTOR2I& Pos() const { - return m_center; + return m_pos; } - void SetCenter( const VECTOR2I& aCenter ) + void SetPos( const VECTOR2I& aCenter ) { - m_center = aCenter; + m_pos = aCenter; } + virtual VECTOR2I Anchor(int n) const + { + return m_pos; + } + + virtual int AnchorCount() const + { + return 1; + } + + private: - VECTOR2I m_center; + VECTOR2I m_pos; SHAPE* m_shape; }; diff --git a/pcbnew/router/pns_utils.cpp b/pcbnew/router/pns_utils.cpp index c787753534..e1042e6437 100644 --- a/pcbnew/router/pns_utils.cpp +++ b/pcbnew/router/pns_utils.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,13 +15,15 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include "pns_utils.h" #include "pns_line.h" #include "pns_router.h" +#include + const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize, int aClearance, @@ -42,3 +44,51 @@ const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, return s; } + +const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, + int aClearance, + int aWalkaroundThickness ) +{ + int d = aSeg.GetWidth() / 2 + aClearance + aWalkaroundThickness / 2 + HULL_MARGIN; + int x = (int)( 2.0 / ( 1.0 + M_SQRT2 ) * d ); + + const VECTOR2I a = aSeg.GetSeg().A; + const VECTOR2I b = aSeg.GetSeg().B; + + VECTOR2I dir = b - a; + VECTOR2I p0 = dir.Perpendicular().Resize( d ); + VECTOR2I ds = dir.Perpendicular().Resize( x / 2 ); + VECTOR2I pd = dir.Resize( x / 2 ); + VECTOR2I dp = dir.Resize( d ); + + SHAPE_LINE_CHAIN s; + + s.SetClosed( true ); + + s.Append( b + p0 + pd ); + s.Append( b + dp + ds ); + s.Append( b + dp - ds ); + s.Append( b - p0 + pd ); + s.Append( a - p0 - pd ); + s.Append( a - dp - ds ); + s.Append( a - dp + ds ); + s.Append( a + p0 - pd ); + + // make sure the hull outline is always clockwise + if( s.CSegment( 0 ).Side( a ) < 0 ) + return s.Reverse(); + else + return s; +} + +SHAPE_RECT ApproximateSegmentAsRect( const SHAPE_SEGMENT& aSeg ) +{ + SHAPE_RECT r; + + VECTOR2I delta ( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 ); + VECTOR2I p0 ( aSeg.GetSeg().A - delta ); + VECTOR2I p1 ( aSeg.GetSeg().B + delta ); + + return SHAPE_RECT ( std::min(p0.x, p1.x), std::min(p0.y, p1.y), + std::abs(p1.x - p0.x), std::abs(p1.y - p0.y )); +} \ No newline at end of file diff --git a/pcbnew/router/pns_utils.h b/pcbnew/router/pns_utils.h index 655720f1f1..50bfc90179 100644 --- a/pcbnew/router/pns_utils.h +++ b/pcbnew/router/pns_utils.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_UTILS_H @@ -23,10 +23,20 @@ #include #include +#include +#include + +#define HULL_MARGIN 10 /** Various utility functions */ const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize, int aClearance, int aChamfer ); +const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, + int aClearance, + int aWalkaroundThickness ); + +SHAPE_RECT ApproximateSegmentAsRect( const SHAPE_SEGMENT& aSeg ); + #endif // __PNS_UTILS_H diff --git a/pcbnew/router/pns_via.cpp b/pcbnew/router/pns_via.cpp index 30666d78ab..037bb16e99 100644 --- a/pcbnew/router/pns_via.cpp +++ b/pcbnew/router/pns_via.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,98 +15,16 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include "pns_via.h" #include "pns_node.h" #include "pns_utils.h" +#include "pns_router.h" #include -static bool Circle2Circle( VECTOR2I p1, VECTOR2I p2, int r1, int r2, VECTOR2I& force ) -{ - int mindist = r1 + r2; - VECTOR2I delta = p2 - p1; - int dist = delta.EuclideanNorm(); - - if( dist >= mindist ) - return false; - - force = delta.Resize( abs( mindist - dist ) + 1 ); - return true; -}; - -static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECTOR2I& force ) -{ - VECTOR2I vts[] = - { - VECTOR2I( rp0.x, rp0.y ), - VECTOR2I( rp0.x, rp0.y + rsize.y ), - VECTOR2I( rp0.x + rsize.x, rp0.y + rsize.y ), - VECTOR2I( rp0.x + rsize.x, rp0.y ), - VECTOR2I( rp0.x, rp0.y ) - }; - - int dist = INT_MAX; - VECTOR2I nearest; - - for( int i = 0; i < 4; i++ ) - { - SEG s( vts[i], vts[i + 1] ); - - VECTOR2I pn = s.NearestPoint( cc ); - - int d = (pn - cc).EuclideanNorm(); - - if( d < dist ) - { - nearest = pn; - dist = d; - } - } - - bool inside = cc.x >= rp0.x && cc.x <= (rp0.x + rsize.x) - && cc.y >= rp0.y && cc.y <= (rp0.y + rsize.y); - - VECTOR2I delta = cc - nearest; - - if( dist >= cr && !inside ) - return false; - - if( inside ) - force = -delta.Resize( abs( cr + dist ) + 1 ); - else - force = delta.Resize( abs( cr - dist ) + 1 ); - - return true; -}; - - -static bool ShPushoutForce( const SHAPE* shape, VECTOR2I p, int r, VECTOR2I& force, int clearance ) -{ - switch( shape->Type() ) - { - case SH_CIRCLE: - { - const SHAPE_CIRCLE* cir = static_cast(shape); - return Circle2Circle( cir->GetCenter(), p, cir->GetRadius(), r + clearance + 1, force ); - } - - case SH_RECT: - { - const SHAPE_RECT* rect = static_cast(shape); - return Rect2Circle( rect->GetPosition(), rect->GetSize(), p, r + clearance + 1, force ); - } - - default: - return false; - } - - return false; -} - - bool PNS_VIA::PushoutForce( PNS_NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForce, @@ -115,30 +33,31 @@ bool PNS_VIA::PushoutForce( PNS_NODE* aNode, { int iter = 0; PNS_VIA mv( *this ); - VECTOR2I force, totalForce; + VECTOR2I force, totalForce, force2; + while( iter < aMaxIterations ) { - PNS_NODE::OptObstacle obs = aNode->CheckColliding( &mv, - aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY ); + + PNS_NODE::OptObstacle obs = aNode->CheckColliding( &mv, aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY ); if( !obs ) break; int clearance = aNode->GetClearance( obs->item, &mv ); - if( iter > 10 ) + if( iter > aMaxIterations / 2 ) { - VECTOR2I l = -aDirection.Resize( m_diameter / 4 ); + VECTOR2I l = aDirection.Resize( m_diameter / 2 ); totalForce += l; - mv.SetPos( mv.GetPos() + l ); + mv.SetPos( mv.Pos() + l ); } - if( ShPushoutForce( obs->item->GetShape(), mv.GetPos(), mv.GetDiameter() / 2, force, - clearance ) ) - { - totalForce += force; - mv.SetPos( mv.GetPos() + force ); + bool col = CollideShapes( obs->item->Shape(), mv.Shape(), clearance, true, force2 ); + + if(col) { + totalForce += force2; + mv.SetPos( mv.Pos() + force2 ); } @@ -155,7 +74,26 @@ bool PNS_VIA::PushoutForce( PNS_NODE* aNode, const SHAPE_LINE_CHAIN PNS_VIA::Hull( int aClearance, int aWalkaroundThickness ) const { + int cl = (aClearance + aWalkaroundThickness / 2); + return OctagonalHull( m_pos - VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter, - m_diameter ), aClearance + 1, (2 * aClearance + m_diameter) * 0.26 ); + m_diameter ), cl + 1, (2 * cl + m_diameter) * 0.26 ); +} + +PNS_VIA* PNS_VIA::Clone ( ) const +{ + PNS_VIA* v = new PNS_VIA(); + + v->SetNet( Net() ); + v->SetLayers( Layers() ); + v->m_pos = m_pos; + v->m_diameter = m_diameter; + v->m_drill = m_drill; + v->m_owner = NULL; + v->m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 ); + v->m_rank = m_rank; + v->m_marker = m_marker; + + return v; } diff --git a/pcbnew/router/pns_via.h b/pcbnew/router/pns_via.h index 1a0fc2a2bd..684116b6da 100644 --- a/pcbnew/router/pns_via.h +++ b/pcbnew/router/pns_via.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_VIA_H @@ -45,16 +45,21 @@ public: }; - PNS_VIA( const PNS_VIA& b ) : PNS_ITEM( VIA ) + PNS_VIA( const PNS_VIA& b ) : + PNS_ITEM( VIA ) { - SetNet( b.GetNet() ); - SetLayers( b.GetLayers() ); + SetNet( b.Net() ); + SetLayers( b.Layers() ); m_pos = b.m_pos; m_diameter = b.m_diameter; m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 ); + m_marker = b.m_marker; + m_rank = b.m_rank; + m_owner = b.m_owner; + m_drill = b.m_drill; } - const VECTOR2I& GetPos() const + const VECTOR2I& Pos() const { return m_pos; } @@ -65,7 +70,7 @@ public: m_shape.SetCenter( aPos ); } - int GetDiameter() const + int Diameter() const { return m_diameter; } @@ -76,7 +81,7 @@ public: m_shape.SetRadius( m_diameter / 2 ); } - int GetDrill() const + int Drill() const { return m_drill; } @@ -92,25 +97,24 @@ public: bool aSolidsOnly = true, int aMaxIterations = 10 ); - const SHAPE* GetShape() const + const SHAPE* Shape() const { return &m_shape; } - PNS_VIA* Clone() const - { - PNS_VIA* v = new PNS_VIA(); - - v->SetNet( GetNet() ); - v->SetLayers( GetLayers() ); - v->m_pos = m_pos; - v->m_diameter = m_diameter; - v->m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 ); - - return v; - } + PNS_VIA* Clone ( ) const; const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const; + + virtual VECTOR2I Anchor(int n) const + { + return m_pos; + } + + virtual int AnchorCount() const + { + return 1; + } private: diff --git a/pcbnew/router/pns_walkaround.cpp b/pcbnew/router/pns_walkaround.cpp index 185def64d2..5be937e489 100644 --- a/pcbnew/router/pns_walkaround.cpp +++ b/pcbnew/router/pns_walkaround.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include @@ -38,8 +38,8 @@ void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath ) PNS_NODE::OptObstacle PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath ) { - return m_world->NearestObstacle( &aPath, - m_solids_only ? (PNS_ITEM::SOLID | PNS_ITEM::VIA) : PNS_ITEM::ANY ); + return m_world->NearestObstacle( &aPath, m_item_mask); + } @@ -55,33 +55,42 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath, SHAPE_LINE_CHAIN path_pre[2], path_walk[2], path_post[2]; - VECTOR2I last = aPath.GetCLine().CPoint( -1 ); + VECTOR2I last = aPath.CPoint( -1 );; + if( ( current_obs->hull ).PointInside( last ) ) { m_recursiveBlockageCount++; if( m_recursiveBlockageCount < 3 ) - aPath.GetLine().Append( current_obs->hull.NearestPoint( last ) ); + aPath.Line().Append( current_obs->hull.NearestPoint( last ) ); else { aPath = aPath.ClipToNearestObstacle( m_world ); - return STUCK; + return DONE; } } - aPath.NewWalkaround( current_obs->hull, path_pre[0], path_walk[0], + aPath.Walkaround( current_obs->hull, path_pre[0], path_walk[0], path_post[0], aWindingDirection ); - aPath.NewWalkaround( current_obs->hull, path_pre[1], path_walk[1], + aPath.Walkaround( current_obs->hull, path_pre[1], path_walk[1], path_post[1], !aWindingDirection ); - +#ifdef DEBUG + m_logger.NewGroup (aWindingDirection ? "walk-cw" : "walk-ccw", m_iteration); + m_logger.Log ( &path_walk[0], 0, "path-walk"); + m_logger.Log ( &path_pre[0], 1, "path-pre"); + m_logger.Log ( &path_post[0], 4, "path-post"); + m_logger.Log ( ¤t_obs->hull, 2, "hull"); + m_logger.Log ( current_obs->item, 3, "item"); +#endif + int len_pre = path_walk[0].Length(); int len_alt = path_walk[1].Length(); - + PNS_LINE walk_path( aPath, path_walk[1] ); - bool alt_collides = m_world->CheckColliding( &walk_path, - m_solids_only ? PNS_ITEM::SOLID : PNS_ITEM::ANY ); + bool alt_collides = m_world->CheckColliding( &walk_path, m_item_mask ); + SHAPE_LINE_CHAIN pnew; @@ -126,6 +135,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial WalkaroundStatus s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS; SHAPE_LINE_CHAIN best_path; + start( aInitialPath ); m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle( aInitialPath ); @@ -143,9 +153,10 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial if( ( s_cw == DONE && s_ccw == DONE ) || ( s_cw == STUCK && s_ccw == STUCK ) ) { - int len_cw = path_cw.GetCLine().Length(); - int len_ccw = path_ccw.GetCLine().Length(); + int len_cw = path_cw.CLine().Length(); + int len_ccw = path_ccw.CLine().Length(); + if( m_forceLongerPath ) aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw); else @@ -166,11 +177,11 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial m_iteration++; } - + if( m_iteration == m_iteration_limit ) { - int len_cw = path_cw.GetCLine().Length(); - int len_ccw = path_ccw.GetCLine().Length(); + int len_cw = path_cw.CLine().Length(); + int len_ccw = path_ccw.CLine().Length(); if( m_forceLongerPath ) @@ -185,7 +196,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial // int len_ccw = path_ccw.GetCLine().Length(); bool found = false; - SHAPE_LINE_CHAIN l = aWalkPath.GetCLine(); + SHAPE_LINE_CHAIN l = aWalkPath.CLine(); for( int i = 0; i < l.SegmentCount(); i++ ) { @@ -198,7 +209,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial if( dist_n <= dist_a && dist_n < dist_b ) { - // PNSDisplayDebugLine( l, 3 ); l.Remove( i + 1, -1 ); l.Append( nearest ); l.Simplify(); @@ -214,13 +224,21 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial } } - aWalkPath.SetWorld( m_world ); - aWalkPath.GetLine().Simplify(); + aWalkPath.Line().Simplify(); + if(aWalkPath.SegmentCount() < 1) + return STUCK; + + if(aWalkPath.CPoint(-1) != aInitialPath.CPoint(-1)) + return STUCK; + + if(aWalkPath.CPoint(0) != aInitialPath.CPoint(0)) + return STUCK; + WalkaroundStatus st = s_ccw == DONE || s_cw == DONE ? DONE : STUCK; if( aOptimize && st == DONE ) - PNS_OPTIMIZER::Optimize( &aWalkPath, PNS_OPTIMIZER::MERGE_OBTUSE, m_world ); + PNS_OPTIMIZER::Optimize( &aWalkPath, PNS_OPTIMIZER::MERGE_OBTUSE, m_world ); return st; } diff --git a/pcbnew/router/pns_walkaround.h b/pcbnew/router/pns_walkaround.h index 609b80d2ce..0a87213a22 100644 --- a/pcbnew/router/pns_walkaround.h +++ b/pcbnew/router/pns_walkaround.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __PNS_WALKAROUND_H @@ -23,19 +23,26 @@ #include "pns_line.h" #include "pns_node.h" +#include "pns_router.h" +#include "pns_logger.h" +#include "pns_algo_base.h" -class PNS_WALKAROUND +class PNS_WALKAROUND : public PNS_ALGO_BASE { static const int DefaultIterationLimit = 50; public: - PNS_WALKAROUND( PNS_NODE* aWorld ) : - m_world( aWorld ), m_iteration_limit( DefaultIterationLimit ) + PNS_WALKAROUND( PNS_NODE* aWorld, PNS_ROUTER *aRouter ) : + PNS_ALGO_BASE ( aRouter ), + m_world( aWorld ), + m_iteration_limit( DefaultIterationLimit ) { m_forceSingleDirection = false; m_forceLongerPath = false; m_cursorApproachMode = false; + m_item_mask = PNS_ITEM::ANY; }; + ~PNS_WALKAROUND() {}; enum WalkaroundStatus @@ -57,13 +64,22 @@ public: void SetSolidsOnly( bool aSolidsOnly ) { - m_solids_only = aSolidsOnly; + if(aSolidsOnly) + m_item_mask = PNS_ITEM::SOLID; + else + m_item_mask = PNS_ITEM::ANY; + } + + void SetItemMask ( int aMask ) + { + m_item_mask = aMask; } void SetSingleDirection( bool aForceSingleDirection ) { m_forceSingleDirection = aForceSingleDirection; - m_forceLongerPath = true; + m_forceLongerPath = aForceSingleDirection; + //printf("FSD %d FPD %d\n", m_forceSingleDirection?1:0, m_forceLongerPath ? 1: 0); } void SetApproachCursor( bool aEnabled, const VECTOR2I& aPos ) @@ -75,6 +91,10 @@ public: WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, bool aOptimize = true ); + virtual PNS_LOGGER *Logger() { + return &m_logger; + } + private: void start( const PNS_LINE& aInitialPath ); @@ -86,12 +106,13 @@ private: int m_recursiveBlockageCount; int m_iteration; int m_iteration_limit; - bool m_solids_only; + int m_item_mask; bool m_forceSingleDirection, m_forceLongerPath; bool m_cursorApproachMode; VECTOR2I m_cursorPos; PNS_NODE::OptObstacle m_currentObstacle[2]; bool m_recursiveCollision[2]; + PNS_LOGGER m_logger; }; #endif // __PNS_WALKAROUND_H diff --git a/pcbnew/router/range.h b/pcbnew/router/range.h new file mode 100644 index 0000000000..8409731926 --- /dev/null +++ b/pcbnew/router/range.h @@ -0,0 +1,91 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#ifndef __RANGE_H +#define __RANGE_H + +template class RANGE { + + public: + RANGE (T aMin, T aMax) : + m_min(aMin), + m_max(aMax), + m_defined(true) {} + + RANGE (): + m_defined (false) {}; + + T MinV() const + { + return m_min; + } + + T MaxV() const + { + return m_max; + } + + void Set ( T aMin, T aMax ) const + { + m_max = aMax; + m_min = aMin; + } + + void Grow ( T value ) + { + if(!m_defined) + { + m_min = value; + m_max = value; + m_defined = true; + } else { + m_min = std::min(m_min, value); + m_max = std::max(m_max, value); + } + } + + bool Inside ( const T& value ) const + { + if(!m_defined) + return true; + + return value >= m_min && value <= m_max; + } + + bool Overlaps ( const RANGE &aOther ) const + { + if(!m_defined || !aOther.m_defined) + return true; + + return m_max >= aOther.m_min && m_min <= aOther.m_max; + } + + bool Defined() const + { + return m_defined; + } + + private: + T m_min, m_max; + bool m_defined; + +}; + +#endif \ No newline at end of file diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp index 8ce1db4721..3287082c3c 100644 --- a/pcbnew/router/router_preview_item.cpp +++ b/pcbnew/router/router_preview_item.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,13 +15,16 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #include +#include + #include "class_track.h" #include +#include #include "router_preview_item.h" @@ -34,9 +37,12 @@ using namespace KIGFX; ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem, VIEW_GROUP* aParent ) : EDA_ITEM( NOT_USED ) { - m_Flags = 0; m_parent = aParent; - m_layer = DRAW_N; + + m_shape = NULL; + m_clearance = -1; + m_originLayer = m_layer = ITEM_GAL_LAYER ( GP_OVERLAY ); + if( aItem ) Update( aItem ); @@ -50,62 +56,73 @@ ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM() void ROUTER_PREVIEW_ITEM::Update( const PNS_ITEM* aItem ) { - m_layer = aItem->GetLayers().Start(); - m_color = getLayerColor( m_layer ); + m_originLayer = aItem->Layers().Start(); + + assert (m_originLayer >= 0); + + m_layer = m_originLayer; + m_color = getLayerColor( m_originLayer ); m_color.a = 0.8; - - switch( aItem->GetKind() ) + m_depth = BaseOverlayDepth - aItem->Layers().Start(); + + m_shape = aItem->Shape()->Clone(); + + switch( aItem->Kind() ) { - case PNS_ITEM::LINE: - m_type = PR_LINE; - m_width = static_cast(aItem)->GetWidth(); - m_line = *static_cast( aItem->GetShape() ); - break; + case PNS_ITEM::LINE: + m_type = PR_SHAPE; + m_width = ((PNS_LINE *) aItem)->Width(); + + break; - case PNS_ITEM::SEGMENT: - m_type = PR_LINE; - m_width = static_cast(aItem)->GetWidth(); - m_line = *static_cast( aItem->GetShape() ); - break; + case PNS_ITEM::SEGMENT: + { + PNS_SEGMENT *seg = (PNS_SEGMENT *)aItem; + m_type = PR_SHAPE; + m_width = seg->Width(); + break; + } - case PNS_ITEM::VIA: - m_type = PR_VIA; - m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 ); - m_width = static_cast(aItem)->GetDiameter(); - m_viaCenter = static_cast(aItem)->GetPos(); - break; + case PNS_ITEM::VIA: + m_type = PR_SHAPE; + m_width = 0; + m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 ); + m_depth = ViaOverlayDepth; + break; + + case PNS_ITEM::SOLID: + m_type = PR_SHAPE; + m_width = 0; + break; default: break; } + if(aItem->Marker() & MK_VIOLATION) + m_color = COLOR4D (0, 1, 0, 1); + + if(aItem->Marker() & MK_HEAD) + m_color.Brighten(0.7); + ViewSetVisible( true ); ViewUpdate( GEOMETRY | APPEARANCE ); } - -void ROUTER_PREVIEW_ITEM::MarkAsHead() -{ - if( m_type != PR_VIA ) - m_color.Saturate( 1.0 ); -} - - const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const { BOX2I bbox; switch( m_type ) { - case PR_LINE: - bbox = m_line.BBox(); + case PR_SHAPE: + bbox = m_shape->BBox(); bbox.Inflate( m_width / 2 ); return bbox; - case PR_VIA: - bbox = BOX2I( m_viaCenter, VECTOR2I( 0, 0 ) ); - bbox.Inflate( m_width / 2 ); + case PR_POINT: + bbox = BOX2I ( m_pos - VECTOR2I(100000, 100000), VECTOR2I( 200000, 200000 )); return bbox; default: @@ -115,76 +132,124 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const return bbox; } +void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN &l, KIGFX::GAL* aGal ) const +{ + for( int s = 0; s < l.SegmentCount(); s++ ) + aGal->DrawLine( l.CSegment( s ).A, l.CSegment( s ).B ); + if( l.IsClosed() ) + aGal->DrawLine( l.CSegment( -1 ).B, l.CSegment( 0 ).A ); +} void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const { - switch( m_type ) + //col.Brighten(0.7); + aGal->SetLayerDepth( m_depth ); + + if(m_type == PR_SHAPE) { - case PR_LINE: - aGal->SetLayerDepth( -100.0 ); aGal->SetLineWidth( m_width ); aGal->SetStrokeColor( m_color ); - aGal->SetIsStroke( true ); - aGal->SetIsFill( false ); - - for( int s = 0; s < m_line.SegmentCount(); s++ ) - aGal->DrawLine( m_line.CSegment( s ).A, m_line.CSegment( s ).B ); - - if( m_line.IsClosed() ) - aGal->DrawLine( m_line.CSegment( -1 ).B, m_line.CSegment( 0 ).A ); - break; - - case PR_VIA: - aGal->SetLayerDepth( -101.0 ); - aGal->SetIsStroke( false ); - aGal->SetIsFill( true ); aGal->SetFillColor( m_color ); - aGal->DrawCircle( m_viaCenter, m_width / 2 ); - break; + aGal->SetIsStroke( m_width ? true : false ); + aGal->SetIsFill( true ); - default: - break; + + if(!m_shape) + return; + + switch( m_shape->Type() ) + { + case SH_LINE_CHAIN: + { + const SHAPE_LINE_CHAIN *l = (const SHAPE_LINE_CHAIN *) m_shape; + drawLineChain(*l, aGal); + break; + } + + case SH_SEGMENT: + { + const SHAPE_SEGMENT *s = (const SHAPE_SEGMENT *) m_shape; + aGal->DrawLine( s->GetSeg().A, s->GetSeg().B ); + + if(m_clearance > 0) + { + aGal->SetLayerDepth ( ClearanceOverlayDepth ); + aGal->SetStrokeColor ( COLOR4D( DARKDARKGRAY )); + aGal->SetLineWidth( m_width + 2 * m_clearance ); + aGal->DrawLine( s->GetSeg().A, s->GetSeg().B ); + + } + + break; + } + + case SH_CIRCLE: + { + const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE *) m_shape; + aGal->DrawCircle( c->GetCenter(), c->GetRadius() ); + + if(m_clearance > 0) + { + aGal->SetLayerDepth ( ClearanceOverlayDepth ); + aGal->SetFillColor ( COLOR4D( DARKDARKGRAY )); + aGal->SetIsStroke( false ); + aGal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance ); + } + + break; + } + + case SH_RECT: + { + const SHAPE_RECT *r = (const SHAPE_RECT *) m_shape; + aGal->DrawRectangle (r->GetPosition(), r->GetPosition() + r->GetSize()); + + if(m_clearance > 0) + { + aGal->SetLayerDepth ( ClearanceOverlayDepth ); + VECTOR2I p0 (r -> GetPosition() ), s ( r->GetSize() ); + aGal->SetStrokeColor ( COLOR4D( DARKDARKGRAY )); + aGal->SetIsStroke( true ); + aGal->SetLineWidth ( 2 * m_clearance ); + aGal->DrawLine( p0, VECTOR2I(p0.x + s.x, p0.y) ); + aGal->DrawLine( p0, VECTOR2I(p0.x, p0.y + s.y) ); + aGal->DrawLine( p0 + s , VECTOR2I(p0.x + s.x, p0.y) ); + aGal->DrawLine( p0 + s, VECTOR2I(p0.x, p0.y + s.y) ); + } + + break; + } + } } } -void ROUTER_PREVIEW_ITEM::DebugLine( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle ) +void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle ) { -#if 0 - m_line = aLine; + + m_originLayer = m_layer = 0; m_width = aWidth; m_color = assignColor( aStyle ); + m_type = PR_SHAPE; + m_depth = -2047; + m_shape = aLine.Clone(); - - m_type = PR_LINE; + ViewSetVisible(true); ViewUpdate( GEOMETRY | APPEARANCE ); -#endif + } - -void ROUTER_PREVIEW_ITEM::DebugBox( const BOX2I& aBox, int aStyle ) +void ROUTER_PREVIEW_ITEM::Point( const VECTOR2I& aPos, int aStyle ) { -#if 0 - assert( false ); +} - m_line.Clear(); - m_line.Append( aBox.GetX(), aBox.GetY() ); - m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight() ); - m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight() ); - m_line.Append( aBox.GetX(), aBox.GetY() + aBox.GetHeight() ); - m_line.SetClosed( true ); - m_width = 20000; - m_color = assignColor( aStyle ); - m_type = PR_LINE; - ViewUpdate( GEOMETRY | APPEARANCE ); -#endif +void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle ) +{ } const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const { - // assert (m_view != NULL); - PCB_RENDER_SETTINGS* settings = static_cast ( m_parent->GetView()->GetPainter()->GetSettings() ); @@ -202,10 +267,10 @@ const COLOR4D ROUTER_PREVIEW_ITEM::assignColor( int aStyle ) const color = COLOR4D( 0, 1, 0, 1 ); break; case 1: - color = COLOR4D( 1, 0, 0, 0.3 ); break; + color = COLOR4D( 1, 0, 0, 1 ); break; case 2: - color = COLOR4D( 1, 0.5, 0.5, 1 ); break; + color = COLOR4D( 1, 1, 0, 1 ); break; case 3: color = COLOR4D( 0, 0, 1, 1 ); break; @@ -220,9 +285,11 @@ const COLOR4D ROUTER_PREVIEW_ITEM::assignColor( int aStyle ) const color = COLOR4D( 0, 1, 1, 1 ); break; case 32: - color = COLOR4D( 0, 0, 1, 0.5 ); break; + color = COLOR4D( 0, 0, 1, 1 ); break; default: + color = COLOR4D( 0.4, 0.4, 0.4, 1 ); break; + break; } diff --git a/pcbnew/router/router_preview_item.h b/pcbnew/router/router_preview_item.h index 058c47f816..514b21dcea 100644 --- a/pcbnew/router/router_preview_item.h +++ b/pcbnew/router/router_preview_item.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -15,7 +15,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __ROUTER_PREVIEW_ITEM_H @@ -46,24 +46,32 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM public: enum ItemType { - PR_VIA, - PR_LINE, - PR_STUCK_MARKER - }; - - enum ItemFlags - { - PR_SUGGESTION = 1 + PR_STUCK_MARKER = 0, + PR_POINT, + PR_SHAPE }; + ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem = NULL, KIGFX::VIEW_GROUP* aParent = NULL ); ~ROUTER_PREVIEW_ITEM(); void Update( const PNS_ITEM* aItem ); void StuckMarker( VECTOR2I& aPosition ); - void DebugLine( const SHAPE_LINE_CHAIN& aLine, int aWidth = 0, int aStyle = 0 ); - void DebugBox( const BOX2I& aBox, int aStyle = 0 ); + + void Line( const SHAPE_LINE_CHAIN& aLine, int aWidth = 0, int aStyle = 0 ); + void Box( const BOX2I& aBox, int aStyle = 0 ); + void Point ( const VECTOR2I& aPos, int aStyle = 0); + + void SetColor( const KIGFX::COLOR4D& aColor ) + { + m_color = aColor; + } + + void SetClearance ( int aClearance ) + { + m_clearance = aClearance; + } void Show( int a, std::ostream& b ) const {}; @@ -77,7 +85,7 @@ public: aCount = 1; } - void MarkAsHead(); + void drawLineChain( const SHAPE_LINE_CHAIN &l, KIGFX::GAL *aGal ) const; private: const KIGFX::COLOR4D assignColor( int aStyle ) const; @@ -86,17 +94,25 @@ private: KIGFX::VIEW_GROUP* m_parent; PNS_ROUTER* m_router; - SHAPE_LINE_CHAIN m_line; + SHAPE *m_shape; ItemType m_type; + int m_style; int m_width; int m_layer; + int m_originLayer; + int m_clearance; + + // fixme: shouldn't this go to VIEW? + static const int ClearanceOverlayDepth = -2000; + static const int BaseOverlayDepth = -2020; + static const int ViaOverlayDepth = -2046; + + double m_depth; KIGFX::COLOR4D m_color; - - VECTOR2I m_stuckPosition; - VECTOR2I m_viaCenter; + VECTOR2I m_pos; }; #endif diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index e270a0a5e8..4220aa4035 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -15,22 +15,28 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ +#include + #include #include +#include #include "class_draw_panel_gal.h" -#include "class_board_item.h" #include "class_board.h" #include #include +#include #include #include #include #include +#include +#include +#include #include #include @@ -45,29 +51,181 @@ using namespace KIGFX; using boost::optional; -//static TOOL_ACTION ACT_AutoEndRoute( "pcbnew.InteractiveRouter.AutoEndRoute", AS_CONTEXT, 'G' ); -//static TOOL_ACTION ACT_PlaceVia( "pcbnew.InteractiveRouter.PlaceVia", AS_CONTEXT, 'V' ); -//static TOOL_ACTION ACT_OpenRouteOptions( "pcbnew.InteractiveRouter.OpenRouterOptions", AS_CONTEXT, 'T' ); -//static TOOL_ACTION ACT_SwitchPosture( "pcbnew.InteractiveRouter.SwitchPosture", AS_CONTEXT, '/' ); -//static TOOL_ACTION ACT_EndTrack( "pcbnew.InteractiveRouter.EndTrack", AS_CONTEXT, WXK_END ); +static TOOL_ACTION ACT_NewTrack( "pcbnew.InteractiveRouter.NewTrack", + AS_CONTEXT, 'X', + "New Track", "Starts laying a new track."); +static TOOL_ACTION ACT_EndTrack( "pcbnew.InteractiveRouter.EndTrack", + AS_CONTEXT, WXK_END, + "End Track", "Stops laying the current track."); +static TOOL_ACTION ACT_AutoEndRoute( "pcbnew.InteractiveRouter.AutoEndRoute", + AS_CONTEXT, 'F', + "Auto-end Track", "Automagically finishes currently routed track." ); +static TOOL_ACTION ACT_Drag( "pcbnew.InteractiveRouter.Drag", + AS_CONTEXT, 'G', + "Drag Track/Via", "Drags a track or a via." ); +static TOOL_ACTION ACT_PlaceThroughVia( "pcbnew.InteractiveRouter.PlaceVia", + AS_CONTEXT, 'V', + "Place Through Via", "Adds a through-hole via at the end of currently routed track." ); +static TOOL_ACTION ACT_CustomTrackWidth( "pcbnew.InteractiveRouter.CustomTrackWidth", + AS_CONTEXT, 'W', + "Custom Track Width", "Shows a dialog for changing the track width and via size."); +static TOOL_ACTION ACT_RouterOptions( "pcbnew.InteractiveRouter.RouterOptions", + AS_CONTEXT, 'E', + "Routing Options...", "Shows a dialog containing router options."); +static TOOL_ACTION ACT_SwitchPosture( "pcbnew.InteractiveRouter.SwitchPosture", + AS_CONTEXT, '/', + "Switch Track Posture", "Switches posture of the currenly routed track."); ROUTER_TOOL::ROUTER_TOOL() : TOOL_INTERACTIVE( "pcbnew.InteractiveRouter" ) { m_router = NULL; - m_menu = new CONTEXT_MENU; - - m_menu->SetTitle( wxT( "Interactive router" ) ); // fixme: not implemented yet. Sorry. - m_menu->Add( wxT( "Cancel" ), 1 ); - m_menu->Add( wxT( "New track" ), 2 ); - m_menu->Add( wxT( "End track" ), 3 ); - m_menu->Add( wxT( "Auto-end track" ), 4 ); - m_menu->Add( wxT( "Place via" ), 5 ); - m_menu->Add( wxT( "Switch posture" ), 6 ); - - m_menu->Add( wxT( "Routing options..." ), 7 ); } +class CONTEXT_TRACK_WIDTH_MENU: public CONTEXT_MENU +{ +public: + CONTEXT_TRACK_WIDTH_MENU() + { + setCustomEventHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::handleCustomEvent, this, _1 ) ); + } + + void SetBoard( BOARD* aBoard ) + { + BOARD_DESIGN_SETTINGS &bds = aBoard->GetDesignSettings(); + + wxString msg; + m_board = aBoard; + + Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Custom size" ), wxEmptyString, wxITEM_CHECK ); + + Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use the starting track width" ), + _( "Route using the width of the starting track." ), + wxITEM_CHECK ); + + Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, + _( "Use netclass values" ), + _( "Use track and via sizes from the net class" ), + wxITEM_CHECK ); + + for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ ) + { + msg = _ ("Track "); + msg << StringFromValue( g_UserUnit, bds.m_TrackWidthList[i], true ); + + if( i == 0 ) + msg << _( " (from netclass)" ); + + Append( ID_POPUP_PCB_SELECT_WIDTH1 + i, msg, wxEmptyString, wxITEM_CHECK ); + } + + AppendSeparator(); + + for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ ) + { + msg = _ ("Via "); + msg << StringFromValue( g_UserUnit, bds.m_ViasDimensionsList[i].m_Diameter, + true ); + wxString drill = StringFromValue( g_UserUnit, + bds.m_ViasDimensionsList[i].m_Drill, + true ); + + if( bds.m_ViasDimensionsList[i].m_Drill <= 0 ) + { + msg << _ (", drill: default"); + } else { + msg << _ (", drill: ") << drill; + } + + if( i == 0 ) + msg << _( " (from netclass)" ); + + Append( ID_POPUP_PCB_SELECT_VIASIZE1 + i, msg, wxEmptyString, wxITEM_CHECK ); + } + } + +protected: + OPT_TOOL_EVENT handleCustomEvent( const wxEvent& aEvent ) + { +#if ID_POPUP_PCB_SELECT_VIASIZE1 < ID_POPUP_PCB_SELECT_WIDTH1 +#error You have changed event ids, it breaks a piece of code. Lookup this line for more details. +// Recognising type of event (track width/via size) is based on comparison if the event id is +// within a specific range. If ranges of event ids changes, then the following is not valid anymore. +#endif + BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings(); + + int id = aEvent.GetId(); + + // General settings, to be modified below + bds.m_UseConnectedTrackWidth = false; + bds.UseCustomTrackViaSize( false ); + + if( id == ID_POPUP_PCB_SELECT_CUSTOM_WIDTH ) + { + bds.UseCustomTrackViaSize( true ); + } + + else if( id == ID_POPUP_PCB_SELECT_AUTO_WIDTH ) + { + bds.m_UseConnectedTrackWidth = true; + } + + else if( id == ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES ) + { + bds.SetViaSizeIndex( 0 ); + bds.SetTrackWidthIndex( 0 ); + } + + else if( id > ID_POPUP_PCB_SELECT_VIASIZE1 ) // via size has changed + { + assert( id < ID_POPUP_PCB_SELECT_WIDTH_END_RANGE ); + + bds.SetViaSizeIndex( id - ID_POPUP_PCB_SELECT_VIASIZE1 ); + } + + else // track width has changed + { + assert( id >= ID_POPUP_PCB_SELECT_WIDTH1 ); + assert( id < ID_POPUP_PCB_SELECT_VIASIZE ); + + bds.SetTrackWidthIndex( id - ID_POPUP_PCB_SELECT_WIDTH1 ); + } + + return OPT_TOOL_EVENT( COMMON_ACTIONS::trackViaSizeChanged.MakeEvent() ); + } + + BOARD* m_board; +}; + + +class CONTEXT_GRID_MENU: public CONTEXT_MENU { }; + + +class ROUTER_TOOL_MENU: public CONTEXT_MENU { + +public: + ROUTER_TOOL_MENU( BOARD *aBoard ) + { + SetTitle( wxT( "Interactive Router" ) ); + Add( ACT_NewTrack ); + Add( ACT_EndTrack ); +// Add( ACT_AutoEndRoute ); // fixme: not implemented yet. Sorry. + Add( ACT_Drag ); + Add( ACT_PlaceThroughVia ); + Add( ACT_SwitchPosture ); + + AppendSeparator ( ); + + CONTEXT_TRACK_WIDTH_MENU* trackMenu = new CONTEXT_TRACK_WIDTH_MENU; + trackMenu->SetBoard( aBoard ); + AppendSubMenu( trackMenu, wxT( "Select Track Width" ) ); + + Add( ACT_CustomTrackWidth ); + + AppendSeparator ( ); + Add( ACT_RouterOptions ); + } +}; ROUTER_TOOL::~ROUTER_TOOL() { @@ -108,6 +266,7 @@ void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill ) { BOARD* board = getModel( PCB_T ); + BOARD_DESIGN_SETTINGS &bds = board->GetDesignSettings(); NETCLASS* netClass = NULL; NETINFO_ITEM* ni = board->FindNet( aNetCode ); @@ -115,11 +274,11 @@ void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth, if( ni ) { wxString netClassName = ni->GetClassName(); - netClass = board->GetDesignSettings().m_NetClasses.Find( netClassName ); + netClass = bds.m_NetClasses.Find( netClassName ); } if( !netClass ) - netClass = board->GetDesignSettings().m_NetClasses.GetDefault(); + netClass = bds.m_NetClasses.GetDefault(); aWidth = netClass->GetTrackWidth(); aViaDiameter = netClass->GetViaDiameter(); @@ -134,74 +293,67 @@ PNS_ITEM* ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa if( aLayer > 0 ) tl = aLayer; - PNS_ITEM* picked_seg = NULL; - PNS_ITEM* picked_via = NULL; + PNS_ITEM* prioritized[4]; + + for(int i = 0; i < 4; i++) + prioritized[i] = 0; + PNS_ITEMSET candidates = m_router->QueryHoverItems( aWhere ); BOOST_FOREACH( PNS_ITEM* item, candidates.Items() ) { - if( !IsCopperLayer( item->GetLayers().Start() ) ) + if( !IsCopperLayer( item->Layers().Start() ) ) continue; - if( item->GetParent() && !item->GetParent()->ViewIsVisible() && - !item->GetParent()->IsSelected() ) - continue; + // fixme: this causes flicker with live loop removal... + //if( item->Parent() && !item->Parent()->ViewIsVisible() ) + // continue; - if( aNet < 0 || item->GetNet() == aNet ) + if( aNet < 0 || item->Net() == aNet ) { if( item->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID ) ) { - if( item->GetLayers().Overlaps( tl ) || !picked_via ) - picked_via = item; + if( !prioritized[2] ) + prioritized[2] = item; + if( item->Layers().Overlaps( tl )) + prioritized[0] = item; } else { - if( item->GetLayers().Overlaps( tl ) || !picked_seg ) - picked_seg = item; + if( !prioritized[3] ) + prioritized[3] = item; + if (item->Layers().Overlaps( tl )) + prioritized[1] = item; } } } - if( DisplayOpt.ContrastModeDisplay ) + PNS_ITEM *rv = NULL; + for(int i = 0; i < 4; i++) { - if( picked_seg && !picked_seg->GetLayers().Overlaps( tl ) ) - picked_seg = NULL; + PNS_ITEM *item = prioritized[i]; + + if( DisplayOpt.ContrastModeDisplay ) + if( item && !item->Layers().Overlaps( tl ) ) + item = NULL; + + if(item) + { + rv = item; + break; + } } - PNS_ITEM* rv = picked_via ? picked_via : picked_seg; - - if( rv && aLayer >= 0 && !rv->GetLayers().Overlaps( aLayer ) ) + if( rv && aLayer >= 0 && !rv->Layers().Overlaps( aLayer ) ) rv = NULL; if( rv ) - TRACE( 0, "%s, layer : %d, tl: %d", rv->GetKindStr().c_str() % rv->GetLayers().Start() % + TRACE( 0, "%s, layer : %d, tl: %d", rv->KindStr().c_str() % rv->Layers().Start() % tl ); return rv; } - -void ROUTER_TOOL::setMsgPanel( bool aEnabled, int aEntry, - const wxString& aUpperMessage, const wxString& aLowerMessage ) -{ - PCB_EDIT_FRAME* frame = getEditFrame (); - - if( m_panelItems.size() <= (unsigned int) aEntry ) - m_panelItems.resize( aEntry + 1 ); - - m_panelItems[aEntry] = MSG_PANEL_ITEM( aUpperMessage, aLowerMessage, BLACK ); - frame->SetMsgPanel( m_panelItems ); -} - - -void ROUTER_TOOL::clearMsgPanel() -{ - PCB_EDIT_FRAME* frame = getEditFrame (); - - frame->ClearMsgPanel(); -} - - void ROUTER_TOOL::highlightNet( bool aEnabled, int aNetcode ) { RENDER_SETTINGS* rs = getView()->GetPainter()->GetSettings(); @@ -214,37 +366,104 @@ void ROUTER_TOOL::highlightNet( bool aEnabled, int aNetcode ) getView()->UpdateAllLayersColor(); } +void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt ) +{ +#ifdef DEBUG + if( evt.IsKeyPressed() ) + { + switch( evt.KeyCode() ) + { + case 'S': + TRACEn(2, "saving drag/route log...\n"); + m_router->DumpLog(); + break; + } + } + else +#endif + if( evt.IsAction( &ACT_RouterOptions ) ) + { + DIALOG_PNS_SETTINGS settingsDlg( m_toolMgr->GetEditFrame(), m_router->Settings() ); + + if( settingsDlg.ShowModal() ) + m_router->ApplySettings(); + } + + else if( evt.IsAction( &ACT_CustomTrackWidth ) ) + { + DIALOG_TRACK_VIA_SIZE sizeDlg( m_toolMgr->GetEditFrame(), m_router->Settings() ); + BOARD_DESIGN_SETTINGS& bds = getModel( PCB_T )->GetDesignSettings(); + + sizeDlg.ShowModal(); + + // TODO it should be changed, router settings won't keep track & via sizes in the future + bds.SetCustomTrackWidth( m_router->Settings().GetTrackWidth() ); + bds.SetCustomViaSize( m_router->Settings().GetViaDiameter() ); + bds.SetCustomViaDrill( m_router->Settings().GetViaDrill() ); + bds.UseCustomTrackViaSize( true ); + + // TODO Should be done another way, but RunAction() won't work here. As the ROUTER_TOOL + // did not call Wait(), it does not wait for events and therefore the sent event + // won't arrive here + TOOL_EVENT event = COMMON_ACTIONS::trackViaSizeChanged.MakeEvent(); + handleCommonEvents( event ); + } + + else if( evt.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) ) + { + BOARD_DESIGN_SETTINGS& bds = getModel( PCB_T )->GetDesignSettings(); + + m_router->Settings().SetTrackWidth( bds.GetCurrentTrackWidth() ); + m_router->Settings().SetViaDiameter( bds.GetCurrentViaSize() ); + m_router->Settings().SetViaDrill( bds.GetCurrentViaDrill() ); + m_router->ApplySettings(); + } +} void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent ) { VIEW_CONTROLS* ctls = getViewControls(); int tl = getView()->GetTopLayer(); + VECTOR2I cp = ctls->GetCursorPosition(); PNS_ITEM* startItem = NULL; if( aEvent.IsMotion() || aEvent.IsClick() ) { VECTOR2I p = aEvent.Position(); + startItem = pickSingleItem( p ); - if( startItem && startItem->GetNet() >= 0 ) + bool snapEnabled = !aEvent.Modifier(MD_SHIFT); + + m_router->EnableSnapping ( snapEnabled ); + + if(!snapEnabled && startItem && !startItem->Layers().Overlaps( tl ) ) + startItem = NULL; + + if( startItem && startItem->Net() >= 0 ) { bool dummy; - VECTOR2I cursorPos = m_router->SnapToItem( startItem, p, dummy ); - ctls->ForceCursorPosition( true, cursorPos ); + VECTOR2I psnap = m_router->SnapToItem( startItem, p, dummy ); + + if (snapEnabled) { + m_startSnapPoint = psnap; + ctls->ForceCursorPosition( true, psnap ); + } else { + m_startSnapPoint = cp; + ctls->ForceCursorPosition( false ); + } - m_startSnapPoint = cursorPos; - - if( startItem->GetLayers().IsMultilayer() ) + if( startItem->Layers().IsMultilayer() ) m_startLayer = tl; else - m_startLayer = startItem->GetLayers().Start(); + m_startLayer = startItem->Layers().Start(); m_startItem = startItem; } else { m_startItem = NULL; - m_startSnapPoint = p; + m_startSnapPoint = cp; m_startLayer = tl; ctls->ForceCursorPosition( false ); } @@ -255,13 +474,18 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent ) void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) { VIEW_CONTROLS* ctls = getViewControls(); - VECTOR2I p = aEvent.Position(); + VECTOR2I p = getView()->ToWorld( ctls->GetMousePosition() ); + VECTOR2I cp = ctls->GetCursorPosition(); int layer; - if( m_router->GetCurrentNet() < 0 || !m_startItem ) + bool snapEnabled = !aEvent.Modifier(MD_SHIFT); + + m_router->EnableSnapping ( snapEnabled ); + + if( !snapEnabled || m_router->GetCurrentNet() < 0 || !m_startItem ) { m_endItem = NULL; - m_endSnapPoint = p; + m_endSnapPoint = cp; return; } @@ -272,7 +496,7 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) else layer = m_router->GetCurrentLayer(); - PNS_ITEM* endItem = pickSingleItem( p, m_startItem->GetNet(), layer ); + PNS_ITEM* endItem = pickSingleItem( p, m_startItem->Net(), layer ); if( endItem ) { @@ -284,57 +508,39 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) else { m_endItem = NULL; - m_endSnapPoint = ctls->GetCursorPosition(); + m_endSnapPoint = cp; ctls->ForceCursorPosition( false ); } - // Draw ratsnest for the currently routed track - RN_DATA* ratsnest = getModel( PCB_T )->GetRatsnest(); - ratsnest->ClearSimple(); - - if( ( m_endItem == NULL || m_endItem == m_startItem ) && m_startItem->GetNet() > 0 ) - { - // The ending node has to be first, so the line for the track is drawn first - ratsnest->AddSimple( m_endSnapPoint, m_startItem->GetNet() ); - - // Those nodes are added just to force ratsnest not to drawn - // lines to already routed parts of the track - const PICKED_ITEMS_LIST& changes = m_router->GetLastChanges(); - for( unsigned int i = 0; i < changes.GetCount(); ++i ) - { - // Block the new tracks, do not handle tracks that were moved - // (moved tracks are saved in the undo buffer with UR_DELETED status instead) - if( changes.GetPickedItemStatus( i ) == UR_NEW ) - ratsnest->AddBlocked( static_cast( changes.GetPickedItem( i ) ) ); - } - - // Also the origin of the new track should be skipped in the ratsnest shown for the routed track - ratsnest->AddBlocked( static_cast( m_startItem->GetParent() ) ); - } - if( m_endItem ) - TRACE( 0, "%s, layer : %d", m_endItem->GetKindStr().c_str() % - m_endItem->GetLayers().Start() ); + TRACE( 0, "%s, layer : %d", m_endItem->KindStr().c_str() % + m_endItem->Layers().Start() ); } -void ROUTER_TOOL::startRouting() +void ROUTER_TOOL::performRouting() { + PCB_EDIT_FRAME* frame = getEditFrame(); bool saveUndoBuffer = true; VIEW_CONTROLS* ctls = getViewControls(); - int width = getDefaultWidth( m_startItem ? m_startItem->GetNet() : -1 ); + if( getModel( PCB_T )->GetDesignSettings().m_UseConnectedTrackWidth ) + { + int width = getDefaultWidth( m_startItem ? m_startItem->Net() : -1 ); - if( m_startItem && m_startItem->OfKind( PNS_ITEM::SEGMENT ) ) - width = static_cast( m_startItem )->GetWidth(); + if( m_startItem && m_startItem->OfKind( PNS_ITEM::SEGMENT ) ) + width = static_cast( m_startItem )->Width(); + + m_router->Settings().SetTrackWidth( width ); + } - m_router->SetCurrentWidth( width ); m_router->SwitchLayer( m_startLayer ); - getEditFrame()->SetTopLayer( m_startLayer ); + frame->SetActiveLayer( m_startLayer ); + frame->GetGalCanvas()->SetFocus(); - if( m_startItem && m_startItem->GetNet() >= 0 ) - highlightNet( true, m_startItem->GetNet() ); + if( m_startItem && m_startItem->Net() >= 0 ) + highlightNet( true, m_startItem->Net() ); ctls->ForceCursorPosition( false ); ctls->SetAutoPan( true ); @@ -366,43 +572,37 @@ void ROUTER_TOOL::startRouting() break; m_router->Move( m_endSnapPoint, m_endItem ); - } - else if( evt->IsKeyPressed() ) + } else if( evt->IsAction( &ACT_PlaceThroughVia ) ) { - switch( std::toupper( evt->KeyCode() ) ) - { - case 'V': - { - int w, diameter, drill; - getNetclassDimensions( m_router->GetCurrentNet(), w, diameter, drill ); - m_router->SetCurrentViaDiameter( diameter ); - m_router->SetCurrentViaDrill( drill ); - m_router->ToggleViaPlacement(); - getEditFrame()->SetTopLayer( m_router->GetCurrentLayer() ); - m_router->Move( m_endSnapPoint, m_endItem ); - break; - } - - case '/': - m_router->FlipPosture(); - break; - - case '+': - case '=': - m_router->SwitchLayer( m_router->NextCopperLayer( true ) ); - updateEndItem( *evt ); - getEditFrame()->SetTopLayer( m_router->GetCurrentLayer() ); - m_router->Move( m_endSnapPoint, m_endItem ); - - break; - - case '-': - m_router->SwitchLayer( m_router->NextCopperLayer( false ) ); - getEditFrame()->SetTopLayer( m_router->GetCurrentLayer() ); - m_router->Move( m_endSnapPoint, m_endItem ); - break; - } + m_router->ToggleViaPlacement(); + frame->SetTopLayer( m_router->GetCurrentLayer() ); + m_router->Move( m_endSnapPoint, m_endItem ); } + else if( evt->IsAction( &ACT_SwitchPosture ) ) + { + m_router->FlipPosture(); + m_router->Move( m_endSnapPoint, m_endItem ); + } + else if( evt->IsAction( &COMMON_ACTIONS::layerNext ) ) + { + m_router->SwitchLayer( m_router->NextCopperLayer( true ) ); + updateEndItem( *evt ); + frame->SetActiveLayer( m_router->GetCurrentLayer() ); + m_router->Move( m_endSnapPoint, m_endItem ); + } + else if( evt->IsAction( &COMMON_ACTIONS::layerPrev ) ) + { + m_router->SwitchLayer( m_router->NextCopperLayer( false ) ); + frame->SetActiveLayer( m_router->GetCurrentLayer() ); + m_router->Move( m_endSnapPoint, m_endItem ); + } + else if( evt->IsAction( &ACT_EndTrack ) ) + { + if( m_router->FixRoute( m_endSnapPoint, m_endItem ) ) + break; + } + + handleCommonEvents(*evt); } m_router->StopRouting(); @@ -410,10 +610,9 @@ void ROUTER_TOOL::startRouting() if( saveUndoBuffer ) { // Save the recent changes in the undo buffer - getEditFrame()->SaveCopyInUndoList( m_router->GetLastChanges(), - UR_UNSPECIFIED ); - m_router->ClearLastChanges(); - getEditFrame()->OnModify(); + frame->SaveCopyInUndoList( m_router->GetUndoBuffer(), UR_UNSPECIFIED ); + m_router->ClearUndoBuffer(); + frame->OnModify(); } else { @@ -430,14 +629,23 @@ void ROUTER_TOOL::startRouting() int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) { VIEW_CONTROLS* ctls = getViewControls(); + BOARD* board = getModel( PCB_T ); + BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings(); - // SetContextMenu ( m_menu ); - // setMsgPanel(true, 0, wxT("KiRouter"), wxT("Pick an item to start routing")); - getEditFrame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Add tracks" ) ); + getEditFrame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Interactive Router" ) ); ctls->SetSnapping( true ); ctls->ShowCursor( true ); + // Set current track widths & via size + m_router->Settings().SetTrackWidth( bds.GetCurrentTrackWidth() ); + m_router->Settings().SetViaDiameter( bds.GetCurrentViaSize() ); + m_router->Settings().SetViaDrill( bds.GetCurrentViaDrill() ); + + ROUTER_TOOL_MENU *ctxMenu = new ROUTER_TOOL_MENU( board ); + + SetContextMenu ( ctxMenu ); + // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { @@ -453,21 +661,69 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) m_needsSync = true; else if( evt->IsMotion() ) updateStartItem( *evt ); - else if( evt->IsClick( BUT_LEFT ) ) + else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &ACT_NewTrack ) ) { updateStartItem( *evt ); - startRouting(); - } - } - // clearMsgPanel(); + if( evt->Modifier( MD_CTRL ) ) + performDragging(); + else + performRouting(); + } else if ( evt->IsAction( &ACT_Drag ) ) + performDragging(); + + handleCommonEvents(*evt); + } // Restore the default settings ctls->SetAutoPan( false ); ctls->ShowCursor( false ); - ctls->ForceCursorPosition( false ); - getEditFrame()->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + delete ctxMenu; + return 0; } + + +void ROUTER_TOOL::performDragging() +{ + VIEW_CONTROLS* ctls = getViewControls(); + + bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem ); + + if(!dragStarted) + return; + + if( m_startItem && m_startItem->Net() >= 0 ) + highlightNet( true, m_startItem->Net() ); + + ctls->ForceCursorPosition( false ); + ctls->SetAutoPan( true ); + + while( OPT_TOOL_EVENT evt = Wait() ) + { + if( evt->IsCancel() ) + break; + else if( evt->IsMotion() ) + { + updateEndItem( *evt ); + m_router->Move( m_endSnapPoint, m_endItem ); + } + else if( evt->IsClick( BUT_LEFT ) ) + { + + if( m_router->FixRoute( m_endSnapPoint, m_endItem ) ) + break; + + } + handleCommonEvents(*evt); + } + + if( m_router->RoutingInProgress() ) + m_router->StopRouting(); + + ctls->SetAutoPan( false ); + ctls->ForceCursorPosition( false ); + highlightNet( false ); +} diff --git a/pcbnew/router/router_tool.h b/pcbnew/router/router_tool.h index 42bbceb19c..db9db3ea6a 100644 --- a/pcbnew/router/router_tool.h +++ b/pcbnew/router/router_tool.h @@ -1,8 +1,9 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2014 CERN * Author: Tomasz Wlostowski + * Author: Maciej Suminski * * 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 @@ -15,7 +16,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __ROUTER_TOOL_H @@ -24,6 +25,8 @@ #include #include +#include + #include #include @@ -35,7 +38,7 @@ class PNS_ROUTER; class PNS_ITEM; -class ROUTER_TOOL : public TOOL_INTERACTIVE +class APIEXPORT ROUTER_TOOL : public TOOL_INTERACTIVE { public: ROUTER_TOOL(); @@ -48,12 +51,11 @@ private: PNS_ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 ); - void setMsgPanel( bool enabled, int entry, const wxString& aUpperMessage = wxT(""), - const wxString& aLowerMessage = wxT("") ); - void clearMsgPanel(); - int getDefaultWidth( int aNetCode ); - void startRouting(); + + void performRouting(); + void performDragging(); + void highlightNet( bool enabled, int netcode = -1 ); void updateStartItem( TOOL_EVENT& aEvent ); @@ -61,6 +63,8 @@ private: void getNetclassDimensions( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill ); + void handleCommonEvents( TOOL_EVENT& evt ); + MSG_PANEL_ITEMS m_panelItems; PNS_ROUTER* m_router; @@ -72,11 +76,11 @@ private: PNS_ITEM* m_endItem; VECTOR2I m_endSnapPoint; + + CONTEXT_MENU* m_menu; + ///> Flag marking that the router's world needs syncing. bool m_needsSync; - - /*boost::shared_ptr m_menu;*/ - CONTEXT_MENU* m_menu; }; #endif diff --git a/pcbnew/router/time_limit.cpp b/pcbnew/router/time_limit.cpp new file mode 100644 index 0000000000..0e14a10678 --- /dev/null +++ b/pcbnew/router/time_limit.cpp @@ -0,0 +1,46 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#include + +#include "time_limit.h" + +TIME_LIMIT::TIME_LIMIT( int aMilliseconds ) : + m_limitMs( aMilliseconds ) + { + Restart(); + }; + +TIME_LIMIT::~TIME_LIMIT () {} + +bool TIME_LIMIT::Expired() const +{ + return ( wxGetLocalTimeMillis().GetValue() - m_startTics ) >= m_limitMs; +} + +void TIME_LIMIT::Restart() +{ + m_startTics = wxGetLocalTimeMillis().GetValue(); +} + +void TIME_LIMIT::Set ( int aMilliseconds ) +{ + m_limitMs = aMilliseconds; +} diff --git a/pcbnew/router/time_limit.h b/pcbnew/router/time_limit.h new file mode 100644 index 0000000000..fbb58c4156 --- /dev/null +++ b/pcbnew/router/time_limit.h @@ -0,0 +1,44 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 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 3 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, see . + */ + +#ifndef __TIME_LIMIT_H +#define __TIME_LIMIT_H + +#include + +class TIME_LIMIT { + +public: + TIME_LIMIT( int aMilliseconds = 0); + ~TIME_LIMIT (); + + bool Expired() const; + void Restart(); + + void Set ( int aMilliseconds ); + +private: + + int m_limitMs; + int64_t m_startTics; +}; + + +#endif \ No newline at end of file diff --git a/pcbnew/router/trace.h b/pcbnew/router/trace.h index 1f8a3e32c9..91f29baa15 100644 --- a/pcbnew/router/trace.h +++ b/pcbnew/router/trace.h @@ -15,22 +15,21 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program. If not, see . + * with this program. If not, see . */ #ifndef __TRACE_H #define __TRACE_H -// #ifdef DEBUG -#if 0 - #include #include #include -static void _trace_print( const char* aFuncName, int level, const std::string& aMsg ) +static inline void _trace_print( const char* aFuncName, int level, const std::string& aMsg ) { +#ifdef DEBUG std::cerr << "trace[" << level << "]: " << aFuncName << ": " << aMsg << std::endl; +#endif } #define TRACE( level, fmt, ... ) \ @@ -39,11 +38,4 @@ static void _trace_print( const char* aFuncName, int level, const std::string& a #define TRACEn( level, msg ) \ _trace_print( __FUNCTION__, level, std::string( msg ) ); -#else - -#define TRACE( level, fmt, ... ) -#define TRACEn( level, msg ) - -#endif - #endif From ae4f41c3281c78eef0a2f816afcca77b2b4631ab Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 16:28:39 +0200 Subject: [PATCH 57/68] Added missing dialog files for pcbnew. --- pcbnew/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index ae2292bf13..2fc30d1fc7 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -97,6 +97,8 @@ set( PCBNEW_DIALOGS dialogs/dialog_netlist_fbp.cpp dialogs/dialog_pcb_text_properties.cpp dialogs/dialog_pcb_text_properties_base.cpp + dialogs/dialog_pns_settings.cpp + dialogs/dialog_pns_settings_base.cpp dialogs/dialog_non_copper_zones_properties_base.cpp dialogs/dialog_pad_properties.cpp dialogs/dialog_pad_properties_base.cpp @@ -115,6 +117,8 @@ set( PCBNEW_DIALOGS dialogs/dialog_set_grid.cpp dialogs/dialog_set_grid_base.cpp dialogs/dialog_target_properties_base.cpp + dialogs/dialog_track_via_size.cpp + dialogs/dialog_track_via_size_base.cpp footprint_wizard.cpp footprint_wizard_frame.cpp dialogs/dialog_footprint_wizard_list_base.cpp From def53707d52bb18376028f309a0675dce2f36cce Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 16:29:53 +0200 Subject: [PATCH 58/68] TOOL_MANAGER is no longer static. Reworked autoregistration of TOOL_ACTIONs. --- common/tool/action_manager.cpp | 4 ++++ common/tool/context_menu.cpp | 15 ++++++--------- common/tool/tool_manager.cpp | 9 +-------- include/tool/tool_action.h | 17 +++++++++++++---- include/tool/tool_manager.h | 27 ++++++++++++++------------- include/wxBasePcbFrame.h | 2 +- pcbnew/basepcbframe.cpp | 4 ++-- pcbnew/board_undo_redo.cpp | 4 ++-- pcbnew/edit.cpp | 6 +++--- pcbnew/pcbframe.cpp | 10 +++++----- pcbnew/tools/pcb_tools.cpp | 34 ++++++++++++++++++++-------------- 11 files changed, 71 insertions(+), 61 deletions(-) diff --git a/common/tool/action_manager.cpp b/common/tool/action_manager.cpp index 51c85aa273..444143b0fb 100644 --- a/common/tool/action_manager.cpp +++ b/common/tool/action_manager.cpp @@ -50,6 +50,7 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) // action name without specifying at least toolName is not valid assert( aAction->GetName().find( '.', 0 ) != std::string::npos ); + // TOOL_ACTIONs must have unique names & ids assert( m_actionNameIndex.find( aAction->m_name ) == m_actionNameIndex.end() ); assert( m_actionIdIndex.find( aAction->m_id ) == m_actionIdIndex.end() ); @@ -60,6 +61,8 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) if( aAction->HasHotKey() ) m_actionHotKeys[aAction->m_currentHotKey].push_back( aAction ); + + aAction->setActionMgr( this ); } @@ -69,6 +72,7 @@ void ACTION_MANAGER::UnregisterAction( TOOL_ACTION* aAction ) m_actionIdIndex.erase( aAction->m_id ); // Indicate that the ACTION_MANAGER no longer care about the object + aAction->setActionMgr( NULL ); aAction->setId( -1 ); if( aAction->HasHotKey() ) diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index 7413761ed3..b6277e16a7 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -73,14 +73,8 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) : void CONTEXT_MENU::setupEvents() { - Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CONTEXT_MENU::onMenuEvent ), - NULL, this ); - Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CONTEXT_MENU::onMenuEvent ), - NULL, this ); - - // Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu) - wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, this ); - AddPendingEvent( menuEvent ); + Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this ); + Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this ); } @@ -191,8 +185,11 @@ void CONTEXT_MENU::onMenuEvent( wxEvent& aEvent ) } } + assert( m_tool ); // without tool & tool manager we cannot handle events + // forward the action/update event to the TOOL_MANAGER - TOOL_MANAGER::Instance().ProcessEvent( *evt ); + if( evt && m_tool ) + m_tool->GetManager()->ProcessEvent( *evt ); } diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index dd77425a0c..a0bba9c51f 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -103,14 +103,6 @@ TOOL_MANAGER::TOOL_MANAGER() : TOOL_MANAGER::~TOOL_MANAGER() -{ - DeleteAll(); - - delete m_actionMgr; -} - - -void TOOL_MANAGER::DeleteAll() { std::map::iterator it, it_end; @@ -122,6 +114,7 @@ void TOOL_MANAGER::DeleteAll() } m_toolState.clear(); + delete m_actionMgr; } diff --git a/include/tool/tool_action.h b/include/tool/tool_action.h index 8fb81e5d8d..4097fd2f7f 100644 --- a/include/tool/tool_action.h +++ b/include/tool/tool_action.h @@ -52,12 +52,12 @@ public: m_currentHotKey( aDefaultHotKey ), m_menuItem( aMenuItem ), m_menuDescription( aMenuDesc ), m_id( -1 ) { - TOOL_MANAGER::Instance().RegisterAction( this ); + TOOL_MANAGER::GetActionList().push_back( this ); } ~TOOL_ACTION() { - TOOL_MANAGER::Instance().UnregisterAction( this ); + TOOL_MANAGER::GetActionList().remove( this ); } bool operator==( const TOOL_ACTION& aRhs ) const @@ -195,6 +195,12 @@ private: m_id = aId; } + /// Assigns ACTION_MANAGER object that handles the TOOL_ACTION. + void setActionMgr( ACTION_MANAGER* aManager ) + { + m_actionMgr = aManager; + } + /// Name of the action (convention is: app.[tool.]action.name) std::string m_name; @@ -219,11 +225,14 @@ private: /// Unique ID for fast matching. Assigned by ACTION_MANAGER. int m_id; + /// Action manager that handles this TOOL_ACTION. + ACTION_MANAGER* m_actionMgr; + /// Origin of the action -// const TOOL_BASE* m_origin; + // const TOOL_BASE* m_origin; /// Originating UI object -// wxWindow* m_uiOrigin; + // wxWindow* m_uiOrigin; }; #endif diff --git a/include/tool/tool_manager.h b/include/tool/tool_manager.h index 1e4563a7e0..c8861c7ff1 100644 --- a/include/tool/tool_manager.h +++ b/include/tool/tool_manager.h @@ -48,20 +48,10 @@ class wxWindow; class TOOL_MANAGER { public: - static TOOL_MANAGER& Instance() - { - static TOOL_MANAGER manager; - - return manager; - } + TOOL_MANAGER(); ~TOOL_MANAGER(); - /** - * Deletes all the tools that were registered in the TOOL_MANAGER. - */ - void DeleteAll(); - /** * Generates an unique ID from for a tool with given name. */ @@ -251,9 +241,20 @@ public: m_passEvent = true; } -private: - TOOL_MANAGER(); + /** + * Returns list of TOOL_ACTIONs. TOOL_ACTIONs add themselves to the list upon their + * creation. + * @return List of TOOL_ACTIONs. + */ + static std::list& GetActionList() + { + // TODO I am afraid this approach won't work when we reach multitab version of kicad. + static std::list actionList; + return actionList; + } + +private: struct TOOL_STATE; typedef std::pair TRANSITION; diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index b2ce7d9a23..19d66214ac 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -90,7 +90,7 @@ protected: /// main window. wxAuiToolBar* m_auxiliaryToolBar; - TOOL_MANAGER& m_toolManager; + TOOL_MANAGER* m_toolManager; TOOL_DISPATCHER* m_toolDispatcher; void updateGridSelectBox(); diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index caa1194fc8..5577650436 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -133,10 +133,10 @@ END_EVENT_TABLE() PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize, long aStyle, const wxString & aFrameName ) : - EDA_DRAW_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ), - m_toolManager( TOOL_MANAGER::Instance() ) + EDA_DRAW_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ) { m_Pcb = NULL; + m_toolManager = NULL; m_toolDispatcher = NULL; m_DisplayPadFill = true; // How to draw pads diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index db51056d02..56b5ca63d2 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -637,7 +637,7 @@ void PCB_EDIT_FRAME::GetBoardFromUndoList( wxCommandEvent& aEvent ) // Inform tools that undo command was issued TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL ); - m_toolManager.ProcessEvent( event ); + m_toolManager->ProcessEvent( event ); /* Get the old list */ PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList(); @@ -660,7 +660,7 @@ void PCB_EDIT_FRAME::GetBoardFromRedoList( wxCommandEvent& aEvent ) // Inform tools that redo command was issued TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL ); - m_toolManager.ProcessEvent( event ); + m_toolManager->ProcessEvent( event ); /* Get the old list */ PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList(); diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index 51de425839..7c2a02804f 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -1391,15 +1391,15 @@ void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent ) // Cancel the current tool // TODO while sending a lot of cancel events works for sure, it is not the most // elegant way to cancel a tool, this should be probably done another way - while( m_toolManager.GetCurrentTool()->GetName() != "pcbnew.InteractiveSelection" && + while( m_toolManager->GetCurrentTool()->GetName() != "pcbnew.InteractiveSelection" && trials++ < MAX_TRIALS ) { TOOL_EVENT cancel( TC_ANY, TA_CANCEL_TOOL ); - m_toolManager.ProcessEvent( cancel ); + m_toolManager->ProcessEvent( cancel ); } if( !actionName.empty() ) - m_toolManager.RunAction( actionName ); + m_toolManager->RunAction( actionName ); } } else diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index b873ef95f7..d04541e200 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -495,9 +495,9 @@ void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard ) ViewReloadBoard( aBoard ); // update the tool manager with the new board and its view. - m_toolManager.SetEnvironment( aBoard, GetGalCanvas()->GetView(), - GetGalCanvas()->GetViewControls(), this ); - m_toolManager.ResetTools( TOOL_BASE::MODEL_RELOAD ); + m_toolManager->SetEnvironment( aBoard, GetGalCanvas()->GetView(), + GetGalCanvas()->GetViewControls(), this ); + m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); } } @@ -677,9 +677,9 @@ void PCB_EDIT_FRAME::UseGalCanvas( bool aEnable ) ViewReloadBoard( m_Pcb ); GetGalCanvas()->GetView()->RecacheAllItems(); - m_toolManager.SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), + m_toolManager->SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), GetGalCanvas()->GetViewControls(), this ); - m_toolManager.ResetTools( TOOL_BASE::MODEL_RELOAD ); + m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); GetGalCanvas()->StartDrawing(); } diff --git a/pcbnew/tools/pcb_tools.cpp b/pcbnew/tools/pcb_tools.cpp index 0decc244d7..eaefa97678 100644 --- a/pcbnew/tools/pcb_tools.cpp +++ b/pcbnew/tools/pcb_tools.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -45,8 +46,8 @@ void PCB_EDIT_FRAME::setupTools() { // Create the manager and dispatcher & route draw panel events to the dispatcher - m_toolManager = TOOL_MANAGER::Instance(); - m_toolDispatcher = new TOOL_DISPATCHER( &m_toolManager, this ); + m_toolManager = new TOOL_MANAGER; + m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, this ); GetGalCanvas()->SetEventDispatcher( m_toolDispatcher ); // Connect handlers to toolbar buttons @@ -59,26 +60,31 @@ void PCB_EDIT_FRAME::setupTools() wxCommandEventHandler( PCB_EDIT_FRAME::onGenericCommand ), NULL, this ); #endif - // Register tools - m_toolManager.RegisterTool( new SELECTION_TOOL ); - m_toolManager.RegisterTool( new ROUTER_TOOL ); - m_toolManager.RegisterTool( new EDIT_TOOL ); - m_toolManager.RegisterTool( new DRAWING_TOOL ); - m_toolManager.RegisterTool( new POINT_EDITOR ); - m_toolManager.RegisterTool( new PCBNEW_CONTROL ); + // Register actions + std::list& actionList = m_toolManager->GetActionList(); + BOOST_FOREACH( TOOL_ACTION* action, actionList ) + m_toolManager->RegisterAction( action ); - m_toolManager.SetEnvironment( NULL, GetGalCanvas()->GetView(), - GetGalCanvas()->GetViewControls(), this ); - m_toolManager.ResetTools( TOOL_BASE::RUN ); + // Register tools + m_toolManager->RegisterTool( new SELECTION_TOOL ); + m_toolManager->RegisterTool( new ROUTER_TOOL ); + m_toolManager->RegisterTool( new EDIT_TOOL ); + m_toolManager->RegisterTool( new DRAWING_TOOL ); + m_toolManager->RegisterTool( new POINT_EDITOR ); + m_toolManager->RegisterTool( new PCBNEW_CONTROL ); + + m_toolManager->SetEnvironment( NULL, GetGalCanvas()->GetView(), + GetGalCanvas()->GetViewControls(), this ); + m_toolManager->ResetTools( TOOL_BASE::RUN ); // Run the selection tool, it is supposed to be always active - m_toolManager.InvokeTool( "pcbnew.InteractiveSelection" ); + m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" ); } void PCB_EDIT_FRAME::destroyTools() { - m_toolManager.DeleteAll(); + delete m_toolManager; delete m_toolDispatcher; } From f31dd1cdafc2d09f9f530d837b07a33341a3f716 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 16:40:56 +0200 Subject: [PATCH 59/68] PNS debug output is enabled with PNS_DEBUG define. --- pcbnew/router/trace.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pcbnew/router/trace.h b/pcbnew/router/trace.h index 91f29baa15..7e6fc80980 100644 --- a/pcbnew/router/trace.h +++ b/pcbnew/router/trace.h @@ -32,10 +32,15 @@ static inline void _trace_print( const char* aFuncName, int level, const std::st #endif } -#define TRACE( level, fmt, ... ) \ - _trace_print( __FUNCTION__, level, ( boost::format( fmt ) % __VA_ARGS__ ).str() ); +#ifdef PNS_DEBUG + #define TRACE( level, fmt, ... ) \ + _trace_print( __FUNCTION__, level, ( boost::format( fmt ) % __VA_ARGS__ ).str() ); -#define TRACEn( level, msg ) \ - _trace_print( __FUNCTION__, level, std::string( msg ) ); + #define TRACEn( level, msg ) \ + _trace_print( __FUNCTION__, level, std::string( msg ) ); +#else + #define TRACE( ... ) + #define TRACEn( ... ) +#endif #endif From d7ac36826055a4537e047737ecdd3f396f07fa87 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 16:53:49 +0200 Subject: [PATCH 60/68] PNS routing settings are stored between router invocations. --- pcbnew/router/pns_router.h | 11 +++++++++++ pcbnew/router/router_tool.cpp | 3 +++ pcbnew/router/router_tool.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 53c0905487..9c867c585d 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -172,6 +172,17 @@ public: */ void ApplySettings(); + /** + * Changes routing settings to ones passed in the parameter. + * @param aSettings are the new settings. + */ + void LoadSettings( const PNS_ROUTING_SETTINGS& aSettings ) + { + m_settings = aSettings; + + ApplySettings(); + } + void EnableSnapping ( bool aEnable ) { m_snappingEnabled = aEnable; diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 4220aa4035..db2c996a34 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -244,6 +244,7 @@ void ROUTER_TOOL::Reset( RESET_REASON aReason ) m_router->ClearWorld(); m_router->SetBoard( getModel( PCB_T ) ); m_router->SyncWorld(); + m_router->LoadSettings( m_settings ); m_needsSync = false; if( getView() ) @@ -620,6 +621,8 @@ void ROUTER_TOOL::performRouting() m_needsSync = true; } + m_settings = m_router->Settings(); + ctls->SetAutoPan( false ); ctls->ForceCursorPosition( false ); highlightNet( false ); diff --git a/pcbnew/router/router_tool.h b/pcbnew/router/router_tool.h index db9db3ea6a..e516222470 100644 --- a/pcbnew/router/router_tool.h +++ b/pcbnew/router/router_tool.h @@ -34,6 +34,7 @@ #include #include "pns_layerset.h" +#include "pns_routing_settings.h" class PNS_ROUTER; class PNS_ITEM; @@ -68,6 +69,7 @@ private: MSG_PANEL_ITEMS m_panelItems; PNS_ROUTER* m_router; + PNS_ROUTING_SETTINGS m_settings; ///< Stores routing settings between router invocations PNS_ITEM* m_startItem; int m_startLayer; From 0d9373ca6c9ca9ec546eeeb8d7f92f52d1acb3a8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 18:45:59 +0200 Subject: [PATCH 61/68] Undo/report support for track dragging (PNS). --- pcbnew/router/pns_router.cpp | 4 ---- pcbnew/router/router_tool.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index a08b0f0fc7..72e001801c 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -373,13 +373,9 @@ void PNS_ROUTER::ClearWorld() if( m_placer ) delete m_placer; - if( m_previewItems ) - delete m_previewItems; - m_clearanceFunc = NULL; m_world = NULL; m_placer = NULL; - m_previewItems = NULL; } diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index db2c996a34..45e2d9d577 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -621,8 +621,6 @@ void ROUTER_TOOL::performRouting() m_needsSync = true; } - m_settings = m_router->Settings(); - ctls->SetAutoPan( false ); ctls->ForceCursorPosition( false ); highlightNet( false ); @@ -683,6 +681,8 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) ctls->ShowCursor( false ); getEditFrame()->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + // Store routing settings till the next invocation + m_settings = m_router->Settings(); delete ctxMenu; return 0; @@ -691,6 +691,8 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) void ROUTER_TOOL::performDragging() { + PCB_EDIT_FRAME* frame = getEditFrame(); + bool saveUndoBuffer = true; VIEW_CONTROLS* ctls = getViewControls(); bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem ); @@ -708,6 +710,11 @@ void ROUTER_TOOL::performDragging() { if( evt->IsCancel() ) break; + else if( evt->Action() == TA_UNDO_REDO ) + { + saveUndoBuffer = false; + break; + } else if( evt->IsMotion() ) { updateEndItem( *evt ); @@ -726,6 +733,19 @@ void ROUTER_TOOL::performDragging() if( m_router->RoutingInProgress() ) m_router->StopRouting(); + if( saveUndoBuffer ) + { + // Save the recent changes in the undo buffer + frame->SaveCopyInUndoList( m_router->GetUndoBuffer(), UR_UNSPECIFIED ); + m_router->ClearUndoBuffer(); + frame->OnModify(); + } + else + { + // It was interrupted by TA_UNDO_REDO event, so we have to sync the world now + m_needsSync = true; + } + ctls->SetAutoPan( false ); ctls->ForceCursorPosition( false ); highlightNet( false ); From f04997797bc80ed7ad3fc8ad0aaed2cb19b021da Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 19:04:21 +0200 Subject: [PATCH 62/68] Fixed freezing of GAL canvas if user chooses Cancel in the on close dialog.. --- pcbnew/pcbframe.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index d04541e200..597255c21d 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -591,7 +591,6 @@ void PCB_EDIT_FRAME::OnQuit( wxCommandEvent& event ) void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) { m_canvas->SetAbortRequest( true ); - GetGalCanvas()->StopDrawing(); if( GetScreen()->IsModify() ) { @@ -615,6 +614,8 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) } } + GetGalCanvas()->StopDrawing(); + // Delete the auto save file if it exists. wxFileName fn = GetBoard()->GetFileName(); From 7a526261fbd15e0529b322dc45c77439dfabd34c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 14 May 2014 19:15:25 +0200 Subject: [PATCH 63/68] PNS router deselects all items when started. --- pcbnew/router/router_tool.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 45e2d9d577..a983fac319 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -633,6 +633,9 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) BOARD* board = getModel( PCB_T ); BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings(); + // Deselect all items + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + getEditFrame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Interactive Router" ) ); ctls->SetSnapping( true ); From b2a5b2f3293dbc2f932edd6e5f662935ecd228ea Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 15 May 2014 10:11:17 +0200 Subject: [PATCH 64/68] Scripting fix. --- pcbnew/class_netclass.h | 6 +++--- pcbnew/scripting/pcbnew_scripting_helpers.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pcbnew/class_netclass.h b/pcbnew/class_netclass.h index 7085b3ebe3..0d79013df8 100644 --- a/pcbnew/class_netclass.h +++ b/pcbnew/class_netclass.h @@ -54,9 +54,9 @@ class NETCLASS { private: // Default values used to init a NETCLASS - const static int DEFAULT_CLEARANCE; - const static int DEFAULT_VIA_DRILL; - const static int DEFAULT_UVIA_DRILL; + static const int DEFAULT_CLEARANCE; + static const int DEFAULT_VIA_DRILL; + static const int DEFAULT_UVIA_DRILL; protected: wxString m_Name; ///< Name of the net class diff --git a/pcbnew/scripting/pcbnew_scripting_helpers.cpp b/pcbnew/scripting/pcbnew_scripting_helpers.cpp index 42a0a14391..62b21b3df1 100644 --- a/pcbnew/scripting/pcbnew_scripting_helpers.cpp +++ b/pcbnew/scripting/pcbnew_scripting_helpers.cpp @@ -86,7 +86,7 @@ bool SaveBoard( wxString& aFileName, BOARD* aBoard, { aBoard->m_Status_Pcb &= ~CONNEXION_OK; aBoard->SynchronizeNetsAndNetClasses(); - aBoard->SetCurrentNetClass( aBoard->m_NetClasses.GetDefault()->GetName() ); + aBoard->GetDesignSettings().SetCurrentNetClass( NETCLASS::Default ); #if 0 wxString header; From 4fcaf4c586222b52cefe51992b6f5810d28a87bc Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 15 May 2014 10:51:08 +0200 Subject: [PATCH 65/68] Minor BOARD_DESIGN_SETTINGS refactoring. Removed SetCurrentClassName() (it was not used anywhere and less safe than SetCurrentClass()). Added BOARD_DESIGN_SETTIGNS::GetDefault() to make some pieces of shorter and clearer. --- include/class_board_design_settings.h | 18 ++++++++++-------- pcbnew/autorouter/routing_matrix.cpp | 2 +- pcbnew/autorouter/solve.cpp | 2 +- pcbnew/class_board.cpp | 2 +- pcbnew/class_board_connected_item.cpp | 4 ++-- pcbnew/eagle_plugin.cpp | 2 +- pcbnew/files.cpp | 2 +- pcbnew/kicad_plugin.cpp | 12 ++++++------ pcbnew/legacy_plugin.cpp | 6 +++--- pcbnew/pcb_parser.cpp | 2 +- pcbnew/router/router_tool.cpp | 2 +- 11 files changed, 28 insertions(+), 26 deletions(-) diff --git a/include/class_board_design_settings.h b/include/class_board_design_settings.h index a22f3c5bb6..8d04fe0922 100644 --- a/include/class_board_design_settings.h +++ b/include/class_board_design_settings.h @@ -102,18 +102,22 @@ public: BOARD_DESIGN_SETTINGS(); /** - * Function SetCurrentNetClassName - * sets the current net class name to \a aName. - * - * @param aName is a reference to a wxString object containing the current net class name. + * Function GetDefault + * @return the default netclass. */ - void SetCurrentNetClassName( const wxString& aName ) { m_currentNetClassName = aName; } + inline NETCLASS* GetDefault() const + { + return m_NetClasses.GetDefault(); + } /** * Function GetCurrentNetClassName * @return the current net class name. */ - const wxString& GetCurrentNetClassName() const { return m_currentNetClassName; } + const wxString& GetCurrentNetClassName() const + { + return m_currentNetClassName; + } /** * Function SetCurrentNetClass @@ -275,8 +279,6 @@ public: return m_customViaSize.m_Drill; } - // TODO microvia methods should go here - /** * Function UseCustomTrackViaSize * Enables/disables custom track/via size settings. If enabled, values set with diff --git a/pcbnew/autorouter/routing_matrix.cpp b/pcbnew/autorouter/routing_matrix.cpp index 9d87b52bda..ee1890bf2a 100644 --- a/pcbnew/autorouter/routing_matrix.cpp +++ b/pcbnew/autorouter/routing_matrix.cpp @@ -201,7 +201,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) LAYER_MSK layerMask; // use the default NETCLASS? - NETCLASS* nc = aPcb->GetDesignSettings().m_NetClasses.GetDefault(); + NETCLASS* nc = aPcb->GetDesignSettings().GetDefault(); int trackWidth = nc->GetTrackWidth(); int clearance = nc->GetClearance(); diff --git a/pcbnew/autorouter/solve.cpp b/pcbnew/autorouter/solve.cpp index c1f66b5423..0e0120c458 100644 --- a/pcbnew/autorouter/solve.cpp +++ b/pcbnew/autorouter/solve.cpp @@ -280,7 +280,7 @@ int PCB_EDIT_FRAME::Solve( wxDC* DC, int aLayersCount ) m_canvas->SetAbortRequest( false ); - s_Clearance = GetBoard()->GetDesignSettings().m_NetClasses.GetDefault()->GetClearance(); + s_Clearance = GetBoard()->GetDesignSettings().GetDefault()->GetClearance(); // Prepare the undo command info s_ItemsListPicker.ClearListAndDeleteItems(); // Should not be necessary, but... diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index c05474d29f..2fc5fa7d3e 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -91,7 +91,7 @@ BOARD::BOARD() : m_Layer[layer].m_Type = LT_UNDEFINED; } - NETCLASS* defaultClass = m_designSettings.m_NetClasses.GetDefault(); + NETCLASS* defaultClass = m_designSettings.GetDefault(); defaultClass->SetDescription( _( "This is the default net class." ) ); // Initialize default values in default netclass. diff --git a/pcbnew/class_board_connected_item.cpp b/pcbnew/class_board_connected_item.cpp index 9aaa6d14ad..0b91036802 100644 --- a/pcbnew/class_board_connected_item.cpp +++ b/pcbnew/class_board_connected_item.cpp @@ -144,7 +144,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const if( netclass ) return netclass; else - return board->GetDesignSettings().m_NetClasses.GetDefault(); + return board->GetDesignSettings().GetDefault(); } @@ -158,7 +158,7 @@ wxString BOARD_CONNECTED_ITEM::GetNetClassName() const else { BOARD* board = GetBoard(); - name = board->GetDesignSettings().m_NetClasses.GetDefault()->GetName(); + name = NETCLASS::Default; } return name; diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index b1da39fc6f..2e59478403 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -1146,7 +1146,7 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const if( m_rules->mdWireWire ) { - NETCLASS* defaultNetclass = designSettings.m_NetClasses.GetDefault(); + NETCLASS* defaultNetclass = designSettings.GetDefault(); int clearance = KiROUND( m_rules->mdWireWire ); if( clearance < defaultNetclass->GetClearance() ) diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 89671c066b..10eaa4be0a 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -678,7 +678,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF // Select default Netclass before writing file. // Useful to save default values in headers - GetDesignSettings().SetCurrentNetClass( GetDesignSettings().m_NetClasses.GetDefault()->GetName() ); + GetDesignSettings().SetCurrentNetClass( NETCLASS::Default ); try { diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index adf5ce76eb..f77c4dfbb4 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -572,7 +572,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const FMTIU( dsnSettings.m_TrackWidthList[ii] ).c_str() ); m_out->Print( aNestLevel+1, "(trace_clearance %s)\n", - FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetClearance() ).c_str() ); + FMTIU( dsnSettings.GetDefault()->GetClearance() ).c_str() ); // ZONE_SETTINGS m_out->Print( aNestLevel+1, "(zone_clearance %s)\n", @@ -590,9 +590,9 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const // Save current default via size, for compatibility with older Pcbnew version; m_out->Print( aNestLevel+1, "(via_size %s)\n", - FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetViaDiameter() ).c_str() ); + FMTIU( dsnSettings.GetDefault()->GetViaDiameter() ).c_str() ); m_out->Print( aNestLevel+1, "(via_drill %s)\n", - FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetViaDrill() ).c_str() ); + FMTIU( dsnSettings.GetDefault()->GetViaDrill() ).c_str() ); m_out->Print( aNestLevel+1, "(via_min_size %s)\n", FMTIU( dsnSettings.m_ViasMinSize ).c_str() ); m_out->Print( aNestLevel+1, "(via_min_drill %s)\n", @@ -610,9 +610,9 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const m_out->Print( aNestLevel+1, "(blind_buried_vias_allowed yes)\n" ); m_out->Print( aNestLevel+1, "(uvia_size %s)\n", - FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetuViaDiameter() ).c_str() ); + FMTIU( dsnSettings.GetDefault()->GetuViaDiameter() ).c_str() ); m_out->Print( aNestLevel+1, "(uvia_drill %s)\n", - FMTIU( dsnSettings.m_NetClasses.GetDefault()->GetuViaDrill() ).c_str() ); + FMTIU( dsnSettings.GetDefault()->GetuViaDrill() ).c_str() ); m_out->Print( aNestLevel+1, "(uvias_allowed %s)\n", ( dsnSettings.m_MicroViasAllowed ) ? "yes" : "no" ); m_out->Print( aNestLevel+1, "(uvia_min_size %s)\n", @@ -683,7 +683,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const m_out->Print( 0, "\n" ); // Save the default net class first. - NETCLASS defaultNC = *dsnSettings.m_NetClasses.GetDefault(); + NETCLASS defaultNC = *dsnSettings.GetDefault(); filterNetClass( *aBoard, defaultNC ); // Remove empty nets (from a copy of a netclass) defaultNC.Format( m_out, aNestLevel, m_ctl ); diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index 77a4d14a0e..f2f174267b 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -632,7 +632,7 @@ void LEGACY_PLUGIN::loadSHEET() void LEGACY_PLUGIN::loadSETUP() { - NETCLASS* netclass_default = m_board->GetDesignSettings().m_NetClasses.GetDefault(); + NETCLASS* netclass_default = m_board->GetDesignSettings().GetDefault(); // TODO Orson: is it really necessary to first operate on a copy and then apply it? // would not it be better to use reference here and apply all the changes instantly? BOARD_DESIGN_SETTINGS bds = m_board->GetDesignSettings(); @@ -897,7 +897,7 @@ void LEGACY_PLUGIN::loadSETUP() // at all, the global defaults should go into a preferences // file instead so they are there to start new board // projects. - m_board->GetDesignSettings().m_NetClasses.GetDefault()->SetParams( m_board->GetDesignSettings() ); + m_board->GetDesignSettings().GetDefault()->SetParams( m_board->GetDesignSettings() ); return; // preferred exit } @@ -2985,7 +2985,7 @@ void LEGACY_PLUGIN::saveSHEET( const BOARD* aBoard ) const void LEGACY_PLUGIN::saveSETUP( const BOARD* aBoard ) const { const BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings(); - NETCLASS* netclass_default = bds.m_NetClasses.GetDefault(); + NETCLASS* netclass_default = bds.GetDefault(); fprintf( m_fp, "$SETUP\n" ); diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 77586e843f..547120fa9b 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -808,7 +808,7 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) ); T token; - NETCLASS* defaultNetClass = m_board->GetDesignSettings().m_NetClasses.GetDefault(); + NETCLASS* defaultNetClass = m_board->GetDesignSettings().GetDefault(); // TODO Orson: is it really necessary to first operate on a copy and then apply it? // would not it be better to use reference here and apply all the changes instantly? BOARD_DESIGN_SETTINGS designSettings = m_board->GetDesignSettings(); diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index a983fac319..e0f4a2068a 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -279,7 +279,7 @@ void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth, } if( !netClass ) - netClass = bds.m_NetClasses.GetDefault(); + netClass = bds.GetDefault(); aWidth = netClass->GetTrackWidth(); aViaDiameter = netClass->GetViaDiameter(); From ebf35fd43ae18b2b1d78e51e796a1176a4e56649 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 15 May 2014 17:08:15 +0200 Subject: [PATCH 66/68] Workaround for Mac OS, fixes focus after a mouse click. --- common/tool/tool_dispatcher.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp index 502dccfbdb..4e66a1271c 100644 --- a/common/tool/tool_dispatcher.cpp +++ b/common/tool/tool_dispatcher.cpp @@ -240,6 +240,13 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods ); evt->SetMousePosition( pos ); } + +#ifdef __APPLE__ + // TODO That's a big ugly workaround, somehow DRAWPANEL_GAL loses focus + // after second LMB click and currently I have no means to do better debugging + if( type == wxEVT_LEFT_UP ) + m_editFrame->GetGalCanvas()->SetFocus(); +#endif /* __APPLE__ */ } // Keyboard handling From ad1b138f28928ed1908cb2778e499e6313c6213d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 16 May 2014 13:37:31 +0200 Subject: [PATCH 67/68] Reformatted PNS code to conform the coding policy. --- pcbnew/router/direction.h | 34 +- pcbnew/router/pns_algo_base.h | 15 +- pcbnew/router/pns_dragger.cpp | 140 +++--- pcbnew/router/pns_dragger.h | 55 +-- pcbnew/router/pns_index.h | 42 +- pcbnew/router/pns_item.cpp | 4 +- pcbnew/router/pns_item.h | 20 +- pcbnew/router/pns_itemset.cpp | 35 +- pcbnew/router/pns_itemset.h | 27 +- pcbnew/router/pns_joint.h | 72 +-- pcbnew/router/pns_layerset.h | 12 +- pcbnew/router/pns_line.cpp | 460 +++++++++-------- pcbnew/router/pns_line.h | 58 +-- pcbnew/router/pns_line_placer.cpp | 212 ++++---- pcbnew/router/pns_line_placer.h | 26 +- pcbnew/router/pns_logger.cpp | 99 ++-- pcbnew/router/pns_logger.h | 21 +- pcbnew/router/pns_node.cpp | 409 +++++++-------- pcbnew/router/pns_node.h | 125 +++-- pcbnew/router/pns_optimizer.cpp | 138 +++--- pcbnew/router/pns_optimizer.h | 38 +- pcbnew/router/pns_router.cpp | 288 +++++------ pcbnew/router/pns_router.h | 47 +- pcbnew/router/pns_routing_settings.cpp | 4 +- pcbnew/router/pns_routing_settings.h | 15 +- pcbnew/router/pns_segment.h | 13 +- pcbnew/router/pns_shove.cpp | 655 +++++++++++++------------ pcbnew/router/pns_shove.h | 82 ++-- pcbnew/router/pns_solid.cpp | 34 +- pcbnew/router/pns_solid.h | 5 +- pcbnew/router/pns_utils.cpp | 25 +- pcbnew/router/pns_utils.h | 7 +- pcbnew/router/pns_via.cpp | 27 +- pcbnew/router/pns_via.h | 26 +- pcbnew/router/pns_walkaround.cpp | 69 ++- pcbnew/router/pns_walkaround.h | 39 +- pcbnew/router/range.h | 48 +- pcbnew/router/router_preview_item.cpp | 135 +++-- pcbnew/router/router_preview_item.h | 13 +- pcbnew/router/router_tool.cpp | 124 ++--- pcbnew/router/router_tool.h | 4 +- pcbnew/router/time_limit.cpp | 15 +- pcbnew/router/time_limit.h | 14 +- pcbnew/router/trace.h | 4 +- 44 files changed, 1940 insertions(+), 1795 deletions(-) diff --git a/pcbnew/router/direction.h b/pcbnew/router/direction.h index 646c681cd2..cd872fccb5 100644 --- a/pcbnew/router/direction.h +++ b/pcbnew/router/direction.h @@ -209,12 +209,12 @@ public: // we are more horizontal than vertical? if( w > h ) { - mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E + mp0 = VECTOR2I( ( w - h ) * sw, 0 ); // direction: E mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE } else { - mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N + mp0 = VECTOR2I( 0, sh * ( h - w ) ); // direction: N mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE } @@ -237,7 +237,7 @@ public: pl.Append( aP1 ); pl.Simplify(); return pl; - }; + } bool operator==( const DIRECTION_45& aOther ) const { @@ -275,19 +275,17 @@ public: { DIRECTION_45 l; - if (m_dir == UNDEFINED) + if ( m_dir == UNDEFINED ) return l; - if(m_dir == N) + if( m_dir == N ) l.m_dir = NW; else - l.m_dir = static_cast (m_dir - 1); + l.m_dir = static_cast( m_dir - 1 ); return l; } - - /** * Function ToVector() * @@ -295,19 +293,19 @@ public: */ const VECTOR2I ToVector() const { - switch(m_dir) + switch( m_dir ) { - case N: return VECTOR2I(0, 1); - case S: return VECTOR2I(0, -1); - case E: return VECTOR2I(1, 0); - case W: return VECTOR2I(-1, 0); - case NE: return VECTOR2I(1, 1); - case NW: return VECTOR2I(-1, 1); - case SE: return VECTOR2I(1, -1); - case SW: return VECTOR2I(-1, -1); + case N: return VECTOR2I( 0, 1 ); + case S: return VECTOR2I( 0, -1 ); + case E: return VECTOR2I( 1, 0 ); + case W: return VECTOR2I( -1, 0 ); + case NE: return VECTOR2I( 1, 1 ); + case NW: return VECTOR2I( -1, 1 ); + case SE: return VECTOR2I( 1, -1 ); + case SW: return VECTOR2I( -1, -1 ); default: - return VECTOR2I(0, 0); + return VECTOR2I( 0, 0 ); } } diff --git a/pcbnew/router/pns_algo_base.h b/pcbnew/router/pns_algo_base.h index c274c15116..1aa94333fc 100644 --- a/pcbnew/router/pns_algo_base.h +++ b/pcbnew/router/pns_algo_base.h @@ -33,17 +33,18 @@ class PNS_LOGGER; * Holds a bunch of objects commonly used by all algorithms (P&S settings, parent router instance, logging) **/ -class PNS_ALGO_BASE { - +class PNS_ALGO_BASE +{ public: - PNS_ALGO_BASE ( PNS_ROUTER *aRouter ): + PNS_ALGO_BASE( PNS_ROUTER *aRouter ) : m_router ( aRouter ) - {}; + {} virtual ~PNS_ALGO_BASE() {} ///> Returns the instance of our router - PNS_ROUTER *Router() const { + PNS_ROUTER* Router() const + { return m_router; } @@ -51,10 +52,10 @@ public: PNS_ROUTING_SETTINGS& Settings() const; ///> Returns the logger object, allowing to dump geometry to a file. - virtual PNS_LOGGER *Logger(); + virtual PNS_LOGGER* Logger(); private: - PNS_ROUTER *m_router; + PNS_ROUTER* m_router; }; #endif diff --git a/pcbnew/router/pns_dragger.cpp b/pcbnew/router/pns_dragger.cpp index 5361c641ec..bc43858d95 100644 --- a/pcbnew/router/pns_dragger.cpp +++ b/pcbnew/router/pns_dragger.cpp @@ -29,7 +29,8 @@ PNS_DRAGGER::PNS_DRAGGER( PNS_ROUTER* aRouter ) : { m_world = NULL; m_shove = NULL; -}; +} + PNS_DRAGGER::~PNS_DRAGGER() { @@ -37,97 +38,103 @@ PNS_DRAGGER::~PNS_DRAGGER() delete m_shove; } -void PNS_DRAGGER::SetWorld ( PNS_NODE *aWorld ) + +void PNS_DRAGGER::SetWorld ( PNS_NODE* aWorld ) { m_world = aWorld; } -bool PNS_DRAGGER::startDragSegment( const VECTOR2D& aP, PNS_SEGMENT *aSeg ) + +bool PNS_DRAGGER::startDragSegment( const VECTOR2D& aP, PNS_SEGMENT* aSeg ) { int w2 = aSeg->Width() / 2; m_draggedLine = m_world->AssembleLine ( aSeg, &m_draggedSegmentIndex ); - m_shove->SetInitialLine (m_draggedLine); + m_shove->SetInitialLine( m_draggedLine ); m_lastValidDraggedLine = *m_draggedLine; m_lastValidDraggedLine.ClearSegmentLinks(); - if( (aP - aSeg->Seg().A).EuclideanNorm() <= w2 ) + if( ( aP - aSeg->Seg().A ).EuclideanNorm() <= w2 ) m_mode = CORNER; - else if( (aP - aSeg->Seg().B).EuclideanNorm() <= w2 ) + else if( ( aP - aSeg->Seg().B ).EuclideanNorm() <= w2 ) { m_draggedSegmentIndex ++; m_mode = CORNER; } else m_mode = SEGMENT; + return true; } -bool PNS_DRAGGER::startDragVia( const VECTOR2D& aP, PNS_VIA *aVia ) + +bool PNS_DRAGGER::startDragVia( const VECTOR2D& aP, PNS_VIA* aVia ) { m_draggedVia = aVia; m_initialVia = aVia; m_mode = VIA; - VECTOR2I p0 ( aVia->Pos() ); + VECTOR2I p0( aVia->Pos() ); PNS_JOINT *jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() ); BOOST_FOREACH(PNS_ITEM *item, jt->LinkList() ) { - if(item->OfKind( PNS_ITEM::SEGMENT )) + if( item->OfKind( PNS_ITEM::SEGMENT ) ) { int segIndex; - PNS_SEGMENT *seg = (PNS_SEGMENT *) item; - std::auto_ptr l ( m_world->AssembleLine(seg, &segIndex) ); - - if(segIndex != 0) + PNS_SEGMENT* seg = (PNS_SEGMENT*) item; + std::auto_ptr l( m_world->AssembleLine( seg, &segIndex ) ); + + if( segIndex != 0 ) l->Reverse(); - m_origViaConnections.push_back (*l); - + m_origViaConnections.push_back( *l ); } } - return true; } -bool PNS_DRAGGER::Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem ) + +bool PNS_DRAGGER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) { - m_shove = new PNS_SHOVE ( m_world, Router() ); + m_shove = new PNS_SHOVE( m_world, Router() ); m_lastNode = NULL; m_draggedItems.Clear(); m_currentMode = Settings().Mode(); - TRACE(2, "StartDragging: item %p [kind %d]", aStartItem % aStartItem->Kind()); + TRACE( 2, "StartDragging: item %p [kind %d]", aStartItem % aStartItem->Kind() ); switch( aStartItem->Kind() ) { case PNS_ITEM::SEGMENT: - return startDragSegment ( aP, static_cast (aStartItem) ); + return startDragSegment ( aP, static_cast( aStartItem ) ); + case PNS_ITEM::VIA: return startDragVia ( aP, static_cast (aStartItem) ); + default: return false; } } -bool PNS_DRAGGER::dragMarkObstacles(const VECTOR2I& aP) + +bool PNS_DRAGGER::dragMarkObstacles( const VECTOR2I& aP ) { - if(m_lastNode) + if( m_lastNode ) { delete m_lastNode; m_lastNode = NULL; } - switch(m_mode) + switch( m_mode ) { case SEGMENT: case CORNER: { int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0; - PNS_LINE tmp (*m_draggedLine); + PNS_LINE tmp( *m_draggedLine ); - if(m_mode == SEGMENT) + if( m_mode == SEGMENT ) tmp.DragSegment ( aP, m_draggedSegmentIndex, thresh ); else tmp.DragCorner ( aP, m_draggedSegmentIndex, thresh ); @@ -143,17 +150,17 @@ bool PNS_DRAGGER::dragMarkObstacles(const VECTOR2I& aP) break; } + case VIA: // fixme... { m_lastNode = m_shove->CurrentNode()->Branch(); dumbDragVia ( m_initialVia, m_lastNode, aP ); - break; } } - if (Settings().CanViolateDRC()) + if( Settings().CanViolateDRC() ) m_dragStatus = true; else m_dragStatus = !m_world->CheckColliding( m_draggedItems ); @@ -161,60 +168,62 @@ bool PNS_DRAGGER::dragMarkObstacles(const VECTOR2I& aP) return true; } -void PNS_DRAGGER::dumbDragVia ( PNS_VIA *aVia, PNS_NODE *aNode, const VECTOR2I& aP ) + +void PNS_DRAGGER::dumbDragVia( PNS_VIA* aVia, PNS_NODE* aNode, const VECTOR2I& aP ) { // fixme: this is awful. m_draggedVia = aVia->Clone(); m_draggedVia->SetPos( aP ); m_draggedItems.Clear(); - m_draggedItems.Add(m_draggedVia); + m_draggedItems.Add( m_draggedVia ); - m_lastNode->Remove ( aVia ); - m_lastNode->Add ( m_draggedVia ); + m_lastNode->Remove( aVia ); + m_lastNode->Add( m_draggedVia ); - BOOST_FOREACH(PNS_LINE &l, m_origViaConnections) + BOOST_FOREACH( PNS_LINE &l, m_origViaConnections ) { PNS_LINE origLine (l); - PNS_LINE *draggedLine = l.Clone(); + PNS_LINE* draggedLine = l.Clone(); draggedLine->DragCorner( aP, 0 ); draggedLine->ClearSegmentLinks(); m_draggedItems.AddOwned( draggedLine ); - m_lastNode->Remove ( &origLine ); - m_lastNode->Add ( draggedLine ); + m_lastNode->Remove( &origLine ); + m_lastNode->Add( draggedLine ); } } -bool PNS_DRAGGER::dragShove(const VECTOR2I& aP) + +bool PNS_DRAGGER::dragShove( const VECTOR2I& aP ) { bool ok = false; - - if(m_lastNode) + if( m_lastNode ) { delete m_lastNode; m_lastNode = NULL; } - switch(m_mode) + switch( m_mode ) { case SEGMENT: case CORNER: { int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0; - PNS_LINE tmp (*m_draggedLine); - if(m_mode == SEGMENT) - tmp.DragSegment ( aP, m_draggedSegmentIndex, thresh ); + PNS_LINE tmp( *m_draggedLine ); + + if( m_mode == SEGMENT ) + tmp.DragSegment( aP, m_draggedSegmentIndex, thresh ); else - tmp.DragCorner ( aP, m_draggedSegmentIndex, thresh ); + tmp.DragCorner( aP, m_draggedSegmentIndex, thresh ); - PNS_SHOVE::ShoveStatus st = m_shove->ShoveLines( tmp ); + PNS_SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( tmp ); - if(st == PNS_SHOVE::SH_OK) + if( st == PNS_SHOVE::SH_OK ) ok = true; - else if (st == PNS_SHOVE::SH_HEAD_MODIFIED) + else if( st == PNS_SHOVE::SH_HEAD_MODIFIED ) { tmp = m_shove->NewHead(); ok = true; @@ -222,22 +231,23 @@ bool PNS_DRAGGER::dragShove(const VECTOR2I& aP) m_lastNode = m_shove->CurrentNode()->Branch(); - if(ok) + if( ok ) m_lastValidDraggedLine = tmp; m_lastValidDraggedLine.ClearSegmentLinks(); m_lastValidDraggedLine.Unmark(); - m_lastNode->Add ( &m_lastValidDraggedLine ); - m_draggedItems = PNS_ITEMSET ( &m_lastValidDraggedLine ); + m_lastNode->Add( &m_lastValidDraggedLine ); + m_draggedItems = PNS_ITEMSET( &m_lastValidDraggedLine ); break; } + case VIA: { PNS_VIA *newVia; - PNS_SHOVE::ShoveStatus st = m_shove -> ShoveDraggingVia ( m_draggedVia, aP, &newVia ); + PNS_SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, &newVia ); - if(st == PNS_SHOVE::SH_OK || st == PNS_SHOVE::SH_HEAD_MODIFIED) + if( st == PNS_SHOVE::SH_OK || st == PNS_SHOVE::SH_HEAD_MODIFIED ) ok = true; m_lastNode = m_shove->CurrentNode()->Branch(); @@ -250,16 +260,17 @@ bool PNS_DRAGGER::dragShove(const VECTOR2I& aP) break; } - } m_dragStatus = ok; + return ok; } -bool PNS_DRAGGER::FixRoute( ) + +bool PNS_DRAGGER::FixRoute() { - if(m_dragStatus) + if( m_dragStatus ) { Router()->CommitRouting( CurrentNode() ); return true; @@ -267,35 +278,42 @@ bool PNS_DRAGGER::FixRoute( ) return false; } - -bool PNS_DRAGGER::Drag ( const VECTOR2I& aP ) + + +bool PNS_DRAGGER::Drag( const VECTOR2I& aP ) { - switch ( m_currentMode ) + switch( m_currentMode ) { case RM_MarkObstacles: - return dragMarkObstacles (aP); + return dragMarkObstacles( aP ); + case RM_Shove: case RM_Walkaround: case RM_Smart: - return dragShove ( aP ); + return dragShove( aP ); + default: return false; } } + PNS_NODE *PNS_DRAGGER::CurrentNode() const { return m_lastNode; } + const PNS_ITEMSET PNS_DRAGGER::Traces() { return m_draggedItems; } -PNS_LOGGER *PNS_DRAGGER::Logger() + +PNS_LOGGER* PNS_DRAGGER::Logger() { - if(m_shove) + if( m_shove ) return m_shove->Logger(); + return NULL; } diff --git a/pcbnew/router/pns_dragger.h b/pcbnew/router/pns_dragger.h index 73d206589d..171b8ac79e 100644 --- a/pcbnew/router/pns_dragger.h +++ b/pcbnew/router/pns_dragger.h @@ -39,12 +39,10 @@ class PNS_ROUTER_BASE; * * Via, segment and corner dragging algorithm. */ - class PNS_DRAGGER : public PNS_ALGO_BASE { public: - - PNS_DRAGGER( PNS_ROUTER *aRouter ); + PNS_DRAGGER( PNS_ROUTER* aRouter ); ~PNS_DRAGGER(); /** @@ -52,8 +50,7 @@ public: * * Sets the board to work on. */ - void SetWorld ( PNS_NODE *aWorld ); - + void SetWorld( PNS_NODE* aWorld ); /** * Function Start() @@ -61,7 +58,7 @@ public: * Starts routing a single track at point aP, taking item aStartItem as anchor * (unless NULL). Returns true if a dragging operation has started. */ - bool Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem ); + bool Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ); /** * Function Drag() @@ -69,7 +66,7 @@ public: * Drags the current segment/corner/via to the point aP. * @return true, if dragging finished with success. */ - bool Drag ( const VECTOR2I& aP ); + bool Drag( const VECTOR2I& aP ); /** * Function FixRoute() @@ -78,7 +75,7 @@ public: * and eventually commits it to the world. * @return true, if dragging finished with success. */ - bool FixRoute ( ); + bool FixRoute(); /** * Function CurrentNode() @@ -86,7 +83,6 @@ public: * Returns the most recent world state, including all * items changed due to dragging operation. */ - PNS_NODE* CurrentNode() const; /** @@ -97,11 +93,10 @@ public: const PNS_ITEMSET Traces(); /// @copydoc PNS_ALGO_BASE::Logger() - virtual PNS_LOGGER *Logger(); + virtual PNS_LOGGER* Logger(); private: - - typedef std::pair LinePair; + typedef std::pair LinePair; typedef std::vector LinePairVec; enum DragMode { @@ -110,26 +105,26 @@ private: VIA }; - bool dragMarkObstacles(const VECTOR2I& aP); - bool dragShove(const VECTOR2I& aP); - bool startDragSegment( const VECTOR2D& aP, PNS_SEGMENT *aSeg ); - bool startDragVia( const VECTOR2D& aP, PNS_VIA *aVia ); - void dumbDragVia ( PNS_VIA *aVia, PNS_NODE *aNode, const VECTOR2I& aP ); + bool dragMarkObstacles( const VECTOR2I& aP ); + bool dragShove(const VECTOR2I& aP ); + bool startDragSegment( const VECTOR2D& aP, PNS_SEGMENT* aSeg ); + bool startDragVia( const VECTOR2D& aP, PNS_VIA* aVia ); + void dumbDragVia( PNS_VIA* aVia, PNS_NODE* aNode, const VECTOR2I& aP ); - PNS_NODE * m_world; - PNS_NODE * m_lastNode; - DragMode m_mode; - PNS_LINE * m_draggedLine; - PNS_VIA * m_draggedVia; - PNS_LINE m_lastValidDraggedLine; - PNS_SHOVE * m_shove; - int m_draggedSegmentIndex; - bool m_dragStatus; + PNS_NODE* m_world; + PNS_NODE* m_lastNode; + DragMode m_mode; + PNS_LINE* m_draggedLine; + PNS_VIA* m_draggedVia; + PNS_LINE m_lastValidDraggedLine; + PNS_SHOVE* m_shove; + int m_draggedSegmentIndex; + bool m_dragStatus; PNS_MODE m_currentMode; - std::vector m_origViaConnections; - std::vector m_draggedViaConnections; - PNS_VIA * m_initialVia; - PNS_ITEMSET m_draggedItems; + std::vector m_origViaConnections; + std::vector m_draggedViaConnections; + PNS_VIA* m_initialVia; + PNS_ITEMSET m_draggedItems; }; #endif diff --git a/pcbnew/router/pns_index.h b/pcbnew/router/pns_index.h index 841f61bc1a..edb58b33e4 100644 --- a/pcbnew/router/pns_index.h +++ b/pcbnew/router/pns_index.h @@ -39,13 +39,12 @@ * are assigned to separate R-Tree subindices depending on their type and spanned layers, reducing * overlap and improving search time. **/ - class PNS_INDEX { public: - typedef std::list NetItemsList; - typedef SHAPE_INDEX ItemShapeIndex; - typedef boost::unordered_set ItemSet; + typedef std::list NET_ITEMS_LIST; + typedef SHAPE_INDEX ITEM_SHAPE_INDEX; + typedef boost::unordered_set ITEM_SET; PNS_INDEX(); ~PNS_INDEX(); @@ -115,7 +114,7 @@ public: * * Returns list of all items in a given net. */ - NetItemsList* GetItemsForNet( int aNet ); + NET_ITEMS_LIST* GetItemsForNet( int aNet ); /** * Function Contains() @@ -134,36 +133,35 @@ public: */ int Size() const { return m_allItems.size(); } - ItemSet::iterator begin() { return m_allItems.begin(); } - ItemSet::iterator end() { return m_allItems.end(); } + ITEM_SET::iterator begin() { return m_allItems.begin(); } + ITEM_SET::iterator end() { return m_allItems.end(); } private: static const int MaxSubIndices = 64; static const int SI_Multilayer = 2; static const int SI_SegDiagonal = 0; static const int SI_SegStraight = 1; - static const int SI_Traces = 3; - static const int SI_PadsTop = 0; - static const int SI_PadsBottom = 1; + static const int SI_Traces = 3; + static const int SI_PadsTop = 0; + static const int SI_PadsBottom = 1; template int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ); - ItemShapeIndex* getSubindex( const PNS_ITEM* aItem ); + ITEM_SHAPE_INDEX* getSubindex( const PNS_ITEM* aItem ); - ItemShapeIndex* m_subIndices[MaxSubIndices]; - std::map m_netMap; - ItemSet m_allItems; + ITEM_SHAPE_INDEX* m_subIndices[MaxSubIndices]; + std::map m_netMap; + ITEM_SET m_allItems; }; - PNS_INDEX::PNS_INDEX() { memset( m_subIndices, 0, sizeof( m_subIndices ) ); } -PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) +PNS_INDEX::ITEM_SHAPE_INDEX* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) { int idx_n = -1; @@ -199,7 +197,7 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) assert( idx_n >= 0 && idx_n < MaxSubIndices ); if( !m_subIndices[idx_n] ) - m_subIndices[idx_n] = new ItemShapeIndex; + m_subIndices[idx_n] = new ITEM_SHAPE_INDEX; return m_subIndices[idx_n]; } @@ -207,10 +205,8 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) void PNS_INDEX::Add( PNS_ITEM* aItem ) { - ItemShapeIndex* idx = getSubindex( aItem ); + ITEM_SHAPE_INDEX* idx = getSubindex( aItem ); - - idx->Add( aItem ); m_allItems.insert( aItem ); int net = aItem->Net(); @@ -224,7 +220,7 @@ void PNS_INDEX::Add( PNS_ITEM* aItem ) void PNS_INDEX::Remove( PNS_ITEM* aItem ) { - ItemShapeIndex* idx = getSubindex( aItem ); + ITEM_SHAPE_INDEX* idx = getSubindex( aItem ); idx->Remove( aItem ); m_allItems.erase( aItem ); @@ -303,7 +299,7 @@ void PNS_INDEX::Clear() { for( int i = 0; i < MaxSubIndices; ++i ) { - ItemShapeIndex* idx = m_subIndices[i]; + ITEM_SHAPE_INDEX* idx = m_subIndices[i]; if( idx ) delete idx; @@ -319,7 +315,7 @@ PNS_INDEX::~PNS_INDEX() } -PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet ) +PNS_INDEX::NET_ITEMS_LIST* PNS_INDEX::GetItemsForNet( int aNet ) { if( m_netMap.find( aNet ) == m_netMap.end() ) return NULL; diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp index 6ec4b77989..67fd14ad7b 100644 --- a/pcbnew/router/pns_item.cpp +++ b/pcbnew/router/pns_item.cpp @@ -50,8 +50,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, const PNS_LINE* line = static_cast( aOther ); if( line->EndsWithVia() ) - return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV, - aMTV ); + return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV, aMTV ); } return false; @@ -85,5 +84,4 @@ const std::string PNS_ITEM::KindStr() const PNS_ITEM::~PNS_ITEM() { - } diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index 0bc03b8ba7..cf1e24b1c6 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -91,7 +91,7 @@ public: * * Returns a deep copy of the item */ - virtual PNS_ITEM* Clone( ) const = 0; + virtual PNS_ITEM* Clone() const = 0; /* * Function Hull() @@ -104,7 +104,7 @@ public: virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const { return SHAPE_LINE_CHAIN(); - }; + } /** * Function Kind() @@ -123,7 +123,7 @@ public: */ bool OfKind( int aKindMask ) const { - return (aKindMask & m_kind) != 0; + return ( aKindMask & m_kind ) != 0; } /** @@ -219,7 +219,7 @@ public: * Returns true if the set of layers spanned by aOther overlaps our * layers. */ - bool LayersOverlap( const PNS_ITEM *aOther ) const + bool LayersOverlap( const PNS_ITEM* aOther ) const { return Layers().Overlaps( aOther->Layers() ); } @@ -252,7 +252,6 @@ public: */ PNS_NODE* Owner() const { return m_owner; } - /** * Function Collide() * @@ -308,7 +307,7 @@ public: return m_marker; } - virtual void SetRank ( int aRank ) + virtual void SetRank( int aRank ) { m_rank = aRank; } @@ -318,10 +317,10 @@ public: return m_rank; } - virtual VECTOR2I Anchor(int n) const + virtual VECTOR2I Anchor( int n ) const { return VECTOR2I (); - }; + } virtual int AnchorCount() const { @@ -329,15 +328,14 @@ public: } private: - bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; protected: PnsKind m_kind; - BOARD_CONNECTED_ITEM *m_parent; - PNS_NODE *m_owner; + BOARD_CONNECTED_ITEM* m_parent; + PNS_NODE* m_owner; PNS_LAYERSET m_layers; bool m_movable; diff --git a/pcbnew/router/pns_itemset.cpp b/pcbnew/router/pns_itemset.cpp index fccc5eccae..20254b94c0 100644 --- a/pcbnew/router/pns_itemset.cpp +++ b/pcbnew/router/pns_itemset.cpp @@ -22,8 +22,7 @@ #include "pns_itemset.h" - -PNS_ITEMSET::PNS_ITEMSET( PNS_ITEM *aInitialItem ) +PNS_ITEMSET::PNS_ITEMSET( PNS_ITEM* aInitialItem ) { if(aInitialItem) m_items.push_back(aInitialItem); @@ -38,7 +37,7 @@ PNS_ITEMSET::~PNS_ITEMSET() void PNS_ITEMSET::Clear() { - BOOST_FOREACH(PNS_ITEM *item, m_ownedItems) + BOOST_FOREACH(PNS_ITEM* item, m_ownedItems) { delete item; } @@ -47,9 +46,10 @@ void PNS_ITEMSET::Clear() m_ownedItems.clear(); } + PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd ) { - ItemVector newItems; + ITEM_VECTOR newItems; PNS_LAYERSET l; if( aEnd < 0 ) @@ -57,39 +57,44 @@ PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd ) else l = PNS_LAYERSET( aStart, aEnd ); - BOOST_FOREACH( PNS_ITEM * item, m_items ) + BOOST_FOREACH( PNS_ITEM* item, m_items ) if( item->Layers().Overlaps( l ) ) newItems.push_back( item ); m_items = newItems; + return *this; } PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask ) { - ItemVector newItems; + ITEM_VECTOR newItems; - BOOST_FOREACH( PNS_ITEM * item, m_items ) - - if( item->OfKind ( aKindMask ) ) - newItems.push_back( item ); + BOOST_FOREACH( PNS_ITEM* item, m_items ) + { + if( item->OfKind ( aKindMask ) ) + newItems.push_back( item ); + } m_items = newItems; + return *this; } PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet ) { - ItemVector newItems; + ITEM_VECTOR newItems; - BOOST_FOREACH( PNS_ITEM * item, m_items ) - - if( item->Net() == aNet ) - newItems.push_back( item ); + BOOST_FOREACH( PNS_ITEM* item, m_items ) + { + if( item->Net() == aNet ) + newItems.push_back( item ); + } m_items = newItems; + return *this; } diff --git a/pcbnew/router/pns_itemset.h b/pcbnew/router/pns_itemset.h index 9a6aaab3a8..44fe9c3c92 100644 --- a/pcbnew/router/pns_itemset.h +++ b/pcbnew/router/pns_itemset.h @@ -35,27 +35,28 @@ class PNS_ITEMSET { public: - typedef std::vector ItemVector; + typedef std::vector ITEM_VECTOR; - PNS_ITEMSET( PNS_ITEM *aInitialItem = NULL ); + PNS_ITEMSET( PNS_ITEM* aInitialItem = NULL ); - PNS_ITEMSET (const PNS_ITEMSET &aOther ) + PNS_ITEMSET( const PNS_ITEMSET& aOther ) { m_items = aOther.m_items; - m_ownedItems = ItemVector(); + m_ownedItems = ITEM_VECTOR(); } - const PNS_ITEMSET& operator= (const PNS_ITEMSET &aOther) + const PNS_ITEMSET& operator=( const PNS_ITEMSET& aOther ) { m_items = aOther.m_items; - m_ownedItems = ItemVector(); + m_ownedItems = ITEM_VECTOR(); + return *this; } ~PNS_ITEMSET(); - ItemVector& Items() { return m_items; } - const ItemVector& CItems() const { return m_items; } + ITEM_VECTOR& Items() { return m_items; } + const ITEM_VECTOR& CItems() const { return m_items; } PNS_ITEMSET& FilterLayers( int aStart, int aEnd = -1 ); PNS_ITEMSET& FilterKinds( int aKindMask ); @@ -63,24 +64,24 @@ public: int Size() { return m_items.size(); } - void Add( PNS_ITEM* item ) + void Add( PNS_ITEM* aItem ) { - m_items.push_back( item ); + m_items.push_back( aItem ); } PNS_ITEM* Get( int index ) const { return m_items[index]; } void Clear(); - void AddOwned ( PNS_ITEM *aItem ) + void AddOwned( PNS_ITEM *aItem ) { m_items.push_back( aItem ); m_ownedItems.push_back( aItem ); } private: - ItemVector m_items; - ItemVector m_ownedItems; + ITEM_VECTOR m_items; + ITEM_VECTOR m_ownedItems; }; #endif diff --git a/pcbnew/router/pns_joint.h b/pcbnew/router/pns_joint.h index 699481538f..1bee21c06f 100644 --- a/pcbnew/router/pns_joint.h +++ b/pcbnew/router/pns_joint.h @@ -40,11 +40,11 @@ class PNS_JOINT : public PNS_ITEM { public: - typedef std::vector LinkedItems; + typedef std::vector LINKED_ITEMS; ///> Joints are hashed by their position, layers and net. /// Linked items are, obviously, not hashed - struct HashTag + struct HASH_TAG { VECTOR2I pos; int net; @@ -53,8 +53,7 @@ public: PNS_JOINT() : PNS_ITEM( JOINT ) {} - PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, - int aNet = -1 ) : + PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet = -1 ) : PNS_ITEM( JOINT ) { m_tag.pos = aPos; @@ -62,14 +61,14 @@ public: m_layers = aLayers; } - PNS_JOINT( const PNS_JOINT& b ) : + PNS_JOINT( const PNS_JOINT& aB ) : PNS_ITEM( JOINT ) { - m_layers = b.m_layers; - m_tag.pos = b.m_tag.pos; - m_tag.net = b.m_tag.net; - m_linkedItems = b.m_linkedItems; - m_layers = b.m_layers; + m_layers = aB.m_layers; + m_tag.pos = aB.m_tag.pos; + m_tag.net = aB.m_tag.net; + m_linkedItems = aB.m_linkedItems; + m_layers = aB.m_layers; } PNS_ITEM* Clone ( ) const @@ -85,8 +84,7 @@ public: if( m_linkedItems.size() != 2 ) return false; - if( m_linkedItems[0]->Kind() != SEGMENT || - m_linkedItems[1]->Kind() != SEGMENT ) + if( m_linkedItems[0]->Kind() != SEGMENT || m_linkedItems[1]->Kind() != SEGMENT ) return false; PNS_SEGMENT* seg1 = static_cast( m_linkedItems[0] ); @@ -99,8 +97,7 @@ public: ///> Links the joint to a given board item (when it's added to the PNS_NODE) void Link( PNS_ITEM* aItem ) { - LinkedItems::iterator f = std::find( m_linkedItems.begin(), - m_linkedItems.end(), aItem ); + LINKED_ITEMS::iterator f = std::find( m_linkedItems.begin(), m_linkedItems.end(), aItem ); if( f != m_linkedItems.end() ) return; @@ -112,8 +109,7 @@ public: ///> Returns true if the joint became dangling after unlinking. bool Unlink( PNS_ITEM* aItem ) { - LinkedItems::iterator f = std::find( m_linkedItems.begin(), - m_linkedItems.end(), aItem ); + LINKED_ITEMS::iterator f = std::find( m_linkedItems.begin(), m_linkedItems.end(), aItem ); if( f != m_linkedItems.end() ) m_linkedItems.erase( f ); @@ -131,17 +127,19 @@ public: return static_cast( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] ); } - PNS_VIA *Via() + PNS_VIA* Via() { - for( LinkedItems::iterator i = m_linkedItems.begin(); - i != m_linkedItems.end(); ++i ) + for( LINKED_ITEMS::iterator i = m_linkedItems.begin(); i != m_linkedItems.end(); ++i ) + { if( (*i)->Kind() == PNS_ITEM::VIA ) - return (PNS_VIA *)(*i); + return (PNS_VIA*)( *i ); + } + return NULL; } /// trivial accessors - const HashTag& Tag() const + const HASH_TAG& Tag() const { return m_tag; } @@ -156,7 +154,7 @@ public: return m_tag.net; } - LinkedItems& LinkList() + LINKED_ITEMS& LinkList() { return m_linkedItems; } @@ -166,10 +164,12 @@ public: { int n = 0; - for( LinkedItems::const_iterator i = m_linkedItems.begin(); - i != m_linkedItems.end(); ++i ) + for( LINKED_ITEMS::const_iterator i = m_linkedItems.begin(); + i != m_linkedItems.end(); ++i ) + { if( (*i)->Kind() & aMask ) n++; + } return n; } @@ -189,9 +189,11 @@ public: m_layers.Merge( aJoint.m_layers ); // fixme: duplicate links (?) - for( LinkedItems::const_iterator i = aJoint.m_linkedItems.begin(); - i != aJoint.m_linkedItems.end(); ++i ) + for( LINKED_ITEMS::const_iterator i = aJoint.m_linkedItems.begin(); + i != aJoint.m_linkedItems.end(); ++i ) + { m_linkedItems.push_back( *i ); + } } bool Overlaps( const PNS_JOINT& rhs ) const @@ -202,27 +204,27 @@ public: private: ///> hash tag for unordered_multimap - HashTag m_tag; + HASH_TAG m_tag; ///> list of items linked to this joint - LinkedItems m_linkedItems; + LINKED_ITEMS m_linkedItems; }; // hash function & comparison operator for boost::unordered_map<> -inline bool operator==( PNS_JOINT::HashTag const& p1, - PNS_JOINT::HashTag const& p2 ) +inline bool operator==( PNS_JOINT::HASH_TAG const& aP1, + PNS_JOINT::HASH_TAG const& aP2 ) { - return p1.pos == p2.pos && p1.net == p2.net; + return aP1.pos == aP2.pos && aP1.net == aP2.net; } -inline std::size_t hash_value( PNS_JOINT::HashTag const& p ) +inline std::size_t hash_value( PNS_JOINT::HASH_TAG const& aP ) { std::size_t seed = 0; - boost::hash_combine( seed, p.pos.x ); - boost::hash_combine( seed, p.pos.y ); - boost::hash_combine( seed, p.net ); + boost::hash_combine( seed, aP.pos.x ); + boost::hash_combine( seed, aP.pos.y ); + boost::hash_combine( seed, aP.net ); return seed; } diff --git a/pcbnew/router/pns_layerset.h b/pcbnew/router/pns_layerset.h index d99ef57040..7ba05d84ef 100644 --- a/pcbnew/router/pns_layerset.h +++ b/pcbnew/router/pns_layerset.h @@ -50,17 +50,17 @@ public: m_start = m_end = aLayer; } - PNS_LAYERSET( const PNS_LAYERSET& b ) : - m_start( b.m_start ), - m_end( b.m_end ) + PNS_LAYERSET( const PNS_LAYERSET& aB ) : + m_start( aB.m_start ), + m_end( aB.m_end ) {} ~PNS_LAYERSET() {}; - const PNS_LAYERSET& operator=( const PNS_LAYERSET& b ) + const PNS_LAYERSET& operator=( const PNS_LAYERSET& aB ) { - m_start = b.m_start; - m_end = b.m_end; + m_start = aB.m_start; + m_end = aB.m_end; return *this; } diff --git a/pcbnew/router/pns_line.cpp b/pcbnew/router/pns_line.cpp index 8cc7bcea87..d7663c4e7d 100644 --- a/pcbnew/router/pns_line.cpp +++ b/pcbnew/router/pns_line.cpp @@ -50,14 +50,15 @@ PNS_LINE::PNS_LINE( const PNS_LINE& aOther ) : copyLinks ( &aOther ); } + PNS_LINE::~PNS_LINE() { if( m_segmentRefs ) delete m_segmentRefs; -}; +} -const PNS_LINE& PNS_LINE :: operator= (const PNS_LINE& aOther) +const PNS_LINE& PNS_LINE::operator=( const PNS_LINE& aOther ) { m_line = aOther.m_line; m_width = aOther.m_width; @@ -75,53 +76,62 @@ const PNS_LINE& PNS_LINE :: operator= (const PNS_LINE& aOther) return *this; } -PNS_LINE* PNS_LINE::Clone( ) const + +PNS_LINE* PNS_LINE::Clone() const { PNS_LINE* l = new PNS_LINE( *this ); + return l; } -void PNS_LINE::Mark(int aMarker) + +void PNS_LINE::Mark( int aMarker ) { m_marker = aMarker; - if(m_segmentRefs) + if( m_segmentRefs ) { - BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) - s->Mark(aMarker); + BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs ) + s->Mark( aMarker ); } } + void PNS_LINE::Unmark () { - if(m_segmentRefs) + if( m_segmentRefs ) { - BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) + BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs ) s->Unmark(); } + m_marker = 0; } + int PNS_LINE::Marker()const { int marker = m_marker; - if(m_segmentRefs) + + if( m_segmentRefs ) { - BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) + BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs ) marker |= s->Marker(); } + return marker; } + void PNS_LINE::copyLinks( const PNS_LINE *aParent ) { - if(aParent->m_segmentRefs == NULL) + if( aParent->m_segmentRefs == NULL ) { m_segmentRefs = NULL; return; } - m_segmentRefs = new SegmentRefs(); + m_segmentRefs = new SEGMENT_REFS(); *m_segmentRefs = *aParent->m_segmentRefs; } @@ -140,6 +150,7 @@ PNS_SEGMENT* PNS_SEGMENT::Clone( ) const return s; } + int PNS_LINE::CountCorners( int aAngles ) { int count = 0; @@ -161,6 +172,7 @@ int PNS_LINE::CountCorners( int aAngles ) return count; } + bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, SHAPE_LINE_CHAIN& aWalk, SHAPE_LINE_CHAIN& aPost, bool aCw ) const { @@ -171,38 +183,37 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, if( line.SegmentCount() < 1 ) return false; - if( aObstacle.PointInside( line.CPoint( 0 ) ) || - aObstacle.PointInside( line.CPoint( -1 ) ) ) + if( aObstacle.PointInside( line.CPoint( 0 ) ) || aObstacle.PointInside( line.CPoint( -1 ) ) ) return false; SHAPE_LINE_CHAIN::INTERSECTIONS ips, ips2; - line.Intersect(aObstacle, ips); + line.Intersect( aObstacle, ips ); int nearest_dist = INT_MAX; int farthest_dist = 0; SHAPE_LINE_CHAIN::INTERSECTION nearest, farthest; - for(int i = 0; i < (int) ips.size(); i++) + for( int i = 0; i < (int) ips.size(); i++ ) { const VECTOR2I p = ips[i].p; - int dist = line.PathLength(p); + int dist = line.PathLength( p ); - if(dist <= nearest_dist) + if( dist <= nearest_dist ) { nearest_dist = dist; nearest = ips[i]; } - if(dist >= farthest_dist) + if( dist >= farthest_dist ) { farthest_dist = dist; farthest = ips[i]; } } - if(ips.size() <= 1 || nearest.p == farthest.p) + if( ips.size() <= 1 || nearest.p == farthest.p ) { aPre = line; return true; @@ -213,13 +224,13 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, aPre.Simplify(); aWalk.Clear(); - aWalk.SetClosed(false); + aWalk.SetClosed( false ); aWalk.Append( nearest.p ); int i = nearest.their.Index(); - assert ( nearest.their.Index() >= 0 ); - assert ( farthest.their.Index() >= 0 ); + assert( nearest.their.Index() >= 0 ); + assert( farthest.their.Index() >= 0 ); assert( nearest_dist <= farthest_dist ); @@ -231,14 +242,14 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, i = i_first; - while (i != i_last) + while( i != i_last ) { - aWalk.Append(aObstacle.CPoint(i)); - i += (aCw ? 1 : -1); + aWalk.Append( aObstacle.CPoint( i ) ); + i += ( aCw ? 1 : -1 ); - if (i < 0) + if( i < 0 ) i = aObstacle.PointCount() - 1; - else if (i == aObstacle.PointCount()) + else if( i == aObstacle.PointCount() ) i = 0; } @@ -249,9 +260,11 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, aPost.Append( farthest.p ); aPost.Append( line.Slice( farthest.our.Index() + 1, -1 ) ); aPost.Simplify(); + return true; } + void PNS_LINE::Walkaround( const SHAPE_LINE_CHAIN& aObstacle, SHAPE_LINE_CHAIN& aPath, bool aCw ) const @@ -298,12 +311,12 @@ const PNS_LINE PNS_LINE::ClipToNearestObstacle( PNS_NODE* aNode ) const { PNS_LINE l( *this ); - PNS_NODE::OptObstacle obs = aNode->NearestObstacle( &l ); + PNS_NODE::OPT_OBSTACLE obs = aNode->NearestObstacle( &l ); if( obs ) { l.RemoveVia(); - int p = l.Line().Split( obs->ip_first ); + int p = l.Line().Split( obs->m_ipFirst ); l.Line().Remove( p + 1, -1 ); } @@ -325,113 +338,121 @@ void PNS_LINE::ShowLinks() printf( "seg %d: %p\n", i, (*m_segmentRefs)[i] ); } -SHAPE_LINE_CHAIN dragCornerInternal ( const SHAPE_LINE_CHAIN& origin, const VECTOR2I& aP ) +SHAPE_LINE_CHAIN dragCornerInternal( const SHAPE_LINE_CHAIN& aOrigin, const VECTOR2I& aP ) { optional picked; int i; int d = 2; - if(origin.CSegment(-1).Length() > 100000 * 30) // fixme: constant/parameter? + if( aOrigin.CSegment( -1 ).Length() > 100000 * 30 ) // fixme: constant/parameter? d = 1; - for(i = origin.SegmentCount() - d; i >= 0; i--) + for( i = aOrigin.SegmentCount() - d; i >= 0; i-- ) { - - DIRECTION_45 d_start (origin.CSegment(i)); - VECTOR2I p_start = origin.CPoint(i); - SHAPE_LINE_CHAIN paths [2]; + DIRECTION_45 d_start ( aOrigin.CSegment( i ) ); + VECTOR2I p_start = aOrigin.CPoint( i ); + SHAPE_LINE_CHAIN paths[2]; DIRECTION_45 dirs[2]; - DIRECTION_45 d_prev = (i > 0 ? DIRECTION_45(origin.CSegment(i-1)) : DIRECTION_45()); + DIRECTION_45 d_prev = ( i > 0 ? DIRECTION_45( aOrigin.CSegment( i - 1 ) ) : DIRECTION_45() ); - for(int j = 0; j < 2; j++) + for( int j = 0; j < 2; j++ ) { - paths [j] = d_start.BuildInitialTrace( p_start, aP, j ); - dirs [j] = DIRECTION_45(paths[j].CSegment(0)); + paths[j] = d_start.BuildInitialTrace( p_start, aP, j ); + dirs[j] = DIRECTION_45( paths[j].CSegment( 0 ) ); } - - for( int j = 0; j < 2; j++) - if(dirs[j] == d_start) - { - picked = paths[j]; - break; - } - - if(picked) - break; - - for(int j = 0; j < 2; j++) - if (dirs[j].IsObtuse(d_prev)) + for( int j = 0; j < 2; j++ ) + { + if( dirs[j] == d_start ) { picked = paths[j]; break; } - if(picked) - break; + } + + if( picked ) + break; + + for( int j = 0; j < 2; j++ ) + { + if( dirs[j].IsObtuse( d_prev ) ) + { + picked = paths[j]; + break; + } + } + + if( picked ) + break; } - if(picked) + if( picked ) { - SHAPE_LINE_CHAIN path = origin.Slice(0, i); - path.Append(*picked); - return path; + SHAPE_LINE_CHAIN path = aOrigin.Slice( 0, i ); + path.Append( *picked ); + return path; } - return DIRECTION_45().BuildInitialTrace(origin.CPoint(0), aP, true); + return DIRECTION_45().BuildInitialTrace( aOrigin.CPoint( 0 ), aP, true ); } - void PNS_LINE::DragCorner ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) { SHAPE_LINE_CHAIN path; VECTOR2I snapped = snapDraggedCorner( m_line, aP, aIndex, aSnappingThreshold ); - if( aIndex == 0) + if( aIndex == 0 ) path = dragCornerInternal( m_line.Reverse(), snapped ).Reverse(); else if ( aIndex == m_line.SegmentCount() ) path = dragCornerInternal( m_line, snapped ); - else { + else + { // fixme: awkward behaviour for "outwards" drags - path = dragCornerInternal( m_line.Slice (0, aIndex), snapped ); - SHAPE_LINE_CHAIN path_rev = dragCornerInternal( m_line.Slice (aIndex, -1).Reverse(), snapped ).Reverse(); - path.Append(path_rev); + path = dragCornerInternal( m_line.Slice( 0, aIndex ), snapped ); + SHAPE_LINE_CHAIN path_rev = dragCornerInternal( m_line.Slice( aIndex, -1 ).Reverse(), + snapped ).Reverse(); + path.Append( path_rev ); } + path.Simplify(); m_line = path; } -VECTOR2I PNS_LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const + +VECTOR2I PNS_LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I& aP, + int aIndex, int aThreshold ) const { - int s_start = std::max(aIndex - 2, 0); - int s_end = std::min(aIndex + 2, aPath.SegmentCount() - 1); + int s_start = std::max( aIndex - 2, 0 ); + int s_end = std::min( aIndex + 2, aPath.SegmentCount() - 1 ); int i, j; int best_dist = INT_MAX; VECTOR2I best_snap = aP; - if(aThreshold <= 0) + if( aThreshold <= 0 ) return aP; - for(i = s_start; i <= s_end; i++) + for( i = s_start; i <= s_end; i++ ) { - const SEG& a = aPath.CSegment(i); + const SEG& a = aPath.CSegment( i ); - for(j = s_start; j < i; j++) + for( j = s_start; j < i; j++ ) { - const SEG& b = aPath.CSegment(j); + const SEG& b = aPath.CSegment( j ); - if( ! (DIRECTION_45(a).IsObtuse(DIRECTION_45(b))) ) + if( !( DIRECTION_45( a ).IsObtuse(DIRECTION_45( b ) ) ) ) continue; OPT_VECTOR2I ip = a.IntersectLines(b); - if(ip) + if( ip ) { - int dist = (*ip - aP).EuclideanNorm(); + int dist = ( *ip - aP ).EuclideanNorm(); + if( dist < aThreshold && dist < best_dist ) { best_dist = dist; @@ -444,40 +465,47 @@ VECTOR2I PNS_LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTO return best_snap; } -VECTOR2I PNS_LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const +VECTOR2I PNS_LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, + int aIndex, int aThreshold ) const { VECTOR2I snap_p[2]; - DIRECTION_45 dragDir ( aPath.CSegment(aIndex) ); - int snap_d[2] = {-1, -1}; + DIRECTION_45 dragDir( aPath.CSegment( aIndex ) ); + int snap_d[2] = { -1, -1 }; if( aThreshold == 0 ) return aP; - if(aIndex >= 2) + if( aIndex >= 2 ) { - SEG s = aPath.CSegment(aIndex - 2); - if(DIRECTION_45(s) == dragDir) - snap_d[0] = s.LineDistance(aP); + SEG s = aPath.CSegment( aIndex - 2 ); + + if( DIRECTION_45( s ) == dragDir ) + snap_d[0] = s.LineDistance( aP ); + snap_p[0] = s.A; } - if(aIndex < aPath.SegmentCount() - 2) + if( aIndex < aPath.SegmentCount() - 2 ) { - SEG s = aPath.CSegment(aIndex + 2); - if(DIRECTION_45(s) == dragDir) + SEG s = aPath.CSegment( aIndex + 2 ); + + if( DIRECTION_45( s ) == dragDir ) snap_d[1] = s.LineDistance(aP); + snap_p[1] = s.A; } VECTOR2I best = aP; int minDist = INT_MAX; - for(int i = 0; i < 2; i++) - if(snap_d[i] >= 0 && snap_d[i] < minDist && snap_d[i] <= aThreshold) + for( int i = 0; i < 2; i++ ) + { + if( snap_d[i] >= 0 && snap_d[i] < minDist && snap_d[i] <= aThreshold ) { minDist = snap_d[i]; best = snap_p[i]; } + } return best; } @@ -485,157 +513,166 @@ VECTOR2I PNS_LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const void PNS_LINE::DragSegment ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) { - SHAPE_LINE_CHAIN path (m_line); - VECTOR2I target (aP) ; + SHAPE_LINE_CHAIN path( m_line ); + VECTOR2I target( aP ); SEG guideA[2], guideB[2]; int index = aIndex; target = snapToNeighbourSegments( path, aP, aIndex, aSnappingThreshold ); - if(index == 0) + if( index == 0 ) { - path.Insert (0, path.CPoint(0)); + path.Insert( 0, path.CPoint( 0 ) ); index++; } - if(index == path.SegmentCount()-1) + if( index == path.SegmentCount() - 1 ) { - path.Insert(path.PointCount() - 1, path.CPoint(-1)); + path.Insert( path.PointCount() - 1, path.CPoint( -1 ) ); } - SEG dragged = path.CSegment(index); - DIRECTION_45 drag_dir (dragged); + SEG dragged = path.CSegment( index ); + DIRECTION_45 drag_dir( dragged ); - SEG s_prev = path.CSegment(index - 1); - SEG s_next = path.CSegment(index + 1); + SEG s_prev = path.CSegment( index - 1 ); + SEG s_next = path.CSegment( index + 1 ); - DIRECTION_45 dir_prev (s_prev); - DIRECTION_45 dir_next (s_next); + DIRECTION_45 dir_prev( s_prev ); + DIRECTION_45 dir_next( s_next ); - if(dir_prev == drag_dir) + if( dir_prev == drag_dir ) { dir_prev = dir_prev.Left(); - path.Insert( index, path.CPoint(index) ); + path.Insert( index, path.CPoint( index ) ); index++; } - if(dir_next == drag_dir) + if( dir_next == drag_dir ) { dir_next = dir_next.Right(); - path.Insert( index + 1, path.CPoint(index + 1) ); + path.Insert( index + 1, path.CPoint( index + 1 ) ); } - - s_prev = path.CSegment(index - 1); - s_next = path.CSegment(index + 1); - dragged = path.CSegment(index); + s_prev = path.CSegment( index - 1 ); + s_next = path.CSegment( index + 1 ); + dragged = path.CSegment( index ); bool lockEndpointA = true; bool lockEndpointB = true; - if(aIndex == 0) + if( aIndex == 0 ) { - if(!lockEndpointA) + if( !lockEndpointA ) guideA[0] = guideA[1] = SEG( dragged.A, dragged.A + drag_dir.Right().Right().ToVector() ); - else { + else + { guideA[0] = SEG( dragged.A, dragged.A + drag_dir.Right().ToVector() ); guideA[1] = SEG( dragged.A, dragged.A + drag_dir.Left().ToVector() ); } - } else { - if(dir_prev.IsObtuse(drag_dir)) + } + else + { + if( dir_prev.IsObtuse(drag_dir ) ) { - guideA[0] = SEG( s_prev.A, s_prev.A + drag_dir.Left().ToVector() ); - guideA[1] = SEG( s_prev.A, s_prev.A + drag_dir.Right().ToVector() ); - } else - guideA[0] = guideA[1] = SEG( dragged.A, dragged.A + dir_prev.ToVector() ); + guideA[0] = SEG( s_prev.A, s_prev.A + drag_dir.Left().ToVector() ); + guideA[1] = SEG( s_prev.A, s_prev.A + drag_dir.Right().ToVector() ); + } + else + guideA[0] = guideA[1] = SEG( dragged.A, dragged.A + dir_prev.ToVector() ); } - if(aIndex == m_line.SegmentCount() - 1) + if( aIndex == m_line.SegmentCount() - 1 ) { - if(!lockEndpointB) + if( !lockEndpointB ) guideB[0] = guideB[1] = SEG( dragged.B, dragged.B + drag_dir.Right().Right().ToVector() ); - else { + else + { guideB[0] = SEG( dragged.B, dragged.B + drag_dir.Right().ToVector() ); guideB[1] = SEG( dragged.B, dragged.B + drag_dir.Left().ToVector() ); } - } else { - if(dir_next.IsObtuse(drag_dir)) + } + else + { + if( dir_next.IsObtuse( drag_dir ) ) { - guideB[0] = SEG( s_next.B, s_next.B + drag_dir.Left().ToVector() ); - guideB[1] = SEG( s_next.B, s_next.B + drag_dir.Right().ToVector() ); - } else + guideB[0] = SEG( s_next.B, s_next.B + drag_dir.Left().ToVector() ); + guideB[1] = SEG( s_next.B, s_next.B + drag_dir.Right().ToVector() ); + } + else guideB[0] = guideB[1] = SEG( dragged.B, dragged.B + dir_next.ToVector() ); } - SEG s_current (target, target + drag_dir.ToVector()); + SEG s_current( target, target + drag_dir.ToVector() ); int best_len = INT_MAX; SHAPE_LINE_CHAIN best; - for(int i = 0; i < 2; i++) + for( int i = 0; i < 2; i++ ) { - for(int j = 0; j < 2; j++) + for( int j = 0; j < 2; j++ ) { - OPT_VECTOR2I ip1 = s_current.IntersectLines(guideA[i]); - OPT_VECTOR2I ip2 = s_current.IntersectLines(guideB[j]); + OPT_VECTOR2I ip1 = s_current.IntersectLines( guideA[i] ); + OPT_VECTOR2I ip2 = s_current.IntersectLines( guideB[j] ); - SHAPE_LINE_CHAIN np; + SHAPE_LINE_CHAIN np; - if(!ip1 || !ip2) - continue; + if( !ip1 || !ip2 ) + continue; - SEG s1 ( s_prev.A, *ip1 ); - SEG s2 ( *ip1, *ip2 ); - SEG s3 ( *ip2, s_next.B ); + SEG s1( s_prev.A, *ip1 ); + SEG s2( *ip1, *ip2 ); + SEG s3( *ip2, s_next.B ); - OPT_VECTOR2I ip; + OPT_VECTOR2I ip; - if(ip = s1.Intersect(s_next)) - { - np.Append ( s1.A ); - np.Append ( *ip ); - np.Append ( s_next.B ); - } else if(ip = s3.Intersect(s_prev)) - { - np.Append ( s_prev.A ); - np.Append ( *ip ); - np.Append ( s3.B ); - } else if(ip = s1.Intersect(s3)) - { - np.Append( s_prev.A ); - np.Append( *ip ); - np.Append( s_next.B ); - } else { - np.Append( s_prev.A ); - np.Append( *ip1 ); - np.Append( *ip2 ); - np.Append( s_next.B ); - } + if( ip = s1.Intersect( s_next ) ) + { + np.Append ( s1.A ); + np.Append ( *ip ); + np.Append ( s_next.B ); + } + else if( ip = s3.Intersect( s_prev ) ) + { + np.Append ( s_prev.A ); + np.Append ( *ip ); + np.Append ( s3.B ); + } + else if( ip = s1.Intersect( s3 ) ) + { + np.Append( s_prev.A ); + np.Append( *ip ); + np.Append( s_next.B ); + } + else + { + np.Append( s_prev.A ); + np.Append( *ip1 ); + np.Append( *ip2 ); + np.Append( s_next.B ); + } - if(np.Length() < best_len) - { - best_len = np.Length(); - best = np; - } - + if( np.Length() < best_len ) + { + best_len = np.Length(); + best = np; + } } } - if(!lockEndpointA && aIndex == 0) - best.Remove(0, 0); - if(!lockEndpointB && aIndex == m_line.SegmentCount() - 1) - best.Remove(-1, -1); - - - if(m_line.PointCount() == 1) + if( !lockEndpointA && aIndex == 0 ) + best.Remove( 0, 0 ); + if( !lockEndpointB && aIndex == m_line.SegmentCount() - 1 ) + best.Remove( -1, -1 ); + + if( m_line.PointCount() == 1 ) m_line = best; - else if (aIndex == 0) - m_line.Replace(0, 1, best); - else if (aIndex == m_line.SegmentCount() - 1) - m_line.Replace(-2, -1, best); + else if( aIndex == 0 ) + m_line.Replace( 0, 1, best ); + else if( aIndex == m_line.SegmentCount() - 1 ) + m_line.Replace( -2, -1, best ); else - m_line.Replace(aIndex, aIndex + 1, best); + m_line.Replace( aIndex, aIndex + 1, best ); m_line.Simplify(); } @@ -643,21 +680,23 @@ void PNS_LINE::DragSegment ( const VECTOR2I& aP, int aIndex, int aSnappingThresh bool PNS_LINE::CompareGeometry( const PNS_LINE& aOther ) { - return m_line.CompareGeometry(aOther.m_line); + return m_line.CompareGeometry( aOther.m_line ); } + void PNS_LINE::Reverse() { - m_line = m_line.Reverse(); - if(m_segmentRefs) - std::reverse(m_segmentRefs->begin(), m_segmentRefs->end() ); + m_line = m_line.Reverse(); + + if( m_segmentRefs ) + std::reverse( m_segmentRefs->begin(), m_segmentRefs->end() ); } -void PNS_LINE::AppendVia(const PNS_VIA& aVia) + +void PNS_LINE::AppendVia( const PNS_VIA& aVia ) { - if(aVia.Pos() == m_line.CPoint(0)) + if( aVia.Pos() == m_line.CPoint( 0 ) ) { - Reverse(); } @@ -666,62 +705,73 @@ void PNS_LINE::AppendVia(const PNS_VIA& aVia) m_via.SetNet( m_net ); } -void PNS_LINE::SetRank(int aRank) + +void PNS_LINE::SetRank( int aRank ) { m_rank = aRank; - if(m_segmentRefs) + + if( m_segmentRefs ) { - BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) - s->SetRank(aRank); + BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs ) + s->SetRank( aRank ); } } + int PNS_LINE::Rank() const { int min_rank = INT_MAX; int rank; - if(m_segmentRefs) + + if( m_segmentRefs ) { BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs ) - min_rank = std::min(min_rank, s->Rank()); - rank = (min_rank == INT_MAX) ? -1 : min_rank; - } else { + min_rank = std::min( min_rank, s->Rank() ); + rank = ( min_rank == INT_MAX ) ? -1 : min_rank; + } + else + { rank = m_rank; } return rank; } -void PNS_LINE::ClipVertexRange ( int aStart, int aEnd ) + +void PNS_LINE::ClipVertexRange( int aStart, int aEnd ) { - m_line = m_line.Slice (aStart, aEnd); + m_line = m_line.Slice( aStart, aEnd ); - if(m_segmentRefs) + if( m_segmentRefs ) { - SegmentRefs *snew = new SegmentRefs( m_segmentRefs->begin() + aStart, m_segmentRefs->begin() + aEnd ); + SEGMENT_REFS* snew = new SEGMENT_REFS( m_segmentRefs->begin() + aStart, + m_segmentRefs->begin() + aEnd ); delete m_segmentRefs; m_segmentRefs = snew; } } + bool PNS_LINE::HasLoops() const { - - for(int i = 0; i < PointCount(); i++) - for(int j = 0; j < PointCount(); j++) + for( int i = 0; i < PointCount(); i++ ) + { + for( int j = 0; j < PointCount(); j++ ) { - if( (std::abs(i-j) > 1) && CPoint(i) == CPoint(j)) + if( ( std::abs( i - j ) > 1 ) && CPoint( i ) == CPoint( j ) ) return true; } + } - return false; + return false; } + void PNS_LINE::ClearSegmentLinks() { - if(m_segmentRefs) + if( m_segmentRefs ) delete m_segmentRefs; + m_segmentRefs = NULL; } - diff --git a/pcbnew/router/pns_line.h b/pcbnew/router/pns_line.h index 520409d937..d77c37ec96 100644 --- a/pcbnew/router/pns_line.h +++ b/pcbnew/router/pns_line.h @@ -57,19 +57,18 @@ class PNS_VIA; class PNS_LINE : public PNS_ITEM { public: - typedef std::vector SegmentRefs; + typedef std::vector SEGMENT_REFS; /** * Constructor * Makes an empty line. */ - PNS_LINE() : PNS_ITEM (LINE) + PNS_LINE() : PNS_ITEM( LINE ) { m_segmentRefs = NULL; m_hasVia = false; } - PNS_LINE( const PNS_LINE& aOther ) ; /** @@ -77,7 +76,6 @@ public: * Copies properties (net, layers, etc.) from a base line and replaces the shape * by another **/ - PNS_LINE( const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine ) : PNS_ITEM( aBase ), m_line( aLine ), @@ -92,12 +90,12 @@ public: ~PNS_LINE(); /// @copydoc PNS_ITEM::Clone() - virtual PNS_LINE* Clone( ) const; + virtual PNS_LINE* Clone() const; - const PNS_LINE& operator= (const PNS_LINE& aOther); + const PNS_LINE& operator=( const PNS_LINE& aOther ); ///> Assigns a shape to the line (a polyline/line chain) - void SetShape ( const SHAPE_LINE_CHAIN& aLine ) + void SetShape( const SHAPE_LINE_CHAIN& aLine ) { m_line = aLine; } @@ -135,13 +133,13 @@ public: ///> Returns the aIdx-th point of the line const VECTOR2I& CPoint( int aIdx ) const { - return m_line.CPoint(aIdx); + return m_line.CPoint( aIdx ); } ///> Returns the aIdx-th segment of the line - const SEG CSegment (int aIdx ) const + const SEG CSegment( int aIdx ) const { - return m_line.CSegment(aIdx); + return m_line.CSegment( aIdx ); } ///> Sets line width @@ -169,14 +167,14 @@ public: void LinkSegment( PNS_SEGMENT* aSeg ) { if( !m_segmentRefs ) - m_segmentRefs = new SegmentRefs(); + m_segmentRefs = new SEGMENT_REFS(); m_segmentRefs->push_back( aSeg ); } ///> Returns the list of segments from the owning node that constitute this ///> line (or NULL if the line is not linked) - SegmentRefs* LinkedSegments() + SEGMENT_REFS* LinkedSegments() { return m_segmentRefs; } @@ -195,9 +193,11 @@ public: void ClearSegmentLinks(); ///> Returns the number of segments that were assembled together to form this line. - int LinkCount() const { - if(!m_segmentRefs) + int LinkCount() const + { + if( !m_segmentRefs ) return -1; + return m_segmentRefs->size(); } @@ -208,7 +208,6 @@ public: ///> Clips the line to a given range of vertices. void ClipVertexRange ( int aStart, int aEnd ); - ///> Returns the number of corners of angles specified by mask aAngles. int CountCorners( int aAngles ); @@ -218,12 +217,11 @@ public: ///> aWalkaroundPath = path around the obstacle ///> aPostPath = past from obstacle till the end ///> aCW = whether to walk around in clockwise or counter-clockwise direction. - - bool Walkaround( SHAPE_LINE_CHAIN obstacle, - SHAPE_LINE_CHAIN& pre, - SHAPE_LINE_CHAIN& walk, - SHAPE_LINE_CHAIN& post, - bool cw ) const; + bool Walkaround( SHAPE_LINE_CHAIN aObstacle, + SHAPE_LINE_CHAIN& aPre, + SHAPE_LINE_CHAIN& aWalk, + SHAPE_LINE_CHAIN& aPost, + bool aCw ) const; void Walkaround( const SHAPE_LINE_CHAIN& aObstacle, SHAPE_LINE_CHAIN& aPath, @@ -241,29 +239,31 @@ public: const PNS_VIA& Via() const { return m_via; } - virtual void Mark(int aMarker); + virtual void Mark( int aMarker ); virtual void Unmark (); virtual int Marker() const; - void DragSegment ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 ); - void DragCorner ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 ); + void DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 ); + void DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 ); - void SetRank ( int aRank ); + void SetRank( int aRank ); int Rank() const; bool HasLoops() const; private: + VECTOR2I snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, + int aIndex, int aThreshold) const; - VECTOR2I snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold) const; - VECTOR2I snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const; + VECTOR2I snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, + int aIndex, int aThreshold ) const; ///> Copies m_segmentRefs from the line aParent. - void copyLinks( const PNS_LINE *aParent ) ; + void copyLinks( const PNS_LINE* aParent ) ; ///> List of segments in the owning PNS_NODE (PNS_ITEM::m_owner) that constitute this line, or NULL ///> if the line is not a part of any node. - SegmentRefs* m_segmentRefs; + SEGMENT_REFS* m_segmentRefs; ///> The actual shape of the line SHAPE_LINE_CHAIN m_line; diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index 16f3ea1429..a79993249f 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -44,7 +44,8 @@ PNS_LINE_PLACER::PNS_LINE_PLACER( PNS_ROUTER* aRouter ) : m_world = NULL; m_shove = NULL; m_currentNode = NULL; -}; +} + PNS_LINE_PLACER::~PNS_LINE_PLACER() { @@ -52,11 +53,13 @@ PNS_LINE_PLACER::~PNS_LINE_PLACER() delete m_shove; } -void PNS_LINE_PLACER::setWorld ( PNS_NODE *aWorld ) + +void PNS_LINE_PLACER::setWorld ( PNS_NODE* aWorld ) { m_world = aWorld; } + void PNS_LINE_PLACER::AddVia( bool aEnabled, int aDiameter, int aDrill ) { m_viaDiameter = aDiameter; @@ -64,11 +67,10 @@ void PNS_LINE_PLACER::AddVia( bool aEnabled, int aDiameter, int aDrill ) m_placingVia = aEnabled; } -void PNS_LINE_PLACER::startPlacement( const VECTOR2I& aStart, int aNet, - int aWidth, int aLayer ) + +void PNS_LINE_PLACER::startPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer ) { - - assert(m_world != NULL); + assert( m_world != NULL ); m_direction = m_initial_direction; TRACE( 1, "world %p, intitial-direction %s layer %d\n", @@ -89,14 +91,14 @@ void PNS_LINE_PLACER::startPlacement( const VECTOR2I& aStart, int aNet, m_currentMode = Settings().Mode(); - if(m_shove) + if( m_shove ) delete m_shove; m_shove = NULL; - if(m_currentMode == RM_Shove || m_currentMode == RM_Smart) + if( m_currentMode == RM_Shove || m_currentMode == RM_Smart ) { - m_shove = new PNS_SHOVE( m_world -> Branch(), Router() ); + m_shove = new PNS_SHOVE( m_world->Branch(), Router() ); } m_placingVia = false; @@ -107,8 +109,8 @@ void PNS_LINE_PLACER::setInitialDirection( const DIRECTION_45& aDirection ) { m_initial_direction = aDirection; -if( m_tail.SegmentCount() == 0 ) - m_direction = aDirection; + if( m_tail.SegmentCount() == 0 ) + m_direction = aDirection; } @@ -154,6 +156,7 @@ bool PNS_LINE_PLACER::handleSelfIntersections() m_direction = m_initial_direction; tail.Clear(); head.Clear(); + return true; } else @@ -176,7 +179,7 @@ bool PNS_LINE_PLACER::handlePullback() SHAPE_LINE_CHAIN& head = m_head.Line(); SHAPE_LINE_CHAIN& tail = m_tail.Line(); - if(head.PointCount() < 2) + if( head.PointCount() < 2 ) return false; int n = tail.PointCount(); @@ -201,7 +204,7 @@ bool PNS_LINE_PLACER::handlePullback() // case 2: regardless of the current routing direction, if the tail/head // extremities form an acute or right angle, reduce the tail by one segment // (and hope that further iterations) will result with a cleaner trace - bool pullback_2 = (angle == DIRECTION_45::ANG_RIGHT || angle == DIRECTION_45::ANG_ACUTE); + bool pullback_2 = ( angle == DIRECTION_45::ANG_RIGHT || angle == DIRECTION_45::ANG_ACUTE ); if( pullback_1 || pullback_2 ) { @@ -237,7 +240,7 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd ) int n = tail.SegmentCount(); - if(head.SegmentCount() < 1) + if( head.SegmentCount() < 1 ) return false; // Don't attempt this for too short tails @@ -294,10 +297,10 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd ) } -bool PNS_LINE_PLACER::checkObtusity( const SEG& a, const SEG& b ) const +bool PNS_LINE_PLACER::checkObtusity( const SEG& aA, const SEG& aB ) const { - const DIRECTION_45 dir_a( a ); - const DIRECTION_45 dir_b( b ); + const DIRECTION_45 dir_a( aA ); + const DIRECTION_45 dir_b( aB ); return dir_a.IsObtuse( dir_b ) || dir_a == dir_b; } @@ -399,6 +402,7 @@ bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead ) return false; } + bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) { SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP ); @@ -412,27 +416,30 @@ bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) walkaround.SetSolidsOnly( false ); walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() ); - PNS_WALKAROUND::WalkaroundStatus wf = walkaround.Route( initTrack, walkFull, false ); + PNS_WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false ); - switch(Settings().OptimizerEffort()) + switch( Settings().OptimizerEffort() ) { - case OE_Low: + case OE_LOW: effort = 0; break; - case OE_Medium: - case OE_Full: + + case OE_MEDIUM: + case OE_FULL: effort = PNS_OPTIMIZER::MERGE_SEGMENTS; break; } - if(Settings().SmartPads()) + + if( Settings().SmartPads() ) effort |= PNS_OPTIMIZER::SMART_PADS; if( wf == PNS_WALKAROUND::STUCK ) { walkFull = walkFull.ClipToNearestObstacle( m_currentNode ); rv = true; - - } else if( m_placingVia && viaOk ) { + } + else if( m_placingVia && viaOk ) + { PNS_LAYERSET allLayers( 0, 15 ); PNS_VIA v1( walkFull.CPoint( -1 ), allLayers, m_viaDiameter ); walkFull.AppendVia( v1 ); @@ -440,7 +447,7 @@ bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) PNS_OPTIMIZER::Optimize( &walkFull, effort, m_currentNode ); - if( m_currentNode->CheckColliding(&walkFull) ) + if( m_currentNode->CheckColliding( &walkFull ) ) { TRACEn(0, "strange, walk line colliding\n"); } @@ -451,9 +458,10 @@ bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) return rv; } -bool PNS_LINE_PLACER::rhMarkObstacles ( const VECTOR2I& aP, PNS_LINE& aNewHead ) + +bool PNS_LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, PNS_LINE& aNewHead ) { - m_head.SetShape ( m_direction.BuildInitialTrace( m_p_start, aP ) ); + m_head.SetShape( m_direction.BuildInitialTrace( m_p_start, aP ) ); if( m_placingVia ) { @@ -461,12 +469,13 @@ bool PNS_LINE_PLACER::rhMarkObstacles ( const VECTOR2I& aP, PNS_LINE& aNewHead ) PNS_VIA v1( m_head.CPoint( -1 ), allLayers, m_viaDiameter ); m_head.AppendVia( v1 ); } - + aNewHead = m_head; return m_currentNode->CheckColliding( &m_head ); } + bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) { SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP ); @@ -482,16 +491,16 @@ bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) walkaround.SetSolidsOnly( true ); walkaround.SetIterationLimit( 10 ); - PNS_WALKAROUND::WalkaroundStatus stat_solids = walkaround.Route( initTrack, walkSolids ); + PNS_WALKAROUND::WALKAROUND_STATUS stat_solids = walkaround.Route( initTrack, walkSolids ); optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_SEGMENTS ); optimizer.SetCollisionMask ( PNS_ITEM::SOLID ); optimizer.Optimize( &walkSolids ); if( stat_solids == PNS_WALKAROUND::DONE ) - l2 = walkSolids; - else - l2 = initTrack.ClipToNearestObstacle( m_shove->CurrentNode() ); + l2 = walkSolids; + else + l2 = initTrack.ClipToNearestObstacle( m_shove->CurrentNode() ); PNS_LINE l( m_tail ); l.Line().Append( l2.CLine() ); @@ -513,43 +522,43 @@ bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) // in certain, uncommon cases there may be loops in the head+tail, In such case, we don't shove to avoid // screwing up the database. - if ( l.HasLoops() ) + if( l.HasLoops() ) { aNewHead = m_head; return false; } - PNS_SHOVE::ShoveStatus status = m_shove->ShoveLines( l ); + PNS_SHOVE::SHOVE_STATUS status = m_shove->ShoveLines( l ); m_currentNode = m_shove->CurrentNode(); if( status == PNS_SHOVE::SH_OK ) - { - optimizer.SetWorld( m_currentNode ); - optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS ); - optimizer.SetCollisionMask( PNS_ITEM::ANY ); - optimizer.Optimize( &l2 ); + { + optimizer.SetWorld( m_currentNode ); + optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS ); + optimizer.SetCollisionMask( PNS_ITEM::ANY ); + optimizer.Optimize( &l2 ); - aNewHead = l2; + aNewHead = l2; - return true; - } - else - { - walkaround.SetWorld( m_currentNode ); - walkaround.SetSolidsOnly( false ); - walkaround.SetIterationLimit( 10 ); - walkaround.SetApproachCursor( true, aP ); - walkaround.Route( initTrack, l2 ); - aNewHead = l2.ClipToNearestObstacle( m_shove->CurrentNode() ); - - return false; - } + return true; + } + else + { + walkaround.SetWorld( m_currentNode ); + walkaround.SetSolidsOnly( false ); + walkaround.SetIterationLimit( 10 ); + walkaround.SetApproachCursor( true, aP ); + walkaround.Route( initTrack, l2 ); + aNewHead = l2.ClipToNearestObstacle( m_shove->CurrentNode() ); + return false; + } return false; } + bool PNS_LINE_PLACER::routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead ) { switch( m_currentMode ) @@ -570,18 +579,18 @@ bool PNS_LINE_PLACER::routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead ) bool PNS_LINE_PLACER::optimizeTailHeadTransition() { - PNS_LINE tmp = Trace(); - if(PNS_OPTIMIZER::Optimize(&tmp, PNS_OPTIMIZER::FANOUT_CLEANUP, m_currentNode)) + if( PNS_OPTIMIZER::Optimize( &tmp, PNS_OPTIMIZER::FANOUT_CLEANUP, m_currentNode ) ) { - if(tmp.SegmentCount() < 1) + if( tmp.SegmentCount() < 1 ) return false; m_head = tmp; m_p_start = tmp.CLine().CPoint( 0 ); m_direction = DIRECTION_45( tmp.CSegment( 0 ) ); m_tail.Line().Clear(); + return true; } @@ -611,7 +620,7 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition() // If so, replace the (threshold) last tail points and the head with // the optimized line - if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_OBTUSE, m_currentNode)) + if( PNS_OPTIMIZER::Optimize( &new_head, PNS_OPTIMIZER::MERGE_OBTUSE, m_currentNode ) ) { PNS_LINE tmp( m_tail, opt_line ); @@ -702,22 +711,26 @@ const PNS_LINE PNS_LINE_PLACER::Trace() const return tmp; } + const PNS_ITEMSET PNS_LINE_PLACER::Traces() { m_currentTrace = Trace(); return PNS_ITEMSET( &m_currentTrace ); } + void PNS_LINE_PLACER::FlipPosture() { m_initial_direction = m_initial_direction.Right(); m_direction = m_direction.Right(); } -PNS_NODE* PNS_LINE_PLACER::CurrentNode(bool aLoopsRemoved) const + +PNS_NODE* PNS_LINE_PLACER::CurrentNode( bool aLoopsRemoved ) const { - if(aLoopsRemoved && m_lastNode) + if( aLoopsRemoved && m_lastNode ) return m_lastNode; + return m_currentNode; } @@ -747,16 +760,19 @@ void PNS_LINE_PLACER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, co } } + void PNS_LINE_PLACER::SetLayer(int aLayer) { m_currentLayer = aLayer; } + void PNS_LINE_PLACER::SetWidth(int aWidth) { m_currentWidth = aWidth; } + void PNS_LINE_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) { VECTOR2I p( aP ); @@ -783,7 +799,6 @@ void PNS_LINE_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) m_currentEnd = p; m_currentNet = net; - PNS_NODE *rootNode = Router()->GetWorld()->Branch(); if( splitSeg ) @@ -801,7 +816,7 @@ void PNS_LINE_PLACER::Move( const VECTOR2I& aP, PNS_ITEM* aEndItem ) VECTOR2I p = aP; int eiDepth = -1; - if(aEndItem && aEndItem->Owner()) + if( aEndItem && aEndItem->Owner() ) eiDepth = aEndItem->Owner()->Depth(); if( m_lastNode ) @@ -814,26 +829,27 @@ void PNS_LINE_PLACER::Move( const VECTOR2I& aP, PNS_ITEM* aEndItem ) current = Trace(); - if(!current.PointCount()) + if( !current.PointCount() ) m_currentEnd = m_p_start; else m_currentEnd = current.CLine().CPoint(-1); - PNS_NODE *latestNode = m_currentNode; m_lastNode = latestNode->Branch(); - - if(eiDepth >= 0 && aEndItem && latestNode->Depth() > eiDepth && current.SegmentCount() && current.CPoint(-1) == aP) + if( eiDepth >= 0 && aEndItem && latestNode->Depth() > eiDepth && + current.SegmentCount() && current.CPoint( -1 ) == aP ) { - splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint(-1) ); - if(Settings().RemoveLoops()) + splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) ); + + if( Settings().RemoveLoops() ) removeLoops( m_lastNode, ¤t ); } updateLeadingRatLine(); } + bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { bool realEnd = false; @@ -861,13 +877,11 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) if( aEndItem && m_currentNet >= 0 && m_currentNet == aEndItem->Net() ) realEnd = true; - - if(realEnd || m_placingVia) + if( realEnd || m_placingVia ) lastV = l.SegmentCount(); else - lastV = std::max( 1, l.SegmentCount() - 1 ); - - + lastV = std::max( 1, l.SegmentCount() - 1 ); + PNS_SEGMENT* lastSeg = NULL; for( int i = 0; i < lastV; i++ ) @@ -883,14 +897,14 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) if( pl.EndsWithVia() ) m_lastNode->Add( pl.Via().Clone() ); - if(realEnd) + if( realEnd ) simplifyNewLine ( m_lastNode, lastSeg ); Router()->CommitRouting ( m_lastNode ); m_lastNode = NULL; - if(!realEnd) + if( !realEnd ) { setInitialDirection( d_last ); VECTOR2I p_start = m_placingVia ? p_last : p_pre_last; @@ -908,20 +922,19 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) return realEnd; } + void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest ) { - if(!aLatest->SegmentCount()) + if( !aLatest->SegmentCount() ) return; aNode->Add( aLatest, true ); - for(int s = 0; s < aLatest->SegmentCount(); s++ ) + for( int s = 0; s < aLatest->SegmentCount(); s++ ) { - PNS_SEGMENT *seg = (*aLatest->LinkedSegments())[s]; - - PNS_LINE* ourLine = aNode->AssembleLine( seg ) ; + PNS_SEGMENT *seg = ( *aLatest->LinkedSegments() )[s]; + PNS_LINE* ourLine = aNode->AssembleLine( seg ); PNS_JOINT a, b; - std::vector lines; aNode->FindLineEnds( ourLine, a, b ); @@ -940,19 +953,19 @@ void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest ) { total++; - if( !( line->ContainsSegment( seg ) ) && line->SegmentCount() ) + if( !( line->ContainsSegment( seg ) ) && line->SegmentCount() ) { Router()->DisplayDebugLine ( line->CLine(), -1, 10000 ); - for(int i = 0; i < line->PointCount(); i++ ) - Router()->DisplayDebugPoint ( line->CPoint(i), -1 ); + for( int i = 0; i < line->PointCount(); i++ ) + Router()->DisplayDebugPoint( line->CPoint( i ), -1 ); aNode->Remove( line ); removedCount ++; } } - TRACE(0, "total segs removed: %d/%d\n", removedCount % total); + TRACE( 0, "total segs removed: %d/%d\n", removedCount % total ); delete ourLine; } @@ -960,13 +973,15 @@ void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest ) aNode->Remove( aLatest ); } -void PNS_LINE_PLACER::simplifyNewLine ( PNS_NODE *aNode, PNS_SEGMENT *aLatest ) + +void PNS_LINE_PLACER::simplifyNewLine( PNS_NODE* aNode, PNS_SEGMENT* aLatest ) { - PNS_LINE *l = aNode->AssembleLine( aLatest) ; + PNS_LINE* l = aNode->AssembleLine( aLatest ); SHAPE_LINE_CHAIN simplified ( l->CLine() ); + simplified.Simplify(); - if(simplified.PointCount() != l->PointCount()) + if( simplified.PointCount() != l->PointCount() ) { std::auto_ptr lnew ( l->Clone() ); aNode -> Remove(l); @@ -975,6 +990,7 @@ void PNS_LINE_PLACER::simplifyNewLine ( PNS_NODE *aNode, PNS_SEGMENT *aLatest ) } } + void PNS_LINE_PLACER::UpdateSizes( const PNS_ROUTING_SETTINGS& aSettings ) { int trackWidth = aSettings.GetTrackWidth(); @@ -986,29 +1002,31 @@ void PNS_LINE_PLACER::UpdateSizes( const PNS_ROUTING_SETTINGS& aSettings ) m_viaDrill = aSettings.GetViaDrill(); } + void PNS_LINE_PLACER::updateLeadingRatLine() { PNS_LINE current = Trace(); - if(! current.PointCount() ) + if( !current.PointCount() ) return; std::auto_ptr tmpNode ( m_lastNode->Branch() ); tmpNode->Add( ¤t ); - PNS_JOINT *jt = tmpNode->FindJoint( current.CPoint(-1), current.Layers().Start(), current.Net() ); - - if(!jt) + PNS_JOINT *jt = tmpNode->FindJoint( current.CPoint( -1 ), + current.Layers().Start(), current.Net() ); + + if( !jt ) return; int anchor; - PNS_ITEM *it = tmpNode->NearestUnconnectedItem ( jt, &anchor ); + PNS_ITEM *it = tmpNode->NearestUnconnectedItem( jt, &anchor ); - if(it) + if( it ) { SHAPE_LINE_CHAIN lc; - lc.Append ( current.CPoint(-1) ); - lc.Append ( it->Anchor(anchor) ); + lc.Append ( current.CPoint( -1 ) ); + lc.Append ( it->Anchor( anchor ) ); Router()->DisplayDebugLine( lc, 5, 10000 ); } -} \ No newline at end of file +} diff --git a/pcbnew/router/pns_line_placer.h b/pcbnew/router/pns_line_placer.h index ddbeb23c74..66fdb32c17 100644 --- a/pcbnew/router/pns_line_placer.h +++ b/pcbnew/router/pns_line_placer.h @@ -46,7 +46,7 @@ class PNS_ROUTER_BASE; class PNS_LINE_PLACER : public PNS_ALGO_BASE { public: - PNS_LINE_PLACER( PNS_ROUTER *aRouter ); + PNS_LINE_PLACER( PNS_ROUTER* aRouter ); ~PNS_LINE_PLACER(); /** @@ -56,7 +56,7 @@ public: * (unless NULL). */ void Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem ); - + /** * Function Move() * @@ -92,14 +92,14 @@ public: * * Sets the current routing layer. */ - void SetLayer ( int aLayer ); + void SetLayer( int aLayer ); /** * Function SetWidth() * * Sets the current track width. */ - void SetWidth ( int aWidth ); + void SetWidth( int aWidth ); /** * Function Head() @@ -167,7 +167,7 @@ public: * * Returns the most recent world state. */ - PNS_NODE* CurrentNode(bool aLoopsRemoved = false) const; + PNS_NODE* CurrentNode( bool aLoopsRemoved = false ) const; /** * Function FlipPosture() @@ -185,7 +185,6 @@ public: */ void UpdateSizes( const PNS_ROUTING_SETTINGS& aSettings ); - private: /** * Function route() @@ -197,7 +196,6 @@ private: * @param aP ending point of current route. * @return true, if the routing is complete. */ - bool route( const VECTOR2I& aP ); /** @@ -214,7 +212,7 @@ private: * * Sets the board to route. */ - void setWorld ( PNS_NODE *aWorld ); + void setWorld ( PNS_NODE* aWorld ); /** * Function startPlacement() @@ -268,9 +266,9 @@ private: * * Helper function, checking if segments a and b form an obtuse angle * (in 45-degree regime). - * @return true, if angle (a, b) is obtuse + * @return true, if angle (aA, aB) is obtuse */ - bool checkObtusity( const SEG& a, const SEG& b ) const; + bool checkObtusity( const SEG& aA, const SEG& aB ) const; /** * Function handleSelfIntersections() @@ -339,16 +337,15 @@ private: */ void routeStep( const VECTOR2I& aP ); - ///< route step, walkaround mode + ///> route step, walkaround mode bool rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead); - ///< route step, shove mode + ///> route step, shove mode bool rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead); - ///< route step, mark obstacles mode + ///> route step, mark obstacles mode bool rhMarkObstacles ( const VECTOR2I& aP, PNS_LINE& aNewHead ); - ///> current routing direction DIRECTION_45 m_direction; @@ -399,7 +396,6 @@ private: PNS_LINE m_currentTrace; PNS_MODE m_currentMode; - }; #endif // __PNS_LINE_PLACER_H diff --git a/pcbnew/router/pns_logger.cpp b/pcbnew/router/pns_logger.cpp index e20577b6b9..b09578137c 100644 --- a/pcbnew/router/pns_logger.cpp +++ b/pcbnew/router/pns_logger.cpp @@ -38,136 +38,153 @@ PNS_LOGGER::PNS_LOGGER( ) PNS_LOGGER::~PNS_LOGGER() { - } + void PNS_LOGGER::Clear() { - m_theLog.str(std::string()); + m_theLog.str( std::string() ); m_groupOpened = false; } -void PNS_LOGGER::NewGroup ( const std::string& name, int iter) + +void PNS_LOGGER::NewGroup( const std::string& aName, int aIter ) { - if(m_groupOpened) + if( m_groupOpened ) m_theLog << "endgroup" << std::endl; - m_theLog << "group " << name << " " << iter << std::endl; + + m_theLog << "group " << aName << " " << aIter << std::endl; m_groupOpened = true; } + void PNS_LOGGER::EndGroup() { - if(!m_groupOpened) + if( !m_groupOpened ) return; m_groupOpened = false; m_theLog << "endgroup" << std::endl; } -void PNS_LOGGER::Log ( const PNS_ITEM *item, int kind, const std::string name ) -{ - m_theLog << "item " << kind << " " << name << " "; - m_theLog << item->Net() << " " << item->Layers().Start() << " " << item->Layers().End() << " " << item->Marker() << " " << item->Rank(); - switch(item->Kind()) +void PNS_LOGGER::Log ( const PNS_ITEM* aItem, int aKind, const std::string aName ) +{ + m_theLog << "aItem " << aKind << " " << aName << " "; + m_theLog << aItem->Net() << " " << aItem->Layers().Start() << " " << + aItem->Layers().End() << " " << aItem->Marker() << " " << aItem->Rank(); + + switch( aItem->Kind() ) { case PNS_ITEM::LINE: { - PNS_LINE *l = (PNS_LINE *) item; + PNS_LINE* l = (PNS_LINE*) aItem; m_theLog << " line "; - m_theLog << l->Width() << " " << (l->EndsWithVia() ? 1 : 0) << " "; + m_theLog << l->Width() << " " << ( l->EndsWithVia() ? 1 : 0 ) << " "; dumpShape ( l->Shape() ); m_theLog << std::endl; break; } + case PNS_ITEM::VIA: { m_theLog << " via 0 0 "; - dumpShape ( item->Shape() ); + dumpShape ( aItem->Shape() ); m_theLog << std::endl; break; } case PNS_ITEM::SEGMENT: { - PNS_SEGMENT *s =(PNS_SEGMENT *) item; + PNS_SEGMENT* s =(PNS_SEGMENT*) aItem; m_theLog << " line "; - m_theLog << s->Width() << " 0 linechain 2 0 " << s->Seg().A.x << " " <Seg().A.y << " " << s->Seg().B.x << " " <Seg().B.y << std::endl; + m_theLog << s->Width() << " 0 linechain 2 0 " << s->Seg().A.x << " " << + s->Seg().A.y << " " << s->Seg().B.x << " " <Seg().B.y << std::endl; break; } case PNS_ITEM::SOLID: { - PNS_SOLID *s = (PNS_SOLID*) item; + PNS_SOLID* s = (PNS_SOLID*) aItem; m_theLog << " solid 0 0 "; - dumpShape ( s->Shape() ); + dumpShape( s->Shape() ); m_theLog << std::endl; break; } default: - break; + break; } } -void PNS_LOGGER::Log ( const SHAPE_LINE_CHAIN *l, int kind, const std::string name ) + +void PNS_LOGGER::Log( const SHAPE_LINE_CHAIN *aL, int aKind, const std::string aName ) { - m_theLog << "item " << kind << " " << name << " "; + m_theLog << "item " << aKind << " " << aName << " "; m_theLog << 0 << " " << 0 << " " << 0 << " " << 0 << " " << 0; m_theLog << " line "; m_theLog << 0 << " " << 0 << " "; - dumpShape ( l ); + dumpShape( aL ); m_theLog << std::endl; } -void PNS_LOGGER::Log ( const VECTOR2I& start, const VECTOR2I& end, int kind , const std::string name) -{ +void PNS_LOGGER::Log( const VECTOR2I& aStart, const VECTOR2I& aEnd, + int aKind, const std::string aName) +{ } -void PNS_LOGGER::dumpShape ( const SHAPE * sh ) + +void PNS_LOGGER::dumpShape( const SHAPE* aSh ) { - switch(sh->Type()) + switch( aSh->Type() ) { case SH_LINE_CHAIN: { - const SHAPE_LINE_CHAIN *lc = (const SHAPE_LINE_CHAIN *) sh; - m_theLog << "linechain " << lc->PointCount() << " " << (lc->IsClosed() ? 1 : 0) << " "; - for(int i = 0; i < lc->PointCount(); i++) - m_theLog << lc->CPoint(i).x << " " << lc->CPoint(i).y << " "; + const SHAPE_LINE_CHAIN* lc = (const SHAPE_LINE_CHAIN*) aSh; + m_theLog << "linechain " << lc->PointCount() << " " << ( lc->IsClosed() ? 1 : 0 ) << " "; + + for( int i = 0; i < lc->PointCount(); i++ ) + m_theLog << lc->CPoint( i ).x << " " << lc->CPoint( i ).y << " "; + break; } + case SH_CIRCLE: { - const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE *) sh; + const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE*) aSh; m_theLog << "circle " << c->GetCenter().x << " " << c->GetCenter().y << " " << c->GetRadius(); break; } + case SH_RECT: { - const SHAPE_RECT *r = (const SHAPE_RECT *) sh; - m_theLog << "rect " << r->GetPosition().x << " " << r->GetPosition().y << " " << r->GetSize().x << " " <GetSize().y; + const SHAPE_RECT* r = (const SHAPE_RECT*) aSh; + m_theLog << "rect " << r->GetPosition().x << " " << r->GetPosition().y << " " << + r->GetSize().x << " " <GetSize().y; break; } + case SH_SEGMENT: { - const SHAPE_SEGMENT *s = (const SHAPE_SEGMENT *) sh; - m_theLog << "linechain 2 0 " << s->GetSeg().A.x << " " << s->GetSeg().A.y << " " << s->GetSeg().B.x << " " << s->GetSeg().B.y; + const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) aSh; + m_theLog << "linechain 2 0 " << s->GetSeg().A.x << " " << s->GetSeg().A.y << " " << + s->GetSeg().B.x << " " << s->GetSeg().B.y; break; } + default: break; } } -void PNS_LOGGER::Save ( const std::string& filename ) +void PNS_LOGGER::Save( const std::string& aFilename ) { - EndGroup(); - FILE *f=fopen(filename.c_str(),"wb"); - printf("Saving to '%s' [%p]\n", filename.c_str(), f); + FILE* f = fopen( aFilename.c_str(), "wb" ); + printf( "Saving to '%s' [%p]\n", aFilename.c_str(), f ); const std::string s = m_theLog.str(); - fwrite(s.c_str(), 1, s.length(), f); - fclose(f); + fwrite( s.c_str(), 1, s.length(), f ); + fclose( f ); } diff --git a/pcbnew/router/pns_logger.h b/pcbnew/router/pns_logger.h index cc112908ae..9120a43557 100644 --- a/pcbnew/router/pns_logger.h +++ b/pcbnew/router/pns_logger.h @@ -32,24 +32,25 @@ class PNS_ITEM; class SHAPE_LINE_CHAIN; class SHAPE; -class PNS_LOGGER { - +class PNS_LOGGER +{ public: PNS_LOGGER(); ~PNS_LOGGER(); - void Save ( const std::string& filename ); - + void Save( const std::string& aFilename ); void Clear(); - void NewGroup ( const std::string& name, int iter = 0); + + void NewGroup( const std::string& aName, int aIter = 0 ); void EndGroup(); - void Log ( const PNS_ITEM *item, int kind = 0, const std::string name = std::string () ); - void Log ( const SHAPE_LINE_CHAIN *l, int kind = 0, const std::string name = std::string () ); - void Log ( const VECTOR2I& start, const VECTOR2I& end, int kind = 0, const std::string name = std::string () ); + + void Log( const PNS_ITEM* aItem, int aKind = 0, const std::string aName = std::string() ); + void Log( const SHAPE_LINE_CHAIN *aL, int aKind = 0, const std::string aName = std::string() ); + void Log( const VECTOR2I& aStart, const VECTOR2I& aEnd, int aKind = 0, + const std::string aName = std::string() ); private: - - void dumpShape ( const SHAPE* sh ); + void dumpShape ( const SHAPE* aSh ); bool m_groupOpened; std::stringstream m_theLog; diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index 4413289dfb..df63612ab6 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -53,11 +53,13 @@ PNS_NODE::PNS_NODE() m_parent = NULL; m_maxClearance = 800000; // fixme: depends on how thick traces are. m_index = new PNS_INDEX; + #ifdef DEBUG allocNodes.insert( this ); #endif } + PNS_NODE::~PNS_NODE() { TRACE( 0, "PNS_NODE::delete %p", this ); @@ -69,7 +71,6 @@ PNS_NODE::~PNS_NODE() } #ifdef DEBUG - if( allocNodes.find( this ) == allocNodes.end() ) { TRACEn( 0, "attempting to free an already-free'd node.\n" ); @@ -77,31 +78,31 @@ PNS_NODE::~PNS_NODE() } allocNodes.erase( this ); - #endif - for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); - i != m_index->end(); ++i ) + for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i ) + { if( (*i)->BelongsTo( this ) ) delete *i; + } unlinkParent(); delete m_index; } -int PNS_NODE::GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const +int PNS_NODE::GetClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const { - return (*m_clearanceFunctor)( a, b ); + return (*m_clearanceFunctor)( aA, aB ); } + PNS_NODE* PNS_NODE::Branch() { PNS_NODE* child = new PNS_NODE; TRACE( 0, "PNS_NODE::branch %p (parent %p)", child % this ); - m_children.push_back( child ); child->m_depth = m_depth + 1; @@ -114,10 +115,9 @@ PNS_NODE* PNS_NODE::Branch() // to stored items. if( !isRoot() ) { - JointMap::iterator j; + JOINT_MAP::iterator j; - for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); - i != m_index->end(); ++i ) + for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i ) child->m_index->Add( *i ); child->m_joints = m_joints; @@ -150,7 +150,7 @@ void PNS_NODE::unlinkParent() // function object that visits potential obstacles and performs // the actual collision refining -struct PNS_NODE::obstacleVisitor +struct PNS_NODE::OBSTACLE_VISITOR { ///> node we are searching in (either root or a branch) PNS_NODE* m_node; @@ -159,7 +159,7 @@ struct PNS_NODE::obstacleVisitor PNS_NODE* m_override; ///> list of encountered obstacles - Obstacles& m_tab; + OBSTACLES& m_tab; ///> the item we are looking for collisions with const PNS_ITEM* m_item; @@ -176,8 +176,7 @@ struct PNS_NODE::obstacleVisitor ///> additional clearance int m_extraClearance; - obstacleVisitor( PNS_NODE::Obstacles& aTab, const PNS_ITEM* aItem, - int aKindMask ) : + OBSTACLE_VISITOR( PNS_NODE::OBSTACLES& aTab, const PNS_ITEM* aItem, int aKindMask ) : m_tab( aTab ), m_item( aItem ), m_kindMask( aKindMask ), @@ -185,9 +184,9 @@ struct PNS_NODE::obstacleVisitor m_matchCount( 0 ), m_extraClearance( 0 ) { - if(aItem->Kind() == PNS_ITEM::LINE) - m_extraClearance += static_cast(aItem)->Width() / 2; - }; + if( aItem->Kind() == PNS_ITEM::LINE ) + m_extraClearance += static_cast( aItem )->Width() / 2; + } void SetCountLimit( int aLimit ) { @@ -212,7 +211,7 @@ struct PNS_NODE::obstacleVisitor int clearance = m_extraClearance + m_node->GetClearance( aItem, m_item ); - if(aItem->Kind() == PNS_ITEM::LINE) + if( aItem->Kind() == PNS_ITEM::LINE ) clearance += static_cast(aItem)->Width() / 2; if( !aItem->Collide( m_item, clearance ) ) @@ -220,7 +219,7 @@ struct PNS_NODE::obstacleVisitor PNS_OBSTACLE obs; - obs.item = aItem; + obs.m_item = aItem; m_tab.push_back( obs ); m_matchCount++; @@ -234,9 +233,9 @@ struct PNS_NODE::obstacleVisitor int PNS_NODE::QueryColliding( const PNS_ITEM* aItem, - PNS_NODE::Obstacles& aObstacles, int aKindMask, int aLimitCount ) + PNS_NODE::OBSTACLES& aObstacles, int aKindMask, int aLimitCount ) { - obstacleVisitor visitor( aObstacles, aItem, aKindMask ); + OBSTACLE_VISITOR visitor( aObstacles, aItem, aKindMask ); #ifdef DEBUG assert( allocNodes.find( this ) != allocNodes.end() ); @@ -249,7 +248,7 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem, m_index->Query( aItem, m_maxClearance, visitor ); // if we haven't found enough items, look in the root branch as well. - if( !isRoot() && ( visitor.m_matchCount < aLimitCount || aLimitCount < 0) ) + if( !isRoot() && ( visitor.m_matchCount < aLimitCount || aLimitCount < 0 ) ) { visitor.SetWorld( m_root, this ); m_root->m_index->Query( aItem, m_maxClearance, visitor ); @@ -259,9 +258,9 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem, } -PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKindMask ) +PNS_NODE::OPT_OBSTACLE PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKindMask ) { - Obstacles obs_list; + OBSTACLES obs_list; bool found_isects = false; const SHAPE_LINE_CHAIN& line = aItem->CLine(); @@ -281,13 +280,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin // if(! QueryColliding ( aItem, obs_list, aKindMask )) if( !n ) - return OptObstacle(); + return OPT_OBSTACLE(); PNS_LINE& aLine = (PNS_LINE&) *aItem; PNS_OBSTACLE nearest; - nearest.item = NULL; - nearest.dist_first = INT_MAX; + nearest.m_item = NULL; + nearest.m_distFirst = INT_MAX; BOOST_FOREACH( PNS_OBSTACLE obs, obs_list ) { @@ -296,13 +295,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin std::vector isect_list; - int clearance = GetClearance( obs.item, &aLine ); + int clearance = GetClearance( obs.m_item, &aLine ); - SHAPE_LINE_CHAIN hull = obs.item->Hull( clearance, aItem->Width() ); + SHAPE_LINE_CHAIN hull = obs.m_item->Hull( clearance, aItem->Width() ); if( aLine.EndsWithVia() ) { - int clearance = GetClearance( obs.item, &aLine.Via() ); + int clearance = GetClearance( obs.m_item, &aLine.Via() ); SHAPE_LINE_CHAIN viaHull = aLine.Via().Hull( clearance, aItem->Width() ); @@ -313,13 +312,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin int dist = aLine.CLine().Length() + ( isect.p - aLine.Via().Pos() ).EuclideanNorm(); - if( dist < nearest.dist_first ) + if( dist < nearest.m_distFirst ) { found_isects = true; - nearest.dist_first = dist; - nearest.ip_first = isect.p; - nearest.item = obs.item; - nearest.hull = hull; + nearest.m_distFirst = dist; + nearest.m_ipFirst = isect.p; + nearest.m_item = obs.m_item; + nearest.m_hull = hull; } if( dist > dist_max ) @@ -338,13 +337,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin { int dist = aLine.CLine().PathLength( isect.p ); - if( dist < nearest.dist_first ) + if( dist < nearest.m_distFirst ) { found_isects = true; - nearest.dist_first = dist; - nearest.ip_first = isect.p; - nearest.item = obs.item; - nearest.hull = hull; + nearest.m_distFirst = dist; + nearest.m_ipFirst = isect.p; + nearest.m_item = obs.m_item; + nearest.m_hull = hull; } if( dist > dist_max ) @@ -354,37 +353,41 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin } } - nearest.ip_last = ip_last; - nearest.dist_last = dist_max; + nearest.m_ipLast = ip_last; + nearest.m_distLast = dist_max; } - if(!found_isects) - nearest.item = obs_list[0].item; + if( !found_isects ) + nearest.m_item = obs_list[0].m_item; return nearest; } -PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEMSET& aSet, int aKindMask ) + +PNS_NODE::OPT_OBSTACLE PNS_NODE::CheckColliding( const PNS_ITEMSET& aSet, int aKindMask ) { - BOOST_FOREACH( const PNS_ITEM *item, aSet.CItems() ) + BOOST_FOREACH( const PNS_ITEM* item, aSet.CItems() ) { - OptObstacle obs = CheckColliding(item, aKindMask); - if(obs) + OPT_OBSTACLE obs = CheckColliding( item, aKindMask ); + + if( obs ) return obs; } - return OptObstacle(); + + return OPT_OBSTACLE(); } -PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKindMask ) + +PNS_NODE::OPT_OBSTACLE PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKindMask ) { - Obstacles obs; + OBSTACLES obs; obs.reserve( 100 ); if( aItemA->Kind() == PNS_ITEM::LINE ) { int n = 0; - const PNS_LINE* line = static_cast(aItemA); + const PNS_LINE* line = static_cast( aItemA ); const SHAPE_LINE_CHAIN& l = line->CLine(); for( int i = 0; i < l.SegmentCount(); i++ ) @@ -393,7 +396,7 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKin n += QueryColliding( &s, obs, aKindMask, 1 ); if( n ) - return OptObstacle( obs[0] ); + return OPT_OBSTACLE( obs[0] ); } if( line->EndsWithVia() ) @@ -401,13 +404,13 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKin n += QueryColliding( &line->Via(), obs, aKindMask, 1 ); if( n ) - return OptObstacle( obs[0] ); + return OPT_OBSTACLE( obs[0] ); } } else if( QueryColliding( aItemA, obs, aKindMask, 1 ) > 0 ) - return OptObstacle( obs[0] ); + return OPT_OBSTACLE( obs[0] ); - return OptObstacle(); + return OPT_OBSTACLE(); } @@ -417,23 +420,24 @@ bool PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, const PNS_ITEM* aItemB, i int clearance = GetClearance( aItemA, aItemB ); // fixme: refactor - if(aItemA->Kind() == PNS_ITEM::LINE) - clearance += static_cast(aItemA)->Width() / 2; - if(aItemB->Kind() == PNS_ITEM::LINE) - clearance += static_cast(aItemB)->Width() / 2; + if( aItemA->Kind() == PNS_ITEM::LINE ) + clearance += static_cast( aItemA )->Width() / 2; + if( aItemB->Kind() == PNS_ITEM::LINE ) + clearance += static_cast( aItemB )->Width() / 2; return aItemA->Collide( aItemB, clearance ); } -struct hitVisitor +struct HIT_VISITOR { PNS_ITEMSET& m_items; const VECTOR2I& m_point; const PNS_NODE* m_world; - hitVisitor( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, const PNS_NODE* aWorld ) : - m_items( aTab ), m_point( aPoint ), m_world( aWorld ) {}; + HIT_VISITOR( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, const PNS_NODE* aWorld ) : + m_items( aTab ), m_point( aPoint ), m_world( aWorld ) + {} bool operator()( PNS_ITEM* aItem ) { @@ -455,17 +459,17 @@ const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) const // fixme: we treat a point as an infinitely small circle - this is inefficient. SHAPE_CIRCLE s( aPoint, 0 ); - hitVisitor visitor( items, aPoint, this ); + HIT_VISITOR visitor( items, aPoint, this ); m_index->Query( &s, m_maxClearance, visitor ); if( !isRoot() ) // fixme: could be made cleaner { PNS_ITEMSET items_root; - hitVisitor visitor_root( items_root, aPoint, m_root ); + HIT_VISITOR visitor_root( items_root, aPoint, m_root ); m_root->m_index->Query( &s, m_maxClearance, visitor_root ); - BOOST_FOREACH( PNS_ITEM * item, items_root.Items() ) + BOOST_FOREACH( PNS_ITEM* item, items_root.Items() ) { if( !overrides( item ) ) items.Add( item ); @@ -506,10 +510,10 @@ void PNS_NODE::addLine( PNS_LINE* aLine, bool aAllowRedundant ) if ( !aAllowRedundant ) psegR = findRedundantSegment( pseg ); - if(psegR) - aLine->LinkSegment(psegR); - else { - + if( psegR ) + aLine->LinkSegment( psegR ); + else + { pseg->SetOwner( this ); linkJoint( s.A, pseg->Layers(), aLine->Net(), pseg ); @@ -532,7 +536,7 @@ void PNS_NODE::addSegment( PNS_SEGMENT* aSeg, bool aAllowRedundant ) return; } - if ( !aAllowRedundant && findRedundantSegment ( aSeg ) ) + if( !aAllowRedundant && findRedundantSegment ( aSeg ) ) return; aSeg->SetOwner( this ); @@ -559,11 +563,11 @@ void PNS_NODE::Add( PNS_ITEM* aItem, bool aAllowRedundant ) break; case PNS_ITEM::LINE: - addLine( static_cast (aItem), aAllowRedundant ); + addLine( static_cast( aItem ), aAllowRedundant ); break; case PNS_ITEM::VIA: - addVia( static_cast(aItem) ); + addVia( static_cast( aItem ) ); break; default: @@ -574,7 +578,6 @@ void PNS_NODE::Add( PNS_ITEM* aItem, bool aAllowRedundant ) void PNS_NODE::doRemove( PNS_ITEM* aItem ) { - // assert(m_root->m_index->Contains(aItem) || m_index->Contains(aItem)); // case 1: removing an item that is stored in the root node from any branch: @@ -612,7 +615,7 @@ void PNS_NODE::removeLine( PNS_LINE* aLine ) assert (segRefs != NULL); assert (aLine->Owner()); - if ( (int)segRefs->size() != aLine->SegmentCount()) + if ( (int) segRefs->size() != aLine->SegmentCount() ) { //printf("******weird deletion: segrefs %d segcount %d hasloops %d\n", segRefs->size(), aLine->SegmentCount(), aLine->HasLoops()); } @@ -627,20 +630,19 @@ void PNS_NODE::removeLine( PNS_LINE* aLine ) } - void PNS_NODE::removeVia( PNS_VIA* aVia ) { // We have to split a single joint (associated with a via, binding together multiple layers) // into multiple independent joints. As I'm a lazy bastard, I simply delete the via and all its links and re-insert them. - PNS_JOINT::HashTag tag; + PNS_JOINT::HASH_TAG tag; - VECTOR2I p ( aVia->Pos() ); - PNS_LAYERSET vLayers ( aVia->Layers() ); + VECTOR2I p( aVia->Pos() ); + PNS_LAYERSET vLayers( aVia->Layers() ); int net = aVia->Net(); - PNS_JOINT *jt = FindJoint( p, vLayers.Start(), net ); - PNS_JOINT::LinkedItems links ( jt->LinkList() ); + PNS_JOINT* jt = FindJoint( p, vLayers.Start(), net ); + PNS_JOINT::LINKED_ITEMS links( jt->LinkList() ); tag.net = net; tag.pos = p; @@ -648,15 +650,15 @@ void PNS_NODE::removeVia( PNS_VIA* aVia ) bool split; do { - split = false; - std::pair range = m_joints.equal_range( tag ); + split = false; + std::pair range = m_joints.equal_range( tag ); if( range.first == m_joints.end() ) break; // find and remove all joints containing the via to be removed - for( JointMap::iterator f = range.first; f != range.second; ++f ) + for( JOINT_MAP::iterator f = range.first; f != range.second; ++f ) { if( aVia->LayersOverlap ( &f->second ) ) { @@ -665,10 +667,10 @@ void PNS_NODE::removeVia( PNS_VIA* aVia ) break; } } - } while (split); + } while( split ); // and re-link them, using the former via's link list - BOOST_FOREACH(PNS_ITEM *item, links) + BOOST_FOREACH(PNS_ITEM* item, links) { if( item != aVia ) linkJoint ( p, item->Layers(), net, item ); @@ -677,6 +679,7 @@ void PNS_NODE::removeVia( PNS_VIA* aVia ) doRemove( aVia ); } + void PNS_NODE::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) { Remove( aOldItem ); @@ -711,37 +714,37 @@ void PNS_NODE::Remove( PNS_ITEM* aItem ) } -void PNS_NODE::followLine( PNS_SEGMENT* current, bool scanDirection, int& pos, - int limit, VECTOR2I* corners, PNS_SEGMENT** segments ) +void PNS_NODE::followLine( PNS_SEGMENT* aCurrent, bool aScanDirection, int& aPos, + int aLimit, VECTOR2I* aCorners, PNS_SEGMENT** aSegments ) { bool prevReversed = false; for( ; ; ) { const VECTOR2I p = - (scanDirection ^ prevReversed) ? current->Seg().B : current->Seg().A; - const PNS_JOINT *jt = FindJoint( p, current ); + ( aScanDirection ^ prevReversed ) ? aCurrent->Seg().B : aCurrent->Seg().A; + const PNS_JOINT* jt = FindJoint( p, aCurrent ); assert( jt ); - assert( pos > 0 && pos < limit ); + assert( aPos > 0 && aPos < aLimit ); - corners[pos] = jt->Pos(); - segments[pos] = current; + aCorners[aPos] = jt->Pos(); + aSegments[aPos] = aCurrent; - pos += (scanDirection ? 1 : -1); + aPos += ( aScanDirection ? 1 : -1 ); if( !jt->IsLineCorner() ) break; - current = jt->NextSegment( current ); + aCurrent = jt->NextSegment( aCurrent ); prevReversed = - ( jt->Pos() == (scanDirection ? current->Seg().B : current->Seg().A ) ); + ( jt->Pos() == (aScanDirection ? aCurrent->Seg().B : aCurrent->Seg().A ) ); } } -PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex) +PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int* aOriginSegmentIndex) { const int MaxVerts = 1024; @@ -761,7 +764,7 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex) int n = 0; - PNS_SEGMENT *prev_seg = NULL; + PNS_SEGMENT* prev_seg = NULL; for( int i = i_start + 1; i < i_end; i++ ) { @@ -773,8 +776,9 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex) { pl->LinkSegment( segs[i] ); - if(segs[i] == aSeg && aOriginSegmentIndex) + if( segs[i] == aSeg && aOriginSegmentIndex ) *aOriginSegmentIndex = n; + n++; } @@ -782,53 +786,57 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex) } - assert (pl->SegmentCount() != 0); - assert (pl->SegmentCount() == (int) pl->LinkedSegments()->size()); + assert( pl->SegmentCount() != 0 ); + assert( pl->SegmentCount() == (int) pl->LinkedSegments()->size() ); return pl; } -void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b ) +void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& aA, PNS_JOINT& aB ) { - a = *FindJoint( aLine->CPoint( 0 ), aLine ); - b = *FindJoint( aLine->CPoint( -1 ), aLine ); + aA = *FindJoint( aLine->CPoint( 0 ), aLine ); + aB = *FindJoint( aLine->CPoint( -1 ), aLine ); } -void PNS_NODE::MapConnectivity ( PNS_JOINT* aStart, std::vector & aFoundJoints ) + +void PNS_NODE::MapConnectivity ( PNS_JOINT* aStart, std::vector& aFoundJoints ) { std::deque searchQueue; std::set processed; - searchQueue.push_back(aStart); - processed.insert ( aStart ); + searchQueue.push_back( aStart ); + processed.insert( aStart ); - while(!searchQueue.empty()) + while( !searchQueue.empty() ) { - PNS_JOINT *current = searchQueue.front(); + PNS_JOINT* current = searchQueue.front(); searchQueue.pop_front(); - BOOST_FOREACH ( PNS_ITEM *item, current->LinkList() ) + BOOST_FOREACH( PNS_ITEM* item, current->LinkList() ) + { if ( item->OfKind( PNS_ITEM::SEGMENT ) ) { - PNS_SEGMENT *seg = static_cast(item); - PNS_JOINT *a = FindJoint( seg->Seg().A, seg ); - PNS_JOINT *b = FindJoint( seg->Seg().B, seg ); - PNS_JOINT *next = (*a == *current) ? b : a; + PNS_SEGMENT* seg = static_cast( item ); + PNS_JOINT* a = FindJoint( seg->Seg().A, seg ); + PNS_JOINT* b = FindJoint( seg->Seg().B, seg ); + PNS_JOINT* next = ( *a == *current ) ? b : a; if( processed.find( next ) == processed.end() ) { - processed.insert ( next ); + processed.insert( next ); searchQueue.push_back( next ); } } + } } - BOOST_FOREACH(PNS_JOINT *jt, processed) + BOOST_FOREACH(PNS_JOINT* jt, processed) aFoundJoints.push_back( jt ); } -PNS_ITEM *PNS_NODE::NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor, int aKindMask ) + +PNS_ITEM* PNS_NODE::NearestUnconnectedItem( PNS_JOINT* aStart, int* aAnchor, int aKindMask ) { std::set disconnected; std::vector joints; @@ -836,32 +844,33 @@ PNS_ITEM *PNS_NODE::NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor, in AllItemsInNet( aStart->Net(), disconnected ); MapConnectivity ( aStart, joints ); - BOOST_FOREACH(PNS_JOINT *jt, joints) + BOOST_FOREACH( PNS_JOINT *jt, joints ) { - BOOST_FOREACH (PNS_ITEM *link, jt->LinkList() ) + BOOST_FOREACH( PNS_ITEM* link, jt->LinkList() ) { - if(disconnected.find(link) != disconnected.end() ) - disconnected.erase(link); + if( disconnected.find( link ) != disconnected.end() ) + disconnected.erase( link ); } } int best_dist = INT_MAX; - PNS_ITEM *best = NULL; + PNS_ITEM* best = NULL; - BOOST_FOREACH (PNS_ITEM *item, disconnected ) + BOOST_FOREACH( PNS_ITEM* item, disconnected ) { - if( item->OfKind ( aKindMask ) ) + if( item->OfKind( aKindMask ) ) { for(int i = 0; i < item->AnchorCount(); i++) { - VECTOR2I p = item->Anchor ( i ); - int d = (p - aStart->Pos()).EuclideanNorm(); + VECTOR2I p = item->Anchor( i ); + int d = ( p - aStart->Pos() ).EuclideanNorm(); - if(d < best_dist) + if( d < best_dist ) { best_dist = d; best = item; - if(aAnchor) + + if( aAnchor ) *aAnchor = i; } } @@ -871,31 +880,32 @@ PNS_ITEM *PNS_NODE::NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor, in return best; } -int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, std::vector& aLines ) + +int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& aA, PNS_JOINT& aB, std::vector& aLines ) { - BOOST_FOREACH( PNS_ITEM* item, a.LinkList() ) + BOOST_FOREACH( PNS_ITEM* item, aA.LinkList() ) { if( item->Kind() == PNS_ITEM::SEGMENT ) { - PNS_SEGMENT* seg = static_cast(item); + PNS_SEGMENT* seg = static_cast( item ); PNS_LINE* line = AssembleLine( seg ); PNS_JOINT j_start, j_end; FindLineEnds( line, j_start, j_end ); + int id_start = line->CLine().Find( aA.Pos() ); + int id_end = line->CLine().Find( aB.Pos() ); - int id_start = line->CLine().Find (a.Pos()); - int id_end = line->CLine().Find (b.Pos()); + if( id_end < id_start ) + std::swap( id_end, id_start ); - if(id_end < id_start) - std::swap(id_end, id_start); - - if(id_start >= 0 && id_end >= 0) + if( id_start >= 0 && id_end >= 0 ) { line->ClipVertexRange ( id_start, id_end ); aLines.push_back( line ); - } else + } + else delete line; } } @@ -906,12 +916,12 @@ int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, std::vector range; + std::pair range; // not found and we are not root? find in the root and copy results here. if( f == m_joints.end() && !isRoot() ) @@ -978,7 +988,8 @@ PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLaye break; } } - } while( merged ); + } + while( merged ); return m_joints.insert( TagJointPair( tag, jt ) )->second; } @@ -991,10 +1002,8 @@ void PNS_JOINT::Dump() const } -void PNS_NODE::linkJoint( const VECTOR2I& aPos, - const PNS_LAYERSET& aLayers, - int aNet, - PNS_ITEM* aWhere ) +void PNS_NODE::linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, + int aNet, PNS_ITEM* aWhere ) { PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet ); @@ -1003,7 +1012,7 @@ void PNS_NODE::linkJoint( const VECTOR2I& aPos, void PNS_NODE::unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, - int aNet, PNS_ITEM* aWhere ) + int aNet, PNS_ITEM* aWhere ) { // fixme: remove dangling joints PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet ); @@ -1021,7 +1030,7 @@ void PNS_NODE::Dump( bool aLong ) for( i = m_items.begin(); i != m_items.end(); i++ ) { if( (*i)->GetKind() == PNS_ITEM::SEGMENT ) - all_segs.insert( static_cast(*i) ); + all_segs.insert( static_cast( *i ) ); } if( !isRoot() ) @@ -1033,24 +1042,24 @@ void PNS_NODE::Dump( bool aLong ) } } - JointMap::iterator j; + JOINT_MAP::iterator j; if( aLong ) - for( j = m_joints.begin(); j!=m_joints.end(); ++j ) + for( j = m_joints.begin(); j != m_joints.end(); ++j ) { printf( "joint : %s, links : %d\n", j->second.GetPos().Format().c_str(), j->second.LinkCount() ); - PNS_JOINT::LinkedItems::const_iterator k; + PNS_JOINT::LINKED_ITEMS::const_iterator k; for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k ) { - const PNS_ITEM* item = *k; + const PNS_ITEM* m_item = *k; - switch( item->GetKind() ) + switch( m_item->GetKind() ) { case PNS_ITEM::SEGMENT: { - const PNS_SEGMENT* seg = static_cast(item); + const PNS_SEGMENT* seg = static_cast( m_item ); printf( " -> seg %s %s\n", seg->GetSeg().A.Format().c_str(), seg->GetSeg().B.Format().c_str() ); break; @@ -1075,7 +1084,6 @@ void PNS_NODE::Dump( bool aLong ) if( aLong ) printf( "Line: %s, net %d ", l->GetLine().Format().c_str(), l->GetNet() ); - for( std::vector::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j ) { printf( "%s ", (*j)->GetSeg().A.Format().c_str() ); @@ -1094,7 +1102,7 @@ void PNS_NODE::Dump( bool aLong ) } -void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded ) +void PNS_NODE::GetUpdatedItems( ITEM_VECTOR& aRemoved, ITEM_VECTOR& aAdded ) { aRemoved.reserve( m_override.size() ); aAdded.reserve( m_index->Size() ); @@ -1102,10 +1110,10 @@ void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded ) if( isRoot() ) return; - BOOST_FOREACH( PNS_ITEM * item, m_override ) + BOOST_FOREACH( PNS_ITEM* item, m_override ) aRemoved.push_back( item ); - for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i!=m_index->end(); ++i ) + for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i ) aAdded.push_back( *i ); } @@ -1115,7 +1123,8 @@ void PNS_NODE::releaseChildren() // copy the kids as the PNS_NODE destructor erases the item from the parent node. std::vector kids = m_children; - BOOST_FOREACH( PNS_NODE * node, kids ) { + BOOST_FOREACH( PNS_NODE * node, kids ) + { node->releaseChildren(); delete node; } @@ -1130,11 +1139,11 @@ void PNS_NODE::Commit( PNS_NODE* aNode ) BOOST_FOREACH( PNS_ITEM * item, aNode->m_override ) Remove( item ); - for( PNS_INDEX::ItemSet::iterator i = aNode->m_index->begin(); + for( PNS_INDEX::ITEM_SET::iterator i = aNode->m_index->begin(); i != aNode->m_index->end(); ++i ) { - (*i)->SetRank ( -1 ); - (*i)->Unmark (); + (*i)->SetRank( -1 ); + (*i)->Unmark(); Add( *i ); } @@ -1151,74 +1160,86 @@ void PNS_NODE::KillChildren() void PNS_NODE::AllItemsInNet( int aNet, std::set& aItems ) { - PNS_INDEX::NetItemsList* l_cur = m_index->GetItemsForNet( aNet ); + PNS_INDEX::NET_ITEMS_LIST* l_cur = m_index->GetItemsForNet( aNet ); - - if(l_cur) + if( l_cur ) { - BOOST_FOREACH (PNS_ITEM *item, *l_cur ) - aItems.insert ( item ); + BOOST_FOREACH( PNS_ITEM*item, *l_cur ) + aItems.insert( item ); } if( !isRoot() ) { - PNS_INDEX::NetItemsList* l_root = m_root->m_index->GetItemsForNet( aNet ); + PNS_INDEX::NET_ITEMS_LIST* l_root = m_root->m_index->GetItemsForNet( aNet ); - if(l_root) - for( PNS_INDEX::NetItemsList::iterator i = l_root->begin(); i!= l_root->end(); ++i ) + if( l_root ) + for( PNS_INDEX::NET_ITEMS_LIST::iterator i = l_root->begin(); i!= l_root->end(); ++i ) if( !overrides( *i ) ) aItems.insert( *i ); } } + void PNS_NODE::ClearRanks() { - for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i ) + for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i ) { - (*i)->SetRank(-1); - (*i)->Mark(0); + (*i)->SetRank( -1 ); + (*i)->Mark( 0 ); } } -int PNS_NODE::FindByMarker ( int aMarker, PNS_ITEMSET& aItems ) + +int PNS_NODE::FindByMarker( int aMarker, PNS_ITEMSET& aItems ) { - for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i ) - if ( (*i)->Marker() & aMarker ) aItems.Add(*i); + for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i ) + { + if( (*i)->Marker() & aMarker ) + aItems.Add( *i ); + } + return 0; } -int PNS_NODE::RemoveByMarker ( int aMarker ) + +int PNS_NODE::RemoveByMarker( int aMarker ) { - for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i ) - if ( (*i)->Marker() & aMarker ) - { - Remove (*i); - } + for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i ) + { + if ( (*i)->Marker() & aMarker ) + { + Remove( *i ); + } + } + return 0; } + PNS_SEGMENT* PNS_NODE::findRedundantSegment ( PNS_SEGMENT *aSeg ) { - PNS_JOINT *jtStart = FindJoint ( aSeg->Seg().A, aSeg ); + PNS_JOINT* jtStart = FindJoint ( aSeg->Seg().A, aSeg ); - if(!jtStart) + if( !jtStart ) return NULL; - BOOST_FOREACH( PNS_ITEM *item, jtStart->LinkList() ) - if(item->OfKind(PNS_ITEM::SEGMENT)) + BOOST_FOREACH( PNS_ITEM* item, jtStart->LinkList() ) + { + if( item->OfKind( PNS_ITEM::SEGMENT ) ) { - PNS_SEGMENT *seg2 = (PNS_SEGMENT *) item; + PNS_SEGMENT* seg2 = (PNS_SEGMENT*) item; - const VECTOR2I a1 ( aSeg->Seg().A ); - const VECTOR2I b1 ( aSeg->Seg().B ); + const VECTOR2I a1( aSeg->Seg().A ); + const VECTOR2I b1( aSeg->Seg().B ); - const VECTOR2I a2 ( seg2->Seg().A ); - const VECTOR2I b2 ( seg2->Seg().B ); + const VECTOR2I a2( seg2->Seg().A ); + const VECTOR2I b2( seg2->Seg().B ); if( seg2->Layers().Start() == aSeg->Layers().Start() && - ((a1 == a2 && b1 == b2) || (a1 == b2 && a2 == b1))) + ( ( a1 == a2 && b1 == b2 ) || ( a1 == b2 && a2 == b1 ) ) ) return seg2; } + } return NULL; } diff --git a/pcbnew/router/pns_node.h b/pcbnew/router/pns_node.h index 4242f8d614..f4d728a3d6 100644 --- a/pcbnew/router/pns_node.h +++ b/pcbnew/router/pns_node.h @@ -52,7 +52,7 @@ class PNS_INDEX; class PNS_CLEARANCE_FUNC { public: - virtual int operator()( const PNS_ITEM* a, const PNS_ITEM* b ) = 0; + virtual int operator()( const PNS_ITEM* aA, const PNS_ITEM* aB ) = 0; virtual ~PNS_CLEARANCE_FUNC() {} }; @@ -65,20 +65,20 @@ public: struct PNS_OBSTACLE { ///> Item we search collisions with - PNS_ITEM* head; + PNS_ITEM* m_head; - ///> Item found to be colliding with head - PNS_ITEM* item; + ///> Item found to be colliding with m_head + PNS_ITEM* m_item; - ///> Hull of the colliding item - SHAPE_LINE_CHAIN hull; + ///> Hull of the colliding m_item + SHAPE_LINE_CHAIN m_hull; ///> First and last intersection point between the head item and the hull - ///> of the colliding item - VECTOR2I ip_first, ip_last; + ///> of the colliding m_item + VECTOR2I m_ipFirst, m_ipLast; ///> ... and the distance thereof - int dist_first, dist_last; + int m_distFirst, m_distLast; }; /** @@ -93,34 +93,33 @@ struct PNS_OBSTACLE * - lightweight cloning/branching (for recursive optimization and shove * springback) **/ - class PNS_NODE { public: - typedef boost::optional OptObstacle; - typedef std::vector ItemVector; - typedef std::vector Obstacles; + typedef boost::optional OPT_OBSTACLE; + typedef std::vector ITEM_VECTOR; + typedef std::vector OBSTACLES; PNS_NODE (); ~PNS_NODE (); ///> Returns the expected clearance between items a and b. - int GetClearance ( const PNS_ITEM* a, const PNS_ITEM* b ) const; + int GetClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const; ///> Returns the pre-set worst case clearance between any pair of items - int GetMaxClearance () const + int GetMaxClearance() const { return m_maxClearance; } ///> Sets the worst-case clerance between any pair of items - void SetMaxClearance ( int aClearance ) + void SetMaxClearance( int aClearance ) { m_maxClearance = aClearance; } ///> Assigns a clerance resolution function object - void SetClearanceFunctor ( PNS_CLEARANCE_FUNC* aFunc ) + void SetClearanceFunctor( PNS_CLEARANCE_FUNC* aFunc ) { m_clearanceFunctor = aFunc; } @@ -147,11 +146,10 @@ public: * @param aLimitCount stop looking for collisions after finding this number of colliding items * @return number of obstacles found */ - int QueryColliding ( const PNS_ITEM* aItem, - Obstacles& aObstacles, - int aKindMask = PNS_ITEM::ANY, - int aLimitCount = -1 ); - + int QueryColliding( const PNS_ITEM* aItem, + OBSTACLES& aObstacles, + int aKindMask = PNS_ITEM::ANY, + int aLimitCount = -1 ); /** * Function NearestObstacle() @@ -162,7 +160,7 @@ public: * @param aKindMask mask of obstacle types to take into account * @return the obstacle, if found, otherwise empty. */ - OptObstacle NearestObstacle ( const PNS_LINE* aItem, + OPT_OBSTACLE NearestObstacle( const PNS_LINE* aItem, int aKindMask = PNS_ITEM::ANY ); /** @@ -174,7 +172,7 @@ public: * @param aKindMask mask of obstacle types to take into account * @return the obstacle, if found, otherwise empty. */ - OptObstacle CheckColliding ( const PNS_ITEM* aItem, + OPT_OBSTACLE CheckColliding( const PNS_ITEM* aItem, int aKindMask = PNS_ITEM::ANY ); @@ -187,7 +185,7 @@ public: * @param aKindMask mask of obstacle types to take into account * @return the obstacle, if found, otherwise empty. */ - OptObstacle CheckColliding ( const PNS_ITEMSET& aSet, + OPT_OBSTACLE CheckColliding( const PNS_ITEMSET& aSet, int aKindMask = PNS_ITEM::ANY ); @@ -200,9 +198,9 @@ public: * @param aKindMask mask of obstacle types to take into account * @return the obstacle, if found, otherwise empty. */ - bool CheckColliding ( const PNS_ITEM* aItemA, - const PNS_ITEM* aItemB, - int aKindMask = PNS_ITEM::ANY ); + bool CheckColliding( const PNS_ITEM* aItemA, + const PNS_ITEM* aItemB, + int aKindMask = PNS_ITEM::ANY ); /** * Function HitTest() @@ -211,7 +209,7 @@ public: * @param aPoint the point * @return the items */ - const PNS_ITEMSET HitTest ( const VECTOR2I& aPoint ) const; + const PNS_ITEMSET HitTest( const VECTOR2I& aPoint ) const; /** * Function Add() @@ -221,7 +219,7 @@ public: * @param aAllowRedundant if true, duplicate items are allowed (e.g. a segment or via * at the same coordinates as an existing one) */ - void Add ( PNS_ITEM* aItem, bool aAllowRedundant = false ); + void Add( PNS_ITEM* aItem, bool aAllowRedundant = false ); /** * Function Remove() @@ -229,7 +227,7 @@ public: * Just as the name says, removes an item from this branch. * @param aItem item to remove */ - void Remove ( PNS_ITEM* aItem ); + void Remove( PNS_ITEM* aItem ); /** * Function Replace() @@ -238,7 +236,7 @@ public: * @param aOldItem item to be removed * @param aNewItem item add instead */ - void Replace ( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ); + void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ); /** * Function Branch() @@ -248,7 +246,7 @@ public: * any branches in use, their parents must NOT be deleted. * @return the new branch */ - PNS_NODE* Branch ( ); + PNS_NODE* Branch(); /** * Function AssembleLine() @@ -259,14 +257,10 @@ public: * @param aOriginSegmentIndex index of aSeg in the resulting line * @return the line */ - - PNS_LINE* AssembleLine ( PNS_SEGMENT* aSeg, - int *aOriginSegmentIndex = NULL ); + PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex = NULL ); ///> Prints the contents and joints structure - void Dump ( bool aLong = false ); - - + void Dump( bool aLong = false ); /** * Function GetUpdatedItems() @@ -276,8 +270,7 @@ public: * @param aRemoved removed items * @param aAdded added items */ - void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded ); - + void GetUpdatedItems( ITEM_VECTOR& aRemoved, ITEM_VECTOR& aAdded ); /** * Function Commit() @@ -302,23 +295,24 @@ public: * Searches for a joint at a given position, linked to given item. * @return the joint, if found, otherwise empty */ - PNS_JOINT* FindJoint( const VECTOR2I& aPos, PNS_ITEM *aItem ) + PNS_JOINT* FindJoint( const VECTOR2I& aPos, PNS_ITEM* aItem ) { return FindJoint( aPos, aItem->Layers().Start(), aItem->Net() ); } - void MapConnectivity ( PNS_JOINT* aStart, std::vector & aFoundJoints ); + void MapConnectivity( PNS_JOINT* aStart, std::vector & aFoundJoints ); - PNS_ITEM *NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor = NULL, int aKindMask = PNS_ITEM::ANY); + PNS_ITEM* NearestUnconnectedItem( PNS_JOINT* aStart, int *aAnchor = NULL, + int aKindMask = PNS_ITEM::ANY); ///> finds all lines between a pair of joints. Used by the loop removal procedure. - int FindLinesBetweenJoints( PNS_JOINT& a, - PNS_JOINT& b, + int FindLinesBetweenJoints( PNS_JOINT& aA, + PNS_JOINT& aB, std::vector& aLines ); ///> finds the joints corresponding to the ends of line aLine - void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b ); + void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& aA, PNS_JOINT& aB ); ///> Destroys all child nodes. Applicable only to the root node. void KillChildren(); @@ -326,28 +320,27 @@ public: void AllItemsInNet( int aNet, std::set& aItems ); void ClearRanks(); - - int FindByMarker ( int aMarker, PNS_ITEMSET& aItems ); - int RemoveByMarker ( int aMarker ); + int FindByMarker( int aMarker, PNS_ITEMSET& aItems ); + int RemoveByMarker( int aMarker ); private: - struct obstacleVisitor; - typedef boost::unordered_multimap JointMap; - typedef JointMap::value_type TagJointPair; + struct OBSTACLE_VISITOR; + typedef boost::unordered_multimap JOINT_MAP; + typedef JOINT_MAP::value_type TagJointPair; /// nodes are not copyable - PNS_NODE ( const PNS_NODE& b ); - PNS_NODE& operator= ( const PNS_NODE& b ); + PNS_NODE( const PNS_NODE& aB ); + PNS_NODE& operator=( const PNS_NODE& aB ); ///> tries to find matching joint and creates a new one if not found PNS_JOINT& touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet ); - ///> touches a joint and links it to an item + ///> touches a joint and links it to an m_item void linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, - int aNet, PNS_ITEM* aWhere ); + int aNet, PNS_ITEM* aWhere ); ///> unlinks an item from a joint void unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, @@ -372,26 +365,26 @@ private: return m_parent == NULL; } - ///> checks if this branch contains an updated version of the item + ///> checks if this branch contains an updated version of the m_item ///> from the root branch. bool overrides( PNS_ITEM* aItem ) const { return m_override.find( aItem ) != m_override.end(); } - PNS_SEGMENT *findRedundantSegment ( PNS_SEGMENT *aSeg ); + PNS_SEGMENT *findRedundantSegment ( PNS_SEGMENT* aSeg ); ///> scans the joint map, forming a line starting from segment (current). - void followLine ( PNS_SEGMENT* current, - bool scanDirection, - int& pos, - int limit, - VECTOR2I* corners, - PNS_SEGMENT** segments ); + void followLine( PNS_SEGMENT* aCurrent, + bool aScanDirection, + int& aPos, + int aLimit, + VECTOR2I* aCorners, + PNS_SEGMENT** aSegments ); ///> hash table with the joints, linking the items. Joints are hashed by ///> their position, layer set and net. - JointMap m_joints; + JOINT_MAP m_joints; ///> node this node was branched from PNS_NODE* m_parent; diff --git a/pcbnew/router/pns_optimizer.cpp b/pcbnew/router/pns_optimizer.cpp index e6aab0e9a1..6451bca600 100644 --- a/pcbnew/router/pns_optimizer.cpp +++ b/pcbnew/router/pns_optimizer.cpp @@ -30,14 +30,11 @@ #include "pns_router.h" /** - * * Cost Estimator Methods - * */ - -int PNS_COST_ESTIMATOR::CornerCost( const SEG& a, const SEG& b ) +int PNS_COST_ESTIMATOR::CornerCost( const SEG& aA, const SEG& aB ) { - DIRECTION_45 dir_a( a ), dir_b( b ); + DIRECTION_45 dir_a( aA ), dir_b( aB ); switch( dir_a.Angle( dir_b ) ) { @@ -109,8 +106,8 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther, if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost ) return true; - else if( aOther.m_cornerCost < m_cornerCost * aCornerTollerance && aOther.m_lengthCost < - m_lengthCost * aLengthTollerance ) + else if( aOther.m_cornerCost < m_cornerCost * aCornerTollerance && + aOther.m_lengthCost < m_lengthCost * aLengthTollerance ) return true; return false; @@ -118,9 +115,7 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther, /** - * * Optimizer - * **/ PNS_OPTIMIZER::PNS_OPTIMIZER( PNS_NODE* aWorld ) : m_world( aWorld ), m_collisionKindMask( PNS_ITEM::ANY ), m_effortLevel( MERGE_SEGMENTS ) @@ -135,14 +130,14 @@ PNS_OPTIMIZER::~PNS_OPTIMIZER() } -struct PNS_OPTIMIZER::CacheVisitor +struct PNS_OPTIMIZER::CACHE_VISITOR { - CacheVisitor( const PNS_ITEM* aOurItem, PNS_NODE* aNode, int aMask ) : + CACHE_VISITOR( const PNS_ITEM* aOurItem, PNS_NODE* aNode, int aMask ) : m_ourItem( aOurItem ), m_collidingItem( NULL ), m_node( aNode ), m_mask( aMask ) - {}; + {} bool operator()( PNS_ITEM* aOtherItem ) { @@ -171,14 +166,14 @@ void PNS_OPTIMIZER::cacheAdd( PNS_ITEM* aItem, bool aIsStatic = false ) return; m_cache.Add( aItem ); - m_cacheTags[aItem].hits = 1; - m_cacheTags[aItem].isStatic = aIsStatic; + m_cacheTags[aItem].m_hits = 1; + m_cacheTags[aItem].m_isStatic = aIsStatic; } void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int aEndVertex ) { - PNS_LINE::SegmentRefs* segs = aLine->LinkedSegments(); + PNS_LINE::SEGMENT_REFS* segs = aLine->LinkedSegments(); if( !segs ) return; @@ -198,7 +193,7 @@ void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int void PNS_OPTIMIZER::CacheRemove( PNS_ITEM* aItem ) { if( aItem->Kind() == PNS_ITEM::LINE ) - removeCachedSegments( static_cast (aItem) ); + removeCachedSegments( static_cast( aItem ) ); } @@ -219,7 +214,7 @@ void PNS_OPTIMIZER::ClearCache( bool aStaticOnly ) for( CachedItemTags::iterator i = m_cacheTags.begin(); i!= m_cacheTags.end(); ++i ) { - if( i->second.isStatic ) + if( i->second.m_isStatic ) { m_cache.Remove( i->first ); m_cacheTags.erase( i->first ); @@ -230,7 +225,7 @@ void PNS_OPTIMIZER::ClearCache( bool aStaticOnly ) bool PNS_OPTIMIZER::checkColliding( PNS_ITEM* aItem, bool aUpdateCache ) { - CacheVisitor v( aItem, m_world, m_collisionKindMask ); + CACHE_VISITOR v( aItem, m_world, m_collisionKindMask ); return m_world->CheckColliding( aItem ); @@ -239,19 +234,19 @@ bool PNS_OPTIMIZER::checkColliding( PNS_ITEM* aItem, bool aUpdateCache ) if( !v.m_collidingItem ) { - PNS_NODE::OptObstacle obs = m_world->CheckColliding( aItem ); + PNS_NODE::OPT_OBSTACLE obs = m_world->CheckColliding( aItem ); if( obs ) { if( aUpdateCache ) - cacheAdd( obs->item ); + cacheAdd( obs->m_item ); return true; } } else { - m_cacheTags[v.m_collidingItem].hits++; + m_cacheTags[v.m_collidingItem].m_hits++; return true; } @@ -430,7 +425,6 @@ bool PNS_OPTIMIZER::mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath, int cost_orig = PNS_COST_ESTIMATOR::CornerCost( aCurrentPath ); - if( aLine->SegmentCount() < 4 ) return false; @@ -442,7 +436,8 @@ bool PNS_OPTIMIZER::mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath, const SEG s1 = aCurrentPath.CSegment( n ); const SEG s2 = aCurrentPath.CSegment( n + step ); - SHAPE_LINE_CHAIN path[2], * picked = NULL; + SHAPE_LINE_CHAIN path[2]; + SHAPE_LINE_CHAIN* picked = NULL; int cost[2]; for( int i = 0; i < 2; i++ ) @@ -485,10 +480,10 @@ bool PNS_OPTIMIZER::mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath, } -PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::circleBreakouts( int aWidth, +PNS_OPTIMIZER::BREAKOUT_LIST PNS_OPTIMIZER::circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const { - BreakoutList breakouts; + BREAKOUT_LIST breakouts; for( int angle = 0; angle < 360; angle += 45 ) { @@ -505,12 +500,12 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::circleBreakouts( int aWidth, } -PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, +PNS_OPTIMIZER::BREAKOUT_LIST PNS_OPTIMIZER::rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const { const SHAPE_RECT* rect = static_cast(aShape); VECTOR2I s = rect->GetSize(), c = rect->GetPosition() + VECTOR2I( s.x / 2, s.y / 2 ); - BreakoutList breakouts; + BREAKOUT_LIST breakouts; VECTOR2I d_offset; @@ -520,7 +515,6 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, VECTOR2I d_vert = VECTOR2I( 0, s.y / 2 + aWidth ); VECTOR2I d_horiz = VECTOR2I( s.x / 2 + aWidth, 0 ); - breakouts.push_back( SHAPE_LINE_CHAIN( c, c + d_horiz ) ); breakouts.push_back( SHAPE_LINE_CHAIN( c, c - d_horiz ) ); breakouts.push_back( SHAPE_LINE_CHAIN( c, c + d_vert ) ); @@ -560,59 +554,59 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, } -PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth, +PNS_OPTIMIZER::BREAKOUT_LIST PNS_OPTIMIZER::computeBreakouts( int aWidth, const PNS_ITEM* aItem, bool aPermitDiagonal ) const { switch( aItem->Kind() ) { case PNS_ITEM::VIA: - { - const PNS_VIA* via = static_cast( aItem ); - return circleBreakouts( aWidth, via->Shape(), aPermitDiagonal ); - } + { + const PNS_VIA* via = static_cast( aItem ); + return circleBreakouts( aWidth, via->Shape(), aPermitDiagonal ); + } case PNS_ITEM::SOLID: + { + const SHAPE* shape = aItem->Shape(); + + switch( shape->Type() ) { - const SHAPE* shape = aItem->Shape(); + case SH_RECT: + return rectBreakouts( aWidth, shape, aPermitDiagonal ); - switch( shape->Type() ) - { - case SH_RECT: - return rectBreakouts( aWidth, shape, aPermitDiagonal ); - - case SH_SEGMENT: - { - const SHAPE_SEGMENT *seg = static_cast (shape); - const SHAPE_RECT rect = ApproximateSegmentAsRect ( *seg ); - return rectBreakouts( aWidth, &rect, aPermitDiagonal ); - } - - case SH_CIRCLE: - return circleBreakouts( aWidth, shape, aPermitDiagonal ); - - default: - break; - } + case SH_SEGMENT: + { + const SHAPE_SEGMENT* seg = static_cast (shape); + const SHAPE_RECT rect = ApproximateSegmentAsRect ( *seg ); + return rectBreakouts( aWidth, &rect, aPermitDiagonal ); } + case SH_CIRCLE: + return circleBreakouts( aWidth, shape, aPermitDiagonal ); + + default: + break; + } + } + default: break; } - return BreakoutList(); + return BREAKOUT_LIST(); } PNS_ITEM* PNS_OPTIMIZER::findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const { - PNS_JOINT *jt = m_world->FindJoint( aP, aLayer, aNet ); + PNS_JOINT* jt = m_world->FindJoint( aP, aLayer, aNet ); if( !jt ) return NULL; BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() ) { - if( item->OfKind (PNS_ITEM::VIA | PNS_ITEM::SOLID ) ) + if( item->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID ) ) return item; } @@ -632,7 +626,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, typedef std::pair RtVariant; std::vector variants; - BreakoutList breakouts = computeBreakouts( aLine->Width(), aPad, true ); + BREAKOUT_LIST breakouts = computeBreakouts( aLine->Width(), aPad, true ); SHAPE_LINE_CHAIN line = ( aEnd ? aLine->CLine().Reverse() : aLine->CLine() ); @@ -647,7 +641,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, { SHAPE_LINE_CHAIN v; SHAPE_LINE_CHAIN connect = dir.BuildInitialTrace( l.CPoint( -1 ), - line.CPoint( p ), diag == 0 ); + line.CPoint( p ), diag == 0 ); DIRECTION_45 dir_bkout( l.CSegment( -1 ) ); @@ -739,9 +733,10 @@ bool PNS_OPTIMIZER::runSmartPads( PNS_LINE* aLine ) if( endPad ) smartPadsSingle( aLine, endPad, true, - vtx < 0 ? line.PointCount() - 1 : line.PointCount() - 1 - vtx ); + vtx < 0 ? line.PointCount() - 1 : line.PointCount() - 1 - vtx ); aLine->Line().Simplify(); + return true; } @@ -756,7 +751,7 @@ bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorl } -bool PNS_OPTIMIZER::fanoutCleanup( PNS_LINE * aLine ) +bool PNS_OPTIMIZER::fanoutCleanup( PNS_LINE* aLine ) { if( aLine->PointCount() < 3 ) return false; @@ -769,40 +764,35 @@ bool PNS_OPTIMIZER::fanoutCleanup( PNS_LINE * aLine ) int thr = aLine->Width() * 10; int len = aLine->CLine().Length(); - - if(!startPad) + if( !startPad ) return false; - - bool startMatch = startPad->OfKind(PNS_ITEM::VIA | PNS_ITEM::SOLID); + bool startMatch = startPad->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID ); bool endMatch = false; if(endPad) { - endMatch = endPad->OfKind(PNS_ITEM::VIA | PNS_ITEM::SOLID); + endMatch = endPad->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID ); } else { endMatch = aLine->EndsWithVia(); } - - if(startMatch && endMatch && len < thr) + if( startMatch && endMatch && len < thr ) { - for(int i = 0; i < 2; i++ ) { - SHAPE_LINE_CHAIN l2 = DIRECTION_45().BuildInitialTrace(p_start, p_end, i); - PNS_ROUTER::GetInstance()->DisplayDebugLine (l2, 4, 10000); + SHAPE_LINE_CHAIN l2 = DIRECTION_45().BuildInitialTrace( p_start, p_end, i ); + PNS_ROUTER::GetInstance()->DisplayDebugLine( l2, 4, 10000 ); PNS_LINE repl; - repl = PNS_LINE (*aLine, l2 ); - + repl = PNS_LINE( *aLine, l2 ); - - if (!m_world->CheckColliding(&repl)) + if( !m_world->CheckColliding( &repl ) ) { - aLine->SetShape(repl.CLine()); + aLine->SetShape( repl.CLine() ); return true; } } } + return false; } diff --git a/pcbnew/router/pns_optimizer.h b/pcbnew/router/pns_optimizer.h index 3e1d9b211c..fb75b41a53 100644 --- a/pcbnew/router/pns_optimizer.h +++ b/pcbnew/router/pns_optimizer.h @@ -38,23 +38,22 @@ class PNS_ROUTER; * * Calculates the cost of a given line, taking corner angles and total length into account. **/ - class PNS_COST_ESTIMATOR { public: PNS_COST_ESTIMATOR() : m_lengthCost( 0 ), m_cornerCost( 0 ) - {}; + {} - PNS_COST_ESTIMATOR( const PNS_COST_ESTIMATOR& b ) : - m_lengthCost( b.m_lengthCost ), - m_cornerCost( b.m_cornerCost ) - {}; + PNS_COST_ESTIMATOR( const PNS_COST_ESTIMATOR& aB ) : + m_lengthCost( aB.m_lengthCost ), + m_cornerCost( aB.m_cornerCost ) + {} ~PNS_COST_ESTIMATOR() {}; - static int CornerCost( const SEG& a, const SEG& b ); + static int CornerCost( const SEG& aA, const SEG& aB ); static int CornerCost( const SHAPE_LINE_CHAIN& aLine ); static int CornerCost( const PNS_LINE& aLine ); @@ -63,7 +62,7 @@ public: void Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine ); bool IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTollerance, - double aCornerTollerace ) const; + double aCornerTollerace ) const; double GetLengthCost() const { return m_lengthCost; } double GetCornerCost() const { return m_cornerCost; } @@ -84,7 +83,6 @@ private: * the procedure as long as the total cost of the line keeps decreasing * - "Smart Pads" - that is, rerouting pad/via exits to make them look nice (SMART_PADS). **/ - class PNS_OPTIMIZER { public: @@ -122,14 +120,14 @@ public: private: static const int MaxCachedItems = 256; - typedef std::vector BreakoutList; + typedef std::vector BREAKOUT_LIST; - struct CacheVisitor; + struct CACHE_VISITOR; - struct CachedItem + struct CACHED_ITEM { - int hits; - bool isStatic; + int m_hits; + bool m_isStatic; }; bool mergeObtuse( PNS_LINE* aLine ); @@ -142,15 +140,13 @@ private: bool checkColliding( PNS_ITEM* aItem, bool aUpdateCache = true ); bool checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath ); - void cacheAdd( PNS_ITEM* aItem, bool aIsStatic ); void removeCachedSegments( PNS_LINE* aLine, int aStartVertex = 0, int aEndVertex = -1 ); - BreakoutList circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; - BreakoutList rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; - BreakoutList ovalBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; - BreakoutList computeBreakouts( int aWidth, const PNS_ITEM* aItem, - bool aPermitDiagonal ) const; + BREAKOUT_LIST circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; + BREAKOUT_LIST rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; + BREAKOUT_LIST ovalBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; + BREAKOUT_LIST computeBreakouts( int aWidth, const PNS_ITEM* aItem, bool aPermitDiagonal ) const; int smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, int aEndVertex ); @@ -158,7 +154,7 @@ private: SHAPE_INDEX_LIST m_cache; - typedef boost::unordered_map CachedItemTags; + typedef boost::unordered_map CachedItemTags; CachedItemTags m_cacheTags; PNS_NODE* m_world; int m_collisionKindMask; diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 72e001801c..e1f3440625 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -82,28 +82,28 @@ public: m_defaultClearance = 254000; // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance(); } - int localPadClearance( const PNS_ITEM * item ) const + int localPadClearance( const PNS_ITEM* aItem ) const { - if(!item->Parent() || item->Parent()->Type() != PCB_PAD_T ) + if( !aItem->Parent() || aItem->Parent()->Type() != PCB_PAD_T ) return 0; - const D_PAD *pad = static_cast( item->Parent() ); + const D_PAD* pad = static_cast( aItem->Parent() ); return pad->GetLocalClearance(); } - int operator()( const PNS_ITEM* a, const PNS_ITEM* b ) + int operator()( const PNS_ITEM* aA, const PNS_ITEM* aB ) { - int net_a = a->Net(); - int cl_a = (net_a >= 0 ? m_clearanceCache[net_a] : m_defaultClearance); - int net_b = b->Net(); - int cl_b = (net_b >= 0 ? m_clearanceCache[net_b] : m_defaultClearance); + int net_a = aA->Net(); + int cl_a = ( net_a >= 0 ? m_clearanceCache[net_a] : m_defaultClearance ); + int net_b = aB->Net(); + int cl_b = ( net_b >= 0 ? m_clearanceCache[net_b] : m_defaultClearance ); - int pad_a = localPadClearance( a ); - int pad_b = localPadClearance( b ); + int pad_a = localPadClearance( aA ); + int pad_b = localPadClearance( aB ); - cl_a = std::max(cl_a, pad_a); - cl_b = std::max(cl_b, pad_b); + cl_a = std::max( cl_a, pad_a ); + cl_b = std::max( cl_b, pad_b ); return std::max( cl_a, cl_b ); } @@ -113,9 +113,10 @@ private: int m_defaultClearance; }; + PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) { - PNS_LAYERSET layers ( 0, 15 ); + PNS_LAYERSET layers( 0, 15 ); switch( aPad->GetAttribute() ) { @@ -131,7 +132,7 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) for( i = FIRST_COPPER_LAYER; i <= LAST_COPPER_LAYER; i++ ) { - if( lmsk & (1 << i) ) + if( lmsk & ( 1 << i ) ) { layers = PNS_LAYERSET( i ); break; @@ -162,17 +163,16 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) double orient = aPad->GetOrientation() / 10.0; bool nonOrtho = false; - if( orient == 90.0 || orient == 270.0 ) sz = VECTOR2I( sz.y, sz.x ); else if( orient != 0.0 && orient != 180.0 ) { // rotated pads are replaced by for the moment by circles due to my laziness ;) - solid->SetShape ( new SHAPE_CIRCLE (c, std::min(sz.x, sz.y) / 2 ) ); + solid->SetShape( new SHAPE_CIRCLE( c, std::min( sz.x, sz.y ) / 2 ) ); nonOrtho = true; } - if(!nonOrtho) + if( !nonOrtho ) { switch( aPad->GetShape() ) { @@ -183,15 +183,17 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) case PAD_OVAL: if( sz.x == sz.y ) solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); - else { + else + { VECTOR2I delta; - if (sz.x > sz.y) - delta = VECTOR2I((sz.x - sz.y) / 2, 0); + if( sz.x > sz.y ) + delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 ); else - delta = VECTOR2I(0, (sz.y - sz.x) / 2); + delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 ); - SHAPE_SEGMENT *shape = new SHAPE_SEGMENT( c - delta, c + delta, std::min(sz.x, sz.y) ); + SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta, + std::min( sz.x, sz.y ) ); solid->SetShape( shape ); } break; @@ -203,6 +205,7 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) default: TRACEn( 0, "unsupported pad shape" ); delete solid; + return NULL; } } @@ -250,7 +253,8 @@ int PNS_ROUTER::NextCopperLayer( bool aUp ) LAYER_MSK mask = m_board->GetEnabledLayers() & m_board->GetVisibleLayers(); LAYER_NUM l = m_currentLayer; - do { + do + { l += ( aUp ? 1 : -1 ); if( l > LAST_COPPER_LAYER ) @@ -261,7 +265,8 @@ int PNS_ROUTER::NextCopperLayer( bool aUp ) if( mask & GetLayerMask( l ) ) return l; - } while( l != m_currentLayer ); + } + while( l != m_currentLayer ); return l; } @@ -269,7 +274,6 @@ int PNS_ROUTER::NextCopperLayer( bool aUp ) void PNS_ROUTER::SyncWorld() { - if( !m_board ) { TRACEn( 0, "No board attached, aborting sync." ); @@ -379,13 +383,6 @@ void PNS_ROUTER::ClearWorld() } -/*void PNS_ROUTER::SetCurrentWidth( int w ) -{ - // fixme: change width while routing - m_currentWidth = w; -}*/ - - bool PNS_ROUTER::RoutingInProgress() const { return m_state != IDLE; @@ -405,49 +402,49 @@ const PNS_ITEMSET PNS_ROUTER::QueryHoverItems( const VECTOR2I& aP ) } -const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment ) +const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* aItem, VECTOR2I aP, bool& aSplitsSegment ) { VECTOR2I anchor; - if( !item ) + if( !aItem ) { aSplitsSegment = false; return aP; } - switch( item->Kind() ) + switch( aItem->Kind() ) { case PNS_ITEM::SOLID: - anchor = static_cast(item)->Pos(); + anchor = static_cast( aItem )->Pos(); aSplitsSegment = false; break; case PNS_ITEM::VIA: - anchor = static_cast(item)->Pos(); + anchor = static_cast( aItem )->Pos(); aSplitsSegment = false; break; case PNS_ITEM::SEGMENT: + { + PNS_SEGMENT* seg = static_cast( aItem ); + const SEG& s = seg->Seg(); + int w = seg->Width(); + + aSplitsSegment = false; + + if( ( aP - s.A ).EuclideanNorm() < w / 2 ) + anchor = s.A; + else if( ( aP - s.B ).EuclideanNorm() < w / 2 ) + anchor = s.B; + else { - PNS_SEGMENT* seg = static_cast( item ); - const SEG& s = seg->Seg(); - int w = seg->Width(); - - aSplitsSegment = false; - - if( ( aP - s.A ).EuclideanNorm() < w / 2 ) - anchor = s.A; - else if( ( aP - s.B ).EuclideanNorm() < w / 2 ) - anchor = s.B; - else - { - anchor = s.NearestPoint( aP ); - aSplitsSegment = true; - } - - break; + anchor = s.NearestPoint( aP ); + aSplitsSegment = true; } + break; + } + default: break; } @@ -455,16 +452,19 @@ const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplit return anchor; } + bool PNS_ROUTER::StartDragging( const VECTOR2I& aP, PNS_ITEM* aStartItem ) { - if(!aStartItem || aStartItem->OfKind(PNS_ITEM::SOLID)) + if( !aStartItem || aStartItem->OfKind( PNS_ITEM::SOLID ) ) return false; m_dragger = new PNS_DRAGGER ( this ); m_dragger->SetWorld( m_world ); + if( m_dragger->Start ( aP, aStartItem ) ) m_state = DRAG_SEGMENT; - else { + else + { delete m_dragger; m_state = IDLE; return false; @@ -476,8 +476,6 @@ bool PNS_ROUTER::StartDragging( const VECTOR2I& aP, PNS_ITEM* aStartItem ) bool PNS_ROUTER::StartRouting( const VECTOR2I& aP, PNS_ITEM* aStartItem ) { - - m_state = ROUTE_TRACK; m_placer = new PNS_LINE_PLACER( this ); @@ -518,11 +516,11 @@ void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, int aColor, int aClearance { ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems ); - if(aColor >= 0) - pitem->SetColor ( KIGFX::COLOR4D ( aColor )); + if( aColor >= 0 ) + pitem->SetColor( KIGFX::COLOR4D ( aColor ) ); - if(aClearance >= 0) - pitem->SetClearance ( aClearance ); + if( aClearance >= 0 ) + pitem->SetClearance( aClearance ); m_previewItems->Add( pitem ); @@ -530,12 +528,14 @@ void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, int aColor, int aClearance m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); } + void PNS_ROUTER::DisplayItems( const PNS_ITEMSET& aItems ) { - BOOST_FOREACH(const PNS_ITEM *item, aItems.CItems()) - DisplayItem(item); + BOOST_FOREACH( const PNS_ITEM *item, aItems.CItems() ) + DisplayItem( item ); } + void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth ) { ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); @@ -547,18 +547,17 @@ void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int } - -void PNS_ROUTER::DisplayDebugPoint( const VECTOR2I pos, int aType ) +void PNS_ROUTER::DisplayDebugPoint( const VECTOR2I aPos, int aType ) { ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); - pitem->Point( pos, aType ); + pitem->Point( aPos, aType ); m_previewItems->Add( pitem ); pitem->ViewSetVisible( true ); m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); - } + void PNS_ROUTER::Move( const VECTOR2I& aP, PNS_ITEM* endItem ) { m_currentEnd = aP; @@ -573,57 +572,62 @@ void PNS_ROUTER::Move( const VECTOR2I& aP, PNS_ITEM* endItem ) case DRAG_SEGMENT: moveDragging (aP, endItem ); break; + default: break; } } -void PNS_ROUTER::moveDragging( const VECTOR2I& aP, PNS_ITEM* endItem ) + +void PNS_ROUTER::moveDragging( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { eraseView(); m_dragger->Drag( aP ); PNS_ITEMSET dragged = m_dragger->Traces(); - updateView ( m_dragger->CurrentNode ( ), dragged ); + updateView ( m_dragger->CurrentNode(), dragged ); } -void PNS_ROUTER::markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ItemVector& aRemoved ) + +void PNS_ROUTER::markViolations( PNS_NODE* aNode, PNS_ITEMSET& aCurrent, + PNS_NODE::ITEM_VECTOR& aRemoved ) { - - BOOST_FOREACH(PNS_ITEM *item, aCurrent.Items()) + BOOST_FOREACH( PNS_ITEM *item, aCurrent.Items() ) { - PNS_NODE::Obstacles obstacles; + PNS_NODE::OBSTACLES obstacles; aNode->QueryColliding( item, obstacles, PNS_ITEM::ANY ); - if ( item->OfKind(PNS_ITEM::LINE ) ) + if( item->OfKind( PNS_ITEM::LINE ) ) { - PNS_LINE *l = static_cast (item); - if (l->EndsWithVia()) + PNS_LINE *l = static_cast( item ); + + if( l->EndsWithVia() ) { PNS_VIA v ( l->Via() ); - aNode->QueryColliding(&v , obstacles, PNS_ITEM::ANY ); + aNode->QueryColliding( &v, obstacles, PNS_ITEM::ANY ); } } - BOOST_FOREACH(PNS_OBSTACLE& obs, obstacles) + BOOST_FOREACH( PNS_OBSTACLE& obs, obstacles ) { - int clearance = aNode->GetClearance( item, obs.item ); - std::auto_ptr tmp ( obs.item->Clone() ); - tmp->Mark ( MK_VIOLATION ); + int clearance = aNode->GetClearance( item, obs.m_item ); + std::auto_ptr tmp( obs.m_item->Clone() ); + tmp->Mark( MK_VIOLATION ); DisplayItem( tmp.get(), -1, clearance ); - aRemoved.push_back(obs.item); + aRemoved.push_back( obs.m_item ); } } } -void PNS_ROUTER::updateView( PNS_NODE *aNode, PNS_ITEMSET& aCurrent ) + +void PNS_ROUTER::updateView( PNS_NODE* aNode, PNS_ITEMSET& aCurrent ) { - PNS_NODE::ItemVector removed, added; - PNS_NODE::Obstacles obstacles; + PNS_NODE::ITEM_VECTOR removed, added; + PNS_NODE::OBSTACLES obstacles; - if(!aNode) + if( !aNode ) return; if( Settings().Mode() == RM_MarkObstacles ) @@ -661,15 +665,14 @@ void PNS_ROUTER::ApplySettings() m_placer->Move( m_currentEnd, m_currentEndItem ); movePlacing( m_currentEnd, m_currentEndItem ); } - - // TODO handle mode/optimization/other options change } -void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* endItem ) + +void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { eraseView(); - m_placer->Move( aP, endItem ); + m_placer->Move( aP, aEndItem ); PNS_LINE current = m_placer->Trace(); DisplayItem( ¤t ); @@ -681,9 +684,10 @@ void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* endItem ) updateView ( m_placer->CurrentNode ( true ), tmp ); } + void PNS_ROUTER::CommitRouting( PNS_NODE* aNode ) { - PNS_NODE::ItemVector removed, added; + PNS_NODE::ITEM_VECTOR removed, added; aNode->GetUpdatedItems( removed, added ); @@ -706,31 +710,31 @@ void PNS_ROUTER::CommitRouting( PNS_NODE* aNode ) switch( item->Kind() ) { case PNS_ITEM::SEGMENT: - { - PNS_SEGMENT* seg = static_cast( item ); - TRACK* track = new TRACK( m_board ); - const SEG& s = seg->Seg(); + { + PNS_SEGMENT* seg = static_cast( item ); + TRACK* track = new TRACK( m_board ); + const SEG& s = seg->Seg(); - track->SetStart( wxPoint( s.A.x, s.A.y ) ); - track->SetEnd( wxPoint( s.B.x, s.B.y ) ); - track->SetWidth( seg->Width() ); - track->SetLayer( seg->Layers().Start() ); - track->SetNetCode( seg->Net() ); - newBI = track; - break; - } + track->SetStart( wxPoint( s.A.x, s.A.y ) ); + track->SetEnd( wxPoint( s.B.x, s.B.y ) ); + track->SetWidth( seg->Width() ); + track->SetLayer( seg->Layers().Start() ); + track->SetNetCode( seg->Net() ); + newBI = track; + break; + } case PNS_ITEM::VIA: - { - VIA* via_board = new VIA( m_board ); - PNS_VIA* via = static_cast( item ); - via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) ); - via_board->SetWidth( via->Diameter() ); - via_board->SetDrill( via->Drill() ); - via_board->SetNetCode( via->Net() ); - newBI = via_board; - break; - } + { + VIA* via_board = new VIA( m_board ); + PNS_VIA* via = static_cast( item ); + via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) ); + via_board->SetWidth( via->Diameter() ); + via_board->SetDrill( via->Drill() ); + via_board->SetNetCode( via->Net() ); + newBI = via_board; + break; + } default: break; @@ -770,34 +774,33 @@ PNS_VIA* PNS_ROUTER::checkLoneVia( PNS_JOINT* aJoint ) const return NULL; } + bool PNS_ROUTER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { bool rv = false; - switch(m_state) + switch( m_state ) { case ROUTE_TRACK: - rv = m_placer->FixRoute (aP, aEndItem); + rv = m_placer->FixRoute( aP, aEndItem ); m_placingVia = false; - break; + case DRAG_SEGMENT: - rv = m_dragger->FixRoute (); + rv = m_dragger->FixRoute(); break; default: break; } - - if(rv) + if( rv ) StopRouting(); return rv; } - void PNS_ROUTER::StopRouting() { // Update the ratsnest with new changes @@ -806,10 +809,10 @@ void PNS_ROUTER::StopRouting() if( !RoutingInProgress() ) return; - if(m_placer) + if( m_placer ) delete m_placer; - if(m_dragger) + if( m_dragger ) delete m_dragger; m_placer = NULL; @@ -825,7 +828,7 @@ void PNS_ROUTER::StopRouting() void PNS_ROUTER::FlipPosture() { - if(m_state == ROUTE_TRACK) + if( m_state == ROUTE_TRACK ) { m_placer->FlipPosture(); m_placer->Move ( m_currentEnd, m_currentEndItem ); @@ -833,22 +836,23 @@ void PNS_ROUTER::FlipPosture() } -void PNS_ROUTER::SwitchLayer( int layer ) +void PNS_ROUTER::SwitchLayer( int aLayer ) { switch( m_state ) { case IDLE: - m_currentLayer = layer; + m_currentLayer = aLayer; break; case ROUTE_TRACK: - if( m_startsOnVia ) - { - m_currentLayer = layer; - //m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth, - // m_currentLayer ); - } - break; + if( m_startsOnVia ) + { + m_currentLayer = aLayer; + //m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth, + // m_currentLayer ); + } + break; + default: break; } @@ -864,32 +868,38 @@ void PNS_ROUTER::ToggleViaPlacement() } } + int PNS_ROUTER::GetCurrentNet() const { - switch(m_state) + switch( m_state ) { case ROUTE_TRACK: return m_placer->CurrentNet(); + default: return m_currentNet; } } + int PNS_ROUTER::GetCurrentLayer() const { - switch(m_state) + switch( m_state ) { case ROUTE_TRACK: return m_placer->CurrentLayer(); + default: return m_currentLayer; } } - + + void PNS_ROUTER::DumpLog() { - PNS_LOGGER *logger = NULL; - switch(m_state) + PNS_LOGGER* logger = NULL; + + switch( m_state ) { case DRAG_SEGMENT: logger = m_dragger->Logger(); @@ -899,6 +909,6 @@ void PNS_ROUTER::DumpLog() break; } - if(logger) + if( logger ) logger->Save ( "/tmp/shove.log" ); } diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 9c867c585d..b5fc2a6daa 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -51,9 +51,10 @@ class PNS_CLEARANCE_FUNC; class PNS_SHOVE; class PNS_DRAGGER; -namespace KIGFX { -class VIEW; -class VIEW_GROUP; +namespace KIGFX +{ + class VIEW; + class VIEW_GROUP; }; @@ -62,7 +63,6 @@ class VIEW_GROUP; * * Main router class. */ - class PNS_ROUTER { private: @@ -94,7 +94,7 @@ public: const VECTOR2I CurrentEnd() const; - int GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const; + int GetClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const; PNS_NODE* GetWorld() const { @@ -114,8 +114,8 @@ public: void ToggleViaPlacement(); - int GetCurrentLayer() const;// { return m_currentLayer; } - int GetCurrentNet() const;// { return m_currentNet; } + int GetCurrentLayer() const; + int GetCurrentNet() const; void DumpLog(); @@ -134,14 +134,19 @@ public: // typedef boost::optional optHoverItem; const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP ); - const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment ); + const VECTOR2I SnapToItem( PNS_ITEM* aItem, VECTOR2I aP, bool& aSplitsSegment ); bool StartDragging( const VECTOR2I& aP, PNS_ITEM* aItem ); void SetIterLimit( int aX ) { m_iterLimit = aX; } int GetIterLimit() const { return m_iterLimit; }; - void SetShowIntermediateSteps(bool aX, int aSnapshotIter = -1 ) { m_showInterSteps = aX; m_snapshotIter = aSnapshotIter; } + void SetShowIntermediateSteps( bool aX, int aSnapshotIter = -1 ) + { + m_showInterSteps = aX; + m_snapshotIter = aSnapshotIter; + } + bool GetShowIntermediateSteps() const { return m_showInterSteps; } int GetShapshotIter() const { return m_snapshotIter; } @@ -168,7 +173,7 @@ public: /** * Applies stored settings. - * \see Settings() + * @see Settings() */ void ApplySettings(); @@ -183,30 +188,29 @@ public: ApplySettings(); } - void EnableSnapping ( bool aEnable ) + void EnableSnapping( bool aEnable ) { m_snappingEnabled = aEnable; } - bool SnappingEnabled () const + bool SnappingEnabled() const { return m_snappingEnabled; } - private: - void movePlacing ( const VECTOR2I& aP, PNS_ITEM* aItem ); - void moveDragging ( const VECTOR2I& aP, PNS_ITEM* aItem ); + void movePlacing( const VECTOR2I& aP, PNS_ITEM* aItem ); + void moveDragging( const VECTOR2I& aP, PNS_ITEM* aItem ); void eraseView(); - void updateView( PNS_NODE *aNode, PNS_ITEMSET &aCurrent ); //PNS_LINE *aCurrent = NULL ); + void updateView( PNS_NODE* aNode, PNS_ITEMSET& aCurrent ); void clearViewFlags(); // optHoverItem queryHoverItemEx(const VECTOR2I& aP); - PNS_ITEM* pickSingleItem( PNS_ITEMSET& aItems ) const; // std::vector aItems) const; - void splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP ); // optHoverItem& aItem); + PNS_ITEM* pickSingleItem( PNS_ITEMSET& aItems ) const; + void splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP ); PNS_VIA* checkLoneVia( PNS_JOINT* aJoint ) const; PNS_ITEM* syncPad( D_PAD* aPad ); @@ -219,7 +223,7 @@ private: void highlightCurrent( bool enabled ); - void markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ItemVector& aRemoved ); + void markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ITEM_VECTOR& aRemoved ); int m_currentLayer; int m_currentNet; @@ -241,8 +245,7 @@ private: KIGFX::VIEW* m_view; KIGFX::VIEW_GROUP* m_previewItems; - - PNS_ITEM *m_currentEndItem; + PNS_ITEM* m_currentEndItem; VECTOR2I m_currentEnd; VECTOR2I m_currentStart; @@ -252,7 +255,7 @@ private: bool m_snappingEnabled; bool m_violation; -// optHoverItem m_startItem, m_endItem; + // optHoverItem m_startItem, m_endItem; PNS_ROUTING_SETTINGS m_settings; PNS_CLEARANCE_FUNC* m_clearanceFunc; diff --git a/pcbnew/router/pns_routing_settings.cpp b/pcbnew/router/pns_routing_settings.cpp index cddc110311..cf87359674 100644 --- a/pcbnew/router/pns_routing_settings.cpp +++ b/pcbnew/router/pns_routing_settings.cpp @@ -23,7 +23,7 @@ PNS_ROUTING_SETTINGS::PNS_ROUTING_SETTINGS() { m_routingMode = RM_Walkaround; - m_optimizerEffort = OE_Full; + m_optimizerEffort = OE_FULL; m_removeLoops = true; m_smartPads = true; m_shoveVias = true; @@ -38,11 +38,13 @@ PNS_ROUTING_SETTINGS::PNS_ROUTING_SETTINGS() m_canViolateDRC = false; } + TIME_LIMIT PNS_ROUTING_SETTINGS::ShoveTimeLimit() const { return TIME_LIMIT ( m_shoveTimeLimit ); } + int PNS_ROUTING_SETTINGS::ShoveIterationLimit() const { return m_shoveIterationLimit; diff --git a/pcbnew/router/pns_routing_settings.h b/pcbnew/router/pns_routing_settings.h index 02eab2a352..5f6de3fa92 100644 --- a/pcbnew/router/pns_routing_settings.h +++ b/pcbnew/router/pns_routing_settings.h @@ -36,9 +36,9 @@ enum PNS_MODE ///> Optimization effort enum PNS_OPTIMIZATION_EFFORT { - OE_Low = 0, - OE_Medium = 1, - OE_Full = 2 + OE_LOW = 0, + OE_MEDIUM = 1, + OE_FULL = 2 }; /** @@ -91,7 +91,7 @@ public: ///> Returns true if follow mouse mode is active (permanently on for the moment). bool FollowMouse() const { - return m_followMouse && !(Mode() == RM_MarkObstacles); + return m_followMouse && !( Mode() == RM_MarkObstacles ); } ///> Returns true if smoothing segments durign dragging is enabled. @@ -120,10 +120,10 @@ public: const DIRECTION_45 InitialDirection() const { - if(m_startDiagonal) - return DIRECTION_45 (DIRECTION_45::NE); + if( m_startDiagonal ) + return DIRECTION_45( DIRECTION_45::NE ); else - return DIRECTION_45 (DIRECTION_45::N); + return DIRECTION_45( DIRECTION_45::N ); } int ShoveIterationLimit() const; @@ -133,7 +133,6 @@ public: TIME_LIMIT WalkaroundTimeLimit() const; private: - bool m_shoveVias; bool m_startDiagonal; bool m_removeLoops; diff --git a/pcbnew/router/pns_segment.h b/pcbnew/router/pns_segment.h index 0ebc4bc767..2550526c2e 100644 --- a/pcbnew/router/pns_segment.h +++ b/pcbnew/router/pns_segment.h @@ -37,17 +37,17 @@ class PNS_SEGMENT : public PNS_ITEM public: PNS_SEGMENT() : PNS_ITEM( SEGMENT ) - {}; + {} PNS_SEGMENT( const SEG& aSeg, int aNet ) : - PNS_ITEM( SEGMENT ), m_seg(aSeg, 0) + PNS_ITEM( SEGMENT ), m_seg( aSeg, 0 ) { m_net = aNet; - }; + } PNS_SEGMENT( const PNS_LINE& aParentLine, const SEG& aSeg ) : PNS_ITEM( SEGMENT ), - m_seg(aSeg, aParentLine.Width()) + m_seg( aSeg, aParentLine.Width() ) { m_net = aParentLine.Net(); m_layers = aParentLine.Layers(); @@ -55,7 +55,6 @@ public: m_rank = aParentLine.Rank(); }; - PNS_SEGMENT* Clone( ) const; const SHAPE* Shape() const @@ -101,14 +100,14 @@ public: void SwapEnds() { SEG tmp = m_seg.GetSeg(); - m_seg.SetSeg( SEG (tmp.B , tmp.A )); + m_seg.SetSeg( SEG (tmp.B , tmp.A ) ); } const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const; virtual VECTOR2I Anchor(int n) const { - if(n == 0) + if( n == 0 ) return m_seg.GetSeg().A; else return m_seg.GetSeg().B; diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index 491f3327f3..8b46a503db 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -41,63 +41,70 @@ #include -static void sanityCheck (PNS_LINE *l_old, PNS_LINE *l_new) +static void sanityCheck( PNS_LINE *aOld, PNS_LINE *aNew ) { - assert (l_old->CPoint(0) == l_new->CPoint(0) ); - assert (l_old->CPoint(-1) == l_new->CPoint(-1 )); + assert( aOld->CPoint( 0 ) == aNew->CPoint( 0 ) ); + assert( aOld->CPoint( -1 ) == aNew->CPoint( -1 ) ); } -PNS_SHOVE::PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER *aRouter ) : + +PNS_SHOVE::PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter ) : PNS_ALGO_BASE ( aRouter ) { m_root = aWorld; -}; +} PNS_SHOVE::~PNS_SHOVE() { -// free all the stuff we've created during routing/dragging operation. - BOOST_FOREACH(PNS_ITEM *item, m_gcItems) + // free all the stuff we've created during routing/dragging operation. + BOOST_FOREACH( PNS_ITEM *item, m_gcItems ) delete item; } + // garbage-collected line assembling -PNS_LINE* PNS_SHOVE::assembleLine ( const PNS_SEGMENT *aSeg, int *aIndex ) +PNS_LINE* PNS_SHOVE::assembleLine( const PNS_SEGMENT *aSeg, int *aIndex ) { - PNS_LINE *l = m_currentNode->AssembleLine( const_cast (aSeg), aIndex); + PNS_LINE* l = m_currentNode->AssembleLine( const_cast( aSeg ), aIndex ); m_gcItems.push_back(l); + return l; } + // garbage-collected line cloning PNS_LINE *PNS_SHOVE::cloneLine ( const PNS_LINE *aLine ) { PNS_LINE *l = aLine->Clone(); - m_gcItems.push_back(l); + m_gcItems.push_back( l ); return l; } + // A dumb function that checks if the shoved line is shoved the right way, e.g. // visually "outwards" of the line/via applying pressure on it. Unfortunately there's no // mathematical concept of orientation of an open curve, so we use some primitive heuristics: // if the shoved line wraps around the start of the "pusher", it's likely shoved in wrong direction. -bool PNS_SHOVE::checkBumpDirection ( PNS_LINE *aCurrent, PNS_LINE *aShoved ) const +bool PNS_SHOVE::checkBumpDirection( PNS_LINE *aCurrent, PNS_LINE *aShoved ) const { - const SEG ss = aCurrent->CSegment(0); + const SEG ss = aCurrent->CSegment( 0 ); - int dist = m_currentNode->GetClearance(aCurrent, aShoved) + PNS_HULL_MARGIN; + int dist = m_currentNode->GetClearance( aCurrent, aShoved ) + PNS_HULL_MARGIN; dist += aCurrent->Width() / 2; dist += aShoved->Width() / 2; - const VECTOR2I ps = ss.A - (ss.B - ss.A).Resize(dist); + const VECTOR2I ps = ss.A - ( ss.B - ss.A ).Resize( dist ); - return !aShoved->CLine().PointOnEdge(ps); + return !aShoved->CLine().PointOnEdge( ps ); } -PNS_SHOVE::ShoveStatus PNS_SHOVE::walkaroundLoneVia ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved ) + +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::walkaroundLoneVia( PNS_LINE* aCurrent, PNS_LINE* aObstacle, + PNS_LINE* aShoved ) { int clearance = m_currentNode->GetClearance( aCurrent, aObstacle ); const SHAPE_LINE_CHAIN hull = aCurrent->Via().Hull( clearance, aObstacle->Width() ); @@ -108,13 +115,15 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::walkaroundLoneVia ( PNS_LINE *aCurrent, PNS_LI const SHAPE_LINE_CHAIN& shortest = path_ccw.Length() < path_cw.Length() ? path_ccw : path_cw; - if(shortest.PointCount() < 2) + if( shortest.PointCount() < 2 ) return SH_INCOMPLETE; - if(aObstacle->CPoint(-1) != shortest.CPoint(-1)) + + if( aObstacle->CPoint( -1 ) != shortest.CPoint( -1 ) ) return SH_INCOMPLETE; - if(aObstacle->CPoint(0) != shortest.CPoint(0)) + + if( aObstacle->CPoint( 0 ) != shortest.CPoint( 0 ) ) return SH_INCOMPLETE; - + aShoved->SetShape( shortest ); if( m_currentNode->CheckColliding( aShoved, aCurrent ) ) @@ -123,33 +132,35 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::walkaroundLoneVia ( PNS_LINE *aCurrent, PNS_LI return SH_OK; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::processHullSet ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved, const HullSet& hulls ) + +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE* aObstacle, + PNS_LINE* aShoved, const HULL_SET& aHulls ) { const SHAPE_LINE_CHAIN& obs = aObstacle->CLine(); bool failingDirCheck = false; int attempt; - for(attempt = 0; attempt < 4; attempt++) + for( attempt = 0; attempt < 4; attempt++ ) { - bool invertTraversal = (attempt >= 2); + bool invertTraversal = ( attempt >= 2 ); bool clockwise = attempt % 2; int vFirst = -1, vLast = -1; SHAPE_LINE_CHAIN path; - PNS_LINE l ( *aObstacle ); + PNS_LINE l( *aObstacle ); - for(int i = 0; i < (int)hulls.size(); i++ ) + for( int i = 0; i < (int) aHulls.size(); i++ ) { - const SHAPE_LINE_CHAIN& hull = hulls[invertTraversal ? hulls.size() - 1 - i : i]; + const SHAPE_LINE_CHAIN& hull = aHulls[invertTraversal ? aHulls.size() - 1 - i : i]; l.Walkaround( hull, path, clockwise ); path.Simplify(); l.SetShape( path ); } - for(int i = 0; i < std::min ( path.PointCount(), obs.PointCount() ); i++) + for( int i = 0; i < std::min ( path.PointCount(), obs.PointCount() ); i++ ) { - if(path.CPoint(i) != obs.CPoint(i)) + if( path.CPoint( i ) != obs.CPoint( i ) ) { vFirst = i; break; @@ -157,36 +168,37 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::processHullSet ( PNS_LINE *aCurrent, PNS_LINE } int k = obs.PointCount() - 1; - for(int i = path.PointCount() - 1; i >= 0 && k >= 0; i--, k--) + for( int i = path.PointCount() - 1; i >= 0 && k >= 0; i--, k-- ) { - if(path.CPoint(i) != obs.CPoint(k)) + if( path.CPoint( i ) != obs.CPoint( k ) ) { vLast = i; break; } } - if( ( vFirst < 0 || vLast < 0) && !path.CompareGeometry( aObstacle->CLine() )) + if( ( vFirst < 0 || vLast < 0 ) && !path.CompareGeometry( aObstacle->CLine() ) ) { TRACE( 100, "attempt %d fail vfirst-last", attempt ); continue; } - if(path.CPoint(-1) != obs.CPoint(-1) || path.CPoint(0) != obs.CPoint(0)) + if( path.CPoint( -1 ) != obs.CPoint( -1 ) || path.CPoint( 0 ) != obs.CPoint( 0 ) ) { - TRACE(100, "attempt %d fail vend-start\n", attempt); + TRACE( 100, "attempt %d fail vend-start\n", attempt ); continue; } - if(!checkBumpDirection(aCurrent, &l)) + if( !checkBumpDirection( aCurrent, &l ) ) { TRACE( 100, "attempt %d fail direction-check", attempt ); failingDirCheck = true; - aShoved->SetShape(l.CLine()); + aShoved->SetShape( l.CLine() ); + continue; } - if(path.SelfIntersecting()) + if( path.SelfIntersecting() ) { TRACE( 100, "attempt %d fail self-intersect", attempt ); continue; @@ -194,13 +206,13 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::processHullSet ( PNS_LINE *aCurrent, PNS_LINE bool colliding = m_currentNode->CheckColliding( &l, aCurrent ); - if( (aCurrent->Marker() & MK_HEAD) && !colliding) + if( ( aCurrent->Marker() & MK_HEAD ) && !colliding ) { - PNS_JOINT *jtStart = m_currentNode->FindJoint ( aCurrent->CPoint(0), aCurrent ); + PNS_JOINT* jtStart = m_currentNode->FindJoint( aCurrent->CPoint( 0 ), aCurrent ); - BOOST_FOREACH( PNS_ITEM *item, jtStart->LinkList() ) + BOOST_FOREACH( PNS_ITEM* item, jtStart->LinkList() ) { - if(m_currentNode->CheckColliding(item, &l)) + if( m_currentNode->CheckColliding( item, &l ) ) colliding = true; } } @@ -219,7 +231,9 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::processHullSet ( PNS_LINE *aCurrent, PNS_LINE return failingDirCheck ? SH_OK : SH_INCOMPLETE; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::processSingleLine ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved ) + +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processSingleLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle, + PNS_LINE* aShoved ) { aShoved->ClearSegmentLinks(); @@ -227,73 +241,75 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::processSingleLine ( PNS_LINE *aCurrent, PNS_LI if( aObstacle->LinkedSegments() ) { - BOOST_FOREACH( PNS_SEGMENT *s, *aObstacle->LinkedSegments() ) - if(s->Marker() & MK_HEAD) + BOOST_FOREACH( PNS_SEGMENT* s, *aObstacle->LinkedSegments() ) + + if( s->Marker() & MK_HEAD ) { obstacleIsHead = true; break; } } - ShoveStatus rv; + SHOVE_STATUS rv; bool viaOnEnd = aCurrent->EndsWithVia(); if( viaOnEnd && ( !aCurrent->LayersOverlap( aObstacle ) || aCurrent->SegmentCount() == 0 ) ) { rv = walkaroundLoneVia( aCurrent, aObstacle, aShoved ); - } else { + } + else + { int w = aObstacle->Width(); int n_segs = aCurrent->SegmentCount(); int clearance = m_currentNode->GetClearance( aCurrent, aObstacle ); - HullSet hulls; + HULL_SET hulls; hulls.reserve( n_segs + 1 ); for( int i = 0; i < n_segs; i++ ) { - PNS_SEGMENT seg ( *aCurrent, aCurrent->CSegment(i) ); - hulls.push_back ( seg.Hull( clearance, w ) ); + PNS_SEGMENT seg( *aCurrent, aCurrent->CSegment( i ) ); + hulls.push_back( seg.Hull( clearance, w ) ); } if( viaOnEnd ) hulls.push_back ( aCurrent->Via().Hull( clearance, w ) ); - rv = processHullSet ( aCurrent, aObstacle, aShoved, hulls); + rv = processHullSet ( aCurrent, aObstacle, aShoved, hulls ); } - if(obstacleIsHead) + if( obstacleIsHead ) aShoved->Mark( aShoved->Marker() | MK_HEAD ); return rv; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingSegment( PNS_LINE *aCurrent, PNS_SEGMENT *aObstacleSeg ) +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSegment( PNS_LINE* aCurrent, PNS_SEGMENT* aObstacleSeg ) { int segIndex; - PNS_LINE *obstacleLine = assembleLine (aObstacleSeg, &segIndex); - PNS_LINE *shovedLine = cloneLine ( obstacleLine ); + PNS_LINE* obstacleLine = assembleLine( aObstacleSeg, &segIndex ); + PNS_LINE* shovedLine = cloneLine( obstacleLine ); - ShoveStatus rv = processSingleLine ( aCurrent, obstacleLine, shovedLine ); - - assert ( obstacleLine->LayersOverlap (shovedLine) ); + SHOVE_STATUS rv = processSingleLine( aCurrent, obstacleLine, shovedLine ); + assert ( obstacleLine->LayersOverlap( shovedLine ) ); - if(rv == SH_OK) + if( rv == SH_OK ) { if ( shovedLine->Marker() & MK_HEAD ) m_newHead = *shovedLine; - sanityCheck(obstacleLine, shovedLine); - m_currentNode->Replace (obstacleLine, shovedLine); - sanityCheck(obstacleLine, shovedLine); + sanityCheck( obstacleLine, shovedLine ); + m_currentNode->Replace( obstacleLine, shovedLine ); + sanityCheck( obstacleLine, shovedLine ); int rank = aCurrent->Rank(); - shovedLine->SetRank ( rank - 1 ); + shovedLine->SetRank( rank - 1 ); - pushLine(shovedLine); + pushLine( shovedLine ); } #ifdef DEBUG @@ -307,64 +323,64 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingSegment( PNS_LINE *aCurrent, PNS_SE return rv; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingLine( PNS_LINE *aCurrent, PNS_LINE *aObstacle ) + +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingLine( PNS_LINE *aCurrent, PNS_LINE *aObstacle ) { - PNS_LINE *shovedLine = cloneLine(aObstacle); + PNS_LINE* shovedLine = cloneLine( aObstacle ); - ShoveStatus rv = processSingleLine ( aCurrent, aObstacle, shovedLine ); + SHOVE_STATUS rv = processSingleLine( aCurrent, aObstacle, shovedLine ); - if(rv == SH_OK) + if( rv == SH_OK ) { if ( shovedLine->Marker() & MK_HEAD ) m_newHead = *shovedLine; - sanityCheck(aObstacle,shovedLine); + sanityCheck( aObstacle, shovedLine ); m_currentNode->Replace( aObstacle, shovedLine ); - sanityCheck(aObstacle,shovedLine); + sanityCheck( aObstacle, shovedLine ); int rank = aObstacle->Rank(); shovedLine->SetRank ( rank ); - pushLine(shovedLine); + pushLine( shovedLine ); #ifdef DEBUG - m_logger.NewGroup ("on-colliding-line", m_iter); - m_logger.Log ( aObstacle, 0, "obstacle-line"); - m_logger.Log ( aCurrent, 1, "current-line"); - m_logger.Log ( shovedLine, 3, "shoved-line"); + m_logger.NewGroup( "on-colliding-line", m_iter ); + m_logger.Log( aObstacle, 0, "obstacle-line" ); + m_logger.Log( aCurrent, 1, "current-line" ); + m_logger.Log( shovedLine, 3, "shoved-line" ); #endif - - } - return rv; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingSolid( PNS_LINE *aCurrent, PNS_SOLID *aObstacleSolid ) + +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE* aCurrent, PNS_SOLID* aObstacleSolid ) { PNS_WALKAROUND walkaround( m_currentNode, Router() ); - PNS_LINE* walkaroundLine = cloneLine(aCurrent); + PNS_LINE* walkaroundLine = cloneLine( aCurrent ); - - if(aCurrent->EndsWithVia()) + if( aCurrent->EndsWithVia() ) { PNS_VIA vh = aCurrent->Via(); - PNS_VIA *via = NULL; - PNS_JOINT *jtStart = m_currentNode->FindJoint ( vh.Pos(), aCurrent ); + PNS_VIA* via = NULL; + PNS_JOINT* jtStart = m_currentNode->FindJoint ( vh.Pos(), aCurrent ); - if(!jtStart) + if( !jtStart ) return SH_INCOMPLETE; - BOOST_FOREACH( PNS_ITEM *item, jtStart->LinkList() ) - if(item->OfKind(PNS_ITEM::VIA)) - { - via = (PNS_VIA *) item; - break; - } + BOOST_FOREACH( PNS_ITEM* item, jtStart->LinkList() ) + { + if( item->OfKind( PNS_ITEM::VIA ) ) + { + via = (PNS_VIA*) item; + break; + } + } - if( via && m_currentNode->CheckColliding(via, aObstacleSolid) ) - return onCollidingVia ( aObstacleSolid, via ); + if( via && m_currentNode->CheckColliding( via, aObstacleSolid ) ) + return onCollidingVia( aObstacleSolid, via ); } walkaround.SetSolidsOnly( true ); @@ -373,45 +389,45 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingSolid( PNS_LINE *aCurrent, PNS_SOLI int currentRank = aCurrent->Rank(); int nextRank; - if (!Settings().JumpOverObstacles() ) + if( !Settings().JumpOverObstacles() ) { nextRank = currentRank + 10000; walkaround.SetSingleDirection( false ); - } else { + } + else + { nextRank = currentRank - 1; walkaround.SetSingleDirection( true ); } - - if (walkaround.Route( *aCurrent, *walkaroundLine, false ) != PNS_WALKAROUND::DONE ) + if( walkaround.Route( *aCurrent, *walkaroundLine, false ) != PNS_WALKAROUND::DONE ) return SH_INCOMPLETE; walkaroundLine->ClearSegmentLinks(); walkaroundLine->Unmark(); walkaroundLine->Line().Simplify(); - if(walkaroundLine->HasLoops()) + if( walkaroundLine->HasLoops() ) return SH_INCOMPLETE; - if (aCurrent->Marker() & MK_HEAD) + if( aCurrent->Marker() & MK_HEAD ) { - walkaroundLine->Mark(MK_HEAD); + walkaroundLine->Mark( MK_HEAD ); m_newHead = *walkaroundLine; } - m_currentNode->Replace( aCurrent, walkaroundLine ); walkaroundLine->SetRank ( nextRank ); #ifdef DEBUG - m_logger.NewGroup ("on-colliding-solid", m_iter); - m_logger.Log ( aObstacleSolid, 0, "obstacle-solid"); - m_logger.Log ( aCurrent, 1, "current-line"); - m_logger.Log ( walkaroundLine, 3, "walk-line"); + m_logger.NewGroup( "on-colliding-solid", m_iter ); + m_logger.Log( aObstacleSolid, 0, "obstacle-solid" ); + m_logger.Log( aCurrent, 1, "current-line" ); + m_logger.Log( walkaroundLine, 3, "walk-line" ); #endif popLine(); - pushLine(walkaroundLine); + pushLine( walkaroundLine ); return SH_OK; } @@ -423,13 +439,13 @@ bool PNS_SHOVE::reduceSpringback( const PNS_ITEMSET& aHeadSet ) while( !m_nodeStack.empty() ) { - SpringbackTag spTag = m_nodeStack.back(); + SPRINGBACK_TAG spTag = m_nodeStack.back(); - if( !spTag.node->CheckColliding( aHeadSet ) ) + if( !spTag.m_node->CheckColliding( aHeadSet ) ) { rv = true; - delete spTag.node; + delete spTag.m_node; m_nodeStack.pop_back(); } else @@ -440,98 +456,99 @@ bool PNS_SHOVE::reduceSpringback( const PNS_ITEMSET& aHeadSet ) } - -bool PNS_SHOVE::pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET& aHeadItems, const PNS_COST_ESTIMATOR& aCost ) +bool PNS_SHOVE::pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET& aHeadItems, + const PNS_COST_ESTIMATOR& aCost ) { - SpringbackTag st; + SPRINGBACK_TAG st; - st.node = aNode; - st.cost = aCost; - st.headItems = aHeadItems; + st.m_node = aNode; + st.m_cost = aCost; + st.m_headItems = aHeadItems; m_nodeStack.push_back( st ); + return true; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::pushVia ( PNS_VIA *aVia, const VECTOR2I& aForce, int aCurrentRank ) +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForce, int aCurrentRank ) { - - LinePairVec draggedLines; + LINE_PAIR_VEC draggedLines; VECTOR2I p0 ( aVia->Pos() ); - PNS_JOINT *jt = m_currentNode->FindJoint( p0, 1, aVia->Net() ); - PNS_VIA *pushedVia = aVia -> Clone(); + PNS_JOINT* jt = m_currentNode->FindJoint( p0, 1, aVia->Net() ); + PNS_VIA* pushedVia = aVia -> Clone(); pushedVia->SetPos( p0 + aForce ); - pushedVia->Mark( aVia->Marker() ) ; + pushedVia->Mark( aVia->Marker() ); - if(aVia->Marker() & MK_HEAD) + if( aVia->Marker() & MK_HEAD ) { m_draggedVia = pushedVia; } - if(!jt) + if( !jt ) { - TRACEn(1, "weird, can't find the center-of-via joint\n"); + TRACEn( 1, "weird, can't find the center-of-via joint\n" ); return SH_INCOMPLETE; } - BOOST_FOREACH(PNS_ITEM *item, jt->LinkList() ) + BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() ) { - if(item->OfKind( PNS_ITEM::SEGMENT )) + if( item->OfKind( PNS_ITEM::SEGMENT ) ) { - PNS_SEGMENT *seg = (PNS_SEGMENT *) item; - LinePair lp; + PNS_SEGMENT* seg = (PNS_SEGMENT*) item; + LINE_PAIR lp; int segIndex; - lp.first = assembleLine(seg, &segIndex); + lp.first = assembleLine( seg, &segIndex ); - assert(segIndex == 0 || (segIndex == (lp.first->SegmentCount() - 1) )); + assert( segIndex == 0 || ( segIndex == ( lp.first->SegmentCount() - 1 ) ) ); - if(segIndex == 0) + if( segIndex == 0 ) lp.first->Reverse(); lp.second = cloneLine( lp.first ); lp.second->ClearSegmentLinks(); - lp.second->DragCorner( p0 + aForce, lp.second->CLine().Find( p0 )); + lp.second->DragCorner( p0 + aForce, lp.second->CLine().Find( p0 ) ); lp.second->AppendVia ( *pushedVia ); - draggedLines.push_back(lp); + draggedLines.push_back( lp ); } } m_currentNode->Remove( aVia ); m_currentNode->Add ( pushedVia ); - if(aVia->BelongsTo(m_currentNode)) + if( aVia->BelongsTo( m_currentNode ) ) delete aVia; - pushedVia -> SetRank (aCurrentRank - 1); + pushedVia->SetRank( aCurrentRank - 1 ); #ifdef DEBUG m_logger.Log ( aVia, 0, "obstacle-via"); m_logger.Log ( pushedVia, 1, "pushed-via"); #endif - BOOST_FOREACH( LinePair lp, draggedLines ) + BOOST_FOREACH( LINE_PAIR lp, draggedLines ) { - if(lp.first->Marker() & MK_HEAD) + if( lp.first->Marker() & MK_HEAD ) { - lp.second->Mark ( MK_HEAD ); + lp.second->Mark( MK_HEAD ); m_newHead = *lp.second; } unwindStack(lp.first); - if(lp.second->SegmentCount()) + if( lp.second->SegmentCount() ) { - m_currentNode->Replace ( lp.first, lp.second ); - lp.second->SetRank( aCurrentRank - 1); - pushLine(lp.second); - } else - m_currentNode->Remove(lp.first); + m_currentNode->Replace( lp.first, lp.second ); + lp.second->SetRank( aCurrentRank - 1 ); + pushLine( lp.second ); + } + else + m_currentNode->Remove( lp.first ); #ifdef DEBUG - m_logger.Log ( lp.first, 2, "fan-pre"); - m_logger.Log ( lp.second, 3, "fan-post"); + m_logger.Log( lp.first, 2, "fan-pre" ); + m_logger.Log( lp.second, 3, "fan-post" ); #endif } @@ -539,108 +556,112 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::pushVia ( PNS_VIA *aVia, const VECTOR2I& aForc } -PNS_SHOVE::ShoveStatus PNS_SHOVE::onCollidingVia (PNS_ITEM *aCurrent, PNS_VIA *aObstacleVia ) +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingVia (PNS_ITEM* aCurrent, PNS_VIA* aObstacleVia ) { int clearance = m_currentNode->GetClearance( aCurrent, aObstacleVia ) ; - LinePairVec draggedLines; - VECTOR2I p0 ( aObstacleVia->Pos() ); + LINE_PAIR_VEC draggedLines; + VECTOR2I p0( aObstacleVia->Pos() ); bool colLine = false, colVia = false; PNS_LINE *currentLine = NULL; VECTOR2I mtvLine, mtvVia, mtv, mtvSolid; int rank = -1; - if( aCurrent->OfKind (PNS_ITEM::LINE)) + if( aCurrent->OfKind( PNS_ITEM::LINE ) ) { - #ifdef DEBUG - m_logger.NewGroup ("push-via-by-line", m_iter); - m_logger.Log(aCurrent, 4, "current"); + m_logger.NewGroup( "push-via-by-line", m_iter ); + m_logger.Log( aCurrent, 4, "current" ); #endif currentLine = (PNS_LINE*) aCurrent; - colLine = CollideShapes( aObstacleVia->Shape(), currentLine->Shape(), clearance + currentLine->Width() / 2 + PNS_HULL_MARGIN, true, mtvLine ); + colLine = CollideShapes( aObstacleVia->Shape(), currentLine->Shape(), + clearance + currentLine->Width() / 2 + PNS_HULL_MARGIN, + true, mtvLine ); - if(currentLine->EndsWithVia()) - colVia = CollideShapes (currentLine->Via().Shape(), aObstacleVia->Shape(), clearance + PNS_HULL_MARGIN, true, mtvVia); + if( currentLine->EndsWithVia() ) + colVia = CollideShapes( currentLine->Via().Shape(), aObstacleVia->Shape(), + clearance + PNS_HULL_MARGIN, true, mtvVia ); - if(!colLine && !colVia) - return SH_OK; + if( !colLine && !colVia ) + return SH_OK; - if(colLine && colVia) + if( colLine && colVia ) mtv = mtvVia.EuclideanNorm() > mtvLine.EuclideanNorm() ? mtvVia : mtvLine; - else if (colLine) + else if( colLine ) mtv = mtvLine; else mtv = mtvVia; + rank = currentLine->Rank(); } else if (aCurrent->OfKind(PNS_ITEM::SOLID)) { - CollideShapes( aObstacleVia->Shape(), aCurrent->Shape(), clearance + PNS_HULL_MARGIN, true, mtvSolid ); + CollideShapes( aObstacleVia->Shape(), aCurrent->Shape(), + clearance + PNS_HULL_MARGIN, true, mtvSolid ); mtv = mtvSolid; rank = aCurrent->Rank() + 10000; } - return pushVia ( aObstacleVia, mtv, rank ); + return pushVia( aObstacleVia, mtv, rank ); } -PNS_SHOVE::ShoveStatus PNS_SHOVE::onReverseCollidingVia (PNS_LINE *aCurrent, PNS_VIA *aObstacleVia ) + +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onReverseCollidingVia( PNS_LINE* aCurrent, PNS_VIA* aObstacleVia ) { - std::vector steps; + std::vector steps; int n = 0; - PNS_LINE *cur = cloneLine( aCurrent ); + PNS_LINE* cur = cloneLine( aCurrent ); cur->ClearSegmentLinks(); - PNS_JOINT *jt = m_currentNode->FindJoint ( aObstacleVia->Pos(), aObstacleVia ); - PNS_LINE *shoved = cloneLine( aCurrent ); + PNS_JOINT* jt = m_currentNode->FindJoint( aObstacleVia->Pos(), aObstacleVia ); + PNS_LINE* shoved = cloneLine( aCurrent ); shoved->ClearSegmentLinks(); - cur->RemoveVia(); unwindStack(aCurrent); - BOOST_FOREACH( PNS_ITEM *item, jt->LinkList() ) + BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() ) { - - if (item->OfKind(PNS_ITEM::SEGMENT) && item->LayersOverlap (aCurrent) ) + if( item->OfKind( PNS_ITEM::SEGMENT ) && item->LayersOverlap( aCurrent ) ) { - PNS_SEGMENT *seg = (PNS_SEGMENT *) item; - PNS_LINE *head = assembleLine( seg ); + PNS_SEGMENT* seg = (PNS_SEGMENT*) item; + PNS_LINE* head = assembleLine( seg ); head->AppendVia( *aObstacleVia ); - ShoveStatus st = processSingleLine ( head, cur, shoved ); + SHOVE_STATUS st = processSingleLine ( head, cur, shoved ); if( st != SH_OK ) { #ifdef DEBUG - m_logger.NewGroup ("on-reverse-via-fail-shove", m_iter); - m_logger.Log ( aObstacleVia, 0, "the-via"); - m_logger.Log ( aCurrent, 1, "current-line"); - m_logger.Log ( shoved, 3, "shoved-line"); + m_logger.NewGroup( "on-reverse-via-fail-shove", m_iter ); + m_logger.Log( aObstacleVia, 0, "the-via" ); + m_logger.Log( aCurrent, 1, "current-line" ); + m_logger.Log( shoved, 3, "shoved-line" ); #endif return st; } - cur->SetShape ( shoved->CLine() ); + + cur->SetShape( shoved->CLine() ); n++; } } - if(!n) + if( !n ) { #ifdef DEBUG - m_logger.NewGroup ("on-reverse-via-fail-lonevia", m_iter); - m_logger.Log ( aObstacleVia, 0, "the-via"); - m_logger.Log ( aCurrent, 1, "current-line"); + m_logger.NewGroup( "on-reverse-via-fail-lonevia", m_iter ); + m_logger.Log( aObstacleVia, 0, "the-via" ); + m_logger.Log( aCurrent, 1, "current-line" ); #endif - PNS_LINE head(*aCurrent); + PNS_LINE head( *aCurrent ); head.Line().Clear(); head.AppendVia( *aObstacleVia ); head.ClearSegmentLinks(); - ShoveStatus st = processSingleLine ( &head, aCurrent, shoved ); + SHOVE_STATUS st = processSingleLine( &head, aCurrent, shoved ); if( st != SH_OK ) return st; @@ -648,96 +669,103 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::onReverseCollidingVia (PNS_LINE *aCurrent, PNS cur->SetShape ( shoved->CLine() ); } - if(aCurrent->EndsWithVia()) - shoved->AppendVia( aCurrent->Via( )); + if( aCurrent->EndsWithVia() ) + shoved->AppendVia( aCurrent->Via() ); #ifdef DEBUG - m_logger.NewGroup ("on-reverse-via", m_iter); - m_logger.Log ( aObstacleVia, 0, "the-via"); - m_logger.Log ( aCurrent, 1, "current-line"); - m_logger.Log ( shoved, 3, "shoved-line"); + m_logger.NewGroup( "on-reverse-via", m_iter ); + m_logger.Log( aObstacleVia, 0, "the-via" ); + m_logger.Log( aCurrent, 1, "current-line" ); + m_logger.Log( shoved, 3, "shoved-line" ); #endif int currentRank = aCurrent->Rank(); m_currentNode->Replace ( aCurrent, shoved ); - pushLine(shoved); + pushLine( shoved ); shoved->SetRank( currentRank ); return SH_OK; } -void PNS_SHOVE::unwindStack ( PNS_SEGMENT *seg ) +void PNS_SHOVE::unwindStack( PNS_SEGMENT *aSeg ) { - for (std::vector::iterator i = m_lineStack.begin(); i != m_lineStack.end(); ) + for( std::vector::iterator i = m_lineStack.begin(); i != m_lineStack.end(); ) { - if( (*i)->ContainsSegment ( seg ) ) + if( (*i)->ContainsSegment ( aSeg ) ) i = m_lineStack.erase( i ); else i++; } - for (std::vector::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ) + for( std::vector::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ) { - if( (*i)->ContainsSegment ( seg ) ) + if( (*i)->ContainsSegment( aSeg ) ) i = m_optimizerQueue.erase( i ); else i++; } } -void PNS_SHOVE::unwindStack ( PNS_ITEM *item ) -{ - if (item->OfKind(PNS_ITEM::SEGMENT)) - unwindStack(static_cast(item)); - else if (item->OfKind(PNS_ITEM::LINE)) { - PNS_LINE *l = static_cast( item ); - if (!l->LinkedSegments()) +void PNS_SHOVE::unwindStack( PNS_ITEM* aItem ) +{ + if( aItem->OfKind( PNS_ITEM::SEGMENT ) ) + unwindStack( static_cast( aItem ) ); + else if( aItem->OfKind( PNS_ITEM::LINE ) ) + { + PNS_LINE* l = static_cast( aItem ); + + if ( !l->LinkedSegments() ) return; - BOOST_FOREACH(PNS_SEGMENT *seg, *l->LinkedSegments() ) - unwindStack(seg); + BOOST_FOREACH( PNS_SEGMENT* seg, *l->LinkedSegments() ) + unwindStack( seg ); } } -void PNS_SHOVE::pushLine (PNS_LINE *l) + +void PNS_SHOVE::pushLine( PNS_LINE* aL ) { - if(l->LinkCount() >= 0 && (l->LinkCount() != l->SegmentCount())) - assert(false); + if( aL->LinkCount() >= 0 && ( aL->LinkCount() != aL->SegmentCount() ) ) + assert( false ); - m_lineStack.push_back(l); - m_optimizerQueue.push_back(l); + m_lineStack.push_back( aL ); + m_optimizerQueue.push_back( aL ); } + void PNS_SHOVE::popLine( ) { - PNS_LINE *l = m_lineStack.back(); + PNS_LINE* l = m_lineStack.back(); - for (std::vector::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ) + for( std::vector::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ) { - if( (*i) == l ) + if( ( *i ) == l ) { i = m_optimizerQueue.erase( i ); - } else + } + else i++; } m_lineStack.pop_back(); } -PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveIteration(int aIter) + +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter ) { PNS_LINE* currentLine = m_lineStack.back(); - PNS_NODE::OptObstacle nearest; - ShoveStatus st; + PNS_NODE::OPT_OBSTACLE nearest; + SHOVE_STATUS st; - PNS_ITEM::PnsKind search_order[] = { PNS_ITEM::SOLID, PNS_ITEM::VIA, PNS_ITEM::SEGMENT }; + PNS_ITEM::PnsKind search_order[] = { PNS_ITEM::SOLID, PNS_ITEM::VIA, PNS_ITEM::SEGMENT }; - for(int i = 0; i < 3; i++) + for( int i = 0; i < 3; i++ ) { nearest = m_currentNode->NearestObstacle( currentLine, search_order[i] ); - if(nearest) + + if( nearest ) break; } @@ -747,23 +775,25 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveIteration(int aIter) return SH_OK; } - PNS_ITEM *ni = nearest->item; + PNS_ITEM* ni = nearest->m_item; - unwindStack(ni); + unwindStack( ni ); - if( !ni->OfKind(PNS_ITEM::SOLID) && ni->Rank() >= 0 && ni->Rank() > currentLine->Rank() ) + if( !ni->OfKind( PNS_ITEM::SOLID ) && ni->Rank() >= 0 && ni->Rank() > currentLine->Rank() ) { switch( ni->Kind() ) { case PNS_ITEM::VIA: { - PNS_VIA *revVia = (PNS_VIA *) ni; + PNS_VIA* revVia = (PNS_VIA*) ni; TRACE( 2, "iter %d: reverse-collide-via", aIter ); - if (currentLine->EndsWithVia() && m_currentNode->CheckColliding(¤tLine->Via(), revVia)) + if( currentLine->EndsWithVia() && m_currentNode->CheckColliding( ¤tLine->Via(), revVia ) ) { st = SH_INCOMPLETE; - } else { + } + else + { st = onReverseCollidingVia ( currentLine, revVia ); } @@ -772,35 +802,37 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveIteration(int aIter) case PNS_ITEM::SEGMENT: { - PNS_SEGMENT *seg = (PNS_SEGMENT* ) ni; + PNS_SEGMENT* seg = (PNS_SEGMENT*) ni; TRACE( 2, "iter %d: reverse-collide-segment ", aIter ); - PNS_LINE *revLine = assembleLine ( seg ); + PNS_LINE* revLine = assembleLine( seg ); popLine(); st = onCollidingLine( revLine, currentLine ); - pushLine(revLine); + pushLine( revLine ); break; } default: - assert(false); + assert( false ); } - } else { // "forward" collisoins + } + else + { // "forward" collisoins switch( ni->Kind() ) { case PNS_ITEM::SEGMENT: TRACE( 2, "iter %d: collide-segment ", aIter ); - st = onCollidingSegment( currentLine, (PNS_SEGMENT* ) ni ); + st = onCollidingSegment( currentLine, (PNS_SEGMENT*) ni ); break; case PNS_ITEM::VIA: TRACE( 2, "iter %d: shove-via ", aIter ); - st = onCollidingVia ( currentLine, (PNS_VIA *) ni ); + st = onCollidingVia( currentLine, (PNS_VIA*) ni ); break; case PNS_ITEM::SOLID: TRACE( 2, "iter %d: walk-solid ", aIter ); - st = onCollidingSolid ( currentLine, (PNS_SOLID *) ni ); + st = onCollidingSolid( currentLine, (PNS_SOLID*) ni ); break; default: @@ -811,12 +843,13 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveIteration(int aIter) return st; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveMainLoop() + +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveMainLoop() { - ShoveStatus st = SH_OK; + SHOVE_STATUS st = SH_OK; TRACE( 1, "ShoveStart [root: %d jts, current: %d jts]", m_root->JointCount() % - m_currentNode->JointCount() ); + m_currentNode->JointCount() ); int iterLimit = Settings().ShoveIterationLimit(); TIME_LIMIT timeLimit = Settings().ShoveTimeLimit(); @@ -827,7 +860,7 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveMainLoop() while( !m_lineStack.empty() ) { - st = shoveIteration(m_iter); + st = shoveIteration( m_iter ); m_iter++; @@ -842,37 +875,37 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveMainLoop() } -PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead ) +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead ) { - ShoveStatus st = SH_OK; + SHOVE_STATUS st = SH_OK; // empty head? nothing to shove... - if( ! aCurrentHead.SegmentCount() ) + if( !aCurrentHead.SegmentCount() ) return SH_INCOMPLETE; - PNS_LINE* head = cloneLine ( &aCurrentHead ); + PNS_LINE* head = cloneLine( &aCurrentHead ); head->ClearSegmentLinks(); m_lineStack.clear(); m_optimizerQueue.clear(); - m_newHead = OptLine(); + m_newHead = OPT_LINE(); m_logger.Clear(); - PNS_ITEMSET headSet ( cloneLine( &aCurrentHead ) ); + PNS_ITEMSET headSet( cloneLine( &aCurrentHead ) ); reduceSpringback( headSet ); - PNS_NODE *parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().node; + PNS_NODE* parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node; m_currentNode = parent->Branch(); m_currentNode->ClearRanks(); m_currentNode->Add( head ); - head->Mark ( MK_HEAD ); - head->SetRank ( 100000 ); + head->Mark( MK_HEAD ); + head->SetRank( 100000 ); - m_logger.NewGroup ("initial", 0); - m_logger.Log ( head, 0, "head"); + m_logger.NewGroup( "initial", 0 ); + m_logger.Log( head, 0, "head" ); PNS_VIA* headVia = NULL; @@ -881,24 +914,24 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead ) headVia = head->Via().Clone(); m_currentNode->Add( headVia ); headVia->Mark( MK_HEAD ); - headVia->SetRank ( 100000 ); - m_logger.Log ( headVia, 0, "head-via"); - + headVia->SetRank( 100000 ); + m_logger.Log( headVia, 0, "head-via" ); } - pushLine (head); + pushLine( head ); st = shoveMainLoop(); - runOptimizer ( m_currentNode, head ); + runOptimizer( m_currentNode, head ); if( m_newHead && st == SH_OK ) { st = SH_HEAD_MODIFIED; - Router()->DisplayDebugLine ( m_newHead->CLine(), 3, 20000 ); + Router()->DisplayDebugLine( m_newHead->CLine(), 3, 20000 ); } - m_currentNode->RemoveByMarker ( MK_HEAD ); + m_currentNode->RemoveByMarker( MK_HEAD ); - TRACE( 1, "Shove status : %s after %d iterations", ((st == SH_OK || st == SH_HEAD_MODIFIED) ? "OK" : "FAILURE") % m_iter ); + TRACE( 1, "Shove status : %s after %d iterations", + ( ( st == SH_OK || st == SH_HEAD_MODIFIED ) ? "OK" : "FAILURE") % m_iter ); if( st == SH_OK || st == SH_HEAD_MODIFIED ) { @@ -909,34 +942,34 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead ) delete m_currentNode; m_currentNode = parent; - m_newHead = OptLine(); + m_newHead = OPT_LINE(); } return st; } -PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveDraggingVia ( PNS_VIA *aVia, const VECTOR2I& aWhere, PNS_VIA **aNewVia ) +PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveDraggingVia( PNS_VIA* aVia, const VECTOR2I& aWhere, + PNS_VIA** aNewVia ) { - ShoveStatus st = SH_OK; + SHOVE_STATUS st = SH_OK; m_lineStack.clear(); m_optimizerQueue.clear(); - m_newHead = OptLine(); + m_newHead = OPT_LINE(); m_draggedVia = NULL; //reduceSpringback( aCurrentHead ); - PNS_NODE *parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().node; + PNS_NODE* parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node; m_currentNode = parent->Branch(); - m_currentNode->ClearRanks(); + m_currentNode->ClearRanks(); aVia->Mark( MK_HEAD ); - - st = pushVia ( aVia, (aWhere - aVia->Pos()), 0 ); + st = pushVia( aVia, ( aWhere - aVia->Pos() ), 0 ); st = shoveMainLoop(); - runOptimizer ( m_currentNode, NULL ); + runOptimizer( m_currentNode, NULL ); if( st == SH_OK || st == SH_HEAD_MODIFIED ) { @@ -948,64 +981,69 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveDraggingVia ( PNS_VIA *aVia, const VECTOR m_currentNode = parent; } - if(aNewVia) + if( aNewVia ) *aNewVia = m_draggedVia; return st; } -void PNS_SHOVE::runOptimizer ( PNS_NODE *node, PNS_LINE *head ) + +void PNS_SHOVE::runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead ) { - PNS_OPTIMIZER optimizer( node ); + PNS_OPTIMIZER optimizer( aNode ); int optFlags = 0, n_passes = 0, extend = 0; PNS_OPTIMIZATION_EFFORT effort = Settings().OptimizerEffort(); - - switch(effort) + switch( effort ) { - case OE_Low: + case OE_LOW: optFlags = PNS_OPTIMIZER::MERGE_OBTUSE; n_passes = 1; extend = 0; break; - case OE_Medium: + + case OE_MEDIUM: optFlags = PNS_OPTIMIZER::MERGE_OBTUSE; n_passes = 2; extend = 1; break; - case OE_Full: + + case OE_FULL: optFlags = PNS_OPTIMIZER::MERGE_SEGMENTS; n_passes = 2; break; + default: break; } - if(Settings().SmartPads()) + if( Settings().SmartPads() ) optFlags |= PNS_OPTIMIZER::SMART_PADS ; optimizer.SetEffortLevel( optFlags ); optimizer.SetCollisionMask( PNS_ITEM::ANY ); - for(int pass = 0; pass < n_passes; pass ++) + for( int pass = 0; pass < n_passes; pass++ ) { - std::reverse ( m_optimizerQueue.begin(), m_optimizerQueue.end() ); - for(std::vector::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ++i) - { - PNS_LINE *line = *i; - - if( ! (line -> Marker() & MK_HEAD ) ) - { - if(effort == OE_Medium || effort == OE_Low ) - { - RANGE r = findShovedVertexRange ( line ); + std::reverse( m_optimizerQueue.begin(), m_optimizerQueue.end() ); - if (r.Defined()) + for( std::vector::iterator i = m_optimizerQueue.begin(); + i != m_optimizerQueue.end(); ++i) + { + PNS_LINE* line = *i; + + if( !( line -> Marker() & MK_HEAD ) ) + { + if( effort == OE_MEDIUM || effort == OE_LOW ) + { + RANGE r = findShovedVertexRange( line ); + + if( r.Defined() ) { - int start_v = std::max(0, r.MinV() - extend); - int end_v = std::min(line->PointCount() - 1 , r.MaxV() + extend ); - line->ClipVertexRange ( start_v, end_v ); + int start_v = std::max( 0, r.MinV() - extend ); + int end_v = std::min( line->PointCount() - 1 , r.MaxV() + extend ); + line->ClipVertexRange( start_v, end_v ); } } @@ -1013,9 +1051,9 @@ void PNS_SHOVE::runOptimizer ( PNS_NODE *node, PNS_LINE *head ) if( optimizer.Optimize( line, &optimized ) ) { - node->Remove( line ); - line->SetShape(optimized.CLine()); - node->Add( line ); + aNode->Remove( line ); + line->SetShape( optimized.CLine() ); + aNode->Add( line ); } } } @@ -1024,23 +1062,24 @@ void PNS_SHOVE::runOptimizer ( PNS_NODE *node, PNS_LINE *head ) } -const RANGE PNS_SHOVE::findShovedVertexRange ( PNS_LINE *l ) + +const RANGE PNS_SHOVE::findShovedVertexRange( PNS_LINE *aL ) { RANGE r; - for(int i = 0; i < l->SegmentCount(); i++) + for( int i = 0; i < aL->SegmentCount(); i++ ) { - PNS_SEGMENT *s = (*l->LinkedSegments())[i]; - PNS_JOINT *jt = m_root->FindJoint( s->Seg().A, s->Layer(), s->Net() ); + PNS_SEGMENT* s = (*aL->LinkedSegments())[i]; + PNS_JOINT* jt = m_root->FindJoint( s->Seg().A, s->Layer(), s->Net() ); bool found = false; - if(jt) + if( jt ) { - BOOST_FOREACH( PNS_ITEM *item, jt->LinkList() ) + BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() ) { - if(item->OfKind(PNS_ITEM::SEGMENT)) + if( item->OfKind( PNS_ITEM::SEGMENT ) ) { - PNS_SEGMENT *s_old = (PNS_SEGMENT *) item; + PNS_SEGMENT* s_old = (PNS_SEGMENT*) item; if( s_old->Net() == s->Net() && s_old->Layer() == s->Layer() && @@ -1054,27 +1093,31 @@ const RANGE PNS_SHOVE::findShovedVertexRange ( PNS_LINE *l ) } } - if(!found) + if( !found ) { - r.Grow(i); - r.Grow(i + 1); + r.Grow( i ); + r.Grow( i + 1 ); } } + return r; } + PNS_NODE* PNS_SHOVE::CurrentNode() { - return m_nodeStack.empty() ? m_root : m_nodeStack.back().node; + return m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node; } + const PNS_LINE PNS_SHOVE::NewHead() const { - assert(m_newHead); + assert( m_newHead ); + return *m_newHead; } -void PNS_SHOVE::SetInitialLine ( PNS_LINE *aInitial ) +void PNS_SHOVE::SetInitialLine( PNS_LINE* aInitial ) { m_root = m_root->Branch(); m_root->Remove ( aInitial ); diff --git a/pcbnew/router/pns_shove.h b/pcbnew/router/pns_shove.h index d070e89790..53568ab281 100644 --- a/pcbnew/router/pns_shove.h +++ b/pcbnew/router/pns_shove.h @@ -44,7 +44,7 @@ class PNS_SHOVE : public PNS_ALGO_BASE { public: - enum ShoveStatus + enum SHOVE_STATUS { SH_OK = 0, SH_NULL, @@ -52,72 +52,74 @@ public: SH_HEAD_MODIFIED }; - PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER *aRouter ); + PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter ); ~PNS_SHOVE(); - virtual PNS_LOGGER *Logger() + virtual PNS_LOGGER* Logger() { return &m_logger; } - ShoveStatus ShoveLines( const PNS_LINE& aCurrentHead ); - ShoveStatus ShoveDraggingVia ( PNS_VIA *aVia, const VECTOR2I& aWhere, PNS_VIA **aNewVia ); + SHOVE_STATUS ShoveLines( const PNS_LINE& aCurrentHead ); + SHOVE_STATUS ShoveDraggingVia( PNS_VIA*aVia, const VECTOR2I& aWhere, PNS_VIA** aNewVia ); PNS_NODE* CurrentNode(); const PNS_LINE NewHead() const; - void SetInitialLine ( PNS_LINE *aInitial ); + void SetInitialLine ( PNS_LINE* aInitial ); private: - typedef std::vector HullSet; - typedef boost::optional OptLine; - typedef std::pair LinePair; - typedef std::vector LinePairVec; + typedef std::vector HULL_SET; + typedef boost::optional OPT_LINE; + typedef std::pair LINE_PAIR; + typedef std::vector LINE_PAIR_VEC; - struct SpringbackTag + struct SPRINGBACK_TAG { - int64_t length; - int segments; - VECTOR2I p; - PNS_NODE *node; - PNS_ITEMSET headItems; - PNS_COST_ESTIMATOR cost; + int64_t m_length; + int m_segments; + VECTOR2I m_p; + PNS_NODE* m_node; + PNS_ITEMSET m_headItems; + PNS_COST_ESTIMATOR m_cost; }; - ShoveStatus processSingleLine(PNS_LINE *aCurrent, PNS_LINE* aObstacle, PNS_LINE *aShoved ); - ShoveStatus processHullSet ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved, const HullSet& hulls ); + SHOVE_STATUS processSingleLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle, PNS_LINE* aShoved ); + SHOVE_STATUS processHullSet( PNS_LINE* aCurrent, PNS_LINE* aObstacle, + PNS_LINE* aShoved, const HULL_SET& hulls ); - bool reduceSpringback( const PNS_ITEMSET &aHeadItems ); - bool pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET &aHeadItems, const PNS_COST_ESTIMATOR& aCost ); + bool reduceSpringback( const PNS_ITEMSET& aHeadItems ); + bool pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET &aHeadItems, + const PNS_COST_ESTIMATOR& aCost ); - ShoveStatus walkaroundLoneVia ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved ); - bool checkBumpDirection ( PNS_LINE *aCurrent, PNS_LINE *aShoved ) const; + SHOVE_STATUS walkaroundLoneVia( PNS_LINE* aCurrent, PNS_LINE* aObstacle, PNS_LINE* aShoved ); + bool checkBumpDirection( PNS_LINE* aCurrent, PNS_LINE* aShoved ) const; - ShoveStatus onCollidingLine( PNS_LINE *aCurrent, PNS_LINE *aObstacle ); - ShoveStatus onCollidingSegment( PNS_LINE *aCurrent, PNS_SEGMENT *aObstacleSeg ); - ShoveStatus onCollidingSolid( PNS_LINE *aCurrent, PNS_SOLID *aObstacleSolid ); - ShoveStatus onCollidingVia( PNS_ITEM *aCurrent, PNS_VIA *aObstacleVia ); - ShoveStatus onReverseCollidingVia( PNS_LINE *aCurrent, PNS_VIA *aObstacleVia ); - ShoveStatus pushVia ( PNS_VIA *aVia, const VECTOR2I& aForce, int aCurrentRank ); + SHOVE_STATUS onCollidingLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle ); + SHOVE_STATUS onCollidingSegment( PNS_LINE* aCurrent, PNS_SEGMENT* aObstacleSeg ); + SHOVE_STATUS onCollidingSolid( PNS_LINE* aCurrent, PNS_SOLID* aObstacleSolid ); + SHOVE_STATUS onCollidingVia( PNS_ITEM* aCurrent, PNS_VIA* aObstacleVia ); + SHOVE_STATUS onReverseCollidingVia( PNS_LINE* aCurrent, PNS_VIA* aObstacleVia ); + SHOVE_STATUS pushVia( PNS_VIA* aVia, const VECTOR2I& aForce, int aCurrentRank ); - void unwindStack ( PNS_SEGMENT *seg ); - void unwindStack ( PNS_ITEM *item ); + void unwindStack( PNS_SEGMENT* aSeg ); + void unwindStack( PNS_ITEM *aItem ); - void runOptimizer ( PNS_NODE *node, PNS_LINE *head ); + void runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead ); - void pushLine ( PNS_LINE *l ); + void pushLine( PNS_LINE *aL ); void popLine(); - const RANGE findShovedVertexRange ( PNS_LINE *l ); + const RANGE findShovedVertexRange( PNS_LINE *aL ); - PNS_LINE *assembleLine ( const PNS_SEGMENT *aSeg, int *aIndex = NULL ); - PNS_LINE *cloneLine ( const PNS_LINE *aLine ); + PNS_LINE* assembleLine( const PNS_SEGMENT* aSeg, int* aIndex = NULL ); + PNS_LINE* cloneLine( const PNS_LINE* aLine ); - ShoveStatus shoveIteration(int aIter); - ShoveStatus shoveMainLoop(); + SHOVE_STATUS shoveIteration( int aIter ); + SHOVE_STATUS shoveMainLoop(); - std::vector m_nodeStack; + std::vector m_nodeStack; std::vector m_lineStack; std::vector m_optimizerQueue; std::vector m_gcItems; @@ -127,7 +129,7 @@ private: PNS_LINE* m_currentHead; PNS_LINE* m_collidingLine; - OptLine m_newHead; + OPT_LINE m_newHead; PNS_LOGGER m_logger; PNS_VIA* m_draggedVia; diff --git a/pcbnew/router/pns_solid.cpp b/pcbnew/router/pns_solid.cpp index da4fab064d..6305ceabc4 100644 --- a/pcbnew/router/pns_solid.cpp +++ b/pcbnew/router/pns_solid.cpp @@ -30,29 +30,29 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness ) const { - int cl = aClearance + aWalkaroundThickness / 2; + int cl = aClearance + aWalkaroundThickness / 2; switch( m_shape->Type() ) { case SH_RECT: - { - SHAPE_RECT* rect = static_cast( m_shape ); - return OctagonalHull( rect->GetPosition(), rect->GetSize(), - cl + 1, 0.2 * cl ); - } + { + SHAPE_RECT* rect = static_cast( m_shape ); + return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl ); + } case SH_CIRCLE: - { - SHAPE_CIRCLE* circle = static_cast( m_shape ); - int r = circle->GetRadius(); - return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ), - cl + 1, 0.52 * (r + cl) ); - } + { + SHAPE_CIRCLE* circle = static_cast( m_shape ); + int r = circle->GetRadius(); + return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ), + cl + 1, 0.52 * ( r + cl ) ); + } + case SH_SEGMENT: - { - SHAPE_SEGMENT *seg = static_cast ( m_shape ); - return SegmentHull (*seg, aClearance, aWalkaroundThickness ); - } + { + SHAPE_SEGMENT* seg = static_cast ( m_shape ); + return SegmentHull( *seg, aClearance, aWalkaroundThickness ); + } default: break; @@ -64,6 +64,6 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness PNS_ITEM* PNS_SOLID::Clone ( ) const { - PNS_ITEM *solid = new PNS_SOLID ( *this ); + PNS_ITEM* solid = new PNS_SOLID( *this ); return solid; } diff --git a/pcbnew/router/pns_solid.h b/pcbnew/router/pns_solid.h index d1e725a461..88f8431d24 100644 --- a/pcbnew/router/pns_solid.h +++ b/pcbnew/router/pns_solid.h @@ -49,7 +49,7 @@ public: m_pos = aSolid.m_pos; } - PNS_ITEM* Clone( ) const; + PNS_ITEM* Clone() const; const SHAPE* Shape() const { return m_shape; } @@ -73,7 +73,7 @@ public: m_pos = aCenter; } - virtual VECTOR2I Anchor(int n) const + virtual VECTOR2I Anchor( int aN ) const { return m_pos; } @@ -83,7 +83,6 @@ public: return 1; } - private: VECTOR2I m_pos; SHAPE* m_shape; diff --git a/pcbnew/router/pns_utils.cpp b/pcbnew/router/pns_utils.cpp index e1042e6437..5a69e673d8 100644 --- a/pcbnew/router/pns_utils.cpp +++ b/pcbnew/router/pns_utils.cpp @@ -24,10 +24,8 @@ #include -const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, - const VECTOR2I& aSize, - int aClearance, - int aChamfer ) +const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize, + int aClearance, int aChamfer ) { SHAPE_LINE_CHAIN s; @@ -45,9 +43,9 @@ const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, return s; } -const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, - int aClearance, - int aWalkaroundThickness ) + +const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance, + int aWalkaroundThickness ) { int d = aSeg.GetWidth() / 2 + aClearance + aWalkaroundThickness / 2 + HULL_MARGIN; int x = (int)( 2.0 / ( 1.0 + M_SQRT2 ) * d ); @@ -81,14 +79,15 @@ const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, return s; } + SHAPE_RECT ApproximateSegmentAsRect( const SHAPE_SEGMENT& aSeg ) { SHAPE_RECT r; - VECTOR2I delta ( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 ); - VECTOR2I p0 ( aSeg.GetSeg().A - delta ); - VECTOR2I p1 ( aSeg.GetSeg().B + delta ); + VECTOR2I delta( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 ); + VECTOR2I p0( aSeg.GetSeg().A - delta ); + VECTOR2I p1( aSeg.GetSeg().B + delta ); - return SHAPE_RECT ( std::min(p0.x, p1.x), std::min(p0.y, p1.y), - std::abs(p1.x - p0.x), std::abs(p1.y - p0.y )); -} \ No newline at end of file + return SHAPE_RECT( std::min( p0.x, p1.x ), std::min( p0.y, p1.y ), + std::abs( p1.x - p0.x ), std::abs( p1.y - p0.y ) ); +} diff --git a/pcbnew/router/pns_utils.h b/pcbnew/router/pns_utils.h index 50bfc90179..5bf6d9313b 100644 --- a/pcbnew/router/pns_utils.h +++ b/pcbnew/router/pns_utils.h @@ -31,11 +31,10 @@ /** Various utility functions */ const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize, - int aClearance, int aChamfer ); + int aClearance, int aChamfer ); -const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, - int aClearance, - int aWalkaroundThickness ); +const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance, + int aWalkaroundThickness ); SHAPE_RECT ApproximateSegmentAsRect( const SHAPE_SEGMENT& aSeg ); diff --git a/pcbnew/router/pns_via.cpp b/pcbnew/router/pns_via.cpp index 037bb16e99..f7ff5e9461 100644 --- a/pcbnew/router/pns_via.cpp +++ b/pcbnew/router/pns_via.cpp @@ -25,26 +25,22 @@ #include -bool PNS_VIA::PushoutForce( PNS_NODE* aNode, - const VECTOR2I& aDirection, - VECTOR2I& aForce, - bool aSolidsOnly, - int aMaxIterations ) +bool PNS_VIA::PushoutForce( PNS_NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForce, + bool aSolidsOnly, int aMaxIterations ) { int iter = 0; PNS_VIA mv( *this ); VECTOR2I force, totalForce, force2; - while( iter < aMaxIterations ) { - - PNS_NODE::OptObstacle obs = aNode->CheckColliding( &mv, aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY ); + PNS_NODE::OPT_OBSTACLE obs = aNode->CheckColliding( &mv, + aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY ); if( !obs ) break; - int clearance = aNode->GetClearance( obs->item, &mv ); + int clearance = aNode->GetClearance( obs->m_item, &mv ); if( iter > aMaxIterations / 2 ) { @@ -53,14 +49,13 @@ bool PNS_VIA::PushoutForce( PNS_NODE* aNode, mv.SetPos( mv.Pos() + l ); } - bool col = CollideShapes( obs->item->Shape(), mv.Shape(), clearance, true, force2 ); + bool col = CollideShapes( obs->m_item->Shape(), mv.Shape(), clearance, true, force2 ); - if(col) { + if( col ) { totalForce += force2; mv.SetPos( mv.Pos() + force2 ); } - iter++; } @@ -68,19 +63,21 @@ bool PNS_VIA::PushoutForce( PNS_NODE* aNode, return false; aForce = totalForce; + return true; } const SHAPE_LINE_CHAIN PNS_VIA::Hull( int aClearance, int aWalkaroundThickness ) const { - int cl = (aClearance + aWalkaroundThickness / 2); + int cl = ( aClearance + aWalkaroundThickness / 2 ); return OctagonalHull( m_pos - - VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter, - m_diameter ), cl + 1, (2 * cl + m_diameter) * 0.26 ); + VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter, m_diameter ), + cl + 1, ( 2 * cl + m_diameter ) * 0.26 ); } + PNS_VIA* PNS_VIA::Clone ( ) const { PNS_VIA* v = new PNS_VIA(); diff --git a/pcbnew/router/pns_via.h b/pcbnew/router/pns_via.h index 684116b6da..00a4587b74 100644 --- a/pcbnew/router/pns_via.h +++ b/pcbnew/router/pns_via.h @@ -32,7 +32,8 @@ class PNS_VIA : public PNS_ITEM { public: PNS_VIA() : - PNS_ITEM( VIA ) {}; + PNS_ITEM( VIA ) + {} PNS_VIA( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aDiameter, int aNet = -1 ) : PNS_ITEM( VIA ) @@ -42,21 +43,21 @@ public: m_pos = aPos; m_diameter = aDiameter; m_shape = SHAPE_CIRCLE( aPos, aDiameter / 2 ); - }; + } - PNS_VIA( const PNS_VIA& b ) : + PNS_VIA( const PNS_VIA& aB ) : PNS_ITEM( VIA ) { - SetNet( b.Net() ); - SetLayers( b.Layers() ); - m_pos = b.m_pos; - m_diameter = b.m_diameter; + SetNet( aB.Net() ); + SetLayers( aB.Layers() ); + m_pos = aB.m_pos; + m_diameter = aB.m_diameter; m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 ); - m_marker = b.m_marker; - m_rank = b.m_rank; - m_owner = b.m_owner; - m_drill = b.m_drill; + m_marker = aB.m_marker; + m_rank = aB.m_rank; + m_owner = aB.m_owner; + m_drill = aB.m_drill; } const VECTOR2I& Pos() const @@ -106,7 +107,7 @@ public: const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const; - virtual VECTOR2I Anchor(int n) const + virtual VECTOR2I Anchor( int n ) const { return m_pos; } @@ -117,7 +118,6 @@ public: } private: - int m_diameter; int m_drill; VECTOR2I m_pos; diff --git a/pcbnew/router/pns_walkaround.cpp b/pcbnew/router/pns_walkaround.cpp index 5be937e489..071f762a32 100644 --- a/pcbnew/router/pns_walkaround.cpp +++ b/pcbnew/router/pns_walkaround.cpp @@ -32,22 +32,22 @@ using boost::optional; void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath ) { m_iteration = 0; - m_iteration_limit = 50; + m_iterationLimit = 50; } -PNS_NODE::OptObstacle PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath ) +PNS_NODE::OPT_OBSTACLE PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath ) { - return m_world->NearestObstacle( &aPath, m_item_mask); - + return m_world->NearestObstacle( &aPath, m_itemMask ); } -PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath, - bool aWindingDirection ) +PNS_WALKAROUND::WALKAROUND_STATUS PNS_WALKAROUND::singleStep( PNS_LINE& aPath, + bool aWindingDirection ) { optional& current_obs = aWindingDirection ? m_currentObstacle[0] : m_currentObstacle[1]; + bool& prev_recursive = aWindingDirection ? m_recursiveCollision[0] : m_recursiveCollision[1]; if( !current_obs ) @@ -55,15 +55,14 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath, SHAPE_LINE_CHAIN path_pre[2], path_walk[2], path_post[2]; - VECTOR2I last = aPath.CPoint( -1 );; + VECTOR2I last = aPath.CPoint( -1 ); - - if( ( current_obs->hull ).PointInside( last ) ) + if( ( current_obs->m_hull ).PointInside( last ) ) { m_recursiveBlockageCount++; if( m_recursiveBlockageCount < 3 ) - aPath.Line().Append( current_obs->hull.NearestPoint( last ) ); + aPath.Line().Append( current_obs->m_hull.NearestPoint( last ) ); else { aPath = aPath.ClipToNearestObstacle( m_world ); @@ -71,17 +70,18 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath, } } - aPath.Walkaround( current_obs->hull, path_pre[0], path_walk[0], - path_post[0], aWindingDirection ); - aPath.Walkaround( current_obs->hull, path_pre[1], path_walk[1], - path_post[1], !aWindingDirection ); + aPath.Walkaround( current_obs->m_hull, path_pre[0], path_walk[0], + path_post[0], aWindingDirection ); + aPath.Walkaround( current_obs->m_hull, path_pre[1], path_walk[1], + path_post[1], !aWindingDirection ); + #ifdef DEBUG - m_logger.NewGroup (aWindingDirection ? "walk-cw" : "walk-ccw", m_iteration); - m_logger.Log ( &path_walk[0], 0, "path-walk"); - m_logger.Log ( &path_pre[0], 1, "path-pre"); - m_logger.Log ( &path_post[0], 4, "path-post"); - m_logger.Log ( ¤t_obs->hull, 2, "hull"); - m_logger.Log ( current_obs->item, 3, "item"); + m_logger.NewGroup( aWindingDirection ? "walk-cw" : "walk-ccw", m_iteration ); + m_logger.Log( &path_walk[0], 0, "path-walk" ); + m_logger.Log( &path_pre[0], 1, "path-pre" ); + m_logger.Log( &path_post[0], 4, "path-post" ); + m_logger.Log( ¤t_obs->m_hull, 2, "hull" ); + m_logger.Log( current_obs->m_item, 3, "item" ); #endif int len_pre = path_walk[0].Length(); @@ -89,8 +89,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath, PNS_LINE walk_path( aPath, path_walk[1] ); - bool alt_collides = m_world->CheckColliding( &walk_path, m_item_mask ); - + bool alt_collides = m_world->CheckColliding( &walk_path, m_itemMask ); SHAPE_LINE_CHAIN pnew; @@ -127,15 +126,13 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath, } -PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitialPath, - PNS_LINE& aWalkPath, - bool aOptimize ) +PNS_WALKAROUND::WALKAROUND_STATUS PNS_WALKAROUND::Route( const PNS_LINE& aInitialPath, + PNS_LINE& aWalkPath, bool aOptimize ) { PNS_LINE path_cw( aInitialPath ), path_ccw( aInitialPath ); - WalkaroundStatus s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS; + WALKAROUND_STATUS s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS; SHAPE_LINE_CHAIN best_path; - start( aInitialPath ); m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle( aInitialPath ); @@ -143,7 +140,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial aWalkPath = aInitialPath; - while( m_iteration < m_iteration_limit ) + while( m_iteration < m_iterationLimit ) { if( s_cw != STUCK ) s_cw = singleStep( path_cw, true ); @@ -155,7 +152,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial { int len_cw = path_cw.CLine().Length(); int len_ccw = path_ccw.CLine().Length(); - if( m_forceLongerPath ) aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw); @@ -178,16 +174,15 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial m_iteration++; } - if( m_iteration == m_iteration_limit ) + if( m_iteration == m_iterationLimit ) { int len_cw = path_cw.CLine().Length(); int len_ccw = path_ccw.CLine().Length(); - if( m_forceLongerPath ) - aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw); + aWalkPath = ( len_cw > len_ccw ? path_cw : path_ccw ); else - aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw); + aWalkPath = ( len_cw < len_ccw ? path_cw : path_ccw ); } if( m_cursorApproachMode ) @@ -226,16 +221,16 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial aWalkPath.Line().Simplify(); - if(aWalkPath.SegmentCount() < 1) + if( aWalkPath.SegmentCount() < 1 ) return STUCK; - if(aWalkPath.CPoint(-1) != aInitialPath.CPoint(-1)) + if( aWalkPath.CPoint( -1 ) != aInitialPath.CPoint( -1 ) ) return STUCK; - if(aWalkPath.CPoint(0) != aInitialPath.CPoint(0)) + if( aWalkPath.CPoint( 0 ) != aInitialPath.CPoint( 0 ) ) return STUCK; - WalkaroundStatus st = s_ccw == DONE || s_cw == DONE ? DONE : STUCK; + WALKAROUND_STATUS st = s_ccw == DONE || s_cw == DONE ? DONE : STUCK; if( aOptimize && st == DONE ) PNS_OPTIMIZER::Optimize( &aWalkPath, PNS_OPTIMIZER::MERGE_OBTUSE, m_world ); diff --git a/pcbnew/router/pns_walkaround.h b/pcbnew/router/pns_walkaround.h index 0a87213a22..71b9c1ce2d 100644 --- a/pcbnew/router/pns_walkaround.h +++ b/pcbnew/router/pns_walkaround.h @@ -32,20 +32,20 @@ class PNS_WALKAROUND : public PNS_ALGO_BASE static const int DefaultIterationLimit = 50; public: - PNS_WALKAROUND( PNS_NODE* aWorld, PNS_ROUTER *aRouter ) : + PNS_WALKAROUND( PNS_NODE* aWorld, PNS_ROUTER* aRouter ) : PNS_ALGO_BASE ( aRouter ), m_world( aWorld ), - m_iteration_limit( DefaultIterationLimit ) + m_iterationLimit( DefaultIterationLimit ) { m_forceSingleDirection = false; m_forceLongerPath = false; m_cursorApproachMode = false; - m_item_mask = PNS_ITEM::ANY; - }; + m_itemMask = PNS_ITEM::ANY; + } ~PNS_WALKAROUND() {}; - enum WalkaroundStatus + enum WALKAROUND_STATUS { IN_PROGRESS = 0, DONE, @@ -59,23 +59,23 @@ public: void SetIterationLimit( const int aIterLimit ) { - m_iteration_limit = aIterLimit; + m_iterationLimit = aIterLimit; } void SetSolidsOnly( bool aSolidsOnly ) { - if(aSolidsOnly) - m_item_mask = PNS_ITEM::SOLID; + if( aSolidsOnly ) + m_itemMask = PNS_ITEM::SOLID; else - m_item_mask = PNS_ITEM::ANY; + m_itemMask = PNS_ITEM::ANY; } - void SetItemMask ( int aMask ) + void SetItemMask( int aMask ) { - m_item_mask = aMask; + m_itemMask = aMask; } - void SetSingleDirection( bool aForceSingleDirection ) + void SetSingleDirection( bool aForceSingleDirection ) { m_forceSingleDirection = aForceSingleDirection; m_forceLongerPath = aForceSingleDirection; @@ -88,29 +88,30 @@ public: m_cursorApproachMode = aEnabled; } - WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, + WALKAROUND_STATUS Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, bool aOptimize = true ); - virtual PNS_LOGGER *Logger() { + virtual PNS_LOGGER* Logger() + { return &m_logger; } private: void start( const PNS_LINE& aInitialPath ); - WalkaroundStatus singleStep( PNS_LINE& aPath, bool aWindingDirection ); - PNS_NODE::OptObstacle nearestObstacle( const PNS_LINE& aPath ); + WALKAROUND_STATUS singleStep( PNS_LINE& aPath, bool aWindingDirection ); + PNS_NODE::OPT_OBSTACLE nearestObstacle( const PNS_LINE& aPath ); PNS_NODE* m_world; int m_recursiveBlockageCount; int m_iteration; - int m_iteration_limit; - int m_item_mask; + int m_iterationLimit; + int m_itemMask; bool m_forceSingleDirection, m_forceLongerPath; bool m_cursorApproachMode; VECTOR2I m_cursorPos; - PNS_NODE::OptObstacle m_currentObstacle[2]; + PNS_NODE::OPT_OBSTACLE m_currentObstacle[2]; bool m_recursiveCollision[2]; PNS_LOGGER m_logger; }; diff --git a/pcbnew/router/range.h b/pcbnew/router/range.h index 8409731926..0778cf70e7 100644 --- a/pcbnew/router/range.h +++ b/pcbnew/router/range.h @@ -21,16 +21,17 @@ #ifndef __RANGE_H #define __RANGE_H -template class RANGE { - +template +class RANGE +{ public: - RANGE (T aMin, T aMax) : - m_min(aMin), - m_max(aMax), - m_defined(true) {} + RANGE( T aMin, T aMax ) : + m_min( aMin ), + m_max( aMax ), + m_defined( true ) {} - RANGE (): - m_defined (false) {}; + RANGE(): + m_defined( false ) {} T MinV() const { @@ -42,36 +43,38 @@ template class RANGE { return m_max; } - void Set ( T aMin, T aMax ) const + void Set( T aMin, T aMax ) const { m_max = aMax; m_min = aMin; } - void Grow ( T value ) + void Grow( T aValue ) { - if(!m_defined) + if( !m_defined ) { - m_min = value; - m_max = value; + m_min = aValue; + m_max = aValue; m_defined = true; - } else { - m_min = std::min(m_min, value); - m_max = std::max(m_max, value); + } + else + { + m_min = std::min( m_min, aValue ); + m_max = std::max( m_max, aValue ); } } - bool Inside ( const T& value ) const + bool Inside( const T& aValue ) const { - if(!m_defined) + if( !m_defined ) return true; - return value >= m_min && value <= m_max; + return aValue >= m_min && aValue <= m_max; } - bool Overlaps ( const RANGE &aOther ) const + bool Overlaps ( const RANGE& aOther ) const { - if(!m_defined || !aOther.m_defined) + if( !m_defined || !aOther.m_defined ) return true; return m_max >= aOther.m_min && m_min <= aOther.m_max; @@ -85,7 +88,6 @@ template class RANGE { private: T m_min, m_max; bool m_defined; - }; -#endif \ No newline at end of file +#endif diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp index 3287082c3c..85a7062b5a 100644 --- a/pcbnew/router/router_preview_item.cpp +++ b/pcbnew/router/router_preview_item.cpp @@ -43,7 +43,6 @@ ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem, VIEW_GROUP* aPa m_clearance = -1; m_originLayer = m_layer = ITEM_GAL_LAYER ( GP_OVERLAY ); - if( aItem ) Update( aItem ); } @@ -56,60 +55,59 @@ ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM() void ROUTER_PREVIEW_ITEM::Update( const PNS_ITEM* aItem ) { - m_originLayer = aItem->Layers().Start(); - assert (m_originLayer >= 0); + assert( m_originLayer >= 0 ); m_layer = m_originLayer; m_color = getLayerColor( m_originLayer ); m_color.a = 0.8; m_depth = BaseOverlayDepth - aItem->Layers().Start(); - m_shape = aItem->Shape()->Clone(); switch( aItem->Kind() ) { - case PNS_ITEM::LINE: - m_type = PR_SHAPE; - m_width = ((PNS_LINE *) aItem)->Width(); - - break; + case PNS_ITEM::LINE: + m_type = PR_SHAPE; + m_width = ( (PNS_LINE*) aItem )->Width(); - case PNS_ITEM::SEGMENT: - { - PNS_SEGMENT *seg = (PNS_SEGMENT *)aItem; - m_type = PR_SHAPE; - m_width = seg->Width(); - break; - } + break; - case PNS_ITEM::VIA: - m_type = PR_SHAPE; - m_width = 0; - m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 ); - m_depth = ViaOverlayDepth; - break; - - case PNS_ITEM::SOLID: - m_type = PR_SHAPE; - m_width = 0; - break; + case PNS_ITEM::SEGMENT: + { + PNS_SEGMENT* seg = (PNS_SEGMENT*) aItem; + m_type = PR_SHAPE; + m_width = seg->Width(); + break; + } + + case PNS_ITEM::VIA: + m_type = PR_SHAPE; + m_width = 0; + m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 ); + m_depth = ViaOverlayDepth; + break; + + case PNS_ITEM::SOLID: + m_type = PR_SHAPE; + m_width = 0; + break; default: break; } - if(aItem->Marker() & MK_VIOLATION) - m_color = COLOR4D (0, 1, 0, 1); + if( aItem->Marker() & MK_VIOLATION ) + m_color = COLOR4D( 0, 1, 0, 1 ); - if(aItem->Marker() & MK_HEAD) - m_color.Brighten(0.7); + if( aItem->Marker() & MK_HEAD ) + m_color.Brighten( 0.7 ); ViewSetVisible( true ); ViewUpdate( GEOMETRY | APPEARANCE ); } + const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const { BOX2I bbox; @@ -122,7 +120,7 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const return bbox; case PR_POINT: - bbox = BOX2I ( m_pos - VECTOR2I(100000, 100000), VECTOR2I( 200000, 200000 )); + bbox = BOX2I ( m_pos - VECTOR2I( 100000, 100000 ), VECTOR2I( 200000, 200000 ) ); return bbox; default: @@ -132,20 +130,23 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const return bbox; } -void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN &l, KIGFX::GAL* aGal ) const + +void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN &aL, KIGFX::GAL* aGal ) const { - for( int s = 0; s < l.SegmentCount(); s++ ) - aGal->DrawLine( l.CSegment( s ).A, l.CSegment( s ).B ); - if( l.IsClosed() ) - aGal->DrawLine( l.CSegment( -1 ).B, l.CSegment( 0 ).A ); + for( int s = 0; s < aL.SegmentCount(); s++ ) + aGal->DrawLine( aL.CSegment( s ).A, aL.CSegment( s ).B ); + + if( aL.IsClosed() ) + aGal->DrawLine( aL.CSegment( -1 ).B, aL.CSegment( 0 ).A ); } + void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const { //col.Brighten(0.7); aGal->SetLayerDepth( m_depth ); - if(m_type == PR_SHAPE) + if( m_type == PR_SHAPE ) { aGal->SetLineWidth( m_width ); aGal->SetStrokeColor( m_color ); @@ -153,31 +154,29 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const aGal->SetIsStroke( m_width ? true : false ); aGal->SetIsFill( true ); - - if(!m_shape) + if( !m_shape ) return; switch( m_shape->Type() ) { case SH_LINE_CHAIN: { - const SHAPE_LINE_CHAIN *l = (const SHAPE_LINE_CHAIN *) m_shape; - drawLineChain(*l, aGal); + const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) m_shape; + drawLineChain( *l, aGal ); break; } case SH_SEGMENT: { - const SHAPE_SEGMENT *s = (const SHAPE_SEGMENT *) m_shape; + const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) m_shape; aGal->DrawLine( s->GetSeg().A, s->GetSeg().B ); - if(m_clearance > 0) + if( m_clearance > 0 ) { - aGal->SetLayerDepth ( ClearanceOverlayDepth ); - aGal->SetStrokeColor ( COLOR4D( DARKDARKGRAY )); + aGal->SetLayerDepth( ClearanceOverlayDepth ); + aGal->SetStrokeColor( COLOR4D( DARKDARKGRAY )); aGal->SetLineWidth( m_width + 2 * m_clearance ); aGal->DrawLine( s->GetSeg().A, s->GetSeg().B ); - } break; @@ -185,13 +184,13 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const case SH_CIRCLE: { - const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE *) m_shape; + const SHAPE_CIRCLE* c = (const SHAPE_CIRCLE*) m_shape; aGal->DrawCircle( c->GetCenter(), c->GetRadius() ); - if(m_clearance > 0) + if( m_clearance > 0 ) { - aGal->SetLayerDepth ( ClearanceOverlayDepth ); - aGal->SetFillColor ( COLOR4D( DARKDARKGRAY )); + aGal->SetLayerDepth( ClearanceOverlayDepth ); + aGal->SetFillColor( COLOR4D( DARKDARKGRAY ) ); aGal->SetIsStroke( false ); aGal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance ); } @@ -201,20 +200,20 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const case SH_RECT: { - const SHAPE_RECT *r = (const SHAPE_RECT *) m_shape; - aGal->DrawRectangle (r->GetPosition(), r->GetPosition() + r->GetSize()); + const SHAPE_RECT* r = (const SHAPE_RECT*) m_shape; + aGal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() ); - if(m_clearance > 0) + if( m_clearance > 0 ) { - aGal->SetLayerDepth ( ClearanceOverlayDepth ); - VECTOR2I p0 (r -> GetPosition() ), s ( r->GetSize() ); - aGal->SetStrokeColor ( COLOR4D( DARKDARKGRAY )); + aGal->SetLayerDepth( ClearanceOverlayDepth ); + VECTOR2I p0( r->GetPosition() ), s( r->GetSize() ); + aGal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) ); aGal->SetIsStroke( true ); - aGal->SetLineWidth ( 2 * m_clearance ); - aGal->DrawLine( p0, VECTOR2I(p0.x + s.x, p0.y) ); - aGal->DrawLine( p0, VECTOR2I(p0.x, p0.y + s.y) ); - aGal->DrawLine( p0 + s , VECTOR2I(p0.x + s.x, p0.y) ); - aGal->DrawLine( p0 + s, VECTOR2I(p0.x, p0.y + s.y) ); + aGal->SetLineWidth( 2 * m_clearance ); + aGal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) ); + aGal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) ); + aGal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) ); + aGal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) ); } break; @@ -224,9 +223,8 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const } -void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle ) +void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle ) { - m_originLayer = m_layer = 0; m_width = aWidth; m_color = assignColor( aStyle ); @@ -234,15 +232,16 @@ void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int a m_depth = -2047; m_shape = aLine.Clone(); - ViewSetVisible(true); + ViewSetVisible( true ); ViewUpdate( GEOMETRY | APPEARANCE ); - } -void ROUTER_PREVIEW_ITEM::Point( const VECTOR2I& aPos, int aStyle ) + +void ROUTER_PREVIEW_ITEM::Point( const VECTOR2I& aPos, int aStyle ) { } + void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle ) { } @@ -251,7 +250,7 @@ void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle ) const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const { PCB_RENDER_SETTINGS* settings = - static_cast ( m_parent->GetView()->GetPainter()->GetSettings() ); + static_cast( m_parent->GetView()->GetPainter()->GetSettings() ); return settings->GetLayerColor( aLayer ); } diff --git a/pcbnew/router/router_preview_item.h b/pcbnew/router/router_preview_item.h index 514b21dcea..c22e21c5e6 100644 --- a/pcbnew/router/router_preview_item.h +++ b/pcbnew/router/router_preview_item.h @@ -44,13 +44,12 @@ class PNS_ROUTER; class ROUTER_PREVIEW_ITEM : public EDA_ITEM { public: - enum ItemType + enum ITEM_TYPE { PR_STUCK_MARKER = 0, PR_POINT, PR_SHAPE }; - ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem = NULL, KIGFX::VIEW_GROUP* aParent = NULL ); ~ROUTER_PREVIEW_ITEM(); @@ -68,12 +67,12 @@ public: m_color = aColor; } - void SetClearance ( int aClearance ) + void SetClearance( int aClearance ) { m_clearance = aClearance; } - void Show( int a, std::ostream& b ) const {}; + void Show( int aA, std::ostream& aB ) const {}; const BOX2I ViewBBox() const; @@ -85,7 +84,7 @@ public: aCount = 1; } - void drawLineChain( const SHAPE_LINE_CHAIN &l, KIGFX::GAL *aGal ) const; + void drawLineChain( const SHAPE_LINE_CHAIN& aL, KIGFX::GAL *aGal ) const; private: const KIGFX::COLOR4D assignColor( int aStyle ) const; @@ -94,9 +93,9 @@ private: KIGFX::VIEW_GROUP* m_parent; PNS_ROUTER* m_router; - SHAPE *m_shape; + SHAPE* m_shape; - ItemType m_type; + ITEM_TYPE m_type; int m_style; int m_width; diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index e0f4a2068a..eace67a44f 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -82,35 +82,35 @@ ROUTER_TOOL::ROUTER_TOOL() : m_router = NULL; } + class CONTEXT_TRACK_WIDTH_MENU: public CONTEXT_MENU { public: CONTEXT_TRACK_WIDTH_MENU() { - setCustomEventHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::handleCustomEvent, this, _1 ) ); + setCustomEventHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::handleCustomEvent, + this, _1 ) ); } void SetBoard( BOARD* aBoard ) { - BOARD_DESIGN_SETTINGS &bds = aBoard->GetDesignSettings(); + BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings(); wxString msg; m_board = aBoard; - Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Custom size" ), wxEmptyString, wxITEM_CHECK ); + Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Custom size" ), + wxEmptyString, wxITEM_CHECK ); Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use the starting track width" ), - _( "Route using the width of the starting track." ), - wxITEM_CHECK ); + _( "Route using the width of the starting track." ), wxITEM_CHECK ); - Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, - _( "Use netclass values" ), - _( "Use track and via sizes from the net class" ), - wxITEM_CHECK ); + Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use netclass values" ), + _( "Use track and via sizes from the net class" ), wxITEM_CHECK ); for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ ) { - msg = _ ("Track "); + msg = _( "Track "); msg << StringFromValue( g_UserUnit, bds.m_TrackWidthList[i], true ); if( i == 0 ) @@ -123,17 +123,18 @@ public: for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ ) { - msg = _ ("Via "); - msg << StringFromValue( g_UserUnit, bds.m_ViasDimensionsList[i].m_Diameter, - true ); + msg = _("Via "); + msg << StringFromValue( g_UserUnit, bds.m_ViasDimensionsList[i].m_Diameter, true ); wxString drill = StringFromValue( g_UserUnit, - bds.m_ViasDimensionsList[i].m_Drill, - true ); + bds.m_ViasDimensionsList[i].m_Drill, + true ); if( bds.m_ViasDimensionsList[i].m_Drill <= 0 ) { msg << _ (", drill: default"); - } else { + } + else + { msg << _ (", drill: ") << drill; } @@ -148,7 +149,7 @@ protected: OPT_TOOL_EVENT handleCustomEvent( const wxEvent& aEvent ) { #if ID_POPUP_PCB_SELECT_VIASIZE1 < ID_POPUP_PCB_SELECT_WIDTH1 -#error You have changed event ids, it breaks a piece of code. Lookup this line for more details. +#error You have changed event ids order, it breaks code. Check the source code for more details. // Recognising type of event (track width/via size) is based on comparison if the event id is // within a specific range. If ranges of event ids changes, then the following is not valid anymore. #endif @@ -156,7 +157,7 @@ protected: int id = aEvent.GetId(); - // General settings, to be modified below + // Initial settings, to be modified below bds.m_UseConnectedTrackWidth = false; bds.UseCustomTrackViaSize( false ); @@ -198,13 +199,10 @@ protected: }; -class CONTEXT_GRID_MENU: public CONTEXT_MENU { }; - - -class ROUTER_TOOL_MENU: public CONTEXT_MENU { - +class ROUTER_TOOL_MENU: public CONTEXT_MENU +{ public: - ROUTER_TOOL_MENU( BOARD *aBoard ) + ROUTER_TOOL_MENU( BOARD* aBoard ) { SetTitle( wxT( "Interactive Router" ) ); Add( ACT_NewTrack ); @@ -227,6 +225,7 @@ public: } }; + ROUTER_TOOL::~ROUTER_TOOL() { delete m_router; @@ -259,12 +258,13 @@ int ROUTER_TOOL::getDefaultWidth( int aNetCode ) int w, d1, d2; getNetclassDimensions( aNetCode, w, d1, d2 ); + return w; } void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth, - int& aViaDiameter, int& aViaDrill ) +int& aViaDiameter, int& aViaDrill ) { BOARD* board = getModel( PCB_T ); BOARD_DESIGN_SETTINGS &bds = board->GetDesignSettings(); @@ -316,29 +316,29 @@ PNS_ITEM* ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa { if( !prioritized[2] ) prioritized[2] = item; - if( item->Layers().Overlaps( tl )) + if( item->Layers().Overlaps( tl ) ) prioritized[0] = item; } else { - if( !prioritized[3] ) + if( !prioritized[3] ) prioritized[3] = item; - if (item->Layers().Overlaps( tl )) + if( item->Layers().Overlaps( tl ) ) prioritized[1] = item; } } } - PNS_ITEM *rv = NULL; - for(int i = 0; i < 4; i++) + PNS_ITEM* rv = NULL; + for( int i = 0; i < 4; i++ ) { - PNS_ITEM *item = prioritized[i]; + PNS_ITEM* item = prioritized[i]; if( DisplayOpt.ContrastModeDisplay ) if( item && !item->Layers().Overlaps( tl ) ) item = NULL; - if(item) + if( item ) { rv = item; break; @@ -349,12 +349,12 @@ PNS_ITEM* ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa rv = NULL; if( rv ) - TRACE( 0, "%s, layer : %d, tl: %d", rv->KindStr().c_str() % rv->Layers().Start() % - tl ); + TRACE( 0, "%s, layer : %d, tl: %d", rv->KindStr().c_str() % rv->Layers().Start() % tl ); return rv; } + void ROUTER_TOOL::highlightNet( bool aEnabled, int aNetcode ) { RENDER_SETTINGS* rs = getView()->GetPainter()->GetSettings(); @@ -367,22 +367,23 @@ void ROUTER_TOOL::highlightNet( bool aEnabled, int aNetcode ) getView()->UpdateAllLayersColor(); } -void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt ) + +void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& aEvent ) { #ifdef DEBUG - if( evt.IsKeyPressed() ) - { - switch( evt.KeyCode() ) - { - case 'S': - TRACEn(2, "saving drag/route log...\n"); - m_router->DumpLog(); - break; - } + if( aEvent.IsKeyPressed() ) + { + switch( aEvent.KeyCode() ) + { + case 'S': + TRACEn( 2, "saving drag/route log...\n" ); + m_router->DumpLog(); + break; } + } else #endif - if( evt.IsAction( &ACT_RouterOptions ) ) + if( aEvent.IsAction( &ACT_RouterOptions ) ) { DIALOG_PNS_SETTINGS settingsDlg( m_toolMgr->GetEditFrame(), m_router->Settings() ); @@ -390,7 +391,7 @@ void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt ) m_router->ApplySettings(); } - else if( evt.IsAction( &ACT_CustomTrackWidth ) ) + else if( aEvent.IsAction( &ACT_CustomTrackWidth ) ) { DIALOG_TRACK_VIA_SIZE sizeDlg( m_toolMgr->GetEditFrame(), m_router->Settings() ); BOARD_DESIGN_SETTINGS& bds = getModel( PCB_T )->GetDesignSettings(); @@ -410,7 +411,7 @@ void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt ) handleCommonEvents( event ); } - else if( evt.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) ) + else if( aEvent.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) ) { BOARD_DESIGN_SETTINGS& bds = getModel( PCB_T )->GetDesignSettings(); @@ -421,6 +422,7 @@ void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt ) } } + void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent ) { VIEW_CONTROLS* ctls = getViewControls(); @@ -431,14 +433,11 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent ) if( aEvent.IsMotion() || aEvent.IsClick() ) { VECTOR2I p = aEvent.Position(); - startItem = pickSingleItem( p ); - bool snapEnabled = !aEvent.Modifier(MD_SHIFT); - m_router->EnableSnapping ( snapEnabled ); - if(!snapEnabled && startItem && !startItem->Layers().Overlaps( tl ) ) + if( !snapEnabled && startItem && !startItem->Layers().Overlaps( tl ) ) startItem = NULL; if( startItem && startItem->Net() >= 0 ) @@ -446,10 +445,13 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent ) bool dummy; VECTOR2I psnap = m_router->SnapToItem( startItem, p, dummy ); - if (snapEnabled) { + if( snapEnabled ) + { m_startSnapPoint = psnap; ctls->ForceCursorPosition( true, psnap ); - } else { + } + else + { m_startSnapPoint = cp; ctls->ForceCursorPosition( false ); } @@ -514,8 +516,7 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) } if( m_endItem ) - TRACE( 0, "%s, layer : %d", m_endItem->KindStr().c_str() % - m_endItem->Layers().Start() ); + TRACE( 0, "%s, layer : %d", m_endItem->KindStr().c_str() % m_endItem->Layers().Start() ); } @@ -573,7 +574,8 @@ void ROUTER_TOOL::performRouting() break; m_router->Move( m_endSnapPoint, m_endItem ); - } else if( evt->IsAction( &ACT_PlaceThroughVia ) ) + } + else if( evt->IsAction( &ACT_PlaceThroughVia ) ) { m_router->ToggleViaPlacement(); frame->SetTopLayer( m_router->GetCurrentLayer() ); @@ -636,7 +638,8 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) // Deselect all items m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); - getEditFrame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Interactive Router" ) ); + getEditFrame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, + _( "Interactive Router" ) ); ctls->SetSnapping( true ); ctls->ShowCursor( true ); @@ -700,7 +703,7 @@ void ROUTER_TOOL::performDragging() bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem ); - if(!dragStarted) + if( !dragStarted ) return; if( m_startItem && m_startItem->Net() >= 0 ) @@ -725,12 +728,11 @@ void ROUTER_TOOL::performDragging() } else if( evt->IsClick( BUT_LEFT ) ) { - if( m_router->FixRoute( m_endSnapPoint, m_endItem ) ) break; - } - handleCommonEvents(*evt); + + handleCommonEvents( *evt ); } if( m_router->RoutingInProgress() ) diff --git a/pcbnew/router/router_tool.h b/pcbnew/router/router_tool.h index e516222470..e2e1119fe3 100644 --- a/pcbnew/router/router_tool.h +++ b/pcbnew/router/router_tool.h @@ -49,7 +49,6 @@ public: int Main( TOOL_EVENT& aEvent ); private: - PNS_ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 ); int getDefaultWidth( int aNetCode ); @@ -57,7 +56,7 @@ private: void performRouting(); void performDragging(); - void highlightNet( bool enabled, int netcode = -1 ); + void highlightNet( bool aEnabled, int aNetcode = -1 ); void updateStartItem( TOOL_EVENT& aEvent ); void updateEndItem( TOOL_EVENT& aEvent ); @@ -78,7 +77,6 @@ private: PNS_ITEM* m_endItem; VECTOR2I m_endSnapPoint; - CONTEXT_MENU* m_menu; ///> Flag marking that the router's world needs syncing. diff --git a/pcbnew/router/time_limit.cpp b/pcbnew/router/time_limit.cpp index 0e14a10678..b4cef54869 100644 --- a/pcbnew/router/time_limit.cpp +++ b/pcbnew/router/time_limit.cpp @@ -24,23 +24,28 @@ TIME_LIMIT::TIME_LIMIT( int aMilliseconds ) : m_limitMs( aMilliseconds ) - { - Restart(); - }; +{ + Restart(); +} + + +TIME_LIMIT::~TIME_LIMIT() +{} -TIME_LIMIT::~TIME_LIMIT () {} bool TIME_LIMIT::Expired() const { return ( wxGetLocalTimeMillis().GetValue() - m_startTics ) >= m_limitMs; } + void TIME_LIMIT::Restart() { m_startTics = wxGetLocalTimeMillis().GetValue(); } -void TIME_LIMIT::Set ( int aMilliseconds ) + +void TIME_LIMIT::Set( int aMilliseconds ) { m_limitMs = aMilliseconds; } diff --git a/pcbnew/router/time_limit.h b/pcbnew/router/time_limit.h index fbb58c4156..8c7a07db5e 100644 --- a/pcbnew/router/time_limit.h +++ b/pcbnew/router/time_limit.h @@ -23,22 +23,20 @@ #include -class TIME_LIMIT { - +class TIME_LIMIT +{ public: - TIME_LIMIT( int aMilliseconds = 0); - ~TIME_LIMIT (); + TIME_LIMIT( int aMilliseconds = 0 ); + ~TIME_LIMIT(); bool Expired() const; void Restart(); - void Set ( int aMilliseconds ); + void Set( int aMilliseconds ); private: - int m_limitMs; int64_t m_startTics; }; - -#endif \ No newline at end of file +#endif diff --git a/pcbnew/router/trace.h b/pcbnew/router/trace.h index 7e6fc80980..c115b67881 100644 --- a/pcbnew/router/trace.h +++ b/pcbnew/router/trace.h @@ -25,10 +25,10 @@ #include #include -static inline void _trace_print( const char* aFuncName, int level, const std::string& aMsg ) +static inline void _trace_print( const char* aFuncName, int aLevel, const std::string& aMsg ) { #ifdef DEBUG - std::cerr << "trace[" << level << "]: " << aFuncName << ": " << aMsg << std::endl; + std::cerr << "trace[" << aLevel << "]: " << aFuncName << ": " << aMsg << std::endl; #endif } From 51ee6916ec06d382eed93f9d45d94e7ce4eb0712 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 16 May 2014 16:01:03 +0200 Subject: [PATCH 68/68] Removed header files from CMakeLists.txt. --- pcbnew/router/CMakeLists.txt | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/pcbnew/router/CMakeLists.txt b/pcbnew/router/CMakeLists.txt index 94d89b771c..411216441f 100644 --- a/pcbnew/router/CMakeLists.txt +++ b/pcbnew/router/CMakeLists.txt @@ -10,51 +10,26 @@ include_directories( ) set( PCBNEW_PNS_SRCS - direction.h - time_limit.h time_limit.cpp - trace.h - pns_algo_base.h pns_algo_base.cpp pns_dragger.cpp - pns_dragger.h - pns_index.h - pns_item.h pns_item.cpp - pns_itemset.h pns_itemset.cpp - pns_joint.h - pns_layerset.h - pns_line.h pns_line.cpp - pns_line_placer.h pns_line_placer.cpp - pns_logger.h pns_logger.cpp - pns_node.h pns_node.cpp - pns_optimizer.h pns_optimizer.cpp - pns_router.h pns_router.cpp - pns_routing_settings.h pns_routing_settings.cpp - pns_segment.h - pns_shove.h pns_shove.cpp - pns_solid.h pns_solid.cpp - pns_utils.h pns_utils.cpp - pns_via.h pns_via.cpp - pns_walkaround.h pns_walkaround.cpp router_preview_item.cpp - router_preview_item.h router_tool.cpp - router_tool.h ) add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} )