void ROUTER_TOOL::handleCommonEvents( const TOOL_EVENT& aEvent )
{
#ifdef DEBUG
    if( aEvent.IsKeyPressed() )
    {
        switch( aEvent.KeyCode() )
        {
            case 'S':
                TRACEn( 2, "saving drag/route log...\n" );
                m_router->DumpLog();
                break;
        }
    }
    else
#endif
    if( aEvent.IsAction( &ACT_RouterOptions ) )
    {
        DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );

        if( settingsDlg.ShowModal() )
	    {
            // FIXME: do we need an explicit update?
        }
    }
    else if( aEvent.IsAction( &ACT_SetDpDimensions ) )
    {
        PNS_SIZES_SETTINGS sizes = m_router->Sizes();
        DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( m_frame, sizes );

        if( settingsDlg.ShowModal() )
        {
            m_router->UpdateSizes( sizes );
        }
    }
    else if( aEvent.IsAction( &ACT_CustomTrackWidth ) )
    {
        BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
        DIALOG_TRACK_VIA_SIZE sizeDlg( m_frame, bds );

        if( sizeDlg.ShowModal() )
        {
            bds.UseCustomTrackViaSize( true );
            m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged );
        }
    }

    else if( aEvent.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) )
    {

        PNS_SIZES_SETTINGS sizes ( m_router->Sizes() );
        sizes.ImportCurrent ( m_board->GetDesignSettings() );
        m_router->UpdateSizes ( sizes );
    }
}
bool ROUTER_TOOL::onViaCommand( VIATYPE_T aType )
{
    BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();

    const int layerCount = bds.GetCopperLayerCount();
    int currentLayer = m_router->GetCurrentLayer();

    PNS_SIZES_SETTINGS sizes = m_router->Sizes();

    // fixme: P&S supports more than one fixed layer pair. Update the dialog?
    sizes.ClearLayerPairs();
    sizes.AddLayerPair( m_frame->GetScreen()->m_Route_Layer_TOP,
                        m_frame->GetScreen()->m_Route_Layer_BOTTOM );

    if( !m_router->IsPlacingVia() )
    {
        // Cannot place microvias or blind vias if not allowed (obvious)
        if( ( aType == VIA_BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
            return false;

        if( ( aType == VIA_MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
            return false;

        //Can only place through vias on 2-layer boards
        if( ( aType != VIA_THROUGH ) && ( layerCount <= 2 ) )
            return false;

        //Can only place microvias if we're on an outer layer, or directly adjacent to one
        if( ( aType == VIA_MICROVIA ) && ( currentLayer > In1_Cu ) && ( currentLayer < layerCount-2 ) )
            return false;

        //Cannot place blind vias with front/back as the layer pair, this doesn't make sense
        if( ( aType == VIA_BLIND_BURIED ) && ( sizes.GetLayerTop() == F_Cu ) && ( sizes.GetLayerBottom() == B_Cu ) )
            return false;
    }

    sizes.SetViaType( aType );
    if( VIA_MICROVIA == aType )
    {
        sizes.SetViaDiameter( bds.GetCurrentMicroViaSize() );
        sizes.SetViaDrill( bds.GetCurrentMicroViaDrill() );
    }

    m_router->UpdateSizes( sizes );
    m_router->ToggleViaPlacement();

    m_router->Move( m_endSnapPoint, m_endItem );        // refresh

    return false;
}
bool ROUTER_TOOL::prepareInteractive()
{
    int routingLayer = getStartLayer ( m_startItem );
    m_frame->SetActiveLayer( ToLAYER_ID ( routingLayer ) );

    // fixme: switch on invisible layer

    if( m_startItem && m_startItem->Net() >= 0 )
    {
        highlightNet( true, m_startItem->Net() );
        // Update track width and via size shown in main toolbar comboboxes
        m_frame->SetCurrentNetClass( m_startItem->Parent()->GetNetClass()->GetName() );
    }
    else
        m_frame->SetCurrentNetClass( NETCLASS::Default );

    m_ctls->ForceCursorPosition( false );
    m_ctls->SetAutoPan( true );

    PNS_SIZES_SETTINGS sizes ( m_router->Sizes() );

    sizes.Init ( m_board, m_startItem );
    sizes.AddLayerPair ( m_frame->GetScreen()->m_Route_Layer_TOP,
                         m_frame->GetScreen()->m_Route_Layer_BOTTOM );
    m_router->UpdateSizes( sizes );

    if ( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
    {
        wxMessageBox ( m_router->FailureReason(), _( "Error" ) );
        highlightNet ( false );
        return false;
    }

    m_endItem = NULL;
    m_endSnapPoint = m_startSnapPoint;

    return true;
}
bool ROUTER_TOOL::onViaCommand( TOOL_EVENT& aEvent, VIATYPE_T aType )
{
    BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();

    const int layerCount = bds.GetCopperLayerCount();
    int currentLayer = m_router->GetCurrentLayer();
    LAYER_ID pairTop = m_frame->GetScreen()->m_Route_Layer_TOP;
    LAYER_ID pairBottom = m_frame->GetScreen()->m_Route_Layer_BOTTOM;

    PNS_SIZES_SETTINGS sizes = m_router->Sizes();

    // fixme: P&S supports more than one fixed layer pair. Update the dialog?
    sizes.ClearLayerPairs();

    if( !m_router->IsPlacingVia() )
    {
        // Cannot place microvias or blind vias if not allowed (obvious)
        if( ( aType == VIA_BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
        {
            DisplayError( m_frame, _( "Blind/buried vias have to be enabled in the design settings." ) );
            return false;
        }

        if( ( aType == VIA_MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
        {
            DisplayError( m_frame, _( "Microvias have to be enabled in the design settings." ) );
            return false;
        }

        // Can only place through vias on 2-layer boards
        if( ( aType != VIA_THROUGH ) && ( layerCount <= 2 ) )
        {
            DisplayError( m_frame, _( "Only through vias are allowed on 2 layer boards." ) );
            return false;
        }

        // Can only place microvias if we're on an outer layer, or directly adjacent to one
        if( ( aType == VIA_MICROVIA ) && ( currentLayer > In1_Cu ) && ( currentLayer < layerCount - 2 ) )
        {
            DisplayError( m_frame, _( "Microvias can be placed only between the outer layers " \
                                      "(F.Cu/B.Cu) and the ones directly adjacent to them." ) );
            return false;
        }
    }

    // Convert blind/buried via to a through hole one, if it goes through all layers
    if( aType == VIA_BLIND_BURIED && ( ( currentLayer == B_Cu ) || ( currentLayer == F_Cu ) )
                                    && ( ( pairTop == B_Cu && pairBottom == F_Cu )
                                      || ( pairTop == F_Cu && pairBottom == B_Cu ) ) )
    {
        aType = VIA_THROUGH;
    }

    switch( aType )
    {
    case VIA_THROUGH:
        sizes.SetViaDiameter( bds.GetCurrentViaSize() );
        sizes.SetViaDrill( bds.GetCurrentViaDrill() );
        sizes.AddLayerPair( pairTop, pairBottom );
        break;

    case VIA_MICROVIA:
        sizes.SetViaDiameter( bds.GetCurrentMicroViaSize() );
        sizes.SetViaDrill( bds.GetCurrentMicroViaDrill() );

        if( currentLayer == F_Cu || currentLayer == In1_Cu )
            sizes.AddLayerPair( F_Cu, In1_Cu );
        else if( currentLayer == B_Cu || currentLayer == layerCount - 2 )
            sizes.AddLayerPair( B_Cu, layerCount - 2 );
        else
            wxASSERT( false );
        break;

    case VIA_BLIND_BURIED:
        sizes.SetViaDiameter( bds.GetCurrentViaSize() );
        sizes.SetViaDrill( bds.GetCurrentViaDrill() );

        if( currentLayer == pairTop || currentLayer == pairBottom )
            sizes.AddLayerPair( pairTop, pairBottom );
        else
            sizes.AddLayerPair( pairTop, currentLayer );
        break;

    default:
        wxASSERT( false );
        break;
    }

    sizes.SetViaType( aType );

    m_router->UpdateSizes( sizes );
    m_router->ToggleViaPlacement();

    updateEndItem( aEvent );

    m_router->Move( m_endSnapPoint, m_endItem );        // refresh

    return false;
}