int WinEDA_BasePcbFrame::Test_1_Net_Ratsnest(wxDC * DC, int ref_netcode)
{

	affiche_chevelu = FALSE;
	DrawGeneralRatsnest(DC, ref_netcode);
	Tst_Ratsnest(DC, ref_netcode );
	DrawGeneralRatsnest(DC, ref_netcode);

	return m_Pcb->GetNumRatsnests();
}
/* Draw the BOARD, and others elements : axis, grid ..
 */
void PCB_EDIT_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
{
    PCB_SCREEN* screen = GetScreen();

    if( !GetBoard() || !screen )
        return;

    GRSetDrawMode( DC, GR_COPY );

    m_canvas->DrawBackGround( DC );

    DrawWorkSheet( DC, GetScreen(), g_DrawDefaultLineThickness,
                    IU_PER_MILS, GetBoard()->GetFileName() );

    GetBoard()->Draw( m_canvas, DC, GR_OR | GR_ALLOW_HIGHCONTRAST );

    DrawGeneralRatsnest( DC );

#ifdef USE_WX_OVERLAY

    if( IsShown() )
    {
        m_overlay.Reset();
        wxDCOverlay overlaydc( m_overlay, (wxWindowDC*) DC );
        overlaydc.Clear();
    }

#endif

    if( m_canvas->IsMouseCaptured() )
        m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );

    // Redraw the cursor
    m_canvas->DrawCrossHair( DC );
}
void WinEDA_PcbFrame::StartMove_Module(MODULE * module, wxDC * DC)
/**********************************************************************/
{

	if (module == NULL ) return;

	m_CurrentScreen->m_CurrentItem = module;
	m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
	module->m_Flags |= IS_MOVED;
	ModuleInitOrient = module->m_Orient;
	ModuleInitLayer = module->m_Layer;

	/* Effacement chevelu general si necessaire */
	if(g_Show_Ratsnest) DrawGeneralRatsnest(DC);

	if( g_DragSegmentList ) /* Anormal ! */
	{
		EraseDragListe();
	}

	if( g_Drag_Pistes_On)
	{
		Build_Drag_Liste(DrawPanel, DC, module);
	}

	m_Pcb->m_Status_Pcb |= DO_NOT_SHOW_GENERAL_RASTNEST;
	m_CurrentScreen->ManageCurseur = Montre_Position_Empreinte;
	m_CurrentScreen->ForceCloseManageCurseur = Exit_Module;
	DrawPanel->m_AutoPAN_Request = TRUE;

	// effacement module a l'ecran:
	module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);
	// Reaffichage
	m_CurrentScreen->ManageCurseur(DrawPanel, DC, FALSE);
}
void WinEDA_BasePcbFrame::Rotate_Module(wxDC * DC, MODULE * module,
				int angle, bool incremental)
