Commit 87323530 authored by Maciej Suminski's avatar Maciej Suminski
Browse files

SELECTION_TOOL uses ITEMS_PICKED_LIST to store selected items.

Modifications done using the EDIT_TOOL are saved using the default KiCad's undo buffer.
If there is only one item selected, info about the item is displayed in the bottom status bar.
parent e4efe212
Loading
Loading
Loading
Loading
+58 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@


#include <fctsys.h>
#include <fctsys.h>
#include <class_drawpanel.h>
#include <class_drawpanel.h>
#include <class_drawpanel_gal.h>
#include <macros.h>
#include <macros.h>


#include <pcbnew.h>
#include <pcbnew.h>
@@ -40,6 +41,8 @@
#include <class_zone.h>
#include <class_zone.h>
#include <class_edge_mod.h>
#include <class_edge_mod.h>


#include <tools/selection_tool.h>
#include <tool/tool_manager.h>


/* Functions to undo and redo edit commands.
/* Functions to undo and redo edit commands.
 *  commands to undo are stored in CurrentScreen->m_UndoList
 *  commands to undo are stored in CurrentScreen->m_UndoList
@@ -424,6 +427,7 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed
    BOARD_ITEM* item;
    BOARD_ITEM* item;
    bool        not_found = false;
    bool        not_found = false;
    bool        reBuild_ratsnest = false;
    bool        reBuild_ratsnest = false;
    KIGFX::VIEW* view = m_galCanvas->GetView();


    // Undo in the reverse order of list creation: (this can allow stacked changes
    // Undo in the reverse order of list creation: (this can allow stacked changes
    // like the same item can be changes and deleted in the same complex command
    // like the same item can be changes and deleted in the same complex command
@@ -484,35 +488,80 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed
        case UR_CHANGED:    /* Exchange old and new data for each item */
        case UR_CHANGED:    /* Exchange old and new data for each item */
        {
        {
            BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii );
            BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii );

            // Remove all pads/drawings/texts, as they become invalid
            // for the VIEW after SwapData() called for modules
            if( item->Type() == PCB_MODULE_T )
            {
                MODULE* oldModule = static_cast<MODULE*>( item );
                oldModule->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Remove ),
                                                        view ) );
            }

            item->SwapData( image );
            item->SwapData( image );

            // Update all pads/drawings/texts, as they become invalid
            // for the VIEW after SwapData() called for modules
            if( item->Type() == PCB_MODULE_T )
            {
                MODULE* newModule = static_cast<MODULE*>( item );
                newModule->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Add ),
                                                        view ) );
            }

            item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS );
        }
        }
        break;
        break;


        case UR_NEW:        /* new items are deleted */
        case UR_NEW:        /* new items are deleted */
            aList->SetPickedItemStatus( UR_DELETED, ii );
            aList->SetPickedItemStatus( UR_DELETED, ii );
            GetBoard()->Remove( item );
            GetBoard()->Remove( item );

            if( item->Type() == PCB_MODULE_T )
            {
                MODULE* module = static_cast<MODULE*>( item );
                module->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Remove ),
                                                                   view ) );
            }
            view->Remove( item );

            item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
            break;
            break;


        case UR_DELETED:    /* deleted items are put in List, as new items */
        case UR_DELETED:    /* deleted items are put in List, as new items */
            aList->SetPickedItemStatus( UR_NEW, ii );
            aList->SetPickedItemStatus( UR_NEW, ii );
            GetBoard()->Add( item );
            GetBoard()->Add( item );

            if( item->Type() == PCB_MODULE_T )
            {
                MODULE* module = static_cast<MODULE*>( item );
                module->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Add ),
                                                                   view ) );
            }
            view->Add( item );

            item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
            build_item_list = true;
            build_item_list = true;
            break;
            break;


        case UR_MOVED:
        case UR_MOVED:
            item->Move( aRedoCommand ? aList->m_TransformPoint : -aList->m_TransformPoint );
            item->Move( aRedoCommand ? aList->m_TransformPoint : -aList->m_TransformPoint );
            item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
            break;
            break;


        case UR_ROTATED:
        case UR_ROTATED:
            item->Rotate( aList->m_TransformPoint, aRedoCommand ? 900 : -900 );
            item->Rotate( aList->m_TransformPoint, aRedoCommand ? 900 : -900 );
            item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
            break;
            break;


        case UR_ROTATED_CLOCKWISE:
        case UR_ROTATED_CLOCKWISE:
            item->Rotate( aList->m_TransformPoint, aRedoCommand ? -900 : 900 );
            item->Rotate( aList->m_TransformPoint, aRedoCommand ? -900 : 900 );
            item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
            break;
            break;


        case UR_FLIPPED:
        case UR_FLIPPED:
            item->Flip( aList->m_TransformPoint );
            item->Flip( aList->m_TransformPoint );
            item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS );
            break;
            break;


        default:
        default:
@@ -540,6 +589,11 @@ void PCB_EDIT_FRAME::GetBoardFromUndoList( wxCommandEvent& event )
    if( GetScreen()->GetUndoCommandCount() <= 0 )
    if( GetScreen()->GetUndoCommandCount() <= 0 )
        return;
        return;


    // Clear the selection, as it may be altered with undone items
    SELECTION_TOOL* selectionTool = static_cast<SELECTION_TOOL*>( m_toolManager->FindTool(
                                                                  "pcbnew.InteractiveSelection" ) );
    selectionTool->ClearSelection();

    /* Get the old list */
    /* Get the old list */
    PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList();
    PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList();
    /* Undo the command */
    /* Undo the command */
@@ -559,6 +613,10 @@ void PCB_EDIT_FRAME::GetBoardFromRedoList( wxCommandEvent& event )
    if( GetScreen()->GetRedoCommandCount() == 0 )
    if( GetScreen()->GetRedoCommandCount() == 0 )
        return;
        return;


    // Clear the selection, as it may be altered with redone items
    SELECTION_TOOL* selectionTool = static_cast<SELECTION_TOOL*>( m_toolManager->FindTool(
                                                                  "pcbnew.InteractiveSelection" ) );
    selectionTool->ClearSelection();


    /* Get the old list */
    /* Get the old list */
    PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList();
    PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList();
+85 −47
Original line number Original line Diff line number Diff line
@@ -72,11 +72,15 @@ bool EDIT_TOOL::Init()
int EDIT_TOOL::Main( TOOL_EVENT& aEvent )
int EDIT_TOOL::Main( TOOL_EVENT& aEvent )
{
{
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );

    // By default, modified items need to update their geometry
    m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY;


    if( selection.Empty() )
    if( selection.Empty() )
        return 0; // there are no items to operate on
        return 0; // there are no items to operate on


    VECTOR2D dragPosition;
    VECTOR2D dragPosition;      // The last position of the cursor while dragging
    m_dragging = false;
    m_dragging = false;
    bool restore = false;       // Should items' state be restored when finishing the tool?
    bool restore = false;       // Should items' state be restored when finishing the tool?


@@ -98,9 +102,16 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent )
        else if( evt->Category() == TC_COMMAND )
        else if( evt->Category() == TC_COMMAND )
        {
        {
            if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
            if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
            {
                Rotate( aEvent );
                Rotate( aEvent );
            }
            else if( evt->IsAction( &COMMON_ACTIONS::flip ) )
            else if( evt->IsAction( &COMMON_ACTIONS::flip ) )
            {
                Flip( aEvent );
                Flip( aEvent );

                // Flip causes change of layers
                enableUpdateFlag( KIGFX::VIEW_ITEM::LAYERS );
            }
        }
        }


        else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
        else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
