Commit c4ad58f2 authored by Maciej Suminski's avatar Maciej Suminski

Added rotate & flip to the pcbnew.InteractiveMove tool, hotkeys for them and...

Added rotate & flip to the pcbnew.InteractiveMove tool, hotkeys for them and undoing all the  operations on cancelling the tool.
parent 1de8eba4
...@@ -36,7 +36,9 @@ using boost::optional; ...@@ -36,7 +36,9 @@ using boost::optional;
MOVE_TOOL::MOVE_TOOL() : MOVE_TOOL::MOVE_TOOL() :
TOOL_INTERACTIVE( "pcbnew.InteractiveMove" ), m_selectionTool( NULL ), 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() ...@@ -48,8 +50,6 @@ MOVE_TOOL::~MOVE_TOOL()
void MOVE_TOOL::Reset() void MOVE_TOOL::Reset()
{ {
m_toolMgr->RegisterAction( &m_activate );
// Find the selection tool, so they can cooperate // Find the selection tool, so they can cooperate
TOOL_BASE* selectionTool = m_toolMgr->FindTool( std::string( "pcbnew.InteractiveSelection" ) ); TOOL_BASE* selectionTool = m_toolMgr->FindTool( std::string( "pcbnew.InteractiveSelection" ) );
...@@ -63,6 +63,11 @@ void MOVE_TOOL::Reset() ...@@ -63,6 +63,11 @@ void MOVE_TOOL::Reset()
return; 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") // the tool launches upon reception of action event ("pcbnew.InteractiveMove")
Go( &MOVE_TOOL::Main, m_activate.GetEvent() ); Go( &MOVE_TOOL::Main, m_activate.GetEvent() );
} }
...@@ -90,17 +95,30 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -90,17 +95,30 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
break; // Finish 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 ) if( dragging )
{ {
// Dragging is already active // Drag items to the current cursor position
VECTOR2D movement = ( evt->Position() - dragPosition ); VECTOR2D movement = ( evt->Position() - dragPosition );
std::set<BOARD_ITEM*>::iterator it, it_end; m_state.Move( movement );
// 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 ) );
} }
else else
{ {
...@@ -112,28 +130,17 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -112,28 +130,17 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
std::set<BOARD_ITEM*>::iterator it; std::set<BOARD_ITEM*>::iterator it;
for( it = m_selection.begin(); it != m_selection.end(); ++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 // Gather all selected items into one VIEW_GROUP
viewGroupAdd( *it, &m_items ); 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; dragging = true;
} }
...@@ -144,25 +151,21 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -144,25 +151,21 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
break; // Finish break; // Finish
} }
// Clean-up after movement // Restore visibility of the original items
std::deque<ITEM_STATE>::iterator it, it_end; vgSetVisibility( &m_items, true );
// Movement has to be rollbacked, so restore the previous state of items
if( restore ) if( restore )
{ {
// Movement has to be rollbacked, so restore the previous state of items vgUpdate( &m_items, VIEW_ITEM::APPEARANCE );
for( it = m_itemsState.begin(), it_end = m_itemsState.end(); it != it_end; ++it ) m_state.RestoreAll();
it->Restore();
} }
else else
{ {
// Apply changes vgUpdate( &m_items, m_state.GetUpdateFlag() );
for( it = m_itemsState.begin(), it_end = m_itemsState.end(); it != it_end; ++it ) m_state.Apply();
{
it->RestoreVisibility();
it->item->ViewUpdate( VIEW_ITEM::GEOMETRY );
}
} }
m_itemsState.clear();
m_items.Clear(); m_items.Clear();
view->Remove( &m_items ); view->Remove( &m_items );
controls->ShowCursor( false ); controls->ShowCursor( false );
...@@ -173,17 +176,43 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -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 // Modules are treated in a special way - when they are moved, we have to
ITEM_STATE state; // move all the parts that make the module, not the module itself
state.Save( aItem ); if( aItem->Type() == PCB_MODULE_T )
m_itemsState.push_back( state ); {
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 // Add items to the VIEW_GROUP, so they will be displayed on the overlay
// while dragging // while dragging
aGroup->Add( aItem ); aGroup->Add( aItem );
}
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 );
}
// Set the original item as invisible
aItem->ViewSetVisible( false ); 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 @@ ...@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 CERN * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <math/vector2d.h> #include <math/vector2d.h>
#include <tool/tool_interactive.h> #include <tool/tool_interactive.h>
#include <tool/item_state.h>
#include <view/view_group.h> #include <view/view_group.h>
class BOARD_ITEM; class BOARD_ITEM;
...@@ -40,7 +41,8 @@ class VIEW_GROUP; ...@@ -40,7 +41,8 @@ class VIEW_GROUP;
/** /**
* Class MOVE_TOOL * 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 class MOVE_TOOL : public TOOL_INTERACTIVE
...@@ -67,55 +69,32 @@ private: ...@@ -67,55 +69,32 @@ private:
/// Adds an item to the VIEW_GROUP that holds all moved items and displays them on the overlay /// 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 ); void viewGroupAdd( BOARD_ITEM* aItem, KiGfx::VIEW_GROUP* aGroup );
/// Structure for (re)storing BOARD_ITEM state /// Changes visibility settings for items stored in a VIEW_GROUP
typedef struct void vgSetVisibility( KiGfx::VIEW_GROUP* aGroup, bool aVisible ) const;
{
BOARD_ITEM* item; /// Pointer to the item /// Updates items stored in a VIEW_GROUP with selected update flag
VECTOR2D position; /// Original position of the item void vgUpdate( KiGfx::VIEW_GROUP* aGroup, KiGfx::VIEW_ITEM::ViewUpdateFlags aFlags ) const;
bool visible; /// Original visibility flag
/// Saves the state of items and allows to restore them
void Save( BOARD_ITEM* aItem ) ITEM_STATE m_state;
{
wxPoint pos = aItem->GetPosition();
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;
/// Selection tool used for obtaining selected items /// Selection tool used for obtaining selected items
SELECTION_TOOL* m_selectionTool; SELECTION_TOOL* m_selectionTool;
/// Stores the initial state of moved items (so it is possible to rollback changes) /// Set of selected items (obtained from pcbnew.InteractiveSelection tool)
std::deque<ITEM_STATE> m_itemsState;
/// Set of selected items (obtained from pcbnew.
std::set<BOARD_ITEM*> m_selection; std::set<BOARD_ITEM*> m_selection;
/// VIEW_GROUP that helds currently moved items /// VIEW_GROUP that helds currently moved items
KiGfx::VIEW_GROUP m_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; 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 #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment