示例#1
0
void PNS_KICAD_IFACE::AddItem( PNS::ITEM* aItem )
{
    BOARD_CONNECTED_ITEM* newBI = NULL;

    switch( aItem->Kind() )
    {
    case PNS::ITEM::SEGMENT_T:
    {
        PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
        TRACK* track = new TRACK( m_board );
        const SEG& s = seg->Seg();
        track->SetStart( wxPoint( s.A.x, s.A.y ) );
        track->SetEnd( wxPoint( s.B.x, s.B.y ) );
        track->SetWidth( seg->Width() );
        track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
        track->SetNetCode( seg->Net() > 0 ? seg->Net() : 0 );
        newBI = track;
        break;
    }

    case PNS::ITEM::VIA_T:
    {
        VIA* via_board = new VIA( m_board );
        PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
        via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) );
        via_board->SetWidth( via->Diameter() );
        via_board->SetDrill( via->Drill() );
        via_board->SetNetCode( via->Net() > 0 ? via->Net() : 0 );
        via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
        via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
                                 ToLAYER_ID( via->Layers().End() ) );
        newBI = via_board;
        break;
    }

    default:
        break;
    }

    if( newBI )
    {
        aItem->SetParent( newBI );
        newBI->ClearFlags();

        m_commit->Add( newBI );
    }
}
TRACK* SPECCTRA_DB::makeTRACK( PATH* aPath, int aPointIndex, int aNetcode ) throw( IO_ERROR )
{
    int layerNdx = findLayerName( aPath->layer_id );

    if( layerNdx == -1 )
    {
        wxString layerName = FROM_UTF8( aPath->layer_id.c_str() );
        THROW_IO_ERROR( wxString::Format( _("Session file uses invalid layer id \"%s\""),
                                          GetChars( layerName ) ) );
    }

    TRACK* track = new TRACK( sessionBoard );

    track->SetStart( mapPt( aPath->points[aPointIndex+0], routeResolution ) );
    track->SetEnd( mapPt( aPath->points[aPointIndex+1], routeResolution ) );
    track->SetLayer( pcbLayer2kicad[layerNdx] );
    track->SetWidth( scale( aPath->aperture_width, routeResolution ) );
    track->SetNetCode( aNetcode );

    return track;
}
void BOARD_ITEM::SwapData( BOARD_ITEM* aImage )
{
    if( aImage == NULL )
    {
        return;
    }

    EDA_ITEM * pnext = Next();
    EDA_ITEM * pback = Back();

    switch( Type() )
    {
    case PCB_MODULE_T:
    {
        MODULE* tmp = (MODULE*) aImage->Clone();
        ( (MODULE*) aImage )->Copy( (MODULE*) this );
        ( (MODULE*) this )->Copy( tmp );
        delete tmp;
    }
        break;

    case PCB_ZONE_AREA_T:
    {
        ZONE_CONTAINER* tmp = (ZONE_CONTAINER*) aImage->Clone();
        ( (ZONE_CONTAINER*) aImage )->Copy( (ZONE_CONTAINER*) this );
        ( (ZONE_CONTAINER*) this )->Copy( tmp );
        delete tmp;
    }
        break;

    case PCB_LINE_T:
        std::swap( *((DRAWSEGMENT*)this), *((DRAWSEGMENT*)aImage) );
        break;

    case PCB_TRACE_T:
    case PCB_VIA_T:
    {
        TRACK* track = (TRACK*) this;
        TRACK* image = (TRACK*) aImage;

        EXCHG(track->m_Layer, image->m_Layer );

        // swap start, end, width and shape for track and image.
        wxPoint exchp = track->GetStart();
        track->SetStart( image->GetStart() );
        image->SetStart( exchp );
        exchp = track->GetEnd();
        track->SetEnd( image->GetEnd() );
        image->SetEnd( exchp );

        int atmp = track->GetWidth();
        track->SetWidth( image->GetWidth() );
        image->SetWidth( atmp );

        if( Type() == PCB_VIA_T )
        {
            VIA *via = static_cast<VIA*>( this );
            VIA *viaimage = static_cast<VIA*>( aImage );

            VIATYPE_T viatmp = via->GetViaType();
            via->SetViaType( viaimage->GetViaType() );
            viaimage->SetViaType( viatmp );

            int drilltmp = via->GetDrillValue();

            if( via->IsDrillDefault() )
                drilltmp = -1;

            int itmp = viaimage->GetDrillValue();

            if( viaimage->IsDrillDefault() )
                itmp = -1;

            EXCHG(itmp, drilltmp );

            if( drilltmp > 0 )
                via->SetDrill( drilltmp );
            else
                via->SetDrillDefault();

            if( itmp > 0 )
                viaimage->SetDrill( itmp );
            else
                viaimage->SetDrillDefault();
        }
    }
        break;

    case PCB_TEXT_T:
        std::swap( *((TEXTE_PCB*)this), *((TEXTE_PCB*)aImage) );
        break;

    case PCB_TARGET_T:
        std::swap( *((PCB_TARGET*)this), *((PCB_TARGET*)aImage) );
        break;

    case PCB_DIMENSION_T:
        std::swap( *((DIMENSION*)this), *((DIMENSION*)aImage) );
        break;

    case PCB_ZONE_T:
    default:
        wxLogMessage( wxT( "SwapData() error: unexpected type %d" ), Type() );
        break;
    }

    if( pnext != Next() || pback != Back() )
    {
        Pnext = pnext;
        Pback = pback;
#ifdef DEBUG
        wxLogMessage( wxT( "SwapData Error: %s Pnext or Pback pointers modified" ),
                      GetClass().GetData() );
#endif
    }
}
示例#4
0
bool DIALOG_TRACK_VIA_PROPERTIES::Apply( COMMIT& aCommit )
{
    if( !check() )
        return false;

    bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
    bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;

    for( auto item : m_items )
    {
        aCommit.Modify( item );

        switch( item->Type() )
        {
            case PCB_TRACE_T:
            {
                assert( m_tracks );
                TRACK* t = static_cast<TRACK*>( item );

                if( m_trackStartX.Valid() || m_trackStartY.Valid() )
                {
                    wxPoint start = t->GetStart();

                    if( m_trackStartX.Valid() )
                        start.x = m_trackStartX.GetValue();

                    if( m_trackStartY.Valid() )
                        start.y = m_trackStartY.GetValue();

                    t->SetStart( start );
                }

                if( m_trackEndX.Valid() || m_trackEndY.Valid() )
                {
                    wxPoint end = t->GetEnd();

                    if( m_trackEndX.Valid() )
                        end.x = m_trackEndX.GetValue();

                    if( m_trackEndY.Valid() )
                        end.y = m_trackEndY.GetValue();

                    t->SetEnd( end );
                }

                if( m_trackNetclass->IsChecked() )
                {
                    t->SetWidth( t->GetNetClass()->GetTrackWidth() );
                }
                else if( m_trackWidth.Valid() )
                {
                    t->SetWidth( m_trackWidth.GetValue() );
                }

                LAYER_NUM layer = m_TrackLayerCtrl->GetLayerSelection();

                if( layer != UNDEFINED_LAYER )
                    t->SetLayer( (LAYER_ID) layer );

                if( changeLock )
                    t->SetLocked( setLock );

                break;
            }

            case PCB_VIA_T:
            {
                assert( m_vias );

                VIA* v = static_cast<VIA*>( item );

                if( m_viaX.Valid() || m_viaY.Valid() )
                {
                    wxPoint pos = v->GetPosition();

                    if( m_viaX.Valid() )
                        pos.x = m_viaX.GetValue();

                    if( m_viaY.Valid() )
                        pos.y = m_viaY.GetValue();

                    v->SetPosition( pos );
                }

                if( m_viaNetclass->IsChecked() )
                {
                    switch( v->GetViaType() )
                    {
                    default:
                        wxFAIL_MSG("Unhandled via type");
                        // fall through

                    case VIA_THROUGH:
                    case VIA_BLIND_BURIED:
                        v->SetWidth( v->GetNetClass()->GetViaDiameter() );
                        v->SetDrill( v->GetNetClass()->GetViaDrill() );
                        break;

                    case VIA_MICROVIA:
                        v->SetWidth( v->GetNetClass()->GetuViaDiameter() );
                        v->SetDrill( v->GetNetClass()->GetuViaDrill() );
                        break;
                    }
                }
                else
                {
                    if( m_viaDiameter.Valid() )
                        v->SetWidth( m_viaDiameter.GetValue() );

                    if( m_viaDrill.Valid() )
                        v->SetDrill( m_viaDrill.GetValue() );
                }

                if( changeLock )
                    v->SetLocked( setLock );

                break;
            }

            default:
                assert( false );
                break;
        }
    }

    return true;
}
void BOARD_ITEM::SwapData( BOARD_ITEM* aImage )
{
    if( aImage == NULL )
        return;

    // Remark: to create images of edited items to undo, we are using Clone method
    // which can duplication of items foe copy, but does not clone all members
    // mainly pointers in chain and time stamp, which is set to new, unique value.
    // So we have to use the current values of these parameters.

    EDA_ITEM * pnext = Next();
    EDA_ITEM * pback = Back();
    DHEAD* mylist    = m_List;
    time_t timestamp = GetTimeStamp();

    switch( Type() )
    {
    case PCB_MODULE_T:
    {
        MODULE* tmp = (MODULE*) aImage->Clone();
        ( (MODULE*) aImage )->Copy( (MODULE*) this );
        ( (MODULE*) this )->Copy( tmp );
        delete tmp;
    }
        break;

    case PCB_ZONE_AREA_T:
    {
        ZONE_CONTAINER* tmp = (ZONE_CONTAINER*) aImage->Clone();
        ( (ZONE_CONTAINER*) aImage )->Copy( (ZONE_CONTAINER*) this );
        ( (ZONE_CONTAINER*) this )->Copy( tmp );
        delete tmp;
    }
        break;

    case PCB_LINE_T:
        std::swap( *((DRAWSEGMENT*)this), *((DRAWSEGMENT*)aImage) );
        break;

    case PCB_TRACE_T:
    case PCB_VIA_T:
    {
        TRACK* track = (TRACK*) this;
        TRACK* image = (TRACK*) aImage;

        std::swap(track->m_Layer, image->m_Layer );

        // swap start, end, width and shape for track and image.
        wxPoint exchp = track->GetStart();
        track->SetStart( image->GetStart() );
        image->SetStart( exchp );
        exchp = track->GetEnd();
        track->SetEnd( image->GetEnd() );
        image->SetEnd( exchp );

        int atmp = track->GetWidth();
        track->SetWidth( image->GetWidth() );
        image->SetWidth( atmp );

        if( Type() == PCB_VIA_T )
        {
            VIA *via = static_cast<VIA*>( this );
            VIA *viaimage = static_cast<VIA*>( aImage );

            VIATYPE_T viatmp = via->GetViaType();
            via->SetViaType( viaimage->GetViaType() );
            viaimage->SetViaType( viatmp );

            int drilltmp = via->GetDrillValue();

            if( via->IsDrillDefault() )
                drilltmp = -1;

            int itmp = viaimage->GetDrillValue();

            if( viaimage->IsDrillDefault() )
                itmp = -1;

            std::swap(itmp, drilltmp );

            if( drilltmp > 0 )
                via->SetDrill( drilltmp );
            else
                via->SetDrillDefault();

            if( itmp > 0 )
                viaimage->SetDrill( itmp );
            else
                viaimage->SetDrillDefault();
        }
    }
        break;

    case PCB_TEXT_T:
        std::swap( *((TEXTE_PCB*)this), *((TEXTE_PCB*)aImage) );
        break;

    case PCB_TARGET_T:
        std::swap( *((PCB_TARGET*)this), *((PCB_TARGET*)aImage) );
        break;

    case PCB_DIMENSION_T:
        std::swap( *((DIMENSION*)this), *((DIMENSION*)aImage) );
        break;

    case PCB_ZONE_T:
    default:
        wxLogMessage( wxT( "SwapData() error: unexpected type %d" ), Type() );
        break;
    }

    // Restore pointers and time stamp, to be sure they are not broken
    Pnext = pnext;
    Pback = pback;
    m_List = mylist;
    SetTimeStamp( timestamp );
}
void PNS_ROUTER::CommitRouting( PNS_NODE* aNode )
{
    PNS_NODE::ITEM_VECTOR removed, added;

    aNode->GetUpdatedItems( removed, added );

    for( unsigned int i = 0; i < removed.size(); i++ )
    {
        BOARD_CONNECTED_ITEM* parent = removed[i]->Parent();

        if( parent )
        {
            m_view->Remove( parent );
            m_board->Remove( parent );
            m_undoBuffer.PushItem( ITEM_PICKER( parent, UR_DELETED ) );
        }
    }

    for( PNS_ITEM* item : added )
    {
        BOARD_CONNECTED_ITEM* newBI = NULL;

        switch( item->Kind() )
        {
        case PNS_ITEM::SEGMENT:
        {
            PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>( item );
            TRACK* track = new TRACK( m_board );
            const SEG& s = seg->Seg();

            track->SetStart( wxPoint( s.A.x, s.A.y ) );
            track->SetEnd( wxPoint( s.B.x, s.B.y ) );
            track->SetWidth( seg->Width() );
            track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
            track->SetNetCode( seg->Net() > 0 ? seg->Net() : 0 );
            newBI = track;
            break;
        }

        case PNS_ITEM::VIA:
        {
            VIA* via_board = new VIA( m_board );
            PNS_VIA* via = static_cast<PNS_VIA*>( item );
            via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) );
            via_board->SetWidth( via->Diameter() );
            via_board->SetDrill( via->Drill() );
            via_board->SetNetCode( via->Net() > 0 ? via->Net() : 0 );
            via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
            via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
                                     ToLAYER_ID( via->Layers().End() ) );
            newBI = via_board;
            break;
        }

        default:
            break;
        }

        if( newBI )
        {
            item->SetParent( newBI );
            newBI->ClearFlags();
            m_view->Add( newBI );
            m_board->Add( newBI );
            m_undoBuffer.PushItem( ITEM_PICKER( newBI, UR_NEW ) );
            newBI->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
        }
    }

    m_board->GetRatsnest()->Recalculate();
    m_world->Commit( aNode );
}
bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
{
    auto connectivity = m_frame->GetBoard()->GetConnectivity();
    int newNetCode = m_netSelector->GetSelectedNetcode();
    std::vector<D_PAD*> changingPads;

    if ( !m_netSelector->IsIndeterminate() )
    {
        std::set<D_PAD*> connectedPads;

        for( auto& item : m_items )
        {
            const KICAD_T ourTypes[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_MODULE_T, EOT };
            auto connectedItems = connectivity->GetConnectedItems( static_cast<BOARD_CONNECTED_ITEM*>( item ), ourTypes, true );
            for ( auto citem : connectedItems )
            {
                if( citem->Type() == PCB_PAD_T )
                {
                    connectedPads.insert( static_cast<D_PAD*>( citem ) );
                }
            }
        }

        for( D_PAD* pad : connectedPads )
        {
            if( pad->GetNetCode() != newNetCode )
                changingPads.push_back( pad );
        }
    }

    // Run validations:

    if( changingPads.size() )
    {
        if( !confirmPadChange( changingPads ) )
            return false;
    }

    if( m_vias )
    {
        if( !m_viaDiameter.Validate( GEOMETRY_MIN_SIZE, INT_MAX )
            || !m_viaDrill.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
            return false;

        if( m_ViaDiameterCtrl->IsEnabled() && !m_viaDiameter.IsIndeterminate()
            && m_ViaDrillCtrl->IsEnabled() && !m_viaDrill.IsIndeterminate()
            && m_viaDiameter.GetValue() <= m_viaDrill.GetValue() )
        {
            DisplayError( GetParent(), _( "Via drill size must be smaller than via diameter" ) );
            m_ViaDrillCtrl->SelectAll();
            m_ViaDrillCtrl->SetFocus();
            return false;
        }

        if( m_ViaStartLayer->GetLayerSelection() != UNDEFINED_LAYER &&
            m_ViaStartLayer->GetLayerSelection() == m_ViaEndLayer->GetLayerSelection() )
        {
            DisplayError( GetParent(), _( "Via start layer and end layer cannot be the same" ) );
            return false;
        }
    }

    if( m_tracks )
    {
        if( !m_trackWidth.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
            return false;
    }

    // If we survived that, then save the changes:

    bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
    bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;

    for( auto item : m_items )
    {
        m_commit.Modify( item );

        switch( item->Type() )
        {
            case PCB_TRACE_T:
            {
                wxASSERT( m_tracks );
                TRACK* t = static_cast<TRACK*>( item );

                if( !m_trackStartX.IsIndeterminate() )
                    t->SetStart( wxPoint( m_trackStartX.GetValue(), t->GetStart().y ) );

                if( !m_trackStartY.IsIndeterminate() )
                    t->SetStart( wxPoint( t->GetStart().x, m_trackStartY.GetValue() ) );

                if( !m_trackEndX.IsIndeterminate() )
                    t->SetEnd( wxPoint( m_trackEndX.GetValue(), t->GetEnd().y ) );

                if( !m_trackEndY.IsIndeterminate() )
                    t->SetEnd( wxPoint( t->GetEnd().x, m_trackEndY.GetValue() ) );

                if( m_trackNetclass->IsChecked() )
                    t->SetWidth( t->GetNetClass()->GetTrackWidth() );
                else if( !m_trackWidth.IsIndeterminate() )
                    t->SetWidth( m_trackWidth.GetValue() );

                LAYER_NUM layer = m_TrackLayerCtrl->GetLayerSelection();

                if( layer != UNDEFINED_LAYER )
                    t->SetLayer( (PCB_LAYER_ID) layer );

                if( changeLock )
                    t->SetLocked( setLock );

                if ( !m_netSelector->IsIndeterminate() )
                    t->SetNetCode( m_netSelector->GetSelectedNetcode() );

                break;
            }

            case PCB_VIA_T:
            {
                wxASSERT( m_vias );
                VIA* v = static_cast<VIA*>( item );

                if( !m_viaX.IsIndeterminate() )
                    v->SetPosition( wxPoint( m_viaX.GetValue(), v->GetPosition().y ) );

                if( !m_viaY.IsIndeterminate() )
                    v->SetPosition( wxPoint( v->GetPosition().x, m_viaY.GetValue() ) );

                if( m_ViaTypeChoice->GetSelection() != 3)
                {
                    switch( m_ViaTypeChoice->GetSelection() )
                    {
                    default:
                    case 0: v->SetViaType( VIA_THROUGH ); v->SanitizeLayers(); break;
                    case 1: v->SetViaType( VIA_MICROVIA );                     break;
                    case 2: v->SetViaType( VIA_BLIND_BURIED );                 break;
                    }
                }

                auto startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
                auto endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );

                if (startLayer != UNDEFINED_LAYER )
                    v->SetTopLayer( startLayer );

                if (endLayer != UNDEFINED_LAYER )
                    v->SetBottomLayer( endLayer );

                v->SanitizeLayers();

                if( m_viaNetclass->IsChecked() )
                {
                    switch( v->GetViaType() )
                    {
                    default:
                        wxFAIL_MSG("Unhandled via type");
                        // fall through

                    case VIA_THROUGH:
                    case VIA_BLIND_BURIED:
                        v->SetWidth( v->GetNetClass()->GetViaDiameter() );
                        v->SetDrill( v->GetNetClass()->GetViaDrill() );
                        break;

                    case VIA_MICROVIA:
                        v->SetWidth( v->GetNetClass()->GetuViaDiameter() );
                        v->SetDrill( v->GetNetClass()->GetuViaDrill() );
                        break;
                    }
                }
                else
                {
                    if( !m_viaDiameter.IsIndeterminate() )
                        v->SetWidth( m_viaDiameter.GetValue() );

                    if( !m_viaDrill.IsIndeterminate() )
                        v->SetDrill( m_viaDrill.GetValue() );
                }

                if ( !m_netSelector->IsIndeterminate() )
                    v->SetNetCode( m_netSelector->GetSelectedNetcode() );

                if( changeLock )
                    v->SetLocked( setLock );

                break;
            }

            default:
                wxASSERT( false );
                break;
        }
    }

    if ( !m_netSelector->IsIndeterminate() )
    {
        // Commit::Push() will rebuild connectivitiy propagating nets from connected pads
        // outwards.  We therefore have to update the connected pads in order for the net
        // change to "stick".
        for( D_PAD* pad : changingPads )
        {
            m_commit.Modify( pad );
            pad->SetNetCode( m_netSelector->GetSelectedNetcode() );
        }
    }

    m_commit.Push( _( "Edit track/via properties" ) );

    return true;
}
bool DIALOG_TRACK_VIA_PROPERTIES::Apply()
{
    if( !check() )
        return false;

    for( int i = 0; i < m_items.Size(); ++i )
    {
        BOARD_ITEM* item = m_items.Item<BOARD_ITEM>( i );

        switch( item->Type() )
        {
            case PCB_TRACE_T:
            {
                assert( m_tracks );
                TRACK* t = static_cast<TRACK*>( item );

                if( m_trackStartX.Valid() || m_trackStartY.Valid() )
                {
                    wxPoint start = t->GetStart();

                    if( m_trackStartX.Valid() )
                        start.x = m_trackStartX.GetValue();

                    if( m_trackStartY.Valid() )
                        start.y = m_trackStartY.GetValue();

                    t->SetStart( start );
                }

                if( m_trackEndX.Valid() || m_trackEndY.Valid() )
                {
                    wxPoint end = t->GetEnd();

                    if( m_trackEndX.Valid() )
                        end.x = m_trackEndX.GetValue();

                    if( m_trackEndY.Valid() )
                        end.y = m_trackEndY.GetValue();

                    t->SetEnd( end );
                }

                if( m_trackNetclass->IsChecked() )
                {
                    t->SetWidth( t->GetNetClass()->GetTrackWidth() );
                }
                else if( m_trackWidth.Valid() )
                {
                    t->SetWidth( m_trackWidth.GetValue() );
                }

                LAYER_NUM layer = m_TrackLayerCtrl->GetLayerSelection();

                if( layer != UNDEFINED_LAYER )
                    t->SetLayer( (LAYER_ID) layer );

                break;
            }

            case PCB_VIA_T:
            {
                assert( m_vias );

                VIA* v = static_cast<VIA*>( item );

                if( m_viaX.Valid() || m_viaY.Valid() )
                {
                    wxPoint pos = v->GetPosition();

                    if( m_viaX.Valid() )
                        pos.x = m_viaX.GetValue();

                    if( m_viaY.Valid() )
                        pos.y = m_viaY.GetValue();

                    v->SetPosition( pos );
                }

                if( m_viaNetclass->IsChecked() )
                {
                    v->SetWidth( v->GetNetClass()->GetViaDiameter() );
                    v->SetDrill( v->GetNetClass()->GetViaDrill() );
                }
                else
                {
                    if( m_viaDiameter.Valid() )
                        v->SetWidth( m_viaDiameter.GetValue() );

                    if( m_viaDrill.Valid() )
                        v->SetDrill( m_viaDrill.GetValue() );
                }

                break;
            }

            default:
                assert( false );
                break;
        }
    }

    return true;
}
/**
 * Function SwapData
 * Used in undo / redo command:
 *  swap data between Item and a copy
 *  swapped data is data modified by edition, mainly sizes and texts
 * so ONLY FEW values are swapped
 * @param aItem = the item
 * @param aImage = a copy of the item
 */
void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage )
{
    if( aItem == NULL || aImage == NULL )
    {
        wxMessageBox( wxT( "SwapData error: NULL pointer" ) );
        return;
    }

    // Swap layers:
    if( aItem->Type() != PCB_MODULE_T && aItem->Type() != PCB_ZONE_AREA_T )
    {
        // These items have a global swap function.
        int layer, layerimg;
        layer    = aItem->GetLayer();
        layerimg = aImage->GetLayer();
        aItem->SetLayer( layerimg );
        aImage->SetLayer( layer );
    }

    switch( aItem->Type() )
    {
    case PCB_MODULE_T:
        {
            MODULE* tmp = (MODULE*) aImage->Clone();
            ( (MODULE*) aImage )->Copy( (MODULE*) aItem );
            ( (MODULE*) aItem )->Copy( tmp );
            delete tmp;
        }
        break;

    case PCB_ZONE_AREA_T:
        {
            ZONE_CONTAINER* tmp = (ZONE_CONTAINER*) aImage->Clone();
            ( (ZONE_CONTAINER*) aImage )->Copy( (ZONE_CONTAINER*) aItem );
            ( (ZONE_CONTAINER*) aItem )->Copy( tmp );
            delete tmp;
        }
        break;

    case PCB_LINE_T:
#if 0
        EXCHG( ( (DRAWSEGMENT*) aItem )->m_Start, ( (DRAWSEGMENT*) aImage )->m_Start );
        EXCHG( ( (DRAWSEGMENT*) aItem )->m_End, ( (DRAWSEGMENT*) aImage )->m_End );
        EXCHG( ( (DRAWSEGMENT*) aItem )->m_Width, ( (DRAWSEGMENT*) aImage )->m_Width );
        EXCHG( ( (DRAWSEGMENT*) aItem )->m_Shape, ( (DRAWSEGMENT*) aImage )->m_Shape );
#else
        {
            DRAWSEGMENT tmp = *(DRAWSEGMENT*) aImage;
            *aImage = *aItem;
            *aItem  = tmp;
        }
#endif
        break;

    case PCB_TRACE_T:
    case PCB_VIA_T:
        {
            TRACK* track = (TRACK*) aItem;
            TRACK* image = (TRACK*) aImage;

            // swap start, end, width and shape for track and image.
            wxPoint exchp = track->GetStart(); track->SetStart( image->GetStart() ); image->SetStart( exchp );
            exchp = track->GetEnd(); track->SetEnd( image->GetEnd() ); image->SetEnd( exchp );
            int atmp = track->GetWidth(); track->SetWidth( image->GetWidth() ); image->SetWidth( atmp );
            atmp = track->GetShape(); track->SetShape( image->GetShape() ); image->SetShape( atmp );

            atmp = track->GetDrillValue();

            if( track->IsDrillDefault() )
                atmp = -1;

            int itmp = image->GetDrillValue();

            if( image->IsDrillDefault() )
                itmp = -1;

            EXCHG(itmp, atmp );

            if( atmp > 0 )
                track->SetDrill( atmp );
            else
                track->SetDrillDefault();

            if( itmp > 0 )
                image->SetDrill( itmp );
            else
                image->SetDrillDefault();
        }
        break;

    case PCB_TEXT_T:
        EXCHG( ( (TEXTE_PCB*) aItem )->m_Mirror, ( (TEXTE_PCB*) aImage )->m_Mirror );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_Size, ( (TEXTE_PCB*) aImage )->m_Size );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_Pos, ( (TEXTE_PCB*) aImage )->m_Pos );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_Thickness, ( (TEXTE_PCB*) aImage )->m_Thickness );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_Orient, ( (TEXTE_PCB*) aImage )->m_Orient );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_Text, ( (TEXTE_PCB*) aImage )->m_Text );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_Italic, ( (TEXTE_PCB*) aImage )->m_Italic );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_Bold, ( (TEXTE_PCB*) aImage )->m_Bold );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_HJustify, ( (TEXTE_PCB*) aImage )->m_HJustify );
        EXCHG( ( (TEXTE_PCB*) aItem )->m_VJustify, ( (TEXTE_PCB*) aImage )->m_VJustify );
        break;

    case PCB_TARGET_T:
        ( (PCB_TARGET*) aItem )->Exchg( (PCB_TARGET*) aImage );
        break;

    case PCB_DIMENSION_T:
        {
            wxString txt = ( (DIMENSION*) aItem )->GetText();
            ( (DIMENSION*) aItem )->SetText( ( (DIMENSION*) aImage )->GetText() );
            ( (DIMENSION*) aImage )->SetText( txt );
            EXCHG( ( (DIMENSION*) aItem )->m_Width, ( (DIMENSION*) aImage )->m_Width );
            EXCHG( ( (DIMENSION*) aItem )->m_Text.m_Size, ( (DIMENSION*) aImage )->m_Text.m_Size );
            EXCHG( ( (DIMENSION*) aItem )->m_Text.m_Pos, ( (DIMENSION*) aImage )->m_Text.m_Pos );
            EXCHG( ( (DIMENSION*) aItem )->m_Text.m_Thickness,
                   ( (DIMENSION*) aImage )->m_Text.m_Thickness );
            EXCHG( ( (DIMENSION*) aItem )->m_Text.m_Mirror,
                   ( (DIMENSION*) aImage )->m_Text.m_Mirror );
        }
        break;

    case PCB_ZONE_T:
    default:
        wxMessageBox( wxT( "SwapData() error: unexpected type" ) );
        break;
    }
}