From 0c6a37f89e4274bce4cd77bf4cd49600aeee8f26 Mon Sep 17 00:00:00 2001 From: dickelbeck Date: Mon, 2 Nov 2009 05:20:58 +0000 Subject: [PATCH] ++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. --- CHANGELOG.txt | 13 ++- pcbnew/dialog_design_rules.cpp | 64 +++++++++++- pcbnew/dialog_design_rules.h | 7 +- pcbnew/dialog_design_rules_base.cpp | 19 ++-- pcbnew/dialog_design_rules_base.fbp | 14 +-- pcbnew/specctra.h | 39 ++++--- pcbnew/specctra_export.cpp | 152 ++++++++++++++++++---------- 7 files changed, 218 insertions(+), 90 deletions(-) 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; }