bool NETCLASSES::Add( NETCLASSPTR aNetClass )
{
    const wxString& name = aNetClass->GetName();

    if( name == NETCLASS::Default )
    {
        // invoke operator=(), which is currently generated by compiler.
        m_Default = aNetClass;

        return true;
    }

    // Test for an existing netclass:
    if( !Find( name ) )
    {
        // name not found, take ownership
        m_NetClasses[name] = aNetClass;

        return true;
    }
    else
    {
        // name already exists
        // do not "take ownership" and return false telling caller such.
        return false;
    }
}
static void class2gridRow( wxGrid* grid, int row, NETCLASSPTR nc )
{
    wxString msg;

    // label is netclass name
    grid->SetRowLabelValue( row, nc->GetName() );

    msg = StringFromValue( g_UserUnit, nc->GetClearance() );
    grid->SetCellValue( row, GRID_CLEARANCE, msg );

    msg = StringFromValue( g_UserUnit, nc->GetTrackWidth() );
    grid->SetCellValue( row, GRID_TRACKSIZE, msg );

    msg = StringFromValue( g_UserUnit, nc->GetViaDiameter() );
    grid->SetCellValue( row, GRID_VIASIZE, msg );

    msg = StringFromValue( g_UserUnit, nc->GetViaDrill() );
    grid->SetCellValue( row, GRID_VIADRILL, msg );

    msg = StringFromValue( g_UserUnit, nc->GetuViaDiameter() );
    grid->SetCellValue( row, GRID_uVIASIZE, msg );

    msg = StringFromValue( g_UserUnit, nc->GetuViaDrill() );
    grid->SetCellValue( row, GRID_uVIADRILL, msg );
}
bool BOARD_DESIGN_SETTINGS::SetCurrentNetClass( const wxString& aNetClassName )
{
    NETCLASSPTR netClass = m_NetClasses.Find( aNetClassName );
    bool        lists_sizes_modified = false;

    // if not found (should not happen) use the default
    if( netClass == NULL )
        netClass = m_NetClasses.GetDefault();

    m_currentNetClassName = netClass->GetName();

    // Initialize others values:
    if( m_ViasDimensionsList.size() == 0 )
    {
        VIA_DIMENSION viadim;
        lists_sizes_modified = true;
        m_ViasDimensionsList.push_back( viadim );
    }

    if( m_TrackWidthList.size() == 0 )
    {
        lists_sizes_modified = true;
        m_TrackWidthList.push_back( 0 );
    }

    /* note the m_ViasDimensionsList[0] and m_TrackWidthList[0] values
     * are always the Netclass values
     */
    if( m_ViasDimensionsList[0].m_Diameter != netClass->GetViaDiameter() )
    {
        lists_sizes_modified = true;
        m_ViasDimensionsList[0].m_Diameter = netClass->GetViaDiameter();
    }

    if( m_ViasDimensionsList[0].m_Drill != netClass->GetViaDrill() )
    {
        lists_sizes_modified = true;
        m_ViasDimensionsList[0].m_Drill = netClass->GetViaDrill();
    }

    if( m_TrackWidthList[0] != netClass->GetTrackWidth() )
    {
        lists_sizes_modified = true;
        m_TrackWidthList[0] = netClass->GetTrackWidth();
    }

    if( GetViaSizeIndex() >= m_ViasDimensionsList.size() )
        SetViaSizeIndex( m_ViasDimensionsList.size() );

    if( GetTrackWidthIndex() >= m_TrackWidthList.size() )
        SetTrackWidthIndex( m_TrackWidthList.size() );

    return lists_sizes_modified;
}
void DIALOG_DESIGN_RULES::InitDialogRules()
{
    // @todo:  Move the initialization code into TransferDataToWindow() to follow wxWidgets
    //         dialog data transfer convention.
    SetFocus();
    SetReturnCode( 0 );

    m_Pcb = m_Parent->GetBoard();
    m_BrdSettings = &m_Pcb->GetDesignSettings();

    // Initialize the Rules List
    InitRulesList();

    // copy all NETs into m_AllNets by adding them as NETCUPs.

    // @todo go fix m_Pcb->SynchronizeNetsAndNetClasses() so that the netcode==0 is not
    //       present in the BOARD::m_NetClasses
    NETCLASSES& netclasses = m_BrdSettings->m_NetClasses;
    NETCLASSPTR netclass = netclasses.GetDefault();

    // Initialize list of nets for Default Net Class
    for( NETCLASS::iterator name = netclass->begin();  name != netclass->end();  ++name )
    {
        m_AllNets.push_back( NETCUP( *name, netclass->GetName() ) );
    }

    // Initialize list of nets for others (custom) Net Classes
    for( NETCLASSES::const_iterator nc = netclasses.begin();  nc != netclasses.end();  ++nc )
    {
        netclass = nc->second;

        for( NETCLASS::const_iterator name = netclass->begin();  name != netclass->end();  ++name )
        {
            m_AllNets.push_back( NETCUP( *name, netclass->GetName() ) );
        }
    }

    InitializeRulesSelectionBoxes();
    InitGlobalRules();
}
    void SaveParam( wxConfigBase* aConfig ) const override
    {
        if( !m_Pt_param || !aConfig )
            return;

        wxString                   oldPath = aConfig->GetPath();
        NETCLASSES::const_iterator nc = m_Pt_param->begin();

        for( unsigned index = 0; index <= m_Pt_param->GetCount(); ++index )
        {
            wxString    path = "";
            NETCLASSPTR netclass;

            if( index == 0 )
                path = "Default";
            else
                path << index;

            aConfig->SetPath( oldPath );
            aConfig->SetPath( m_Ident );
            aConfig->SetPath( path );

            if( index == 0 )
            {
                netclass = m_Pt_param->GetDefault();
            }
            else
            {
                netclass = nc->second;
                ++nc;
            }

            aConfig->Write( NetclassNameKey, netclass->GetName() );

#define WRITE_MM( aKey, aValue ) aConfig->Write( aKey, Iu2Millimeter( aValue ) )
            WRITE_MM( ClearanceKey,    netclass->GetClearance() );
            WRITE_MM( TrackWidthKey,   netclass->GetTrackWidth() );
            WRITE_MM( ViaDiameterKey,  netclass->GetViaDiameter() );
            WRITE_MM( ViaDrillKey,     netclass->GetViaDrill() );
            WRITE_MM( uViaDiameterKey, netclass->GetuViaDiameter() );
            WRITE_MM( uViaDrillKey,    netclass->GetuViaDrill() );
            WRITE_MM( dPairWidthKey,   netclass->GetDiffPairWidth() );
            WRITE_MM( dPairGapKey,     netclass->GetDiffPairGap() );
            WRITE_MM( dPairViaGapKey,  netclass->GetDiffPairViaGap() );
        }

        aConfig->SetPath( oldPath );
    }
