Refactor SELECTION, SELECTION_CONDITIONS, and context menus to common

SELECTION now holds EDA_ITEMs not BOARD_ITEMs so various places had to
change to casting the selected items to BOARD_ITEMs.

Fixed compilation warnings on clang (Tom)
This commit is contained in:
Jon Evans 2017-02-27 22:04:44 -05:00 committed by Tomasz Włostowski
parent 0afb249447
commit fd4e2b042c
26 changed files with 434 additions and 306 deletions

View File

@ -301,6 +301,11 @@ set( COMMON_SRCS
tool/context_menu.cpp tool/context_menu.cpp
tool/actions.cpp tool/actions.cpp
tool/common_tools.cpp tool/common_tools.cpp
tool/grid_menu.cpp
tool/zoom_menu.cpp
tool/tool_menu.cpp
tool/conditional_menu.cpp
tool/selection_conditions.cpp
geometry/seg.cpp geometry/seg.cpp
geometry/shape.cpp geometry/shape.cpp

View File

@ -22,7 +22,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "conditional_menu.h" #include <tool/conditional_menu.h>
#include <tool/context_menu.h> #include <tool/context_menu.h>
void CONDITIONAL_MENU::AddItem( const TOOL_ACTION& aAction, const SELECTION_CONDITION& aCondition, void CONDITIONAL_MENU::AddItem( const TOOL_ACTION& aAction, const SELECTION_CONDITION& aCondition,

View File

@ -23,11 +23,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "grid_menu.h" #include <tool/grid_menu.h>
#include <id.h> #include <id.h>
#include <draw_frame.h> #include <draw_frame.h>
#include <class_base_screen.h> #include <class_base_screen.h>
#include <tools/pcb_actions.h> #include <tool/actions.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <functional> #include <functional>

View File

@ -22,9 +22,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "selection_conditions.h"
#include "selection_tool.h" #include <tool/selection.h>
#include <class_board_connected_item.h> #include <tool/selection_conditions.h>
#include <functional> #include <functional>
using namespace std::placeholders; using namespace std::placeholders;
@ -36,35 +36,6 @@ bool SELECTION_CONDITIONS::NotEmpty( const SELECTION& aSelection )
} }
bool SELECTION_CONDITIONS::OnlyConnectedItems( const SELECTION& aSelection )
{
if( aSelection.Empty() )
return false;
for( const auto &item : aSelection )
{
auto type = item->Type();
if( type != PCB_PAD_T && type != PCB_VIA_T && type != PCB_TRACE_T && type != PCB_ZONE_T )
return false;
}
return true;
}
SELECTION_CONDITION SELECTION_CONDITIONS::SameNet( bool aAllowUnconnected )
{
return std::bind( &SELECTION_CONDITIONS::sameNetFunc, _1, aAllowUnconnected );
}
SELECTION_CONDITION SELECTION_CONDITIONS::SameLayer()
{
return std::bind( &SELECTION_CONDITIONS::sameLayerFunc, _1 );
}
SELECTION_CONDITION SELECTION_CONDITIONS::HasType( KICAD_T aType ) SELECTION_CONDITION SELECTION_CONDITIONS::HasType( KICAD_T aType )
{ {
return std::bind( &SELECTION_CONDITIONS::hasTypeFunc, _1, aType ); return std::bind( &SELECTION_CONDITIONS::hasTypeFunc, _1, aType );
@ -107,72 +78,6 @@ SELECTION_CONDITION SELECTION_CONDITIONS::LessThan( int aNumber )
} }
bool SELECTION_CONDITIONS::sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected )
{
if( aSelection.Empty() )
return false;
int netcode = -1; // -1 stands for 'net code is not yet determined'
for( const auto& aitem : aSelection )
{
int current_netcode = -1;
const BOARD_CONNECTED_ITEM* item =
dynamic_cast<const BOARD_CONNECTED_ITEM*>( aitem );
if( item )
{
current_netcode = item->GetNetCode();
}
else
{
if( !aAllowUnconnected )
return false;
else
// if it is not a BOARD_CONNECTED_ITEM, treat it as if there was no net assigned
current_netcode = 0;
}
assert( current_netcode >= 0 );
if( netcode < 0 )
{
netcode = current_netcode;
if( netcode == NETINFO_LIST::UNCONNECTED && !aAllowUnconnected )
return false;
}
else if( netcode != current_netcode )
{
return false;
}
}
return true;
}
bool SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection )
{
if( aSelection.Empty() )
return false;
LSET layerSet;
layerSet.set();
for( const auto& item : aSelection )
{
layerSet &= item->GetLayerSet();
if( !layerSet.any() ) // there are no common layers left
return false;
}
return true;
}
bool SELECTION_CONDITIONS::hasTypeFunc( const SELECTION& aSelection, KICAD_T aType ) bool SELECTION_CONDITIONS::hasTypeFunc( const SELECTION& aSelection, KICAD_T aType )
{ {
for( const auto& item : aSelection ) for( const auto& item : aSelection )

View File

@ -21,14 +21,17 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "tool_menu.h" #include <draw_frame.h>
#include <tool/tool_menu.h>
#include <tool/tool_interactive.h>
#include <tool/context_menu.h> #include <tool/context_menu.h>
#include "pcb_actions.h" #include <tool/actions.h>
#include "zoom_menu.h" #include <tool/zoom_menu.h>
#include "grid_menu.h" #include <tool/grid_menu.h>
#include "selection_tool.h" // For SELECTION #include <tool/selection.h>
TOOL_MENU::TOOL_MENU( TOOL_INTERACTIVE& aTool ) : TOOL_MENU::TOOL_MENU( TOOL_INTERACTIVE& aTool ) :

View File

@ -22,11 +22,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "zoom_menu.h" #include <tool/zoom_menu.h>
#include <id.h> #include <id.h>
#include <draw_frame.h> #include <draw_frame.h>
#include <class_base_screen.h> #include <class_base_screen.h>
#include <tools/pcb_actions.h> #include <tool/actions.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <functional> #include <functional>

141
include/tool/selection.h Normal file
View File

@ -0,0 +1,141 @@
/*
* 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>
*
* 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 __SELECTION_H
#define __SELECTION_H
#include <set>
#include <base_struct.h>
#include <view/view_group.h>
class SELECTION : public KIGFX::VIEW_GROUP
{
public:
using ITER = std::set<EDA_ITEM*>::iterator;
using CITER = std::set<EDA_ITEM*>::const_iterator;
ITER begin() { return m_items.begin(); }
ITER end() { return m_items.end(); }
CITER begin() const { return m_items.cbegin(); }
CITER end() const { return m_items.cend(); }
virtual void Add( EDA_ITEM* aItem )
{
m_items.insert( aItem );
}
virtual void Remove( EDA_ITEM *aItem )
{
m_items.erase( aItem );
}
virtual void Clear() override
{
m_items.clear();
}
virtual unsigned int GetSize() const override
{
return m_items.size();
}
virtual KIGFX::VIEW_ITEM* GetItem( unsigned int idx ) const override
{
auto iter = m_items.begin();
std::advance( iter, idx );
return *iter;
}
bool Contains( EDA_ITEM* aItem ) const
{
return m_items.find( aItem ) != m_items.end();
}
/// Checks if there is anything selected
bool Empty() const
{
return ( m_items.size() == 0 );
}
/// Returns the number of selected parts
int Size() const
{
return m_items.size();
}
const std::set<EDA_ITEM*> GetItems() const
{
return m_items;
}
/// Returns the center point of the selection area bounding box.
VECTOR2I GetCenter() const;
EDA_ITEM* operator[]( const int index ) const
{
if( index < 0 || (unsigned int) index >= m_items.size() )
return nullptr;
auto iter = m_items.begin();
std::advance( iter, index );
return *iter;
}
EDA_ITEM* Front() const
{
if ( !m_items.size() )
return nullptr;
return *m_items.begin();
}
std::set<EDA_ITEM*>& Items()
{
return m_items;
}
virtual const VIEW_GROUP::ITEMS updateDrawList() const override;
private:
/// Set of selected items
std::set<EDA_ITEM*> m_items;
// mute hidden overloaded virtual function warnings
using VIEW_GROUP::Add;
using VIEW_GROUP::Remove;
};
enum SELECTION_LOCK_FLAGS
{
SELECTION_UNLOCKED = 0,
SELECTION_LOCK_OVERRIDE = 1,
SELECTION_LOCKED = 2
};
#endif

View File

@ -29,7 +29,7 @@
#include <core/typeinfo.h> #include <core/typeinfo.h>
#include <vector> #include <vector>
struct SELECTION; #include <tool/selection.h>
///> Functor type that checks a specific condition for selected items. ///> Functor type that checks a specific condition for selected items.
typedef std::function<bool (const SELECTION&)> SELECTION_CONDITION; typedef std::function<bool (const SELECTION&)> SELECTION_CONDITION;
@ -66,33 +66,6 @@ public:
*/ */
static bool NotEmpty( const SELECTION& aSelection ); static bool NotEmpty( const SELECTION& aSelection );
/**
* Function OnlyConnectedItems
* Tests if selection contains exclusively connected items (pads, tracks, vias, zones).
* @param aSelection is the selection to be tested.
* @return True if there are only connected items connected.
*/
static bool OnlyConnectedItems( const SELECTION& aSelection );
/**
* Function SameNet
* Creates a functor that tests if selection contains items belonging to the same net or are
* unconnected if aAllowUnconnected == true.
* @param aAllowUnconnected determines if unconnected items (with no net code assigned) should
* be treated as connected to the same net.
* @return Functor testing if selected items are belonging to the same net.
*/
static SELECTION_CONDITION SameNet( bool aAllowUnconnected = false );
/**
* Function SameLayer
* Creates a functor that tests if selection contains items that belong exclusively to the same
* layer. In case of items belonging to multiple layers, it is enough to have a single common
* layer with other items.
* @return Functor testing if selected items share at least one common layer.
*/
static SELECTION_CONDITION SameLayer();
/** /**
* Function HasType * Function HasType
* Creates a functor that tests if among the selected items there is at least one of a given type. * Creates a functor that tests if among the selected items there is at least one of a given type.
@ -154,12 +127,6 @@ public:
static SELECTION_CONDITION LessThan( int aNumber ); static SELECTION_CONDITION LessThan( int aNumber );
private: private:
///> Helper function used by SameNet()
static bool sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected );
///> Helper function used by SameLayer()
static bool sameLayerFunc( const SELECTION& aSelection );
///> Helper function used by HasType() ///> Helper function used by HasType()
static bool hasTypeFunc( const SELECTION& aSelection, KICAD_T aType ); static bool hasTypeFunc( const SELECTION& aSelection, KICAD_T aType );

View File

@ -24,8 +24,8 @@
#ifndef TOOLS_TOOL_MENU__H_ #ifndef TOOLS_TOOL_MENU__H_
#define TOOLS_TOOL_MENU__H_ #define TOOLS_TOOL_MENU__H_
#include "conditional_menu.h" #include <tool/conditional_menu.h>
#include "pcb_tool.h" #include <tool/tool_event.h>
#include <vector> #include <vector>
#include <memory> #include <memory>

View File

@ -291,8 +291,7 @@ set( PCBNEW_CLASS_SRCS
tools/selection_tool.cpp tools/selection_tool.cpp
tools/selection_area.cpp tools/selection_area.cpp
tools/selection_conditions.cpp tools/pcb_selection_conditions.cpp
tools/conditional_menu.cpp
tools/bright_box.cpp tools/bright_box.cpp
tools/edit_points.cpp tools/edit_points.cpp
tools/edit_constraints.cpp tools/edit_constraints.cpp
@ -310,10 +309,7 @@ set( PCBNEW_CLASS_SRCS
tools/zoom_tool.cpp tools/zoom_tool.cpp
tools/tools_common.cpp tools/tools_common.cpp
tools/tool_event_utils.cpp tools/tool_event_utils.cpp
tools/tool_menu.cpp
tools/grid_menu.cpp
tools/zoom_menu.cpp
tools/size_menu.cpp tools/size_menu.cpp
footprint_preview_panel.cpp footprint_preview_panel.cpp

View File

@ -27,7 +27,7 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
struct SELECTION; class SELECTION;
class COMMIT; class COMMIT;
class PCB_BASE_FRAME; class PCB_BASE_FRAME;

View File

@ -46,12 +46,13 @@ using namespace std::placeholders;
#include <tool/context_menu.h> #include <tool/context_menu.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tool/tool_settings.h> #include <tool/tool_settings.h>
#include <tool/grid_menu.h>
#include <tool/zoom_menu.h>
#include <tools/pcb_actions.h> #include <tools/pcb_actions.h>
#include <tools/size_menu.h> #include <tools/size_menu.h>
#include <tools/selection_tool.h> #include <tools/selection_tool.h>
#include <tools/edit_tool.h> #include <tools/edit_tool.h>
#include <tools/grid_menu.h>
#include <tools/zoom_menu.h>
#include <tools/tool_event_utils.h> #include <tools/tool_event_utils.h>
#include <ratsnest_data.h> #include <ratsnest_data.h>

View File

@ -675,7 +675,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
preview.Add( item ); preview.Add( item );
} }
BOARD_ITEM* firstItem = preview.Front(); BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( preview.Front() );
m_view->Add( &preview ); m_view->Add( &preview );
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@ -696,7 +696,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
delta = cursorPos - firstItem->GetPosition(); delta = cursorPos - firstItem->GetPosition();
for( auto item : preview ) for( auto item : preview )
item->Move( wxPoint( delta.x, delta.y ) ); static_cast<BOARD_ITEM*>( item )->Move( wxPoint( delta.x, delta.y ) );
m_view->Update( &preview ); m_view->Update( &preview );
} }
@ -712,7 +712,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
for( auto item : preview ) for( auto item : preview )
{ {
item->Rotate( rotationPoint, rotationAngle ); static_cast<BOARD_ITEM*>( item )->Rotate( rotationPoint, rotationAngle );
} }
m_view->Update( &preview ); m_view->Update( &preview );
@ -720,7 +720,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
else if( evt->IsAction( &PCB_ACTIONS::flip ) ) else if( evt->IsAction( &PCB_ACTIONS::flip ) )
{ {
for( auto item : preview ) for( auto item : preview )
item->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); static_cast<BOARD_ITEM*>( item )->Flip( wxPoint( cursorPos.x, cursorPos.y ) );
m_view->Update( &preview ); m_view->Update( &preview );
} }
@ -807,7 +807,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
} }
if( converted ) if( converted )
converted->SetLayer( item->GetLayer() ); converted->SetLayer( static_cast<BOARD_ITEM*>( item )->GetLayer() );
delete item; delete item;
item = converted; item = converted;

View File

@ -28,7 +28,7 @@
#include <tools/pcb_tool.h> #include <tools/pcb_tool.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include "tool_menu.h" #include <tool/tool_menu.h>
namespace KIGFX namespace KIGFX
{ {

View File

@ -273,7 +273,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
if( selection.Empty() ) if( selection.Empty() )
break; break;
BOARD_ITEM* curr_item = selection.Front(); BOARD_ITEM* curr_item = static_cast<BOARD_ITEM*>( selection.Front() );
if( m_dragging && evt->Category() == TC_MOUSE ) if( m_dragging && evt->Category() == TC_MOUSE )
{ {
@ -285,7 +285,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
// Drag items to the current cursor position // Drag items to the current cursor position
for( auto item : selection ) for( auto item : selection )
item->Move( movement + m_offset ); static_cast<BOARD_ITEM*>( item )->Move( movement + m_offset );
updateRatsnest( true ); updateRatsnest( true );
} }
@ -378,7 +378,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
// So, instead, reset the position manually // So, instead, reset the position manually
for( auto item : selection ) for( auto item : selection )
{ {
item->SetPosition( item->GetPosition() - totalMovement ); BOARD_ITEM* i = static_cast<BOARD_ITEM*>( item );
i->SetPosition( i->GetPosition() - totalMovement );
// And what about flipping and rotation? // And what about flipping and rotation?
// for now, they won't be undone, but maybe that is how // for now, they won't be undone, but maybe that is how
@ -395,7 +396,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
if( m_dragging ) if( m_dragging )
{ {
// Update dragging offset (distance between cursor and the first dragged item) // Update dragging offset (distance between cursor and the first dragged item)
m_offset = selection.Front()->GetPosition() - modPoint; m_offset = static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() - modPoint;
getView()->Update( &selection ); getView()->Update( &selection );
updateRatsnest( true ); updateRatsnest( true );
} }
@ -454,7 +455,7 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected
{ {
// Display properties dialog // Display properties dialog
BOARD_ITEM* item = selection.Front(); BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
// Some of properties dialogs alter pointers, so we should deselect them // Some of properties dialogs alter pointers, so we should deselect them
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@ -495,7 +496,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
for( auto item : selection ) for( auto item : selection )
{ {
m_commit->Modify( item ); m_commit->Modify( item );
item->Rotate( rotatePoint, rotateAngle ); static_cast<BOARD_ITEM*>( item )->Rotate( rotatePoint, rotateAngle );
} }
if( !m_dragging ) if( !m_dragging )
@ -640,7 +641,7 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
for( auto item : selection ) for( auto item : selection )
{ {
m_commit->Modify( item ); m_commit->Modify( item );
item->Flip( flipPoint ); static_cast<BOARD_ITEM*>( item )->Flip( flipPoint );
} }
if( !m_dragging ) if( !m_dragging )
@ -719,8 +720,8 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
{ {
m_commit->Modify( item ); m_commit->Modify( item );
item->Move( translation ); static_cast<BOARD_ITEM*>( item )->Move( translation );
item->Rotate( rotPoint, rotation ); static_cast<BOARD_ITEM*>( item )->Rotate( rotPoint, rotation );
if( !m_dragging ) if( !m_dragging )
getView()->Update( item, KIGFX::GEOMETRY ); getView()->Update( item, KIGFX::GEOMETRY );
@ -760,7 +761,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
for( auto item : selection ) for( auto item : selection )
{ {
if( item ) if( item )
old_items.push_back( item ); old_items.push_back( static_cast<BOARD_ITEM*>( item ) );
} }
for( unsigned i = 0; i < old_items.size(); ++i ) for( unsigned i = 0; i < old_items.size(); ++i )
@ -835,7 +836,7 @@ private:
BOARD_ITEM* getNthItemToArray( int n ) const override BOARD_ITEM* getNthItemToArray( int n ) const override
{ {
return m_selection[n]; return static_cast<BOARD_ITEM*>( m_selection[n] );
} }
BOARD* getBoard() const override BOARD* getBoard() const override
@ -951,10 +952,10 @@ void EDIT_TOOL::updateRatsnest( bool aRedraw )
for( auto item : selection ) for( auto item : selection )
{ {
ratsnest->Update( item ); ratsnest->Update( static_cast<BOARD_ITEM*>( item ) );
if( aRedraw ) if( aRedraw )
ratsnest->AddSimple( item ); ratsnest->AddSimple( static_cast<BOARD_ITEM*>( item ) );
} }
} }
@ -963,7 +964,7 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection )
{ {
if( aSelection.Size() == 1 ) if( aSelection.Size() == 1 )
{ {
return aSelection.Front()->GetPosition() - m_offset; return static_cast<BOARD_ITEM*>( aSelection.Front() )->GetPosition() - m_offset;
} }
else else
{ {

View File

@ -39,7 +39,7 @@
#include "pcb_actions.h" #include "pcb_actions.h"
#include "selection_tool.h" #include "selection_tool.h"
#include "selection_conditions.h" #include "pcb_selection_conditions.h"
#include "edit_tool.h" #include "edit_tool.h"
// Pad tools // Pad tools

View File

@ -199,8 +199,8 @@ private:
// lines like this make me really think about a better name for SELECTION_CONDITIONS class // lines like this make me really think about a better name for SELECTION_CONDITIONS class
bool mergeEnabled = ( SELECTION_CONDITIONS::MoreThan( 1 ) && bool mergeEnabled = ( SELECTION_CONDITIONS::MoreThan( 1 ) &&
/*SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) &&*/ /*SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) &&*/
SELECTION_CONDITIONS::SameNet( true ) && PCB_SELECTION_CONDITIONS::SameNet( true ) &&
SELECTION_CONDITIONS::SameLayer() )( selTool->GetSelection() ); PCB_SELECTION_CONDITIONS::SameLayer() )( selTool->GetSelection() );
Enable( getMenuId( PCB_ACTIONS::zoneMerge ), mergeEnabled ); Enable( getMenuId( PCB_ACTIONS::zoneMerge ), mergeEnabled );
} }
@ -523,8 +523,9 @@ int PCB_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode )
bool modified = false; bool modified = false;
for( auto item : selection ) for( auto i : selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
bool prevState = item->IsLocked(); bool prevState = item->IsLocked();
switch( aMode ) switch( aMode )
@ -923,7 +924,7 @@ int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent )
const SELECTION& selection = selTool->GetSelection(); const SELECTION& selection = selTool->GetSelection();
if( selection.Size() == 1 ) if( selection.Size() == 1 )
m_frame->SendMessageToEESCHEMA( selection.Front() ); m_frame->SendMessageToEESCHEMA( static_cast<BOARD_ITEM*>( selection.Front() ) );
return 0; return 0;
} }

