From 781008bfa5ad9ca16bd567bb7d887ff3f9727f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Tue, 31 Oct 2017 12:01:59 +0100 Subject: [PATCH] refactoring: allow to run TOOL_MANAGER and SELECTION_TOOL without a host wxFrame --- common/tool/action_manager.cpp | 8 +- common/tool/tool_dispatcher.cpp | 12 ++- common/tool/tool_manager.cpp | 16 ++- pcbnew/tools/pcb_tool.cpp | 10 ++ pcbnew/tools/pcb_tool.h | 5 + pcbnew/tools/selection.cpp | 175 ++++++++++++++++++++++++++++++++ pcbnew/tools/selection_tool.cpp | 167 +++++++----------------------- 7 files changed, 251 insertions(+), 142 deletions(-) create mode 100644 pcbnew/tools/selection.cpp diff --git a/common/tool/action_manager.cpp b/common/tool/action_manager.cpp index 45c95cbec5..35d190fe0e 100644 --- a/common/tool/action_manager.cpp +++ b/common/tool/action_manager.cpp @@ -233,8 +233,12 @@ int ACTION_MANAGER::processHotKey( TOOL_ACTION* aAction ) if( ( hotkey & TOOL_ACTION::LEGACY_HK ) ) { hotkey = hotkey & ~TOOL_ACTION::LEGACY_HK; // it leaves only HK_xxx identifier - EDA_DRAW_FRAME* frame = static_cast( m_toolMgr->GetEditFrame() ); - EDA_HOTKEY* hk_desc = frame->GetHotKeyDescription( hotkey ); + + auto frame = dynamic_cast( m_toolMgr->GetEditFrame() ); + EDA_HOTKEY* hk_desc = nullptr; + + if( frame ) + hk_desc = frame->GetHotKeyDescription( hotkey ); if( hk_desc ) { diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp index f45fb01863..f27cc93c14 100644 --- a/common/tool/tool_dispatcher.cpp +++ b/common/tool/tool_dispatcher.cpp @@ -146,7 +146,7 @@ void TOOL_DISPATCHER::ResetState() KIGFX::VIEW* TOOL_DISPATCHER::getView() { - return static_cast( m_toolMgr->GetEditFrame() )->GetGalCanvas()->GetView(); + return m_toolMgr->GetView(); } @@ -451,7 +451,11 @@ void TOOL_DISPATCHER::updateUI() { // TODO I don't feel it is the right place for updating UI, // but at the moment I cannot think of a better one.. - EDA_DRAW_FRAME* frame = static_cast( m_toolMgr->GetEditFrame() ); - frame->UpdateStatusBar(); - //frame->UpdateMsgPanel(); + + auto frame = dynamic_cast( m_toolMgr->GetEditFrame() ); + if( frame ) + { + frame->UpdateStatusBar(); + //frame->UpdateMsgPanel(); + } } diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index 9c869eddec..b8933bc4bb 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -674,7 +674,14 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) // Run update handlers on the created copy menu->UpdateAll(); m_menuActive = true; - GetEditFrame()->PopupMenu( menu.get() ); + + auto frame = dynamic_cast( m_editFrame ); + + if( frame ) + { + frame->PopupMenu( menu.get() ); + } + m_menuActive = false; m_viewControls->WarpCursor( cursor, true, false ); @@ -739,8 +746,11 @@ bool TOOL_MANAGER::ProcessEvent( const TOOL_EVENT& aEvent ) if( m_view->IsDirty() ) { - EDA_DRAW_FRAME* f = static_cast( GetEditFrame() ); - f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER. + auto f = dynamic_cast( GetEditFrame() ); + if( f ) + { + f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER. + } } return hotkey_handled; diff --git a/pcbnew/tools/pcb_tool.cpp b/pcbnew/tools/pcb_tool.cpp index cc0bf26372..26640cf31b 100644 --- a/pcbnew/tools/pcb_tool.cpp +++ b/pcbnew/tools/pcb_tool.cpp @@ -195,6 +195,16 @@ void PCB_TOOL::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer, view()->Remove( &preview ); } +void PCB_TOOL::Reset( RESET_REASON aReason ) +{ + +} + +void PCB_TOOL::setTransitions() +{ + +} + PCB_DISPLAY_OPTIONS* PCB_TOOL::displayOptions() const { return static_cast( frame()->GetDisplayOptions() ); diff --git a/pcbnew/tools/pcb_tool.h b/pcbnew/tools/pcb_tool.h index d09781da2a..5306214194 100644 --- a/pcbnew/tools/pcb_tool.h +++ b/pcbnew/tools/pcb_tool.h @@ -79,6 +79,8 @@ public: virtual ~PCB_TOOL() {}; + virtual void Reset( RESET_REASON aReason ) override; + /** * Function SetEditModules() * @@ -123,6 +125,9 @@ protected: const wxString& aCommitMessage, int aOptions = IPO_ROTATE | IPO_FLIP | IPO_REPEAT ); + virtual void setTransitions() override; + + KIGFX::PCB_VIEW* view() const { return static_cast( getView() ); } KIGFX::VIEW_CONTROLS* controls() const { return getViewControls(); } PCB_EDIT_FRAME* frame() const { return getEditFrame(); } diff --git a/pcbnew/tools/selection.cpp b/pcbnew/tools/selection.cpp new file mode 100644 index 0000000000..17cd62ef05 --- /dev/null +++ b/pcbnew/tools/selection.cpp @@ -0,0 +1,175 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013-2017 CERN + * @author Tomasz Wlostowski + * @author Maciej Suminski + * Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * 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 +using namespace std::placeholders; + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "selection_tool.h" +#include "pcb_bright_box.h" +#include "pcb_actions.h" + +#include "kicad_plugin.h" + +// TODO(JE) Only works for BOARD_ITEM +VECTOR2I SELECTION::GetPosition() const +{ + return static_cast( GetBoundingBox().GetPosition() ); +} + + +VECTOR2I SELECTION::GetCenter() const +{ + return static_cast( GetBoundingBox().Centre() ); +} + + +EDA_RECT SELECTION::GetBoundingBox() const +{ + EDA_RECT bbox; + + bbox = Front()->GetBoundingBox(); + auto i = m_items.begin(); + ++i; + + for( ; i != m_items.end(); ++i ) + { + bbox.Merge( (*i)->GetBoundingBox() ); + } + + return bbox; +} + + +EDA_ITEM* SELECTION::GetTopLeftItem( bool onlyModules ) const +{ + BOARD_ITEM* topLeftItem = nullptr; + BOARD_ITEM* currentItem; + + wxPoint pnt; + + // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection + for( auto item : m_items ) + { + currentItem = static_cast( item ); + pnt = currentItem->GetPosition(); + + if( ( currentItem->Type() != PCB_MODULE_T ) && onlyModules ) + { + continue; + } + else + { + if( topLeftItem == nullptr ) + { + topLeftItem = currentItem; + } + else if( ( pnt.x < topLeftItem->GetPosition().x ) || + ( ( topLeftItem->GetPosition().x == pnt.x ) && + ( pnt.y < topLeftItem->GetPosition().y ) ) ) + { + topLeftItem = currentItem; + } + } + } + + return static_cast( topLeftItem ); +} + + +EDA_ITEM* SELECTION::GetTopLeftModule() const +{ + return GetTopLeftItem( true ); +} + + +const BOX2I SELECTION::ViewBBox() const +{ + BOX2I r; + r.SetMaximum(); + return r; + EDA_RECT eda_bbox; + + if( Size() == 1 ) + { + eda_bbox = Front()->GetBoundingBox(); + } + else if( Size() > 1 ) + { + eda_bbox = Front()->GetBoundingBox(); + auto i = m_items.begin(); + ++i; + + for( ; i != m_items.end(); ++i ) + { + eda_bbox.Merge( (*i)->GetBoundingBox() ); + } + } + + return BOX2I( eda_bbox.GetOrigin(), eda_bbox.GetSize() ); +} + + +const KIGFX::VIEW_GROUP::ITEMS SELECTION::updateDrawList() const +{ + std::vector items; + + for( auto item : m_items ) + { + items.push_back( item ); + + if( item->Type() == PCB_MODULE_T ) + { + MODULE* module = static_cast( item ); + module->RunOnChildren( [&] ( BOARD_ITEM* bitem ) { items.push_back( bitem ); } ); + } + } + + return items; +} diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index d31ac66335..3247e5cc95 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -202,7 +202,12 @@ bool SELECTION_TOOL::Init() // only show separator if there is a Select menu to show above it menu.AddSeparator( SELECTION_CONDITIONS::NotEmpty, 1000 ); - m_menu.AddStandardSubMenus( *getEditFrame() ); + auto frame = getEditFrame(); + + if( frame ) + { + m_menu.AddStandardSubMenus( *frame ); + } return true; } @@ -226,8 +231,8 @@ void SELECTION_TOOL::Reset( RESET_REASON aReason ) clearSelection(); // Reinsert the VIEW_GROUP, in case it was removed from the VIEW - getView()->Remove( &m_selection ); - getView()->Add( &m_selection ); + view()->Remove( &m_selection ); + view()->Add( &m_selection ); } @@ -399,7 +404,10 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) } } - m_frame->GetGalCanvas()->ForceRefresh(); + if( m_frame ) + { + m_frame->GetGalCanvas()->ForceRefresh(); + } } @@ -574,10 +582,13 @@ bool SELECTION_TOOL::selectMultiple() } } - if( m_selection.Size() == 1 ) - m_frame->SetCurItem( static_cast( m_selection.Front() ) ); - else - m_frame->SetCurItem( NULL ); + if( m_frame ) + { + if( m_selection.Size() == 1 ) + m_frame->SetCurItem( static_cast( m_selection.Front() ) ); + else + m_frame->SetCurItem( NULL ); + } // Inform other potentially interested tools if( !m_selection.Empty() ) @@ -1539,16 +1550,18 @@ void SELECTION_TOOL::select( BOARD_ITEM* aItem ) m_selection.Add( aItem ); selectVisually( aItem ); - - if( m_selection.Size() == 1 ) + if( m_frame ) { - // Set as the current item, so the information about selection is displayed - m_frame->SetCurItem( aItem, true ); - } - else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be - { // called for every next selected item - // If multiple items are selected, do not show the information about the selected item - m_frame->SetCurItem( NULL, true ); + if( m_selection.Size() == 1 ) + { + // Set as the current item, so the information about selection is displayed + m_frame->SetCurItem( aItem, true ); + } + else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be + { // called for every next selected item + // If multiple items are selected, do not show the information about the selected item + m_frame->SetCurItem( NULL, true ); + } } } @@ -1563,7 +1576,10 @@ void SELECTION_TOOL::unselect( BOARD_ITEM* aItem ) if( m_selection.Empty() ) { - m_frame->SetCurItem( NULL ); + if( m_frame ) + { + m_frame->SetCurItem( NULL ); + } m_locked = true; } } @@ -1996,121 +2012,6 @@ bool SELECTION_TOOL::SanitizeSelection() } -// TODO(JE) Only works for BOARD_ITEM -VECTOR2I SELECTION::GetPosition() const -{ - return static_cast( GetBoundingBox().GetPosition() ); -} - - -VECTOR2I SELECTION::GetCenter() const -{ - return static_cast( GetBoundingBox().Centre() ); -} - - -EDA_RECT SELECTION::GetBoundingBox() const -{ - EDA_RECT bbox; - - bbox = Front()->GetBoundingBox(); - auto i = m_items.begin(); - ++i; - - for( ; i != m_items.end(); ++i ) - { - bbox.Merge( (*i)->GetBoundingBox() ); - } - - return bbox; -} - - -EDA_ITEM* SELECTION::GetTopLeftItem( bool onlyModules ) const -{ - BOARD_ITEM* topLeftItem = nullptr; - BOARD_ITEM* currentItem; - - wxPoint pnt; - - // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection - for( auto item : m_items ) - { - currentItem = static_cast( item ); - pnt = currentItem->GetPosition(); - - if( ( currentItem->Type() != PCB_MODULE_T ) && onlyModules ) - { - continue; - } - else - { - if( topLeftItem == nullptr ) - { - topLeftItem = currentItem; - } - else if( ( pnt.x < topLeftItem->GetPosition().x ) || - ( ( topLeftItem->GetPosition().x == pnt.x ) && - ( pnt.y < topLeftItem->GetPosition().y ) ) ) - { - topLeftItem = currentItem; - } - } - } - - return static_cast( topLeftItem ); -} - - -EDA_ITEM* SELECTION::GetTopLeftModule() const -{ - return GetTopLeftItem( true ); -} - - -const BOX2I SELECTION::ViewBBox() const -{ - EDA_RECT eda_bbox; - - if( Size() == 1 ) - { - eda_bbox = Front()->GetBoundingBox(); - } - else if( Size() > 1 ) - { - eda_bbox = Front()->GetBoundingBox(); - auto i = m_items.begin(); - ++i; - - for( ; i != m_items.end(); ++i ) - { - eda_bbox.Merge( (*i)->GetBoundingBox() ); - } - } - - return BOX2I( eda_bbox.GetOrigin(), eda_bbox.GetSize() ); -} - - -const KIGFX::VIEW_GROUP::ITEMS SELECTION::updateDrawList() const -{ - std::vector items; - - for( auto item : m_items ) - { - items.push_back( item ); - - if( item->Type() == PCB_MODULE_T ) - { - MODULE* module = static_cast( item ); - module->RunOnChildren( [&] ( BOARD_ITEM* bitem ) { items.push_back( bitem ); } ); - } - } - - return items; -} - - const TOOL_EVENT SELECTION_TOOL::SelectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.selected" ); const TOOL_EVENT SELECTION_TOOL::UnselectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.unselected" ); const TOOL_EVENT SELECTION_TOOL::ClearedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.cleared" );