KiCad PCB EDA Suite
Loading...
Searching...
No Matches
model_zones_overview.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 Ethan Chien <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <board.h>
22#include <netinfo.h>
23#include <vector>
24#include <wx/string.h>
26#include <wx/dcmemory.h>
27#include <pcb_edit_frame.h>
28#include <wx/variant.h>
30
31
32wxDEFINE_EVENT( EVT_ZONES_OVERVIEW_COUNT_CHANGE, wxCommandEvent );
33
34
36{
37 std::sort( m_filteredZones.begin(), m_filteredZones.end(),
38 [&]( ZONE* const& l, ZONE* const& r )
39 {
40 return l->HigherPriority( r );
41 } );
42}
43
44
46{
47 wxCommandEvent rowCountChange( EVT_ZONES_OVERVIEW_COUNT_CHANGE );
48 rowCountChange.SetInt( GetCount() );
49 wxPostEvent( m_parent, rowCountChange );
50}
51
52
53static wxBitmap MakeBitmapForLayers( LSEQ const& layers, COLOR_SETTINGS const& settings, const wxSize& aSize )
54{
55 wxBitmap bitmap( aSize );
56 wxBrush brush;
57 wxPen pen;
58 wxMemoryDC iconDC;
59
60 iconDC.SelectObject( bitmap );
61 brush.SetStyle( wxBRUSHSTYLE_SOLID );
62 const int layer_cout = layers.size();
63 std::vector<PCB_LAYER_ID> layersToDraw;
64
65 if( layer_cout > 4 )
66 {
67 for( const PCB_LAYER_ID& i : { layers[0], layers[1], layers[layer_cout - 1], layers[layer_cout - 2] } )
68 layersToDraw.push_back( i );
69 }
70 else
71 {
72 layersToDraw = layers;
73 }
74
75 const int step = static_cast<int>( aSize.y / layersToDraw.size() );
76
77 for( size_t i = 0; i < layersToDraw.size(); ++i )
78 {
79 const KIGFX::COLOR4D color = settings.GetColor( layersToDraw[i] );
80 brush.SetColour( color.ToColour() );
81 pen.SetColour( color.ToColour() );
82 iconDC.SetBrush( brush );
83 iconDC.SetPen( pen );
84 iconDC.DrawRectangle( 0, i * step, aSize.x, step );
85 }
86
87 return bitmap;
88}
89
90
92 ZONE_SETTINGS_BAG& aZoneSettingsBag ) :
93 m_parent( aParent ),
94 m_frame( aFrame ),
95 m_zoneSettingsBag( aZoneSettingsBag ),
96 m_sortByName( true ),
97 m_sortByNet( true ),
99{
100 m_filteredZones = m_zoneSettingsBag.GetClonedZoneList();
101 Reset( m_filteredZones.size() );
102}
103
104
105void MODEL_ZONES_OVERVIEW::GetValueByRow( wxVariant& aVariant, unsigned aRow, unsigned aCol ) const
106{
107 if( static_cast<size_t>( aRow ) + 1 > m_filteredZones.size() )
108 return;
109
110 const ZONE& cur = *m_filteredZones[aRow];
111
112 switch( aCol )
113 {
114 case NAME:
115 aVariant = cur.GetZoneName();
116 break;
117
118 case NET:
119 aVariant = cur.GetNet()->GetNetname();
120 break;
121
122 case LAYERS:
123 {
124 wxArrayString layers;
125
126 for( PCB_LAYER_ID layer : cur.GetLayerSet().Seq() )
127 layers.Add( m_frame->GetBoard()->GetLayerName( layer ) );
128
129 aVariant << wxDataViewIconText( wxJoin( layers, ',' ),
130 MakeBitmapForLayers( cur.GetLayerSet().UIOrder(), *m_frame->GetColorSettings(),
131 wxSize( LAYER_BAR_WIDTH, LAYER_BAR_HEIGHT ) ) );
132 break;
133 }
134
135 default:
136 break;
137 }
138}
139
140
142{
143 m_sortByName = aEnable;
144}
145
146
148{
149 m_sortByNet = aEnable;
150}
151
152
157
158
159bool MODEL_ZONES_OVERVIEW::SetValueByRow( const wxVariant& aVariant, unsigned aRow, unsigned aCol )
160{
161 return {};
162}
163
164
166{
167 return m_filteredZones.size();
168}
169
170
171ZONE* MODEL_ZONES_OVERVIEW::GetZone( wxDataViewItem const& aItem ) const
172{
173 if( !aItem.IsOk() )
174 return nullptr;
175
176 unsigned int aRow = GetRow( aItem );
177
178 if( aRow + 1 > GetCount() )
179 return nullptr;
180
181 return m_filteredZones[aRow];
182}
183
184
185wxDataViewItem MODEL_ZONES_OVERVIEW::GetItemByZone( ZONE* aZone ) const
186{
187 if( !aZone )
188 return {};
189
190 for( size_t i = 0; i < m_filteredZones.size(); i++ )
191 {
192 if( m_filteredZones[i] == aZone )
193 return GetItem( i );
194 }
195
196 return {};
197}
198
199
200std::optional<unsigned> MODEL_ZONES_OVERVIEW::MoveZoneIndex( unsigned aIndex, ZONE_INDEX_MOVEMENT aMovement )
201{
202 switch( aMovement )
203 {
205 if( aIndex >= 1 && GetCount() > 1 )
206 return SwapZonePriority( aIndex, aIndex - 1 );
207
208 break;
209
211 if( aIndex + 1 < GetCount() )
212 return SwapZonePriority( aIndex, aIndex + 1 );
213
214 break;
215
217 if( aIndex >= 1 && GetCount() > 1 )
218 {
219 unsigned cur = aIndex;
220
221 while( cur > 0 )
222 {
223 SwapZonePriority( cur, cur - 1 );
224 --cur;
225 }
226
227 return 0u;
228 }
229
230 break;
231
233 if( aIndex + 1 < GetCount() )
234 {
235 unsigned cur = aIndex;
236 const unsigned last = GetCount() - 1;
237
238 while( cur < last )
239 {
240 SwapZonePriority( cur, cur + 1 );
241 ++cur;
242 }
243
244 return last;
245 }
246
247 break;
248 }
249
250 return std::optional<unsigned>{};
251}
252
253
254std::optional<unsigned> MODEL_ZONES_OVERVIEW::SwapZonePriority( unsigned aDragIndex, unsigned aDropIndex )
255{
256 for( const unsigned i : { aDragIndex, aDropIndex } )
257 {
258 if( !( i < GetCount() ) )
259 return {};
260 }
261
262 if( aDragIndex == aDropIndex )
263 return aDragIndex;
264
265 m_zoneSettingsBag.SwapPriority( m_filteredZones[aDragIndex], m_filteredZones[aDropIndex] );
266 std::swap( m_filteredZones[aDragIndex], m_filteredZones[aDropIndex] );
267
268 for( const unsigned int row : { aDragIndex, aDropIndex } )
269 RowChanged( row );
270
271 return aDropIndex;
272}
273
274
275wxDataViewItem MODEL_ZONES_OVERVIEW::ApplyFilter( wxString const& aFilterText, wxDataViewItem aSelection )
276{
277 if( m_zoneSettingsBag.GetClonedZoneList().empty() )
278 return {};
279
280 wxString lowerFilterText = aFilterText.Strip( wxString::both ).Lower();
281
282 if( lowerFilterText.empty() )
283 return ClearFilter( aSelection );
284
285 ZONE* selected_zone = GetZone( aSelection );
286 m_filteredZones.clear();
287
288 for( ZONE* zone : m_zoneSettingsBag.GetClonedZoneList() )
289 {
290 if( m_layerFilter != UNDEFINED_LAYER && !zone->GetLayerSet().Contains( m_layerFilter ) )
291 continue;
292
293 if( ( m_sortByName && zone->GetZoneName().Lower().Contains( lowerFilterText ) )
294 || ( m_sortByNet && zone->GetNetname().Lower().Contains( lowerFilterText ) ) )
295 {
296 m_filteredZones.push_back( zone );
297 }
298 }
299
301 Reset( GetCount() );
303 return GetItemByZone( selected_zone );
304}
305
306
307wxDataViewItem MODEL_ZONES_OVERVIEW::ClearFilter( wxDataViewItem aSelection )
308{
309 if( m_zoneSettingsBag.GetClonedZoneList().empty() )
310 return {};
311
312 ZONE* zone = GetZone( aSelection );
313 m_filteredZones.clear();
314
315 for( ZONE* z : m_zoneSettingsBag.GetClonedZoneList() )
316 {
317 if( m_layerFilter == UNDEFINED_LAYER || z->GetLayerSet().Contains( m_layerFilter ) )
318 m_filteredZones.push_back( z );
319 }
320
322 Reset( GetCount() );
324 return GetItemByZone( zone );
325}
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
wxColour ToColour() const
Definition color4d.cpp:221
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition lset.cpp:739
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition lset.cpp:309
bool SetValueByRow(const wxVariant &aVariant, unsigned aRow, unsigned aCol) override
void EnableFitterByNet(bool aEnable)
void GetValueByRow(wxVariant &aVariant, unsigned aRow, unsigned aCol) const override
std::optional< unsigned > SwapZonePriority(unsigned aDragIndex, unsigned aDropIndex)
Swap two zone while drag && drop.
MODEL_ZONES_OVERVIEW(wxWindow *aParent, PCB_BASE_FRAME *aFrame, ZONE_SETTINGS_BAG &aZoneSettingsBag)
wxDataViewItem ClearFilter(wxDataViewItem aSelection)
Clear up the filter.
void SetLayerFilter(PCB_LAYER_ID aLayer)
ZONE * GetZone(wxDataViewItem const &item) const
wxDataViewItem GetItemByZone(ZONE *) const
std::vector< ZONE * > m_filteredZones
std::optional< unsigned > MoveZoneIndex(unsigned aIndex, ZONE_INDEX_MOVEMENT aMovement)
Move selected zone up/down.
void EnableFitterByName(bool aEnable)
unsigned int GetCount() const override
wxDataViewItem ApplyFilter(wxString const &aFilterText, wxDataViewItem aSelection)
Filter the zones by the filter text.
ZONE_SETTINGS_BAG & m_zoneSettingsBag
const wxString & GetNetname() const
Definition netinfo.h:100
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
Handle a list of polygons defining a copper zone.
Definition zone.h:70
const wxString & GetZoneName() const
Definition zone.h:160
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition zone.h:133
void Reset() override
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ UNDEFINED_LAYER
Definition layer_ids.h:57
wxDEFINE_EVENT(EVT_ZONES_OVERVIEW_COUNT_CHANGE, wxCommandEvent)
static wxBitmap MakeBitmapForLayers(LSEQ const &layers, COLOR_SETTINGS const &settings, const wxSize &aSize)
#define LAYER_BAR_HEIGHT
ZONE_INDEX_MOVEMENT
#define LAYER_BAR_WIDTH