From 56059efd8ac2872cb861e77c1024d3d14d251e68 Mon Sep 17 00:00:00 2001 From: charras Date: Sat, 10 Oct 2009 17:27:53 +0000 Subject: [PATCH] Netclasses work continued Fixed problems in libedit and crashes when no component loaded --- common/about_kicad.cpp | 2 +- cvpcb/CMakeLists.txt | 1 + cvpcb/dummy_functions.cpp | 21 + eeschema/block_libedit.cpp | 36 +- eeschema/class_libentry.cpp | 13 +- .../dialog_edit_component_in_lib_base.cpp | 7 +- .../dialog_edit_component_in_lib_base.fbp | 10 +- eeschema/dialog_lib_new_component.fbp | 81 +- eeschema/dialog_lib_new_component.h | 6 + eeschema/dialog_lib_new_component_base.cpp | 19 +- eeschema/dialog_lib_new_component_base.h | 2 + eeschema/edit_component_in_lib.cpp | 73 +- eeschema/libedit.cpp | 23 +- eeschema/libeditfrm.h | 204 +-- eeschema/libframe.cpp | 12 +- eeschema/netform.cpp | 2 +- gerbview/CMakeLists.txt | 1 + gerbview/dummy_functions.cpp | 21 + include/wxPcbStruct.h | 5 +- internat/fr/kicad.mo | Bin 197393 -> 198216 bytes internat/fr/kicad.po | 1366 +++++++++-------- pcbnew/CMakeLists.txt | 1 + pcbnew/attribut.cpp | 3 +- pcbnew/class_netinfo.h | 42 +- pcbnew/class_track.cpp | 158 +- pcbnew/class_track.h | 7 + pcbnew/controle.cpp | 265 +--- pcbnew/deltrack.cpp | 2 +- pcbnew/dialog_track_options_base.cpp | 4 +- pcbnew/dialog_track_options_base.fbp | 4 +- pcbnew/edit_track_width.cpp | 92 +- pcbnew/editrack-part2.cpp | 3 +- pcbnew/magnetic_tracks_functions.cpp | 275 ++++ pcbnew/onrightclick.cpp | 10 +- pcbnew/protos.h | 29 +- pcbnew/tr_modif.cpp | 4 +- pcbnew/track.cpp | 309 ++-- 37 files changed, 1743 insertions(+), 1370 deletions(-) create mode 100644 cvpcb/dummy_functions.cpp create mode 100644 gerbview/dummy_functions.cpp create mode 100644 pcbnew/magnetic_tracks_functions.cpp diff --git a/common/about_kicad.cpp b/common/about_kicad.cpp index c9f4315605..9089110d17 100644 --- a/common/about_kicad.cpp +++ b/common/about_kicad.cpp @@ -8,7 +8,7 @@ #include "appl_wxstruct.h" -#define BUILD_VERSION "(20091001-unstable)" +#define BUILD_VERSION "(20091010-unstable)" #ifdef HAVE_SVN_VERSION diff --git a/cvpcb/CMakeLists.txt b/cvpcb/CMakeLists.txt index 58bea9a1df..31eff70fda 100644 --- a/cvpcb/CMakeLists.txt +++ b/cvpcb/CMakeLists.txt @@ -19,6 +19,7 @@ set(CVPCB_SRCS dialog_cvpcb_config_fbp.cpp dialog_display_options.cpp displayframe.cpp + dummy_functions.cpp genequiv.cpp init.cpp listboxes.cpp diff --git a/cvpcb/dummy_functions.cpp b/cvpcb/dummy_functions.cpp new file mode 100644 index 0000000000..1876ca1cce --- /dev/null +++ b/cvpcb/dummy_functions.cpp @@ -0,0 +1,21 @@ +/* dummy_functions.cpp + * + * There are functions used in some classes. + * they are useful in pcbnew, but have no meaning or are never used + * in cvpcb or gerbview. + * but they must exist because they appear in some classes, and here, no nothing. + */ +#include "fctsys.h" + +#include "common.h" +#include "pcbnew.h" + + +TRACK* Marque_Une_Piste( BOARD* aPcb, + TRACK* aStartSegm, + int* aSegmCount, + int* aTrackLen, + bool aReorder ) +{ + return NULL; +} diff --git a/eeschema/block_libedit.cpp b/eeschema/block_libedit.cpp index 68ea7bc43b..15e5e852f2 100644 --- a/eeschema/block_libedit.cpp +++ b/eeschema/block_libedit.cpp @@ -101,7 +101,8 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC ) case BLOCK_DRAG: /* Drag */ case BLOCK_MOVE: /* Move */ case BLOCK_COPY: /* Copy */ - ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate, + if ( m_component ) + ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate, m_unit, m_convert, g_EditPinByPinIsOn ); if( ItemCount ) @@ -125,12 +126,14 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC ) break; case BLOCK_DELETE: /* Delete */ - ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate, + if ( m_component ) + ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate, m_unit, m_convert, g_EditPinByPinIsOn ); if( ItemCount ) SaveCopyInUndoList( m_component ); - m_component->DeleteSelectedItems(); + if ( m_component ) + m_component->DeleteSelectedItems(); break; case BLOCK_SAVE: /* Save */ @@ -142,14 +145,16 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC ) case BLOCK_MIRROR_Y: - ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate, + if ( m_component ) + ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate, m_unit, m_convert, g_EditPinByPinIsOn ); if( ItemCount ) SaveCopyInUndoList( m_component ); pt = GetScreen()->m_BlockLocate.Centre(); pt.y *= -1; - m_component->MirrorSelectedItemsH( pt ); + if ( m_component ) + m_component->MirrorSelectedItemsH( pt ); break; case BLOCK_ZOOM: /* Window Zoom */ @@ -166,7 +171,8 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC ) if( MustDoPlace <= 0 ) { if( GetScreen()->m_BlockLocate.m_Command != BLOCK_SELECT_ITEMS_ONLY ) - m_component->ClearSelectedItems(); + if ( m_component ) + m_component->ClearSelectedItems(); GetScreen()->m_BlockLocate.m_Flags = 0; GetScreen()->m_BlockLocate.m_State = STATE_NO_BLOCK; @@ -213,19 +219,23 @@ void WinEDA_LibeditFrame::HandleBlockPlace( wxDC* DC ) case BLOCK_MOVE: /* Move */ case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/ GetScreen()->m_BlockLocate.ClearItemsList(); - SaveCopyInUndoList( m_component ); + if ( m_component ) + SaveCopyInUndoList( m_component ); pt = GetScreen()->m_BlockLocate.m_MoveVector; pt.y *= -1; - m_component->MoveSelectedItems( pt ); + if ( m_component ) + m_component->MoveSelectedItems( pt ); DrawPanel->Refresh( TRUE ); break; case BLOCK_COPY: /* Copy */ GetScreen()->m_BlockLocate.ClearItemsList(); - SaveCopyInUndoList( m_component ); + if ( m_component ) + SaveCopyInUndoList( m_component ); pt = GetScreen()->m_BlockLocate.m_MoveVector; pt.y *= -1; - m_component->CopySelectedItems( pt ); + if ( m_component ) + m_component->CopySelectedItems( pt ); break; case BLOCK_PASTE: /* Paste (recopie du dernier bloc sauve */ @@ -233,10 +243,12 @@ void WinEDA_LibeditFrame::HandleBlockPlace( wxDC* DC ) break; case BLOCK_MIRROR_Y: /* Invert by popup menu, from block move */ - SaveCopyInUndoList( m_component ); + if ( m_component ) + SaveCopyInUndoList( m_component ); pt = GetScreen()->m_BlockLocate.Centre(); pt.y *= -1; - m_component->MirrorSelectedItemsH( pt ); + if ( m_component ) + m_component->MirrorSelectedItemsH( pt ); break; case BLOCK_ZOOM: // Handled by HandleBlockEnd diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index a6df593293..153e7b34a0 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -599,8 +599,8 @@ bool LIB_COMPONENT::Load( FILE* file, char* line, int* lineNum, return false; } - m_DrawPinNum = (drawnum == 'N') ? FALSE : TRUE; - m_DrawPinName = (drawname == 'N') ? FALSE : TRUE; + m_DrawPinNum = (drawnum == 'N') ? FALSE : true; + m_DrawPinName = (drawname == 'N') ? FALSE : true; /* Copy part name and prefix. */ strupper( name ); @@ -622,7 +622,7 @@ bool LIB_COMPONENT::Load( FILE* file, char* line, int* lineNum, // Copy optional infos if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'L' ) - m_UnitSelectionLocked = TRUE; + m_UnitSelectionLocked = true; if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'P' ) m_Options = ENTRY_POWER; @@ -862,10 +862,10 @@ void LIB_COMPONENT::SetFields( const std::vector aFields ) { bool create = FALSE; if( !aFields[ii].m_Text.IsEmpty() ) - create = TRUE; + create = true; if( !aFields[ii].m_Name.IsEmpty() && ( aFields[ii].m_Name != ReturnDefaultFieldName( ii ) ) ) - create = TRUE; + create = true; if( create ) { LIB_FIELD*Field = new LIB_FIELD( this, ii ); @@ -1302,7 +1302,7 @@ void LIB_COMPONENT::SetConversion( bool asConvert ) { if( asConvert == HasConversion() ) return; - + // Duplicate items to create the converted shape if( asConvert ) { @@ -1321,6 +1321,7 @@ void LIB_COMPONENT::SetConversion( bool asConvert ) } else { + // Delete converted shape items becuase the converted shape does not exist LIB_DRAW_ITEM_LIST::iterator i = m_Drawings.begin(); while( i != m_Drawings.end() ) diff --git a/eeschema/dialog_edit_component_in_lib_base.cpp b/eeschema/dialog_edit_component_in_lib_base.cpp index 32b91d6853..aa3e5879fc 100644 --- a/eeschema/dialog_edit_component_in_lib_base.cpp +++ b/eeschema/dialog_edit_component_in_lib_base.cpp @@ -31,18 +31,21 @@ DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE::DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE( wx m_OptionsBoxSizer->Add( m_AsConvertButt, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_ShowPinNumButt = new wxCheckBox( m_PanelBasic, wxID_ANY, _("Show Pin Num"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ShowPinNumButt->SetValue(true); m_ShowPinNumButt->SetToolTip( _("Show or hide pin numbers") ); m_OptionsBoxSizer->Add( m_ShowPinNumButt, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_ShowPinNameButt = new wxCheckBox( m_PanelBasic, wxID_ANY, _("Show Pin Name"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ShowPinNameButt->SetValue(true); m_ShowPinNameButt->SetToolTip( _("Show or hide pin names") ); m_OptionsBoxSizer->Add( m_ShowPinNameButt, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_PinsNameInsideButt = new wxCheckBox( m_PanelBasic, wxID_ANY, _("Pin Name Inside"), wxDefaultPosition, wxDefaultSize, 0 ); + m_PinsNameInsideButt->SetValue(true); m_PinsNameInsideButt->SetToolTip( _("Check this option to have pin names inside the body and pin number outside.\nIf not checked pins names and pins numbers are outside.") ); @@ -63,7 +66,7 @@ DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE::DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE( wx m_staticTextNbUnits->Wrap( -1 ); bSizernbunits->Add( m_staticTextNbUnits, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_SelNumberOfUnits = new wxSpinCtrl( m_PanelBasic, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 16, 1 ); + m_SelNumberOfUnits = new wxSpinCtrl( m_PanelBasic, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 16, 1 ); bSizernbunits->Add( m_SelNumberOfUnits, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); bSizerMidBasicPanel->Add( bSizernbunits, 1, wxEXPAND, 5 ); @@ -75,7 +78,7 @@ DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE::DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE( wx m_staticTextskew->Wrap( -1 ); bSizer17->Add( m_staticTextskew, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_SetSkew = new wxSpinCtrl( m_PanelBasic, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100, 0 ); + m_SetSkew = new wxSpinCtrl( m_PanelBasic, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 100, 0 ); bSizer17->Add( m_SetSkew, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); bSizerMidBasicPanel->Add( bSizer17, 1, wxEXPAND, 5 ); diff --git a/eeschema/dialog_edit_component_in_lib_base.fbp b/eeschema/dialog_edit_component_in_lib_base.fbp index 4469f7a9f4..76d57ba164 100644 --- a/eeschema/dialog_edit_component_in_lib_base.fbp +++ b/eeschema/dialog_edit_component_in_lib_base.fbp @@ -246,7 +246,7 @@ 0 - 0 + 1 1 @@ -298,7 +298,7 @@ 0 - 0 + 1 1 @@ -350,7 +350,7 @@ 0 - 0 + 1 1 @@ -531,7 +531,7 @@ 1 16 - 0 + 1 m_SelNumberOfUnits protected @@ -648,7 +648,7 @@ 0 100 - 0 + 1 m_SetSkew protected diff --git a/eeschema/dialog_lib_new_component.fbp b/eeschema/dialog_lib_new_component.fbp index c511114b3b..8b15faf626 100644 --- a/eeschema/dialog_lib_new_component.fbp +++ b/eeschema/dialog_lib_new_component.fbp @@ -522,7 +522,7 @@ 0 wxID_ANY 0 - 40 + 26 1 @@ -754,7 +754,7 @@ 0 wxID_ANY - Prevent drawing items from being &moved + Parts in package locked (cannot be swapped) m_checkLockItems @@ -949,9 +949,9 @@ 0 wxID_ANY 40 - 10000 + 100 - 0 + 1 m_spinPinTextPosition protected @@ -1190,6 +1190,79 @@ + + 5 + wxEXPAND + 1 + + + bSizer121 + wxHORIZONTAL + none + + 3 + wxEXPAND + 0 + + 0 + protected + 12 + + + + 3 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + + 1 + + 1 + + + 0 + wxID_ANY + Pin name &inside + + + m_checkShowPinNameInside + protected + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10 wxALL|wxEXPAND diff --git a/eeschema/dialog_lib_new_component.h b/eeschema/dialog_lib_new_component.h index 87188feac4..e919314ddd 100644 --- a/eeschema/dialog_lib_new_component.h +++ b/eeschema/dialog_lib_new_component.h @@ -62,6 +62,12 @@ public: m_checkShowPinName->SetValue( show ); } bool GetShowPinName( void ) { return m_checkShowPinName->GetValue(); } + + void SetPinNameInside( bool show ) + { + m_checkShowPinNameInside->SetValue( show ); + } + bool GetPinNameInside( void ) { return m_checkShowPinNameInside->GetValue(); } }; #endif // __dialog_lib_new_component__ diff --git a/eeschema/dialog_lib_new_component_base.cpp b/eeschema/dialog_lib_new_component_base.cpp index fac5110437..283c5a342b 100644 --- a/eeschema/dialog_lib_new_component_base.cpp +++ b/eeschema/dialog_lib_new_component_base.cpp @@ -80,7 +80,7 @@ DIALOG_LIB_NEW_COMPONENT_BASE::DIALOG_LIB_NEW_COMPONENT_BASE( wxWindow* parent, bSizer4->Add( 0, 0, 1, wxEXPAND, 3 ); - m_spinPartCount = new wxSpinCtrl( this, wxID_ANY, wxT("1"), wxDefaultPosition, wxSize( 100,-1 ), wxSP_ARROW_KEYS, 1, 40, 0 ); + m_spinPartCount = new wxSpinCtrl( this, wxID_ANY, wxT("1"), wxDefaultPosition, wxSize( 100,-1 ), wxSP_ARROW_KEYS, 1, 26, 0 ); bSizer4->Add( m_spinPartCount, 0, wxALIGN_CENTER_VERTICAL|wxALL, 3 ); @@ -118,7 +118,7 @@ DIALOG_LIB_NEW_COMPONENT_BASE::DIALOG_LIB_NEW_COMPONENT_BASE( wxWindow* parent, bSizer9->Add( 12, 0, 0, wxEXPAND, 3 ); - m_checkLockItems = new wxCheckBox( this, wxID_ANY, _("Prevent drawing items from being &moved"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkLockItems = new wxCheckBox( this, wxID_ANY, _("Parts in package locked (cannot be swapped)"), wxDefaultPosition, wxDefaultSize, 0 ); bSizer9->Add( m_checkLockItems, 0, wxALIGN_CENTER_VERTICAL|wxALL, 3 ); @@ -146,7 +146,7 @@ DIALOG_LIB_NEW_COMPONENT_BASE::DIALOG_LIB_NEW_COMPONENT_BASE( wxWindow* parent, bSizer6->Add( 0, 0, 1, wxEXPAND, 3 ); - m_spinPinTextPosition = new wxSpinCtrl( this, wxID_ANY, wxT("40"), wxDefaultPosition, wxSize( 100,-1 ), wxSP_ARROW_KEYS, 0, 10000, 40 ); + m_spinPinTextPosition = new wxSpinCtrl( this, wxID_ANY, wxT("40"), wxDefaultPosition, wxSize( 100,-1 ), wxSP_ARROW_KEYS, 1, 100, 40 ); bSizer6->Add( m_spinPinTextPosition, 0, wxALIGN_CENTER_VERTICAL|wxALL, 3 ); m_staticText5 = new wxStaticText( this, wxID_ANY, _("mils"), wxDefaultPosition, wxSize( 30,-1 ), 0 ); @@ -181,6 +181,19 @@ DIALOG_LIB_NEW_COMPONENT_BASE::DIALOG_LIB_NEW_COMPONENT_BASE( wxWindow* parent, bSizer5->Add( bSizer12, 0, wxALL|wxEXPAND, 0 ); + wxBoxSizer* bSizer121; + bSizer121 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer121->Add( 12, 0, 0, wxEXPAND, 3 ); + + m_checkShowPinNameInside = new wxCheckBox( this, wxID_ANY, _("Pin name &inside"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkShowPinNameInside->SetValue(true); + + bSizer121->Add( m_checkShowPinNameInside, 0, wxALIGN_CENTER_VERTICAL|wxALL, 3 ); + + bSizer5->Add( bSizer121, 1, wxEXPAND, 5 ); + bSizer5->Add( 0, 5, 0, wxALL|wxEXPAND, 10 ); diff --git a/eeschema/dialog_lib_new_component_base.h b/eeschema/dialog_lib_new_component_base.h index bc8c541f30..d9b410610a 100644 --- a/eeschema/dialog_lib_new_component_base.h +++ b/eeschema/dialog_lib_new_component_base.h @@ -67,6 +67,8 @@ class DIALOG_LIB_NEW_COMPONENT_BASE : public wxDialog wxCheckBox* m_checkShowPinName; + wxCheckBox* m_checkShowPinNameInside; + wxStdDialogButtonSizer* m_sdbSizer; wxButton* m_sdbSizerOK; wxButton* m_sdbSizerCancel; diff --git a/eeschema/edit_component_in_lib.cpp b/eeschema/edit_component_in_lib.cpp index f122940190..d5a126f94f 100644 --- a/eeschema/edit_component_in_lib.cpp +++ b/eeschema/edit_component_in_lib.cpp @@ -5,6 +5,7 @@ #include "fctsys.h" #include "appl_wxstruct.h" #include "common.h" +#include "class_drawpanel.h" #include "confirm.h" #include "gestfich.h" @@ -31,13 +32,12 @@ void WinEDA_LibeditFrame::OnEditComponentProperties( wxCommandEvent& event ) { EditComponentProperties(); + DrawPanel->Refresh(); } void WinEDA_LibeditFrame::EditComponentProperties() { - wxASSERT( m_component != NULL && m_library != NULL ); - DIALOG_EDIT_COMPONENT_IN_LIBRARY dlg( this ); if( dlg.ShowModal() == wxID_CANCEL ) @@ -120,15 +120,21 @@ void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnOkClick( wxCommandEvent& event ) /* Update the doc, keyword and doc filename strings */ size_t i; int index; - CMP_LIB_ENTRY* entry; + CMP_LIB_ENTRY* entry = NULL; LIB_COMPONENT* component = m_Parent->GetComponent(); + if( component == NULL ) + { + EndModal( wxID_CANCEL ); + return; + } + CMP_LIBRARY* library = m_Parent->GetLibrary(); if( m_Parent->GetAliasName().IsEmpty() ) { entry = (CMP_LIB_ENTRY*) component; } - else + else if ( library ) { entry = library->FindEntry( m_Parent->GetAliasName() ); } @@ -213,21 +219,26 @@ void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnOkClick( wxCommandEvent& event ) component->m_DrawPinNum = m_ShowPinNumButt->GetValue() ? 1 : 0; component->m_DrawPinName = m_ShowPinNameButt->GetValue() ? 1 : 0; - if( m_PinsNameInsideButt->GetValue() == FALSE ) - component->m_TextInside = 0; + if( m_PinsNameInsideButt->GetValue() == false ) + component->m_TextInside = 0; // pin text outside the body (name is on the pin) else + { component->m_TextInside = m_SetSkew->GetValue(); + // Ensure component->m_TextInside != 0, because the meaning is "text outside". + if( component->m_TextInside == 0 ) + component->m_TextInside = 20; // give a reasonnable value + } - if( m_OptionPower->GetValue() == TRUE ) + if( m_OptionPower->GetValue() == true ) component->m_Options = ENTRY_POWER; else component->m_Options = ENTRY_NORMAL; /* Set the option "Units locked". - * Obviously, cannot be TRUE if there is only one part */ + * Obviously, cannot be true if there is only one part */ component->m_UnitSelectionLocked = m_OptionPartsLocked->GetValue(); if( component->GetPartCount() <= 1 ) - component->m_UnitSelectionLocked = FALSE; + component->m_UnitSelectionLocked = false; /* Update the footprint filter list */ component->m_FootprintList.Clear(); @@ -273,8 +284,8 @@ edited!" ), if( IsOK( this, _( "Remove all aliases from list?" ) ) ) { m_PartAliasList->Clear(); - m_ButtonDeleteAllAlias->Enable( FALSE ); - m_ButtonDeleteOneAlias->Enable( FALSE ); + m_ButtonDeleteAllAlias->Enable( false ); + m_ButtonDeleteOneAlias->Enable( false ); } } @@ -316,8 +327,8 @@ library <%s>." ), m_PartAliasList->Append( aliasname ); if( m_Parent->GetAliasName().IsEmpty() ) - m_ButtonDeleteAllAlias->Enable( TRUE ); - m_ButtonDeleteOneAlias->Enable( TRUE ); + m_ButtonDeleteAllAlias->Enable( true ); + m_ButtonDeleteOneAlias->Enable( true ); } @@ -342,8 +353,8 @@ edited!" ), if( m_PartAliasList->IsEmpty() ) { - m_ButtonDeleteAllAlias->Enable( FALSE ); - m_ButtonDeleteOneAlias->Enable( FALSE ); + m_ButtonDeleteAllAlias->Enable( false ); + m_ButtonDeleteOneAlias->Enable( false ); } } @@ -379,20 +390,20 @@ bool DIALOG_EDIT_COMPONENT_IN_LIBRARY::SetUnsetConvert() || ( m_Parent->GetShowDeMorgan() == component->HasConversion() ) ) return false; - if( m_Parent->GetShowDeMorgan() - && !IsOK( this, _( "Add new pins for alternate body style \ -( DeMorgan ) to component?" ) ) ) + if( m_Parent->GetShowDeMorgan() ) { - m_Parent->SetShowDeMorgan( false ); + if( !IsOK( this, _( "Add new pins for alternate body style \ +( DeMorgan ) to component?" ) ) ) return false; } - if( !m_Parent->GetShowDeMorgan() - && !IsOK( this, _( "Delete alternate body style (DeMorgan) draw \ -items from component?" ) ) ) + else if( component->HasConversion() ) { - m_Parent->SetShowDeMorgan( true ); - return false; + if( !IsOK( this, _( "Delete alternate body style (DeMorgan) draw items from component?" ) ) ) + { + m_Parent->SetShowDeMorgan( true ); + return false; + } } component->SetConversion( m_Parent->GetShowDeMorgan() ); @@ -419,7 +430,7 @@ void DIALOG_EDIT_COMPONENT_IN_LIBRARY::BrowseAndSelectDocFile( wxCommandEvent& e mask, /* Masque d'affichage */ this, wxFD_OPEN, - TRUE + true ); if( FullFileName.IsEmpty() ) return; @@ -446,8 +457,8 @@ void DIALOG_EDIT_COMPONENT_IN_LIBRARY::DeleteAllFootprintFilter( if( IsOK( this, _( "Ok to Delete FootprintFilter LIST" ) ) ) { m_FootprintFilterListBox->Clear(); - m_ButtonDeleteAllFootprintFilter->Enable( FALSE ); - m_ButtonDeleteOneFootprintFilter->Enable( FALSE ); + m_ButtonDeleteAllFootprintFilter->Enable( false ); + m_ButtonDeleteOneFootprintFilter->Enable( false ); } } @@ -486,8 +497,8 @@ void DIALOG_EDIT_COMPONENT_IN_LIBRARY::AddFootprintFilter( wxCommandEvent& WXUNU } m_FootprintFilterListBox->Append( Line ); - m_ButtonDeleteAllFootprintFilter->Enable( TRUE ); - m_ButtonDeleteOneFootprintFilter->Enable( TRUE ); + m_ButtonDeleteAllFootprintFilter->Enable( true ); + m_ButtonDeleteOneFootprintFilter->Enable( true ); } @@ -503,7 +514,7 @@ void DIALOG_EDIT_COMPONENT_IN_LIBRARY::DeleteOneFootprintFilter( if( !component || (m_FootprintFilterListBox->GetCount() == 0) ) { - m_ButtonDeleteAllFootprintFilter->Enable( FALSE ); - m_ButtonDeleteOneFootprintFilter->Enable( FALSE ); + m_ButtonDeleteAllFootprintFilter->Enable( false ); + m_ButtonDeleteOneFootprintFilter->Enable( false ); } } diff --git a/eeschema/libedit.cpp b/eeschema/libedit.cpp index e78ebcedfa..c26982ea58 100644 --- a/eeschema/libedit.cpp +++ b/eeschema/libedit.cpp @@ -113,6 +113,7 @@ library \"%s\"." ), GetScreen()->ClearUndoRedoList(); Zoom_Automatique( false ); DrawPanel->Refresh(); + SetShowDeMorgan(m_component->HasConversion() ); } @@ -506,7 +507,10 @@ lost!\n\nClear the current component from the screen?" ) ) ) return; if( dlg.GetName().IsEmpty() ) + { + wxMessageBox(_("This new component has no name and cannot be created. Aborted")); return; + } name = dlg.GetName().MakeUpper(); name.Replace( wxT( " " ), wxT( "_" ) ); @@ -525,12 +529,25 @@ lost!\n\nClear the current component from the screen?" ) ) ) LIB_COMPONENT* component = new LIB_COMPONENT( name ); component->m_Prefix.m_Text = dlg.GetReference(); component->SetPartCount( dlg.GetPartCount() ); + // Initialize component->m_TextInside member: + // if 0, pin text is outside the body (on the pin) + // if > 0, pin text is inside the body component->SetConversion( dlg.GetAlternateBodyStyle() ); - component->m_TextInside = dlg.GetPinTextPosition(); - component->m_Options = ( dlg.GetPowerSymbol() ) ? ENTRY_POWER : - ENTRY_NORMAL; + SetShowDeMorgan( dlg.GetAlternateBodyStyle() ); + if( dlg.GetPinNameInside( ) ) + { + component->m_TextInside = dlg.GetPinTextPosition(); + if( component->m_TextInside == 0 ) + component->m_TextInside = 1; + } + else + component->m_TextInside = 0; + component->m_Options = ( dlg.GetPowerSymbol() ) ? ENTRY_POWER : ENTRY_NORMAL; component->m_DrawPinNum = dlg.GetShowPinNumber(); component->m_DrawPinName = dlg.GetShowPinName(); + component->m_UnitSelectionLocked = dlg.GetLockItems(); + if( dlg.GetPartCount() < 2 ) + component->m_UnitSelectionLocked = false; if( m_component ) { diff --git a/eeschema/libeditfrm.h b/eeschema/libeditfrm.h index a7bf3e94a3..eb28024f43 100644 --- a/eeschema/libeditfrm.h +++ b/eeschema/libeditfrm.h @@ -20,8 +20,8 @@ class LIB_DRAW_ITEM; class WinEDA_LibeditFrame : public WinEDA_DrawFrame { public: - WinEDAChoiceBox* m_SelpartBox; - WinEDAChoiceBox* m_SelAliasBox; + WinEDAChoiceBox* m_SelpartBox; // a Box to select a part to edit (if any) + WinEDAChoiceBox* m_SelAliasBox; // a box to select the alias to edit (if any) public: WinEDA_LibeditFrame( wxWindow* father, @@ -31,59 +31,59 @@ public: ~WinEDA_LibeditFrame(); - void Process_Special_Functions( wxCommandEvent& event ); - void OnImportPart( wxCommandEvent& event ); - void OnExportPart( wxCommandEvent& event ); - void OnSelectAlias( wxCommandEvent& event ); - void OnSelectPart( wxCommandEvent& event ); - void DeleteOnePart( wxCommandEvent& event ); - void CreateNewLibraryPart( wxCommandEvent& event ); - void OnEditComponentProperties( wxCommandEvent& event ); - void InstallFieldsEditorDialog( wxCommandEvent& event ); - void LoadOneLibraryPart( wxCommandEvent& event ); - void OnViewEntryDoc( wxCommandEvent& event ); - void OnCheckComponent( wxCommandEvent& event ); - void OnSelectBodyStyle( wxCommandEvent& event ); + void Process_Special_Functions( wxCommandEvent& event ); + void OnImportPart( wxCommandEvent& event ); + void OnExportPart( wxCommandEvent& event ); + void OnSelectAlias( wxCommandEvent& event ); + void OnSelectPart( wxCommandEvent& event ); + void DeleteOnePart( wxCommandEvent& event ); + void CreateNewLibraryPart( wxCommandEvent& event ); + void OnEditComponentProperties( wxCommandEvent& event ); + void InstallFieldsEditorDialog( wxCommandEvent& event ); + void LoadOneLibraryPart( wxCommandEvent& event ); + void OnViewEntryDoc( wxCommandEvent& event ); + void OnCheckComponent( wxCommandEvent& event ); + void OnSelectBodyStyle( wxCommandEvent& event ); - void OnUpdateEditingPart( wxUpdateUIEvent& event ); - void OnUpdateNotEditingPart( wxUpdateUIEvent& event ); - void OnUpdateUndo( wxUpdateUIEvent& event ); - void OnUpdateRedo( wxUpdateUIEvent& event ); - void OnUpdateSaveCurrentLib( wxUpdateUIEvent& event ); - void OnUpdateViewDoc( wxUpdateUIEvent& event ); - void OnUpdatePinByPin( wxUpdateUIEvent& event ); - void OnUpdatePartNumber( wxUpdateUIEvent& event ); - void OnUpdateDeMorganNormal( wxUpdateUIEvent& event ); - void OnUpdateDeMorganConvert( wxUpdateUIEvent& event ); - void OnUpdateSelectAlias( wxUpdateUIEvent& event ); + void OnUpdateEditingPart( wxUpdateUIEvent& event ); + void OnUpdateNotEditingPart( wxUpdateUIEvent& event ); + void OnUpdateUndo( wxUpdateUIEvent& event ); + void OnUpdateRedo( wxUpdateUIEvent& event ); + void OnUpdateSaveCurrentLib( wxUpdateUIEvent& event ); + void OnUpdateViewDoc( wxUpdateUIEvent& event ); + void OnUpdatePinByPin( wxUpdateUIEvent& event ); + void OnUpdatePartNumber( wxUpdateUIEvent& event ); + void OnUpdateDeMorganNormal( wxUpdateUIEvent& event ); + void OnUpdateDeMorganConvert( wxUpdateUIEvent& event ); + void OnUpdateSelectAlias( wxUpdateUIEvent& event ); - void UpdateAliasSelectList(); - void UpdatePartSelectList(); - void DisplayLibInfos(); - void RedrawActiveWindow( wxDC* DC, bool EraseBg ); - void OnCloseWindow( wxCloseEvent& Event ); - void ReCreateHToolbar(); - void ReCreateVToolbar(); - void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); - bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); - int BestZoom(); // Retourne le meilleur zoom - void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ); + void UpdateAliasSelectList(); + void UpdatePartSelectList(); + void DisplayLibInfos(); + void RedrawActiveWindow( wxDC* DC, bool EraseBg ); + void OnCloseWindow( wxCloseEvent& Event ); + void ReCreateHToolbar(); + void ReCreateVToolbar(); + void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); + bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); + int BestZoom(); // Retourne le meilleur zoom + void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ); - SCH_SCREEN* GetScreen() { return (SCH_SCREEN*) GetBaseScreen(); } - void OnHotKey( wxDC* DC, int hotkey, - EDA_BaseStruct* DrawStruct ); + SCH_SCREEN* GetScreen() { return (SCH_SCREEN*) GetBaseScreen(); } + void OnHotKey( wxDC* DC, int hotkey, + EDA_BaseStruct* DrawStruct ); - void GeneralControle( wxDC* DC, - wxPoint MousePositionInPixels ); + void GeneralControle( wxDC* DC, + wxPoint MousePositionInPixels ); - void LoadSettings(); - void SaveSettings(); + void LoadSettings(); + void SaveSettings(); - LIB_COMPONENT* GetComponent( void ) { return m_component; } + LIB_COMPONENT* GetComponent( void ) { return m_component; } - CMP_LIBRARY* GetLibrary( void ) { return m_library; } + CMP_LIBRARY* GetLibrary( void ) { return m_library; } - wxString& GetAliasName( void ) { return m_aliasName; } + wxString& GetAliasName( void ) { return m_aliasName; } int GetUnit( void ) { return m_unit; } @@ -93,6 +93,7 @@ public: m_unit = unit; } + int GetConvert( void ) { return m_convert; } void SetConvert( int convert ) @@ -101,16 +102,18 @@ public: m_convert = convert; } - LIB_DRAW_ITEM* GetLastDrawItem( void ) { return m_lastDrawItem; } + + LIB_DRAW_ITEM* GetLastDrawItem( void ) { return m_lastDrawItem; } void SetLastDrawItem( LIB_DRAW_ITEM* drawItem ) { m_lastDrawItem = drawItem; } - LIB_DRAW_ITEM* GetDrawItem( void ) { return m_drawItem; } - void SetDrawItem( LIB_DRAW_ITEM* drawItem ); + LIB_DRAW_ITEM* GetDrawItem( void ) { return m_drawItem; } + + void SetDrawItem( LIB_DRAW_ITEM* drawItem ); bool GetShowDeMorgan( void ) { return m_showDeMorgan; } @@ -119,79 +122,84 @@ public: private: // General: - void SaveOnePartInMemory(); - void SelectActiveLibrary(); - void SaveActiveLibrary( wxCommandEvent& event ); + void SaveOnePartInMemory(); + void SelectActiveLibrary(); + void SaveActiveLibrary( wxCommandEvent& event ); - bool LoadOneLibraryPartAux( CMP_LIB_ENTRY* LibEntry, - CMP_LIBRARY* Library ); + bool LoadOneLibraryPartAux( CMP_LIB_ENTRY* LibEntry, + CMP_LIBRARY* Library ); - void DisplayCmpDoc(); - void EditComponentProperties(); + void DisplayCmpDoc(); + void EditComponentProperties(); // General editing public: - void SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, - int flag_type_command = 0 ); + void SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, + int flag_type_command = 0 ); private: - void GetComponentFromUndoList(wxCommandEvent& event); - void GetComponentFromRedoList(wxCommandEvent& event); + void GetComponentFromUndoList( wxCommandEvent& event ); + void GetComponentFromRedoList( wxCommandEvent& event ); // Edition des Pins: - void CreatePin( wxDC* DC ); - void DeletePin( wxDC* DC, - LIB_COMPONENT* LibEntry, - LIB_PIN* Pin ); - void StartMovePin( wxDC* DC ); + void CreatePin( wxDC* DC ); + void DeletePin( wxDC* DC, + LIB_COMPONENT* LibEntry, + LIB_PIN* Pin ); + void StartMovePin( wxDC* DC ); // Edition de l'ancre - void PlaceAncre(); + void PlaceAncre(); // Edition des graphismes: - LIB_DRAW_ITEM* CreateGraphicItem( LIB_COMPONENT* LibEntry, wxDC* DC ); - void GraphicItemBeginDraw( wxDC* DC ); - void StartMoveDrawSymbol( wxDC* DC ); - void EndDrawGraphicItem( wxDC* DC ); - void LoadOneSymbol(); - void SaveOneSymbol(); - void EditGraphicSymbol( wxDC* DC, - LIB_DRAW_ITEM* DrawItem ); - void EditSymbolText( wxDC* DC, LIB_DRAW_ITEM* DrawItem ); - void RotateSymbolText( wxDC* DC ); - void DeleteDrawPoly( wxDC* DC ); - LIB_DRAW_ITEM* LocateItemUsingCursor(); - void RotateField( wxDC* DC, LIB_FIELD* Field ); - void PlaceField( wxDC* DC, LIB_FIELD* Field ); - void EditField( wxDC* DC, LIB_FIELD* Field ); - void StartMoveField( wxDC* DC, LIB_FIELD* field ); + LIB_DRAW_ITEM* CreateGraphicItem( LIB_COMPONENT* LibEntry, wxDC* DC ); + void GraphicItemBeginDraw( wxDC* DC ); + void StartMoveDrawSymbol( wxDC* DC ); + void EndDrawGraphicItem( wxDC* DC ); + void LoadOneSymbol(); + void SaveOneSymbol(); + void EditGraphicSymbol( wxDC* DC, + LIB_DRAW_ITEM* DrawItem ); + void EditSymbolText( wxDC* DC, LIB_DRAW_ITEM* DrawItem ); + void RotateSymbolText( wxDC* DC ); + void DeleteDrawPoly( wxDC* DC ); + LIB_DRAW_ITEM* LocateItemUsingCursor(); + void RotateField( wxDC* DC, LIB_FIELD* Field ); + void PlaceField( wxDC* DC, LIB_FIELD* Field ); + void EditField( wxDC* DC, LIB_FIELD* Field ); + void StartMoveField( wxDC* DC, LIB_FIELD* field ); public: /* Block commands: */ - int ReturnBlockCommand( int key ); - void HandleBlockPlace( wxDC* DC ); - int HandleBlockEnd( wxDC* DC ); + int ReturnBlockCommand( int key ); + void HandleBlockPlace( wxDC* DC ); + int HandleBlockEnd( wxDC* DC ); - void PlacePin( wxDC* DC ); - void InitEditOnePin(); - void GlobalSetPins( wxDC* DC, LIB_PIN* MasterPin, int id ); + void PlacePin( wxDC* DC ); + void InitEditOnePin(); + void GlobalSetPins( wxDC* DC, LIB_PIN* MasterPin, int id ); // Repetition automatique de placement de pins - void RepeatPinItem( wxDC* DC, LIB_PIN* Pin ); + void RepeatPinItem( wxDC* DC, LIB_PIN* Pin ); protected: - wxString m_ConfigPath; - wxString m_LastLibImportPath; - wxString m_LastLibExportPath; + wxString m_ConfigPath; + wxString m_LastLibImportPath; + wxString m_LastLibExportPath; - static LIB_COMPONENT* m_component; - static CMP_LIBRARY* m_library; + static LIB_COMPONENT* m_component; // The current edited component (NULL if no component) + static CMP_LIBRARY* m_library; // The current active libary (NULL if none) static LIB_DRAW_ITEM* m_lastDrawItem; static LIB_DRAW_ITEM* m_drawItem; static wxString m_aliasName; - static int m_unit; - static int m_convert; - static bool m_showDeMorgan; + static int m_unit; // The unit number to edit and show + static int m_convert; // Show the normal shape ( m_convert <= 1 ) + // or the converted shape ( m_convert > 1 ) + static bool m_showDeMorgan; // true to force DeMorgan/normal tools selection enabled + // They are enabled when the loaded component has + // Graphic items for converted shape + // But under some circumstances (New component created) + // these tools must left enable static wxSize m_clientSize; DECLARE_EVENT_TABLE() diff --git a/eeschema/libframe.cpp b/eeschema/libframe.cpp index 4ca9c97e5c..a8eec2f8e0 100644 --- a/eeschema/libframe.cpp +++ b/eeschema/libframe.cpp @@ -154,6 +154,7 @@ WinEDA_LibeditFrame::WinEDA_LibeditFrame( wxWindow* father, m_Draw_Axis = true; // true pour avoir les axes dessines m_Draw_Grid = true; // true pour avoir la axes dessinee m_ConfigPath = wxT( "LibraryEditor" ); + SetShowDeMorgan( false ); // Give an icon SetIcon( wxIcon( libedit_xpm ) ); @@ -440,8 +441,7 @@ void WinEDA_LibeditFrame::OnUpdatePartNumber( wxUpdateUIEvent& event ) /* Using the typical event.Enable() call doesn't seem to work with wxGTK * so use the pointer to alias combobox to directly enable or disable. */ - m_SelpartBox->Enable( m_component != NULL - && m_component->GetPartCount() > 1 ); + m_SelpartBox->Enable( m_component && m_component->GetPartCount() > 1 ); } @@ -450,8 +450,8 @@ void WinEDA_LibeditFrame::OnUpdateDeMorganNormal( wxUpdateUIEvent& event ) if( m_HToolBar == NULL ) return; - event.Enable( m_component != NULL - && m_component->HasConversion() ); + event.Enable( GetShowDeMorgan() || + (m_component && m_component->HasConversion()) ); m_HToolBar->ToggleTool( event.GetId(), m_convert <= 1 ); } @@ -461,8 +461,8 @@ void WinEDA_LibeditFrame::OnUpdateDeMorganConvert( wxUpdateUIEvent& event ) if( m_HToolBar == NULL ) return; - event.Enable( m_component != NULL - && m_component->HasConversion() ); + event.Enable( GetShowDeMorgan() || + (m_component && m_component->HasConversion()) ); m_HToolBar->ToggleTool( event.GetId(), m_convert > 1 ); } diff --git a/eeschema/netform.cpp b/eeschema/netform.cpp index 78637c774a..78c4fe81d0 100644 --- a/eeschema/netform.cpp +++ b/eeschema/netform.cpp @@ -796,7 +796,7 @@ static void FindAllsInstancesOfComponent( SCH_COMPONENT* Component_in, for( pin = Entry->GetNextPin(); pin != NULL; pin = Entry->GetNextPin( pin ) ) { - wxASSERT( pin->Type() != COMPONENT_PIN_DRAW_TYPE ); + wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE ); if( pin->m_Unit && ( pin->m_Unit != Component2->GetUnitSelection( sheet ) ) ) diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt index fa7e7051ae..f0b8224444 100644 --- a/gerbview/CMakeLists.txt +++ b/gerbview/CMakeLists.txt @@ -12,6 +12,7 @@ set(GERBVIEW_SRCS controle.cpp dcode.cpp deltrack.cpp + dummy_functions.cpp edit.cpp export_to_pcbnew.cpp files.cpp diff --git a/gerbview/dummy_functions.cpp b/gerbview/dummy_functions.cpp new file mode 100644 index 0000000000..1876ca1cce --- /dev/null +++ b/gerbview/dummy_functions.cpp @@ -0,0 +1,21 @@ +/* dummy_functions.cpp + * + * There are functions used in some classes. + * they are useful in pcbnew, but have no meaning or are never used + * in cvpcb or gerbview. + * but they must exist because they appear in some classes, and here, no nothing. + */ +#include "fctsys.h" + +#include "common.h" +#include "pcbnew.h" + + +TRACK* Marque_Une_Piste( BOARD* aPcb, + TRACK* aStartSegm, + int* aSegmCount, + int* aTrackLen, + bool aReorder ) +{ + return NULL; +} diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index bf51dc2f0b..2cbb8d1237 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -59,7 +59,7 @@ public: bool m_TrackAndViasSizesList_Changed; private: - + DRC* m_drc; ///< the DRC controller, see drc.cpp // we'll use lower case function names for private member functions. @@ -457,9 +457,10 @@ public: * Basic routine used by other routines when editing tracks or vias * @param aTrackItem = the track segment or via to modify * @param aItemsListPicker = the list picker to use for an undo command (can be NULL) + * @param aUseNetclassValue = true to use NetClass value, false to use g_DesignSettings value * @return true if done, false if no not change (because DRC error) */ - bool SetTrackSegmentWidth( TRACK* aTrackItem, PICKED_ITEMS_LIST* aItemsListPicker ); + bool SetTrackSegmentWidth( TRACK* aTrackItem, PICKED_ITEMS_LIST* aItemsListPicker, bool aUseNetclassValue ); // zone handling diff --git a/internat/fr/kicad.mo b/internat/fr/kicad.mo index 9af3c0b180260b97e8c4a2e7ed6155ba22378a07..ea2526f7a25ce4bda4235ce3b55f51f68d5aadc8 100644 GIT binary patch delta 62153 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

