KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_selection_filter.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) 2020 Jon Evans <[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 modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <pcb_base_edit_frame.h>
22#include <tool/tool_manager.h>
25#include <wx/settings.h>
26#include <wx/dcbuffer.h>
27
28
29wxDEFINE_EVENT( EVT_PCB_SELECTION_FILTER_FLASH, PCB_SELECTION_FILTER_EVENT );
30
33 m_frame( dynamic_cast<PCB_BASE_EDIT_FRAME*>( aParent ) ),
34 m_onlyCheckbox( nullptr )
35{
36 wxFont font = KIUI::GetInfoFont( this );
37 m_cbLockedItems->SetFont( font );
38 m_cbFootprints->SetFont( font );
39 m_cbText->SetFont( font );
40 m_cbTracks->SetFont( font );
41 m_cbVias->SetFont( font );
42 m_cbPads->SetFont( font );
43 m_cbGraphics->SetFont( font );
44 m_cbZones->SetFont( font );
45 m_cbKeepouts->SetFont( font );
46 m_cbDimensions->SetFont( font );
47 m_cbPoints->SetFont( font );
48 m_cbOtherItems->SetFont( font );
49 m_cbAllItems->SetFont( font );
50
51 SetBorders( true, false, false, false );
52
53 wxASSERT( m_frame );
54 m_tool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
55 wxASSERT( m_tool );
56
57 PCB_SELECTION_FILTER_OPTIONS& opts = m_tool->GetFilter();
59
60 m_cbFootprints->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
61 m_cbText->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
62 m_cbTracks->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
63 m_cbVias->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
64 m_cbPads->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
65 m_cbGraphics->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
66 m_cbZones->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
67 m_cbKeepouts->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
68 m_cbDimensions->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
69 m_cbPoints->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
70 m_cbOtherItems->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this );
71
72 m_frame->Bind( EDA_LANG_CHANGED, &PANEL_SELECTION_FILTER::OnLanguageChanged, this );
73
74 SetMinSize( GetBestSize() );
75
76 m_flashSteps = 10;
77 m_defaultBg = GetBackgroundColour();
78 m_flashTimer.SetOwner( this );
79 Bind( wxEVT_TIMER, &PANEL_SELECTION_FILTER::onFlashTimer, this );
80 aParent->Bind( EVT_PCB_SELECTION_FILTER_FLASH, &PANEL_SELECTION_FILTER::OnFlashEvent, this );
81}
82
83
85{
86 // Stop any active flashing
87 m_flashTimer.Stop();
88 if( !m_flashCounters.empty() )
89 {
90 Unbind( wxEVT_PAINT, &PANEL_SELECTION_FILTER::onPanelPaint, this );
91 }
92 m_flashCounters.clear();
93
94 m_frame->Unbind( EDA_LANG_CHANGED, &PANEL_SELECTION_FILTER::OnLanguageChanged, this );
95 m_frame->Unbind( EVT_PCB_SELECTION_FILTER_FLASH, &PANEL_SELECTION_FILTER::OnFlashEvent, this );
96}
97
98
100{
101 Freeze();
102
103 m_cbLockedItems->SetValue( aOptions.lockedItems );
104 m_cbFootprints->SetValue( aOptions.footprints );
105 m_cbText->SetValue( aOptions.text );
106 m_cbTracks->SetValue( aOptions.tracks );
107 m_cbVias->SetValue( aOptions.vias );
108 m_cbPads->SetValue( aOptions.pads );
109 m_cbGraphics->SetValue( aOptions.graphics );
110 m_cbZones->SetValue( aOptions.zones );
111 m_cbKeepouts->SetValue( aOptions.keepouts );
112 m_cbDimensions->SetValue( aOptions.dimensions );
113 m_cbPoints->SetValue( aOptions.points );
114 m_cbOtherItems->SetValue( aOptions.otherItems );
115
116 m_cbAllItems->SetValue( aOptions.All() );
117
118 Thaw();
119}
120
121
122void PANEL_SELECTION_FILTER::OnFilterChanged( wxCommandEvent& aEvent )
123{
124 if( aEvent.GetEventObject() == m_cbAllItems )
125 {
126 bool newState = m_cbAllItems->GetValue();
127
128 m_cbFootprints->SetValue( newState );
129 m_cbText->SetValue( newState );
130 m_cbTracks->SetValue( newState );
131 m_cbVias->SetValue( newState );
132 m_cbPads->SetValue( newState );
133 m_cbGraphics->SetValue( newState );
134 m_cbZones->SetValue( newState );
135 m_cbKeepouts->SetValue( newState );
136 m_cbDimensions->SetValue( newState );
137 m_cbPoints->SetValue( newState );
138 m_cbOtherItems->SetValue( newState );
139 }
140
141 PCB_SELECTION_FILTER_OPTIONS& opts = m_tool->GetFilter();
142
143 // If any of the other checkboxes turned off, turn off the All Items checkbox
144 bool allChecked = setFilterFromCheckboxes( opts );
145 m_cbAllItems->SetValue( allChecked );
146}
147
148
150{
151 aOptions.lockedItems = m_cbLockedItems->GetValue();
152 aOptions.footprints = m_cbFootprints->GetValue();
153 aOptions.text = m_cbText->GetValue();
154 aOptions.tracks = m_cbTracks->GetValue();
155 aOptions.vias = m_cbVias->GetValue();
156 aOptions.pads = m_cbPads->GetValue();
157 aOptions.graphics = m_cbGraphics->GetValue();
158 aOptions.zones = m_cbZones->GetValue();
159 aOptions.keepouts = m_cbKeepouts->GetValue();
160 aOptions.dimensions = m_cbDimensions->GetValue();
161 aOptions.points = m_cbPoints->GetValue();
162 aOptions.otherItems = m_cbOtherItems->GetValue();
163
164 return aOptions.All();
165}
166
167
168void PANEL_SELECTION_FILTER::onRightClick( wxMouseEvent& aEvent )
169{
170 wxMenu menu;
171
172 wxCheckBox* cb = dynamic_cast<wxCheckBox*>( aEvent.GetEventObject() );
173
174 if( !cb )
175 return;
176
177 m_onlyCheckbox = cb;
178
179 wxString label;
180 label.Printf( _( "Only %s" ), cb->GetLabel().Lower() );
181
182 menu.Append( new wxMenuItem( &menu, wxID_ANY, label, wxEmptyString, wxITEM_NORMAL ) );
183
184 menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_SELECTION_FILTER::onPopupSelection, this );
185
186 PopupMenu( &menu );
187}
188
189
190void PANEL_SELECTION_FILTER::onPopupSelection( wxCommandEvent& aEvent )
191{
192 if( !m_onlyCheckbox )
193 return;
194
195 m_cbAllItems->SetValue( false );
196 m_cbFootprints->SetValue( false );
197 m_cbText->SetValue( false );
198 m_cbTracks->SetValue( false );
199 m_cbVias->SetValue( false );
200 m_cbPads->SetValue( false );
201 m_cbGraphics->SetValue( false );
202 m_cbZones->SetValue( false );
203 m_cbKeepouts->SetValue( false );
204 m_cbDimensions->SetValue( false );
205 m_cbPoints->SetValue( false );
206 m_cbOtherItems->SetValue( false );
207
208 m_onlyCheckbox->SetValue( true );
209 m_onlyCheckbox = nullptr;
210
211 wxCommandEvent dummy;
213}
214
215
216void PANEL_SELECTION_FILTER::OnLanguageChanged( wxCommandEvent& aEvent )
217{
218 m_cbAllItems->SetLabel( _( "All items" ) );
219 m_cbLockedItems->SetLabel( _( "Locked items" ) );
220 m_cbLockedItems->SetToolTip( _( "Allow selection of locked items" ) );
221 m_cbFootprints->SetLabel( _( "Footprints" ) );
222 m_cbText->SetLabel( _( "Text" ) );
223 m_cbTracks->SetLabel( _( "Tracks" ) );
224 m_cbVias->SetLabel( _( "Vias" ) );
225 m_cbPads->SetLabel( _( "Pads" ) );
226 m_cbGraphics->SetLabel( _( "Graphics" ) );
227 m_cbZones->SetLabel( _( "Zones" ) );
228 m_cbKeepouts->SetLabel( _( "Rule Areas" ) );
229 m_cbDimensions->SetLabel( _( "Dimensions" ) );
230 m_cbPoints->SetLabel( _( "Points" ) );
231 m_cbOtherItems->SetLabel( _( "Other items" ) );
232
233 m_cbAllItems->GetParent()->Layout();
234
235 aEvent.Skip();
236}
237
238
240{
241 if( !aBox )
242 return;
243
244 // If already flashing, just reset the counter
245 if( m_flashCounters.find( aBox ) != m_flashCounters.end() )
246 {
248 return;
249 }
250
252 m_defaultBg = aBox->GetBackgroundColour();
253
254 // Bind paint event to this panel if not already bound
255 if( m_flashCounters.size() == 1 )
256 {
257 Bind( wxEVT_PAINT, &PANEL_SELECTION_FILTER::onPanelPaint, this );
258 }
259
260 Refresh();
261}
262
263
264void PANEL_SELECTION_FILTER::onFlashTimer( wxTimerEvent& aEvent )
265{
266 for( auto it = m_flashCounters.begin(); it != m_flashCounters.end(); )
267 {
268 int step = --( it->second );
269
270 if( step <= 0 )
271 it = m_flashCounters.erase( it );
272 else
273 ++it;
274 }
275
276 if( m_flashCounters.empty() )
277 {
278 m_flashTimer.Stop();
279 // Unbind paint event when no more flashing
280 Unbind( wxEVT_PAINT, &PANEL_SELECTION_FILTER::onPanelPaint, this );
281 }
282
283 Refresh();
284}
285
286
287void PANEL_SELECTION_FILTER::onPanelPaint( wxPaintEvent& aEvent )
288{
289 wxPaintDC dc( this );
290
291 // First, let the default painting happen
292 aEvent.Skip();
293
294 // Then draw our highlights on top
295 for( auto& pair : m_flashCounters )
296 {
297 wxCheckBox* checkbox = pair.first;
298 int step = pair.second;
299
300 if( step > 0 )
301 {
302 // Get the checkbox position relative to this panel
303 wxPoint checkboxPos = checkbox->GetPosition();
304 wxSize checkboxSize = checkbox->GetSize();
305 wxRect checkboxRect( checkboxPos, checkboxSize );
306
307 // Calculate blended color based on current flash step
308 wxColour highlight = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT );
309 wxColour blend(
310 ( highlight.Red() * step + m_defaultBg.Red() * ( m_flashSteps - step ) ) / m_flashSteps,
311 ( highlight.Green() * step + m_defaultBg.Green() * ( m_flashSteps - step ) ) / m_flashSteps,
312 ( highlight.Blue() * step + m_defaultBg.Blue() * ( m_flashSteps - step ) ) / m_flashSteps );
313
314 // Draw semi-transparent overlay
315 wxColour overlayColor( blend.Red(), blend.Green(), blend.Blue(), 128 );
316 dc.SetBrush( wxBrush( overlayColor ) );
317 dc.SetPen( wxPen( overlayColor ) );
318 dc.DrawRectangle( checkboxRect );
319 }
320 }
321}
322
323
325{
326 const PCB_SELECTION_FILTER_OPTIONS& aOptions = aEvent.m_options;
327
328 if( aOptions.lockedItems )
330
331 if( aOptions.footprints )
333
334 if( aOptions.text )
336
337 if( aOptions.tracks )
339
340 if( aOptions.vias )
342
343 if( aOptions.pads )
345
346 if( aOptions.graphics )
348
349 if( aOptions.zones )
351
352 if( aOptions.keepouts )
354
355 if( aOptions.dimensions )
357
358 if( aOptions.points )
360
361 if( aOptions.otherItems )
363
364 if( !m_flashCounters.empty() )
365 m_flashTimer.Start( 50 );
366}
PANEL_SELECTION_FILTER_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
PCB_BASE_EDIT_FRAME * m_frame
void onPopupSelection(wxCommandEvent &aEvent)
std::map< wxCheckBox *, int > m_flashCounters
void flashCheckbox(wxCheckBox *aBox)
PCB_SELECTION_TOOL * m_tool
bool setFilterFromCheckboxes(PCB_SELECTION_FILTER_OPTIONS &aOptions)
PANEL_SELECTION_FILTER(wxWindow *aParent)
void OnFlashEvent(PCB_SELECTION_FILTER_EVENT &aEvent)
void SetCheckboxesFromFilter(PCB_SELECTION_FILTER_OPTIONS &aOptions)
void onFlashTimer(wxTimerEvent &aEvent)
void OnLanguageChanged(wxCommandEvent &aEvent)
void OnFilterChanged(wxCommandEvent &aEvent) override
void onRightClick(wxMouseEvent &aEvent)
void onPanelPaint(wxPaintEvent &aEvent)
Common, abstract interface for edit frames.
PCB_SELECTION_FILTER_OPTIONS m_options
The selection tool: currently supports:
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition wx_panel.h:39
#define _(s)
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
wxDEFINE_EVENT(EVT_PCB_SELECTION_FILTER_FLASH, PCB_SELECTION_FILTER_EVENT)
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
std::vector< FAB_LAYER_COLOR > dummy
This file contains data structures that are saved in the project file or project local settings file ...
bool otherItems
Anything not fitting one of the above categories.
bool graphics
Graphic lines, shapes, polygons.
bool footprints
Allow selecting entire footprints.
bool text
Text (free or attached to a footprint)
bool lockedItems
Allow selecting locked items.