@@ -109,19 +120,24 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent )
            {
            {
                // Drag items to the current cursor position
                // Drag items to the current cursor position
                VECTOR2D movement = ( evt->Position() - dragPosition );
                VECTOR2D movement = ( evt->Position() - dragPosition );
                m_state.Move( movement );
                for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
                {
                    BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );
                    item->Move( wxPoint( movement.x, movement.y ) );
                }
            }
            }
            else
            else
            {
            {
                // Prepare to drag
                // Prepare to drag - save items, so changes can be undone
                std::set<BOARD_ITEM*>::iterator it;
                for( unsigned int i = 0; i < selection.items.GetCount(); ++i )

                for( it = selection.items.begin(); it != selection.items.end(); ++it )
                {
                {
                    // Save the state of the selected items, in case it has to be restored
                    BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );
                    m_state.Save( *it );
                    std::cout << "saved " << (unsigned long) item << std::endl;
                }
                }


                editFrame->OnModify();
                editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED );

                m_dragging = true;
                m_dragging = true;
            }
            }


@@ -138,14 +154,13 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent )
    if( restore )
    if( restore )
    {
    {
        // Modifications has to be rollbacked, so restore the previous state of items
        // Modifications has to be rollbacked, so restore the previous state of items
        selection.group->ItemsViewUpdate( VIEW_ITEM::APPEARANCE );
        wxCommandEvent dummy;
        m_state.RestoreAll();
        editFrame->GetBoardFromUndoList( dummy );
    }
    }
    else
    else
    {
    {
        // Changes are applied, so update the items
        // Changes are applied, so update the items
        selection.group->ItemsViewUpdate( m_state.GetUpdateFlag() );
        selection.group->ItemsViewUpdate( m_updateFlag );
        m_state.Apply();
    }
    }


    controls->ShowCursor( false );
    controls->ShowCursor( false );
@@ -161,13 +176,20 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent )
int EDIT_TOOL::Properties( TOOL_EVENT& aEvent )
int EDIT_TOOL::Properties( TOOL_EVENT& aEvent )
{
{
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );


    // Properties are displayed when there is only one item selected
    // Properties are displayed when there is only one item selected
    if( selection.items.size() == 1 )
    if( selection.Size() == 1 )
    {
    {
        // Display properties dialog
        // Display properties dialog
        PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( 0 ) );
        BOARD_ITEM* item = *selection.items.begin();

        if( !m_dragging )   // If it is being dragged, then it is already saved with UR_CHANGED flag
        {
            editFrame->SaveCopyInUndoList( item, UR_CHANGED );
            editFrame->OnModify();
        }

        editFrame->OnEditItemRequest( NULL, item );
        editFrame->OnEditItemRequest( NULL, item );


        item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
        item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
@@ -182,25 +204,28 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent )
int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent )
int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent )
{
{
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    VECTOR2D cursorPos = getView()->ToWorld( getViewControls()->GetCursorPosition() );
    VECTOR2D cursor = getView()->ToWorld( getViewControls()->GetCursorPosition() );
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );


    if( m_dragging )
    if( !m_dragging )   // If it is being dragged, then it is already saved with UR_CHANGED flag
    {
    {
        m_state.Rotate( cursorPos, 900.0 );
        editFrame->OnModify();
        selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY );
        editFrame->SaveCopyInUndoList( selection.items, UR_ROTATED, wxPoint( cursor.x, cursor.y ) );
    }
    }
    else
    {
        std::set<BOARD_ITEM*>::iterator it;


        for( it = selection.items.begin(); it != selection.items.end(); ++it )
    for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
    {
    {
            (*it)->Rotate( wxPoint( cursorPos.x, cursorPos.y ), 900.0 );
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );
            (*it)->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );

        item->Rotate( wxPoint( cursor.x, cursor.y ), 900.0 );
        if( !m_dragging )
            item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
    }
    }


    if( m_dragging )
        selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );

    setTransitions();
    setTransitions();
    }


    return 0;
    return 0;
}
}
@@ -209,25 +234,28 @@ int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent )
int EDIT_TOOL::Flip( TOOL_EVENT& aEvent )
int EDIT_TOOL::Flip( TOOL_EVENT& aEvent )
{
{
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    VECTOR2D cursorPos = getView()->ToWorld( getViewControls()->GetCursorPosition() );
    VECTOR2D cursor = getView()->ToWorld( getViewControls()->GetCursorPosition() );
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );


    if( m_dragging )
    if( !m_dragging )   // If it is being dragged, then it is already saved with UR_CHANGED flag
    {
    {
        m_state.Flip( cursorPos );
        editFrame->OnModify();
        selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY );
        editFrame->SaveCopyInUndoList( selection.items, UR_FLIPPED, wxPoint( cursor.x, cursor.y ) );
    }
    }
    else
    {
        std::set<BOARD_ITEM*>::iterator it;


        for( it = selection.items.begin(); it != selection.items.end(); ++it )
    for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
    {
    {
            (*it)->Flip( wxPoint( cursorPos.x, cursorPos.y ) );
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );
            (*it)->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS );

        item->Flip( wxPoint( cursor.x, cursor.y ) );
        if( !m_dragging )
            item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS );
    }
    }


    if( m_dragging )
        selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );

    setTransitions();
    setTransitions();
    }


    return 0;
    return 0;
}
}
@@ -236,14 +264,24 @@ int EDIT_TOOL::Flip( TOOL_EVENT& aEvent )
int EDIT_TOOL::Remove( TOOL_EVENT& aEvent )
int EDIT_TOOL::Remove( TOOL_EVENT& aEvent )
{
{
    // Get a copy of the selected items set
    // Get a copy of the selected items set
    std::set<BOARD_ITEM*> selectedItems = m_selectionTool->GetSelection().items;
    PICKED_ITEMS_LIST selectedItems = m_selectionTool->GetSelection().items;
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );


    // As we are about to remove items, they have to be removed from the selection first
    // As we are about to remove items, they have to be removed from the selection first
    m_selectionTool->ClearSelection();
    m_selectionTool->ClearSelection();


    std::set<BOARD_ITEM*>::iterator it;
    // Save them
    for( it = selectedItems.begin(); it != selectedItems.end(); ++it )
    for( unsigned int i = 0; i < selectedItems.GetCount(); ++i )
        remove( *it );
        selectedItems.SetPickedItemStatus( UR_DELETED, i );
    editFrame->OnModify();
    editFrame->SaveCopyInUndoList( selectedItems, UR_DELETED );

    // And now remove
    for( unsigned int i = 0; i < selectedItems.GetCount(); ++i )
    {
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selectedItems.GetPickedItem( i ) );
        remove( item );
    }


    // Rebuild list of pads and nets if necessary
    // Rebuild list of pads and nets if necessary
    BOARD* board = getModel<BOARD>( PCB_T );
    BOARD* board = getModel<BOARD>( PCB_T );