View File

@ -0,0 +1,127 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 CERN
* @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
* 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 "pcb_selection_conditions.h"
#include "selection_tool.h"
#include <class_board_connected_item.h>
#include <functional>
using namespace std::placeholders;
bool PCB_SELECTION_CONDITIONS::OnlyConnectedItems( const SELECTION& aSelection )
{
if( aSelection.Empty() )
return false;
for( const auto &item : aSelection )
{
auto type = item->Type();
if( type != PCB_PAD_T && type != PCB_VIA_T && type != PCB_TRACE_T && type != PCB_ZONE_T )
return false;
}
return true;
}
SELECTION_CONDITION PCB_SELECTION_CONDITIONS::SameNet( bool aAllowUnconnected )
{
return std::bind( &PCB_SELECTION_CONDITIONS::sameNetFunc, _1, aAllowUnconnected );
}
SELECTION_CONDITION PCB_SELECTION_CONDITIONS::SameLayer()
{
return std::bind( &PCB_SELECTION_CONDITIONS::sameLayerFunc, _1 );
}
bool PCB_SELECTION_CONDITIONS::sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected )
{
if( aSelection.Empty() )
return false;
int netcode = -1; // -1 stands for 'net code is not yet determined'
for( const auto& aitem : aSelection )
{
int current_netcode = -1;
const BOARD_CONNECTED_ITEM* item =
dynamic_cast<const BOARD_CONNECTED_ITEM*>( aitem );
if( item )
{
current_netcode = item->GetNetCode();
}
else
{
if( !aAllowUnconnected )
return false;
else
// if it is not a BOARD_CONNECTED_ITEM, treat it as if there was no net assigned
current_netcode = 0;
}
assert( current_netcode >= 0 );
if( netcode < 0 )
{
netcode = current_netcode;
if( netcode == NETINFO_LIST::UNCONNECTED && !aAllowUnconnected )
return false;
}
else if( netcode != current_netcode )
{
return false;
}
}
return true;
}
bool PCB_SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection )
{
if( aSelection.Empty() )
return false;
LSET layerSet;
layerSet.set();
for( const auto& i : aSelection )
{
auto item = static_cast<BOARD_ITEM*>( i );
layerSet &= item->GetLayerSet();
if( !layerSet.any() ) // there are no common layers left
return false;
}
return true;
}

