int PCB_EDIT_FRAME::OnHotkeyCopyItem()
{
    BOARD_ITEM* item = GetCurItem();
    bool itemCurrentlyEdited = item && item->GetFlags();

    if( itemCurrentlyEdited )
        return 0;

    item = PcbGeneralLocateAndDisplay();

    if( item == NULL )
        return 0;

    SetCurItem( item );

    int eventId = 0;

    switch( item->Type() )
    {
    case PCB_TEXT_T:
        eventId = ID_POPUP_PCB_COPY_TEXTEPCB;
        break;
    default:
        eventId = 0;
        break;
    }

    return eventId;
}
bool PCB_EDIT_FRAME::OnHotkeyRotateItem( int aIdCommand )
{
    BOARD_ITEM* item = GetCurItem();
    bool        itemCurrentlyEdited = item && item->GetFlags();
    int         evt_type = 0; // Used to post a wxCommandEvent on demand

    wxASSERT( aIdCommand == HK_ROTATE_ITEM );

    // Allows block rotate operation on hot key.
    if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
    {
        evt_type = ID_POPUP_ROTATE_BLOCK;
    }
    else
    {
        if( !itemCurrentlyEdited )
            item = PcbGeneralLocateAndDisplay();

        if( item == NULL )
            return false;

        SetCurItem( item );

        switch( item->Type() )
        {
        case PCB_MODULE_T:
            evt_type = ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE;
            break;

        case PCB_TEXT_T:
            evt_type = ID_POPUP_PCB_ROTATE_TEXTEPCB;
            break;

        case PCB_MODULE_TEXT_T:
            evt_type = ID_POPUP_PCB_ROTATE_TEXTMODULE;
            break;

        default:
            break;
        }
    }

    if( evt_type != 0 )
    {
        wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
        evt.SetEventObject( this );
        evt.SetId( evt_type );
        GetEventHandler()->ProcessEvent( evt );
        return true;
    }

    return false;
}
bool PCB_EDIT_FRAME::OnHotkeyMoveItem( int aIdCommand )
{
    BOARD_ITEM* item = GetCurItem();
    bool itemCurrentlyEdited = item && item->GetFlags();

    if( itemCurrentlyEdited )
        return false;

    item = PcbGeneralLocateAndDisplay();

    if( item == NULL )
        return false;

    SetCurItem( item );

    int evt_type = 0;       // Used to post a wxCommandEvent on demand

    switch( item->Type() )
    {
    case PCB_TRACE_T:
    case PCB_VIA_T:
        if( aIdCommand == HK_MOVE_ITEM )
            evt_type = ID_POPUP_PCB_MOVE_TRACK_NODE;

        if( aIdCommand == HK_DRAG_ITEM )
            evt_type = ID_POPUP_PCB_DRAG_TRACK_SEGMENT;

        if( aIdCommand == HK_DRAG_TRACK_KEEP_SLOPE )
            evt_type = ID_POPUP_PCB_DRAG_TRACK_SEGMENT_KEEP_SLOPE;

        break;

    case PCB_MODULE_T:
        {
            if( aIdCommand == HK_MOVE_ITEM )
                evt_type = ID_POPUP_PCB_MOVE_MODULE_REQUEST;

            if( aIdCommand == HK_DRAG_ITEM )
                evt_type = ID_POPUP_PCB_DRAG_MODULE_REQUEST;
        }
        break;

    case PCB_PAD_T:
        // Post MODULE_REQUEST events here to prevent pads
        // from being moved or dragged by hotkeys.
        // Process_Special_Functions takes care of finding
        // the parent.
        if( aIdCommand == HK_MOVE_ITEM )
            evt_type = ID_POPUP_PCB_MOVE_MODULE_REQUEST;

        if( aIdCommand == HK_DRAG_ITEM )
            evt_type = ID_POPUP_PCB_DRAG_MODULE_REQUEST;

        break;

    case PCB_TEXT_T:
        if( aIdCommand == HK_MOVE_ITEM )
            evt_type = ID_POPUP_PCB_MOVE_TEXTEPCB_REQUEST;

        break;

    case PCB_TARGET_T:
        if( aIdCommand == HK_MOVE_ITEM )
            evt_type = ID_POPUP_PCB_MOVE_PCB_TARGET_REQUEST;

        break;

    case PCB_ZONE_AREA_T:
        if( aIdCommand == HK_MOVE_ITEM )
            evt_type = ID_POPUP_PCB_MOVE_ZONE_OUTLINES;

        if( aIdCommand == HK_DRAG_ITEM )
            evt_type = ID_POPUP_PCB_DRAG_ZONE_OUTLINE_SEGMENT;

        break;

    case PCB_MODULE_TEXT_T:
        if( aIdCommand == HK_MOVE_ITEM )
            evt_type = ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST;

        break;

    case PCB_LINE_T:
        if( aIdCommand == HK_MOVE_ITEM )
            evt_type = ID_POPUP_PCB_MOVE_DRAWING_REQUEST;

        break;

    case PCB_DIMENSION_T:
        if( aIdCommand == HK_MOVE_ITEM )
            evt_type = ID_POPUP_PCB_MOVE_TEXT_DIMENSION_REQUEST;
        break;

    default:
        break;
    }

    if( evt_type != 0 )
    {
        wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
        evt.SetEventObject( this );
        evt.SetId( evt_type );
        GetEventHandler()->ProcessEvent( evt );
        return true;
    }

    return false;
}
bool PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosition,
                               EDA_ITEM* aItem )
{
    if( aHotkeyCode == 0 )
        return false;

    bool itemCurrentlyEdited = GetCurItem() && GetCurItem()->GetFlags();
    MODULE* module = NULL;
    int evt_type = 0;       //Used to post a wxCommandEvent on demand
    PCB_SCREEN* screen = GetScreen();
    auto displ_opts = (PCB_DISPLAY_OPTIONS*)GetDisplayOptions();

    /* Convert lower to upper case
     * (the usual toupper function has problem with non ascii codes like function keys
     */
    if( (aHotkeyCode >= 'a') && (aHotkeyCode <= 'z') )
        aHotkeyCode += 'A' - 'a';

    EDA_HOTKEY* HK_Descr = GetDescriptorFromHotkey( aHotkeyCode, common_Hotkey_List );

    if( HK_Descr == NULL )
        HK_Descr = GetDescriptorFromHotkey( aHotkeyCode, board_edit_Hotkey_List );

    if( HK_Descr == NULL )
        return false;

    int hk_id = HK_Descr->m_Idcommand;

    // Create a wxCommandEvent that will be posted in some hot keys functions
    wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED );
    cmd.SetEventObject( this );

    LAYER_NUM  ll;

    switch( hk_id )
    {
    default:
    case HK_NOT_FOUND:
        return false;

    case HK_LEFT_CLICK:
        OnLeftClick( aDC, aPosition );
        break;

    case HK_LEFT_DCLICK:    // Simulate a double left click: generate 2 events
        OnLeftClick( aDC, aPosition );
        OnLeftDClick( aDC, aPosition );
        break;

    case HK_SWITCH_TRACK_WIDTH_TO_NEXT:
        if( GetCanvas()->IsMouseCaptured() )
            GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false );

        if( GetDesignSettings().GetTrackWidthIndex() < GetDesignSettings().m_TrackWidthList.size() - 1 )
            GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().GetTrackWidthIndex() + 1 );
        else
            GetDesignSettings().SetTrackWidthIndex( 0 );

        if( GetCanvas()->IsMouseCaptured() )
            GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false );

        break;

    case HK_SWITCH_TRACK_WIDTH_TO_PREVIOUS:
        if( GetCanvas()->IsMouseCaptured() )
            GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false );

        if( GetDesignSettings().GetTrackWidthIndex() <= 0 )
            GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().m_TrackWidthList.size() -1 );
        else
            GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().GetTrackWidthIndex() - 1 );

        if( GetCanvas()->IsMouseCaptured() )
            GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false );

        break;

    case HK_SWITCH_GRID_TO_FASTGRID1:
        SetFastGrid1();
        break;

    case HK_SWITCH_GRID_TO_FASTGRID2:
        SetFastGrid2();
        break;

    case HK_SWITCH_GRID_TO_NEXT:
        evt_type = ID_POPUP_GRID_NEXT;
        break;

    case HK_SWITCH_GRID_TO_PREVIOUS:
        evt_type = ID_POPUP_GRID_PREV;
        break;

    case HK_SWITCH_LAYER_TO_PREVIOUS:
        ll = GetActiveLayer();

        if( !IsCopperLayer( ll ) )
            break;

        if( ll == F_Cu )
            ll = B_Cu;
        else if( ll == B_Cu )
            ll = ToLAYER_ID( GetBoard()->GetCopperLayerCount() - 2 );
        else
            ll = ll - 1;

        SwitchLayer( aDC, ToLAYER_ID( ll ) );
        break;

    case HK_SWITCH_LAYER_TO_NEXT:
        ll = GetActiveLayer();

        if( !IsCopperLayer( ll ) )
            break;

        if( ll == B_Cu )
            ll = F_Cu;
        else if( ++ll >= GetBoard()->GetCopperLayerCount() - 1 )
            ll = B_Cu;

        SwitchLayer( aDC, ToLAYER_ID( ll ) );
        break;

    case HK_SWITCH_LAYER_TO_COMPONENT:
        SwitchLayer( aDC, F_Cu );
        break;

    case HK_SWITCH_LAYER_TO_COPPER:
        SwitchLayer( aDC, B_Cu );
        break;

    case HK_SWITCH_LAYER_TO_INNER1:
        SwitchLayer( aDC, In1_Cu );
        break;

    case HK_SWITCH_LAYER_TO_INNER2:
        SwitchLayer( aDC, In2_Cu );
        break;

    case HK_SWITCH_LAYER_TO_INNER3:
        SwitchLayer( aDC, In3_Cu );
        break;

    case HK_SWITCH_LAYER_TO_INNER4:
        SwitchLayer( aDC, In4_Cu );
        break;

    case HK_SWITCH_LAYER_TO_INNER5:
        SwitchLayer( aDC, In5_Cu );
        break;

    case HK_SWITCH_LAYER_TO_INNER6:
        SwitchLayer( aDC, In6_Cu );
        break;

    case HK_HELP: // Display Current hotkey list
        DisplayHotkeyList( this, g_Board_Editor_Hotkeys_Descr );
        break;

    case HK_PREFERENCES:
        evt_type = wxID_PREFERENCES;
        break;

    case HK_ZOOM_IN:
        evt_type = ID_KEY_ZOOM_IN;
        break;

    case HK_ZOOM_OUT:
        evt_type = ID_KEY_ZOOM_OUT;
        break;

    case HK_ZOOM_REDRAW:
        evt_type = ID_ZOOM_REDRAW;
        break;

    case HK_ZOOM_AUTO:
        evt_type = ID_ZOOM_PAGE;
        break;

    case HK_ZOOM_CENTER:
        evt_type = ID_POPUP_ZOOM_CENTER;
        break;

    case HK_ZOOM_SELECTION:
        evt_type = ID_ZOOM_SELECTION;
        break;

    case HK_ADD_MODULE:
        evt_type = ID_PCB_MODULE_BUTT;
        break;

    case HK_UNDO:
    case HK_REDO:
        if( !itemCurrentlyEdited )
        {
            wxCommandEvent event( wxEVT_COMMAND_TOOL_CLICKED, HK_Descr->m_IdMenuEvent );
            wxPostEvent( this, event );
        }

        break;

    case HK_RESET_LOCAL_COORD:  // Set the relative coord
        GetScreen()->m_O_Curseur = GetCrossHairPosition();
        break;

    case HK_SET_GRID_ORIGIN:
        PCBNEW_CONTROL::SetGridOrigin( GetGalCanvas()->GetView(), this,
                                       new KIGFX::ORIGIN_VIEWITEM( GetGridOrigin(), UR_TRANSIENT ),
                                       GetCrossHairPosition() );
        m_canvas->Refresh();
        break;

    case HK_RESET_GRID_ORIGIN:
        PCBNEW_CONTROL::SetGridOrigin( GetGalCanvas()->GetView(), this,
                                       new KIGFX::ORIGIN_VIEWITEM( GetGridOrigin(), UR_TRANSIENT ),
                                       wxPoint( 0, 0 ) );
        m_canvas->Refresh();
        break;

    case HK_SWITCH_UNITS:
        evt_type = (GetUserUnits() == INCHES) ?
                    ID_TB_OPTIONS_SELECT_UNIT_MM : ID_TB_OPTIONS_SELECT_UNIT_INCH;
        break;

    case HK_SWITCH_TRACK_DISPLAY_MODE:
        displ_opts->m_DisplayPcbTrackFill = !displ_opts->m_DisplayPcbTrackFill;
        m_canvas->Refresh();
        break;

    case HK_DELETE:
        OnHotkeyDeleteItem( aDC );
        break;

    case HK_BACK_SPACE:
        if( IsCopperLayer( GetActiveLayer() ) )
        {
            if( !itemCurrentlyEdited )
            {
                // no track is currently being edited - select a segment and remove it.
                // @todo: possibly? pass the HK command code to PcbGeneralLocateAndDisplay()
                // so it can restrict its search to specific item types.
                BOARD_ITEM * item = PcbGeneralLocateAndDisplay();

                // don't let backspace delete modules!!
                if( item && item->IsTrack() )
                {
                    Delete_Segment( aDC, (TRACK*) item );
                    SetCurItem( NULL );
                }

                OnModify();
            }
            else if( GetCurItem()->IsTrack() )
            {
                // then an element is being edited - remove the last segment.
                // simple lines for debugger:
                TRACK* track = (TRACK*) GetCurItem();
                track = Delete_Segment( aDC, track );
                SetCurItem( track );
                OnModify();
            }
        }

        break;

    case HK_GET_AND_MOVE_FOOTPRINT:
        if( !itemCurrentlyEdited )
            evt_type = ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST;

        break;

    case HK_FIND_ITEM:
        if( !itemCurrentlyEdited )
            evt_type = ID_FIND_ITEMS;

        break;

    case HK_OPEN:
        if( !itemCurrentlyEdited )
            evt_type = ID_LOAD_FILE ;

        break;

    case HK_SAVE:
        if( !itemCurrentlyEdited )
            evt_type = ID_SAVE_BOARD;

        break;

    case HK_ADD_MICROVIA: // Place a micro via if a track is in progress
        if( GetToolId() != ID_TRACK_BUTT )
            return true;

        if( !itemCurrentlyEdited )                         // no track in progress: nothing to do
            break;

        if( GetCurItem()->Type() != PCB_TRACE_T )           // Should not occur
            return true;

        if( !GetCurItem()->IsNew() )
            return true;

        // place micro via and switch layer
        if( IsMicroViaAcceptable() )
            evt_type = ID_POPUP_PCB_PLACE_MICROVIA;

        break;

    case HK_ADD_BLIND_BURIED_VIA:
    case HK_ADD_THROUGH_VIA: // Switch to alternate layer and Place a via if a track is in progress
        if( GetBoard()->GetDesignSettings().m_BlindBuriedViaAllowed &&
            hk_id == HK_ADD_BLIND_BURIED_VIA  )
            GetBoard()->GetDesignSettings().m_CurrentViaType = VIA_BLIND_BURIED;
        else
            GetBoard()->GetDesignSettings().m_CurrentViaType = VIA_THROUGH;

        if( !itemCurrentlyEdited ) // no track in progress: switch layer only
        {
            Other_Layer_Route( NULL, aDC );
            if( displ_opts->m_ContrastModeDisplay )
                m_canvas->Refresh();
            break;
        }

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

        if( GetCurItem()->Type() != PCB_TRACE_T )
            return true;

        if( !GetCurItem()->IsNew() )
            return true;

        evt_type = hk_id == HK_ADD_BLIND_BURIED_VIA ?
            ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA : ID_POPUP_PCB_PLACE_THROUGH_VIA;
        break;

    case HK_SEL_LAYER_AND_ADD_THROUGH_VIA:
    case HK_SEL_LAYER_AND_ADD_BLIND_BURIED_VIA:
        if( GetCurItem() == NULL || !GetCurItem()->IsNew() ||
            GetCurItem()->Type() != PCB_TRACE_T )
            break;

        evt_type = hk_id == HK_SEL_LAYER_AND_ADD_BLIND_BURIED_VIA ?
            ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_BLIND_BURIED_VIA :
            ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_THROUGH_VIA;
        break;

    case HK_SWITCH_TRACK_POSTURE:
        /* change the position of initial segment when creating new tracks
         * switch from _/  to -\ .
         */
        evt_type = ID_POPUP_PCB_SWITCH_TRACK_POSTURE ;
        break;

    case HK_DRAG_TRACK_KEEP_SLOPE:
        OnHotkeyMoveItem( HK_DRAG_TRACK_KEEP_SLOPE );
        break;

    case HK_PLACE_ITEM:
        OnHotkeyPlaceItem( aDC );
        break;

    case HK_ADD_NEW_TRACK: // Start new track, if possible
        OnHotkeyBeginRoute( aDC );
        break;

    case HK_EDIT_ITEM:      // Edit board item
        OnHotkeyEditItem( HK_EDIT_ITEM );
        break;

    case HK_EDIT_MODULE_WITH_MODEDIT:      // Edit module with module editor
        OnHotkeyEditItem( HK_EDIT_MODULE_WITH_MODEDIT );
        break;

    case HK_LOCK_UNLOCK_FOOTPRINT: // toggle module "MODULE_is_LOCKED" status:
        // get any module, locked or not locked and toggle its locked status
        if( !itemCurrentlyEdited )
        {
            wxPoint pos = RefPos( true );
            module = GetBoard()->GetFootprint( pos, screen->m_Active_Layer, true );
        }
        else if( GetCurItem()->Type() == PCB_MODULE_T )
        {
            module = (MODULE*) GetCurItem();
        }

        if( module )
        {
            SetCurItem( module );
            module->SetLocked( !module->IsLocked() );
            OnModify();
            SetMsgPanel( module );
        }
        break;

    case HK_DRAG_ITEM:    // Start drag module or track segment
        OnHotkeyMoveItem( HK_DRAG_ITEM );
        break;

    case HK_MOVE_ITEM:                  // Start move item
        OnHotkeyMoveItem( HK_MOVE_ITEM );
        break;

    case HK_COPY_ITEM:
        evt_type = OnHotkeyCopyItem();
        break;

    case HK_ROTATE_ITEM:        // Rotation
        OnHotkeyRotateItem( HK_ROTATE_ITEM );
        break;

    case HK_FLIP_ITEM:
        OnHotkeyFlipItem( HK_FLIP_ITEM );
        break;

    case HK_MOVE_ITEM_EXACT:
    case HK_DUPLICATE_ITEM:
    case HK_DUPLICATE_ITEM_AND_INCREMENT:
    case HK_CREATE_ARRAY:
        OnHotkeyDuplicateOrArrayItem( HK_Descr->m_Idcommand );
        break;

    case HK_SWITCH_HIGHCONTRAST_MODE: // switch to high contrast mode and refresh the canvas
        displ_opts->m_ContrastModeDisplay = !displ_opts->m_ContrastModeDisplay;
        m_canvas->Refresh();
        break;

    case HK_CANVAS_CAIRO:
        evt_type = ID_MENU_CANVAS_CAIRO;
        break;

    case HK_CANVAS_OPENGL:
        evt_type = ID_MENU_CANVAS_OPENGL;
        break;

    case HK_CANVAS_LEGACY:
        evt_type = ID_MENU_CANVAS_LEGACY;
        break;

    case HK_ZONE_FILL_OR_REFILL:
        evt_type = ID_POPUP_PCB_FILL_ALL_ZONES;
        break;

    case HK_ZONE_REMOVE_FILLED:
        evt_type = ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES;
        break;
    }

    if( evt_type != 0 )
    {
        wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
        evt.SetEventObject( this );
        evt.SetId( evt_type );
        GetEventHandler()->ProcessEvent( evt );
    }

    return true;
}
bool PCB_EDIT_FRAME::OnHotkeyDeleteItem( wxDC* aDC )
{
    BOARD_ITEM* item = GetCurItem();
    bool ItemFree = (item == NULL) || (item->GetFlags() == 0);

    switch( GetToolId() )
    {
    case ID_TRACK_BUTT:
        if( !IsCopperLayer ( GetActiveLayer() ) )
            return false;

        if( ItemFree )
        {
            item = PcbGeneralLocateAndDisplay();

            if( item && !item->IsTrack() )
                return false;

            Delete_Track( aDC, (TRACK*) item );
        }
        else if( item->IsTrack( ) )
        {
            // simple lines for debugger:
            TRACK* track = (TRACK*) item;
            track = Delete_Segment( aDC, track );
            SetCurItem( track );
            OnModify();
            return true;
        }
        break;

    case ID_PCB_MODULE_BUTT:
        if( ItemFree )
        {
            wxPoint pos    = RefPos( false );
            MODULE* module = GetBoard()->GetFootprint( pos, UNDEFINED_LAYER, false );

            if( module == NULL || module->IsLocked() )
                return false;

            RemoveStruct( module, aDC );
        }
        else
            return false;
        break;

    default:
        if( ItemFree )
        {
            item = PcbGeneralLocateAndDisplay();

            // Shouldn't there be a check for locked tracks and vias here?
            if( item == NULL || (item->Type() == PCB_MODULE_T && (MODULE*)item->IsLocked()) )
                return false;

            RemoveStruct( item, aDC );
        }
        else
            return false;
    }

    OnModify();
    SetCurItem( NULL );
    return true;
}
bool PCB_EDIT_FRAME::OnHotkeyEditItem( int aIdCommand )
{
    BOARD_ITEM* item = GetCurItem();
    bool itemCurrentlyEdited = item && item->GetFlags();

    if( itemCurrentlyEdited )
        return false;

    item = PcbGeneralLocateAndDisplay();

    if( item == NULL )
        return false;

    SetCurItem( item );

    int evt_type = 0;       //Used to post a wxCommandEvent on demand

    switch( item->Type() )
    {
    case PCB_TRACE_T:
    case PCB_VIA_T:
        if( aIdCommand == HK_EDIT_ITEM )
        {
            // Be sure the corresponding netclass is selected before edit:
            SetCurrentNetClass( ( (BOARD_CONNECTED_ITEM*)item )->GetNetClassName() );
            evt_type = ID_POPUP_PCB_EDIT_TRACKSEG;
        }

        break;

    case PCB_TEXT_T:
        if( aIdCommand == HK_EDIT_ITEM )
            evt_type = ID_POPUP_PCB_EDIT_TEXTEPCB;

        break;

    case PCB_MODULE_T:
        if( aIdCommand == HK_EDIT_ITEM )
            evt_type = ID_POPUP_PCB_EDIT_MODULE_PRMS;
        else if( aIdCommand == HK_EDIT_MODULE_WITH_MODEDIT )
            evt_type = ID_POPUP_PCB_EDIT_MODULE_WITH_MODEDIT;

        break;

    case PCB_PAD_T:
        // Until dec 2012 a EDIT_MODULE event is posted here to prevent pads
        // from being edited by hotkeys.
        // Process_Special_Functions takes care of finding the parent.
        // After dec 2012 a EDIT_PAD event is posted, because there is no
        // reason to not allow pad edit by hotkey
        // (pad coordinates are no more modified by rounding, in nanometer version
        // when using inches or mm in dialog)
        if( aIdCommand == HK_EDIT_ITEM )
            evt_type = ID_POPUP_PCB_EDIT_PAD;

        break;

    case PCB_TARGET_T:
        if( aIdCommand == HK_EDIT_ITEM )
            evt_type = ID_POPUP_PCB_EDIT_PCB_TARGET;

        break;

    case PCB_DIMENSION_T:
        if( aIdCommand == HK_EDIT_ITEM )
            evt_type = ID_POPUP_PCB_EDIT_DIMENSION;

        break;

    case PCB_MODULE_TEXT_T:
        if( aIdCommand == HK_EDIT_ITEM )
            evt_type = ID_POPUP_PCB_EDIT_TEXTMODULE;

        break;

    case PCB_LINE_T:
        if( aIdCommand == HK_EDIT_ITEM )
            evt_type = ID_POPUP_PCB_EDIT_DRAWING;

        break;

    case PCB_ZONE_AREA_T:
        if( aIdCommand == HK_EDIT_ITEM )
            evt_type = ID_POPUP_PCB_EDIT_ZONE_PARAMS;

        break;

    default:
        break;
    }

    if( evt_type != 0 )
    {
        wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
        evt.SetEventObject( this );
        evt.SetId( evt_type );
        GetEventHandler()->ProcessEvent( evt );
        return true;
    }

    return false;
}
void WinEDA_ModuleEditFrame::OnLeftDClick(wxDC * DC, const wxPoint& MousePos)
/****************************************************************************/
/* Appelé sur un double click:
	pour un élément editable (textes, composant):
		appel de l'editeur correspondant.
*/
{
EDA_BaseStruct * DrawStruct = m_CurrentScreen->m_CurrentItem;
wxPoint pos = GetPosition();
wxClientDC dc(DrawPanel);

	DrawPanel->PrepareGraphicContext(&dc);

	switch ( m_ID_current_state )
		{
		case 0:
			if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
				{
				DrawStruct = PcbGeneralLocateAndDisplay();
				}

			if ( (DrawStruct == NULL) || (DrawStruct->m_Flags != 0) )
				break;

			// Element localisé
			m_CurrentScreen->m_CurrentItem = DrawStruct;
			switch ( DrawStruct->m_StructType )
				{
				case TYPEPAD:
					InstallPadOptionsFrame(
						(D_PAD *)DrawStruct, &dc, pos);
					DrawPanel->MouseToCursorSchema();
					break;

				case TYPEMODULE:
					InstallModuleOptionsFrame((MODULE *)DrawStruct,
						&dc, pos);
					DrawPanel->MouseToCursorSchema();
					break;

				case TYPETEXTEMODULE:
					InstallTextModOptionsFrame((TEXTE_MODULE *)DrawStruct,
						&dc, pos);
					DrawPanel->MouseToCursorSchema();
					break;

				default:
					break;
				}
			break;	// end case 0

		case ID_LINE_COMMENT_BUTT:
			{
			if ( DrawStruct && (DrawStruct->m_Flags & IS_NEW) )
				{
				End_Edge_Module((EDGE_MODULE *) DrawStruct, DC);
				m_CurrentScreen->m_CurrentItem = NULL;
				}
			break;
			}

		default:
			break;
		}
}
bool PCB_EDIT_FRAME::OnHotkeyDuplicateOrArrayItem( int aIdCommand )
{
    BOARD_ITEM* item = GetCurItem();
    bool itemCurrentlyEdited = item && item->GetFlags();

    if( itemCurrentlyEdited )
        return false;

    item = PcbGeneralLocateAndDisplay();

    if( item == NULL )
        return false;

    SetCurItem( item );

    int evt_type = 0;       // Used to post a wxCommandEvent on demand

    bool canDuplicate = true;

    switch( item->Type() )
    {
    // Only handle items we know we can handle
    case PCB_PAD_T:
        canDuplicate = false;
        // no break
    case PCB_MODULE_T:
    case PCB_LINE_T:
    case PCB_TEXT_T:
    case PCB_TRACE_T:
    case PCB_ZONE_AREA_T:
    case PCB_TARGET_T:
    case PCB_DIMENSION_T:
        switch( aIdCommand )
        {
        case HK_CREATE_ARRAY:
            if( canDuplicate )
                evt_type = ID_POPUP_PCB_CREATE_ARRAY;
            break;

        case HK_DUPLICATE_ITEM_AND_INCREMENT:
            if( canDuplicate )
                evt_type = ID_POPUP_PCB_DUPLICATE_ITEM_AND_INCREMENT;
            break;

        case HK_DUPLICATE_ITEM:
            if( canDuplicate )
                evt_type = ID_POPUP_PCB_DUPLICATE_ITEM;
            break;

        case HK_MOVE_ITEM_EXACT:
            evt_type = ID_POPUP_PCB_MOVE_EXACT;
            break;

        default:
            // We don't handle other commands here
            break;
        }
        break;

    default:
        evt_type = 0;
        break;
    }

    return PostCommandMenuEvent( evt_type );
}
Exemple #9
0
bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
{
    wxString    msg;
    int         flags = 0;
    bool        locate_track = false;
    bool        blockActive  = (GetScreen()->m_BlockLocate.m_Command != BLOCK_IDLE);

    wxClientDC  dc( m_canvas );

    BOARD_ITEM* item = GetCurItem();

    m_canvas->SetCanStartBlock( -1 );    // Avoid to start a block coomand when clicking on menu

    // If a command or a block is in progress:
    // Put the Cancel command (if needed) and the End command

    if( blockActive )
    {
        createPopUpBlockMenu( aPopMenu );
        aPopMenu->AppendSeparator();
        return true;
    }

    m_canvas->CrossHairOff( &dc );

    if( GetToolId() != ID_NO_TOOL_SELECTED )
    {
        if( item && item->GetFlags() )
        {
            AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel" ),
                         KiBitmap( cancel_xpm ) );
        }
        else
        {
            AddMenuItem( aPopMenu, ID_POPUP_CLOSE_CURRENT_TOOL,
                         _( "End Tool" ), KiBitmap( cursor_xpm ) );
        }

        aPopMenu->AppendSeparator();
    }
    else
    {
        if( item && item->GetFlags() )
        {
            AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND,
                         _( "Cancel" ), KiBitmap( cancel_xpm ) );
            aPopMenu->AppendSeparator();
        }
    }

    /* Select a proper item */

    wxPoint cursorPos = GetScreen()->GetCrossHairPosition();
    wxPoint selectPos = m_Collector->GetRefPos();

    selectPos = GetScreen()->GetNearestGridPosition( selectPos );

    /*  We can reselect another item only if there are no item being edited
     * because ALL moving functions use GetCurItem(), therefore GetCurItem()
     * must return the same item during moving. We know an item is moving
     * if( item && (item->m_Flags != 0)) is true and after calling
     * PcbGeneralLocateAndDisplay(), GetCurItem() is any arbitrary BOARD_ITEM,
     * not the current item being edited. In such case we cannot call
     * PcbGeneralLocateAndDisplay().
     */
    if( !item || (item->GetFlags() == 0) )
    {
        // show "item selector" menu only if no item now or selected item was not
        // previously picked at this position
        if( !item || cursorPos != selectPos )
        {
            m_canvas->SetAbortRequest( false );
            item = PcbGeneralLocateAndDisplay();

            if( m_canvas->GetAbortRequest() )
            {
                m_canvas->CrossHairOn( &dc );
                return false;
            }
        }
    }

    item = GetCurItem();

    if( item )
        flags = item->GetFlags();
    else
        flags = 0;

    if( item )
    {
        switch( item->Type() )
        {
        case PCB_MODULE_T:
            createPopUpMenuForFootprints( (MODULE*) item, aPopMenu );

            if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_MODULE ) )
            {
                aPopMenu->AppendSeparator();

                if( !( (MODULE*) item )->IsLocked() )
                {
                    msg = AddHotkeyName( _("Lock Module" ), g_Board_Editor_Hokeys_Descr,
                                         HK_LOCK_UNLOCK_FOOTPRINT );
                    AddMenuItem( aPopMenu, ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE, msg,
                                 KiBitmap( locked_xpm ) );
                }
                else
                {
                    msg = AddHotkeyName( _( "Unlock Module" ), g_Board_Editor_Hokeys_Descr,
                                         HK_LOCK_UNLOCK_FOOTPRINT );
                    AddMenuItem( aPopMenu, ID_POPUP_PCB_AUTOPLACE_FREE_MODULE, msg,
                                 KiBitmap( unlocked_xpm ) );
                }

                if( !flags )
                    aPopMenu->Append( ID_POPUP_PCB_AUTOPLACE_CURRENT_MODULE,
                                      _( "Auto Place Module" ) );
            }

            if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_TRACKS ) )
            {
                if( !flags )
                    aPopMenu->Append( ID_POPUP_PCB_AUTOROUTE_MODULE, _( "Autoroute Module" ) );
            }
            break;

        case PCB_PAD_T:
            createPopUpMenuForFpPads( (D_PAD*) item, aPopMenu );
            break;

        case PCB_MODULE_TEXT_T:
            createPopUpMenuForFpTexts( (TEXTE_MODULE*) item, aPopMenu );
            break;

        case PCB_LINE_T:  // Some graphic items on technical layers
            if( (flags & IS_NEW) )
            {
                AddMenuItem( aPopMenu, ID_POPUP_PCB_STOP_CURRENT_DRAWING,
                             _( "End Drawing" ), KiBitmap( apply_xpm ) );
            }

            if( !flags )
            {
                msg = AddHotkeyName( _( "Move Drawing" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_DRAWING_REQUEST,
                             msg, KiBitmap( move_xpm ) );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_DRAWING, _( "Edit Drawing" ),
                             KiBitmap( edit_xpm ) );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DRAWING,
                             _( "Delete Drawing" ), KiBitmap( delete_xpm ) );

                if( item->GetLayer() > LAST_COPPER_LAYER )
                    AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DRAWING_LAYER,
                                 _( "Delete All Drawing on Layer" ), KiBitmap( delete_xpm ) );
            }

            break;

        case PCB_ZONE_T:      // Item used to fill a zone
            AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_ZONE,
                         _( "Delete Zone Filling" ), KiBitmap( delete_xpm ) );
            break;

        case PCB_ZONE_AREA_T:    // Item used to handle a zone area (outlines, holes ...)
            if( flags & IS_NEW )
            {
                AddMenuItem( aPopMenu, ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE,
                             _( "Close Zone Outline" ), KiBitmap( apply_xpm ) );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_ZONE_LAST_CREATED_CORNER,
                             _( "Delete Last Corner" ), KiBitmap( delete_xpm ) );
            }
            else
            {
                createPopUpMenuForZones( (ZONE_CONTAINER*) item, aPopMenu );
            }

            break;

        case PCB_TEXT_T:
            createPopUpMenuForTexts( (TEXTE_PCB*) item, aPopMenu );
            break;

        case PCB_TRACE_T:
        case PCB_VIA_T:
            locate_track = true;
            createPopupMenuForTracks( (TRACK*) item, aPopMenu );
            break;

        case PCB_MARKER_T:
            createPopUpMenuForMarkers( (MARKER_PCB*) item, aPopMenu );
            break;

        case PCB_DIMENSION_T:
            if( !flags )
            {
                msg = AddHotkeyName( _( "Edit Dimension" ), g_Board_Editor_Hokeys_Descr,
                                     HK_EDIT_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_DIMENSION, msg, KiBitmap( edit_xpm ) );
                msg = AddHotkeyName( _( "Move Dimension Text" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_TEXT_DIMENSION_REQUEST,
                             msg, KiBitmap( move_text_xpm ) );
                msg = AddHotkeyName( _( "Delete Dimension" ), g_Board_Editor_Hokeys_Descr,
                                     HK_DELETE );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DIMENSION,
                             msg, KiBitmap( delete_xpm ) );
            }
            break;

        case PCB_TARGET_T:
            if( !flags )
            {
                msg = AddHotkeyName( _( "Move Target" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_MIRE_REQUEST, msg, KiBitmap( move_xpm ) );
                msg = AddHotkeyName( _( "Edit Target" ), g_Board_Editor_Hokeys_Descr,
                                     HK_EDIT_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_MIRE, msg, KiBitmap( edit_xpm ) );
                msg = AddHotkeyName( _( "Delete Target" ), g_Board_Editor_Hokeys_Descr, HK_DELETE );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_MIRE,
                             msg, KiBitmap( delete_xpm ) );
            }

            break;

        case PCB_MODULE_EDGE_T:
        case SCREEN_T:
        case TYPE_NOT_INIT:
        case PCB_T:
            msg.Printf( wxT( "PCB_EDIT_FRAME::OnRightClick() Error: unexpected DrawType %d" ),
                        item->Type() );
            wxMessageBox( msg );
            SetCurItem( NULL );
            break;

        default:
            msg.Printf( wxT( "PCB_EDIT_FRAME::OnRightClick() Error: unknown DrawType %d" ),
                        item->Type() );
            wxMessageBox( msg );

            // Attempt to clear error (but should no occurs )
            if( item->Type() >= MAX_STRUCT_TYPE_ID )
                SetCurItem( NULL );

            break;
        }

        aPopMenu->AppendSeparator();
    }

    if( !flags )
    {
        msg = AddHotkeyName( _( "Get and Move Footprint" ),
                             g_Board_Editor_Hokeys_Descr, HK_GET_AND_MOVE_FOOTPRINT );
        AddMenuItem( aPopMenu, ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST,
                     msg, KiBitmap( move_module_xpm ) );
    }

    /* Display context sensitive commands: */
    switch(  GetToolId() )
    {
    case ID_PCB_ZONES_BUTT:
        if(  GetBoard()->m_ZoneDescriptorList.size() > 0 )
        {
            aPopMenu->AppendSeparator();
            AddMenuItem( aPopMenu, ID_POPUP_PCB_FILL_ALL_ZONES,
                         _( "Fill or Refill All Zones" ), KiBitmap( fill_zone_xpm ) );
            AddMenuItem( aPopMenu, ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES,
                         _( "Remove Filled Areas in All Zones" ), KiBitmap( zone_unfill_xpm ) );
            aPopMenu->AppendSeparator();
        }

        AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_LAYER,
                     _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
        aPopMenu->AppendSeparator();
        break;

    case ID_TRACK_BUTT:
        if ( ! locate_track )   // This menu is already added when a track is located
            AddMenuItem( aPopMenu, Append_Track_Width_List( GetBoard() ),
                         ID_POPUP_PCB_SELECT_WIDTH, _( "Select Track Width" ),
                         KiBitmap( width_track_xpm ) );

        AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_CU_LAYER,
                     _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
        AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_LAYER_PAIR,
                     _( "Select Layer Pair for Vias" ), KiBitmap( select_layer_pair_xpm ) );
        aPopMenu->AppendSeparator();
        break;

    case ID_PCB_CIRCLE_BUTT:
    case ID_PCB_ARC_BUTT:
    case ID_PCB_ADD_TEXT_BUTT:
    case ID_PCB_ADD_LINE_BUTT:
    case ID_PCB_DIMENSION_BUTT:
        AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_NO_CU_LAYER,
                      _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
        aPopMenu->AppendSeparator();
        break;

    case ID_PCB_MODULE_BUTT:
        AddMenuItem( aPopMenu, ID_POPUP_PCB_DISPLAY_FOOTPRINT_DOC,
                     _( "Footprint Documentation" ), KiBitmap( book_xpm ) );
        aPopMenu->AppendSeparator();
        break;

    case ID_NO_TOOL_SELECTED:
        if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_MODULE ) )
        {
            wxMenu* commands = new wxMenu;
            AddMenuItem( aPopMenu, commands, ID_POPUP_PCB_AUTOPLACE_COMMANDS,
                         _( "Glob Move and Place" ), KiBitmap( move_xpm ) );
            AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES,
                         _( "Unlock All Modules" ), KiBitmap( unlocked_xpm ) );
            AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES,
                         _( "Lock All Modules" ), KiBitmap( locked_xpm ) );
            commands->AppendSeparator();
            AddMenuItem( commands, ID_POPUP_PCB_AUTOMOVE_ALL_MODULES,
                         _( "Move All Modules" ), KiBitmap( move_xpm ) );
            commands->Append( ID_POPUP_PCB_AUTOMOVE_NEW_MODULES, _( "Move New Modules" ) );
            commands->AppendSeparator();
            commands->Append( ID_POPUP_PCB_AUTOPLACE_ALL_MODULES, _( "Autoplace All Modules" ) );
            commands->Append( ID_POPUP_PCB_AUTOPLACE_NEW_MODULES, _( "Autoplace New Modules" ) );
            commands->Append( ID_POPUP_PCB_AUTOPLACE_NEXT_MODULE, _( "Autoplace Next Module" ) );
            commands->AppendSeparator();
            AddMenuItem( commands, ID_POPUP_PCB_REORIENT_ALL_MODULES,
                         _( "Orient All Modules" ), KiBitmap( rotate_module_pos_xpm ) );
            aPopMenu->AppendSeparator();
        }

        if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_TRACKS ) )
        {
            wxMenu* commands = new wxMenu;
            aPopMenu->Append( ID_POPUP_PCB_AUTOROUTE_COMMANDS, _( "Autoroute" ), commands );
            AddMenuItem( commands, ID_POPUP_PCB_SELECT_LAYER_PAIR,
                         _( "Select Layer Pair" ), KiBitmap( select_layer_pair_xpm ) );
            commands->AppendSeparator();
            commands->Append( ID_POPUP_PCB_AUTOROUTE_ALL_MODULES, _( "Autoroute All Modules" ) );
            commands->AppendSeparator();
            commands->Append( ID_POPUP_PCB_AUTOROUTE_RESET_UNROUTED, _( "Reset Unrouted" ) );
            aPopMenu->AppendSeparator();
        }

        if( locate_track )
            AddMenuItem( aPopMenu, Append_Track_Width_List( GetBoard() ),
                         ID_POPUP_PCB_SELECT_WIDTH, _( "Select Track Width" ),
                         KiBitmap( width_track_xpm ) );

        AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_LAYER,
                     _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
        aPopMenu->AppendSeparator();
        break;
    }

    m_canvas->CrossHairOn( &dc );
    return true;
}
void WinEDA_PcbFrame::OnRightClick(const wxPoint& MousePos, wxMenu * PopMenu)
/****************************************************************************/
/* Prepare le menu PullUp affiché par un click sur le bouton droit
de la souris.
   Ce menu est ensuite complété par la liste des commandes de ZOOM
*/
{
EDA_BaseStruct *DrawStruct = m_CurrentScreen->m_CurrentItem;
wxString msg;
int flags = 0;
bool locate_track = FALSE;
bool BlockActive = (m_CurrentScreen->BlockLocate.m_Command !=  BLOCK_IDLE);
wxClientDC dc(DrawPanel);

	GetScreen()->CursorOff(DrawPanel, &dc);
	DrawPanel->m_CanStartBlock = -1;	// Ne pas engager un debut de bloc sur validation menu

	 // Simple localisation des elements si possible
	if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
	{
		if (m_HTOOL_current_state == ID_TOOLBARH_PCB_AUTOPLACE)
		{
			DrawStruct = Locate_Prefered_Module(m_Pcb, CURSEUR_OFF_GRILLE);
			if ( DrawStruct ) ((MODULE*)DrawStruct)->Display_Infos(this);
			else DrawStruct = PcbGeneralLocateAndDisplay();
		}
		else DrawStruct = PcbGeneralLocateAndDisplay();
	}

	// Si commande en cours: affichage fin de commande
	if ( m_ID_current_state )
	{
		if ( DrawStruct && DrawStruct->m_Flags )
		{
			ADD_MENUITEM(PopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND,
				_("Cancel"), cancel_xpm);
		}
		else
		{
			ADD_MENUITEM(PopMenu, ID_POPUP_CLOSE_CURRENT_TOOL,
				_("End Tool"), cancel_tool_xpm);
		}
		PopMenu->AppendSeparator();
	}

	else
	{
		if ( (DrawStruct && DrawStruct->m_Flags) || BlockActive )
		{
			if ( BlockActive )
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND,
					_("Cancel Block"), cancel_xpm );
				ADD_MENUITEM(PopMenu, ID_POPUP_ZOOM_BLOCK,
					_("Zoom Block (Midd butt drag)"), zoom_selected_xpm );
				PopMenu->AppendSeparator();
				ADD_MENUITEM(PopMenu, ID_POPUP_PLACE_BLOCK,
					_("Place Block"), apply_xpm );
				ADD_MENUITEM(PopMenu, ID_POPUP_COPY_BLOCK,
					_("Copy Block (shift + drag mouse)"), copyblock_xpm );
				ADD_MENUITEM(PopMenu, ID_POPUP_INVERT_BLOCK,
					_("Flip Block (alt + drag mouse)"), invert_module_xpm );
				ADD_MENUITEM(PopMenu, ID_POPUP_ROTATE_BLOCK,
					_("Rotate Block (ctrl + drag mouse)"), rotate_pos_xpm );
				ADD_MENUITEM(PopMenu, ID_POPUP_DELETE_BLOCK,
					_("Delete Block (shift+ctrl + drag mouse)"), delete_xpm );
			}
			else
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND,
					_("Cancel"), cancel_xpm);
			}
			PopMenu->AppendSeparator();
		}
	}

	if ( BlockActive ) goto out;

	m_CurrentScreen->m_CurrentItem = DrawStruct;

	if ( DrawStruct )
	{
		flags = DrawStruct->m_Flags;
		switch ( DrawStruct->m_StructType )
		{
		case TYPEMODULE:
			if( !flags ) AppendModuleOnRightClickMenu(PopMenu, TRUE);
			else AppendModuleOnRightClickMenu(PopMenu, FALSE);

			if (m_HTOOL_current_state == ID_TOOLBARH_PCB_AUTOPLACE)
			{
				PopMenu->AppendSeparator();
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE, _("Fix Module"),
					Locked_xpm);
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_AUTOPLACE_FREE_MODULE, _("Free Module"),
					Unlocked_xpm);
				if( !flags )
					PopMenu->Append( ID_POPUP_PCB_AUTOPLACE_CURRENT_MODULE,
						_("Auto place Module"));
			}

			if (m_HTOOL_current_state == ID_TOOLBARH_PCB_AUTOROUTE)
			{
				if( !flags )
					PopMenu->Append( ID_POPUP_PCB_AUTOROUTE_MODULE, _("Autoroute"));
			}

			if( !flags )
			{
				PopMenu->AppendSeparator();
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_MODULE,
					_("Delete Module"), Delete_Module_xpm);
			}
			break;

		case TYPEPAD:
			if( !flags )
			{
			MODULE * Module = (MODULE *) DrawStruct->m_Parent;
				if (Module)
				{
					AppendModuleOnRightClickMenu(PopMenu, TRUE);
					PopMenu->AppendSeparator();
				}
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_MOVE_PAD_REQUEST,
					_("Move Pad"), move_pad_xpm);
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DRAG_PAD_REQUEST,
					_("Drag Pad"), drag_pad_xpm);
			}
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_EDIT_PAD, _("Edit Pad"), options_pad_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_IMPORT_PAD_SETTINGS, 
					_("New Pad Settings"), options_new_pad_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_EXPORT_PAD_SETTINGS,
				_("Export Pad Settings"), Export_Options_Pad_xpm);
			if (m_HTOOL_current_state == ID_TOOLBARH_PCB_AUTOROUTE)
			{
				if( !flags )
				{
					PopMenu->Append( ID_POPUP_PCB_AUTOROUTE_PAD, _("Autoroute Pad"));
					PopMenu->Append( ID_POPUP_PCB_AUTOROUTE_NET, _("Autoroute Net"));
				}
			}

			if( !flags )
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_PAD,
					_("delete Pad"), Delete_Pad_xpm);
				PopMenu->AppendSeparator();
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS,
					_("Global Pad Settings"), global_options_pad_xpm);
			}
			break;

		case TYPETEXTEMODULE:
			if( !flags )
			{
			MODULE * Module = (MODULE *) DrawStruct->m_Parent;
				if (Module)
				{
					AppendModuleOnRightClickMenu(PopMenu, TRUE);
					PopMenu->AppendSeparator();
				}
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST,
					_("Move Text Mod."), Move_Field_xpm);
			}
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_ROTATE_TEXTMODULE,
				_("Rotate Text Mod."), Rotate_Field_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_EDIT_TEXTMODULE,
				_("Edit Text Mod."), edit_text_xpm);
			if ( ((TEXTE_MODULE*)DrawStruct)->m_Type == TEXT_is_DIVERS)
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_TEXTMODULE,
					_("Delete Text Mod."), delete_xpm);
			break;

		case TYPEDRAWSEGMENT:
			if( !flags )
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_MOVE_DRAWING_REQUEST,
					_("Move Drawing"), move_xpm);
			}
			if( flags & IS_NEW )
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_STOP_CURRENT_DRAWING,
					_("End Drawing"), apply_xpm);
			}
			PopMenu->Append(ID_POPUP_PCB_EDIT_DRAWING, _("Edit Drawing"));
			PopMenu->Append(ID_POPUP_PCB_DELETE_DRAWING, _("Delete Drawing"));
			break;

		case TYPEEDGEZONE:
			if( flags & IS_NEW )
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE,
					_("End edge zone"), apply_xpm);
			}
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_EDGE_ZONE,
				_("Delete edge zone"), delete_xpm);
			break;

		case TYPETEXTE:
			if( !flags )
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_MOVE_TEXTEPCB_REQUEST,
							_("Move Text"), move_text_xpm);
			}
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_ROTATE_TEXTEPCB,
				_("Rotate Text"), rotate_pos_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_EDIT_TEXTEPCB,
				_("Edit Text"), edit_text_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_TEXTEPCB,
				_("Delete Text"), delete_text_xpm);
			break;

		case TYPETRACK:
		case TYPEVIA:
			locate_track = TRUE;
			CreatePopupMenuForTracks( (TRACK *) DrawStruct, GetScreen()->m_Curseur,
				PopMenu);
			break;

		case TYPEZONE:
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_EDIT_ZONE,
				_("Edit Zone"), edit_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_ZONE,
				_("Delete Zone"), delete_xpm);
			break;

		case TYPEMARQUEUR:
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_MARKER,
				_("Delete Marker"), delete_xpm);
			break;

		case TYPECOTATION:
			if( !flags )
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_EDIT_COTATION,
					_("Edit Cotation"), edit_xpm);
			}
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_COTATION,
				_("Delete Cotation"), delete_xpm);
			break;

		case TYPEMIRE:
			if( !flags )
			{
				ADD_MENUITEM(PopMenu, ID_POPUP_PCB_MOVE_MIRE_REQUEST,
							_("Move Mire"), move_xpm );
			}
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_EDIT_MIRE,
				_("Edit Mire"), edit_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DELETE_MIRE, 
				_("Delete Mire"), delete_xpm);
			break;

		case TYPEEDGEMODULE:
		case TYPESCREEN:
		case TYPE_NOT_INIT:
		case TYPEPCB:
		case PCB_EQUIPOT_STRUCT_TYPE:
			msg.Printf(
				wxT("WinEDA_PcbFrame::OnRightClick Error: illegal DrawType %d"),
				DrawStruct->m_StructType);
			DisplayError(this, msg );
			break;

		default:
			msg.Printf(
				wxT("WinEDA_PcbFrame::OnRightClick Error: unknown DrawType %d"),
				DrawStruct->m_StructType);
			DisplayError(this, msg );
			break;
		}
	PopMenu->AppendSeparator();
	}

	/* Traitement des fonctions specifiques */
	switch (  m_ID_current_state )
		{
		case ID_PCB_ZONES_BUTT:
			{
			bool add_separator = FALSE;
			PopMenu->Append(ID_POPUP_PCB_FILL_ZONE, _("Fill zone") );

			if ( DrawStruct &&
				 ( (DrawStruct->m_StructType == TYPEPAD) ||
					(DrawStruct->m_StructType == TYPETRACK) ||
					(DrawStruct->m_StructType == TYPEVIA) ) )
				{
				add_separator = TRUE;
				PopMenu->Append(ID_POPUP_PCB_SELECT_NET_ZONE, _("Select Net"));
				}
			if( m_Pcb->m_CurrentLimitZone )
				{
				add_separator = TRUE;
				PopMenu->Append(ID_POPUP_PCB_DELETE_ZONE_LIMIT, _("Delete Zone Limit"));
				}
			if ( add_separator ) PopMenu->AppendSeparator();
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_SELECT_LAYER,
				_("Select Working Layer"), Select_W_Layer_xpm);
			PopMenu->AppendSeparator();
			}
			break;

		case ID_TRACK_BUTT:
			{
			ADD_MENUITEM_WITH_SUBMENU( PopMenu, Append_Track_Width_List(),
						ID_POPUP_PCB_SELECT_WIDTH,
						_("Select Track Width"), width_track_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_SELECT_CU_LAYER,
				_("Select Working Layer"), Select_W_Layer_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_SELECT_LAYER_PAIR,
					_("Select layer pair for vias"), select_layer_pair_xpm);
			PopMenu->AppendSeparator();
			}
			break;

		case ID_PCB_CIRCLE_BUTT:
		case ID_PCB_ARC_BUTT:
		case ID_TEXT_COMMENT_BUTT:
		case ID_LINE_COMMENT_BUTT:
		case ID_PCB_COTATION_BUTT:
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_SELECT_NO_CU_LAYER,
				_("Select Working Layer"), Select_W_Layer_xpm);
			PopMenu->AppendSeparator();
			break;

		case ID_COMPONENT_BUTT:
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_DISPLAY_FOOTPRINT_DOC,
					_("Footprint documentation"), book_xpm);
			PopMenu->AppendSeparator();
			break;

		case 0:
			if (m_HTOOL_current_state == ID_TOOLBARH_PCB_AUTOPLACE)
				{
				wxMenu * commands = new wxMenu;
				ADD_MENUITEM_WITH_SUBMENU(PopMenu, commands,
					ID_POPUP_PCB_AUTOPLACE_COMMANDS, _("Glob Move and Place"), move_xpm);
				ADD_MENUITEM(commands, ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES,
					_("Free All Modules"), Unlocked_xpm);
				ADD_MENUITEM(commands, ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES,
					_("Fixe All Modules"), Locked_xpm);
				commands->AppendSeparator();
				ADD_MENUITEM(commands, ID_POPUP_PCB_AUTOMOVE_ALL_MODULES, 
					_("Move All Modules"), move_xpm);
				commands->Append( ID_POPUP_PCB_AUTOMOVE_NEW_MODULES, _("Move New Modules"));
				commands->AppendSeparator();
				commands->Append( ID_POPUP_PCB_AUTOPLACE_ALL_MODULES, _("Autoplace All Modules"));
				commands->Append( ID_POPUP_PCB_AUTOPLACE_NEW_MODULES, _("Autoplace New Modules"));
				commands->Append( ID_POPUP_PCB_AUTOPLACE_NEXT_MODULE, _("Autoplace Next Module"));
				commands->AppendSeparator();
				ADD_MENUITEM(commands, ID_POPUP_PCB_REORIENT_ALL_MODULES,
					_("Orient All Modules"), rotate_module_pos_xpm);
				PopMenu->AppendSeparator();
				}
			if (m_HTOOL_current_state == ID_TOOLBARH_PCB_AUTOROUTE)
				{
				wxMenu * commands = new wxMenu;
				PopMenu->Append(ID_POPUP_PCB_AUTOROUTE_COMMANDS, _("Global Autoroute"), commands);
				ADD_MENUITEM(commands, ID_POPUP_PCB_SELECT_LAYER_PAIR,
						_("Select layer pair"), select_layer_pair_xpm);
				commands->AppendSeparator();
				commands->Append( ID_POPUP_PCB_AUTOROUTE_ALL_MODULES, _("Autoroute All Modules"));
				commands->AppendSeparator();
				commands->Append( ID_POPUP_PCB_AUTOROUTE_RESET_UNROUTED, _("Reset Unrouted"));
				if ( m_Pcb->m_Modules )
					{
					commands->AppendSeparator();
					commands->Append( ID_POPUP_PCB_AUTOROUTE_GET_AUTOROUTER,
									_("Global AutoRouter"));
					commands->Append( ID_POPUP_PCB_AUTOROUTE_GET_AUTOROUTER_DATA,
									_("Read Global AutoRouter Data"));
					}
				PopMenu->AppendSeparator();
				}

			if ( locate_track )
				ADD_MENUITEM_WITH_SUBMENU(PopMenu, Append_Track_Width_List(),
						ID_POPUP_PCB_SELECT_WIDTH, _("Select Track Width"),
						width_track_xpm);
			ADD_MENUITEM(PopMenu, ID_POPUP_PCB_SELECT_LAYER,
				_("Select Working Layer"), Select_W_Layer_xpm);
			PopMenu->AppendSeparator();
			break;

		}
  out:
	GetScreen()->CursorOn(DrawPanel, &dc);
}
/* 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;
    }
}
/* handle the double click on the mouse left button
 */