@@ -265,6 +303,7 @@ void EDIT_TOOL::remove( BOARD_ITEM* aItem )
    case PCB_MODULE_T:
    case PCB_MODULE_T:
    {
    {
        MODULE* module = static_cast<MODULE*>( aItem );
        MODULE* module = static_cast<MODULE*>( aItem );
        module->ClearFlags();


        for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
        for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
            getView()->Remove( pad );
            getView()->Remove( pad );
@@ -305,7 +344,6 @@ void EDIT_TOOL::remove( BOARD_ITEM* aItem )
    case PCB_ZONE_T:                // SEG_ZONE items are now deprecated
    case PCB_ZONE_T:                // SEG_ZONE items are now deprecated
        break;
        break;


    // TODO
    default:                        // other types do not need to (or should not) be handled
    default:                        // other types do not need to (or should not) be handled
        assert( false );
        assert( false );
        return;
        return;
@@ -313,7 +351,7 @@ void EDIT_TOOL::remove( BOARD_ITEM* aItem )
    }
    }


    getView()->Remove( aItem );
    getView()->Remove( aItem );
    board->Delete( aItem );
    board->Remove( aItem );
}
}




+10 −4
Original line number Original line Diff line number Diff line
@@ -28,7 +28,6 @@
#include <math/vector2d.h>
#include <math/vector2d.h>
#include <tool/tool_interactive.h>
#include <tool/tool_interactive.h>
#include <view/view_group.h>
#include <view/view_group.h>
#include "item_state.h"