View File

@ -0,0 +1,72 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 CERN
* @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
* 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 PCB_SELECTION_CONDITIONS_H_
#define PCB_SELECTION_CONDITIONS_H_
#include <tool/selection.h>
#include <tool/selection_conditions.h>
#include <class_board_item.h>
class PCB_SELECTION_CONDITIONS : public SELECTION_CONDITIONS
{
public:
/**
* Function OnlyConnectedItems
* Tests if selection contains exclusively connected items (pads, tracks, vias, zones).
* @param aSelection is the selection to be tested.
* @return True if there are only connected items connected.
*/
static bool OnlyConnectedItems( const SELECTION& aSelection );
/**
* Function SameNet
* Creates a functor that tests if selection contains items belonging to the same net or are
* unconnected if aAllowUnconnected == true.
* @param aAllowUnconnected determines if unconnected items (with no net code assigned) should
* be treated as connected to the same net.
* @return Functor testing if selected items are belonging to the same net.
*/
static SELECTION_CONDITION SameNet( bool aAllowUnconnected = false );
/**
* Function SameLayer
* Creates a functor that tests if selection contains items that belong exclusively to the same
* layer. In case of items belonging to multiple layers, it is enough to have a single common
* layer with other items.
* @return Functor testing if selected items share at least one common layer.
*/
static SELECTION_CONDITION SameLayer();
private:
///> Helper function used by SameNet()
static bool sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected );
///> Helper function used by SameLayer()
static bool sameLayerFunc( const SELECTION& aSelection );
};
#endif /* PCB_SELECTION_CONDITIONS_H_ */