/***********************************************************************/
/*
	Fait tourner l'empreinte de angle degres, dans le sens < 0.
	Si incremental == TRUE, la rotation est faite a partir de la derniere orientation,
	sinon le module est mis dans l'orientation absolue angle.
	Si DC == NULL, le composant n'est pas redessine.
	Sinon, il est efface, tourne et redessine
*/
{
	if ( module == NULL ) return;

	m_CurrentScreen->SetModify();

	/* efface ancienne position */
	if( !(module->m_Flags & IS_MOVED) ) /* Rotation simple */
	{
		if ( DC )
		{
			module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);
			 /* Reaffichage chevelu general si necessaire */
			if(g_Show_Ratsnest) DrawGeneralRatsnest(DC);
		}
	}
	else
	{
		/* reaffiche module en mouvement */
		if ( DC )
		{
			DrawModuleOutlines(DrawPanel, DC, module);
			Dessine_Segments_Dragges(DrawPanel, DC);
		}
	}

	m_Pcb->m_Status_Pcb &= ~(LISTE_CHEVELU_OK | CONNEXION_OK);

	if ( incremental )
		module->SetOrientation(module->m_Orient + angle);
	else
		module->SetOrientation(angle);

	module->Display_Infos(this);

	if ( DC )
	{
		if( !(module->m_Flags & IS_MOVED) ) /* Rotation simple */
		{
			module->Draw(DrawPanel, DC, wxPoint(0,0), GR_OR);
			 /* Reaffichage chevelu general si necessaire */
			ReCompile_Ratsnest_After_Changes( DC );
		}
		else
		{
			/* reaffiche module en mouvement */
			DrawModuleOutlines(DrawPanel, DC, module);
			Dessine_Segments_Dragges(DrawPanel, DC);
		}
	}
}
bool WinEDA_PcbFrame::Delete_Module(MODULE * module, wxDC * DC)
/**************************************************************/
/*
Commande Delete Module :
	Suppression d'une empreinte
	les pointeurs divers sont mis a jour
*/
{
EDA_BaseStruct * PtBack, *PtNext;
wxString msg;
	/* Si l'empreinte est selectee , on ne peut pas l'effacer ! */
	if ( module == NULL ) return FALSE;

	/* Confirmation de l'effacement */
	module->Display_Infos(this);

	msg << _("Delete Module") << wxT(" ") << module->m_Reference->m_Text
			<< wxT("  (") << _("Value ") << module->m_Value->m_Text
			<< wxT(") ?");
	if( !IsOK(this, msg ) )
	{
		return FALSE;
	}

	m_CurrentScreen->SetModify();

	/* Erase rastnest if needed */
	if(g_Show_Ratsnest) DrawGeneralRatsnest(DC);

	/* Effacement du module a l'ecran */
	if ( DC ) module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);

	/* Suppression du chainage */
	PtBack = module->Pback;
	PtNext = module->Pnext;
	if( PtBack == (EDA_BaseStruct*) m_Pcb )
		{
		m_Pcb->m_Modules = (MODULE*)PtNext;
		}
	else
		{
		PtBack->Pnext = PtNext;
		}
	if(PtNext) PtNext->Pback = PtBack;

	/* Sauvegarde en buffer des undelete */
	SaveItemEfface( module, 1);

	m_Pcb->m_Status_Pcb = 0 ;
	build_liste_pads() ;
	ReCompile_Ratsnest_After_Changes( DC );
	return TRUE;
}
void WinEDA_PcbFrame::Ratsnest_On_Off(wxDC * DC)
/***********************************************/

/* Affiche ou efface le chevelu selon l'etat du bouton d'appel */
{
int ii;
CHEVELU * pt_chevelu;

	if((m_Pcb->m_Status_Pcb & LISTE_CHEVELU_OK) == 0 )
		{
		if ( g_Show_Ratsnest ) Compile_Ratsnest( DC, TRUE );
		return;
		}

	DrawGeneralRatsnest(DC, 0); /* effacement eventuel du chevelu affiche */

	pt_chevelu = m_Pcb->m_Ratsnest;
	if ( pt_chevelu == NULL ) return;

	if(g_Show_Ratsnest)
	{
		for( ii = m_Pcb->GetNumRatsnests(); ii > 0 ; pt_chevelu++, ii--)
		{
			pt_chevelu->status |= CH_VISIBLE;
		}
		DrawGeneralRatsnest(DC, 0);
	}

	else
	{
		for( ii = m_Pcb->GetNumRatsnests(); ii > 0; pt_chevelu++, ii--)
		{
			pt_chevelu->status &= ~CH_VISIBLE;
		}
	}
}
Exemple #7
0
/**
 * Function Compile_Ratsnest
 *  Create the entire board ratsnest.
 *  Must be called after a board change (changes for
 *  pads, footprints or a read netlist ).
 * @param aDC = the current device context (can be NULL)
 * @param aDisplayStatus : if true, display the computation results
 */
void PCB_BASE_FRAME::Compile_Ratsnest( wxDC* aDC, bool aDisplayStatus )
{
    wxString msg;

    GetBoard()->m_Status_Pcb = 0;   // we want a full ratsnest computation, from the scratch
    ClearMsgPanel();

    // Rebuild the full pads and net info list
    RecalculateAllTracksNetcode();

    if( aDisplayStatus )
    {
        msg.Printf( wxT( " %d" ), m_Pcb->GetPadCount() );
        AppendMsgPanel( wxT( "Pads" ), msg, RED );
        msg.Printf( wxT( " %d" ), m_Pcb->GetNetCount() );
        AppendMsgPanel( wxT( "Nets" ), msg, CYAN );
    }

    /* Compute the full ratsnest
     *  which can be see like all the possible links or logical connections.
     *  some of them are active (no track connected) and others are inactive
     * (when tracks connect pads)
     *  This full ratsnest is not modified by track editing.
     *  It changes only when a netlist is read, or footprints are modified
     */
    Build_Board_Ratsnest();

    // Compute the pad connections due to the existing tracks (physical connections)
    TestConnections();

    /* Compute the active ratsnest, i.e. the unconnected links
     */
    TestForActiveLinksInRatsnest( 0 );

    // Redraw the active ratsnest ( if enabled )
    if( GetBoard()->IsElementVisible(RATSNEST_VISIBLE) && aDC )
        DrawGeneralRatsnest( aDC, 0 );

    if( aDisplayStatus )
        SetMsgPanel( m_Pcb );
}
void WinEDA_BasePcbFrame::Compile_Ratsnest( wxDC * DC, bool display_status_pcb )
/******************************************************************************/

