/**
 * Function UpdateCopyOfZonesList
 * check a pick list to remove zones identical to their copies
 * and set the type of operation in picker (UR_DELETED, UR_CHANGED)
 * if an item is deleted, the initial values are retrievered,
 * because they can have changed in edition
 * @param aPickList = the main pick list
 * @param aAuxiliaryList = the list of deleted or added (new created) items after calculations
 * @param aPcb = the Board
 *
 * aAuxiliaryList is a list of pickers updated by zone algorithms:
 *  This list contains zones which were added or deleted during the zones combine process
 * aPickList :is a list of zones that can be modified (changed or deleted, or not modified)
 *  Typically, this is the list of existing zones on the layer of the edited zone,
 *  before any change.
 *  >> if the picked zone is not changed, it is removed from list
 *  >> if the picked zone was deleted (i.e. not found in board list), the picker is modified:
 *          its status becomes UR_DELETED
 *          the aAuxiliaryList corresponding picker is removed (if not found : set an error)
 *  >> if the picked zone was flagged as UR_NEW, and was after deleted ,
 *  perhaps combined with an other zone  (i.e. not found in board list):
 *          the picker is removed
 *          the zone itself if really deleted
 *          the aAuxiliaryList corresponding picker is removed (if not found : set an error)
 * After aPickList is cleaned, the aAuxiliaryList is read
 *  All pickers flagged UR_NEW are moved to aPickList
 * (the corresponding zones are zone that were created by the zone normalize and combine process,
 * mainly when adding cutout areas, or creating self intersecting contours)
 *  All pickers flagged UR_DELETED are removed, and the coresponding zones actually deleted
 * (the corresponding zones are new zone that were created by the zone normalize process,
 * when creating self intersecting contours, and after combined with an existing zone.
 * At the end of the update process the aAuxiliaryList must be void,
 *  because all pickers created by the combine process
 *  must have been removed (removed for new and deleted zones, or moved in aPickList.)
 * If not an error is set.
 */
