1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2014 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 #include "pcb_selection_conditions.h"
26 #include "pcb_selection_tool.h"
27 #include <board_connected_item.h>
28 #include <pcb_shape.h>
29 
30 #include <functional>
31 using namespace std::placeholders;
32 
33 using S_C = SELECTION_CONDITION;
34 
35 
OnlyConnectedItems(const SELECTION & aSelection)36 bool PCB_SELECTION_CONDITIONS::OnlyConnectedItems( const SELECTION& aSelection )
37 {
38     if( aSelection.Empty() )
39         return false;
40 
41     for( const auto &item : aSelection )
42     {
43         auto type = item->Type();
44 
45         if( type != PCB_PAD_T && type != PCB_VIA_T && type != PCB_TRACE_T && type != PCB_ZONE_T )
46             return false;
47     }
48 
49     return true;
50 }
51 
52 
SameNet(bool aAllowUnconnected)53 S_C PCB_SELECTION_CONDITIONS::SameNet( bool aAllowUnconnected )
54 {
55     return std::bind( &PCB_SELECTION_CONDITIONS::sameNetFunc, _1, aAllowUnconnected );
56 }
57 
58 
SameLayer()59 S_C PCB_SELECTION_CONDITIONS::SameLayer()
60 {
61     return std::bind( &PCB_SELECTION_CONDITIONS::sameLayerFunc, _1 );
62 }
63 
64 
OnlyGraphicShapeTypes(const std::set<SHAPE_T> aTypes)65 S_C PCB_SELECTION_CONDITIONS::OnlyGraphicShapeTypes( const std::set<SHAPE_T> aTypes )
66 {
67     return std::bind( &PCB_SELECTION_CONDITIONS::onlyGraphicShapeTypesFunc, _1, aTypes );
68 }
69 
70 
71 
sameNetFunc(const SELECTION & aSelection,bool aAllowUnconnected)72 bool PCB_SELECTION_CONDITIONS::sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected )
73 {
74     if( aSelection.Empty() )
75         return false;
76 
77     int netcode = -1;   // -1 stands for 'net code is not yet determined'
78 
79     for( const auto& aitem : aSelection )
80     {
81         int current_netcode = -1;
82 
83         const BOARD_CONNECTED_ITEM* item =
84             dynamic_cast<const BOARD_CONNECTED_ITEM*>( aitem );
85 
86         if( item )
87         {
88             current_netcode = item->GetNetCode();
89         }
90         else
91         {
92             if( !aAllowUnconnected )
93                 return false;
94             else
95                 // if it is not a BOARD_CONNECTED_ITEM, treat it as if there was no net assigned
96                 current_netcode = 0;
97         }
98 
99         assert( current_netcode >= 0 );
100 
101         if( netcode < 0 )
102         {
103             netcode = current_netcode;
104 
105             if( netcode == NETINFO_LIST::UNCONNECTED && !aAllowUnconnected )
106                 return false;
107         }
108         else if( netcode != current_netcode )
109         {
110             return false;
111         }
112     }
113 
114     return true;
115 }
116 
117 
sameLayerFunc(const SELECTION & aSelection)118 bool PCB_SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection )
119 {
120     if( aSelection.Empty() )
121         return false;
122 
123     LSET layerSet;
124     layerSet.set();
125 
126     for( const auto& i : aSelection )
127     {
128         auto item = static_cast<BOARD_ITEM*>( i );
129         layerSet &= item->GetLayerSet();
130 
131         if( !layerSet.any() )       // there are no common layers left
132             return false;
133     }
134 
135     return true;
136 }
137 
138 
onlyGraphicShapeTypesFunc(const SELECTION & aSelection,const std::set<SHAPE_T> aTypes)139 bool PCB_SELECTION_CONDITIONS::onlyGraphicShapeTypesFunc( const SELECTION& aSelection,
140                                                           const std::set<SHAPE_T> aTypes )
141 {
142     if( aSelection.Empty() )
143         return false;
144 
145     for( const EDA_ITEM* item : aSelection )
146     {
147         if( item->Type() != PCB_SHAPE_T && item->Type() != PCB_FP_SHAPE_T )
148             return false;
149 
150         SHAPE_T shape = static_cast<const PCB_SHAPE*>( item )->GetShape();
151 
152         if( !aTypes.count( shape ) )
153             return false;
154     }
155 
156     return true;
157 }
158