diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 198541afca..d1b702244b 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,10 @@ void SELECTION_TOOL::Reset() int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) { bool dragging = false; + m_board = static_cast( m_toolMgr->GetEditFrame() )->GetBoard(); + + if( !m_board ) + return 0; // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) @@ -131,8 +136,12 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) if( !m_additive ) clearSelection(); - aItem->SetSelected(); - m_selectedItems.insert( aItem ); + // Prevent selection of invisible items + if( selectable( aItem ) ) + { + aItem->SetSelected(); + m_selectedItems.insert( aItem ); + } } } @@ -214,11 +223,6 @@ BOARD_ITEM* SELECTION_TOOL::pickSmallestComponent( GENERAL_COLLECTOR* aCollector } -void SELECTION_TOOL::handleHighlight( const VECTOR2D& aP ) -{ -} - - void SELECTION_TOOL::selectMultiple() { OPT_TOOL_EVENT evt; @@ -258,8 +262,8 @@ void SELECTION_TOOL::selectMultiple() { BOARD_ITEM* item = static_cast( it->first ); - // Add only those items which are fully within a selection box - if( selectionBox.Contains( item->ViewBBox() ) ) + // Add only those items which are visible and fully within the selection box + if( selectable( item ) && selectionBox.Contains( item->ViewBBox() ) ) { item->SetSelected(); m_selectedItems.insert( item ); @@ -331,3 +335,40 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) return NULL; } + + +bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const +{ + switch( aItem->Type() ) + { + case PCB_VIA_T: + { + // For vias it is enough if only one of layers is visible + LAYER_NUM top, bottom; + static_cast( aItem )->ReturnLayerPair( &top, &bottom ); + + return ( m_board->IsLayerVisible( top ) || + m_board->IsLayerVisible( bottom ) ); + } + break; + + case PCB_PAD_T: + // Pads are supposed to be on top, bottom or both at the same time (THT) + if( aItem->IsOnLayer( LAYER_N_FRONT ) && m_board->IsLayerVisible( LAYER_N_FRONT ) ) + return true; + + if( aItem->IsOnLayer( LAYER_N_BACK ) && m_board->IsLayerVisible( LAYER_N_BACK ) ) + return true; + + return false; + break; + + case PCB_MODULE_EDGE_T: + // These are not selectable, otherwise silkscreen drawings would be easily destroyed + return false; + break; + } + + // All other items + return m_board->IsLayerVisible( aItem->GetLayer() ); +} diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index 6d485395fa..7a59d31921 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -35,7 +35,6 @@ class SELECTION_AREA; class BOARD_ITEM; class GENERAL_COLLECTOR; - /** * Class SELECTION_TOOL * @@ -43,8 +42,6 @@ class GENERAL_COLLECTOR; * - pick single objects (click LMB) * - add objects to existing selection (Shift+LMB) * - draw selection box (drag LMB) - * - * WORK IN PROGRESS. CONSIDER AS A DEMO! */ class SELECTION_TOOL : public TOOL_INTERACTIVE @@ -53,25 +50,98 @@ public: SELECTION_TOOL(); ~SELECTION_TOOL(); + /** + * Function Reset() + * + * Initializes the selection tool. + */ void Reset(); + + /** + * Function Main() + * + * The main loop. + */ int Main( TOOL_EVENT& aEvent ); + + /** + * Function GetSelection() + * + * Returns the set of currently selected items. + */ const std::set& GetSelection() const { return m_selectedItems; } private: + /** + * Function selectSingle() + * Selects an item pointed by the parameter aWhere. If there is more than one item at that + * place, there is a menu displayed that allows to choose the item. + * + * @param aWhere is the place where the item should be selected. + */ void selectSingle( const VECTOR2I& aWhere ); + + /** + * Function selectMultiple() + * Handles drawing a selection box that allows to select many items at the same time. + */ void selectMultiple(); - void handleHighlight( const VECTOR2D& aP ); + + /** + * Function disambiguationMenu() + * Handles the menu that allows to select one of many items in case there is more than one + * item at the selected point (@see selectSingle()). + * + * @param aItems contains list of items that are displayed to the user. + */ BOARD_ITEM* disambiguationMenu( GENERAL_COLLECTOR* aItems ); + + /** + * Function pickSmallestComponent() + * Allows to find the smallest (in terms of bounding box area) item from the list. + * + * @param aCollector containes the list of items. + */ BOARD_ITEM* pickSmallestComponent( GENERAL_COLLECTOR* aCollector ); + + /** + * Function toggleSelection() + * Changes selection status of a given item. + * + * @param aItem is the item to have selection status changed. + */ void toggleSelection( BOARD_ITEM* aItem ); + + /** + * Function clearSelection() + * Clears selections of currently selected items. + */ void clearSelection(); + /** + * Function selectable() + * Checks conditions for an item to be selected. + * + * @return True if the item fulfills conditions to be selected. + */ + bool selectable( const BOARD_ITEM* aItem ) const; + + /// Currently used PCB + BOARD* m_board; + + /// Container storing currently selected items std::set m_selectedItems; + + /// Visual representation of selection area SELECTION_AREA* m_selArea; + + /// Menu shown in case of selection ambiguity boost::shared_ptr m_menu; + + /// Flag saying if items should be added to the current selection or rather replace it bool m_additive; };