Esempio n. 1
0
TRACK * PCB_EDIT_FRAME::OnHotkeyBeginRoute( wxDC* aDC )
{
    if( !IsCopperLayer( GetActiveLayer() ) )
        return NULL;

    bool itemCurrentlyEdited = GetCurItem() && GetCurItem()->GetFlags();

    // Ensure the track tool is active
    if( GetToolId() != ID_TRACK_BUTT && !itemCurrentlyEdited )
    {
        wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED );
        cmd.SetEventObject( this );
        cmd.SetId( ID_TRACK_BUTT );
        GetEventHandler()->ProcessEvent( cmd );
    }

    if( GetToolId() != ID_TRACK_BUTT )
        return NULL;

    TRACK* track = NULL;

    if( !itemCurrentlyEdited )     // no track in progress:
    {
        track = Begin_Route( NULL, aDC );
        SetCurItem( track );

        if( track )
            m_canvas->SetAutoPanRequest( true );
    }
    else if( GetCurItem()->IsNew() )
    {
        track = Begin_Route( (TRACK*) GetCurItem(), aDC );

        // SetCurItem() must not write to the msg panel
        // because a track info is displayed while moving the mouse cursor
        if( track )      // A new segment was created
            SetCurItem( track, false );

        m_canvas->SetAutoPanRequest( true );
    }

    return track;
}
bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC )
{
    unsigned    itmp;

    if( aTrack == NULL )
    {
        if( GetActiveLayer() != GetScreen()->m_Route_Layer_TOP )
            SetActiveLayer( GetScreen()->m_Route_Layer_TOP );
        else
            SetActiveLayer( GetScreen()->m_Route_Layer_BOTTOM );

        UpdateStatusBar();
        return true;
    }

    // Avoid more than one via on the current location:
    if( GetBoard()->GetViaByPosition( g_CurrentTrackSegment->GetEnd(),
                                      g_CurrentTrackSegment->GetLayer() ) )
        return false;

    for( TRACK* segm = g_FirstTrackSegment;  segm;  segm = segm->Next() )
    {
        if( segm->Type() == PCB_VIA_T && g_CurrentTrackSegment->GetEnd() == segm->GetStart() )
            return false;
    }

    // Is the current segment Ok (no DRC error) ?
    if( g_Drc_On )
    {
        if( BAD_DRC==m_drc->Drc( g_CurrentTrackSegment, GetBoard()->m_Track ) )
            // DRC error, the change layer is not made
            return false;

        // Handle 2 segments.
        if( g_TwoSegmentTrackBuild && g_CurrentTrackSegment->Back() )
        {
            if( BAD_DRC == m_drc->Drc( g_CurrentTrackSegment->Back(), GetBoard()->m_Track ) )
                return false;
        }
    }

    /* Save current state before placing a via.
     * If the via cannot be placed this current state will be reused
     */
    itmp = g_CurrentTrackList.GetCount();
    Begin_Route( g_CurrentTrackSegment, DC );

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

    // create the via
    VIA* via = new VIA( GetBoard() );
    via->SetFlags( IS_NEW );
    via->SetViaType( GetDesignSettings().m_CurrentViaType );
    via->SetNetCode( GetBoard()->GetHighLightNetCode() );
    via->SetPosition( g_CurrentTrackSegment->GetEnd() );

    // for microvias, the size and hole will be changed later.
    via->SetWidth( GetDesignSettings().GetCurrentViaSize());
    via->SetDrill( GetDesignSettings().GetCurrentViaDrill() );

    // Usual via is from copper to component.
    // layer pair is B_Cu and F_Cu.
    via->SetLayerPair( B_Cu, F_Cu );

    LAYER_ID first_layer = GetActiveLayer();
    LAYER_ID last_layer;

    // prepare switch to new active layer:
    if( first_layer != GetScreen()->m_Route_Layer_TOP )
        last_layer = GetScreen()->m_Route_Layer_TOP;
    else
        last_layer = GetScreen()->m_Route_Layer_BOTTOM;

    // Adjust the actual via layer pair
    switch( via->GetViaType() )
    {
    case VIA_BLIND_BURIED:
        via->SetLayerPair( first_layer, last_layer );
        break;

    case VIA_MICROVIA:  // from external to the near neighbor inner layer
        {
            LAYER_ID last_inner_layer = ToLAYER_ID( ( GetBoard()->GetCopperLayerCount() - 2 ) );

            if( first_layer == B_Cu )
                last_layer = last_inner_layer;
            else if( first_layer == F_Cu )
                last_layer = In1_Cu;
            else if( first_layer == last_inner_layer )
                last_layer = B_Cu;
            else if( first_layer == In1_Cu )
                last_layer = F_Cu;
            // else error: will be removed later
            via->SetLayerPair( first_layer, last_layer );

            // Update diameter and hole size, which where set previously
            // for normal vias
            NETINFO_ITEM* net = via->GetNet();
            via->SetWidth( net->GetMicroViaSize() );
            via->SetDrill( net->GetMicroViaDrillSize() );
        }
        break;

    default:
        break;
    }

    if( g_Drc_On && BAD_DRC == m_drc->Drc( via, GetBoard()->m_Track ) )
    {
        // DRC fault: the Via cannot be placed here ...
        delete via;

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

        // delete the track(s) added in Begin_Route()
        while( g_CurrentTrackList.GetCount() > itmp )
        {
            Delete_Segment( DC, g_CurrentTrackSegment );
        }

         SetCurItem( g_CurrentTrackSegment, false );

        // Refresh DRC diag, erased by previous calls
        if( m_drc->GetCurrentMarker() )
            SetMsgPanel( m_drc->GetCurrentMarker() );

        return false;
    }

    SetActiveLayer( last_layer );

    TRACK*  lastNonVia = g_CurrentTrackSegment;

    /* A new via was created. It was Ok.
     */
    g_CurrentTrackList.PushBack( via );

    /* The via is now in linked list and we need a new track segment
     * after the via, starting at via location.
     * it will become the new current segment (from via to the mouse cursor)
     */

    TRACK* track = (TRACK*)lastNonVia->Clone();

    /* the above creates a new segment from the last entered segment, with the
     * current width, flags, netcode, etc... values.
     * layer, start and end point are not correct,
     * and will be modified next
     */

    // set the layer to the new value
    track->SetLayer( GetActiveLayer() );

    /* the start point is the via position and the end point is the cursor
     * which also is on the via (will change when moving mouse)
     */
    track->SetEnd( via->GetStart() );
    track->SetStart( via->GetStart() );

    g_CurrentTrackList.PushBack( track );

    if( g_TwoSegmentTrackBuild )
    {
        // Create a second segment (we must have 2 track segments to adjust)
        g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() );
    }

    m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
    SetMsgPanel( via );
    UpdateStatusBar();

    return true;
}
/* Handle the left button mouse click, when a tool is active
 */