View File

@ -974,7 +974,7 @@ int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent )
// Start dragging the appended board // Start dragging the appended board
SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>(); SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
const SELECTION& selection = selectionTool->GetSelection(); const SELECTION& selection = selectionTool->GetSelection();
VECTOR2D v( selection.Front()->GetPosition() ); VECTOR2D v( static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() );
getViewControls()->WarpCursor( v, true, true ); getViewControls()->WarpCursor( v, true, true );
m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" ); m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );

View File

@ -133,8 +133,10 @@ int PLACEMENT_TOOL::AlignTop( const TOOL_EVENT& aEvent )
} }
// Move the selected items // Move the selected items
for( auto item : selection ) for( auto i : selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
int difference = top - item->GetBoundingBox().GetY(); int difference = top - item->GetBoundingBox().GetY();
item->Move( wxPoint( 0, difference ) ); item->Move( wxPoint( 0, difference ) );
@ -168,8 +170,10 @@ int PLACEMENT_TOOL::AlignBottom( const TOOL_EVENT& aEvent )
} }
// Move the selected items // Move the selected items
for( auto item : selection ) for( auto i : selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
int difference = bottom - item->GetBoundingBox().GetBottom(); int difference = bottom - item->GetBoundingBox().GetBottom();
item->Move( wxPoint( 0, difference ) ); item->Move( wxPoint( 0, difference ) );
@ -203,8 +207,10 @@ int PLACEMENT_TOOL::AlignLeft( const TOOL_EVENT& aEvent )
} }
// Move the selected items // Move the selected items
for( auto item : selection ) for( auto i : selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
int difference = left - item->GetBoundingBox().GetX(); int difference = left - item->GetBoundingBox().GetX();
item->Move( wxPoint( difference, 0 ) ); item->Move( wxPoint( difference, 0 ) );
@ -238,8 +244,10 @@ int PLACEMENT_TOOL::AlignRight( const TOOL_EVENT& aEvent )
} }
// Move the selected items // Move the selected items
for( auto item : selection ) for( auto i : selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
int difference = right - item->GetBoundingBox().GetRight(); int difference = right - item->GetBoundingBox().GetRight();
item->Move( wxPoint( difference, 0 ) ); item->Move( wxPoint( difference, 0 ) );
@ -277,7 +285,7 @@ int PLACEMENT_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
std::vector<BOARD_ITEM*> itemsList; std::vector<BOARD_ITEM*> itemsList;
for( auto item : selection ) for( auto item : selection )
itemsList.push_back( item ); itemsList.push_back( static_cast<BOARD_ITEM*>( item ) );
// Sort items by X coordinate // Sort items by X coordinate
std::sort(itemsList.begin(), itemsList.end(), compareX ); std::sort(itemsList.begin(), itemsList.end(), compareX );
@ -320,7 +328,7 @@ int PLACEMENT_TOOL::DistributeVertically( const TOOL_EVENT& aEvent )
std::vector<BOARD_ITEM*> itemsList; std::vector<BOARD_ITEM*> itemsList;
for( auto item : selection ) for( auto item : selection )
itemsList.push_back( item ); itemsList.push_back( static_cast<BOARD_ITEM*>( item ) );
// Sort items by Y coordinate // Sort items by Y coordinate
std::sort( itemsList.begin(), itemsList.end(), compareY ); std::sort( itemsList.begin(), itemsList.end(), compareY );

View File

@ -337,7 +337,7 @@ SELECTION& SELECTION_TOOL::GetSelection()
// Filter out not modifiable items // Filter out not modifiable items
for( auto item : items ) for( auto item : items )
{ {
if( !modifiable( item ) ) if( !modifiable( static_cast<BOARD_ITEM*>( item ) ) )
{ {
m_selection.Remove( item ); m_selection.Remove( item );
} }
@ -506,7 +506,7 @@ bool SELECTION_TOOL::selectMultiple()
} }
if( m_selection.Size() == 1 ) if( m_selection.Size() == 1 )
m_frame->SetCurItem( m_selection.Front() ); m_frame->SetCurItem( static_cast<BOARD_ITEM*>( m_selection.Front() ) );
else else
m_frame->SetCurItem( NULL ); m_frame->SetCurItem( NULL );
@ -687,8 +687,9 @@ int SELECTION_TOOL::selectCopper( const TOOL_EVENT& aEvent )
// copy the selection, since we're going to iterate and modify // copy the selection, since we're going to iterate and modify
auto selection = m_selection.GetItems(); auto selection = m_selection.GetItems();
for( auto item : selection ) for( auto i : selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
// only connected items can be traversed in the ratsnest // only connected items can be traversed in the ratsnest
if ( item->IsConnected() ) if ( item->IsConnected() )
{ {
@ -751,8 +752,9 @@ int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent )
// copy the selection, since we're going to iterate and modify // copy the selection, since we're going to iterate and modify
auto selection = m_selection.GetItems(); auto selection = m_selection.GetItems();
for( auto item : selection ) for( auto i : selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
// only connected items get a net code // only connected items get a net code
if( item->IsConnected() ) if( item->IsConnected() )
{ {
@ -794,19 +796,19 @@ int SELECTION_TOOL::selectSameSheet( const TOOL_EVENT& aEvent )
std::list<MODULE*> modList; std::list<MODULE*> modList;
// store all modules that are on that sheet // store all modules that are on that sheet
for( MODULE* item = modules; item; item = item->Next() ) for( MODULE* mitem = modules; mitem; mitem = mitem->Next() )
{ {
if ( item != NULL && item->GetPath().Contains( sheetPath ) ) if ( mitem != NULL && mitem->GetPath().Contains( sheetPath ) )
{ {
modList.push_back( item ); modList.push_back( mitem );
} }
} }
//Generate a list of all pads, and of all nets they belong to. //Generate a list of all pads, and of all nets they belong to.
std::list<int> netcodeList; std::list<int> netcodeList;
for( MODULE* mod : modList ) for( MODULE* mmod : modList )
{ {
for( D_PAD* pad = mod->Pads().GetFirst(); pad; pad = pad->Next() ) for( D_PAD* pad = mmod->Pads().GetFirst(); pad; pad = pad->Next() )
{ {
if( pad->IsConnected() ) if( pad->IsConnected() )
{ {
@ -828,9 +830,9 @@ int SELECTION_TOOL::selectSameSheet( const TOOL_EVENT& aEvent )
{ {
std::list<BOARD_CONNECTED_ITEM*> netPads; std::list<BOARD_CONNECTED_ITEM*> netPads;
ratsnest->GetNetItems( netCode, netPads, (RN_ITEM_TYPE)( RN_PADS ) ); ratsnest->GetNetItems( netCode, netPads, (RN_ITEM_TYPE)( RN_PADS ) );
for( BOARD_CONNECTED_ITEM* item : netPads ) for( BOARD_CONNECTED_ITEM* mitem : netPads )
{ {
bool found = ( std::find( modList.begin(), modList.end(), item->GetParent() ) != modList.end() ); bool found = ( std::find( modList.begin(), modList.end(), mitem->GetParent() ) != modList.end() );
if( !found ) if( !found )
{ {
// if we cannot find the module of the pad in the modList // if we cannot find the module of the pad in the modList
@ -1044,8 +1046,9 @@ int SELECTION_TOOL::filterSelection( const TOOL_EVENT& aEvent )
// copy selection items from the saved selection // copy selection items from the saved selection
// according to the dialog options // according to the dialog options
for( auto item : selection ) for( auto i : selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
bool include = itemIsIncludedByFilter( *item, board, layerMask, opts ); bool include = itemIsIncludedByFilter( *item, board, layerMask, opts );
if( include ) if( include )
@ -1063,7 +1066,7 @@ void SELECTION_TOOL::clearSelection()
return; return;
for( auto item : m_selection ) for( auto item : m_selection )
unselectVisually( item ); unselectVisually( static_cast<BOARD_ITEM*>( item ) );
m_selection.Clear(); m_selection.Clear();
@ -1704,8 +1707,9 @@ bool SELECTION_TOOL::SanitizeSelection()
if( !m_editModules ) if( !m_editModules )
{ {
for( auto item : m_selection ) for( auto i : m_selection )
{ {
auto item = static_cast<BOARD_ITEM*>( i );
if( item->Type() == PCB_PAD_T ) if( item->Type() == PCB_PAD_T )
{ {
MODULE* mod = static_cast<MODULE*>( item->GetParent() ); MODULE* mod = static_cast<MODULE*>( item->GetParent() );
@ -1748,13 +1752,14 @@ bool SELECTION_TOOL::SanitizeSelection()
} }
// TODO(JE) Only works for BOARD_ITEM
VECTOR2I SELECTION::GetCenter() const VECTOR2I SELECTION::GetCenter() const
{ {
VECTOR2I centre; VECTOR2I centre;
if( Size() == 1 ) if( Size() == 1 )
{ {
centre = Front()->GetCenter(); centre = static_cast<BOARD_ITEM*>( Front() )->GetCenter();
} }
else else
{ {

View File

@ -31,9 +31,10 @@
#include <math/vector2d.h> #include <math/vector2d.h>
#include <tools/pcb_tool.h> #include <tools/pcb_tool.h>
#include <tool/context_menu.h> #include <tool/context_menu.h>
#include <tool/selection.h>
#include "selection_conditions.h" #include <tools/pcb_selection_conditions.h>
#include "tool_menu.h" #include <tool/tool_menu.h>
class PCB_BASE_FRAME; class PCB_BASE_FRAME;
class SELECTION_AREA; class SELECTION_AREA;
@ -45,111 +46,6 @@ namespace KIGFX
class GAL; class GAL;
} }
struct SELECTION : public KIGFX::VIEW_GROUP
{
public:
using ITER = std::set<BOARD_ITEM*>::iterator;
using CITER = std::set<BOARD_ITEM*>::const_iterator;
ITER begin() { return m_items.begin(); }
ITER end() { return m_items.end(); }
CITER begin() const { return m_items.cbegin(); }
CITER end() const { return m_items.cend(); }
virtual void Add( BOARD_ITEM* aItem )
{
m_items.insert( aItem );
}
virtual void Remove( BOARD_ITEM *aItem )
{
m_items.erase( aItem );
}
virtual void Clear() override
{
m_items.clear();
}
virtual unsigned int GetSize() const override
{
return m_items.size();
}
virtual KIGFX::VIEW_ITEM* GetItem( unsigned int idx ) const override
{
auto iter = m_items.begin();
std::advance( iter, idx );
return *iter;
}
bool Contains( BOARD_ITEM* aItem ) const
{
return m_items.find( aItem ) != m_items.end();
}
/// Checks if there is anything selected
bool Empty() const
{
return ( m_items.size() == 0 );
}
/// Returns the number of selected parts
int Size() const
{
return m_items.size();
}
const std::set<BOARD_ITEM*> GetItems() const
{
return m_items;
}
/// Returns the center point of the selection area bounding box.
VECTOR2I GetCenter() const;
BOARD_ITEM* operator[]( const int index ) const
{
if( index < 0 || (unsigned int) index >= m_items.size() )
return nullptr;
auto iter = m_items.begin();
std::advance( iter, index );
return *iter;
}
BOARD_ITEM* Front() const
{
if ( !m_items.size() )
return nullptr;
return *m_items.begin();
}
std::set<BOARD_ITEM*>& Items()
{
return m_items;
}
virtual const VIEW_GROUP::ITEMS updateDrawList() const override;
private:
/// Set of selected items
std::set<BOARD_ITEM*> m_items;
// mute hidden overloaded virtual function warnings
using VIEW_GROUP::Add;
using VIEW_GROUP::Remove;
};
enum SELECTION_LOCK_FLAGS
{
SELECTION_UNLOCKED = 0,
SELECTION_LOCK_OVERRIDE = 1,
SELECTION_LOCKED = 2
};
/** /**
* Class SELECTION_TOOL * Class SELECTION_TOOL