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;
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 );
}
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 @@
* 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
void Save( BOARD_ITEM* aItem )
{
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;
/// Changes visibility settings for items stored in a VIEW_GROUP
void vgSetVisibility( KiGfx::VIEW_GROUP* aGroup, bool aVisible ) const;
/// Updates items stored in a VIEW_GROUP with selected update flag
void vgUpdate( KiGfx::VIEW_GROUP* aGroup, KiGfx::VIEW_ITEM::ViewUpdateFlags aFlags ) const;
/// 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
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