class BOARD_ITEM;
class BOARD_ITEM;
class SELECTION_TOOL;
class SELECTION_TOOL;
@@ -93,9 +92,6 @@ public:
    int Remove( TOOL_EVENT& aEvent );
    int Remove( TOOL_EVENT& aEvent );


private:
private:
    ///> Saves the state of items and allows to restore them
    ITEM_STATE m_state;

    ///> Selection tool used for obtaining selected items
    ///> Selection tool used for obtaining selected items
    SELECTION_TOOL* m_selectionTool;
    SELECTION_TOOL* m_selectionTool;


@@ -107,6 +103,16 @@ private:


    ///> Sets up handlers for various events
    ///> Sets up handlers for various events
    void setTransitions();
    void setTransitions();

    ///> The required update flag for modified items
    KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS m_updateFlag;

    ///> Enables higher order update flag
    void enableUpdateFlag( KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS aFlag )
    {
        if( m_updateFlag < aFlag )
            m_updateFlag = aFlag;
    }
};
};


#endif
#endif

pcbnew/tools/item_state.h

deleted100644 → 0
+0 −284
Original line number Original line Diff line number Diff line
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2013 CERN
 * @author Maciej Suminski <maciej.suminski@cern.ch>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

#ifndef ITEM_STATE_H_
#define ITEM_STATE_H_

#include <deque>
#include <class_board_item.h>

/**
 * Class ITEM_STATE
 *
 * Provides means for modifying properties of groups of items and gives possibility of rolling back
 * the introduced changes. Does not take ownership of modified items, neither takes care of
 * refreshing.
 */
class ITEM_STATE
{
public:
    ITEM_STATE() :
        m_movement( 0.0, 0.0 ), m_flips( 0 ), m_rotation( 0.0 )
    {
#ifdef __WXDEBUG__
        m_canSave = true;
#endif
    }

    /**
     * Function Save()
     *
     * Adds an item and saves it's state.
     * @param aItem is the item to be added.
     */
    void Save( BOARD_ITEM* aItem )
    {
#ifdef __WXDEBUG__
        wxASSERT_MSG( m_canSave, wxT( "You cannot save items after issuing commands. You have "
                                      "either RestoreAll() or Apply() before adding items!" ) );
#endif
        m_items.push_back( aItem );
    }

    /**
     * Function RestoreAll()
     *
     * Rollbacks all the changes to the initial state.
     */
    void RestoreAll()
    {
        // Check if there is a not saved movement command
        saveMovement();

        std::deque<BOARD_ITEM*>::iterator it, it_end;
        std::deque<COMMAND>::iterator cmd, cmd_end;

        for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
        {
            for( cmd = m_commands.begin(), cmd_end = m_commands.end(); cmd != cmd_end; ++cmd )
                cmd->Revert( *it );
        }

        reset();
    }

    /**
     * Function Apply()
     *
     * Resets the state, clears the list of items & changes, so the object can be reused for
     * other items.
     */
    void Apply()
    {
        reset();
    }

    /**
     * Function Move()
     *
     * Moves stored items by a given vector.
     * @param aMovement is the movement vector.
     */
    void Move( const VECTOR2D& aMovement )
    {
#ifdef __WXDEBUG__
        m_canSave = false;
#endif
        std::deque<BOARD_ITEM*>::iterator it, it_end;

        for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
            (*it)->Move( wxPoint( aMovement.x, aMovement.y ) );

        m_movement += aMovement;
    }

    /**
     * Function Rotate()
     *
     * Rotates stored items by a given angle.
     * @param aAngle is the angle (in decidegrees).
     */
    void Rotate( const VECTOR2D& aPoint, double aAngle )
    {
#ifdef __WXDEBUG__
        m_canSave = false;
#endif
        saveMovement();
        m_commands.push_front( COMMAND( COMMAND::ROTATE, aPoint, aAngle ) );

        std::deque<BOARD_ITEM*>::iterator it, it_end;

        for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
            (*it)->Rotate( wxPoint( aPoint.x, aPoint.y ), aAngle );

        m_rotation += aAngle;
    }