/*
	Génère le chevelu complet de la carte.
	Doit etre appelé APRES le calcul de connectivité
	Doit etre appelé apres changement de structure de la carte (modif
 de pads, de nets, de modules).

	Si display_status_pcb : affichage des résultats en bas d'ecran
*/
{
wxString msg;
	
	affiche_chevelu = TRUE;

	/* construction de la liste des coordonnées des pastilles */
	m_Pcb->m_Status_Pcb = 0;		/* réinit total du calcul */
	build_liste_pads() ;
	MsgPanel->EraseMsgBox() ;  /* effacement du bas d'ecran */
	msg.Printf( wxT(" %d"),m_Pcb->m_NbPads) ;
	Affiche_1_Parametre(this, 1, wxT("pads"), msg,RED) ;

	msg.Printf( wxT(" %d"),m_Pcb->m_NbNets) ;
	Affiche_1_Parametre(this, 8, wxT("Nets"), msg,CYAN) ;

	reattribution_reference_piste(display_status_pcb);
	Build_Board_Ratsnest(DC );	/* calcul du chevelu general */
	test_connexions(DC);		/* determine les blocks de pads connectés par
										les pistes existantes */

	Tst_Ratsnest(DC, 0 );	/* calcul du chevelu actif */

	// Reaffichage des chevelus actifs
	if( g_Show_Ratsnest ) DrawGeneralRatsnest( DC, 0 );

	if ( display_status_pcb ) Affiche_Infos_Status_Pcb(this);
}
void PCB_EDIT_FRAME::Show_1_Ratsnest( EDA_ITEM* item, wxDC* DC )
{
    D_PAD*   pt_pad = NULL;
    MODULE*  Module = NULL;

    if( GetBoard()->IsElementVisible(RATSNEST_VISIBLE) )
        return;

    if( ( GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK ) == 0 )
        Compile_Ratsnest( DC, true );

    if( item )
    {
        if( item->Type() == PCB_PAD_T )
        {
            pt_pad = (D_PAD*) item;
            Module = pt_pad->GetParent();
        }

        if( pt_pad ) // Displaying the ratsnest of the corresponding net.
        {
            SetMsgPanel( pt_pad );

            for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
            {
                RATSNEST_ITEM* net = &GetBoard()->m_FullRatsnest[ii];

                if( net->GetNet() == pt_pad->GetNetCode() )
                {
                    if( ( net->m_Status & CH_VISIBLE ) != 0 )
                        continue;

                    net->m_Status |= CH_VISIBLE;

                    if( ( net->m_Status & CH_ACTIF ) == 0 )
                        continue;

                    net->Draw( m_canvas, DC, GR_XOR, wxPoint( 0, 0 ) );
                }
            }
        }
        else
        {
            if( item->Type() == PCB_MODULE_TEXT_T )
            {
                if( item->GetParent() && ( item->GetParent()->Type() == PCB_MODULE_T ) )
                    Module = static_cast<MODULE*>( item->GetParent() );
            }
            else if( item->Type() == PCB_MODULE_T )
            {
                Module = static_cast<MODULE*>( item );
            }

            if( Module )
            {
                SetMsgPanel( Module );
                pt_pad = Module->Pads();

                for( ; pt_pad != NULL; pt_pad = pt_pad->Next() )
                {
                    for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
                    {
                        RATSNEST_ITEM* net = &GetBoard()->m_FullRatsnest[ii];

                        if( ( net->m_PadStart == pt_pad ) || ( net->m_PadEnd == pt_pad ) )
                        {
                            if( net->m_Status & CH_VISIBLE )
                                continue;

                            net->m_Status |= CH_VISIBLE;

                            if( (net->m_Status & CH_ACTIF) == 0 )
                                continue;

                            net->Draw( m_canvas, DC, GR_XOR, wxPoint( 0, 0 ) );
                        }
                    }
                }

                pt_pad = NULL;
            }
        }
    }

    // Erase if no pad or module has been selected.
    if( ( pt_pad == NULL ) && ( Module == NULL ) )
    {
        DrawGeneralRatsnest( DC );

        for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
            GetBoard()->m_FullRatsnest[ii].m_Status &= ~CH_VISIBLE;
    }
}
void WinEDA_PcbFrame::Show_1_Ratsnest(EDA_BaseStruct * item, wxDC * DC)
/**********************************************************************/
/* Affiche le ratsnest relatif
	au net du pad pointe par la souris
	ou au module localise par la souris
	Efface le chevelu affiche si aucun module ou pad n'est selectionne
*/
{
int ii;
CHEVELU * pt_chevelu;
D_PAD * pt_pad = NULL;
MODULE * Module = NULL;

	if (g_Show_Ratsnest) return;	// Deja Affich�

	if((m_Pcb->m_Status_Pcb & LISTE_CHEVELU_OK) == 0 )
		{
		Compile_Ratsnest( DC, TRUE );
		}

	if ( item && (item->m_StructType == TYPEPAD) )
		{
		pt_pad = (D_PAD*)item;
		Module = (MODULE *) pt_pad->m_Parent;
		}

	if ( pt_pad ) /* Affichage du chevelu du net correspondant */
		{
		pt_pad->Display_Infos(this);
		pt_chevelu = (CHEVELU*) m_Pcb->m_Ratsnest;
		for( ii = m_Pcb->GetNumRatsnests(); ii > 0; pt_chevelu++, ii--)
			{
			if( pt_chevelu->m_NetCode == pt_pad->m_NetCode)
				{
				if( (pt_chevelu->status & CH_VISIBLE) != 0 ) continue;
				pt_chevelu->status |= CH_VISIBLE;
				if( (pt_chevelu->status & CH_ACTIF) == 0 ) continue;

				GRSetDrawMode(DC, GR_XOR);
				GRLine( &DrawPanel->m_ClipBox, DC, pt_chevelu->pad_start->m_Pos.x,
									pt_chevelu->pad_start->m_Pos.y,
									pt_chevelu->pad_end->m_Pos.x,
									pt_chevelu->pad_end->m_Pos.y,
									g_DesignSettings.m_RatsnestColor);
				}
			}
		}
	else
		{
		if ( item && (item->m_StructType == TYPEMODULE) )
			{
			Module = (MODULE*)item;
			}

		if( Module)
			{
			Module->Display_Infos(this);
			pt_pad = Module->m_Pads;
			for( ; pt_pad != NULL; pt_pad = (D_PAD*)pt_pad->Pnext)
				{
				pt_chevelu = (CHEVELU*) m_Pcb->m_Ratsnest;
				for( ii = m_Pcb->GetNumRatsnests(); ii > 0; pt_chevelu++, ii--)
					{
					if( (pt_chevelu->pad_start == pt_pad) ||
						(pt_chevelu->pad_end == pt_pad) )
						{
						if( pt_chevelu->status & CH_VISIBLE ) continue;
						pt_chevelu->status |= CH_VISIBLE;
						if( (pt_chevelu->status & CH_ACTIF) == 0 ) continue;

						GRSetDrawMode(DC, GR_XOR);
						GRLine(&DrawPanel->m_ClipBox, DC, pt_chevelu->pad_start->m_Pos.x,
									pt_chevelu->pad_start->m_Pos.y,
									pt_chevelu->pad_end->m_Pos.x,
									pt_chevelu->pad_end->m_Pos.y,
									g_DesignSettings.m_RatsnestColor);
						}
					}
				}
			pt_pad = NULL;
			}
		}

	/* Effacement complet des selections
		si aucun pad ou module n'a ete localise */
	if( (pt_pad == NULL) && (Module == NULL) )
		{
		MsgPanel->EraseMsgBox();
		DrawGeneralRatsnest(DC);
		pt_chevelu = (CHEVELU*) m_Pcb->m_Ratsnest;
		for( ii = m_Pcb->GetNumRatsnests();(ii > 0) && pt_chevelu; pt_chevelu++, ii--)
			pt_chevelu->status &= ~CH_VISIBLE;
		}
}
void WinEDA_PcbFrame::Trace_Pcb(wxDC * DC, int mode)
/****************************************************/
/* Trace l'ensemble des elements du PCB sur l'ecran actif*/
{
MARQUEUR * Marqueur;
MODULE * Module;
EDA_BaseStruct * PtStruct;

	if ( ! m_Pcb ) return;

	Module = (MODULE*) m_Pcb->m_Modules;
	for ( ; Module != NULL; Module = (MODULE *) Module->Pnext )
		{
		bool display = TRUE, MaskLay = ALL_CU_LAYERS;
		if( Module->m_Flags & IS_MOVED ) continue ;

		if( ! DisplayOpt.Show_Modules_Cmp )
			{
			if(Module->m_Layer == CMP_N) display = FALSE;
			MaskLay &= ~CMP_LAYER;
			}
		if( ! DisplayOpt.Show_Modules_Cu )
			{
			if(Module->m_Layer == CUIVRE_N) display = FALSE;
			MaskLay &= ~CUIVRE_LAYER;
			}

		if ( display ) Module->Draw(DrawPanel, DC, wxPoint(0,0), mode);
		else  Trace_Pads_Only(DrawPanel, DC, Module, 0, 0, MaskLay, mode);
		}

	/* Trace des elements particuliers de Drawings Pcb */

	PtStruct = m_Pcb->m_Drawings;
	for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
		{
		if ( PtStruct->m_Flags & IS_MOVED ) continue;

		switch(PtStruct->m_StructType)
			{
			case TYPECOTATION:
				((COTATION*) PtStruct)->Draw(DrawPanel, DC, wxPoint(0,0), mode);
				break;

			case TYPETEXTE:
				((TEXTE_PCB*) PtStruct)->Draw(DrawPanel, DC, wxPoint(0,0), mode );
				break;

			case TYPEMIRE:
				((MIREPCB*) PtStruct)->Draw(DrawPanel, DC, wxPoint(0,0), mode);
				break;

			case TYPEMARQUEUR:	 /* Trace des marqueurs */
				Marqueur = ( MARQUEUR*) PtStruct;
				Marqueur->Draw(DrawPanel, DC, mode);
				break;

			default: break;
			}
		}

	Trace_Pistes(DrawPanel, m_Pcb, DC, mode);
	if ( g_HightLigt_Status ) DrawHightLight(DC, g_HightLigth_NetCode) ;

	EDGE_ZONE * segment = m_Pcb->m_CurrentLimitZone;
	for( ; segment != NULL; segment = (EDGE_ZONE *) segment->Pback)
		{
		if ( segment->m_Flags & IS_MOVED ) continue;
		Trace_DrawSegmentPcb(DrawPanel, DC, segment, mode);
		}

	Trace_PcbEdges(DC, mode);
	DrawGeneralRatsnest(DC);

	m_CurrentScreen->ClrRefreshReq();
}
/* Called on events (popup menus) relative to automove and autoplace footprints
 */
void PCB_EDIT_FRAME::OnPlaceOrRouteFootprints( wxCommandEvent& event )
{
    int        id = event.GetId();

    if( m_mainToolBar == NULL )
        return;

    INSTALL_UNBUFFERED_DC( dc, m_canvas );

    switch( id )
    {
    case ID_POPUP_PCB_AUTOROUTE_SELECT_LAYERS:
        return;

    case ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE:
        LockModule( (MODULE*) GetScreen()->GetCurItem(), true );
        return;

    case ID_POPUP_PCB_AUTOPLACE_FREE_MODULE:
        LockModule( (MODULE*) GetScreen()->GetCurItem(), false );
        return;

    case ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES:
        LockModule( NULL, false );
        return;

    case ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES:
        LockModule( NULL, true );
        return;

    case ID_POPUP_CANCEL_CURRENT_COMMAND:
        if( m_canvas->IsMouseCaptured() )
        {
            m_canvas->CallEndMouseCapture( &dc );
        }

        break;

    default:   // Abort a current command (if any)
        m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
        break;
    }

    // Erase ratsnest if needed
    if( GetBoard()->IsElementVisible(RATSNEST_VISIBLE) )
        DrawGeneralRatsnest( &dc );

    GetBoard()->m_Status_Pcb |= DO_NOT_SHOW_GENERAL_RASTNEST;

    switch( id )
    {
    case ID_POPUP_PCB_AUTOPLACE_CURRENT_MODULE:
        AutoPlaceModule( (MODULE*) GetScreen()->GetCurItem(), PLACE_1_MODULE, &dc );
        break;

    case ID_POPUP_PCB_AUTOPLACE_ALL_MODULES:
        AutoPlaceModule( NULL, PLACE_ALL, &dc );
        break;

    case ID_POPUP_PCB_AUTOPLACE_NEW_MODULES:
        AutoPlaceModule( NULL, PLACE_OUT_OF_BOARD, &dc );
        break;

    case ID_POPUP_PCB_AUTOPLACE_NEXT_MODULE:
        AutoPlaceModule( NULL, PLACE_INCREMENTAL, &dc );
        break;

    case ID_POPUP_PCB_SPREAD_ALL_MODULES:
        if( !IsOK( this,
                   _("Not locked footprints inside the board will be moved. OK?") ) )
            break;
        // Fall through
    case ID_POPUP_PCB_SPREAD_NEW_MODULES:
        if( GetBoard()->m_Modules == NULL )
        {
            DisplayError( this, _( "No footprint found!" ) );
            return;
        }
        else
        {
            MODULE* footprint = GetBoard()->m_Modules;
            std::vector<MODULE*> footprintList;
            for( ; footprint != NULL; footprint = footprint->Next() )
                footprintList.push_back( footprint );

            SpreadFootprints( &footprintList, id == ID_POPUP_PCB_SPREAD_NEW_MODULES, true );
        }
        break;

    case ID_POPUP_PCB_AUTOROUTE_ALL_MODULES:
        Autoroute( &dc, ROUTE_ALL );
        break;

    case ID_POPUP_PCB_AUTOROUTE_MODULE:
        Autoroute( &dc, ROUTE_MODULE );
        break;

    case ID_POPUP_PCB_AUTOROUTE_PAD:
        Autoroute( &dc, ROUTE_PAD );
        break;

    case ID_POPUP_PCB_AUTOROUTE_NET:
        Autoroute( &dc, ROUTE_NET );
        break;

    case ID_POPUP_PCB_AUTOROUTE_RESET_UNROUTED:
        Reset_Noroutable( &dc );
        break;

    default:
        wxMessageBox( wxT( "OnPlaceOrRouteFootprints command error" ) );
        break;
    }

    GetBoard()->m_Status_Pcb &= ~DO_NOT_SHOW_GENERAL_RASTNEST;
    Compile_Ratsnest( &dc, true );
}
void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode )
{
    wxString msg;

    if( aNetCode <= 0 ) // -1 = not existing net, 0 = dummy net
        return;

    if( (m_Pcb->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 )
        Compile_Ratsnest( aDC, true );

    // Clear the cluster identifier (subnet) of pads for this net
    for( unsigned i = 0; i < m_Pcb->GetPadCount(); ++i )
    {
        D_PAD* pad = m_Pcb->GetPad(i);
        int    pad_net_code = pad->GetNetCode();

        if( pad_net_code < aNetCode )
            continue;

        if( pad_net_code > aNetCode )
            break;

        pad->SetSubNet( 0 );
    }

    m_Pcb->Test_Connections_To_Copper_Areas( aNetCode );

    // Search for the first and the last segment relative to the given net code
    if( m_Pcb->m_Track )
    {
        CONNECTIONS connections( m_Pcb );

        TRACK* firstTrack;
        TRACK* lastTrack = NULL;
        firstTrack = m_Pcb->m_Track.GetFirst()->GetStartNetCode( aNetCode );

        if( firstTrack )
            lastTrack = firstTrack->GetEndNetCode( aNetCode );

        if( firstTrack && lastTrack ) // i.e. if there are segments
        {
            connections.Build_CurrNet_SubNets_Connections( firstTrack, lastTrack, firstTrack->GetNetCode() );
        }
    }

    Merge_SubNets_Connected_By_CopperAreas( m_Pcb, aNetCode );

    // rebuild the active ratsnest for this net
    DrawGeneralRatsnest( aDC, aNetCode );
    TestForActiveLinksInRatsnest( aNetCode );
    DrawGeneralRatsnest( aDC, aNetCode );

    // Display results
    int net_notconnected_count = 0;
    NETINFO_ITEM* net = m_Pcb->FindNet( aNetCode );

    if( net )       // Should not occur, but ...
    {
        for( unsigned ii = net->m_RatsnestStartIdx; ii < net->m_RatsnestEndIdx; ii++ )
        {
            if( m_Pcb->m_FullRatsnest[ii].IsActive() )
                net_notconnected_count++;
        }

        msg.Printf( wxT( "links %d nc %d  net:nc %d" ),
                    m_Pcb->GetRatsnestsCount(), m_Pcb->GetUnconnectedNetCount(),
                    net_notconnected_count );
    }
    else
        msg.Printf( wxT( "net not found: netcode %d" ),aNetCode );

    SetStatusText( msg );
    return;
}
void WinEDA_BasePcbFrame::Change_Side_Module(MODULE * Module, wxDC * DC)
/**********************************************************************/

/* Change de cote un composant : il y a inversion MIROIR autour de l'axe X
	Le changement n'est fait que si la couche est
		- CUIVRE ou CMP
		Si DC == NULL, il n'y a pas de redessin du composant et du chevelu
*/
{
D_PAD* pt_pad ;
TEXTE_MODULE* pt_texte;
EDGE_MODULE * pt_edgmod ;
EDA_BaseStruct * PtStruct;

	if ( Module == NULL ) return;
	if( (Module->m_Layer != CMP_N) && (Module->m_Layer != CUIVRE_N) ) return;

	m_CurrentScreen->SetModify();

	if ( ! (Module->m_Flags & IS_MOVED) )
		{
		m_Pcb->m_Status_Pcb &= ~( LISTE_CHEVELU_OK | CONNEXION_OK);
		if ( DC ) Module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);

		/* Effacement chevelu general si necessaire */
		if ( DC && g_Show_Ratsnest) DrawGeneralRatsnest(DC);
		/* Init des variables utilisees dans la routine Dessine_Drag_segment() */
		g_Offset_Module.x = 0;
		g_Offset_Module.y = 0;
		}

	else	// Module en deplacement
		{
		/* efface empreinte ( vue en contours) si elle a ete deja dessinee */
		if ( DC )
			{
			DrawModuleOutlines(DrawPanel, DC, Module);
			Dessine_Segments_Dragges(DrawPanel, DC);
			}
		}

	/* mise a jour du Flag de l'empreinte et des couches des contours et textes */
	Module->m_Layer = ChangeSideNumLayer(Module->m_Layer);

	/* Inversion miroir de l'orientation */
	Module->m_Orient = - Module->m_Orient;
	NORMALIZE_ANGLE_POS(Module->m_Orient);

	/* Inversion miroir + layers des pastilles */
	pt_pad = Module->m_Pads;
	for ( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext )
		{
		pt_pad->m_Pos.y -= Module->m_Pos.y ;
		pt_pad->m_Pos.y = -pt_pad->m_Pos.y;
		pt_pad->m_Pos.y += Module->m_Pos.y;
		pt_pad->m_Pos0.y = - pt_pad->m_Pos0.y;
		pt_pad->m_Offset.y = -pt_pad->m_Offset.y;
		pt_pad->m_DeltaSize.y = -pt_pad->m_DeltaSize.y;
		NEGATE_AND_NORMALIZE_ANGLE_POS(pt_pad->m_Orient);
		/* change cote pour pastilles surfaciques */
		pt_pad->m_Masque_Layer = ChangeSideMaskLayer(pt_pad->m_Masque_Layer);
		}

	/* Inversion miroir de la Reference et mise en miroir : */
	pt_texte = Module->m_Reference;
	pt_texte->m_Pos.y -= Module->m_Pos.y;
	pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
	pt_texte->m_Pos.y += Module->m_Pos.y;
	pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
	pt_texte->m_Miroir = 1 ;
	NEGATE_AND_NORMALIZE_ANGLE_POS(pt_texte->m_Orient);
	pt_texte->m_Layer = Module->m_Layer;
	pt_texte->m_Layer = ChangeSideNumLayer(pt_texte->m_Layer);
	if( Module->m_Layer == CUIVRE_N) pt_texte->m_Layer = SILKSCREEN_N_CU;
	if( Module->m_Layer == CMP_N) pt_texte->m_Layer = SILKSCREEN_N_CMP;
	if( (Module->m_Layer == SILKSCREEN_N_CU) ||
			(Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N) )
			 pt_texte->m_Miroir = 0 ;

	/* Inversion miroir de la Valeur et mise en miroir : */
	pt_texte = Module->m_Value;
	pt_texte->m_Pos.y -= Module->m_Pos.y;
	pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
	pt_texte->m_Pos.y += Module->m_Pos.y;
	pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
	pt_texte->m_Miroir = 1 ;
	NEGATE_AND_NORMALIZE_ANGLE_POS(pt_texte->m_Orient);
	pt_texte->m_Layer = Module->m_Layer;
	pt_texte->m_Layer = ChangeSideNumLayer(pt_texte->m_Layer);
	if( Module->m_Layer == CUIVRE_N) pt_texte->m_Layer = SILKSCREEN_N_CU;
	if( Module->m_Layer == CMP_N) pt_texte->m_Layer = SILKSCREEN_N_CMP;
	if( (Module->m_Layer == SILKSCREEN_N_CU) ||
		(Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N) )
		 pt_texte->m_Miroir = 0 ;

	/* Inversion miroir des dessins de l'empreinte : */
	PtStruct = Module->m_Drawings;
	for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext)
		{
		switch( PtStruct->m_StructType)
			{
			case TYPEEDGEMODULE:
				pt_edgmod = (EDGE_MODULE *) PtStruct;
				pt_edgmod->m_Start.y -= Module->m_Pos.y;
				pt_edgmod->m_Start.y = -pt_edgmod->m_Start.y ;
				pt_edgmod->m_Start.y += Module->m_Pos.y;
				pt_edgmod->m_End.y -= Module->m_Pos.y;
				pt_edgmod->m_End.y = -pt_edgmod->m_End.y ;
				pt_edgmod->m_End.y += Module->m_Pos.y;
				/* inversion des coords locales */
				pt_edgmod->m_Start0.y = -pt_edgmod->m_Start0.y;
				pt_edgmod->m_End0.y = -pt_edgmod->m_End0.y;
				if ( pt_edgmod->m_Shape == S_ARC )
				{
					pt_edgmod->m_Angle = - pt_edgmod->m_Angle;
				}

				pt_edgmod->m_Layer = ChangeSideNumLayer(pt_edgmod->m_Layer);
				break;

			case TYPETEXTEMODULE:
				/* Inversion miroir de la position et mise en miroir : */
				pt_texte = (TEXTE_MODULE*)PtStruct;
				pt_texte->m_Pos.y -= Module->m_Pos.y;
				pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
				pt_texte->m_Pos.y += Module->m_Pos.y;
				pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
				pt_texte->m_Miroir = 1 ;
				NEGATE_AND_NORMALIZE_ANGLE_POS(pt_texte->m_Orient);

				pt_texte->m_Layer = Module->m_Layer;
				pt_texte->m_Layer = ChangeSideNumLayer(pt_texte->m_Layer);
				if( Module->m_Layer == CUIVRE_N) pt_texte->m_Layer = SILKSCREEN_N_CU;
				if(Module->m_Layer == CMP_N) pt_texte->m_Layer = SILKSCREEN_N_CMP;
				if((Module->m_Layer == SILKSCREEN_N_CU) ||
				   (Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N))
					 pt_texte->m_Miroir = 0 ;

				break;

			default: DisplayError(this, wxT("Unknown Draw Type")); break;

			}
		}

	/* calcul du rectangle d'encadrement */
	Module->Set_Rectangle_Encadrement();

	Module->Display_Infos(this);

	if( !(Module->m_Flags & IS_MOVED) ) /* Inversion simple */
	{
		if ( DC )
		{
			Module->Draw(DrawPanel, DC, wxPoint(0,0), GR_OR);
			/* affichage chevelu general si necessaire */
			ReCompile_Ratsnest_After_Changes( DC );
		}
	}

	else
	{
		if ( DC )
		{
			DrawModuleOutlines(DrawPanel, DC, Module);
			Dessine_Segments_Dragges(DrawPanel, DC);
		}
		m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
	}
}