void PCB_EDIT_FRAME::OnLeftDClick( wxDC* aDC, const wxPoint& aPosition )
{
    BOARD_ITEM* DrawStruct = GetCurItem();

    switch( GetToolId() )
    {
    case ID_NO_TOOL_SELECTED:
        if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) )
        {
            DrawStruct = PcbGeneralLocateAndDisplay();
        }

        if( (DrawStruct == NULL) || (DrawStruct->GetFlags() != 0) )
            break;

        SendMessageToEESCHEMA( DrawStruct );

        // An item is found
        SetCurItem( DrawStruct );

        switch( DrawStruct->Type() )
        {
        case PCB_TRACE_T:
        case PCB_VIA_T:
            if( DrawStruct->IsNew() )
            {
                if( End_Route( (TRACK*) DrawStruct, aDC ) )
                    m_canvas->SetAutoPanRequest( false );
            }
            else if( DrawStruct->GetFlags() == 0 )
            {
                Edit_TrackSegm_Width( aDC, (TRACK*) DrawStruct );
            }

            break;

        case PCB_TEXT_T:
        case PCB_PAD_T:
        case PCB_MODULE_T:
        case PCB_TARGET_T:
        case PCB_DIMENSION_T:
        case PCB_MODULE_TEXT_T:
            OnEditItemRequest( aDC, DrawStruct );
            m_canvas->MoveCursorToCrossHair();
            break;

        case PCB_LINE_T:
            OnEditItemRequest( aDC, DrawStruct );
            break;

        case PCB_ZONE_AREA_T:
            if( DrawStruct->GetFlags() )
                break;

            OnEditItemRequest( aDC, DrawStruct );
            break;

        default:
            break;
        }

        break;      // end case 0

    case ID_TRACK_BUTT:
        if( DrawStruct && DrawStruct->IsNew() )
        {
            if( End_Route( (TRACK*) DrawStruct, aDC ) )
                m_canvas->SetAutoPanRequest( false );
        }

        break;

    case ID_PCB_ZONES_BUTT:
    case ID_PCB_KEEPOUT_AREA_BUTT:
        if( End_Zone( aDC ) )
        {
            m_canvas->SetAutoPanRequest( false );
            SetCurItem( NULL );
        }

        break;

    case ID_PCB_ADD_LINE_BUTT:
    case ID_PCB_ARC_BUTT:
    case ID_PCB_CIRCLE_BUTT:
        if( DrawStruct == NULL )
            break;

        if( DrawStruct->Type() != PCB_LINE_T )
        {
            DisplayError( this, wxT( "DrawStruct Type error" ) );
            m_canvas->SetAutoPanRequest( false );
            break;
        }

        if( DrawStruct->IsNew() )
        {
            End_Edge( (DRAWSEGMENT*) DrawStruct, aDC );
            m_canvas->SetAutoPanRequest( false );
            SetCurItem( NULL );
        }

        break;
    }
}
Exemple #13
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;
    }
}
Exemple #14
0
void WinEDA_PcbFrame::OnLeftDClick(wxDC * DC, const wxPoint& MousePos)
/********************************************************************************/
/* Appelé sur un double click:
	pour un élément editable (textes, composant):
		appel de l'editeur correspondant.
	pour une connexion en cours:
		termine la connexion
*/
{
    EDA_BaseStruct * DrawStruct = CURRENT_ITEM;
    wxPoint pos = GetPosition();
    wxClientDC dc(DrawPanel);

    DrawPanel->PrepareGraphicContext(&dc);

    switch ( m_ID_current_state )
    {
    case 0:
        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
        {
            DrawStruct = PcbGeneralLocateAndDisplay();
        }

        if ( (DrawStruct == NULL) || (DrawStruct->m_Flags != 0) )
            break;

        // Element localisé
        GetScreen()->m_CurrentItem = DrawStruct;
        switch ( DrawStruct->m_StructType )
        {
        case TYPETRACK:
        case TYPEVIA:
            if (DrawStruct->m_Flags & IS_NEW)
            {
                End_Route( (TRACK *) DrawStruct, DC);
                DrawPanel->m_AutoPAN_Request = FALSE;
            }
            else if (DrawStruct->m_Flags == 0)
            {
                Edit_TrackSegm_Width(DC,
                                     (TRACK *) DrawStruct);
            }
            break;

        case TYPETEXTE:
            InstallTextPCBOptionsFrame((TEXTE_PCB *)DrawStruct,
                                       DC, ((TEXTE_PCB *)DrawStruct)->m_Pos);
            DrawPanel->MouseToCursorSchema();
            break;

        case TYPEPAD:
            InstallPadOptionsFrame(
                (D_PAD *)DrawStruct, &dc, pos);
            DrawPanel->MouseToCursorSchema();
            break;

        case TYPEMODULE:
            InstallModuleOptionsFrame((MODULE *)DrawStruct,
                                      &dc, pos);
            DrawPanel->MouseToCursorSchema();
            break;

        case TYPEMIRE:
            InstallMireOptionsFrame( (MIREPCB *)DrawStruct, &dc, pos);
            DrawPanel->MouseToCursorSchema();
            break;

        case TYPETEXTEMODULE:
            InstallTextModOptionsFrame((TEXTE_MODULE *)DrawStruct,
                                       &dc, pos);
            DrawPanel->MouseToCursorSchema();
            break;

        case TYPEDRAWSEGMENT:
            break;

        default:
            break;
        }
        break;	// end case 0

    case ID_TRACK_BUTT:
        if ( DrawStruct && (DrawStruct->m_Flags & IS_NEW) )
        {
            End_Route( (TRACK *) DrawStruct, DC);
            DrawPanel->m_AutoPAN_Request = FALSE;
        }
        break;

    case ID_PCB_ZONES_BUTT:
        End_Zone(DC);
        DrawPanel->m_AutoPAN_Request = FALSE;
        GetScreen()->m_CurrentItem = NULL;
        break;

    case ID_LINE_COMMENT_BUTT:
    case ID_PCB_ARC_BUTT:
    case ID_PCB_CIRCLE_BUTT:
        if ( DrawStruct == NULL ) break;
        if ( DrawStruct->m_StructType != TYPEDRAWSEGMENT )
        {
            DisplayError(this, wxT("DrawStruct Type error"));
            DrawPanel->m_AutoPAN_Request = FALSE;
            break;
        }
        if ( (DrawStruct->m_Flags & IS_NEW) )
        {
            End_Edge( (DRAWSEGMENT *) DrawStruct, &dc);
            DrawPanel->m_AutoPAN_Request = FALSE;
            GetScreen()->m_CurrentItem = NULL;
        }
        break;

    }
}
Exemple #15
0
bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
{
    wxString    msg;
    STATUS_FLAGS flags = 0;
    bool        trackFound = false; // Flag set to true,
                                    // if a track is being the cursor, to avoid
                                    // to display menus relative to tracks twice
    bool        blockActive  = !GetScreen()->m_BlockLocate.IsIdle();

    BOARD_ITEM* item = GetCurItem();

    m_canvas->SetCanStartBlock( -1 );    // Avoid to start a block command when clicking on menu

    // If a command or a block is in progress:
    // Put the Cancel command (if needed) and the End command

    if( blockActive )
    {
        createPopUpBlockMenu( aPopMenu );
        aPopMenu->AppendSeparator();
        return true;
    }

    if( GetToolId() != ID_NO_TOOL_SELECTED )
    {
        if( item && item->GetFlags() )
        {
            AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel" ),
                         KiBitmap( cancel_xpm ) );
        }
        else
        {
            AddMenuItem( aPopMenu, ID_POPUP_CLOSE_CURRENT_TOOL,
                         _( "End Tool" ), KiBitmap( cursor_xpm ) );
        }

        aPopMenu->AppendSeparator();
    }
    else
    {
        if( item && item->GetFlags() )
        {
            AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND,
                         _( "Cancel" ), KiBitmap( cancel_xpm ) );
            aPopMenu->AppendSeparator();
        }
    }

    // Select a proper item

    wxPoint cursorPos = GetCrossHairPosition();
    wxPoint selectPos = m_Collector->GetRefPos();

    selectPos = GetNearestGridPosition( selectPos );

    /*  We can reselect another item only if there are no item being edited
     * because ALL moving functions use GetCurItem(), therefore GetCurItem()
     * must return the same item during moving. We know an item is moving
     * if( item && (item->m_Flags != 0)) is true and after calling
     * PcbGeneralLocateAndDisplay(), GetCurItem() is any arbitrary BOARD_ITEM,
     * not the current item being edited. In such case we cannot call
     * PcbGeneralLocateAndDisplay().
     */
    if( !item || (item->GetFlags() == 0) )
    {
        // show the "item selector" menu if no item selected or
        // if there is a selected item but the mouse has moved
        // (therefore a new item is perhaps under the cursor)
        if( !item || cursorPos != selectPos )
        {
            m_canvas->SetAbortRequest( false );
            PcbGeneralLocateAndDisplay();

            if( m_canvas->GetAbortRequest() )
            {
                return false;
            }
        }
    }

    item = GetCurItem();
    flags = item ? item->GetFlags() : 0;

    // Add the context menu, which depends on the picked item:
    if( item )
    {
        switch( item->Type() )
        {
        case PCB_MODULE_T:
            createPopUpMenuForFootprints( (MODULE*) item, aPopMenu );

            if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_MODULE ) )
            {
                aPopMenu->AppendSeparator();

                if( !( (MODULE*) item )->IsLocked() )
                {
                    msg = AddHotkeyName( _("Lock Footprint" ), g_Board_Editor_Hokeys_Descr,
                                         HK_LOCK_UNLOCK_FOOTPRINT );
                    AddMenuItem( aPopMenu, ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE, msg,
                                 KiBitmap( locked_xpm ) );
                }
                else
                {
                    msg = AddHotkeyName( _( "Unlock Footprint" ), g_Board_Editor_Hokeys_Descr,
                                         HK_LOCK_UNLOCK_FOOTPRINT );
                    AddMenuItem( aPopMenu, ID_POPUP_PCB_AUTOPLACE_FREE_MODULE, msg,
                                 KiBitmap( unlocked_xpm ) );
                }

                if( !flags )
                    aPopMenu->Append( ID_POPUP_PCB_AUTOPLACE_CURRENT_MODULE,
                                      _( "Automatically Place Footprint" ) );
            }

            if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_TRACKS ) )
            {
                if( !flags )
                    aPopMenu->Append( ID_POPUP_PCB_AUTOROUTE_MODULE,
                                      _( "Automatically Route Footprint" ) );
            }
            break;

        case PCB_PAD_T:
            createPopUpMenuForFpPads( static_cast<D_PAD*>( item ), aPopMenu );
            break;

        case PCB_MODULE_TEXT_T:
            createPopUpMenuForFpTexts( static_cast<TEXTE_MODULE*>( item ), aPopMenu );
            break;

        case PCB_LINE_T:  // Some graphic items on technical layers
            if( (flags & IS_NEW) )
            {
                AddMenuItem( aPopMenu, ID_POPUP_PCB_STOP_CURRENT_DRAWING,
                             _( "End Drawing" ), KiBitmap( checked_ok_xpm ) );
            }

            if( !flags )
            {
                msg = AddHotkeyName( _( "Move Drawing" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_DRAWING_REQUEST,
                             msg, KiBitmap( move_xpm ) );

                msg = AddHotkeyName( _( "Duplicate Drawing" ), g_Board_Editor_Hokeys_Descr,
                                     HK_DUPLICATE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DUPLICATE_ITEM,
                             msg, KiBitmap( duplicate_line_xpm ) );

                msg = AddHotkeyName( _("Move Drawing Exactly" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM_EXACT );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_EXACT,
                             msg, KiBitmap( move_line_xpm ) );

                msg = AddHotkeyName( _("Create Drawing Array" ), g_Board_Editor_Hokeys_Descr,
                                     HK_CREATE_ARRAY );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_CREATE_ARRAY,
                             msg, KiBitmap( array_line_xpm ) );

                msg = AddHotkeyName( _( "Edit Drawing" ), g_Board_Editor_Hokeys_Descr,
                                     HK_EDIT_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_DRAWING,
                             msg, KiBitmap( edit_xpm ) );

                AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DRAWING,
                             _( "Delete Drawing" ), KiBitmap( delete_xpm ) );

                if( !IsCopperLayer( item->GetLayer() ) )
                    AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DRAWING_LAYER,
                                 _( "Delete All Drawings on Layer" ), KiBitmap( delete_xpm ) );
            }

            break;

        case PCB_ZONE_T:      // Item used to fill a zone
            AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_ZONE,
                         _( "Delete Zone Filling" ), KiBitmap( delete_xpm ) );
            break;

        case PCB_ZONE_AREA_T:    // Item used to handle a zone area (outlines, holes ...)
            if( flags & IS_NEW )
            {
                AddMenuItem( aPopMenu, ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE,
                             _( "Close Zone Outline" ), KiBitmap( checked_ok_xpm ) );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_ZONE_LAST_CREATED_CORNER,
                             _( "Delete Last Corner" ), KiBitmap( delete_xpm ) );
            }
            else
            {
                createPopUpMenuForZones( (ZONE_CONTAINER*) item, aPopMenu );
            }

            break;

        case PCB_TEXT_T:
            createPopUpMenuForTexts( (TEXTE_PCB*) item, aPopMenu );
            break;

        case PCB_TRACE_T:
        case PCB_VIA_T:
            trackFound = true;
            createPopupMenuForTracks( (TRACK*) item, aPopMenu );
            break;

        case PCB_MARKER_T:
            createPopUpMenuForMarkers( (MARKER_PCB*) item, aPopMenu );
            break;

        case PCB_DIMENSION_T:
            if( !flags )
            {
                msg = AddHotkeyName( _( "Edit Dimension" ), g_Board_Editor_Hokeys_Descr,
                                     HK_EDIT_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_DIMENSION, msg, KiBitmap( edit_xpm ) );

                msg = AddHotkeyName( _( "Move Dimension Text" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_TEXT_DIMENSION_REQUEST,
                             msg, KiBitmap( move_text_xpm ) );

                msg = AddHotkeyName( _( "Duplicate Dimension" ), g_Board_Editor_Hokeys_Descr,
                                     HK_DUPLICATE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DUPLICATE_ITEM,
                             msg, KiBitmap( duplicate_text_xpm ) );

                msg = AddHotkeyName( _("Move Dimension Exactly" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM_EXACT );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_EXACT,
                             msg, KiBitmap( move_text_xpm ) );

                msg = AddHotkeyName( _( "Delete Dimension" ), g_Board_Editor_Hokeys_Descr,
                                     HK_DELETE );

                AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DIMENSION,
                             msg, KiBitmap( delete_xpm ) );
            }
            break;

        case PCB_TARGET_T:
            if( !flags )
            {
                msg = AddHotkeyName( _( "Move Target" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_MIRE_REQUEST,
                             msg, KiBitmap( move_target_xpm ) );

                msg = AddHotkeyName( _("Move Target Exactly" ), g_Board_Editor_Hokeys_Descr,
                                     HK_MOVE_ITEM_EXACT );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_EXACT,
                             msg, KiBitmap( move_target_xpm ) );

                msg = AddHotkeyName( _( "Duplicate Target" ), g_Board_Editor_Hokeys_Descr,
                                     HK_DUPLICATE_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DUPLICATE_ITEM,
                             msg, KiBitmap( duplicate_target_xpm ) );

                msg = AddHotkeyName( _("Create Target Array" ), g_Board_Editor_Hokeys_Descr,
                                     HK_CREATE_ARRAY );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_CREATE_ARRAY,
                             msg, KiBitmap( array_target_xpm ) );

                msg = AddHotkeyName( _( "Edit Target" ), g_Board_Editor_Hokeys_Descr,
                                     HK_EDIT_ITEM );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_MIRE, msg, KiBitmap( edit_xpm ) );

                msg = AddHotkeyName( _( "Delete Target" ), g_Board_Editor_Hokeys_Descr, HK_DELETE );
                AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_MIRE,
                             msg, KiBitmap( delete_xpm ) );
            }

            break;

        case PCB_MODULE_EDGE_T:
        case SCREEN_T:
        case TYPE_NOT_INIT:
        case PCB_T:
            msg.Printf( wxT( "PCB_EDIT_FRAME::OnRightClick() Error: unexpected DrawType %d" ),
                        item->Type() );
            wxMessageBox( msg );
            SetCurItem( NULL );
            break;

        default:
            msg.Printf( wxT( "PCB_EDIT_FRAME::OnRightClick() Error: unknown DrawType %d" ),
                        item->Type() );
            wxMessageBox( msg );

            // Attempt to clear error (but should no occurs )
            if( item->Type() >= MAX_STRUCT_TYPE_ID )
                SetCurItem( NULL );

            break;
        }

       aPopMenu->AppendSeparator();
    }

    if( !flags )
    {
        msg = AddHotkeyName( _( "Get and Move Footprint" ),
                             g_Board_Editor_Hokeys_Descr, HK_GET_AND_MOVE_FOOTPRINT );
        AddMenuItem( aPopMenu, ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST,
                     msg, KiBitmap( move_module_xpm ) );
    }

    // Display context sensitive commands:
    switch(  GetToolId() )
    {
    case ID_PCB_ZONES_BUTT:
        if(  GetBoard()->m_ZoneDescriptorList.size() > 0 )
        {
            aPopMenu->AppendSeparator();
            msg = AddHotkeyName( _( "Fill or Refill All Zones" ),
                                 g_Board_Editor_Hokeys_Descr, HK_ZONE_FILL_OR_REFILL );
            AddMenuItem( aPopMenu, ID_POPUP_PCB_FILL_ALL_ZONES,
                         msg, KiBitmap( fill_zone_xpm ) );
            msg = AddHotkeyName( _( "Remove Filled Areas in All Zones" ),
                                 g_Board_Editor_Hokeys_Descr, HK_ZONE_REMOVE_FILLED );
            AddMenuItem( aPopMenu, ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES,
                         msg, KiBitmap( zone_unfill_xpm ) );
            aPopMenu->AppendSeparator();
        }

        AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_LAYER,
                     _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
        aPopMenu->AppendSeparator();
        break;

    case ID_PCB_KEEPOUT_AREA_BUTT:
        AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_LAYER,
                     _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
        aPopMenu->AppendSeparator();
        break;

    case ID_TRACK_BUTT:
        if ( ! trackFound )   // This menu is already added when a track is located
        {
            aPopMenu->AppendSeparator();
            msg = AddHotkeyName( _( "Begin Track" ),
                                 g_Board_Editor_Hokeys_Descr, HK_ADD_NEW_TRACK );
            AddMenuItem( aPopMenu, ID_POPUP_PCB_BEGIN_TRACK,
                         msg, KiBitmap( add_tracks_xpm ) );

            AddMenuItem( aPopMenu, Append_Track_Width_List( GetBoard() ),
                         ID_POPUP_PCB_SELECT_WIDTH, _( "Select Track Width" ),
                         KiBitmap( width_track_xpm ) );

            AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_CU_LAYER,
                         _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
            AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_LAYER_PAIR,
                         _( "Select Layer Pair for Vias" ), KiBitmap( select_layer_pair_xpm ) );
            aPopMenu->AppendSeparator();
        }
        break;

    case ID_PCB_CIRCLE_BUTT:
    case ID_PCB_ARC_BUTT:
    case ID_PCB_ADD_TEXT_BUTT:
    case ID_PCB_ADD_LINE_BUTT:
    case ID_PCB_DIMENSION_BUTT:
        AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_NO_CU_LAYER,
                      _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
        aPopMenu->AppendSeparator();
        break;

    case ID_PCB_MODULE_BUTT:
        if( !flags )
        {
            AddMenuItem( aPopMenu, ID_POPUP_PCB_DISPLAY_FOOTPRINT_DOC,
                         _( "Footprint Documentation" ), KiBitmap( book_xpm ) );
            aPopMenu->AppendSeparator();
        }
        break;

    case ID_NO_TOOL_SELECTED:
        if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_MODULE ) )
        {
            wxMenu* commands = new wxMenu;
            AddMenuItem( aPopMenu, commands, ID_POPUP_PCB_AUTOPLACE_COMMANDS,
                         _( "Global Spread and Place" ), KiBitmap( move_xpm ) );
            AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES,
                         _( "Unlock All Footprints" ), KiBitmap( unlocked_xpm ) );
            AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES,
                         _( "Lock All Footprints" ), KiBitmap( locked_xpm ) );
            commands->AppendSeparator();
            AddMenuItem( commands, ID_POPUP_PCB_SPREAD_ALL_MODULES,
                         _( "Spread out All Footprints" ), KiBitmap( move_xpm ) );
            commands->Append( ID_POPUP_PCB_SPREAD_NEW_MODULES,
                              _( "Spread out Footprints not Already on Board" ) );
            commands->AppendSeparator();
            commands->Append( ID_POPUP_PCB_AUTOPLACE_ALL_MODULES,
                              _( "Automatically Place All Footprints" ) );
            commands->Append( ID_POPUP_PCB_AUTOPLACE_NEW_MODULES,
                              _( "Automatically Place New Footprints" ) );
            commands->Append( ID_POPUP_PCB_AUTOPLACE_NEXT_MODULE,
                              _( "Automatically Place Next Footprints" ) );
            commands->AppendSeparator();
            AddMenuItem( commands, ID_POPUP_PCB_REORIENT_ALL_MODULES,
                         _( "Orient All Footprints" ), KiBitmap( rotate_module_cw_xpm ) );
            aPopMenu->AppendSeparator();
        }

        if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_TRACKS ) )
        {
            wxMenu* commands = new wxMenu;
            aPopMenu->Append( ID_POPUP_PCB_AUTOROUTE_COMMANDS, _( "Autoroute" ), commands );
            AddMenuItem( commands, ID_POPUP_PCB_SELECT_LAYER_PAIR,
                         _( "Select Layer Pair" ), KiBitmap( select_layer_pair_xpm ) );
            commands->AppendSeparator();
            commands->Append( ID_POPUP_PCB_AUTOROUTE_ALL_MODULES,
                              _( "Automatically Route All Footprints" ) );
            commands->AppendSeparator();
            commands->Append( ID_POPUP_PCB_AUTOROUTE_RESET_UNROUTED, _( "Reset Unrouted" ) );
            aPopMenu->AppendSeparator();
        }

        if( !trackFound )
        {
            msg = AddHotkeyName( _( "Begin Track" ), g_Board_Editor_Hokeys_Descr, HK_ADD_NEW_TRACK );
            AddMenuItem( aPopMenu, ID_POPUP_PCB_BEGIN_TRACK, msg, KiBitmap( add_tracks_xpm ) );

            AddMenuItem( aPopMenu, Append_Track_Width_List( GetBoard() ),
                         ID_POPUP_PCB_SELECT_WIDTH, _( "Select Track Width" ),
                         KiBitmap( width_track_xpm ) );

            AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_LAYER,
                         _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
            aPopMenu->AppendSeparator();
        }
        break;
    }

    return true;
}