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