void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
                            PICKED_ITEMS_LIST& aAuxiliaryList,
                            BOARD*             aPcb )
{
    for( unsigned kk = 0; kk < aPickList.GetCount(); kk++ )
    {
        UNDO_REDO_T  status = aPickList.GetPickedItemStatus( kk );

        ZONE_CONTAINER* ref = (ZONE_CONTAINER*) aPickList.GetPickedItem( kk );

        for( unsigned ii = 0; ; ii++ )  // analyse the main picked list
        {
            ZONE_CONTAINER* zone = aPcb->GetArea( ii );

            if( zone == NULL )
            {
                /* End of list: the stored item is not found:
                 * it must be in aDeletedList:
                 * search it and restore initial values
                 * or
                 * if flagged UR_NEW: remove it definitively
                 */
                if( status == UR_NEW )
                {
                    delete ref;
                    ref = NULL;
                    aPickList.RemovePicker( kk );
                    kk--;
                }
                else
                {
                    ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );
                    aPickList.SetPickedItemStatus( UR_DELETED, kk );

                    wxASSERT_MSG( zcopy != NULL,
                                  wxT( "UpdateCopyOfZonesList() error: link = NULL" ) );

                    ref->Copy( zcopy );

                    // the copy was deleted; the link does not exists now.
                    aPickList.SetPickedItemLink( NULL, kk );
                    delete zcopy;
                }

                // Remove this item from aAuxiliaryList, mainly for tests purpose
                bool notfound = true;

                for( unsigned nn = 0; nn < aAuxiliaryList.GetCount(); nn++ )
                {
                    if( ref != NULL && aAuxiliaryList.GetPickedItem( nn ) == ref )
                    {
                        aAuxiliaryList.RemovePicker( nn );
                        notfound = false;
                        break;
                    }
                }

                wxASSERT_MSG( notfound != true,
                              wxT( "UpdateCopyOfZonesList() error: item not found in "
                                   "aAuxiliaryList" ) );
                break;
            }

            if( zone == ref )      // picked zone found
            {
                if( aPickList.GetPickedItemStatus( kk ) != UR_NEW )
                {
                    ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );

                    if( zone->IsSame( *zcopy ) )    // Remove picked, because no changes
                    {
                        delete zcopy;               // Delete copy
                        aPickList.RemovePicker( kk );
                        kk--;
                    }
                }

                break;
            }
        }
    }

    // Add new zones in main pick list, and remove pickers from Auxiliary List
    for( unsigned ii = 0; ii < aAuxiliaryList.GetCount(); )
    {
        if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_NEW )
        {
            ITEM_PICKER picker = aAuxiliaryList.GetItemWrapper( ii );
            aPickList.PushItem( picker );
            aAuxiliaryList.RemovePicker( ii );
        }
        else if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_DELETED )
        {
            delete aAuxiliaryList.GetPickedItemLink( ii );
            aAuxiliaryList.RemovePicker( ii );
        }
        else
            ii++;
    }

    // Should not occur:
    wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
                  wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
}
예제 #2
0
void SCH_EDIT_FRAME::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList,
                                         UNDO_REDO_T        aTypeCommand,
                                         const wxPoint&     aTransformPoint )
{
    PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();

    commandToUndo->m_TransformPoint = aTransformPoint;
    commandToUndo->m_Status = aTypeCommand;

    // Copy picker list:
    commandToUndo->CopyList( aItemsList );

    // Verify list, and creates data if needed
    for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ )
    {
        SCH_ITEM* item = (SCH_ITEM*) commandToUndo->GetPickedItem( ii );
        wxASSERT( item );

        UNDO_REDO_T command = commandToUndo->GetPickedItemStatus( ii );

        if( command == UR_UNSPECIFIED )
        {
            command = aTypeCommand;
            commandToUndo->SetPickedItemStatus( command, ii );
        }

        switch( command )
        {
        case UR_CHANGED:        /* Create a copy of item */

            /* If needed, create a copy of item, and put in undo list
             * in the picker, as link
             * If this link is not null, the copy is already done
             */
            if( commandToUndo->GetPickedItemLink( ii ) == NULL )
                commandToUndo->SetPickedItemLink( DuplicateStruct( item, true ), ii );

            wxASSERT( commandToUndo->GetPickedItemLink( ii ) );
            break;

        case UR_MOVED:
        case UR_MIRRORED_Y:
        case UR_MIRRORED_X:
        case UR_ROTATED:
        case UR_NEW:
        case UR_DELETED:
        case UR_EXCHANGE_T:
        case UR_WIRE_IMAGE:
            break;

        default:
            wxFAIL_MSG( wxString::Format( wxT( "Unknown undo/redo command %d" ), command ) );
            break;
        }
    }

    if( commandToUndo->GetCount() || aTypeCommand == UR_WIRE_IMAGE )
    {
        /* Save the copy in undo list */
        GetScreen()->PushCommandToUndoList( commandToUndo );

        /* Clear redo list, because after new save there is no redo to do */
        GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList );
    }
    else    // Should not occur
    {
        delete commandToUndo;
    }
}
void PCB_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
                                         UNDO_REDO_T        aTypeCommand,
                                         const wxPoint&     aTransformPoint )
{
    PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();

    commandToUndo->m_TransformPoint = aTransformPoint;

    // Copy picker list:
    commandToUndo->CopyList( aItemsList );

    // Verify list, and creates data if needed
    for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ )
    {
        BOARD_ITEM* item    = (BOARD_ITEM*) commandToUndo->GetPickedItem( ii );

        // For texts belonging to modules, we need to save state of the parent module
        if( item->Type() == PCB_MODULE_TEXT_T )
        {
            item = item->GetParent();
            wxASSERT( item->Type() == PCB_MODULE_T );

            if( item == NULL )
                continue;

            commandToUndo->SetPickedItem( item, ii );
            commandToUndo->SetPickedItemStatus( UR_CHANGED, ii );
        }

        UNDO_REDO_T command = commandToUndo->GetPickedItemStatus( ii );

        if( command == UR_UNSPECIFIED )
        {
            command = aTypeCommand;
            commandToUndo->SetPickedItemStatus( command, ii );
        }

        wxASSERT( item );

        switch( command )
        {
        case UR_CHANGED:

            /* If needed, create a copy of item, and put in undo list
             * in the picker, as link
             * If this link is not null, the copy is already done
             */
            if( commandToUndo->GetPickedItemLink( ii ) == NULL )
                commandToUndo->SetPickedItemLink( item->Clone(), ii );
            break;

        case UR_MOVED:
        case UR_ROTATED:
        case UR_ROTATED_CLOCKWISE:
        case UR_FLIPPED:
        case UR_NEW:
        case UR_DELETED:
            break;

        default:
        {
            wxString msg;
            msg.Printf( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), command );
            wxMessageBox( msg );
        }

        break;

        }
    }

    if( commandToUndo->GetCount() )
    {
        /* Save the copy in undo list */
        GetScreen()->PushCommandToUndoList( commandToUndo );

        /* Clear redo list, because after a new command one cannot redo a command */
        GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList );
    }
    else    // Should not occur
    {
        delete commandToUndo;
    }
}
예제 #4
0
void PCB_BASE_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
                                         UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint )
{
    PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();

    commandToUndo->m_TransformPoint = aTransformPoint;

    // First, filter unnecessary stuff from the list (i.e. for multiple pads / labels modified),
    // take the first occurence of the module (we save copies of modules when one of its subitems
    // is changed).
    for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
    {
        ITEM_PICKER curr_picker = aItemsList.GetItemWrapper(ii);
        BOARD_ITEM* item    = (BOARD_ITEM*) aItemsList.GetPickedItem( ii );

        // For items belonging to modules, we need to save state of the parent module
        if( item->Type() == PCB_MODULE_TEXT_T || item->Type() == PCB_MODULE_EDGE_T
                || item->Type() == PCB_PAD_T )
        {
            // Item to be stored in the undo buffer is the parent module
            item = item->GetParent();
            wxASSERT( item && item->Type() == PCB_MODULE_T );

            if( item == NULL )
                continue;

            // Check if the parent module has already been saved in another entry
            bool found = false;

            for( unsigned j = 0; j < commandToUndo->GetCount(); j++ )
            {
                if( commandToUndo->GetPickedItem( j ) == item && commandToUndo->GetPickedItemStatus( j ) == UR_CHANGED )
                {
                    found = true;
                    break;
                }
            }

            if( !found )
            {
                // Create a clean copy of the parent module
                MODULE* orig = static_cast<MODULE*>( item );
                MODULE* clone = new MODULE( *orig );
                clone->SetParent( GetBoard() );

                // Clear current flags (which can be temporary set by a current edit command)
                for( EDA_ITEM* loc_item = clone->GraphicalItemsList(); loc_item;
                        loc_item = loc_item->Next() )
                    loc_item->ClearFlags();

                for( D_PAD* pad = clone->PadsList(); pad; pad = pad->Next() )
                    pad->ClearFlags();

                clone->Reference().ClearFlags();
                clone->Value().ClearFlags();

                ITEM_PICKER picker( item, UR_CHANGED );
                picker.SetLink( clone );
                commandToUndo->PushItem( picker );

                orig->SetLastEditTime();
            }
            else
            {
                continue;
            }
        }
        else
        {
            // Normal case: all other BOARD_ITEMs, are simply copied to the new list
            commandToUndo->PushItem( curr_picker );
        }
    }

    for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ )
    {
        BOARD_ITEM* item    = (BOARD_ITEM*) commandToUndo->GetPickedItem( ii );
        UNDO_REDO_T command = commandToUndo->GetPickedItemStatus( ii );

        if( command == UR_UNSPECIFIED )
        {
            command = aTypeCommand;
            commandToUndo->SetPickedItemStatus( command, ii );
        }

        wxASSERT( item );

        switch( command )
        {
        case UR_CHANGED:
        case UR_DRILLORIGIN:
        case UR_GRIDORIGIN:

            /* If needed, create a copy of item, and put in undo list
             * in the picker, as link
             * If this link is not null, the copy is already done
             */
            if( commandToUndo->GetPickedItemLink( ii ) == NULL )
            {
                EDA_ITEM* cloned = item->Clone();
                commandToUndo->SetPickedItemLink( cloned, ii );
            }
            break;

        case UR_MOVED:
        case UR_ROTATED:
        case UR_ROTATED_CLOCKWISE:
        case UR_FLIPPED:
        case UR_NEW:
        case UR_DELETED:
            break;

        default:
        {
            wxLogDebug( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), command );
        }
        break;

        }
    }

    if( commandToUndo->GetCount() )
    {
        /* Save the copy in undo list */
        GetScreen()->PushCommandToUndoList( commandToUndo );

        /* Clear redo list, because after a new command one cannot redo a command */
        GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList );
    }
    else
    {
        // Should not occur
        wxASSERT( false );
        delete commandToUndo;
    }
}
void PCB_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
                                         UNDO_REDO_T        aTypeCommand,
                                         const wxPoint&     aTransformPoint )
{
    PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();

    commandToUndo->m_TransformPoint = aTransformPoint;

    // First, filter unnecessary stuff from the list (i.e. for multiple pads / labels modified),
    // take the first occurence of the module.

    for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
    {
        ITEM_PICKER picker = aItemsList.GetItemWrapper(ii);
        BOARD_ITEM* item    = (BOARD_ITEM*) aItemsList.GetPickedItem( ii );

        // For texts belonging to modules, we need to save state of the parent module
        if( item->Type() == PCB_MODULE_TEXT_T  || item->Type() == PCB_PAD_T )
        {
            item = item->GetParent();
            wxASSERT( item->Type() == PCB_MODULE_T );

            if( item == NULL )
                continue;

            bool found = false;

            for( unsigned j = 0; j < commandToUndo->GetCount(); j++ )
            {
                if( commandToUndo->GetPickedItem( j ) == item && commandToUndo->GetPickedItemStatus( j ) == UR_CHANGED )
                {
                    found = true;
                    break;
                }
            }

            if( !found )
                commandToUndo->PushItem( ITEM_PICKER(item, UR_CHANGED ) );
            else
                continue;

        } else {
            commandToUndo->PushItem( picker );
        }
    }

    for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ )
    {
        BOARD_ITEM* item    = (BOARD_ITEM*) commandToUndo->GetPickedItem( ii );
        UNDO_REDO_T command = commandToUndo->GetPickedItemStatus( ii );

        if( command == UR_UNSPECIFIED )
        {
            command = aTypeCommand;
            commandToUndo->SetPickedItemStatus( command, ii );
        }

        wxASSERT( item );

        switch( command )
        {
        case UR_CHANGED:

            /* If needed, create a copy of item, and put in undo list
             * in the picker, as link
             * If this link is not null, the copy is already done
             */
            if( commandToUndo->GetPickedItemLink( ii ) == NULL )
            {
                EDA_ITEM* cloned = item->Clone();
                commandToUndo->SetPickedItemLink( cloned, ii );
            }
            break;

        case UR_MOVED:
        case UR_ROTATED:
        case UR_ROTATED_CLOCKWISE:
        case UR_FLIPPED:
        case UR_NEW:
        case UR_DELETED:
            break;

        default:
        {
            wxString msg;
            msg.Printf( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), command );
            wxMessageBox( msg );
        }

        break;

        }
    }

    if( commandToUndo->GetCount() )
    {
        /* Save the copy in undo list */
        GetScreen()->PushCommandToUndoList( commandToUndo );

        /* Clear redo list, because after a new command one cannot redo a command */
        GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList );
    }
    else    // Should not occur
    {
        delete commandToUndo;
    }
}