* 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.
This commit is contained in:
dickelbeck 2009-11-02 05:20:58 +00:00
parent ba78c6ec5e
commit 0c6a37f89e
7 changed files with 218 additions and 90 deletions

View File

@ -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 <dick@softplc.com>
================================================================================
++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 <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
++pcbnew
@ -19,8 +30,6 @@ email address.
accessible by a specific dialog frame.
2009-oct-27 UPDATE Jerry Jacobs <xor.gate.engineering@gmail.com>
================================================================================
++common

View File

@ -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; col<colCount; ++col )
{
// add two spaces to the text and size it.
wxString colText = aGrid->GetColLabelValue( 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();

View File

@ -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 );

View File

@ -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 );

View File

@ -29,10 +29,10 @@
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">600,520</property>
<property name="minimum_size">-1,-1</property>
<property name="name">DIALOG_DESIGN_RULES_BASE</property>
<property name="pos"></property>
<property name="size">850,692</property>
<property name="size">900,600</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass"></property>
<property name="title">Design Rules Editor</property>
@ -128,7 +128,7 @@
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">Net Classes Editor</property>
<property name="select">0</property>
<property name="select">1</property>
<object class="wxPanel" expanded="1">
<property name="bg"></property>
<property name="context_help"></property>
@ -206,7 +206,7 @@
<property name="col_label_values">&quot;Clearance&quot; &quot;Track Width&quot; &quot;Via Dia&quot; &quot;Via Drill&quot; &quot;uVia Dia&quot; &quot;uVia Drill&quot;</property>
<property name="col_label_vert_alignment">wxALIGN_CENTRE</property>
<property name="cols">6</property>
<property name="column_sizes">100,100,100,100,100</property>
<property name="column_sizes">100,120,84,85,81,90</property>
<property name="context_help"></property>
<property name="drag_col_move">0</property>
<property name="drag_col_size">1</property>
@ -301,7 +301,7 @@
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_HORIZONTAL</property>
<property name="flag">wxALIGN_CENTER_HORIZONTAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
@ -969,7 +969,7 @@
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">Global Design Rules</property>
<property name="select">1</property>
<property name="select">0</property>
<object class="wxPanel" expanded="1">
<property name="bg"></property>
<property name="context_help"></property>
@ -2071,7 +2071,7 @@
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label"> </property>
<property name="label"></property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_staticText8</property>

View File

@ -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; i<vias.size(); ++i )
{
for( unsigned i=via_start_index; i<padstacks.size(); ++i )
{
if( 0 == PADSTACK::Compare( aVia, &padstacks[i] ) )
return (int) i;
}
if( 0 == PADSTACK::Compare( aVia, &vias[i] ) )
return int( i );
}
return -1;
}
/**
* Function AppendVia
* adds \a aVia to the internal via container.
*/
void AppendVia( PADSTACK* aVia )
{
aVia->SetParent( 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 );
//-----</FromBOARD>------------------------------------------------------

View File

@ -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 )
//-----<via_descriptor>-------------------------------------------------
{
// 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 <padstack_descriptors> which is a combined
// list of part padstacks and via padstacks. specctra dsn uses the
// <via_descriptors> 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 )
//-----<output NETCLASSs>----------------------------------------------------
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;
}