Browse Source
SELECTION_TOOL uses ITEMS_PICKED_LIST to store selected items.
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.pull/1/head
6 changed files with 225 additions and 433 deletions
-
58pcbnew/board_undo_redo.cpp
-
132pcbnew/tools/edit_tool.cpp
-
14pcbnew/tools/edit_tool.h
-
284pcbnew/tools/item_state.h
-
132pcbnew/tools/selection_tool.cpp
-
38pcbnew/tools/selection_tool.h
@ -1,284 +0,0 @@ |
|||
/* |
|||
* 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_ */ |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue