diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 39f17f97f6..b6daf5bc76 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,17 @@ KiCad ChangeLog 2009 Please add newer entries at the top, list the date and your name with email address. +2009-Nov-1 UPDATE Dick Hollenbeck +================================================================================ +++pcbnew + * Added exporting of netclass vias to specctra_export. + * DIALOG_DESIGN_RULES now remembers it last selected TAB and screen position and + window size, and its grid columns are automatically expanded to fit the + column titles. Remembering screen position and size allows someone with + multiple monitors, to have a given window always come up on the monitor last chosen + for it. + + 2009-oct-30 UPDATE Jean-Pierre Charras ================================================================================ ++pcbnew @@ -19,8 +30,6 @@ email address. accessible by a specific dialog frame. - - 2009-oct-27 UPDATE Jerry Jacobs ================================================================================ ++common diff --git a/pcbnew/dialog_design_rules.cpp b/pcbnew/dialog_design_rules.cpp index 7d79f6e9e7..97ed8059a1 100644 --- a/pcbnew/dialog_design_rules.cpp +++ b/pcbnew/dialog_design_rules.cpp @@ -56,6 +56,42 @@ enum { const wxString DIALOG_DESIGN_RULES::wildCard = _("* (Any)"); +// dialog should remember it previously selected tab +int DIALOG_DESIGN_RULES::s_LastTabSelection = -1; + +// dialog should remember its previous screen position and size +wxPoint DIALOG_DESIGN_RULES::s_LastPos( -1, -1 ); +wxSize DIALOG_DESIGN_RULES::s_LastSize; + + + + +/** + * Function EnsureGridColumnWidths + * resizes all the columns in a wxGrid based only on the requirements of the + * column titles and not on the grid cell requirements, assuming that the grid + * cell width requirements are narrower than the column title requirements. + */ +// @todo: maybe move this to common.cpp if it works. +void EnsureGridColumnWidths( wxGrid* aGrid ) +{ + wxScreenDC sDC; + + sDC.SetFont( aGrid->GetLabelFont() ); + + int colCount = aGrid->GetNumberCols(); + for( int col=0; colGetColLabelValue( col ) + ' ' + ' '; + + wxSize needed = sDC.GetTextExtent( colText ); + + // set the width of this column + aGrid->SetColSize( col, needed.x ); + } +} + /***********************************************************************************/ DIALOG_DESIGN_RULES::DIALOG_DESIGN_RULES( WinEDA_PcbFrame* parent ) : @@ -65,6 +101,8 @@ DIALOG_DESIGN_RULES::DIALOG_DESIGN_RULES( WinEDA_PcbFrame* parent ) : m_Parent = parent; SetAutoLayout( true ); + EnsureGridColumnWidths( m_grid ); // override any column widths set by wxformbuilder. + wxListItem column0; wxListItem column1; @@ -87,12 +125,24 @@ DIALOG_DESIGN_RULES::DIALOG_DESIGN_RULES( WinEDA_PcbFrame* parent ) : m_rightListCtrl->SetColumnWidth( 0, wxLIST_AUTOSIZE ); m_rightListCtrl->SetColumnWidth( 1, wxLIST_AUTOSIZE ); + // if user has been into the dialog before, go back to same tab + if( s_LastTabSelection != -1 ) + { + m_DRnotebook->SetSelection( s_LastTabSelection ); + } InitDialogRules(); Layout(); GetSizer()->Fit( this ); GetSizer()->SetSizeHints( this ); - Center(); + + if( s_LastPos.x != -1 ) + { + SetSize( s_LastSize ); + SetPosition( s_LastPos ); + } + else + Center(); } @@ -560,6 +610,12 @@ void DIALOG_DESIGN_RULES::CopyDimensionsListsToBoard( ) void DIALOG_DESIGN_RULES::OnCancelButtonClick( wxCommandEvent& event ) /*****************************************************************/ { + s_LastTabSelection = m_DRnotebook->GetSelection(); + + // Save the dialog's position before finishing + s_LastPos = GetPosition(); + s_LastSize = GetSize(); + EndModal( wxID_CANCEL ); } @@ -568,6 +624,8 @@ void DIALOG_DESIGN_RULES::OnCancelButtonClick( wxCommandEvent& event ) void DIALOG_DESIGN_RULES::OnOkButtonClick( wxCommandEvent& event ) /**************************************************************************/ { + s_LastTabSelection = m_DRnotebook->GetSelection(); + if( !TestDataValidity() ) { DisplayError( this, _( "Errors detected, Abort" ) ); @@ -578,6 +636,10 @@ void DIALOG_DESIGN_RULES::OnOkButtonClick( wxCommandEvent& event ) CopyGlobalRulesToBoard(); CopyDimensionsListsToBoard( ); + // Save the dialog's position before finishing + s_LastPos = GetPosition(); + s_LastSize = GetSize(); + EndModal( wxID_OK ); m_Parent->AuxiliaryToolBar_Update_UI(); diff --git a/pcbnew/dialog_design_rules.h b/pcbnew/dialog_design_rules.h index c5541e76e0..dab6df2e51 100644 --- a/pcbnew/dialog_design_rules.h +++ b/pcbnew/dialog_design_rules.h @@ -34,6 +34,11 @@ private: WinEDA_PcbFrame* m_Parent; BOARD* m_Pcb; + static int s_LastTabSelection; ///< which tab user had open last + + static wxSize s_LastSize; ///< last position and size + static wxPoint s_LastPos; + /** * A two column table which gets filled once and never loses any elements, so it is * basically constant, except that the NETCUP::clazz member can change for any @@ -53,7 +58,7 @@ private: void OnOkButtonClick( wxCommandEvent& event ); void OnAddNetclassClick( wxCommandEvent& event ); void OnRemoveNetclassClick( wxCommandEvent& event ); - void OnMoveUpSelectedNetClass( wxCommandEvent& event ); + void OnMoveUpSelectedNetClass( wxCommandEvent& event ); void OnLeftCBSelection( wxCommandEvent& event ); void OnRightCBSelection( wxCommandEvent& event ); void OnRightToLeftCopyButton( wxCommandEvent& event ); diff --git a/pcbnew/dialog_design_rules_base.cpp b/pcbnew/dialog_design_rules_base.cpp index af57db5611..38ea7ec630 100644 --- a/pcbnew/dialog_design_rules_base.cpp +++ b/pcbnew/dialog_design_rules_base.cpp @@ -11,7 +11,7 @@ DIALOG_DESIGN_RULES_BASE::DIALOG_DESIGN_RULES_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( 600,520 ), wxDefaultSize ); + this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); wxBoxSizer* bMainSizer; bMainSizer = new wxBoxSizer( wxVERTICAL ); @@ -35,10 +35,11 @@ DIALOG_DESIGN_RULES_BASE::DIALOG_DESIGN_RULES_BASE( wxWindow* parent, wxWindowID // Columns m_grid->SetColSize( 0, 100 ); - m_grid->SetColSize( 1, 100 ); - m_grid->SetColSize( 2, 100 ); - m_grid->SetColSize( 3, 100 ); - m_grid->SetColSize( 4, 100 ); + m_grid->SetColSize( 1, 120 ); + m_grid->SetColSize( 2, 84 ); + m_grid->SetColSize( 3, 85 ); + m_grid->SetColSize( 4, 81 ); + m_grid->SetColSize( 5, 90 ); m_grid->EnableDragColMove( false ); m_grid->EnableDragColSize( true ); m_grid->SetColLabelSize( 40 ); @@ -84,7 +85,7 @@ DIALOG_DESIGN_RULES_BASE::DIALOG_DESIGN_RULES_BASE( wxWindow* parent, wxWindowID buttonBoxSizer->Add( m_moveUpButton, 0, wxRIGHT|wxLEFT, 5 ); - sbSizer1->Add( buttonBoxSizer, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + sbSizer1->Add( buttonBoxSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); bpanelNetClassesSizer->Add( sbSizer1, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 ); @@ -151,7 +152,7 @@ DIALOG_DESIGN_RULES_BASE::DIALOG_DESIGN_RULES_BASE( wxWindow* parent, wxWindowID m_panelNetClassesEditor->SetSizer( bpanelNetClassesSizer ); m_panelNetClassesEditor->Layout(); bpanelNetClassesSizer->Fit( m_panelNetClassesEditor ); - m_DRnotebook->AddPage( m_panelNetClassesEditor, _("Net Classes Editor"), false ); + m_DRnotebook->AddPage( m_panelNetClassesEditor, _("Net Classes Editor"), true ); m_panelGolbalDesignRules = new wxPanel( m_DRnotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL ); wxBoxSizer* bpanelGlobRulesSizer; bpanelGlobRulesSizer = new wxBoxSizer( wxVERTICAL ); @@ -310,7 +311,7 @@ DIALOG_DESIGN_RULES_BASE::DIALOG_DESIGN_RULES_BASE( wxWindow* parent, wxWindowID wxStaticBoxSizer* sbTracksListSizer; sbTracksListSizer = new wxStaticBoxSizer( new wxStaticBox( m_panelGolbalDesignRules, wxID_ANY, _("Custom Track Widths:") ), wxVERTICAL ); - m_staticText8 = new wxStaticText( m_panelGolbalDesignRules, wxID_ANY, _(" "), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText8 = new wxStaticText( m_panelGolbalDesignRules, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_staticText8->Wrap( -1 ); sbTracksListSizer->Add( m_staticText8, 0, wxALL, 5 ); @@ -355,7 +356,7 @@ DIALOG_DESIGN_RULES_BASE::DIALOG_DESIGN_RULES_BASE( wxWindow* parent, wxWindowID m_panelGolbalDesignRules->SetSizer( bpanelGlobRulesSizer ); m_panelGolbalDesignRules->Layout(); bpanelGlobRulesSizer->Fit( m_panelGolbalDesignRules ); - m_DRnotebook->AddPage( m_panelGolbalDesignRules, _("Global Design Rules"), true ); + m_DRnotebook->AddPage( m_panelGolbalDesignRules, _("Global Design Rules"), false ); bMainSizer->Add( m_DRnotebook, 1, wxEXPAND | wxALL, 5 ); diff --git a/pcbnew/dialog_design_rules_base.fbp b/pcbnew/dialog_design_rules_base.fbp index aa33e64220..2422ddb97c 100644 --- a/pcbnew/dialog_design_rules_base.fbp +++ b/pcbnew/dialog_design_rules_base.fbp @@ -29,10 +29,10 @@ 0 wxID_ANY - 600,520 + -1,-1 DIALOG_DESIGN_RULES_BASE - 850,692 + 900,600 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER Design Rules Editor @@ -128,7 +128,7 @@ Net Classes Editor - 0 + 1 @@ -206,7 +206,7 @@ "Clearance" "Track Width" "Via Dia" "Via Drill" "uVia Dia" "uVia Drill" wxALIGN_CENTRE 6 - 100,100,100,100,100 + 100,120,84,85,81,90 0 1 @@ -301,7 +301,7 @@ 5 - wxALIGN_CENTER_HORIZONTAL + wxALIGN_CENTER_HORIZONTAL|wxALL 0 @@ -969,7 +969,7 @@ Global Design Rules - 1 + 0 @@ -2071,7 +2071,7 @@ 0 wxID_ANY - + m_staticText8 diff --git a/pcbnew/specctra.h b/pcbnew/specctra.h index 8bb35c63d2..1bf0bb9f45 100644 --- a/pcbnew/specctra.h +++ b/pcbnew/specctra.h @@ -2294,11 +2294,9 @@ class LIBRARY : public ELEM UNIT_RES* unit; IMAGES images; - PADSTACKS padstacks; - /// The start of the vias within the padstacks, which trail the pads. - /// This field is not Format()ed. - int via_start_index; + PADSTACKS padstacks; ///< all except vias, which are in 'vias' + PADSTACKS vias; public: @@ -2306,7 +2304,7 @@ public: ELEM( aType, aParent ) { unit = 0; - via_start_index = -1; // 0 or greater means there is at least one via +// via_start_index = -1; // 0 or greater means there is at least one via } ~LIBRARY() { @@ -2319,6 +2317,7 @@ public: padstacks.push_back( aPadstack ); } +/* void SetViaStartIndex( int aIndex ) { via_start_index = aIndex; @@ -2327,6 +2326,7 @@ public: { return via_start_index; } +*/ /** @@ -2392,17 +2392,25 @@ public: */ int FindVia( PADSTACK* aVia ) { - if( via_start_index > -1 ) + for( unsigned i=0; iSetParent( this ); + vias.push_back( aVia ); + } + + /** * Function AppendPADSTACK * adds the padstack to the padstack container. @@ -2426,10 +2434,10 @@ public: int ndx = FindVia( aVia ); if( ndx == -1 ) { - AppendPADSTACK( aVia ); + AppendVia( aVia ); return aVia; } - return &padstacks[ndx]; + return &vias[ndx]; } /** @@ -2458,6 +2466,9 @@ public: for( PADSTACKS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i ) i->Format( out, nestLevel ); + + for( PADSTACKS::iterator i=vias.begin(); i!=vias.end(); ++i ) + i->Format( out, nestLevel ); } UNIT_RES* GetUnits() const @@ -3930,7 +3941,7 @@ class SPECCTRA_DB : public OUTPUTFORMATTER * Function exportNETCLASS * exports \a aNetClass to the DSN file. */ - void exportNETCLASS( NETCLASS* aNetClass ); + void exportNETCLASS( NETCLASS* aNetClass, BOARD* aBoard ); //----------------------------------------------------------- diff --git a/pcbnew/specctra_export.cpp b/pcbnew/specctra_export.cpp index 1499444a78..990625a56b 100644 --- a/pcbnew/specctra_export.cpp +++ b/pcbnew/specctra_export.cpp @@ -668,6 +668,7 @@ PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter, // encode the drill value into the name for later import scale( aDrillDiameter ) ); + name[ sizeof(name)-1 ] = 0; padstack->SetPadstackId( name ); @@ -1238,42 +1239,55 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError ) } - //-----< output the vias >----------------------------------------------- + //-----< output vias used in netclasses and as stock >--------------------- { - // ASSUME: unique pads are now in the padstack list! i.e. this code - // must follow the initial padstack construction code. - // Next we add the via's which may be used. + NETCLASSES& nclasses = aBoard->m_NetClasses; - int defaultViaSize = aBoard->m_NetClasses.GetDefault()->GetViaDiameter(); - int defaultViaDrill = aBoard->m_NetClasses.GetDefault()->GetViaDrill(); -/** - *@todo: *** output vias sizes and drill in NetClasses and in stock *** -*/ - /* I need at least one via for the (class...) scope below - if( defaultViaSize ) - */ - { - PADSTACK* padstack = makeVia( defaultViaSize, defaultViaDrill, - 0, aBoard->GetCopperLayerCount()-1 ); - pcb->library->AddPadstack( padstack ); + // Add the via from the Default netclass first. The via container + // in pcb->library preserves the sequence of addition. - // remember this index, it is the default via and also the start of the - // vias within the padstack list. Before this index are the pads. - // At this index and later are the vias. - pcb->library->SetViaStartIndex( pcb->library->padstacks.size()-1 ); - } + NETCLASS* netclass = nclasses.GetDefault(); + PADSTACK* via = makeVia( netclass->GetViaDiameter(), netclass->GetViaDrill(), + 0, aBoard->GetCopperLayerCount()-1 ); + + // we AppendVia() this first one, there is no way it can be a duplicate, + // the pcb->library via container is empty at this point. After this, + // we'll have to use LookupVia(). + wxASSERT( pcb->library->vias.size() == 0 ); + pcb->library->AppendVia( via ); + + // output the stock vias, but preserve uniqueness in the via container by + // using LookupVia(). for( unsigned i=0; i < aBoard->m_ViasDimensionsList.size(); ++i ) { - int viaSize = aBoard->m_ViasDimensionsList[i].m_Diameter; + int viaSize = aBoard->m_ViasDimensionsList[i].m_Diameter; int viaDrill = aBoard->m_ViasDimensionsList[i].m_Drill; - if( viaSize == defaultViaSize ) - continue; + via = makeVia( viaSize, viaDrill, + 0, aBoard->GetCopperLayerCount()-1 ); - PADSTACK* padstack = makeVia( viaSize, viaDrill, - 0, aBoard->GetCopperLayerCount()-1 ); - pcb->library->AddPadstack( padstack ); + // maybe add 'via' to the library, but only if unique. + PADSTACK* registered = pcb->library->LookupVia( via ); + if( registered != via ) + delete via; + } + + // set the "spare via" index at the start of the + // pcb->library->spareViaIndex = pcb->library->vias.size(); + + // output the non-Default netclass vias + for( NETCLASSES::iterator nc = nclasses.begin(); nc != nclasses.end(); ++nc ) + { + netclass = nc->second; + + via = makeVia( netclass->GetViaDiameter(), netclass->GetViaDrill(), + 0, aBoard->GetCopperLayerCount()-1 ); + + // maybe add 'via' to the library, but only if unique. + PADSTACK* registered = pcb->library->LookupVia( via ); + if( registered != via ) + delete via; } } @@ -1391,25 +1405,17 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError ) //------------------------------------------------------ { - // Output the vias in the padstack list here, by name. This must - // be done after exporting existing vias as WIRE_VIAs. - VIA* vias = pcb->structure->via; - PADSTACKS& padstacks = pcb->library->padstacks; - int viaNdx = pcb->library->via_start_index; + // The pcb->library will output which is a combined + // list of part padstacks and via padstacks. specctra dsn uses the + // to say which of those padstacks are vias. - if( viaNdx != -1 ) + // Output the vias in the padstack list here, by name only. This must + // be done after exporting existing vias as WIRE_VIAs. + VIA* vias = pcb->structure->via; + + for( unsigned viaNdx=0; viaNdx < pcb->library->vias.size(); ++viaNdx ) { -#if 1 - for( ; viaNdx < (int)padstacks.size(); ++viaNdx ) - { - vias->AppendVia( padstacks[viaNdx].padstack_id.c_str() ); - } -#else - // output only the default via. Then use class_descriptors to - // override the default. No, this causes free router not to - // output the unmentioned vias into the session file. - vias->AppendVia( padstacks[viaNdx].padstack_id.c_str() ); -#endif + vias->AppendVia( pcb->library->vias[viaNdx].padstack_id.c_str() ); } } @@ -1417,19 +1423,48 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError ) //--------------------------------------------------------- NETCLASSES& nclasses = aBoard->m_NetClasses; - exportNETCLASS( nclasses.GetDefault() ); + exportNETCLASS( nclasses.GetDefault(), aBoard ); for( NETCLASSES::iterator nc = nclasses.begin(); nc != nclasses.end(); ++nc ) { NETCLASS* netclass = nc->second; - exportNETCLASS( netclass ); + exportNETCLASS( netclass, aBoard ); } } -void SPECCTRA_DB::exportNETCLASS( NETCLASS* aNetClass ) +void SPECCTRA_DB::exportNETCLASS( NETCLASS* aNetClass, BOARD* aBoard ) { - char text[80]; + +/* From page 11 of specctra spec: + + Routing and Placement Rule Hierarchies + + Routing and placement rules can be defined at multiple levels of design + specification. When a routing or placement rule is defined for an object at + multiple levels, a predefined routing or placement precedence order + automatically determines which rule to apply to the object. The routing rule + precedence order is + + pcb < layer < class < class layer < group_set < group_set layer < net < + net layer < group < group layer < fromto < fromto layer < class_class < + class_class layer < padstack < region < class region < net region < + class_class region + + A pcb rule (global rule for the PCB design) has the lowest precedence in the + hierarchy. A class-to-class region rule has the highest precedence. Rules + set at one level of the hierarchy override conflicting rules set at lower + levels. The placement rule precedence order is + + pcb < image_set < image < component < super cluster < room < + room_image_set < family_family < image_image + + A pcb rule (global rule for the PCB design) has the lowest precedence in the + hierarchy. An image-to-image rule has the highest precedence. Rules set at + one level of the hierarchy override conflicting rules set at lower levels. +*/ + + char text[256]; CLASS* clazz = new CLASS( pcb->network ); pcb->network->classes.push_back( clazz ); @@ -1457,15 +1492,20 @@ void SPECCTRA_DB::exportNETCLASS( NETCLASS* aNetClass ) if( aNetClass->GetName() == NETCLASS::Default ) { clazz->class_id = "kicad_default"; + } - int viaNdx = pcb->library->via_start_index; - sprintf( text, "(use_via %s)", pcb->library->padstacks[viaNdx].padstack_id.c_str() ); - clazz->circuit.push_back( text ); - } - else - { - // @todo - } + // the easiest way to get the via name is to create a via (which generates + // the name internal to the PADSTACK), and then grab the name and then + // delete the via. There are not that many netclasses so + // this should never become a performance issue. + + PADSTACK* via = makeVia( aNetClass->GetViaDiameter(), aNetClass->GetViaDrill(), + 0, aBoard->GetCopperLayerCount()-1 ); + + snprintf( text, sizeof(text), "(use_via %s)", via->GetPadstackId().c_str() ); + clazz->circuit.push_back( text ); + + delete via; }