diff --git a/common/view/view_group.cpp b/common/view/view_group.cpp index 3b740e01b5..d4cc2472bc 100644 --- a/common/view/view_group.cpp +++ b/common/view/view_group.cpp @@ -56,21 +56,18 @@ VIEW_GROUP::~VIEW_GROUP() void VIEW_GROUP::Add( VIEW_ITEM* aItem ) { m_items.insert( aItem ); - updateBbox(); } void VIEW_GROUP::Remove( VIEW_ITEM* aItem ) { m_items.erase( aItem ); - updateBbox(); } void VIEW_GROUP::Clear() { m_items.clear(); - updateBbox(); } @@ -121,15 +118,6 @@ void VIEW_GROUP::ViewGetLayers( int aLayers[], int& aCount ) const } -/*void VIEW_GROUP::ViewUpdate( int aUpdateFlags, bool aForceImmediateRedraw ) -{ - BOOST_FOREACH( VIEW_ITEM* item, m_items ) - { - item->ViewUpdate( aUpdateFlags, aForceImmediateRedraw ); - } -}*/ - - void VIEW_GROUP::updateBbox() { // Save the used VIEW, as it used nulled during Remove() diff --git a/include/view/view_group.h b/include/view/view_group.h index 4439234e0d..ab48e80028 100644 --- a/include/view/view_group.h +++ b/include/view/view_group.h @@ -120,9 +120,6 @@ public: */ virtual void ViewGetLayers( int aLayers[], int& aCount ) const; - /// @copydoc VIEW_ITEM::ViewUpdate() - virtual void ViewUpdate( int aUpdateFlags, bool aForceImmediateRedraw ); - /** * Function SetLayer() * Sets layer used to draw the group. diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 79b78b9b1a..d86f9dbf54 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -219,6 +219,7 @@ set(PCBNEW_CLASS_SRCS tools/selection_tool.cpp tools/selection_area.cpp + tools/move_tool.cpp tools/pcb_tools.cpp ) diff --git a/pcbnew/tools/move_tool.cpp b/pcbnew/tools/move_tool.cpp new file mode 100644 index 0000000000..54e5afe7af --- /dev/null +++ b/pcbnew/tools/move_tool.cpp @@ -0,0 +1,185 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Maciej Suminski + * + * 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 + */ + +#include +#include +#include +#include + +#include "selection_tool.h" +#include "move_tool.h" + +using namespace KiGfx; +using boost::optional; + +MOVE_TOOL::MOVE_TOOL() : + TOOL_INTERACTIVE( "pcbnew.InteractiveMove" ), m_selectionTool( NULL ) +{ +} + + +MOVE_TOOL::~MOVE_TOOL() +{ +} + + +void MOVE_TOOL::Reset() +{ + // Find the selection tool, so they can cooperate + TOOL_BASE* selectionTool = m_toolMgr->FindTool( std::string( "pcbnew.InteractiveSelection" ) ); + + if( selectionTool ) + { + m_selectionTool = static_cast( selectionTool ); + } + else + { + wxLogError( "pcbnew.InteractiveSelection tool is not available" ); + return; + } + + // the tool launches upon reception of activate ("pcbnew.InteractiveMove") + Go( &MOVE_TOOL::Main, TOOL_EVENT( TC_Command, TA_ActivateTool, GetName() ) ); //"pcbnew.InteractiveMove")); +} + + +int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) +{ + VECTOR2D dragPosition; + bool dragging = false; + bool restore = false; + VIEW* view = m_toolMgr->GetView(); + std::set selection; + VIEW_GROUP items( view ); + + view->Add( &items ); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + if( evt->IsCancel() ) + { + restore = true; + m_toolMgr->PassEvent(); + break; // Finish + } + + if( evt->IsDrag( MB_Left ) ) + { + if( dragging ) + { + // Dragging is alre + VECTOR2D movement = ( evt->Position() - dragPosition ); + + std::set::iterator it, it_end; + for( it = selection.begin(), it_end = selection.end(); it != it_end; ++it ) + { + (*it)->Move( wxPoint( movement.x, movement.y ) ); + } + items.ViewUpdate( VIEW_ITEM::GEOMETRY ); + } + else + { + // Begin dragging + selection = m_selectionTool->GetSelection(); + + std::set::iterator it; + for( it = selection.begin(); it != selection.end(); ++it ) + { + viewGroupAdd( *it, &items ); + + // but if a MODULE was selected, then we need to redraw all of it's parts + if( (*it)->Type() == PCB_MODULE_T ) + { + MODULE* module = static_cast( *it ); + + // Move everything that belongs to the module + for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) + viewGroupAdd( pad, &items ); + + for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing; + drawing = drawing->Next() ) + viewGroupAdd( drawing, &items ); + + viewGroupAdd( &module->Reference(), &items ); + viewGroupAdd( &module->Value(), &items ); + } + + } + items.ViewUpdate( VIEW_ITEM::GEOMETRY ); + + dragging = true; + } + + dragPosition = evt->Position(); + } + else if( evt->Category() == TC_Mouse ) // Filter out other events + { + if( dragging ) + { + break; // Finish + } + } + } + + // Clean-up after movement + std::deque::iterator it, it_end; + if( restore ) + { + // Movement has to be rollbacked, so restore previous state of items + for( it = m_itemsState.begin(), it_end = m_itemsState.end(); it != it_end; ++it ) + it->Restore(); + } + 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 ); + } + } + + m_itemsState.clear(); + items.Clear(); + view->Remove( &items ); + + return 0; +} + + +void MOVE_TOOL::viewGroupAdd( BOARD_ITEM* aItem, KiGfx::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 ); + + // 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 ); +} diff --git a/pcbnew/tools/move_tool.h b/pcbnew/tools/move_tool.h new file mode 100644 index 0000000000..1022230a69 --- /dev/null +++ b/pcbnew/tools/move_tool.h @@ -0,0 +1,113 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author @author Maciej Suminski + * + * 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 __MOVE_TOOL_H +#define __MOVE_TOOL_H + +#include +#include + +class BOARD_ITEM; +class SELECTION_TOOL; + +namespace KiGfx +{ +class VIEW_GROUP; +} + +/** + * Class MOVE_TOOL + * /// TODO DOCS!! + * Our sample move tool: currently supports: + * - pick single objects (click LMB) + * - add objects to existing move (Shift+LMB) + * - draw move box (drag LMB) + * + * WORK IN PROGRESS. CONSIDER AS A DEMO! + */ + +class MOVE_TOOL : public TOOL_INTERACTIVE +{ +public: + MOVE_TOOL(); + ~MOVE_TOOL(); + + /** + * Function Reset() + * + * Resets the tool and initializes it. + */ + void Reset(); + + /** + * Function Main() + * + * Main loop in which events are handled. + */ + int Main( TOOL_EVENT& aEvent ); + +private: + 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() + { + item->SetPosition( wxPoint( position.x, position.y ) ); + } + + void RestoreVisibility() + { + item->ViewSetVisible( visible ); + } + + void Restore() + { + RestorePosition(); + RestoreVisibility(); + } + } ITEM_STATE; + + /// Selection tool used for obtaining selected items + SELECTION_TOOL* m_selectionTool; + + std::deque m_itemsState; +}; + +#endif diff --git a/pcbnew/tools/pcb_tools.cpp b/pcbnew/tools/pcb_tools.cpp index 4ee70cde94..0dc342a17d 100644 --- a/pcbnew/tools/pcb_tools.cpp +++ b/pcbnew/tools/pcb_tools.cpp @@ -35,16 +35,18 @@ #include #include "selection_tool.h" +#include "move_tool.h" void PCB_EDIT_FRAME::setupTools() { - // create the manager and dispatcher. Route draw panel events to the dispatcher. + // Create the manager and dispatcher. Route draw panel events to the dispatcher m_toolManager = new TOOL_MANAGER; m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, this ); m_galCanvas->SetEventDispatcher( m_toolDispatcher ); - // register our selection tool. + // Register tools m_toolManager->RegisterTool( new SELECTION_TOOL ); + m_toolManager->RegisterTool( new MOVE_TOOL ); }