    /**
     * Function Flip()
     *
     * Changes the board side for stored items.
     * @param aPoint is the rotation point.
     */
    void Flip( const VECTOR2D& aPoint )
    {
#ifdef __WXDEBUG__
        m_canSave = false;
#endif
        saveMovement();
        m_commands.push_front( COMMAND( COMMAND::FLIP, aPoint ) );

        std::deque<BOARD_ITEM*>::iterator it, it_end;

        for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
            (*it)->Flip( wxPoint( aPoint.x, aPoint.y ) );

        m_flips++;
    }

    /**
     * Function ToggleVisibility()
     *
     * Switches the visibility property of stored items.
     */
    void ToggleVisibility()
    {
#ifdef __WXDEBUG__
        m_canSave = false;
#endif
        m_commands.push_front( COMMAND( COMMAND::VISIBILITY ) );

        std::deque<BOARD_ITEM*>::iterator it, it_end;

        for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
            (*it)->ViewSetVisible( !(*it)->ViewIsVisible() );
    }

    /**
     * Function GetUpdateFlag()
     *
     * Returns information on what kind of update should be applied to items in order to display
     * them properly.
     * @return Flag required to refresh items.
     */
    KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS GetUpdateFlag() const
    {
        if( m_flips % 2 == 1 ) // If number of flips is odd, then we need to change layers
            return KIGFX::VIEW_ITEM::LAYERS;
        else if( m_movement.x != 0.0 || m_movement.y != 0.0 || m_rotation != 0.0 )
            return KIGFX::VIEW_ITEM::GEOMETRY;

        return KIGFX::VIEW_ITEM::APPEARANCE;
    }

private:
    /// COMMAND stores modifications that were done to items
    struct COMMAND
    {
        /// Type of command
        enum TYPE { MOVE, ROTATE, FLIP, VISIBILITY };
        TYPE m_type;

        /// Point where flip/rotation occurred or movement vector
        VECTOR2D m_point;

        /// Used only for rotation
        double m_angle;

        COMMAND( TYPE aType, VECTOR2D aPoint = VECTOR2D( 0.0, 0.0 ), double aAngle = 0.0 ) :
            m_type( aType ), m_point( aPoint ), m_angle( aAngle ) {};

        void Revert( BOARD_ITEM* aItem )
        {
            switch( m_type )
            {
            case MOVE:
                aItem->Move( wxPoint( -m_point.x, -m_point.y ) );
                break;

            case ROTATE:
                aItem->Rotate( wxPoint( m_point.x, m_point.y ), -m_angle );
                break;

            case FLIP:
                aItem->Flip( wxPoint( m_point.x, m_point.y ) );
                break;

            case VISIBILITY:
                aItem->ViewSetVisible( !aItem->ViewIsVisible() );
                break;
            }
        }
    };

    /// Adds a MOVEMENT command basing on the current movement vector
    void saveMovement()
    {
        if( m_movement.x != 0.0 || m_movement.y != 0.0 )
        {
            m_commands.push_front( COMMAND( COMMAND::MOVE, m_movement ) );

            m_movement.x = 0.0;
            m_movement.y = 0.0;
        }
    }

    /// Restores the initial state
    void reset()
    {
        m_movement.x = 0.0;
        m_movement.y = 0.0;
        m_flips = 0;
        m_rotation = 0.0;

        m_items.clear();
        m_commands.clear();

#ifdef __WXDEBUG__
        m_canSave = true;
#endif
    }

    /// List of issued commands
    std::deque<BOARD_ITEM*> m_items;

    /// List of items that are affected by commands
    std::deque<COMMAND> m_commands;

    /// Current movement vector (updated by Move() command)
    VECTOR2D m_movement;

    /// Number of flips applied to items
    unsigned int m_flips;

    /// Total rotation applied to items
    double m_rotation;

#ifdef __WXDEBUG__
    /// Debug flag assuring that functions are called in proper order
    bool m_canSave;
#endif
};

#endif /* ITEM_STATE_H_ */
+51 −81

File changed.

Preview size limit exceeded, changes collapsed.

Loading