void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
{
    BOARD_ITEM* DrawStruct = GetCurItem();
    bool        exit = false;
    bool no_tool = GetToolId() == ID_NO_TOOL_SELECTED;

    if( no_tool || ( DrawStruct && DrawStruct->GetFlags() ) )
    {
        m_canvas->SetAutoPanRequest( false );

        if( DrawStruct && DrawStruct->GetFlags() ) // Command in progress
        {
            m_canvas->SetIgnoreMouseEvents( true );
            m_canvas->CrossHairOff( aDC );

            switch( DrawStruct->Type() )
            {
            case PCB_ZONE_AREA_T:
                if( DrawStruct->IsNew() )
                {
                    m_canvas->SetAutoPanRequest( true );
                    Begin_Zone( aDC );
                }
                else
                {
                    End_Move_Zone_Corner_Or_Outlines( aDC, (ZONE_CONTAINER*) DrawStruct );
                }

                exit = true;
                break;

            case PCB_TRACE_T:
            case PCB_VIA_T:
                if( DrawStruct->IsDragging() )
                {
                    PlaceDraggedOrMovedTrackSegment( (TRACK*) DrawStruct, aDC );
                    exit = true;
                }

                break;

            case PCB_TEXT_T:
                Place_Texte_Pcb( (TEXTE_PCB*) DrawStruct, aDC );
                exit = true;
                break;

            case PCB_MODULE_TEXT_T:
                PlaceTexteModule( (TEXTE_MODULE*) DrawStruct, aDC );
                exit = true;
                break;

            case PCB_PAD_T:
                PlacePad( (D_PAD*) DrawStruct, aDC );
                exit = true;
                break;

            case PCB_MODULE_T:
                PlaceModule( (MODULE*) DrawStruct, aDC );
                exit = true;
                break;

            case PCB_TARGET_T:
                PlaceTarget( (PCB_TARGET*) DrawStruct, aDC );
                exit = true;
                break;

            case PCB_LINE_T:
                if( no_tool )   // when no tools: existing item moving.
                {
                    Place_DrawItem( (DRAWSEGMENT*) DrawStruct, aDC );
                    exit = true;
                }

                break;

            case PCB_DIMENSION_T:
                if( ! DrawStruct->IsNew() )
                {   // We are moving the text of an existing dimension. Place it
                    PlaceDimensionText( (DIMENSION*) DrawStruct, aDC );
                    exit = true;
                }
                break;

            default:
                DisplayError( this,
                              wxT( "PCB_EDIT_FRAME::OnLeftClick() err: DrawType %d m_Flags != 0" ),
                              DrawStruct->Type() );
                exit = true;
                break;
            }

            m_canvas->SetIgnoreMouseEvents( false );
            m_canvas->CrossHairOn( aDC );

            if( exit )
                return;
        }
        else if( !wxGetKeyState( WXK_SHIFT ) && !wxGetKeyState( WXK_ALT )
                && !wxGetKeyState( WXK_CONTROL ) )
        {
            DrawStruct = PcbGeneralLocateAndDisplay();

            if( DrawStruct )
                SendMessageToEESCHEMA( DrawStruct );
        }
    }

    if( DrawStruct ) // display netclass info for zones, tracks and pads
    {
        switch( DrawStruct->Type() )
        {
        case PCB_ZONE_AREA_T:
        case PCB_TRACE_T:
        case PCB_VIA_T:
        case PCB_PAD_T:
            GetDesignSettings().SetCurrentNetClass(
                ((BOARD_CONNECTED_ITEM*)DrawStruct)->GetNetClassName() );
            updateTraceWidthSelectBox();
            updateViaSizeSelectBox();
            break;

        default:
           break;
        }
    }

    switch( GetToolId() )
    {
    case ID_MAIN_MENUBAR:
    case ID_NO_TOOL_SELECTED:
        break;

    case ID_PCB_MUWAVE_TOOL_SELF_CMD:
    case ID_PCB_MUWAVE_TOOL_GAP_CMD:
    case ID_PCB_MUWAVE_TOOL_STUB_CMD:
    case ID_PCB_MUWAVE_TOOL_STUB_ARC_CMD:
    case ID_PCB_MUWAVE_TOOL_FUNCTION_SHAPE_CMD:
        MuWaveCommand( aDC, aPosition );
        break;

    case ID_PCB_HIGHLIGHT_BUTT:
    {
        int netcode = SelectHighLight( aDC );

        if( netcode < 0 )
            SetMsgPanel( GetBoard() );
        else
        {
            NETINFO_ITEM* net = GetBoard()->FindNet( netcode );

            if( net )
            {
                MSG_PANEL_ITEMS items;
                net->GetMsgPanelInfo( items );
                SetMsgPanel( items );
            }
        }
    }
    break;

    case ID_PCB_SHOW_1_RATSNEST_BUTT:
        DrawStruct = PcbGeneralLocateAndDisplay();
        Show_1_Ratsnest( DrawStruct, aDC );

        if( DrawStruct )
            SendMessageToEESCHEMA( DrawStruct );

        break;

    case ID_PCB_MIRE_BUTT:
        if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) )
        {
            SetCurItem( (BOARD_ITEM*) CreateTarget( aDC ) );
            m_canvas->MoveCursorToCrossHair();
        }
        else if( DrawStruct->Type() == PCB_TARGET_T )
        {
            PlaceTarget( (PCB_TARGET*) DrawStruct, aDC );
        }
        else
        {
            DisplayError( this, wxT( "OnLeftClick err: not a PCB_TARGET_T" ) );
        }

        break;

    case ID_PCB_CIRCLE_BUTT:
    case ID_PCB_ARC_BUTT:
    case ID_PCB_ADD_LINE_BUTT:
        {
            STROKE_T shape = S_SEGMENT;

            if( GetToolId() == ID_PCB_CIRCLE_BUTT )
                shape = S_CIRCLE;

            if( GetToolId() == ID_PCB_ARC_BUTT )
                shape = S_ARC;

            if( IsCopperLayer( GetActiveLayer() ) )
            {
                DisplayError( this, _( "Graphic not allowed on Copper layers" ) );
                break;
            }

            if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) )
            {
                DrawStruct = (BOARD_ITEM*) Begin_DrawSegment( NULL, shape, aDC );
                SetCurItem( DrawStruct );
                m_canvas->SetAutoPanRequest( true );
            }
            else if( DrawStruct
                   && (DrawStruct->Type() == PCB_LINE_T)
                   && DrawStruct->IsNew() )
            {
                DrawStruct = (BOARD_ITEM*) Begin_DrawSegment( (DRAWSEGMENT*) DrawStruct, shape, aDC );
                SetCurItem( DrawStruct );
                m_canvas->SetAutoPanRequest( true );
            }
        }
        break;

    case ID_TRACK_BUTT:
        if( !IsCopperLayer( GetActiveLayer() ) )
        {
            DisplayError( this, _( "Tracks on Copper layers only " ) );
            break;
        }

        if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) )
        {
            DrawStruct = (BOARD_ITEM*) Begin_Route( NULL, aDC );
            SetCurItem( DrawStruct );

            if( DrawStruct )
                m_canvas->SetAutoPanRequest( true );
        }
        else if( DrawStruct && DrawStruct->IsNew() )
        {
            TRACK* track = Begin_Route( (TRACK*) DrawStruct, aDC );

            // SetCurItem() must not write to the msg panel
            // because a track info is displayed while moving the mouse cursor
            if( track )  // A new segment was created
                SetCurItem( DrawStruct = (BOARD_ITEM*) track, false );

            m_canvas->SetAutoPanRequest( true );
        }

        break;

    case ID_PCB_ZONES_BUTT:
    case ID_PCB_KEEPOUT_AREA_BUTT:
        /* ZONE or KEEPOUT Tool is selected. Determine action for a left click:
         *  this can be start a new zone or select and move an existing zone outline corner
         *  if found near the mouse cursor
         */
        if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) )
        {
            if( Begin_Zone( aDC ) )
            {
                m_canvas->SetAutoPanRequest( true );
                DrawStruct = GetBoard()->m_CurrentZoneContour;
                GetScreen()->SetCurItem( DrawStruct );
            }
        }
        else if( DrawStruct && (DrawStruct->Type() == PCB_ZONE_AREA_T) && DrawStruct->IsNew() )
        {   // Add a new corner to the current outline being created:
            m_canvas->SetAutoPanRequest( true );
            Begin_Zone( aDC );
            DrawStruct = GetBoard()->m_CurrentZoneContour;
            GetScreen()->SetCurItem( DrawStruct );
        }
        else
        {
            DisplayError( this, wxT( "PCB_EDIT_FRAME::OnLeftClick() zone internal error" ) );
        }

        break;

    case ID_PCB_ADD_TEXT_BUTT:
        if( IsLayerInList( EDGE_LAYER, GetActiveLayer() ) )
        {
            DisplayError( this,
                          _( "Texts not allowed on Edge Cut layer" ) );
            break;
        }

        if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) )
        {
            SetCurItem( CreateTextePcb( aDC ) );
            m_canvas->MoveCursorToCrossHair();
            m_canvas->SetAutoPanRequest( true );
        }
        else if( DrawStruct->Type() == PCB_TEXT_T )
        {
            Place_Texte_Pcb( (TEXTE_PCB*) DrawStruct, aDC );
            m_canvas->SetAutoPanRequest( false );
        }
        else
        {
            DisplayError( this, wxT( "OnLeftClick err: not a PCB_TEXT_T" ) );
        }

        break;

    case ID_PCB_MODULE_BUTT:
        if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) )
        {
            m_canvas->MoveCursorToCrossHair();
            DrawStruct = (BOARD_ITEM*) LoadModuleFromLibrary(
                    wxEmptyString, Prj().PcbFootprintLibs(), true, aDC );

            SetCurItem( DrawStruct );

            if( DrawStruct )
                StartMoveModule( (MODULE*) DrawStruct, aDC, false );
        }
        else if( DrawStruct->Type() == PCB_MODULE_T )
        {
            PlaceModule( (MODULE*) DrawStruct, aDC );
            m_canvas->SetAutoPanRequest( false );
        }
        else
        {
            DisplayError( this, wxT( "Internal err: Struct not PCB_MODULE_T" ) );
        }

        break;

    case ID_PCB_DIMENSION_BUTT:
        if( IsLayerInList( EDGE_LAYER|ALL_CU_LAYERS, GetActiveLayer() ) )
        {
            DisplayError( this,
                          _( "Dimension not allowed on Copper or Edge Cut layers" ) );
            break;
        }

        if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) )
        {
            DrawStruct = (BOARD_ITEM*) EditDimension( NULL, aDC );
            SetCurItem( DrawStruct );
            m_canvas->SetAutoPanRequest( true );
        }
        else if( DrawStruct && (DrawStruct->Type() == PCB_DIMENSION_T) && DrawStruct->IsNew() )
        {
            DrawStruct = (BOARD_ITEM*) EditDimension( (DIMENSION*) DrawStruct, aDC );
            SetCurItem( DrawStruct );
            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            DisplayError( this,
                          wxT( "PCB_EDIT_FRAME::OnLeftClick() error item is not a DIMENSION" ) );
        }

        break;

    case ID_PCB_DELETE_ITEM_BUTT:
        if( !DrawStruct || !DrawStruct->GetFlags() )
        {
            DrawStruct = PcbGeneralLocateAndDisplay();

            if( DrawStruct && (DrawStruct->GetFlags() == 0) )
            {
                RemoveStruct( DrawStruct, aDC );
                SetCurItem( DrawStruct = NULL );
            }
        }

        break;

    case ID_PCB_PLACE_OFFSET_COORD_BUTT:
        m_canvas->DrawAuxiliaryAxis( aDC, GR_XOR );
        SetAuxOrigin( GetCrossHairPosition() );
        m_canvas->DrawAuxiliaryAxis( aDC, GR_COPY );
        OnModify();
        break;

    case ID_PCB_PLACE_GRID_COORD_BUTT:
        m_canvas->DrawGridAxis( aDC, GR_XOR, GetBoard()->GetGridOrigin() );
        SetGridOrigin( GetCrossHairPosition() );
        m_canvas->DrawGridAxis( aDC, GR_COPY, GetBoard()->GetGridOrigin() );
        break;

    default:
        DisplayError( this, wxT( "PCB_EDIT_FRAME::OnLeftClick() id error" ) );
        SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString );
        break;
    }
}
void WinEDA_PcbFrame::Other_Layer_Route(TRACK * track, wxDC * DC)
/****************************************************************/
/*
	Change de couche active pour le routage.
	Si une piste est en cours de trace : placement d'une Via
*/
{
TRACK * pt_segm;
SEGVIA * Via;
int ii;
int itmp;

	if(track == NULL)
	{
		if(GetScreen()->m_Active_Layer != GetScreen()->m_Route_Layer_TOP)
			 GetScreen()->m_Active_Layer = GetScreen()->m_Route_Layer_TOP;
		else GetScreen()->m_Active_Layer = GetScreen()->m_Route_Layer_BOTTOM ;
		Affiche_Status_Box();
		SetToolbars();
		return;
	}

	/* Les vias ne doivent pas etre inutilement empilees: */
	if( Locate_Via(m_Pcb, g_CurrentTrackSegment->m_End.x,g_CurrentTrackSegment->m_End.y,g_CurrentTrackSegment->m_Layer))
		return;
	pt_segm = g_FirstTrackSegment;
	for ( ii = 0; ii < g_TrackSegmentCount-1 ; ii++, pt_segm = (TRACK*)pt_segm->Pnext)
	{
		if( (pt_segm->m_StructType == TYPEVIA) &&
			(g_CurrentTrackSegment->m_End.x == pt_segm->m_Start.x) &&
			(g_CurrentTrackSegment->m_End.y == pt_segm->m_Start.y) )
				return;
	}
	/* Test si segment possible a placer */
	if ( Drc_On )
		if ( Drc(this, DC,g_CurrentTrackSegment,m_Pcb->m_Track,1) == BAD_DRC )
			return ;

	/* save etat actuel pour regeneration si via impossible a placer */
	itmp = g_TrackSegmentCount;
	Begin_Route(g_CurrentTrackSegment, DC);

	GetScreen()->ManageCurseur(DrawPanel, DC, FALSE);

	Via = new SEGVIA(m_Pcb);
	Via->m_Flags = IS_NEW;
	Via->m_Width = g_DesignSettings.m_CurrentViaSize;
	Via->m_Shape = g_DesignSettings.m_CurrentViaType ;
	Via->m_NetCode = g_HightLigth_NetCode ;
	Via->m_Start = Via->m_End = g_CurrentTrackSegment->m_End;

	Via->m_Layer = GetScreen()->m_Active_Layer;	// Provisoirement

	if( GetScreen()->m_Active_Layer != GetScreen()->m_Route_Layer_TOP)
			GetScreen()->m_Active_Layer = GetScreen()->m_Route_Layer_TOP ;
	else	GetScreen()->m_Active_Layer = GetScreen()->m_Route_Layer_BOTTOM ;

	if ( (Via->m_Shape & 15) == VIA_ENTERREE )
	{
		Via->m_Layer |= GetScreen()->m_Active_Layer << 4;
	}
	else if ( (Via->m_Shape & 15) == VIA_BORGNE )
	{	// A revoir! ( la via devrait deboucher sur 1 cote )
		Via->m_Layer |= GetScreen()->m_Active_Layer << 4;
	}
	else Via->m_Layer = 0x0F;

	if ( Drc_On &&( Drc(this, DC,Via,m_Pcb->m_Track,1 ) == BAD_DRC ) )
	{ /* Via impossible a placer ici */
		delete Via;
		GetScreen()->m_Active_Layer = g_CurrentTrackSegment->m_Layer ;
		GetScreen()->ManageCurseur(DrawPanel, DC, FALSE);
		return;
	}

	/* la via est OK et est inseree apres le segment courant */
	Via->Pback = g_CurrentTrackSegment;
	g_CurrentTrackSegment->Pnext = Via;
	g_TrackSegmentCount++;
	g_CurrentTrackSegment = new TRACK(*g_CurrentTrackSegment);
	g_CurrentTrackSegment->m_Layer = GetScreen()->m_Active_Layer;
	g_CurrentTrackSegment->m_Start = g_CurrentTrackSegment->m_End = Via->m_Start;
	g_TrackSegmentCount++;
	g_CurrentTrackSegment->Pback = Via;
	Via->Pnext = g_CurrentTrackSegment;
	if ( g_TwoSegmentTrackBuild )
	{	// Create a second segment (we must have 2 track segments to adjust)
		TRACK * track = g_CurrentTrackSegment;
		g_CurrentTrackSegment = new TRACK(*track);
		g_TrackSegmentCount++;
		g_CurrentTrackSegment->Pback = track;
		track->Pnext = g_CurrentTrackSegment;
	}

	GetScreen()->ManageCurseur(DrawPanel, DC, FALSE);
	Affiche_Infos_Piste(this, Via);

	Affiche_Status_Box();
	SetToolbars();
}
Esempio n. 5
0
void WinEDA_PcbFrame::OnLeftClick(wxDC * DC, const wxPoint& MousePos)
/********************************************************************/
/* Traite les commandes declenchée par le bouton gauche de la souris,
	quand un outil est deja selectionné
*/
{
    EDA_BaseStruct * DrawStruct = CURRENT_ITEM;

    if ( (m_ID_current_state == 0) || ( DrawStruct && DrawStruct->m_Flags ))
    {
        DrawPanel->m_AutoPAN_Request = FALSE;
        if ( DrawStruct && DrawStruct->m_Flags ) // Commande "POPUP" en cours
        {
            switch (DrawStruct->m_StructType )
            {
            case TYPETRACK:
            case TYPEVIA:
                if ( CURRENT_ITEM->m_Flags & IS_DRAGGED )
                {
                    PlaceDraggedTrackSegment((TRACK *)DrawStruct, DC);
                    return;
                }
                break;

            case TYPETEXTE:
                Place_Texte_Pcb((TEXTE_PCB *)DrawStruct, DC);
                return;
                break;

            case TYPETEXTEMODULE:
                PlaceTexteModule( (TEXTE_MODULE *) DrawStruct, DC);
                return;
                break;

            case TYPEPAD:
                PlacePad((D_PAD *)DrawStruct, DC);
                return;
                break;

            case TYPEMODULE:
                Place_Module((MODULE *)DrawStruct, DC);
                return;
                break;

            case TYPEMIRE:
                Place_Mire((MIREPCB *)DrawStruct, DC);
                return;
                break;

            case TYPEDRAWSEGMENT:
                if (m_ID_current_state == 0)
                {
                    Place_DrawItem( (DRAWSEGMENT * )DrawStruct, DC);
                    return;
                }
                break;

            default:
                if (m_ID_current_state == 0)
                {
                    DisplayError(this,
                                 wxT("WinEDA_PcbFrame::OnLeftClick() err: m_Flags != 0") );
                    return;
                }
            }
        }
        else
        {
            DrawStruct = PcbGeneralLocateAndDisplay();
        }
    }

    switch ( m_ID_current_state )
    {
    case ID_MAIN_MENUBAR:
    case 0:
        break;

    case ID_NO_SELECT_BUTT:
        break;


    case ID_PCB_MUWAVE_TOOL_SELF_CMD:
    case ID_PCB_MUWAVE_TOOL_GAP_CMD:
    case ID_PCB_MUWAVE_TOOL_STUB_CMD:
    case ID_PCB_MUWAVE_TOOL_STUB_ARC_CMD:
    case ID_PCB_MUWAVE_TOOL_FUNCTION_SHAPE_CMD:
        MuWaveCommand(DC, MousePos);
        break;


    case ID_PCB_HIGHLIGHT_BUTT:
    {
        int netcode = Select_High_Light(DC);
        if ( netcode < 0 ) Affiche_Infos_Status_Pcb(this);
        else Affiche_Infos_Equipot(netcode, this);
    }
    break;

    case ID_PCB_SHOW_1_RATSNEST_BUTT:
        DrawStruct = PcbGeneralLocateAndDisplay();
        Show_1_Ratsnest(DrawStruct, DC);
        break;

    case ID_PCB_MIRE_BUTT:
        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
        {
            GetScreen()->m_CurrentItem = Create_Mire( DC );
            DrawPanel->MouseToCursorSchema();
        }
        else if (DrawStruct->m_StructType == TYPEMIRE )
        {
            Place_Mire((MIREPCB *)DrawStruct, DC);
        }
        else DisplayError(this, wxT("Internal err: Struct not TYPEMIRE"));
        break;

    case ID_PCB_CIRCLE_BUTT:
    case ID_PCB_ARC_BUTT:
    case ID_LINE_COMMENT_BUTT:
    {
        int shape = S_SEGMENT;
        if ( m_ID_current_state == ID_PCB_CIRCLE_BUTT) shape = S_CIRCLE;
        if ( m_ID_current_state == ID_PCB_ARC_BUTT) shape = S_ARC;

        if ( GetScreen()->m_Active_Layer <= CMP_N )
        {
            DisplayError(this, _("Graphic not autorized on Copper layers"));
            break;
        }
        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
        {
            GetScreen()->m_CurrentItem = DrawStruct =
                                             Begin_DrawSegment(NULL, shape, DC);
            DrawPanel->m_AutoPAN_Request = TRUE;
        }
        else if (DrawStruct &&
                 (DrawStruct->m_StructType == TYPEDRAWSEGMENT) &&
                 (DrawStruct->m_Flags & IS_NEW) )
        {
            GetScreen()->m_CurrentItem = DrawStruct =
                                             Begin_DrawSegment((DRAWSEGMENT *)DrawStruct, shape, DC);
            DrawPanel->m_AutoPAN_Request = TRUE;
        }
        break;
    }

    case ID_TRACK_BUTT:
        if ( GetScreen()->m_Active_Layer > CMP_N )
        {
            DisplayError(this, _("Tracks on Copper layers only "));
            break;
        }

        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
        {
            GetScreen()->m_CurrentItem = DrawStruct =
                                             Begin_Route(NULL, DC);
            if ( DrawStruct ) DrawPanel->m_AutoPAN_Request = TRUE;
        }
        else if (DrawStruct &&
//					(DrawStruct->m_StructType == TYPETRACK) &&
                 (DrawStruct->m_Flags & IS_NEW) )
        {
            TRACK * track = Begin_Route((TRACK *) DrawStruct, DC);
            if ( track )	// c'est a dire si OK
                GetScreen()->m_CurrentItem = DrawStruct = track;
            DrawPanel->m_AutoPAN_Request = TRUE;
        }
        break;


    case ID_PCB_ZONES_BUTT:
        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
        {
            GetScreen()->m_CurrentItem = DrawStruct =
                                             Begin_Zone();
        }
        else if (DrawStruct &&
                 (DrawStruct->m_StructType == TYPEEDGEZONE) &&
                 (DrawStruct->m_Flags & IS_NEW) )
        {
            GetScreen()->m_CurrentItem = DrawStruct =
                                             Begin_Zone();
        }
        else DisplayError(this, wxT("Edit: zone internal error"));
        break;

    case ID_TEXT_COMMENT_BUTT:
        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
        {
            GetScreen()->m_CurrentItem = Create_Texte_Pcb( DC );
            DrawPanel->MouseToCursorSchema();
            DrawPanel->m_AutoPAN_Request = TRUE;
        }
        else if (DrawStruct->m_StructType == TYPETEXTE )
        {
            Place_Texte_Pcb((TEXTE_PCB *)DrawStruct, DC);
            DrawPanel->m_AutoPAN_Request = FALSE;
        }
        else DisplayError(this, wxT("Internal err: Struct not TYPETEXTE"));
        break;

    case ID_COMPONENT_BUTT:
        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
        {
            DrawPanel->MouseToCursorSchema();
            GetScreen()->m_CurrentItem = DrawStruct =
                                             Load_Module_From_Library(wxEmptyString, DC);
            if ( DrawStruct )
                StartMove_Module((MODULE *)DrawStruct, DC);
        }
        else if (DrawStruct->m_StructType == TYPEMODULE )
        {
            Place_Module((MODULE *)DrawStruct, DC);
            DrawPanel->m_AutoPAN_Request = FALSE;
        }
        else DisplayError(this, wxT("Internal err: Struct not TYPEMODULE"));
        break;

    case ID_PCB_COTATION_BUTT:
        if ( GetScreen()->m_Active_Layer <= CMP_N )
        {
            DisplayError(this, _("Cotation not autorized on Copper layers"));
            break;
        }
        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
        {
            GetScreen()->m_CurrentItem = DrawStruct =
                                             Begin_Cotation(NULL, DC);
            DrawPanel->m_AutoPAN_Request = TRUE;
        }
        else if (DrawStruct &&
                 (DrawStruct->m_StructType == TYPECOTATION) &&
                 (DrawStruct->m_Flags & IS_NEW) )
        {
            GetScreen()->m_CurrentItem = DrawStruct =
                                             Begin_Cotation((COTATION * )DrawStruct, DC);
            DrawPanel->m_AutoPAN_Request = TRUE;
        }
        else DisplayError(this, wxT("Internal err: Struct not COTATION"));
        break;

    case ID_PCB_DELETE_ITEM_BUTT:
        if ( !DrawStruct || (DrawStruct->m_Flags == 0) )
        {
            DrawStruct = PcbGeneralLocateAndDisplay();
            if ( DrawStruct && (DrawStruct->m_Flags == 0) )
            {
                RemoveStruct(DrawStruct, DC);
                GetScreen()->m_CurrentItem = DrawStruct = NULL;
            }
        }
        break;

    case ID_PCB_PLACE_OFFSET_COORD_BUTT:
        GetScreen()->Trace_Curseur(DrawPanel, DC);
        DrawPanel->m_Draw_Auxiliary_Axe(DC, GR_XOR);
        m_Auxiliary_Axe_Position = GetScreen()->m_Curseur;
        DrawPanel->m_Draw_Auxiliary_Axe( DC, GR_COPY);
        GetScreen()->Trace_Curseur(DrawPanel, DC);
        break;

    default :
        DrawPanel->SetCursor(wxCURSOR_ARROW);
        DisplayError(this, wxT("WinEDA_PcbFrame::OnLeftClick() id error"));
        SetToolID(0, wxCURSOR_ARROW,wxEmptyString);
        break;
    }
}