Added rotate & flip to the pcbnew.InteractiveMove tool, hotkeys for them and undoing all the operations on cancelling the tool.
This commit is contained in:
parent
1de8eba49e
commit
c4ad58f2a8
|
@ -36,7 +36,9 @@ using boost::optional;
|
|||
|
||||
MOVE_TOOL::MOVE_TOOL() :
|
||||
TOOL_INTERACTIVE( "pcbnew.InteractiveMove" ), m_selectionTool( NULL ),
|
||||
m_activate( m_toolName, AS_GLOBAL, 'M', "Move", "Moves the selected item(s)" )
|
||||
m_activate( m_toolName, AS_GLOBAL, 'M', "Move", "Moves the selected item(s)" ),
|
||||
m_rotate( m_toolName + ".rotate", AS_CONTEXT, ' ', "Rotate", "Rotates selected item(s)" ),
|
||||
m_flip( m_toolName + ".flip", AS_CONTEXT, 'F', "Flip", "Flips selected item(s)" )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -48,8 +50,6 @@ MOVE_TOOL::~MOVE_TOOL()
|
|||
|
||||
void MOVE_TOOL::Reset()
|
||||
{
|
||||
m_toolMgr->RegisterAction( &m_activate );
|
||||
|
||||
// Find the selection tool, so they can cooperate
|
||||
TOOL_BASE* selectionTool = m_toolMgr->FindTool( std::string( "pcbnew.InteractiveSelection" ) );
|
||||
|
||||
|
@ -63,6 +63,11 @@ void MOVE_TOOL::Reset()
|
|||
return;
|
||||
}
|
||||
|
||||
// Activate hotkeys
|
||||
m_toolMgr->RegisterAction( &m_activate );
|
||||
m_toolMgr->RegisterAction( &m_rotate );
|
||||
m_toolMgr->RegisterAction( &m_flip );
|
||||
|
||||
// the tool launches upon reception of action event ("pcbnew.InteractiveMove")
|
||||
Go( &MOVE_TOOL::Main, m_activate.GetEvent() );
|
||||
}
|
||||
|
@ -90,17 +95,30 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
break; // Finish
|
||||
}
|
||||
|
||||
if( evt->IsMotion() || evt->IsDrag( MB_Left ) )
|
||||
// Dispatch TOOL_ACTIONs
|
||||
else if( evt->Category() == TC_Command )
|
||||
{
|
||||
VECTOR2D cursorPos = getView()->ToWorld( getViewControls()->GetCursorPosition() );
|
||||
|
||||
if( evt->Matches( m_rotate.GetEvent() ) )
|
||||
{
|
||||
m_state.Rotate( cursorPos, 900.0 );
|
||||
m_items.ViewUpdate( VIEW_ITEM::GEOMETRY );
|
||||
}
|
||||
else if( evt->Matches( m_flip.GetEvent() ) )
|
||||
{
|
||||
m_state.Flip( cursorPos );
|
||||
m_items.ViewUpdate( VIEW_ITEM::GEOMETRY );
|
||||
}
|
||||
}
|
||||
|
||||
else if( evt->IsMotion() || evt->IsDrag( MB_Left ) )
|
||||
{
|
||||
if( dragging )
|
||||
{
|
||||
// Dragging is already active
|
||||
// Drag items to the current cursor position
|
||||
VECTOR2D movement = ( evt->Position() - dragPosition );
|
||||
std::set<BOARD_ITEM*>::iterator it, it_end;
|
||||
|
||||
// so move all the selected items
|
||||
for( it = m_selection.begin(), it_end = m_selection.end(); it != it_end; ++it )
|
||||
(*it)->Move( wxPoint( movement.x, movement.y ) );
|
||||
m_state.Move( movement );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -112,28 +130,17 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
std::set<BOARD_ITEM*>::iterator it;
|
||||
for( it = m_selection.begin(); it != m_selection.end(); ++it )
|
||||
{
|
||||
// Save the state of the selected items, in case it has to be restored
|
||||
m_state.Save( *it );
|
||||
|
||||
// Gather all selected items into one VIEW_GROUP
|
||||
viewGroupAdd( *it, &m_items );
|
||||
|
||||
// Modules are treated in a special way - when they are moved, we have to
|
||||
// move all the parts that make the module, not the module itself
|
||||
if( (*it)->Type() == PCB_MODULE_T )
|
||||
{
|
||||
MODULE* module = static_cast<MODULE*>( *it );
|
||||
|
||||
// Add everything that belongs to the module (besides the module itself)
|
||||
for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
|
||||
viewGroupAdd( pad, &m_items );
|
||||
|
||||
for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing;
|
||||
drawing = drawing->Next() )
|
||||
viewGroupAdd( drawing, &m_items );
|
||||
|
||||
viewGroupAdd( &module->Reference(), &m_items );
|
||||
viewGroupAdd( &module->Value(), &m_items );
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the original items, they are temporarily shown in VIEW_GROUP on overlay
|
||||
vgSetVisibility( &m_items, false );
|
||||
vgUpdate( &m_items, VIEW_ITEM::APPEARANCE );
|
||||
|
||||
dragging = true;
|
||||
}
|
||||
|
||||
|
@ -144,25 +151,21 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
break; // Finish
|
||||
}
|
||||
|
||||
// Clean-up after movement
|
||||
std::deque<ITEM_STATE>::iterator it, it_end;
|
||||
// Restore visibility of the original items
|
||||
vgSetVisibility( &m_items, true );
|
||||
|
||||
// Movement has to be rollbacked, so restore the previous state of items
|
||||
if( restore )
|
||||
{
|
||||
// Movement has to be rollbacked, so restore the previous state of items
|
||||
for( it = m_itemsState.begin(), it_end = m_itemsState.end(); it != it_end; ++it )
|
||||
it->Restore();
|
||||
vgUpdate( &m_items, VIEW_ITEM::APPEARANCE );
|
||||
m_state.RestoreAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply changes
|
||||
for( it = m_itemsState.begin(), it_end = m_itemsState.end(); it != it_end; ++it )
|
||||
{
|
||||
it->RestoreVisibility();
|
||||
it->item->ViewUpdate( VIEW_ITEM::GEOMETRY );
|
||||
}
|
||||
vgUpdate( &m_items, m_state.GetUpdateFlag() );
|
||||
m_state.Apply();
|
||||
}
|
||||
|
||||
m_itemsState.clear();
|
||||
m_items.Clear();
|
||||
view->Remove( &m_items );
|
||||
controls->ShowCursor( false );
|
||||
|
@ -173,17 +176,43 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
void MOVE_TOOL::viewGroupAdd( BOARD_ITEM* aItem, KiGfx::VIEW_GROUP* aGroup )
|
||||
void MOVE_TOOL::viewGroupAdd( BOARD_ITEM* aItem, VIEW_GROUP* aGroup )
|
||||
{
|
||||
// Save the state of the selected items, in case it has to be restored
|
||||
ITEM_STATE state;
|
||||
state.Save( aItem );
|
||||
m_itemsState.push_back( state );
|
||||
// Modules are treated in a special way - when they are moved, we have to
|
||||
// move all the parts that make the module, not the module itself
|
||||
if( aItem->Type() == PCB_MODULE_T )
|
||||
{
|
||||
MODULE* module = static_cast<MODULE*>( aItem );
|
||||
|
||||
// Add everything that belongs to the module (besides the module itself)
|
||||
for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
|
||||
viewGroupAdd( pad, &m_items );
|
||||
|
||||
for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing;
|
||||
drawing = drawing->Next() )
|
||||
viewGroupAdd( drawing, &m_items );
|
||||
|
||||
viewGroupAdd( &module->Reference(), &m_items );
|
||||
viewGroupAdd( &module->Value(), &m_items );
|
||||
}
|
||||
|
||||
// Add items to the VIEW_GROUP, so they will be displayed on the overlay
|
||||
// while dragging
|
||||
aGroup->Add( aItem );
|
||||
|
||||
// Set the original item as invisible
|
||||
aItem->ViewSetVisible( false );
|
||||
}
|
||||
|
||||
|
||||
void MOVE_TOOL::vgSetVisibility( VIEW_GROUP* aGroup, bool aVisible ) const
|
||||
{
|
||||
std::set<VIEW_ITEM*>::const_iterator it, it_end;
|
||||
for( it = aGroup->Begin(), it_end = aGroup->End(); it != it_end; ++it )
|
||||
(*it)->ViewSetVisible( aVisible );
|
||||
}
|
||||
|
||||
|
||||
void MOVE_TOOL::vgUpdate( VIEW_GROUP* aGroup, VIEW_ITEM::ViewUpdateFlags aFlags ) const
|
||||
{
|
||||
std::set<VIEW_ITEM*>::const_iterator it, it_end;
|
||||
for( it = aGroup->Begin(), it_end = aGroup->End(); it != it_end; ++it )
|
||||
(*it)->ViewUpdate( aFlags );
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* @author @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
* @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
|
||||
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <math/vector2d.h>
|
||||
#include <tool/tool_interactive.h>
|
||||
#include <tool/item_state.h>
|
||||
#include <view/view_group.h>
|
||||
|
||||
class BOARD_ITEM;
|
||||
|
@ -40,7 +41,8 @@ class VIEW_GROUP;
|
|||
/**
|
||||
* Class MOVE_TOOL
|
||||
*
|
||||
* Our sample move tool. Allows to move items selected by pcbnew.InteractiveSelection.
|
||||
* Our sample move tool. Allows to move, rotate and flip items selected by
|
||||
* pcbnew.InteractiveSelection tool.
|
||||
*/
|
||||
|
||||
class MOVE_TOOL : public TOOL_INTERACTIVE
|
||||
|
@ -67,55 +69,32 @@ private:
|
|||
/// Adds an item to the VIEW_GROUP that holds all moved items and displays them on the overlay
|
||||
void viewGroupAdd( BOARD_ITEM* aItem, KiGfx::VIEW_GROUP* aGroup );
|
||||
|
||||
/// Structure for (re)storing BOARD_ITEM state
|
||||
typedef struct
|
||||
{
|
||||
BOARD_ITEM* item; /// Pointer to the item
|
||||
VECTOR2D position; /// Original position of the item
|
||||
bool visible; /// Original visibility flag
|
||||
/// Changes visibility settings for items stored in a VIEW_GROUP
|
||||
void vgSetVisibility( KiGfx::VIEW_GROUP* aGroup, bool aVisible ) const;
|
||||
|
||||
void Save( BOARD_ITEM* aItem )
|
||||
{
|
||||
wxPoint pos = aItem->GetPosition();
|
||||
/// Updates items stored in a VIEW_GROUP with selected update flag
|
||||
void vgUpdate( KiGfx::VIEW_GROUP* aGroup, KiGfx::VIEW_ITEM::ViewUpdateFlags aFlags ) const;
|
||||
|
||||
item = aItem;
|
||||
position.x = pos.x;
|
||||
position.y = pos.y;
|
||||
visible = aItem->ViewIsVisible();
|
||||
}
|
||||
|
||||
void RestorePosition()
|
||||
{
|
||||
wxPoint curPosition = item->GetPosition();
|
||||
item->Move( wxPoint( position.x - curPosition.x, position.y - curPosition.y ) );
|
||||
}
|
||||
|
||||
void RestoreVisibility()
|
||||
{
|
||||
item->ViewSetVisible( visible );
|
||||
}
|
||||
|
||||
void Restore()
|
||||
{
|
||||
RestorePosition();
|
||||
RestoreVisibility();
|
||||
}
|
||||
} ITEM_STATE;
|
||||
/// Saves the state of items and allows to restore them
|
||||
ITEM_STATE m_state;
|
||||
|
||||
/// Selection tool used for obtaining selected items
|
||||
SELECTION_TOOL* m_selectionTool;
|
||||
|
||||
/// Stores the initial state of moved items (so it is possible to rollback changes)
|
||||
std::deque<ITEM_STATE> m_itemsState;
|
||||
|
||||
/// Set of selected items (obtained from pcbnew.
|
||||
/// Set of selected items (obtained from pcbnew.InteractiveSelection tool)
|
||||
std::set<BOARD_ITEM*> m_selection;
|
||||
|
||||
/// VIEW_GROUP that helds currently moved items
|
||||
KiGfx::VIEW_GROUP m_items;
|
||||
|
||||
/// Register hotkey fot activation of the move tool
|
||||
/// Register hotkey for activation of the move tool
|
||||
TOOL_ACTION m_activate;
|
||||
|
||||
/// Register hotkey for rotation of selected objects
|
||||
TOOL_ACTION m_rotate;
|
||||
|
||||
/// Register hotkey for flipping of selected objects
|
||||
TOOL_ACTION m_flip;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue