void PCB_EDIT_FRAME::RunActionPlugin( ACTION_PLUGIN* aActionPlugin )
{
    PICKED_ITEMS_LIST itemsList;
    BOARD*  currentPcb  = GetBoard();
    bool    fromEmpty   = false;

    itemsList.m_Status = UR_CHANGED;

    OnModify();

    // Append tracks:
    for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
    {
        ITEM_PICKER picker( item, UR_CHANGED );
        itemsList.PushItem( picker );
    }

    // Append modules:
    for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
    {
        ITEM_PICKER picker( item, UR_CHANGED );
        itemsList.PushItem( picker );
    }

    // Append drawings
    for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )
    {
        ITEM_PICKER picker( item, UR_CHANGED );
        itemsList.PushItem( picker );
    }

    // Append zones outlines
    for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
    {
        ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(
                        ii ), UR_CHANGED );
        itemsList.PushItem( picker );
    }

    // Append zones segm:
    for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() )
    {
        ITEM_PICKER picker( item, UR_CHANGED );
        itemsList.PushItem( picker );
    }

    if( itemsList.GetCount() > 0 )
        SaveCopyInUndoList( itemsList, UR_CHANGED, wxPoint( 0.0, 0.0 ) );
    else
        fromEmpty = true;

    itemsList.ClearItemsList();

    // Execute plugin itself...
    ACTION_PLUGINS::SetActionRunning( true );
    aActionPlugin->Run();
    ACTION_PLUGINS::SetActionRunning( false );

    currentPcb->m_Status_Pcb = 0;

    // Get back the undo buffer to fix some modifications
    PICKED_ITEMS_LIST* oldBuffer = NULL;

    if( fromEmpty )
    {
        oldBuffer = new PICKED_ITEMS_LIST();
        oldBuffer->m_Status = UR_NEW;
    }
    else
    {
        oldBuffer = GetScreen()->PopCommandFromUndoList();
        wxASSERT( oldBuffer );
    }

    // Try do discover what was modified

    PICKED_ITEMS_LIST deletedItemsList;

    // Found deleted modules
    for( unsigned int i = 0; i < oldBuffer->GetCount(); i++ )
    {
        BOARD_ITEM* item = (BOARD_ITEM*) oldBuffer->GetPickedItem( i );
        ITEM_PICKER picker( item, UR_DELETED );

        wxASSERT( item );

        switch( item->Type() )
        {
        case PCB_NETINFO_T:
        case PCB_MARKER_T:
        case PCB_MODULE_T:
        case PCB_TRACE_T:
        case PCB_VIA_T:
        case PCB_LINE_T:
        case PCB_TEXT_T:
        case PCB_DIMENSION_T:
        case PCB_TARGET_T:
        case PCB_SEGZONE_T:

            // If item has a list it's mean that the element is on the board
            if( item->GetList() == NULL )
            {
                deletedItemsList.PushItem( picker );
            }

            break;

        case PCB_ZONE_AREA_T:
        {
            bool zoneFound = false;

            for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
                zoneFound |= currentPcb->GetArea( ii ) == item;

            if( !zoneFound )
            {
                deletedItemsList.PushItem( picker );
            }

            break;
        }

        default:
            wxString msg;
            msg.Printf( _( "(PCB_EDIT_FRAME::OnActionPlugin) needs work: "
                                "BOARD_ITEM type (%d) not handled" ),
                    item->Type() );
            wxFAIL_MSG( msg );
            break;
        }
    }

    // Mark deleted elements in undolist
    for( unsigned int i = 0; i < deletedItemsList.GetCount(); i++ )
    {
        oldBuffer->PushItem( deletedItemsList.GetItemWrapper( i ) );
    }

    // Find new modules
    for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
    {
        if( !oldBuffer->ContainsItem( item ) )
        {
            ITEM_PICKER picker( item, UR_NEW );
            oldBuffer->PushItem( picker );
        }
    }

    for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
    {
        if( !oldBuffer->ContainsItem( item ) )
        {
            ITEM_PICKER picker( item, UR_NEW );
            oldBuffer->PushItem( picker );
        }
    }

    for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )
    {
        if( !oldBuffer->ContainsItem( item ) )
        {
            ITEM_PICKER picker( item, UR_NEW );
            oldBuffer->PushItem( picker );
        }
    }

    for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() )
    {
        if( !oldBuffer->ContainsItem( item ) )
        {
            ITEM_PICKER picker( item, UR_NEW );
            oldBuffer->PushItem( picker );
        }
    }

    for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
    {
        if( !oldBuffer->ContainsItem( (EDA_ITEM*) currentPcb->GetArea( ii ) ) )
        {
            ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(
                            ii ), UR_NEW );
            oldBuffer->PushItem( picker );
        }
    }


    GetScreen()->PushCommandToUndoList( oldBuffer );

    if( IsGalCanvasActive() )
    {
        UseGalCanvas( GetGalCanvas() );
    }
    else
    {
        UpdateUserInterface();
        GetScreen()->SetModify();
        Refresh();
    }
}