// see class_track.h
void TRACK::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
{
    wxString msg;
    BOARD*   board = GetBoard();

    // Display basic infos
    GetMsgPanelInfoBase( aList );

    // Display full track length (in Pcbnew)
    if( board )
    {
        double trackLen = 0;
        double lenPadToDie = 0;
        board->MarkTrace( this, NULL, &trackLen, &lenPadToDie, false );
        msg = ::CoordinateToString( trackLen );
        aList.push_back( MSG_PANEL_ITEM( _( "Track Len" ), msg, DARKCYAN ) );

        if( lenPadToDie != 0 )
        {
            msg = ::LengthDoubleToString( trackLen + lenPadToDie );
            aList.push_back( MSG_PANEL_ITEM( _( "Full Len" ), msg, DARKCYAN ) );

            msg = ::LengthDoubleToString( lenPadToDie );
            aList.push_back( MSG_PANEL_ITEM( _( "In Package" ), msg, DARKCYAN ) );
        }
    }

    NETCLASSPTR netclass = GetNetClass();

    if( netclass )
    {
        aList.push_back( MSG_PANEL_ITEM( _( "NC Name" ), netclass->GetName(), DARKMAGENTA ) );
        aList.push_back( MSG_PANEL_ITEM( _( "NC Clearance" ),
                                         ::CoordinateToString( netclass->GetClearance(), true ),
                                         DARKMAGENTA ) );
        aList.push_back( MSG_PANEL_ITEM( _( "NC Width" ),
                                         ::CoordinateToString( netclass->GetTrackWidth(), true ),
                                         DARKMAGENTA ) );
        aList.push_back( MSG_PANEL_ITEM( _( "NC Via Size" ),
                                         ::CoordinateToString( netclass->GetViaDiameter(), true ),
                                         DARKMAGENTA ) );
        aList.push_back( MSG_PANEL_ITEM( _( "NC Via Drill"),
                                         ::CoordinateToString( netclass->GetViaDrill(), true ),
                                         DARKMAGENTA ) );
    }
}
bool DRC::doNetClass( NETCLASSPTR nc, wxString& msg )
{
    bool ret = true;

    const BOARD_DESIGN_SETTINGS& g = m_pcb->GetDesignSettings();

#define FmtVal( x ) GetChars( StringFromValue( g_UserUnit, x ) )

#if 0   // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
    if( nc->GetClearance() < g.m_MinClearance )
    {
        msg.Printf( _( "NETCLASS: '%s' has Clearance:%s which is less than global:%s" ),
                    GetChars( nc->GetName() ),
                    FmtVal( nc->GetClearance() ),
                    FmtVal( g.m_TrackClearance )
                    );

        addMarkerToPcb( fillMarker( DRCE_NETCLASS_CLEARANCE, msg, m_currentMarker ) );
        m_currentMarker = nullptr;
        ret = false;
    }
#endif

    if( nc->GetTrackWidth() < g.m_TrackMinWidth )
    {
        msg.Printf( _( "NETCLASS: '%s' has TrackWidth:%s which is less than global:%s" ),
                    GetChars( nc->GetName() ),
                    FmtVal( nc->GetTrackWidth() ),
                    FmtVal( g.m_TrackMinWidth )
                    );

        addMarkerToPcb( fillMarker( DRCE_NETCLASS_TRACKWIDTH, msg, m_currentMarker ) );
        m_currentMarker = nullptr;
        ret = false;
    }

    if( nc->GetViaDiameter() < g.m_ViasMinSize )
    {
        msg.Printf( _( "NETCLASS: '%s' has Via Dia:%s which is less than global:%s" ),
                    GetChars( nc->GetName() ),
                    FmtVal( nc->GetViaDiameter() ),
                    FmtVal( g.m_ViasMinSize )
                    );

        addMarkerToPcb( fillMarker( DRCE_NETCLASS_VIASIZE, msg, m_currentMarker ) );
        m_currentMarker = nullptr;
        ret = false;
    }

    if( nc->GetViaDrill() < g.m_ViasMinDrill )
    {
        msg.Printf( _( "NETCLASS: '%s' has Via Drill:%s which is less than global:%s" ),
                    GetChars( nc->GetName() ),
                    FmtVal( nc->GetViaDrill() ),
                    FmtVal( g.m_ViasMinDrill )
                    );

        addMarkerToPcb( fillMarker( DRCE_NETCLASS_VIADRILLSIZE, msg, m_currentMarker ) );
        m_currentMarker = nullptr;
        ret = false;
    }

    if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
    {
        msg.Printf( _( "NETCLASS: '%s' has uVia Dia:%s which is less than global:%s" ),
                    GetChars( nc->GetName() ),
                    FmtVal( nc->GetuViaDiameter() ),
                    FmtVal( g.m_MicroViasMinSize )
                    );

        addMarkerToPcb( fillMarker( DRCE_NETCLASS_uVIASIZE, msg, m_currentMarker ) );
        m_currentMarker = nullptr;
        ret = false;
    }

    if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
    {
        msg.Printf( _( "NETCLASS: '%s' has uVia Drill:%s which is less than global:%s" ),
                    GetChars( nc->GetName() ),
                    FmtVal( nc->GetuViaDrill() ),
                    FmtVal( g.m_MicroViasMinDrill )
                    );

        addMarkerToPcb( fillMarker( DRCE_NETCLASS_uVIADRILLSIZE, msg, m_currentMarker ) );
        m_currentMarker = nullptr;
        ret = false;
    }

    return ret;
}