#}jM 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 delta 61340 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

  • J{4*V^ek)rRWZC4p>x5{$h_BkINU@Y3f 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 diff --git a/internat/fr/kicad.po b/internat/fr/kicad.po index f0a7f689dd..6c401672b4 100644 --- a/internat/fr/kicad.po +++ b/internat/fr/kicad.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: kicad\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-10-08 20:49+0100\n" -"PO-Revision-Date: 2009-10-08 20:57+0100\n" +"POT-Creation-Date: 2009-10-10 15:08+0100\n" +"PO-Revision-Date: 2009-10-10 15:10+0100\n" "Last-Translator: \n" "Language-Team: kicad team \n" "MIME-Version: 1.0\n" @@ -473,286 +473,6 @@ msgstr "Itération" msgid "Ok to abort ?" msgstr "Ok pour arrêter ?" -#: pcbnew/tool_pcb.cpp:29 -msgid "" -"Show active layer selections\n" -"and select layer pair for route and place via" -msgstr "" -"Affiche sélections couche active\n" -"et sélection paire de couches pour routage et placement via" - -#: pcbnew/tool_pcb.cpp:203 -msgid "New board" -msgstr "Nouveau Circuit Imprimé" - -#: pcbnew/tool_pcb.cpp:205 -msgid "Open existing board" -msgstr "Ouvrir C.I. existant" - -#: pcbnew/tool_pcb.cpp:207 -msgid "Save board" -msgstr "Sauver Circuit Imprimé" - -#: pcbnew/tool_pcb.cpp:211 -msgid "Page settings (size, texts)" -msgstr "Ajustage de la feuille de dessin (dimensions, textes)" - -#: pcbnew/tool_pcb.cpp:216 -msgid "Open module editor" -msgstr "Ouvrir Editeur de modules" - -#: pcbnew/tool_pcb.cpp:220 -msgid "Cut selected item" -msgstr "Suppression des éléments sélectionnés" - -#: pcbnew/tool_pcb.cpp:224 -msgid "Copy selected item" -msgstr "Copie des éléments sélectionnés" - -#: pcbnew/tool_pcb.cpp:227 -msgid "Paste" -msgstr "Copie des éléments sauvegardés" - -#: pcbnew/tool_pcb.cpp:232 -msgid "Undo last edition" -msgstr "Défait dernière édition" - -#: pcbnew/tool_pcb.cpp:234 -msgid "Redo the last undo command" -msgstr "Refait la dernière commande defaite" - -#: pcbnew/tool_pcb.cpp:238 -msgid "Print board" -msgstr "Imprimer C.I." - -#: pcbnew/tool_pcb.cpp:240 -msgid "Plot (HPGL, PostScript, or GERBER format)" -msgstr "Tracer en format HPGL, POSTSCRIPT ou GERBER" - -#: pcbnew/tool_pcb.cpp:243 -msgid "Zoom in" -msgstr "Zoom +" - -#: pcbnew/tool_pcb.cpp:248 -msgid "Zoom out" -msgstr "Zoom -" - -#: pcbnew/tool_pcb.cpp:253 -msgid "Redraw view" -msgstr "Redessin de l'écran" - -#: pcbnew/tool_pcb.cpp:258 -msgid "Zoom auto" -msgstr "Zoom Automatique" - -#: pcbnew/tool_pcb.cpp:264 -msgid "Find components and texts" -msgstr "Recherche de composants et textes" - -#: pcbnew/tool_pcb.cpp:272 -msgid "Read netlist" -msgstr "Lire Netliste" - -#: pcbnew/tool_pcb.cpp:274 -msgid "Pcb Design Rules Check" -msgstr "Contrôle des règles de conception" - -#: pcbnew/tool_pcb.cpp:286 -msgid "Mode Module: Manual and Automatic Move or Place for modules" -msgstr "Mode Module: Déplacements ou Placement Manuel ou Automatique des modules" - -#: pcbnew/tool_pcb.cpp:290 -msgid "Mode Track and Autorouting" -msgstr "Mode Pistes et Autoroutage" - -#: pcbnew/tool_pcb.cpp:296 -msgid "Fast access to theWeb Based FreeROUTE advanced router" -msgstr "Acces rapide au routeur avancé FreeROUTE sur le Web" - -#: pcbnew/tool_pcb.cpp:323 -msgid "Drc OFF" -msgstr "Drc DESACTIVEE" - -#: pcbnew/tool_pcb.cpp:326 -msgid "Display Grid OFF" -msgstr "Suppression de l'affichage de la grille" - -#: pcbnew/tool_pcb.cpp:329 -msgid "Display Polar Coord ON" -msgstr "Activer affichage coord Polaires" - -#: pcbnew/tool_pcb.cpp:332 -msgid "Units in inches" -msgstr "Unités en pouces" - -#: pcbnew/tool_pcb.cpp:335 -msgid "Units in millimeters" -msgstr "Unités en millimètres" - -#: pcbnew/tool_pcb.cpp:338 -msgid "Change Cursor Shape" -msgstr "Sélection de la forme du curseur" - -#: pcbnew/tool_pcb.cpp:343 -msgid "Show General Ratsnest" -msgstr "Montrer le chevelu général" - -#: pcbnew/tool_pcb.cpp:346 -msgid "Show Module Ratsnest when moving" -msgstr "Montrer le chevelu du module pendant déplacement" - -#: pcbnew/tool_pcb.cpp:352 -msgid "Enable Auto Del Track" -msgstr "Autoriser l'effacement automatique des pistes" - -#: pcbnew/tool_pcb.cpp:357 -msgid "Show filled areas in zones" -msgstr "Afficher les surfaces remplies dans les zones" - -#: pcbnew/tool_pcb.cpp:360 -msgid "Do not show filled areas in zones" -msgstr "Ne pas afficher les surfaces remplies dans les zones" - -#: pcbnew/tool_pcb.cpp:363 -msgid "Show outlines of filled areas only in zones" -msgstr "Afficher uniquement les contours des surfaces remplies dans les zones" - -#: pcbnew/tool_pcb.cpp:368 -msgid "Show Pads Sketch" -msgstr "Afficher pastilles en contour" - -#: pcbnew/tool_pcb.cpp:372 -msgid "Show Vias Sketch" -msgstr "Afficher Pastilles en Contour" - -#: pcbnew/tool_pcb.cpp:376 -msgid "Show Tracks Sketch" -msgstr "Afficher Pistes en Contour" - -#: pcbnew/tool_pcb.cpp:381 -msgid "High Contrast Mode Display" -msgstr "Mode d'affichage Haut Contraste" - -#: pcbnew/tool_pcb.cpp:388 -msgid "Show Invisible Text" -msgstr "Montrer textes invisibles" - -#: pcbnew/tool_pcb.cpp:399 -msgid "" -"Display/remove auxiliary vertical toolbar (tools for micro wave applications)\n" -" This is a experimental feature (under development)" -msgstr "" -"Affiche/supprime le toolbar vertical auxiliaire (outils pour applications micro-ondes)\n" -"C'est un outil expérimental (en cours de développement)" - -#: pcbnew/tool_pcb.cpp:429 -msgid "Net highlight" -msgstr "Surbrillance des équipotentielles" - -#: pcbnew/tool_pcb.cpp:434 -msgid "Display local ratsnest (pad or module)" -msgstr "Afficher le chevelu local (pastilles ou modules)" - -#: pcbnew/tool_pcb.cpp:440 -msgid "Add modules" -msgstr "Addition de Modules" - -#: pcbnew/tool_pcb.cpp:444 -msgid "Add tracks and vias" -msgstr "Ajouter pistes et vias" - -#: pcbnew/tool_pcb.cpp:448 -msgid "Add zones" -msgstr "Addition de Zones" - -#: pcbnew/tool_pcb.cpp:453 -msgid "Add graphic line or polygon" -msgstr "Addition de lignes ou polygones graphiques" - -#: pcbnew/tool_pcb.cpp:457 -msgid "Add graphic circle" -msgstr "Addition de graphiques (Cercle)" - -#: pcbnew/tool_pcb.cpp:461 -msgid "Add graphic arc" -msgstr "Addition de graphiques (Arc de Cercle)" - -#: pcbnew/tool_pcb.cpp:465 -msgid "Add text" -msgstr "Ajout de Texte" - -#: pcbnew/tool_pcb.cpp:470 -msgid "Add dimension" -msgstr "Ajout des cotes" - -#: pcbnew/tool_pcb.cpp:474 -msgid "Add layer alignment target" -msgstr "Ajouter Mire de superposition" - -#: pcbnew/tool_pcb.cpp:479 -msgid "Delete items" -msgstr "Suppression d'éléments" - -#: pcbnew/tool_pcb.cpp:484 -msgid "Offset adjust for drill and place files" -msgstr "Ajuste offset pour fichier de perçage et placement" - -#: pcbnew/tool_pcb.cpp:510 -msgid "Create line of specified length for microwave applications" -msgstr "Création de lignes de longueur spécifiée (pour applications micro-ondes)" - -#: pcbnew/tool_pcb.cpp:514 -msgid "Create gap of specified length for microwave applications" -msgstr "Création de gaps de longueur spécifiée (pour applications micro-ondes)" - -#: pcbnew/tool_pcb.cpp:520 -msgid "Create stub of specified length for microwave applications" -msgstr "Création de stub de longueur spécifiée (pour applications micro-ondes)" - -#: pcbnew/tool_pcb.cpp:524 -msgid "Create stub (arc) of specified length for microwave applications" -msgstr "Création de stub (arc) de longueur spécifiée (pour applications micro-ondes)" - -#: pcbnew/tool_pcb.cpp:529 -msgid "Create a polynomial shape for microwave applications" -msgstr "Création de formes polynomiales (pour applications micro-ondes)" - -#: pcbnew/tool_pcb.cpp:585 -msgid "Current NetClass clearance value" -msgstr "Valeur isolation NetClass courante" - -#: pcbnew/tool_pcb.cpp:595 -msgid "Name of the current NetClass" -msgstr "Nom de la NetClass courante" - -#: pcbnew/tool_pcb.cpp:601 -msgid "" -"Auto track width: when starting on an existing track use its width\n" -"otherwise, use current width setting" -msgstr "" -"Largeur de piste automatique: si on démarre sur une piste existante, utiliser sa largeur\n" -" sinon utiliser la largeur courante" - -#: pcbnew/tool_pcb.cpp:618 -msgid "Auto" -msgstr "Auto" - -#: pcbnew/tool_pcb.cpp:622 -msgid "Zoom " -msgstr "Zoom " - -#: pcbnew/tool_pcb.cpp:642 -msgid "Grid" -msgstr "Grille" - -#: pcbnew/tool_pcb.cpp:660 -msgid "User Grid" -msgstr "Grille perso" - -#: pcbnew/tool_pcb.cpp:769 -msgid "+/- to switch" -msgstr "+/- pour commuter" - #: pcbnew/solve.cpp:240 msgid "Abort routing?" msgstr "Arrêter le routage?" @@ -1534,33 +1254,285 @@ msgstr "Inclure Pistes Autoroutées" msgid "Include Locked Tracks" msgstr "Inclure Pistes Verrouillées" -#: pcbnew/class_drawsegment.cpp:372 -msgid "Shape" -msgstr "Forme" +#: pcbnew/tool_pcb.cpp:29 +msgid "" +"Show active layer selections\n" +"and select layer pair for route and place via" +msgstr "" +"Affiche sélections couche active\n" +"et sélection paire de couches pour routage et placement via" -#: pcbnew/class_drawsegment.cpp:376 -msgid "Circle" -msgstr "Cercle" +#: pcbnew/tool_pcb.cpp:203 +msgid "New board" +msgstr "Nouveau Circuit Imprimé" -#: pcbnew/class_drawsegment.cpp:380 -msgid "Arc" -msgstr "Arc" +#: pcbnew/tool_pcb.cpp:205 +msgid "Open existing board" +msgstr "Ouvrir C.I. existant" -#: pcbnew/class_drawsegment.cpp:383 -msgid "Angle" -msgstr "Angle" +#: pcbnew/tool_pcb.cpp:207 +msgid "Save board" +msgstr "Sauver Circuit Imprimé" -#: pcbnew/class_drawsegment.cpp:386 -msgid "Curve" -msgstr "Courbe" +#: pcbnew/tool_pcb.cpp:211 +msgid "Page settings (size, texts)" +msgstr "Ajustage de la feuille de dessin (dimensions, textes)" -#: pcbnew/class_drawsegment.cpp:390 -msgid "Segment" -msgstr "Segment" +#: pcbnew/tool_pcb.cpp:216 +msgid "Open module editor" +msgstr "Ouvrir Editeur de modules" -#: pcbnew/class_drawsegment.cpp:400 -msgid "Layer" -msgstr "Couche" +#: pcbnew/tool_pcb.cpp:220 +msgid "Cut selected item" +msgstr "Suppression des éléments sélectionnés" + +#: pcbnew/tool_pcb.cpp:224 +msgid "Copy selected item" +msgstr "Copie des éléments sélectionnés" + +#: pcbnew/tool_pcb.cpp:227 +msgid "Paste" +msgstr "Copie des éléments sauvegardés" + +#: pcbnew/tool_pcb.cpp:232 +msgid "Undo last edition" +msgstr "Défait dernière édition" + +#: pcbnew/tool_pcb.cpp:234 +msgid "Redo the last undo command" +msgstr "Refait la dernière commande defaite" + +#: pcbnew/tool_pcb.cpp:238 +msgid "Print board" +msgstr "Imprimer C.I." + +#: pcbnew/tool_pcb.cpp:240 +msgid "Plot (HPGL, PostScript, or GERBER format)" +msgstr "Tracer en format HPGL, POSTSCRIPT ou GERBER" + +#: pcbnew/tool_pcb.cpp:243 +msgid "Zoom in" +msgstr "Zoom +" + +#: pcbnew/tool_pcb.cpp:248 +msgid "Zoom out" +msgstr "Zoom -" + +#: pcbnew/tool_pcb.cpp:253 +msgid "Redraw view" +msgstr "Redessin de l'écran" + +#: pcbnew/tool_pcb.cpp:258 +msgid "Zoom auto" +msgstr "Zoom Automatique" + +#: pcbnew/tool_pcb.cpp:264 +msgid "Find components and texts" +msgstr "Recherche de composants et textes" + +#: pcbnew/tool_pcb.cpp:272 +msgid "Read netlist" +msgstr "Lire Netliste" + +#: pcbnew/tool_pcb.cpp:274 +msgid "Pcb Design Rules Check" +msgstr "Contrôle des règles de conception" + +#: pcbnew/tool_pcb.cpp:286 +msgid "Mode Module: Manual and Automatic Move or Place for modules" +msgstr "Mode Module: Déplacements ou Placement Manuel ou Automatique des modules" + +#: pcbnew/tool_pcb.cpp:290 +msgid "Mode Track and Autorouting" +msgstr "Mode Pistes et Autoroutage" + +#: pcbnew/tool_pcb.cpp:296 +msgid "Fast access to theWeb Based FreeROUTE advanced router" +msgstr "Acces rapide au routeur avancé FreeROUTE sur le Web" + +#: pcbnew/tool_pcb.cpp:323 +msgid "Drc OFF" +msgstr "Drc DESACTIVEE" + +#: pcbnew/tool_pcb.cpp:326 +msgid "Display Grid OFF" +msgstr "Suppression de l'affichage de la grille" + +#: pcbnew/tool_pcb.cpp:329 +msgid "Display Polar Coord ON" +msgstr "Activer affichage coord Polaires" + +#: pcbnew/tool_pcb.cpp:332 +msgid "Units in inches" +msgstr "Unités en pouces" + +#: pcbnew/tool_pcb.cpp:335 +msgid "Units in millimeters" +msgstr "Unités en millimètres" + +#: pcbnew/tool_pcb.cpp:338 +msgid "Change Cursor Shape" +msgstr "Sélection de la forme du curseur" + +#: pcbnew/tool_pcb.cpp:343 +msgid "Show General Ratsnest" +msgstr "Montrer le chevelu général" + +#: pcbnew/tool_pcb.cpp:346 +msgid "Show Module Ratsnest when moving" +msgstr "Montrer le chevelu du module pendant déplacement" + +#: pcbnew/tool_pcb.cpp:352 +msgid "Enable Auto Del Track" +msgstr "Autoriser l'effacement automatique des pistes" + +#: pcbnew/tool_pcb.cpp:357 +msgid "Show filled areas in zones" +msgstr "Afficher les surfaces remplies dans les zones" + +#: pcbnew/tool_pcb.cpp:360 +msgid "Do not show filled areas in zones" +msgstr "Ne pas afficher les surfaces remplies dans les zones" + +#: pcbnew/tool_pcb.cpp:363 +msgid "Show outlines of filled areas only in zones" +msgstr "Afficher uniquement les contours des surfaces remplies dans les zones" + +#: pcbnew/tool_pcb.cpp:368 +msgid "Show Pads Sketch" +msgstr "Afficher pastilles en contour" + +#: pcbnew/tool_pcb.cpp:372 +msgid "Show Vias Sketch" +msgstr "Afficher Pastilles en Contour" + +#: pcbnew/tool_pcb.cpp:376 +msgid "Show Tracks Sketch" +msgstr "Afficher Pistes en Contour" + +#: pcbnew/tool_pcb.cpp:381 +msgid "High Contrast Mode Display" +msgstr "Mode d'affichage Haut Contraste" + +#: pcbnew/tool_pcb.cpp:388 +msgid "Show Invisible Text" +msgstr "Montrer textes invisibles" + +#: pcbnew/tool_pcb.cpp:399 +msgid "" +"Display/remove auxiliary vertical toolbar (tools for micro wave applications)\n" +" This is a experimental feature (under development)" +msgstr "" +"Affiche/supprime le toolbar vertical auxiliaire (outils pour applications micro-ondes)\n" +"C'est un outil expérimental (en cours de développement)" + +#: pcbnew/tool_pcb.cpp:429 +msgid "Net highlight" +msgstr "Surbrillance des équipotentielles" + +#: pcbnew/tool_pcb.cpp:434 +msgid "Display local ratsnest (pad or module)" +msgstr "Afficher le chevelu local (pastilles ou modules)" + +#: pcbnew/tool_pcb.cpp:440 +msgid "Add modules" +msgstr "Addition de Modules" + +#: pcbnew/tool_pcb.cpp:444 +msgid "Add tracks and vias" +msgstr "Ajouter pistes et vias" + +#: pcbnew/tool_pcb.cpp:448 +msgid "Add zones" +msgstr "Addition de Zones" + +#: pcbnew/tool_pcb.cpp:453 +msgid "Add graphic line or polygon" +msgstr "Addition de lignes ou polygones graphiques" + +#: pcbnew/tool_pcb.cpp:457 +msgid "Add graphic circle" +msgstr "Addition de graphiques (Cercle)" + +#: pcbnew/tool_pcb.cpp:461 +msgid "Add graphic arc" +msgstr "Addition de graphiques (Arc de Cercle)" + +#: pcbnew/tool_pcb.cpp:465 +msgid "Add text" +msgstr "Ajout de Texte" + +#: pcbnew/tool_pcb.cpp:470 +msgid "Add dimension" +msgstr "Ajout des cotes" + +#: pcbnew/tool_pcb.cpp:474 +msgid "Add layer alignment target" +msgstr "Ajouter Mire de superposition" + +#: pcbnew/tool_pcb.cpp:479 +msgid "Delete items" +msgstr "Suppression d'éléments" + +#: pcbnew/tool_pcb.cpp:484 +msgid "Offset adjust for drill and place files" +msgstr "Ajuste offset pour fichier de perçage et placement" + +#: pcbnew/tool_pcb.cpp:510 +msgid "Create line of specified length for microwave applications" +msgstr "Création de lignes de longueur spécifiée (pour applications micro-ondes)" + +#: pcbnew/tool_pcb.cpp:514 +msgid "Create gap of specified length for microwave applications" +msgstr "Création de gaps de longueur spécifiée (pour applications micro-ondes)" + +#: pcbnew/tool_pcb.cpp:520 +msgid "Create stub of specified length for microwave applications" +msgstr "Création de stub de longueur spécifiée (pour applications micro-ondes)" + +#: pcbnew/tool_pcb.cpp:524 +msgid "Create stub (arc) of specified length for microwave applications" +msgstr "Création de stub (arc) de longueur spécifiée (pour applications micro-ondes)" + +#: pcbnew/tool_pcb.cpp:529 +msgid "Create a polynomial shape for microwave applications" +msgstr "Création de formes polynomiales (pour applications micro-ondes)" + +#: pcbnew/tool_pcb.cpp:585 +msgid "Current NetClass clearance value" +msgstr "Valeur isolation NetClass courante" + +#: pcbnew/tool_pcb.cpp:595 +msgid "Name of the current NetClass" +msgstr "Nom de la NetClass courante" + +#: pcbnew/tool_pcb.cpp:601 +msgid "" +"Auto track width: when starting on an existing track use its width\n" +"otherwise, use current width setting" +msgstr "" +"Largeur de piste automatique: si on démarre sur une piste existante, utiliser sa largeur\n" +" sinon utiliser la largeur courante" + +#: pcbnew/tool_pcb.cpp:618 +msgid "Auto" +msgstr "Auto" + +#: pcbnew/tool_pcb.cpp:622 +msgid "Zoom " +msgstr "Zoom " + +#: pcbnew/tool_pcb.cpp:642 +msgid "Grid" +msgstr "Grille" + +#: pcbnew/tool_pcb.cpp:660 +msgid "User Grid" +msgstr "Grille perso" + +#: pcbnew/tool_pcb.cpp:769 +msgid "+/- to switch" +msgstr "+/- pour commuter" #: pcbnew/find.cpp:117 msgid "Marker found" @@ -1612,6 +1584,27 @@ msgstr "Effacer Couche" msgid "Incorrect value for Via drill. No via drill change" msgstr "Valeur incorrecte pour perçage. Pas de changement pour la via" +#: pcbnew/set_color.cpp:276 +#: pcbnew/set_color.cpp:302 +msgid "Show None" +msgstr "Rien Afficher" + +#: pcbnew/set_color.cpp:285 +msgid "Show All" +msgstr "Tout Afficher" + +#: pcbnew/set_color.cpp:297 +msgid "Switch on all of the copper layers" +msgstr "Affiche toutes les couches cuivre" + +#: pcbnew/set_color.cpp:305 +msgid "Switch off all of the copper layers" +msgstr "N'affiche pas les couches cuivre" + +#: pcbnew/set_color.cpp:364 +msgid "Apply" +msgstr "Appliquer" + #: pcbnew/files.cpp:22 msgid "Printed circuit board" msgstr "Circuit imprimé" @@ -1673,6 +1666,44 @@ msgstr "Ecriture fichier CI: " msgid "Failed to create " msgstr "Impossible de créer fichier " +#: pcbnew/class_pcb_text.cpp:237 +msgid "COTATION" +msgstr "COTATION" + +#: pcbnew/class_pcb_text.cpp:239 +msgid "PCB Text" +msgstr "Texte PCB" + +#: pcbnew/class_pcb_text.cpp:241 +#: pcbnew/class_text_mod.cpp:497 +msgid "Layer" +msgstr "Couche" + +#: pcbnew/class_pcb_text.cpp:247 +#: pcbnew/class_text_mod.cpp:485 +msgid "No" +msgstr "Non" + +#: pcbnew/class_pcb_text.cpp:249 +#: pcbnew/class_text_mod.cpp:487 +msgid "Yes" +msgstr "Oui" + +#: pcbnew/class_pcb_text.cpp:252 +#: pcbnew/class_text_mod.cpp:506 +msgid "Orient" +msgstr "Orient" + +#: pcbnew/class_pcb_text.cpp:258 +#: pcbnew/class_text_mod.cpp:512 +msgid "H Size" +msgstr "Taille H" + +#: pcbnew/class_pcb_text.cpp:261 +#: pcbnew/class_text_mod.cpp:515 +msgid "V Size" +msgstr "Taille V" + #: pcbnew/cross-probing.cpp:60 #, c-format msgid "%s found" @@ -1714,27 +1745,6 @@ msgstr "Pas de mémoire pour autoroutage" msgid "Place Cells" msgstr "Place Cells" -#: pcbnew/set_color.cpp:261 -#: pcbnew/set_color.cpp:287 -msgid "Show None" -msgstr "Rien Afficher" - -#: pcbnew/set_color.cpp:270 -msgid "Show All" -msgstr "Tout Afficher" - -#: pcbnew/set_color.cpp:282 -msgid "Switch on all of the copper layers" -msgstr "Affiche toutes les couches cuivre" - -#: pcbnew/set_color.cpp:290 -msgid "Switch off all of the copper layers" -msgstr "N'affiche pas les couches cuivre" - -#: pcbnew/set_color.cpp:349 -msgid "Apply" -msgstr "Appliquer" - #: pcbnew/zones_by_polygon.cpp:309 #: pcbnew/zones_by_polygon.cpp:372 #: pcbnew/zones_by_polygon.cpp:710 @@ -1808,30 +1818,6 @@ msgstr "Erreur. Vous devez choisir une équipotentielle" msgid "You have chosen the \"not connected\" option. This will create insulated copper islands. Are you sure ?" msgstr "Vous avez choisi l'option \"non connecté\". Cela créera des blocs non connectés. Etes vous sûr ?" -#: pcbnew/class_edge_mod.cpp:235 -msgid "Seg" -msgstr "Seg" - -#: pcbnew/class_edge_mod.cpp:237 -msgid "Module" -msgstr "Module" - -#: pcbnew/class_edge_mod.cpp:238 -msgid "Value" -msgstr "Valeur" - -#: pcbnew/class_edge_mod.cpp:241 -msgid "TimeStamp" -msgstr "TimeStamp" - -#: pcbnew/class_edge_mod.cpp:243 -msgid "Mod Layer" -msgstr "Couche Mod." - -#: pcbnew/class_edge_mod.cpp:245 -msgid "Seg Layer" -msgstr "Couche Seg." - #: pcbnew/swap_layers.cpp:72 msgid "Swap Layers:" msgstr "Permutte couches" @@ -1846,9 +1832,30 @@ msgstr "Garder" msgid "Deselect this layer to select the No Change state" msgstr "Désélectionner cette couche pour restorer l'option Pas de Changement" -#: pcbnew/ioascii.cpp:175 -msgid "Error: Unexpected end of file !" -msgstr "Erreur: Fin de fichier inattendue !" +#: pcbnew/class_text_mod.cpp:467 +msgid "Ref." +msgstr "Ref." + +#: pcbnew/class_text_mod.cpp:467 +msgid "Value" +msgstr "Valeur" + +#: pcbnew/class_text_mod.cpp:467 +#: pcbnew/class_text_mod.cpp:476 +msgid "Text" +msgstr "Texte" + +#: pcbnew/class_text_mod.cpp:473 +msgid "Module" +msgstr "Module" + +#: pcbnew/class_text_mod.cpp:499 +msgid " No" +msgstr "Non" + +#: pcbnew/class_text_mod.cpp:501 +msgid " Yes" +msgstr "Oui" #: pcbnew/xchgmod.cpp:174 #, c-format @@ -2062,41 +2069,21 @@ msgstr "Le circuit actuel sera perdu et cette opération ne pourra pas être ann msgid "Current Footprint will be lost and this operation cannot be undone. Continue ?" msgstr "Le module actuel sera perdu et cette opération ne pourra pas être annulée. Continuer ?" -#: pcbnew/class_module.cpp:824 -msgid "Last Change" -msgstr "Last Change" +#: pcbnew/class_edge_mod.cpp:236 +msgid "Seg" +msgstr "Seg" -#: pcbnew/class_module.cpp:830 -msgid "Netlist path" -msgstr "Chemin Netliste " +#: pcbnew/class_edge_mod.cpp:242 +msgid "TimeStamp" +msgstr "TimeStamp" -#: pcbnew/class_module.cpp:847 -msgid "Pads" -msgstr "Pads" +#: pcbnew/class_edge_mod.cpp:244 +msgid "Mod Layer" +msgstr "Couche Mod." -#: pcbnew/class_module.cpp:855 -msgid "Stat" -msgstr "Stat" - -#: pcbnew/class_module.cpp:859 -msgid "Orient" -msgstr "Orient" - -#: pcbnew/class_module.cpp:868 -msgid "No 3D shape" -msgstr "Pas de forme 3D" - -#: pcbnew/class_module.cpp:869 -msgid "3D-Shape" -msgstr "Forme 3D" - -#: pcbnew/class_module.cpp:872 -msgid "Doc: " -msgstr "Doc: " - -#: pcbnew/class_module.cpp:873 -msgid "KeyW: " -msgstr "KeyW: " +#: pcbnew/class_edge_mod.cpp:246 +msgid "Seg Layer" +msgstr "Couche Seg." #: pcbnew/edgemod.cpp:191 msgid "The graphic item will be on a copper layer.It is very dangerous. Are you sure" @@ -2150,54 +2137,6 @@ msgstr "Erreur système sur écriture fichier \"%s\"" msgid "Error writing to STRINGFORMATTER" msgstr "Erreur d'écriture à STRINGFORMATTER" -#: pcbnew/class_zone.cpp:915 -msgid "Zone Outline" -msgstr "Contour de Zone" - -#: pcbnew/class_zone.cpp:919 -msgid "(Cutout)" -msgstr "(Cutout)" - -#: pcbnew/class_zone.cpp:941 -msgid "Not Found" -msgstr " Non Trouvé" - -#: pcbnew/class_zone.cpp:944 -msgid "NetName" -msgstr "NetName" - -#: pcbnew/class_zone.cpp:947 -msgid "Non Copper Zone" -msgstr "Zone non Cuivre" - -#: pcbnew/class_zone.cpp:952 -msgid "NetCode" -msgstr "NetCode" - -#: pcbnew/class_zone.cpp:960 -msgid "Corners" -msgstr "Sommets" - -#: pcbnew/class_zone.cpp:964 -msgid "Segments" -msgstr "Segments" - -#: pcbnew/class_zone.cpp:966 -msgid "Polygons" -msgstr "Polygones" - -#: pcbnew/class_zone.cpp:967 -msgid "Fill mode" -msgstr "Mode de remplissage" - -#: pcbnew/class_zone.cpp:972 -msgid "Hatch lines" -msgstr "Lignes de Hachure" - -#: pcbnew/class_zone.cpp:978 -msgid "Corners in DrawList" -msgstr "Sommets en Liste de dessin" - #: pcbnew/sel_layer.cpp:93 msgid "Select Layer:" msgstr "Sélection couche:" @@ -2367,12 +2306,12 @@ msgid "Vias Options:" msgstr "Options Vias:" #: pcbnew/dialog_track_options_base.cpp:76 -msgid "Through Via" -msgstr "Via Traversante" +msgid "Through via" +msgstr "Via traversante" #: pcbnew/dialog_track_options_base.cpp:76 -msgid "Blind or Buried Via" -msgstr "Via enterrée ou Aveugle" +msgid "Blind or buried via" +msgstr "Via enterrée ou aveugle" #: pcbnew/dialog_track_options_base.cpp:78 msgid "Default Via Type" @@ -2387,12 +2326,12 @@ msgstr "" "Via traversante est la sélection usuelle." #: pcbnew/dialog_track_options_base.cpp:87 -msgid "Do Not Allow Micro Vias" -msgstr "Ne pas Autoriser les Micro Vias" +msgid "Do not allow micro vias" +msgstr "Ne pas autoriser les micro vias" #: pcbnew/dialog_track_options_base.cpp:87 -msgid "Allow Micro Vias" -msgstr "Autoriser les Micro Vias" +msgid "Allow micro vias" +msgstr "Autoriser les micro vias" #: pcbnew/dialog_track_options_base.cpp:91 msgid "" @@ -2801,6 +2740,10 @@ msgstr "Ajuster largeur des pistes et diamètre de vias" msgid "Texts and Drawings" msgstr "Textes et Tracés" +#: pcbnew/menubarpcb.cpp:243 +msgid "Pads" +msgstr "Pads" + #: pcbnew/menubarpcb.cpp:244 msgid "Adjust size,shape,layers... for pads" msgstr "Ajuster taille, forme, couches... pour pads" @@ -2997,7 +2940,6 @@ msgid "Delete Pad (module %s %s) " msgstr "Effacer Pad (module %s %s) " #: pcbnew/modules.cpp:82 -#: pcbnew/librairi.cpp:523 msgid "Name:" msgstr "Nom:" @@ -3178,45 +3120,72 @@ msgstr "Librairie existante " msgid "Create error " msgstr "Erreur en création " -#: pcbnew/class_text_mod.cpp:459 -msgid "Ref." -msgstr "Ref." +#: pcbnew/class_zone.cpp:915 +#: pcbnew/class_board_item.cpp:135 +msgid "Zone Outline" +msgstr "Contour de Zone" -#: pcbnew/class_text_mod.cpp:459 -#: pcbnew/class_text_mod.cpp:468 -#: pcbnew/class_board_item.cpp:105 -msgid "Text" -msgstr "Texte" +#: pcbnew/class_zone.cpp:919 +#: pcbnew/class_board_item.cpp:140 +msgid "(Cutout)" +msgstr "(Cutout)" -#: pcbnew/class_text_mod.cpp:477 -msgid "No" -msgstr "Non" +#: pcbnew/class_zone.cpp:941 +#: pcbnew/class_board_item.cpp:163 +msgid "Not Found" +msgstr " Non Trouvé" -#: pcbnew/class_text_mod.cpp:479 -msgid "Yes" -msgstr "Oui" +#: pcbnew/class_zone.cpp:944 +msgid "NetName" +msgstr "NetName" -#: pcbnew/class_text_mod.cpp:491 -msgid " No" -msgstr "Non" +#: pcbnew/class_zone.cpp:947 +msgid "Non Copper Zone" +msgstr "Zone non Cuivre" -#: pcbnew/class_text_mod.cpp:493 -msgid " Yes" -msgstr "Oui" +#: pcbnew/class_zone.cpp:952 +msgid "NetCode" +msgstr "NetCode" -#: pcbnew/class_text_mod.cpp:504 -msgid "H Size" -msgstr "Taille H" +#: pcbnew/class_zone.cpp:960 +msgid "Corners" +msgstr "Sommets" -#: pcbnew/class_text_mod.cpp:507 -msgid "V Size" -msgstr "Taille V" +#: pcbnew/class_zone.cpp:964 +msgid "Segments" +msgstr "Segments" + +#: pcbnew/class_zone.cpp:966 +msgid "Polygons" +msgstr "Polygones" + +#: pcbnew/class_zone.cpp:967 +msgid "Fill mode" +msgstr "Mode de remplissage" + +#: pcbnew/class_zone.cpp:972 +msgid "Hatch lines" +msgstr "Lignes de Hachure" + +#: pcbnew/class_zone.cpp:978 +msgid "Corners in DrawList" +msgstr "Sommets en Liste de dessin" #: pcbnew/class_board_item.cpp:24 #: pcbnew/dialog_pad_properties_base.cpp:44 msgid "Rect" msgstr "Rect" +#: pcbnew/class_board_item.cpp:25 +msgid "Arc" +msgstr "Arc" + +#: pcbnew/class_board_item.cpp:26 +#: pcbnew/dialog_pad_properties_base.cpp:44 +#: pcbnew/dialog_pad_properties_base.cpp:53 +msgid "Circle" +msgstr "Cercle" + #: pcbnew/class_board_item.cpp:27 msgid "Bezier Curve" msgstr "Courbe de Bezier" @@ -3320,21 +3289,22 @@ msgstr "Mire" msgid "size" msgstr "dimension" -#: pcbnew/edit_track_width.cpp:153 -msgid "Change track width (entire NET) ?" -msgstr "Change largeur piste ( NET complet) ?" +#: pcbnew/edit_track_width.cpp:180 +#, c-format +msgid "Set tracks and vias sizes to the Netclass \"%s\"default value (entire NET \"%s\") ?" +msgstr "" -#: pcbnew/edit_track_width.cpp:203 -msgid "Edit All Tracks and Vias Sizes" -msgstr "Editer TOUTES Pistes et Vias" +#: pcbnew/edit_track_width.cpp:232 +msgid "Set All Tracks and Vias to Netclass value" +msgstr "Ajuster TOUTES Pistes et Vias à la valeur en Netclass" -#: pcbnew/edit_track_width.cpp:208 -msgid "Edit All Via Sizes" -msgstr "Editer TOUTES Vias" +#: pcbnew/edit_track_width.cpp:237 +msgid "Set All Via to Netclass value" +msgstr "Ajuster Toutes les Vias à la Valeur en NetClass" -#: pcbnew/edit_track_width.cpp:213 -msgid "Edit All Track Sizes" -msgstr "Editer TOUTES Pistes" +#: pcbnew/edit_track_width.cpp:242 +msgid "Set All Track to Netclass value" +msgstr "Ajuster Toutes les Pistes à la Valeur en NetClass" #: pcbnew/dialog_non_copper_zones_properties_base.cpp:28 #: pcbnew/dialog_copper_zones_base.cpp:38 @@ -3692,6 +3662,7 @@ msgid "Pad Type:" msgstr "Type Pad:" #: pcbnew/dialog_pad_properties_base.cpp:102 +#: pcbnew/dialog_SVG_print_base.cpp:23 msgid "Layers:" msgstr "Couches:" @@ -4012,29 +3983,38 @@ msgstr "Le fichier Session a une 'reference' à un composant non existant \"%s\" msgid "A wire_via references a missing padstack \"%s\"" msgstr "Une piste ou via a une référence vers un pad \"%s\" manquant" -#: pcbnew/class_track.cpp:988 -msgid "Flags" -msgstr "Flags" +#: pcbnew/pcbcfg.cpp:82 +msgid "Read Project File" +msgstr "Lire Fichier Projet" -#: pcbnew/class_track.cpp:1026 -msgid "Diam" -msgstr "Diam" +#: pcbnew/pcbcfg.cpp:92 +#, c-format +msgid "File %s not found" +msgstr "Fichier %s non trouvé" -#: pcbnew/class_track.cpp:1034 -msgid "Drill" -msgstr "Perçage" +#: pcbnew/pcbcfg.cpp:227 +msgid "Save Project File" +msgstr "Sauver Fichier Projet" -#: pcbnew/class_track.cpp:1038 -msgid "(Specific)" -msgstr "(Specifique)" +#: pcbnew/ioascii.cpp:175 +msgid "Error: Unexpected end of file !" +msgstr "Erreur: Fin de fichier inattendue !" -#: pcbnew/class_track.cpp:1040 -msgid "(Default)" -msgstr "(Défaut)" +#: pcbnew/class_drawsegment.cpp:373 +msgid "Shape" +msgstr "Forme" -#: pcbnew/class_track.cpp:1052 -msgid "Net Class" -msgstr "Classe d'Equipot" +#: pcbnew/class_drawsegment.cpp:384 +msgid "Angle" +msgstr "Angle" + +#: pcbnew/class_drawsegment.cpp:387 +msgid "Curve" +msgstr "Courbe" + +#: pcbnew/class_drawsegment.cpp:391 +msgid "Segment" +msgstr "Segment" #: pcbnew/gen_modules_placefile.cpp:134 msgid "No Modules for Automated Placement" @@ -4052,19 +4032,6 @@ msgstr "Fichier placement côté cuivre:" msgid "Module count" msgstr "Nb Modules" -#: pcbnew/pcbcfg.cpp:82 -msgid "Read Project File" -msgstr "Lire Fichier Projet" - -#: pcbnew/pcbcfg.cpp:92 -#, c-format -msgid "File %s not found" -msgstr "Fichier %s non trouvé" - -#: pcbnew/pcbcfg.cpp:223 -msgid "Save Project File" -msgstr "Sauver Fichier Projet" - #: pcbnew/dialog_edit_module_text_base.cpp:19 #, c-format msgid "Module %s (%s) orient %.1f" @@ -4349,13 +4316,98 @@ msgstr "Pistes Magnétiques" msgid "Control the capture of the pcb cursor when the mouse cursor enters a track" msgstr "Contrôle la capture du curseur pcb quand le curseur souris passe sur une piste" -#: pcbnew/class_pcb_text.cpp:236 -msgid "COTATION" -msgstr "COTATION" +#: pcbnew/toolbars_update_user_interface.cpp:38 +msgid " mils" +msgstr " mils" -#: pcbnew/class_pcb_text.cpp:238 -msgid "PCB Text" -msgstr "Texte PCB" +#: pcbnew/toolbars_update_user_interface.cpp:40 +msgid " mm" +msgstr " mm" + +#: pcbnew/toolbars_update_user_interface.cpp:53 +msgid "NetClass: " +msgstr "NetClass: " + +#: pcbnew/toolbars_update_user_interface.cpp:94 +#: pcbnew/toolbars_update_user_interface.cpp:109 +msgid " *" +msgstr " *" + +#: pcbnew/toolbars_update_user_interface.cpp:198 +msgid "DRC Off (Disable !!!), Currently: DRC is active" +msgstr "DRC off (désactivée !!!), actuellement DRC active" + +#: pcbnew/toolbars_update_user_interface.cpp:200 +msgid "DRC On (Currently: DRC is inactive !!!)" +msgstr "DRC On (Actuellement, DRC désactivée !!!)" + +#: pcbnew/toolbars_update_user_interface.cpp:211 +msgid "Polar coords not show" +msgstr "Coord Polaires non affichées" + +#: pcbnew/toolbars_update_user_interface.cpp:212 +msgid "Display polar coords" +msgstr "Affichage coord Polaires" + +#: pcbnew/toolbars_update_user_interface.cpp:217 +msgid "Show grid" +msgstr "Afficher grille" + +#: pcbnew/toolbars_update_user_interface.cpp:226 +msgid "Hide general ratsnest" +msgstr "Ne pas afficher le chevelu général" + +#: pcbnew/toolbars_update_user_interface.cpp:227 +msgid "Show general ratsnest" +msgstr "Afficher le chevelu général" + +#: pcbnew/toolbars_update_user_interface.cpp:233 +msgid "Hide module ratsnest" +msgstr "Ne pas montrer le chevelu du module" + +#: pcbnew/toolbars_update_user_interface.cpp:234 +msgid "Show module ratsnest" +msgstr "Montrer le chevelu du module" + +#: pcbnew/toolbars_update_user_interface.cpp:241 +msgid "Disable auto delete old track" +msgstr "Ne pas Autoriser l'effacement automatique des pistes" + +#: pcbnew/toolbars_update_user_interface.cpp:242 +msgid "Enable auto delete old track" +msgstr "Autoriser l'effacement automatique des pistes" + +#: pcbnew/toolbars_update_user_interface.cpp:249 +msgid "Show pads sketch mode" +msgstr "Afficher pastilles en mode contour" + +#: pcbnew/toolbars_update_user_interface.cpp:257 +msgid "Show vias sketch mode" +msgstr "Afficher vias en mode contour" + +#: pcbnew/toolbars_update_user_interface.cpp:265 +msgid "Show tracks sketch mode" +msgstr "Afficher pistes en mode contour" + +#: pcbnew/toolbars_update_user_interface.cpp:266 +msgid "Show tracks filled mode" +msgstr "Afficher pistes en mode plein" + +#: pcbnew/toolbars_update_user_interface.cpp:272 +msgid "Normal contrast mode display" +msgstr "Mode d'affichage contraste normal" + +#: pcbnew/toolbars_update_user_interface.cpp:273 +msgid "High contrast mode display" +msgstr "Mode d'affichage haut contraste" + +#: pcbnew/toolbars_update_user_interface.cpp:279 +msgid "Hide invisible text" +msgstr "Cacher textes invisibles" + +#: pcbnew/toolbars_update_user_interface.cpp:280 +msgid "Show invisible text" +msgstr "Montrer textes invisibles" #: pcbnew/dialog_netlist.cpp:68 msgid "Netlist Selection:" @@ -4450,6 +4502,7 @@ msgid "Preview" msgstr "Prévisualisation" #: pcbnew/dialog_print_using_printer_base.cpp:125 +#: pcbnew/dialog_print_using_printer.cpp:465 msgid "Print" msgstr "Imprimer" @@ -4615,99 +4668,6 @@ msgstr "Net Code" msgid "Net Length" msgstr "Long. Net" -#: pcbnew/toolbars_update_user_interface.cpp:38 -msgid " mils" -msgstr " mils" - -#: pcbnew/toolbars_update_user_interface.cpp:40 -msgid " mm" -msgstr " mm" - -#: pcbnew/toolbars_update_user_interface.cpp:53 -msgid "NetClass: " -msgstr "NetClass: " - -#: pcbnew/toolbars_update_user_interface.cpp:94 -#: pcbnew/toolbars_update_user_interface.cpp:109 -msgid " *" -msgstr " *" - -#: pcbnew/toolbars_update_user_interface.cpp:198 -msgid "DRC Off (Disable !!!), Currently: DRC is active" -msgstr "DRC off (désactivée !!!), actuellement DRC active" - -#: pcbnew/toolbars_update_user_interface.cpp:200 -msgid "DRC On (Currently: DRC is inactive !!!)" -msgstr "DRC On (Actuellement, DRC désactivée !!!)" - -#: pcbnew/toolbars_update_user_interface.cpp:211 -msgid "Polar coords not show" -msgstr "Coord Polaires non affichées" - -#: pcbnew/toolbars_update_user_interface.cpp:212 -msgid "Display polar coords" -msgstr "Affichage coord Polaires" - -#: pcbnew/toolbars_update_user_interface.cpp:217 -msgid "Show grid" -msgstr "Afficher grille" - -#: pcbnew/toolbars_update_user_interface.cpp:226 -msgid "Hide general ratsnest" -msgstr "Ne pas afficher le chevelu général" - -#: pcbnew/toolbars_update_user_interface.cpp:227 -msgid "Show general ratsnest" -msgstr "Afficher le chevelu général" - -#: pcbnew/toolbars_update_user_interface.cpp:233 -msgid "Hide module ratsnest" -msgstr "Ne pas montrer le chevelu du module" - -#: pcbnew/toolbars_update_user_interface.cpp:234 -msgid "Show module ratsnest" -msgstr "Montrer le chevelu du module" - -#: pcbnew/toolbars_update_user_interface.cpp:241 -msgid "Disable auto delete old track" -msgstr "Ne pas Autoriser l'effacement automatique des pistes" - -#: pcbnew/toolbars_update_user_interface.cpp:242 -msgid "Enable auto delete old track" -msgstr "Autoriser l'effacement automatique des pistes" - -#: pcbnew/toolbars_update_user_interface.cpp:249 -msgid "Show pads sketch mode" -msgstr "Afficher pastilles en mode contour" - -#: pcbnew/toolbars_update_user_interface.cpp:257 -msgid "Show vias sketch mode" -msgstr "Afficher vias en mode contour" - -#: pcbnew/toolbars_update_user_interface.cpp:265 -msgid "Show tracks sketch mode" -msgstr "Afficher pistes en mode contour" - -#: pcbnew/toolbars_update_user_interface.cpp:266 -msgid "Show tracks filled mode" -msgstr "Afficher pistes en mode plein" - -#: pcbnew/toolbars_update_user_interface.cpp:272 -msgid "Normal contrast mode display" -msgstr "Mode d'affichage contraste normal" - -#: pcbnew/toolbars_update_user_interface.cpp:273 -msgid "High contrast mode display" -msgstr "Mode d'affichage haut contraste" - -#: pcbnew/toolbars_update_user_interface.cpp:278 -msgid "Show invisible text" -msgstr "Montrer textes invisibles" - -#: pcbnew/toolbars_update_user_interface.cpp:279 -msgid "Hide invisible text" -msgstr "Cacher textes invisibles" - #: pcbnew/dialog_orient_footprints.cpp:138 msgid "Orientation:" msgstr "Orientation:" @@ -5042,8 +5002,8 @@ msgid "Place Micro Via" msgstr "Place Micro Via" #: pcbnew/onrightclick.cpp:509 -msgid "Change Width" -msgstr "Change Largeur" +msgid "Change Tracks and Vias Sizes" +msgstr "Changer Taille Pistes et Vias" #: pcbnew/onrightclick.cpp:511 msgid "Change Via Size" @@ -5058,20 +5018,20 @@ msgid "Change Track Width" msgstr "Change Largeur Piste" #: pcbnew/onrightclick.cpp:517 -msgid "Change Net" -msgstr "Change Net" +msgid "Set Net to NetClass values" +msgstr "Ajuster le Net à la Valeur en NetClass" #: pcbnew/onrightclick.cpp:519 -msgid "Change ALL Tracks and Vias" -msgstr "Changer TOUTES Pistes et Vias" +msgid "Set ALL Tracks and Vias to NetClass Values" +msgstr "Ajuster TOUTES Pistes et Vias aux Valeurs en NetClass" #: pcbnew/onrightclick.cpp:521 -msgid "Change ALL Vias (No Track)" -msgstr "Changer TOUTES Vias (Pas les Pistes)" +msgid "Set ALL Vias (No Track)to NetClass Values" +msgstr "Ajuster TOUTES Vias (pas les Pistes) aux Valeurs en NetClass" #: pcbnew/onrightclick.cpp:523 -msgid "Change ALL Tracks (No Via)" -msgstr "Changer TOUTES Pistes (Pas les Vias)" +msgid "Set ALL Tracks (No Via)to NetClass Values" +msgstr "Ajuster TOUTES Pistes (pas les Vias) aux Valeurs en NetClass" #: pcbnew/onrightclick.cpp:531 msgid "Delete Via" @@ -5349,7 +5309,6 @@ msgid "Footprint documentation file" msgstr "Fichier documentation des modules" #: pcbnew/dialog_pcbnew_config_libs_and_paths_fbp.cpp:61 -#: pcbnew/dialog_exchange_modules_base.cpp:68 msgid "Browse" msgstr "Examiner" @@ -5394,6 +5353,43 @@ msgstr "Il y a un problème d'impression" msgid "Print page %d" msgstr "Imprimer page %d" +#: pcbnew/class_track.cpp:951 +msgid "Flags" +msgstr "Flags" + +#: pcbnew/class_track.cpp:963 +msgid "Stat" +msgstr "Stat" + +#: pcbnew/class_track.cpp:986 +msgid "Diam" +msgstr "Diam" + +#: pcbnew/class_track.cpp:993 +#: pcbnew/class_pad.cpp:577 +msgid "Drill" +msgstr "Perçage" + +#: pcbnew/class_track.cpp:997 +msgid "(Specific)" +msgstr "(Specifique)" + +#: pcbnew/class_track.cpp:999 +msgid "(Default)" +msgstr "(Défaut)" + +#: pcbnew/class_track.cpp:1012 +msgid "Net Class" +msgstr "Classe d'Equipot" + +#: pcbnew/class_track.cpp:1019 +msgid "Seg Len" +msgstr "Long. Seg." + +#: pcbnew/class_track.cpp:1028 +msgid "Track Len" +msgstr "Long. Piste" + #: pcbnew/class_pad.cpp:380 msgid "Unknown Pad shape" msgstr "Forme Pad inconnue" @@ -5418,7 +5414,7 @@ msgstr "X Pos" msgid "Y pos" msgstr "Y pos" -#: pcbnew/editrack-part2.cpp:109 +#: pcbnew/editrack-part2.cpp:110 msgid "Drc error, cancelled" msgstr "Erreur DRC, annulation" @@ -5544,10 +5540,12 @@ msgid "3D settings" msgstr "3D Caract" #: pcbnew/dialog_edit_module_for_Modedit.cpp:83 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:205 msgid "Use this attribute for most non smd components" msgstr "Utiliser cet attribut pour la plupart des composants" #: pcbnew/dialog_edit_module_for_Modedit.cpp:86 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:208 msgid "" "Use this attribute for smd components.\n" "Only components with this option are put in the footprint position list file" @@ -5556,30 +5554,37 @@ msgstr "" "Seuls les composants avec cette option sont mis dans le fichier de position des composants" #: pcbnew/dialog_edit_module_for_Modedit.cpp:89 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:211 msgid "Use this attribute for \"virtual\" components drawn on board (like a old ISA PC bus connector)" msgstr "Uiliser cet attribut pour les composants \"virtuels\" directement dessinés sur le PCB (tel que les vieux connecteurs ISA de PC)" #: pcbnew/dialog_edit_module_for_Modedit.cpp:115 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:237 msgid "Enable hotkey move commands and Auto Placement" msgstr "Autoriser les commandes clavier de déplacement et l'auto placement" #: pcbnew/dialog_edit_module_for_Modedit.cpp:116 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:238 msgid "Disable hotkey move commands and Auto Placement" msgstr "Interdire les commandes clavier de déplacement et l'auto placement" #: pcbnew/dialog_edit_module_for_Modedit.cpp:125 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:247 msgid "Shape Scale:" msgstr "Echelle de la forme:" #: pcbnew/dialog_edit_module_for_Modedit.cpp:129 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:251 msgid "Shape Offset:" msgstr "Offset forme:" #: pcbnew/dialog_edit_module_for_Modedit.cpp:133 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:255 msgid "Shape Rotation:" msgstr "Rot de la forme" #: pcbnew/dialog_edit_module_for_Modedit.cpp:237 +#: pcbnew/dialog_edit_module_for_BoardEditor.cpp:359 msgid "3D Shape:" msgstr "Forme 3D:" @@ -6069,6 +6074,30 @@ msgstr "Designation" msgid "Supplier and ref" msgstr "Fournisseur et ref" +#: pcbnew/class_module.cpp:824 +msgid "Last Change" +msgstr "Last Change" + +#: pcbnew/class_module.cpp:830 +msgid "Netlist path" +msgstr "Chemin Netliste " + +#: pcbnew/class_module.cpp:868 +msgid "No 3D shape" +msgstr "Pas de forme 3D" + +#: pcbnew/class_module.cpp:869 +msgid "3D-Shape" +msgstr "Forme 3D" + +#: pcbnew/class_module.cpp:872 +msgid "Doc: " +msgstr "Doc: " + +#: pcbnew/class_module.cpp:873 +msgid "KeyW: " +msgstr "KeyW: " + #: eeschema/pinedit.cpp:25 msgid "line" msgstr "Ligne" @@ -7246,6 +7275,7 @@ msgid "Deselect current tool" msgstr "Désélection outil courant" #: eeschema/tool_lib.cpp:43 +#: eeschema/libframe.cpp:623 msgid "Add pin" msgstr "Addition de \"pins\"" @@ -7254,14 +7284,17 @@ msgid "Add graphic text" msgstr "Addition de textes graphiques (commentaires)" #: eeschema/tool_lib.cpp:51 +#: eeschema/libframe.cpp:649 msgid "Add rectangle" msgstr "Ajout de rectangle" #: eeschema/tool_lib.cpp:55 +#: eeschema/libframe.cpp:653 msgid "Add circle" msgstr "Ajout de cercle" #: eeschema/tool_lib.cpp:59 +#: eeschema/libframe.cpp:657 msgid "Add arc" msgstr "Ajout d'arc" @@ -7908,18 +7941,26 @@ msgid "No Draw" msgstr "Invisible" #: eeschema/pinedit-dialog.cpp:215 +#: eeschema/class_pin.cpp:1225 +#: eeschema/dialog_edit_label_base.cpp:37 msgid "Right" msgstr "Droite" #: eeschema/pinedit-dialog.cpp:216 +#: eeschema/class_pin.cpp:1221 +#: eeschema/dialog_edit_label_base.cpp:37 msgid "Left" msgstr "Gauche" #: eeschema/pinedit-dialog.cpp:217 +#: eeschema/class_pin.cpp:1213 +#: eeschema/dialog_edit_label_base.cpp:37 msgid "Up" msgstr "Haut" #: eeschema/pinedit-dialog.cpp:218 +#: eeschema/class_pin.cpp:1217 +#: eeschema/dialog_edit_label_base.cpp:37 msgid "Down" msgstr "Bas" @@ -8059,7 +8100,7 @@ msgstr "Invisible" #: eeschema/class_pin.cpp:1229 msgid "Unknown" -msgstr "" +msgstr "Inconnu" #: eeschema/tool_sch.cpp:37 msgid "Open schematic project" @@ -8213,19 +8254,19 @@ msgstr "U" #: eeschema/dialog_lib_new_component_base.cpp:76 msgid "Number of &parts per package:" -msgstr "" +msgstr "Nombre de &parts par boitier" #: eeschema/dialog_lib_new_component_base.cpp:97 msgid "Create component with &alternate body style (DeMorgan)" -msgstr "" +msgstr "Créer un composant avec une forme &alternative (DeMorgan)" #: eeschema/dialog_lib_new_component_base.cpp:109 msgid "Create component as power &symbol" msgstr "Créer composant comme &symbole d'alimentation" #: eeschema/dialog_lib_new_component_base.cpp:121 -msgid "Prevent drawing items from being &moved" -msgstr "" +msgid "Parts in package cannot be swapped" +msgstr "Les parts du boitier ne peuvent pas être interchangées" #: eeschema/dialog_lib_new_component_base.cpp:130 msgid "Global Pin Settings" @@ -8233,7 +8274,7 @@ msgstr "Parametres Globaux des Pins" #: eeschema/dialog_lib_new_component_base.cpp:142 msgid "Pin text position &offset:" -msgstr "" +msgstr "Offset de position du text de la pin" #: eeschema/dialog_lib_new_component_base.cpp:152 msgid "mils" @@ -9894,7 +9935,6 @@ msgid " [no file]" msgstr " [pas de fichier]" #: cvpcb/menucfg.cpp:37 -#: cvpcb/tool_cvpcb.cpp:30 msgid "Open a NetList file" msgstr "Lire un Fichier Netliste" @@ -10697,14 +10737,11 @@ msgid "%d errors while reading Gerber file [%s]" msgstr "%d erreurs pendant lecture fichier gerber [%s]" #: gerbview/readgerb.cpp:274 -#: gerbview/files.cpp:203 -#: gerbview/files.cpp:238 #, c-format msgid "Gerber DCODE files (%s)|*.%s" msgstr "Fichiers Gerber DCODE (%s)|*.%s" #: gerbview/readgerb.cpp:278 -#: gerbview/files.cpp:208 msgid "Load GERBER DCODE File" msgstr "Charger Fichier de DCodes" @@ -10738,6 +10775,14 @@ msgstr "Effacer Textes Pcb" msgid "Delete Layer %d" msgstr "Effacer Couche %d" +#: gerbview/set_color.cpp:271 +msgid "Switch on all of the Gerber layers" +msgstr "Affiche toutes les couches Gerber" + +#: gerbview/set_color.cpp:279 +msgid "Switch off all of the Gerber layers" +msgstr "N'affiche pas les couches Gerber" + #: gerbview/files.cpp:84 msgid "Not yet available..." msgstr "non encore disponible" @@ -10967,6 +11012,7 @@ msgid "Find D-codes" msgstr "Chercher DCodes" #: gerbview/tool_gerber.cpp:244 +#: gerbview/select_layers_to_pcb.cpp:220 msgid "Layer " msgstr "Couche " @@ -11088,14 +11134,6 @@ msgstr "Nom Fichier C.I.:" msgid "Ok to change the existing file ?" msgstr "D'accord pour changer le fichier existant ?" -#: gerbview/set_color.cpp:271 -msgid "Switch on all of the Gerber layers" -msgstr "Affiche toutes les couches Gerber" - -#: gerbview/set_color.cpp:279 -msgid "Switch off all of the Gerber layers" -msgstr "N'affiche pas les couches Gerber" - #: gerbview/gerbview_config.cpp:26 msgid "GerbView project files (.cnf)|*.cnf" msgstr "Fichiers projet GerbView (.cnf)|*.cnf" @@ -11492,6 +11530,10 @@ msgstr "??? Via" msgid "Blind/Buried Via" msgstr "Via Aveugle/Enterrée" +#: common/pcbcommon.cpp:64 +msgid "Through Via" +msgstr "Via Traversante" + #: common/pcbcommon.cpp:82 msgid "Kicad footprint library files (*.mod)|*.mod" msgstr "Fichiers Modules Kicad (*.mod)|*.mod" @@ -11885,66 +11927,66 @@ msgstr "Options Générales" msgid "Pad Properties" msgstr "Propriétés du Pad" +#: pcbnew/dialog_edit_module_text_base.h:63 +msgid "Footprint text properties" +msgstr "Propriétés du texte du module" + #: pcbnew/set_color.h:36 msgid "Pcbnew Layer Colors:" msgstr "Pcbnew: Couleur des Couches" -#: pcbnew/set_color.h:79 +#: pcbnew/set_color.h:89 msgid "Copper Layers" msgstr "Couches Cuivre." -#: pcbnew/set_color.h:214 +#: pcbnew/set_color.h:224 msgid "Tech Layers" msgstr "Couches Tech." -#: pcbnew/set_color.h:325 +#: pcbnew/set_color.h:335 msgid "Others" msgstr "Autres" -#: pcbnew/set_color.h:355 +#: pcbnew/set_color.h:366 msgid "Ratsnest" msgstr "Chevelu" -#: pcbnew/set_color.h:364 +#: pcbnew/set_color.h:375 msgid "Pad Cu" msgstr "Pad Cu" -#: pcbnew/set_color.h:372 +#: pcbnew/set_color.h:383 msgid "Pad Cmp" msgstr "Pad Cmp" -#: pcbnew/set_color.h:380 +#: pcbnew/set_color.h:391 msgid "Text Module Cu" msgstr "Texte Module Cu" -#: pcbnew/set_color.h:388 +#: pcbnew/set_color.h:399 msgid "Text Module Cmp" msgstr "Texte Module Cmp" -#: pcbnew/set_color.h:396 +#: pcbnew/set_color.h:407 msgid "Text Module invisible" msgstr "Texte Module invisible" -#: pcbnew/set_color.h:404 +#: pcbnew/set_color.h:415 msgid "Anchors" msgstr "Ancres" -#: pcbnew/set_color.h:421 +#: pcbnew/set_color.h:432 msgid "Show Noconnect" msgstr "Montrer Non Conn" -#: pcbnew/set_color.h:430 +#: pcbnew/set_color.h:441 msgid "Show Modules Cmp" msgstr "Afficher Modules Cmp" -#: pcbnew/set_color.h:439 +#: pcbnew/set_color.h:450 msgid "Show Modules Cu" msgstr "Afficher Modules Cu" -#: pcbnew/dialog_edit_module_text_base.h:63 -msgid "Footprint text properties" -msgstr "Propriétés du texte du module" - #: pcbnew/dialog_drc_base.h:98 msgid "DRC Control" msgstr "Contrôle DRC" @@ -11954,6 +11996,7 @@ msgid "Exchange Modules" msgstr "Echange modules:" #: pcbnew/dialog_edit_module_for_Modedit_base.h:88 +#: pcbnew/dialog_edit_module_for_BoardEditor_base.h:102 msgid "Module properties" msgstr "Propriétés du Module" @@ -12257,6 +12300,17 @@ msgstr "DCodes id." msgid "Page Settings" msgstr "Ajustage opt Page" +#~ msgid "Change track width (entire NET) ?" +#~ msgstr "Change largeur piste ( NET complet) ?" +#~ msgid "Edit All Via Sizes" +#~ msgstr "Editer TOUTES Vias" +#~ msgid "Edit All Track Sizes" +#~ msgstr "Editer TOUTES Pistes" +#~ msgid "Change Width" +#~ msgstr "Change Largeur" +#~ msgid "Change Net" +#~ msgstr "Change Net" + #, fuzzy #~ msgid "Oriention" #~ msgstr "Orientation" @@ -12328,8 +12382,6 @@ msgstr "Ajustage opt Page" #~ msgstr "Couches" #~ msgid "Net classes:" #~ msgstr "Classes d'Equipotentielles:" -#~ msgid "Track size" -#~ msgstr "Largeur piste" #~ msgid "Vias size" #~ msgstr "Diamètre via" #~ msgid "Track Min Size" diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index d12c58f7eb..e92639fa08 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -97,6 +97,7 @@ set(PCBNEW_SRCS librairi.cpp loadcmp.cpp locate.cpp + magnetic_tracks_functions.cpp menubarmodedit.cpp menubarpcb.cpp mirepcb.cpp diff --git a/pcbnew/attribut.cpp b/pcbnew/attribut.cpp index 37017ae2d2..041d37f98a 100644 --- a/pcbnew/attribut.cpp +++ b/pcbnew/attribut.cpp @@ -46,7 +46,8 @@ void WinEDA_PcbFrame::Attribut_Track( TRACK* track, wxDC* DC, bool Flag_On ) return; DrawPanel->CursorOff( DC ); // Erase cursor shape - Track = Marque_Une_Piste( this, DC, track, &nb_segm, GR_OR | GR_SURBRILL ); + Track = Marque_Une_Piste( GetBoard(), track, &nb_segm, NULL, true ); + Trace_Une_Piste( DrawPanel, DC, Track, nb_segm, GR_OR | GR_SURBRILL ); for( ; (Track != NULL) && (nb_segm > 0); nb_segm-- ) { diff --git a/pcbnew/class_netinfo.h b/pcbnew/class_netinfo.h index 1cc6b76d77..97aa681325 100644 --- a/pcbnew/class_netinfo.h +++ b/pcbnew/class_netinfo.h @@ -208,7 +208,7 @@ public: return m_NetClassName; } -#if 0 +#if 1 /** * Function GetTrackWidth * returns the width of tracks used to route this net. @@ -220,16 +220,18 @@ public: } +#if 0 /** - * Function GetTrackWidth + * Function GetTrackMinWidth * returns the Minimum value for tracks thickness (used in DRC) */ - int GetTrackWidth() + int GetTrackMinWidth() { - wxASSERT( m_NetClass ); - return m_NetClass->GetTrackMinWidth(); +// wxASSERT( m_NetClass ); +// return m_NetClass->GetTrackMinWidth(); + return g_DesignSettings.m_TrackMinWidth; } - +#endif /** * Function GetViaSize @@ -238,7 +240,17 @@ public: int GetViaSize() { wxASSERT( m_NetClass ); - return m_NetClass->GetViaSize(); + return m_NetClass->GetViaDiameter(); + } + + /** + * Function GetMicroViaSize + * returns the size of vias used to route this net + */ + int GetMicroViaSize() + { + wxASSERT( m_NetClass ); + return m_NetClass->GetuViaDiameter(); } @@ -249,10 +261,22 @@ public: int GetViaDrillSize() { wxASSERT( m_NetClass ); - return m_NetClass->GetViaDrillSize(); + return m_NetClass->GetViaDrill(); + } + + /** + * Function GetViaDrillSize + * returns the size of via drills used to route this net + */ + int GetMicroViaDrillSize() + { + wxASSERT( m_NetClass ); + return m_NetClass->GetuViaDrill(); } + +#if 0 /** * Function GetViaMinSize * returns the Minimum value for via sizes (used in DRC) @@ -262,7 +286,7 @@ public: wxASSERT( m_NetClass ); return m_NetClass->GetViaMinSize(); } - +#endif /** * Function GetClearance diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index 5d98dd6db1..89ab7dbafd 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -14,32 +14,6 @@ #include "protos.h" -// #define RATSNET_DEBUG - -#ifdef RATSNET_DEBUG - -/**************************************/ -void DbgDisplayTrackInfos( TRACK* track ) -/**************************************/ - -/* Only for ratsnest debug - */ -{ - wxString msg; - - msg << wxT( "Netcode " ) << track->GetNet(); - msg << wxT( " - " ) << track->GetSubNet(); - msg << wxT( "\nptrS " ) << (unsigned) track->start; - msg << wxT( " ptrE " ) << (unsigned) track->end; - msg << wxT( " this " ) << (unsigned) track; - - wxMessageBox( msg ); -} - - -#endif - - /** * Function ShowClearance * tests to see if the clearance border is drawn on the given track. @@ -151,17 +125,27 @@ int TRACK::GetDrillValue() const return g_DesignSettings.m_ViaDrill; } +/** + * Function GetLength + * returns the position of this object. + * @return the length of the track segment (0 for a via). + */ +double TRACK::GetLength() +{ + wxPoint delta = m_End - m_Start; + return sqrt( (double)delta.x*delta.x + (double)delta.y*delta.y ); +} /***********************/ bool TRACK::IsNull() /***********************/ -// return TRUE if segment length = 0 +// return true if segment length = 0 { if( ( Type() != TYPE_VIA ) && ( m_Start == m_End ) ) - return TRUE; + return true; else - return FALSE; + return false; } @@ -272,27 +256,29 @@ EDA_Rect TRACK::GetBoundingBox() return ret; } + /** * Function Rotate * Rotate this object. * @param const wxPoint& aRotCentre - the rotation point. * @param aAngle - the rotation angle in 0.1 degree. */ -void TRACK::Rotate(const wxPoint& aRotCentre, int aAngle) +void TRACK::Rotate( const wxPoint& aRotCentre, int aAngle ) { RotatePoint( &m_Start, aRotCentre, aAngle ); RotatePoint( &m_End, aRotCentre, aAngle ); } + /** * Function Flip * Flip this object, i.e. change the board side for this object * @param const wxPoint& aCentre - the rotation point. */ -void TRACK::Flip(const wxPoint& aCentre ) +void TRACK::Flip( const wxPoint& aCentre ) { - m_Start.y = aCentre.y - (m_Start.y - aCentre.y); - m_End.y = aCentre.y - (m_End.y - aCentre.y); + m_Start.y = aCentre.y - (m_Start.y - aCentre.y); + m_End.y = aCentre.y - (m_End.y - aCentre.y); if( Type() == TYPE_VIA ) { } @@ -712,13 +698,13 @@ void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin angle = 900; // angle is in 0.1 degree if( panel->GetScreen()->Scale( tsize ) >= 6 ) { - if( !(!IsOnLayer( curr_layer )&& DisplayOpt.ContrastModeDisplay)){ - - tsize = (tsize * 8) / 10; // small reduction to give a better look - DrawGraphicText( panel, DC, tpos, - WHITE, net->GetShortNetname(), angle, wxSize( tsize, tsize ), - GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, - false, false ); + if( !(!IsOnLayer( curr_layer )&& DisplayOpt.ContrastModeDisplay) ) + { + tsize = (tsize * 8) / 10; // small reduction to give a better look + DrawGraphicText( panel, DC, tpos, + WHITE, net->GetShortNetname(), angle, wxSize( tsize, tsize ), + GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, + false, false ); } } } @@ -729,13 +715,14 @@ void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin void SEGVIA::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoint& notUsed ) /*******************************************************************************************/ { - int color; - int rayon; - int curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; + int color; + int rayon; + int curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; + + int fillvia = 0; + WinEDA_BasePcbFrame* frame = (WinEDA_BasePcbFrame*) panel->m_Parent; + PCB_SCREEN* screen = frame->GetScreen(); - int fillvia = 0; - WinEDA_BasePcbFrame* frame = (WinEDA_BasePcbFrame*) panel->m_Parent; - PCB_SCREEN* screen = frame->GetScreen(); if( frame->m_DisplayViaFill == FILLED ) fillvia = 1; @@ -907,7 +894,7 @@ void SEGVIA::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoi DrawGraphicText( panel, DC, m_Start, WHITE, net->GetShortNetname(), 0, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, - false, false); + false, false ); } } } @@ -917,12 +904,7 @@ void SEGVIA::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoi void TRACK::DisplayInfo( WinEDA_DrawFrame* frame ) { wxString msg; - int text_pos; - BOARD* board = ( (WinEDA_BasePcbFrame*)frame)->GetBoard(); - -#ifdef RATSNET_DEBUG - DbgDisplayTrackInfos( this ); -#endif + BOARD* board = ( (WinEDA_BasePcbFrame*) frame )->GetBoard(); frame->MsgPanel->EraseMsgBox(); @@ -943,18 +925,11 @@ void TRACK::DisplayInfo( WinEDA_DrawFrame* frame ) msg = wxT( "????" ); break; } - text_pos = 1; + frame->MsgPanel->AppendMessage( _( "Type" ), msg, DARKCYAN ); - Affiche_1_Parametre( frame, text_pos, _( "Type" ), msg, DARKCYAN ); - text_pos += 10; - - - if( Type() == TYPE_TRACK - || Type() == TYPE_ZONE - || Type() == TYPE_VIA ) + // Display Net Name (in pcbnew) + if( frame->m_Ident == PCB_FRAME ) { - /* Display NetName pour les segments de piste type cuivre */ - NETINFO_ITEM* net = board->FindNet( GetNet() ); if( net ) @@ -962,31 +937,18 @@ void TRACK::DisplayInfo( WinEDA_DrawFrame* frame ) else msg = wxT( "" ); - Affiche_1_Parametre( frame, text_pos, _( "NetName" ), msg, RED ); - text_pos += 20; + frame->MsgPanel->AppendMessage( _( "NetName" ), msg, RED ); /* Display net code : (usefull in test or debug) */ msg.Printf( wxT( "%d .%d" ), GetNet(), GetSubNet() ); - - Affiche_1_Parametre( frame, text_pos, _( "NetCode" ), msg, RED ); - text_pos += 8; - } - else - { - Affiche_1_Parametre( frame, text_pos, _( "Segment" ), wxEmptyString, RED ); - if( m_Shape == S_CIRCLE ) - Affiche_1_Parametre( frame, -1, wxEmptyString, _( "Circle" ), RED ); - else - Affiche_1_Parametre( frame, -1, wxEmptyString, _( "Standard" ), RED ); - text_pos += 8; + frame->MsgPanel->AppendMessage( _( "NetCode" ), msg, RED ); } #if defined(DEBUG) /* Display the flags */ msg.Printf( wxT( "0x%08X" ), m_Flags ); - Affiche_1_Parametre( frame, text_pos, _( "Flags" ), msg, BLUE ); - text_pos += 8; + frame->MsgPanel->AppendMessage( _( "Flags" ), msg, BLUE ); #endif @@ -998,8 +960,7 @@ void TRACK::DisplayInfo( WinEDA_DrawFrame* frame ) if( GetState( SEGM_AR ) ) msg[2] = 'A'; - Affiche_1_Parametre( frame, text_pos, _( "Stat" ), msg, MAGENTA ); - text_pos += 6; + frame->MsgPanel->AppendMessage( _( "Stat" ), msg, MAGENTA ); /* Display layer or layer pair) */ if( Type() == TYPE_VIA ) @@ -1014,8 +975,7 @@ void TRACK::DisplayInfo( WinEDA_DrawFrame* frame ) else msg = board->GetLayerName( m_Layer ); - Affiche_1_Parametre( frame, text_pos, _( "Layer" ), msg, BROWN ); - text_pos += 15; + frame->MsgPanel->AppendMessage( _( "Layer" ), msg, BROWN ); /* Display width */ valeur_param( (unsigned) m_Width, msg ); @@ -1023,8 +983,7 @@ void TRACK::DisplayInfo( WinEDA_DrawFrame* frame ) if( Type() == TYPE_VIA ) // Display Diam and Drill values { // Display diameter value: - Affiche_1_Parametre( frame, text_pos, _( "Diam" ), msg, DARKCYAN ); - text_pos += 8; + frame->MsgPanel->AppendMessage( _( "Diam" ), msg, DARKCYAN ); // Display drill value int drill_value = GetDrillValue(); @@ -1032,24 +991,41 @@ void TRACK::DisplayInfo( WinEDA_DrawFrame* frame ) valeur_param( (unsigned) drill_value, msg ); wxString title = _( "Drill" ); - title += wxT(" "); + title += wxT( " " ); if( m_Drill >= 0 ) title += _( "(Specific)" ); else title += _( "(Default)" ); - Affiche_1_Parametre( frame, text_pos, title, msg, RED ); + frame->MsgPanel->AppendMessage( title, msg, RED ); } else - Affiche_1_Parametre( frame, text_pos, _( "Width" ), msg, DARKCYAN ); - + { + frame->MsgPanel->AppendMessage( _( "Width" ), msg, DARKCYAN ); + } + NETCLASS* netclass = GetNetClass(); if( netclass ) { msg = netclass->GetName(); - text_pos += 10; - Affiche_1_Parametre( frame, text_pos, _( "Net Class" ), msg, DARKCYAN ); + frame->MsgPanel->AppendMessage( _( "Net Class" ), msg, DARKCYAN ); + } + + // Display segment length + if( Type() != TYPE_VIA ) // Display Diam and Drill values + { + valeur_param( wxRound( GetLength() ), msg ); + frame->MsgPanel->AppendMessage( _( "Seg Len" ), msg, DARKCYAN ); + } + + // Display full track length (in pcbnew) + if( frame->m_Ident == PCB_FRAME ) + { + int trackLen; + Marque_Une_Piste( board, this, NULL, &trackLen, false ); + valeur_param( trackLen, msg ); + frame->MsgPanel->AppendMessage( _( "Track Len" ), msg, DARKCYAN ); } } diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h index 8eb63e331f..ce99f52f6d 100644 --- a/pcbnew/class_track.h +++ b/pcbnew/class_track.h @@ -96,6 +96,13 @@ public: return m_Start; // it had to be start or end. } + /** + * Function GetLength + * returns the position of this object. + * @return the length of the track segment (0 for a via). + */ + double GetLength(); + EDA_Rect GetBoundingBox(); diff --git a/pcbnew/controle.cpp b/pcbnew/controle.cpp index bf20586a58..cab71e234b 100644 --- a/pcbnew/controle.cpp +++ b/pcbnew/controle.cpp @@ -10,11 +10,13 @@ #include "pcbnew.h" #include "wxPcbStruct.h" #include "protos.h" - #include "pcbnew_id.h" + #include "collectors.h" -#include "bitmaps.h" +//external funtions used here: +extern bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame, + int aCurrentTool, wxSize grid, wxPoint on_grid, wxPoint* curpos ); /*************************************************************************************/ static BOARD_ITEM* AllAreModulesAndReturnSmallestIfSo( GENERAL_COLLECTOR* aCollector ) @@ -220,265 +222,6 @@ BOARD_ITEM* WinEDA_BasePcbFrame::PcbGeneralLocateAndDisplay( int aHotKeyCode ) } -/** - * Function Join - * finds the point where line segment (b1,b0) intersects with segment (a1,a0). - * If that point would be outside of (a0,a1), the respective endpoint is used. - * Join returns the point in "res" and "true" if a suitable point was found, - * "false" if both lines are parallel or if the length of either segment is zero. - */ -static bool Join( wxPoint* res, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1 ) -{ - /* References: - http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ - http://www.gekkou.co.uk/blogs/monologues/2007/12/13/1197586800000.html - */ - - double denom; - double t; - - // if either segment is zero length - if( a1.x==a0.x && a1.y==a0.y ) - return false; - - if( b1.x==b0.x && b1.y==b0.y ) - return false; - - a1 -= a0; - b1 -= b0; - - b0 -= a0; - - denom = (double) b1.y * a1.x - (double) b1.x * a1.y; - if( !denom ) - { - return false; // parallel - } - - t = ((double) b1.y * b0.x - (double) b1.x * b0.y ) / denom; - - t = min( max( t, 0.0 ), 1.0 ); - - res->x = wxRound( a0.x + t * a1.x ); - res->y = wxRound( a0.y + t * a1.y ); - - return true; -} - - -/* - * "Project" finds the projection of a grid point on a track. This is the point - * from where we want to draw new orthogonal tracks when starting on a track. - */ -bool Project( wxPoint* res, wxPoint on_grid, const TRACK* track ) -{ - if( track->m_Start == track->m_End ) - return false; - - wxPoint vec = track->m_End - track->m_Start; - - double t = double( on_grid.x - track->m_Start.x ) * vec.x + - double( on_grid.y - track->m_Start.y ) * vec.y; - - t /= (double) vec.x * vec.x + (double) vec.y * vec.y; - t = min( max( t, 0.0 ), 1.0 ); - - res->x = wxRound( track->m_Start.x + t * vec.x ); - res->y = wxRound( track->m_Start.y + t * vec.y ); - - return true; -} - - -/** - * Function Magnetize - * tests to see if there are any magnetic items within near reach of the given - * "curpos". If yes, then curpos is adjusted appropriately according to that - * near magnetic item and true is returned. - * @param curpos The initial position, and what to adjust if a change is needed. - * @return bool - true if the position was adjusted magnetically, else false. - */ -static bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame, - int aCurrentTool, wxSize grid, wxPoint on_grid, wxPoint* curpos ) -{ - bool doCheckNet = g_MagneticPadOption != capture_always && Drc_On; - bool doTrack = false; - bool doPad = false; - bool amMovingVia = false; - - TRACK* currTrack = g_CurrentTrackSegment; - BOARD_ITEM* currItem = frame->GetCurItem(); - - // D( printf( "currTrack=%p currItem=%p currTrack->Type()=%d currItem->Type()=%d\n", currTrack, currItem, currTrack ? currTrack->Type() : 0, currItem ? currItem->Type() : 0 ); ) - - if( !currTrack && currItem && currItem->Type()==TYPE_VIA && currItem->m_Flags ) - { - // moving a VIA - currTrack = (TRACK*) currItem; - amMovingVia = true; - - return false; // comment this return out and play with it. - } - else if( currItem != currTrack ) - { - currTrack = NULL; - } - - - if( g_MagneticPadOption == capture_always ) - doPad = true; - - if( g_MagneticTrackOption == capture_always ) - doTrack = true; - - if( aCurrentTool == ID_TRACK_BUTT || amMovingVia ) - { - int q = capture_cursor_in_track_tool; - - if( g_MagneticPadOption == q ) - doPad = true; - - if( g_MagneticTrackOption == q ) - doTrack = true; - } - - // D(printf("doPad=%d doTrack=%d aCurrentTool=%d amMovingVia=%d\n", doPad, doTrack, aCurrentTool, amMovingVia );) - - // The search precedence order is pads, then tracks/vias - - if( doPad ) - { - D_PAD* pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE, TRUE ); - if( pad ) - { - if( doCheckNet && currTrack && currTrack->GetNet() != pad->GetNet() ) - return false; - - *curpos = pad->m_Pos; - return true; - } - } - - // after pads, only track & via tests remain, skip them if not desired - if( doTrack ) - { - int layer = ( (PCB_SCREEN*) ActiveScreen )->m_Active_Layer; - - for( TRACK* via = m_Pcb->m_Track; - via && (via = Locate_Via_Area( via, *curpos, layer )) != NULL; - via = via->Next() ) - { - if( via != currTrack ) // a via cannot influence itself - { - if( !doCheckNet || !currTrack || currTrack->GetNet() == via->GetNet() ) - { - *curpos = via->m_Start; - // D(printf("via hit\n");) - return true; - } - } - else - { - //D( printf( "skipping self\n" ); ) - } - } - - if( !currTrack ) - { - int layer_mask = g_TabOneLayerMask[layer]; - - TRACK* track = Locate_Pistes( m_Pcb->m_Track, layer_mask, CURSEUR_OFF_GRILLE ); - if( !track || track->Type() != TYPE_TRACK ) - { - // D(printf("!currTrack and track=%p not found, layer_mask=0x%X\n", track, layer_mask );) - return false; - } - - // D( printf( "Project\n" ); ) - return Project( curpos, on_grid, track ); - } - - /* - * In two segment mode, ignore the final segment if it's inside a grid - * square. - */ - if( !amMovingVia && currTrack && g_TwoSegmentTrackBuild && currTrack->Back() - && currTrack->m_Start.x - grid.x < currTrack->m_End.x - && currTrack->m_Start.x + grid.x > currTrack->m_End.x - && currTrack->m_Start.y - grid.y < currTrack->m_End.y - && currTrack->m_Start.y + grid.y > currTrack->m_End.y ) - { - currTrack = currTrack->Back(); - } - - - for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() ) - { - if( track->Type() != TYPE_TRACK ) - continue; - - if( doCheckNet && currTrack && currTrack->GetNet() != track->GetNet() ) - continue; - - if( g_DesignSettings.IsLayerVisible( track->GetLayer() ) == false ) - continue; - - // omit the layer check if moving a via - if( !amMovingVia && !track->IsOnLayer( layer ) ) - continue; - - if( !track->HitTest( *curpos ) ) - continue; - - D(printf( "have track prospect\n");) - - if( Join( curpos, track->m_Start, track->m_End, currTrack->m_Start, currTrack->m_End ) ) - { - // D(printf( "join currTrack->Type()=%d\n", currTrack->Type() );) - return true; - } - - if( aCurrentTool == ID_TRACK_BUTT || amMovingVia ) - { - // At this point we have a drawing mouse on a track, we are drawing - // a new track and that new track is parallel to the track the - // mouse is on. Find the nearest end point of the track under mouse - // to the mouse and return that. - double distStart = hypot( double( curpos->x - track->m_Start.x ), - double( curpos->y - track->m_Start.y )); - - double distEnd = hypot( double( curpos->x - track->m_End.x ), - double( curpos->y - track->m_End.y )); - - // if track not via, or if its a via dragging but not with its adjacent track - if( currTrack->Type() != TYPE_VIA - || ( currTrack->m_Start != track->m_Start && currTrack->m_Start != track->m_End )) - { - if( distStart <= currTrack->m_Width/2 ) - { - // D(printf("nearest end is start\n");) - *curpos = track->m_Start; - return true; - } - - if( distEnd <= currTrack->m_Width/2 ) - { - // D(printf("nearest end is end\n");) - *curpos = track->m_End; - return true; - } - - // @todo otherwise confine curpos such that it stays centered - // within "track" - } - } - } - } - - return false; -} - - /****************************************************************/ void WinEDA_PcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) /*****************************************************************/ diff --git a/pcbnew/deltrack.cpp b/pcbnew/deltrack.cpp index 8234724ba9..572a133887 100644 --- a/pcbnew/deltrack.cpp +++ b/pcbnew/deltrack.cpp @@ -192,7 +192,7 @@ void WinEDA_PcbFrame::Remove_One_Track( wxDC* DC, TRACK* pt_segm ) if( pt_segm == NULL ) return; - TRACK* trackList = Marque_Une_Piste( this, DC, pt_segm, &segments_to_delete_count, 0 ); + TRACK* trackList = Marque_Une_Piste( GetBoard(), pt_segm, &segments_to_delete_count, NULL, true ); if( segments_to_delete_count == 0 ) return; diff --git a/pcbnew/dialog_track_options_base.cpp b/pcbnew/dialog_track_options_base.cpp index 006d7ab483..fb540305b2 100644 --- a/pcbnew/dialog_track_options_base.cpp +++ b/pcbnew/dialog_track_options_base.cpp @@ -73,7 +73,7 @@ DIALOG_TRACKS_OPTIONS_BASE::DIALOG_TRACKS_OPTIONS_BASE( wxWindow* parent, wxWind wxStaticBoxSizer* sbMiddleLeftSizer; sbMiddleLeftSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Vias Options:") ), wxVERTICAL ); - wxString m_OptViaTypeChoices[] = { _("Through Via"), _("Blind or Buried Via") }; + wxString m_OptViaTypeChoices[] = { _("Through via"), _("Blind or buried via") }; int m_OptViaTypeNChoices = sizeof( m_OptViaTypeChoices ) / sizeof( wxString ); m_OptViaType = new wxRadioBox( this, wxID_ANY, _("Default Via Type"), wxDefaultPosition, wxDefaultSize, m_OptViaTypeNChoices, m_OptViaTypeChoices, 1, wxRA_SPECIFY_COLS ); m_OptViaType->SetSelection( 0 ); @@ -84,7 +84,7 @@ DIALOG_TRACKS_OPTIONS_BASE::DIALOG_TRACKS_OPTIONS_BASE( wxWindow* parent, wxWind sbMiddleLeftSizer->Add( 10, 10, 0, 0, 5 ); - wxString m_AllowMicroViaCtrlChoices[] = { _("Do Not Allow Micro Vias"), _("Allow Micro Vias") }; + wxString m_AllowMicroViaCtrlChoices[] = { _("Do not allow micro vias"), _("Allow micro vias") }; int m_AllowMicroViaCtrlNChoices = sizeof( m_AllowMicroViaCtrlChoices ) / sizeof( wxString ); m_AllowMicroViaCtrl = new wxRadioBox( this, wxID_ALLOW_MICROVIA, _("Micro Vias:"), wxDefaultPosition, wxDefaultSize, m_AllowMicroViaCtrlNChoices, m_AllowMicroViaCtrlChoices, 1, wxRA_SPECIFY_COLS ); m_AllowMicroViaCtrl->SetSelection( 0 ); diff --git a/pcbnew/dialog_track_options_base.fbp b/pcbnew/dialog_track_options_base.fbp index 24ccaa992f..2b22d6bb73 100644 --- a/pcbnew/dialog_track_options_base.fbp +++ b/pcbnew/dialog_track_options_base.fbp @@ -509,7 +509,7 @@ 0 - "Through Via" "Blind or Buried Via" + "Through via" "Blind or buried via" 1 @@ -573,7 +573,7 @@ 0 - "Do Not Allow Micro Vias" "Allow Micro Vias" + "Do not allow micro vias" "Allow micro vias" 1 diff --git a/pcbnew/edit_track_width.cpp b/pcbnew/edit_track_width.cpp index 494ca840da..46a30f523d 100644 --- a/pcbnew/edit_track_width.cpp +++ b/pcbnew/edit_track_width.cpp @@ -1,7 +1,7 @@ -/***************************************************************/ -/* Edition des pistes: Routines de modification de dimensions: */ -/* Modif de largeurs de segment, piste, net , zone et diam Via */ -/***************************************************************/ +/*************************************************************** +* Tracks and Vias size edition: +* Functions to modify sizes of segment, track, net , all vias and/or all tracks +***************************************************************/ #include "fctsys.h" #include "common.h" @@ -13,29 +13,46 @@ #include "protos.h" - /** Function SetTrackSegmentWidth * Modify one track segment width or one via diameter (using DRC control). * Basic routine used by other routines when editing tracks or vias * @param aTrackItem = the track segment or via to modify * @param aItemsListPicker = the list picker to use for an undo command (can be NULL) + * @param aUseNetclassValue = true to use NetClass value, false to use g_DesignSettings value * @return true if done, false if no not change (because DRC error) */ bool WinEDA_PcbFrame::SetTrackSegmentWidth( TRACK* aTrackItem, - PICKED_ITEMS_LIST* aItemsListPicker ) + PICKED_ITEMS_LIST* aItemsListPicker, + bool aUseNetclassValue ) { - int initial_width, new_width; - bool change_ok = false; + int initial_width, new_width; + bool change_ok = false; + NETINFO_ITEM* net = NULL; + + if( aUseNetclassValue ) + net = GetBoard()->FindNet( aTrackItem->GetNet() ); initial_width = aTrackItem->m_Width; - new_width = aTrackItem->m_Width = g_DesignSettings.m_CurrentTrackWidth; + if( net ) + new_width = net->GetTrackWidth(); + else + new_width = g_DesignSettings.m_CurrentTrackWidth; if( aTrackItem->Type() == TYPE_VIA ) { - new_width = aTrackItem->m_Width = g_DesignSettings.m_CurrentViaSize; + if( net ) + new_width = net->GetViaSize(); + else + new_width = aTrackItem->m_Width = g_DesignSettings.m_CurrentViaSize; if( aTrackItem->m_Shape == VIA_MICROVIA ) - new_width = aTrackItem->m_Width = g_DesignSettings.m_CurrentMicroViaSize; + { + if( net ) + new_width = net->GetViaSize(); + else + new_width = aTrackItem->m_Width = g_DesignSettings.m_CurrentMicroViaSize; + } } + aTrackItem->m_Width = new_width; if( initial_width < new_width ) /* make a DRC test because the new size is bigger than the old size */ { int diagdrc = OK_DRC; @@ -46,6 +63,7 @@ bool WinEDA_PcbFrame::SetTrackSegmentWidth( TRACK* aTrackItem, } else if( initial_width > new_width ) change_ok = true; + // if new width == initial_width: do nothing if( change_ok ) @@ -75,7 +93,7 @@ bool WinEDA_PcbFrame::SetTrackSegmentWidth( TRACK* aTrackItem, void WinEDA_PcbFrame::Edit_TrackSegm_Width( wxDC* DC, TRACK* aTrackItem ) { PICKED_ITEMS_LIST itemsListPicker; - bool change = SetTrackSegmentWidth( aTrackItem, &itemsListPicker ); + bool change = SetTrackSegmentWidth( aTrackItem, &itemsListPicker, false ); if( change == 0 || aTrackItem->m_Flags ) return; // No change @@ -84,7 +102,7 @@ void WinEDA_PcbFrame::Edit_TrackSegm_Width( wxDC* DC, TRACK* aTrackItem ) if( DC ) { TRACK* oldsegm = (TRACK*) itemsListPicker.GetPickedItemLink( 0 ); - wxASSERT(oldsegm); + wxASSERT( oldsegm ); DrawPanel->CursorOff( DC ); // Erase cursor shape oldsegm->Draw( DrawPanel, DC, GR_XOR ); // Erase old track shape aTrackItem->Draw( DrawPanel, DC, GR_OR ); // Display new track shape @@ -93,6 +111,7 @@ void WinEDA_PcbFrame::Edit_TrackSegm_Width( wxDC* DC, TRACK* aTrackItem ) SaveCopyInUndoList( itemsListPicker, UR_CHANGED ); } + /** Function Edit_Track_Width * Modify a full track width (using DRC control). * a full track is the set of track segments between 2 ends: pads or a point that has more than 2 segments ends connected @@ -108,14 +127,14 @@ void WinEDA_PcbFrame::Edit_Track_Width( wxDC* DC, TRACK* aTrackSegment ) if( aTrackSegment == NULL ) return; - pt_track = Marque_Une_Piste( this, DC, aTrackSegment, &nb_segm, 0 ); + pt_track = Marque_Une_Piste( GetBoard(), aTrackSegment, &nb_segm, NULL, true ); PICKED_ITEMS_LIST itemsListPicker; bool change = false; for( int ii = 0; ii < nb_segm; ii++, pt_track = pt_track->Next() ) { pt_track->SetState( BUSY, OFF ); - if( SetTrackSegmentWidth( pt_track, &itemsListPicker ) ) + if( SetTrackSegmentWidth( pt_track, &itemsListPicker, false ) ) change = true; } @@ -142,26 +161,36 @@ void WinEDA_PcbFrame::Edit_Track_Width( wxDC* DC, TRACK* aTrackSegment ) /***********************************************************/ -void WinEDA_PcbFrame::Edit_Net_Width( wxDC* DC, int Netcode ) +void WinEDA_PcbFrame::Edit_Net_Width( wxDC* DC, int aNetcode ) /***********************************************************/ { TRACK* pt_segm; - if( Netcode <= 0 ) + if( aNetcode <= 0 ) return; - if( !IsOK( this, _( "Change track width (entire NET) ?" ) ) ) + NETINFO_ITEM* net = GetBoard()->FindNet( aNetcode ); + wxASSERT( net ); + wxString netName = net->GetNetname(); + wxString msg; + NETCLASS* netClass = net->GetNetClass(); + wxASSERT( netClass ); + wxString netClassName = netClass->GetName(); + msg.Printf( _( + "Set tracks and vias sizes to the Netclass \"%s\"default value (entire NET \"%s\") ?" ), + netClassName.c_str(), netName.c_str() ); + if( !IsOK( this, msg ) ) return; - /* balayage des segments */ + /* Examine segments */ PICKED_ITEMS_LIST itemsListPicker; bool change = false; for( pt_segm = GetBoard()->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() ) { - if( Netcode != pt_segm->GetNet() ) /* mauvaise piste */ + if( aNetcode != pt_segm->GetNet() ) /* not in net */ continue; - /* piste d'un net trouvee */ - if( SetTrackSegmentWidth( pt_segm, &itemsListPicker ) ) + /* we have found a item member of the net */ + if( SetTrackSegmentWidth( pt_segm, &itemsListPicker, true ) ) change = true; } @@ -200,17 +229,17 @@ bool WinEDA_PcbFrame::Resize_Pistes_Vias( wxDC* DC, bool Track, bool Via ) if( Track && Via ) { - if( !IsOK( this, _( "Edit All Tracks and Vias Sizes" ) ) ) + if( !IsOK( this, _( "Set All Tracks and Vias to Netclass value" ) ) ) return FALSE; } else if( Via ) { - if( !IsOK( this, _( "Edit All Via Sizes" ) ) ) + if( !IsOK( this, _( "Set All Via to Netclass value" ) ) ) return FALSE; } else if( Track ) { - if( !IsOK( this, _( "Edit All Track Sizes" ) ) ) + if( !IsOK( this, _( "Set All Track to Netclass value" ) ) ) return FALSE; } @@ -221,16 +250,17 @@ bool WinEDA_PcbFrame::Resize_Pistes_Vias( wxDC* DC, bool Track, bool Via ) { if( (pt_segm->Type() == TYPE_VIA ) && Via ) { - if( SetTrackSegmentWidth( pt_segm, &itemsListPicker ) ) + if( SetTrackSegmentWidth( pt_segm, &itemsListPicker, true ) ) change = true; } + + if( (pt_segm->Type() == TYPE_TRACK ) && Track ) + { + if( SetTrackSegmentWidth( pt_segm, &itemsListPicker, true ) ) + change = true;; + } } - if( (pt_segm->Type() == TYPE_TRACK ) && Track ) - { - if( SetTrackSegmentWidth( pt_segm, &itemsListPicker ) ) - change = true;; - } if( !change ) return false; diff --git a/pcbnew/editrack-part2.cpp b/pcbnew/editrack-part2.cpp index 039e66cffc..db7adc1529 100644 --- a/pcbnew/editrack-part2.cpp +++ b/pcbnew/editrack-part2.cpp @@ -73,7 +73,8 @@ void WinEDA_PcbFrame::ExChange_Track_Layer( TRACK* pt_segm, wxDC* DC ) l1 = Route_Layer_TOP; l2 = Route_Layer_BOTTOM; - pt_track = Marque_Une_Piste( this, DC, pt_segm, &nb_segm, GR_XOR ); + pt_track = Marque_Une_Piste( GetBoard(), pt_segm, &nb_segm, NULL, true ); + Trace_Une_Piste( DrawPanel, DC, pt_track, nb_segm, GR_XOR ); /* effacement du flag BUSY et sauvegarde en membre .param de la couche * initiale */ diff --git a/pcbnew/magnetic_tracks_functions.cpp b/pcbnew/magnetic_tracks_functions.cpp new file mode 100644 index 0000000000..88c1889025 --- /dev/null +++ b/pcbnew/magnetic_tracks_functions.cpp @@ -0,0 +1,275 @@ +/********************************************************/ +/* magnetic_tracks_functions.cpp */ +/********************************************************/ + +/* functions used to controle the cursor position, when creating a track + * and when the "magnetic tracks" option is on + * (the current created track is kept near existing tracks + * the distance is the clearance between tracks) + */ + +#include "fctsys.h" +#include "common.h" +#include "pcbnew.h" +#include "wxPcbStruct.h" +#include "protos.h" +#include "pcbnew_id.h" + + +/** + * Function Join + * finds the point where line segment (b1,b0) intersects with segment (a1,a0). + * If that point would be outside of (a0,a1), the respective endpoint is used. + * Join returns the point in "res" and "true" if a suitable point was found, + * "false" if both lines are parallel or if the length of either segment is zero. + */ +static bool Join( wxPoint* res, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1 ) +{ + /* References: + http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ + http://www.gekkou.co.uk/blogs/monologues/2007/12/13/1197586800000.html + */ + + double denom; + double t; + + // if either segment is zero length + if( a1.x==a0.x && a1.y==a0.y ) + return false; + + if( b1.x==b0.x && b1.y==b0.y ) + return false; + + a1 -= a0; + b1 -= b0; + + b0 -= a0; + + denom = (double) b1.y * a1.x - (double) b1.x * a1.y; + if( !denom ) + { + return false; // parallel + } + + t = ((double) b1.y * b0.x - (double) b1.x * b0.y ) / denom; + + t = min( max( t, 0.0 ), 1.0 ); + + res->x = wxRound( a0.x + t * a1.x ); + res->y = wxRound( a0.y + t * a1.y ); + + return true; +} + + +/* + * "Project" finds the projection of a grid point on a track. This is the point + * from where we want to draw new orthogonal tracks when starting on a track. + */ +bool Project( wxPoint* res, wxPoint on_grid, const TRACK* track ) +{ + if( track->m_Start == track->m_End ) + return false; + + wxPoint vec = track->m_End - track->m_Start; + + double t = double( on_grid.x - track->m_Start.x ) * vec.x + + double( on_grid.y - track->m_Start.y ) * vec.y; + + t /= (double) vec.x * vec.x + (double) vec.y * vec.y; + t = min( max( t, 0.0 ), 1.0 ); + + res->x = wxRound( track->m_Start.x + t * vec.x ); + res->y = wxRound( track->m_Start.y + t * vec.y ); + + return true; +} + + +/** + * Function Magnetize + * tests to see if there are any magnetic items within near reach of the given + * "curpos". If yes, then curpos is adjusted appropriately according to that + * near magnetic item and true is returned. + * @param curpos The initial position, and what to adjust if a change is needed. + * @return bool - true if the position was adjusted magnetically, else false. + */ +bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame, + int aCurrentTool, wxSize grid, wxPoint on_grid, wxPoint* curpos ) +{ + bool doCheckNet = g_MagneticPadOption != capture_always && Drc_On; + bool doTrack = false; + bool doPad = false; + bool amMovingVia = false; + + TRACK* currTrack = g_CurrentTrackSegment; + BOARD_ITEM* currItem = frame->GetCurItem(); + + // D( printf( "currTrack=%p currItem=%p currTrack->Type()=%d currItem->Type()=%d\n", currTrack, currItem, currTrack ? currTrack->Type() : 0, currItem ? currItem->Type() : 0 ); ) + + if( !currTrack && currItem && currItem->Type()==TYPE_VIA && currItem->m_Flags ) + { + // moving a VIA + currTrack = (TRACK*) currItem; + amMovingVia = true; + + return false; // comment this return out and play with it. + } + else if( currItem != currTrack ) + { + currTrack = NULL; + } + + + if( g_MagneticPadOption == capture_always ) + doPad = true; + + if( g_MagneticTrackOption == capture_always ) + doTrack = true; + + if( aCurrentTool == ID_TRACK_BUTT || amMovingVia ) + { + int q = capture_cursor_in_track_tool; + + if( g_MagneticPadOption == q ) + doPad = true; + + if( g_MagneticTrackOption == q ) + doTrack = true; + } + + // D(printf("doPad=%d doTrack=%d aCurrentTool=%d amMovingVia=%d\n", doPad, doTrack, aCurrentTool, amMovingVia );) + + // The search precedence order is pads, then tracks/vias + + if( doPad ) + { + D_PAD* pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE, TRUE ); + if( pad ) + { + if( doCheckNet && currTrack && currTrack->GetNet() != pad->GetNet() ) + return false; + + *curpos = pad->m_Pos; + return true; + } + } + + // after pads, only track & via tests remain, skip them if not desired + if( doTrack ) + { + int layer = ( (PCB_SCREEN*) ActiveScreen )->m_Active_Layer; + + for( TRACK* via = m_Pcb->m_Track; + via && (via = Locate_Via_Area( via, *curpos, layer )) != NULL; + via = via->Next() ) + { + if( via != currTrack ) // a via cannot influence itself + { + if( !doCheckNet || !currTrack || currTrack->GetNet() == via->GetNet() ) + { + *curpos = via->m_Start; + // D(printf("via hit\n");) + return true; + } + } + else + { + //D( printf( "skipping self\n" ); ) + } + } + + if( !currTrack ) + { + int layer_mask = g_TabOneLayerMask[layer]; + + TRACK* track = Locate_Pistes( m_Pcb->m_Track, layer_mask, CURSEUR_OFF_GRILLE ); + if( !track || track->Type() != TYPE_TRACK ) + { + // D(printf("!currTrack and track=%p not found, layer_mask=0x%X\n", track, layer_mask );) + return false; + } + + // D( printf( "Project\n" ); ) + return Project( curpos, on_grid, track ); + } + + /* + * In two segment mode, ignore the final segment if it's inside a grid + * square. + */ + if( !amMovingVia && currTrack && g_TwoSegmentTrackBuild && currTrack->Back() + && currTrack->m_Start.x - grid.x < currTrack->m_End.x + && currTrack->m_Start.x + grid.x > currTrack->m_End.x + && currTrack->m_Start.y - grid.y < currTrack->m_End.y + && currTrack->m_Start.y + grid.y > currTrack->m_End.y ) + { + currTrack = currTrack->Back(); + } + + + for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() ) + { + if( track->Type() != TYPE_TRACK ) + continue; + + if( doCheckNet && currTrack && currTrack->GetNet() != track->GetNet() ) + continue; + + if( g_DesignSettings.IsLayerVisible( track->GetLayer() ) == false ) + continue; + + // omit the layer check if moving a via + if( !amMovingVia && !track->IsOnLayer( layer ) ) + continue; + + if( !track->HitTest( *curpos ) ) + continue; + + D(printf( "have track prospect\n");) + + if( Join( curpos, track->m_Start, track->m_End, currTrack->m_Start, currTrack->m_End ) ) + { + // D(printf( "join currTrack->Type()=%d\n", currTrack->Type() );) + return true; + } + + if( aCurrentTool == ID_TRACK_BUTT || amMovingVia ) + { + // At this point we have a drawing mouse on a track, we are drawing + // a new track and that new track is parallel to the track the + // mouse is on. Find the nearest end point of the track under mouse + // to the mouse and return that. + double distStart = hypot( double( curpos->x - track->m_Start.x ), + double( curpos->y - track->m_Start.y )); + + double distEnd = hypot( double( curpos->x - track->m_End.x ), + double( curpos->y - track->m_End.y )); + + // if track not via, or if its a via dragging but not with its adjacent track + if( currTrack->Type() != TYPE_VIA + || ( currTrack->m_Start != track->m_Start && currTrack->m_Start != track->m_End )) + { + if( distStart <= currTrack->m_Width/2 ) + { + // D(printf("nearest end is start\n");) + *curpos = track->m_Start; + return true; + } + + if( distEnd <= currTrack->m_Width/2 ) + { + // D(printf("nearest end is end\n");) + *curpos = track->m_End; + return true; + } + + // @todo otherwise confine curpos such that it stays centered + // within "track" + } + } + } + } + + return false; +} diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index d461c15396..478500d1bd 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -506,7 +506,7 @@ void WinEDA_PcbFrame::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu ) track_mnu = new wxMenu; ADD_MENUITEM_WITH_SUBMENU( PopMenu, track_mnu, ID_POPUP_PCB_EDIT_TRACK_MNU, _( - "Change Width" ), width_track_xpm ); + "Change Tracks and Vias Sizes" ), width_track_xpm ); ADD_MENUITEM( track_mnu, ID_POPUP_PCB_EDIT_TRACKSEG, Track->Type()==TYPE_VIA ? _( "Change Via Size" ) : _( "Change Segment Width" ), width_segment_xpm ); @@ -514,13 +514,13 @@ void WinEDA_PcbFrame::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu ) ADD_MENUITEM( track_mnu, ID_POPUP_PCB_EDIT_TRACK, _( "Change Track Width" ), width_track_xpm ); ADD_MENUITEM( track_mnu, ID_POPUP_PCB_EDIT_NET, - _( "Change Net" ), width_net_xpm ); + _( "Set Net to NetClass values" ), width_net_xpm ); ADD_MENUITEM( track_mnu, ID_POPUP_PCB_EDIT_ALL_VIAS_AND_TRACK_SIZE, - _( "Change ALL Tracks and Vias" ), width_track_via_xpm ); + _( "Set ALL Tracks and Vias to NetClass Values" ), width_track_via_xpm ); ADD_MENUITEM( track_mnu, ID_POPUP_PCB_EDIT_ALL_VIAS_SIZE, - _( "Change ALL Vias (No Track)" ), width_vias_xpm ); + _( "Set ALL Vias (No Track)to NetClass Values" ), width_vias_xpm ); ADD_MENUITEM( track_mnu, ID_POPUP_PCB_EDIT_ALL_TRACK_SIZE, - _( "Change ALL Tracks (No Via)" ), width_track_xpm ); + _( "Set ALL Tracks (No Via)to NetClass Values" ), width_track_xpm ); } // Delete control: diff --git a/pcbnew/protos.h b/pcbnew/protos.h index 851ae30176..2287353464 100644 --- a/pcbnew/protos.h +++ b/pcbnew/protos.h @@ -262,17 +262,24 @@ void Calcule_Coord_Extremite_45( int ox, int oy, int* fx, int* fy ); /*****************/ /* TRACK.CPP : */ /*****************/ -TRACK* Marque_Une_Piste( WinEDA_BasePcbFrame* frame, wxDC* DC, - TRACK* pt_segm, int* nb_segm, int flagcolor ); - -/* Routine de Marquage de 1 piste, a partir du segment pointe par pt_segm. - * le segment pointe est marque puis les segments adjacents - * jusqu'a un pad ou un point de jonction de plus de 2 segments - * le marquage est la mise a 1 du bit BUSY du parametre .status - * Les segments sont ensuite reclasses pour etre contigus en memoire - * Retourne: - * adresse du 1er segment de la chaine creee - * nombre de segments */ +/** + * Function Marque_Une_Piste + * marks a chain of track segments, connected to aTrackList. + * Each segment is marked by setting the BUSY bit into m_Flags. Electrical continuity + * is detected by walking each segment, and finally the segments are rearranged + * into a contiguous chain within the given list. + * @param aPcb = the board to analyse + * @param aStartSegm The first interesting segment within a list of track segment of aPcb + * @param aSegmCount = a pointer to an integer where to return the number of interesting segments + * @param aTrackLen = a pointer to an integer where to return the lenght of the track + * @param aReorder = + * true for reorder the interesting segments (useful for track edition/deletion) + * in this case the flag BUSY is set (the user is responsible of flag clearing) + * false for no reorder : useful when we want just calculate the track lenght + * in this case, flags are reset + * @return TRACK* the first in the chain of interesting segments. + */ +TRACK* Marque_Une_Piste( BOARD * aPcb, TRACK* aStartSegm, int* aSegmCount, int * aTrackLen, bool aReorder ); int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, TRACK** StartTrack, TRACK** EndTrack ); diff --git a/pcbnew/tr_modif.cpp b/pcbnew/tr_modif.cpp index 881cbd22f3..ab38b366dc 100644 --- a/pcbnew/tr_modif.cpp +++ b/pcbnew/tr_modif.cpp @@ -49,7 +49,7 @@ int WinEDA_PcbFrame::EraseRedundantTrack( wxDC* aDC, TRACK* aNewTrack, int aNewT if( aNewTrack->Type() == TYPE_VIA && (aNewTrackSegmentsCount > 1 ) ) aNewTrack = aNewTrack->Next(); - aNewTrack = Marque_Une_Piste( this, aDC, aNewTrack, &aNewTrackSegmentsCount, 0 ); + aNewTrack = Marque_Une_Piste( GetBoard(), aNewTrack, &aNewTrackSegmentsCount, NULL, true ); wxASSERT( aNewTrack ); #if 0 && defined(DEBUG) @@ -204,7 +204,7 @@ int WinEDA_PcbFrame::EraseRedundantTrack( wxDC* aDC, TRACK* aNewTrack, int aNewT nbconnect--; pt_del->SetState( CHAIN, OFF ); - pt_del = Marque_Une_Piste( this, aDC, pt_del, &nb_segm, 0 ); + pt_del = Marque_Une_Piste( GetBoard(), pt_del, &nb_segm, NULL, true ); /* Test si La piste marquee est redondante, c'est a dire si l'un des * segments marques est connecte au point de depart de la piste nouvelle diff --git a/pcbnew/track.cpp b/pcbnew/track.cpp index 8cbf8c8ca1..1a7f1afce5 100644 --- a/pcbnew/track.cpp +++ b/pcbnew/track.cpp @@ -1,7 +1,6 @@ -/*********************************************/ -/* Edition des pistes: Routines d'effacement */ -/* Effacement de segment, piste, net et zone */ -/*********************************************/ +/********************************************* +* track.cpp +*********************************************/ #include "fctsys.h" @@ -10,63 +9,63 @@ #include "protos.h" +/* Functions to reconize a track. + * A track is a list of connected segments (or/and vias) + * from a starting to an ending point + * starting and ending points are a pad or a point with more than 2 segments connected + * (and obviouly a dangling segment end) + */ -typedef std::vector TRACK_PTRS; +typedef std::vector TRACK_PTRS; // buffer of item candidates when search for items on the same track -/* Routines externes : */ -void Montre_Position_New_Piste( int flag );/* defini dans editrack.cc */ - - -/* Routines Locales */ +/* Local functions */ static void Marque_Chaine_segments( BOARD* Pcb, wxPoint ref_pos, int masklayer, TRACK_PTRS* aList ); -/* Variables locales */ - - -/* Routine de Marquage de 1 piste, a partir du segment pointe par pt_segm. - * le segment pointe est marque puis les segments connectes - * jusqu'a un pad ou un point de jonction de plus de 2 segments - * le marquage est la mise a 1 du bit BUSY - * Les segments sont ensuite reclasses pour etre contigus en liste chainee - * Retourne: - * adresse du 1er segment de la chaine creee - * nombre de segments - */ /** * Function Marque_Une_Piste - * marks a chain of track segments, starting at aTrackList. + * marks a chain of track segments, connected to aTrackList. * Each segment is marked by setting the BUSY bit into m_Flags. Electrical continuity * is detected by walking each segment, and finally the segments are rearranged * into a contiguous chain within the given list. - * @param aTrackList The first interesting segment within a list of many - * interesting and uninteresting segments. + * @param aPcb = the board to analyse + * @param aStartSegm The first interesting segment within a list of track segment of aPcb + * @param aSegmCount = a pointer to an integer where to return the number of interesting segments + * @param aTrackLen = a pointer to an integer where to return the lenght of the track + * @param aReorder = bool: + * true for reorder the interesting segments (useful for track edition/deletion) + * in this case the flag BUSY is set (the user is responsible of flag clearing) + * false for no reorder : useful when we want just calculate the track lenght + * in this case, flags are reset * @return TRACK* the first in the chain of interesting segments. */ -TRACK* Marque_Une_Piste( WinEDA_BasePcbFrame* frame, wxDC* DC, - TRACK* aTrackList, int* nb_segm, int flagcolor ) +TRACK* Marque_Une_Piste( BOARD* aPcb, + TRACK* aStartSegm, + int* aSegmCount, + int* aTrackLen, + bool aReorder ) { - int NbSegmBusy; + int NbSegmBusy; - TRACK_PTRS trackList; + TRACK_PTRS trackList; - *nb_segm = 0; - if( aTrackList == NULL ) + if( aSegmCount ) + *aSegmCount = 0; + + if( aStartSegm == NULL ) return NULL; - if( flagcolor ) - aTrackList->Draw( frame->DrawPanel, DC, flagcolor ); - - // Ensure the flag BUSY is cleared because we use it to mark segments of the track - for( TRACK* track = frame->GetBoard()->m_Track; track; track = track->Next() ) - track->SetState( BUSY , OFF ); + // Ensure the flag BUSY of all tracks of the board is cleared + // because we use it to mark segments of the track + for( TRACK* track = aPcb->m_Track; track; track = track->Next() ) + track->SetState( BUSY, OFF ); /* Set flags of the initial track segment */ - aTrackList->SetState( BUSY, ON ); - int masque_layer = aTrackList->ReturnMaskLayer(); + aStartSegm->SetState( BUSY, ON ); + int masque_layer = aStartSegm->ReturnMaskLayer(); - trackList.push_back( aTrackList ); + trackList.push_back( aStartSegm ); /* Examine the initial track segment : if it is really a segment, this is easy. * If it is a via, one must search for connected segments. @@ -74,85 +73,106 @@ TRACK* Marque_Une_Piste( WinEDA_BasePcbFrame* frame, wxDC* DC, * and this via and these 2 segments are a part of a track. * If > 2 only this via is flagged (the track has only this via) */ - if( aTrackList->Type() == TYPE_VIA ) + if( aStartSegm->Type() == TYPE_VIA ) { TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL; - Segm1 = Fast_Locate_Piste( frame->GetBoard()->m_Track, NULL, - aTrackList->m_Start, masque_layer ); + Segm1 = Fast_Locate_Piste( aPcb->m_Track, NULL, + aStartSegm->m_Start, masque_layer ); if( Segm1 ) { Segm2 = Fast_Locate_Piste( Segm1->Next(), NULL, - aTrackList->m_Start, masque_layer ); + aStartSegm->m_Start, masque_layer ); } if( Segm2 ) { Segm3 = Fast_Locate_Piste( Segm2->Next(), NULL, - aTrackList->m_Start, masque_layer ); + aStartSegm->m_Start, masque_layer ); } if( Segm3 ) // More than 2 segments are connected to this via. the "track" is only this via { - *nb_segm = 1; - return aTrackList; + if( aSegmCount ) + *aSegmCount = 1; + return aStartSegm; } if( Segm1 ) // search for others segments connected to the initial segment start point { masque_layer = Segm1->ReturnMaskLayer(); - Marque_Chaine_segments( frame->GetBoard(), aTrackList->m_Start, masque_layer, &trackList ); + Marque_Chaine_segments( + aPcb, aStartSegm->m_Start, masque_layer, &trackList ); } if( Segm2 ) // search for others segments connected to the initial segment end point { masque_layer = Segm2->ReturnMaskLayer(); - Marque_Chaine_segments( frame->GetBoard(), aTrackList->m_Start, masque_layer, &trackList ); + Marque_Chaine_segments( + aPcb, aStartSegm->m_Start, masque_layer, &trackList ); } } - else // mark the chain using both ends of the initial segment { - Marque_Chaine_segments( frame->GetBoard(), aTrackList->m_Start, masque_layer, &trackList ); - Marque_Chaine_segments( frame->GetBoard(), aTrackList->m_End, masque_layer, &trackList ); + Marque_Chaine_segments( aPcb, aStartSegm->m_Start, masque_layer, &trackList ); + Marque_Chaine_segments( aPcb, aStartSegm->m_End, masque_layer, &trackList ); } - // marquage des vias (vias non connectees ou inutiles + // Now we examine selected vias and flag them if they are on the track + // If a via is connected to only one or 2 segments, it is flagged (is on the track) + // If a via is connected to more than 2 segments, it is a track end, and it is removed from the list // go through the list backwards. - for( int i = trackList.size()-1; i>=0; --i ) + for( int i = trackList.size() - 1; i>=0; --i ) { - TRACK* via = trackList[i]; + TRACK* via = trackList[i]; if( via->Type() != TYPE_VIA ) continue; - if( via == aTrackList ) + if( via == aStartSegm ) continue; - via->SetState( BUSY, ON ); + via->SetState( BUSY, ON ); // Try to flag it. the flag will be cleared later if needed masque_layer = via->ReturnMaskLayer(); - TRACK* track = Fast_Locate_Piste( frame->GetBoard()->m_Track, - NULL, via->m_Start, masque_layer ); + TRACK* track = Fast_Locate_Piste( aPcb->m_Track, NULL, via->m_Start, masque_layer ); + + // Fast_Locate_Piste does not consider tracks flagged BUSY. + // So if no connected track found, this via is on the current track only: keep it if( track == NULL ) continue; - /* Test des connexions: si via utile: suppression marquage */ + /* if a track is found, this via connects also others segments of an other track + * This case happens when the vias ends the selected track. + * But must we consider this via is on the selected track, or on an other track. + * (this is important when selecting a track for deletion: must this via be deleted or not?) + * We consider here this via on the track if others segment connected to this via + * remain connected when removing this via. + * We search for all others segment connected together: + * if there are on the same layer, the via is on the selected track + * if there are on different layers, the via is on an other track + */ int layer = track->GetLayer(); while( ( track = Fast_Locate_Piste( track->Next(), NULL, - via->m_Start, masque_layer ) ) != NULL ) + via->m_Start, masque_layer ) ) != NULL ) { if( layer != track->GetLayer() ) { + // The via connects segments of an other track: it is removed from list + // because it is member of an other track via->SetState( BUSY, OFF ); break; } } } - /* Reclassement des segments marques en une chaine */ + /* Rearrange the track list in order to have flagged segments linked from firstTrack + * So the NbSegmBusy segments are consecutive segments in list, the first item + * in the full track list is firstTrack, and the NbSegmBusy-1 next items + * (NbSegmBusy when including firstTrack) are the flagged segments + */ NbSegmBusy = 0; TRACK* firstTrack; - for( firstTrack = frame->GetBoard()->m_Track; firstTrack; firstTrack = firstTrack->Next() ) + for( firstTrack = aPcb->m_Track; firstTrack; firstTrack = firstTrack->Next() ) { - // recherche du debut de la liste des segments marques a BUSY + // Search for the first flagged BUSY segments if( firstTrack->GetState( BUSY ) ) { NbSegmBusy = 1; @@ -160,133 +180,176 @@ TRACK* Marque_Une_Piste( WinEDA_BasePcbFrame* frame, wxDC* DC, } } - wxASSERT( firstTrack ); + if( firstTrack == NULL ) + return NULL; - if( firstTrack ) + double full_len = 0; + if( aReorder ) { DLIST* list = (DLIST*)firstTrack->GetList(); - wxASSERT(list); + wxASSERT( list ); - /* Reclassement de la chaine debutant a FirstTrack et finissant - * au dernier segment marque. FirstTrack n'est pas modifie + /* Rearrange the chain starting at firstTrack + * All others flagged items are moved from their position to the end + * of the flagged list */ TRACK* next; for( TRACK* track = firstTrack->Next(); track; track = next ) { next = track->Next(); - if( track->GetState( BUSY ) ) + if( track->GetState( BUSY ) ) // move it! { NbSegmBusy++; track->UnLink(); list->Insert( track, firstTrack->Next() ); + if( aTrackLen ) + full_len += track->GetLength(); + } + } + } + else if( aTrackLen ) + { + NbSegmBusy = 0; + for( TRACK* track = firstTrack; track; track = track->Next() ) + { + if( track->GetState( BUSY ) ) + { + NbSegmBusy++; + track->SetState( BUSY, OFF ); + full_len += track->GetLength(); } } } - *nb_segm = NbSegmBusy; - - if( flagcolor ) - Trace_Une_Piste( frame->DrawPanel, DC, firstTrack, NbSegmBusy, flagcolor ); + if( aTrackLen ) + *aTrackLen = wxRound( full_len ); + if( aSegmCount ) + *aSegmCount = NbSegmBusy; return firstTrack; } /********************************************************************************/ -static void Marque_Chaine_segments( BOARD* Pcb, wxPoint ref_pos, int masque_layer, TRACK_PTRS* aList ) +static void Marque_Chaine_segments( BOARD* aPcb, wxPoint aRef_pos, int aLayerMask, + TRACK_PTRS* aList ) /********************************************************************************/ -/* - * routine utilisee par Supprime_1_Piste() - * Positionne le bit BUSY dans la chaine de segments commencant - * au point ox, oy sur la couche layer - * - * Les vias sont mises en liste des segments traites mais ne sont pas - * marquees. +/** + * Function used by Marque_Une_Piste() + * - Set the BUSY flag of connected segments, the first search point is + * ref_pos on layers allowed in masque_layer + * - Put segments fount in aList + * Vias are put in list but their flags BUSY is not set + * @param Pcb = the board + * @param aRef_pos = the reference coordinate of the starting search + * @param aLayerMask = the allowed layers for segments to search + * (1 layer when starting point is on a segment, but more than one when starting point is on a via) + * @param aList = the track list to fill with points of segments flagged */ { - TRACK* pt_segm, // Pointe le segment courant analyse - * pt_via, // pointe la via reperee, eventuellement a detruire - * MarqSegm; // pointe le segment a detruire (= NULL ou pt_segm - int NbSegm; + TRACK* pt_segm, // Pointe le segment courant analyse + * pt_via, // pointe la via reperee, eventuellement a detruire + * SegmentCandidate; // pointe le segment a detruire (= NULL ou pt_segm + int NbSegm; - if( Pcb->m_Track == NULL ) + if( aPcb->m_Track == NULL ) return; - /* Marquage de la chaine */ + /* Set the BUSY flag of all connected segments, first search starting at aRef_pos + * Search ends when: + * - a pad is found (end of a track) + * - a segment found is flagged "EDIT" + * - a segment end has more than one other segment end connected + * - and obviously when no connected item found + * Vias are a special case, because we must see others segment connected on others layers + * and they change the layer mask. They can be a track end or not + * They will be analyser later, and vias on terminal points of the track will be + * considered as part of this track if they do not connect segments of an other track together + * and will be considered as part of an other track + * if when removing the via, the segments of taht other track are disconnected + */ for( ; ; ) { - if( Fast_Locate_Pad_Connecte( Pcb, ref_pos, masque_layer ) != NULL ) + if( Fast_Locate_Pad_Connecte( aPcb, aRef_pos, aLayerMask ) != NULL ) return; - /* Localisation d'une via (car elle connecte plusieurs segments) */ - pt_via = Fast_Locate_Via( Pcb->m_Track, NULL, ref_pos, masque_layer ); + /* Test for a via: a via changes the layer mask and can connect a lot of segments + * at location aRef_pos + * When found, the via is just pushed in list. + * Vias will be examined later, when all connected segment are found and push in list + * This is because whena via is found we do not know at this time the number of connected items + * and we do not know if this via is on the track or finish the track + */ + pt_via = Fast_Locate_Via( aPcb->m_Track, NULL, aRef_pos, aLayerMask ); if( pt_via ) { if( pt_via->GetState( EDIT ) ) return; - masque_layer = pt_via->ReturnMaskLayer(); + aLayerMask = pt_via->ReturnMaskLayer(); aList->push_back( pt_via ); } - /* Recherche des segments connectes au point ref_pos - * si 1 segment: peut etre marque - * si > 1 segment: - * le segment ne peut etre marque + /* Now we search all segments connected to point aRef_pos + * if only 1 segment: this segment is candidate + * if > 1 segment: + * end of track (more than 2 segment connected at this location) */ - pt_segm = Pcb->m_Track; MarqSegm = NULL; + pt_segm = aPcb->m_Track; SegmentCandidate = NULL; NbSegm = 0; while( ( pt_segm = Fast_Locate_Piste( pt_segm, NULL, - ref_pos, masque_layer ) ) != NULL ) + aRef_pos, aLayerMask ) ) != NULL ) { - if( pt_segm->GetState( EDIT ) ) /* Fin de piste */ + if( pt_segm->GetState( EDIT ) ) // End of track return; - if( pt_segm->GetState( BUSY ) ) + if( pt_segm->GetState( BUSY ) ) // already found and selected: skip it { pt_segm = pt_segm->Next(); continue; } - if( pt_segm == pt_via ) /* deja traite */ + if( pt_segm == pt_via ) // just previously found: skip it { pt_segm = pt_segm->Next(); continue; } NbSegm++; - if( NbSegm == 1 ) /* 1ere detection de segment de piste */ + if( NbSegm == 1 ) /* First time we found a connected item: pt_segm is candidate */ { - MarqSegm = pt_segm; - pt_segm = pt_segm->Next(); + SegmentCandidate = pt_segm; + pt_segm = pt_segm->Next(); } - else /* 2eme detection de segment -> fin de piste */ + else /* More than 1 segment connected -> this location is an end of the track */ { return; } } - if( MarqSegm ) + if( SegmentCandidate ) // A candidate is found: flag it an push it in list { - /* preparation de la nouvelle recherche */ - masque_layer = MarqSegm->ReturnMaskLayer(); + /* Initialize parameters to search items connected to this candidate: + * we must analyse connections to its other end + */ + aLayerMask = SegmentCandidate->ReturnMaskLayer(); - if( ref_pos == MarqSegm->m_Start ) + if( aRef_pos == SegmentCandidate->m_Start ) { - ref_pos = MarqSegm->m_End; + aRef_pos = SegmentCandidate->m_End; } else { - ref_pos = MarqSegm->m_Start; + aRef_pos = SegmentCandidate->m_Start; } - pt_segm = Pcb->m_Track; /* reinit recherche des segments */ + pt_segm = aPcb->m_Track; /* restart list of tracks to analyse */ - /* Marquage et mise en liste du segment */ - aList->push_back( MarqSegm ); - MarqSegm->SetState( BUSY, ON ); + /* flag this item an push it in list of selected items */ + aList->push_back( SegmentCandidate ); + SegmentCandidate->SetState( BUSY, ON ); } else return; @@ -299,12 +362,14 @@ int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, TRACK** StartTrack, TRACK** EndTrack ) /**********************************************************/ -/* Calcule les coordonnes des extremites d'une piste - * retourne 1 si OK, 0 si piste bouclee - * Retourne dans *StartTrack en *EndTrack les segments de debut et fin - * Les coord StartTrack->m_Start.x, m_Start.y contiennent le debut de la piste - * Les coord EndTrack->m_End.x, m_End.y contiennent le debut de la piste - * Les segments sont supposes chaines de facon consecutive +/* Calculate the end points coordinates of a track (a list of connected segments) + * RefTrack is a segment of the track + * return 1 if OK, 0 when a track is a closed loop + * and the beginning and the end of the track in *StartTrack and *EndTrack + * Modify *StartTrack en *EndTrack : + * (*StartTrack)->m_Start coordinate is the beginning of the track + * (*EndTrack)->m_End coordinate is the end of the track + * Segments connected must be consecutives in list */ { TRACK* Track, * via, * segm, * TrackListEnd; @@ -433,7 +498,7 @@ int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, void ListSetState( EDA_BaseStruct* Start, int NbItem, int State, int onoff ) /***************************************************************************/ -/* Met a jour le membre .state d'une chaine de structures +/* Set to onoff the .m_State member, bit mask State of a list of items */ { if( Start == NULL )