refactoring: allow to run TOOL_MANAGER and SELECTION_TOOL without a host wxFrame

This commit is contained in:
Tomasz Włostowski 2017-10-31 12:01:59 +01:00
parent 06f3b35255
commit 781008bfa5
7 changed files with 251 additions and 142 deletions

View File

@ -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<EDA_DRAW_FRAME*>( m_toolMgr->GetEditFrame() );
EDA_HOTKEY* hk_desc = frame->GetHotKeyDescription( hotkey );
auto frame = dynamic_cast<EDA_DRAW_FRAME*>( m_toolMgr->GetEditFrame() );
EDA_HOTKEY* hk_desc = nullptr;
if( frame )
hk_desc = frame->GetHotKeyDescription( hotkey );
if( hk_desc )
{

View File

@ -146,7 +146,7 @@ void TOOL_DISPATCHER::ResetState()
KIGFX::VIEW* TOOL_DISPATCHER::getView()
{
return static_cast<EDA_DRAW_FRAME*>( 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<EDA_DRAW_FRAME*>( m_toolMgr->GetEditFrame() );
frame->UpdateStatusBar();
//frame->UpdateMsgPanel();
auto frame = dynamic_cast<EDA_DRAW_FRAME*>( m_toolMgr->GetEditFrame() );
if( frame )
{
frame->UpdateStatusBar();
//frame->UpdateMsgPanel();
}
}

View File

@ -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<wxFrame*>( 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<EDA_DRAW_FRAME*>( GetEditFrame() );
f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER.
auto f = dynamic_cast<EDA_DRAW_FRAME*>( GetEditFrame() );
if( f )
{
f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER.
}
}
return hotkey_handled;

View File

@ -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<PCB_DISPLAY_OPTIONS*>( frame()->GetDisplayOptions() );

View File

@ -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<KIGFX::PCB_VIEW*>( getView() ); }
KIGFX::VIEW_CONTROLS* controls() const { return getViewControls(); }
PCB_EDIT_FRAME* frame() const { return getEditFrame<PCB_EDIT_FRAME>(); }

175
pcbnew/tools/selection.cpp Normal file
View File

@ -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 <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
* 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 <limits>
#include <functional>
using namespace std::placeholders;
#include <class_board.h>
#include <class_board_item.h>
#include <class_track.h>
#include <class_module.h>
#include <class_pcb_text.h>
#include <class_drawsegment.h>
#include <class_zone.h>
#include <wxPcbStruct.h>
#include <class_draw_panel_gal.h>
#include <view/view_controls.h>
#include <view/view_group.h>
#include <preview_items/selection_area.h>
#include <painter.h>
#include <bitmaps.h>
#include <hotkeys.h>
#include <tool/tool_event.h>
#include <tool/tool_manager.h>
#include <connectivity.h>
#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<VECTOR2I>( GetBoundingBox().GetPosition() );
}
VECTOR2I SELECTION::GetCenter() const
{
return static_cast<VECTOR2I>( 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<BOARD_ITEM*>( 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<EDA_ITEM*>( 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<VIEW_ITEM*> items;
for( auto item : m_items )
{
items.push_back( item );
if( item->Type() == PCB_MODULE_T )
{
MODULE* module = static_cast<MODULE*>( item );
module->RunOnChildren( [&] ( BOARD_ITEM* bitem ) { items.push_back( bitem ); } );
}
}
return items;
}

View File

@ -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<PCB_BASE_FRAME>() );
auto frame = getEditFrame<PCB_BASE_FRAME>();
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<BOARD_ITEM*>( m_selection.Front() ) );
else
m_frame->SetCurItem( NULL );
if( m_frame )
{
if( m_selection.Size() == 1 )
m_frame->SetCurItem( static_cast<BOARD_ITEM*>( 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<VECTOR2I>( GetBoundingBox().GetPosition() );
}
VECTOR2I SELECTION::GetCenter() const
{
return static_cast<VECTOR2I>( 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<BOARD_ITEM*>( 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<EDA_ITEM*>( 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<VIEW_ITEM*> items;
for( auto item : m_items )
{
items.push_back( item );
if( item->Type() == PCB_MODULE_T )
{
MODULE* module = static_cast<MODULE*>( 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" );