KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_setup_severities.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21#include <widgets/ui_common.h>
22#include <rc_item.h>
24#include <wx/radiobut.h>
25#include <wx/scrolwin.h>
26#include <wx/sizer.h>
27#include <wx/stattext.h>
28#include <wx/statline.h>
29#include "confirm.h"
30
31
33 std::vector<std::reference_wrapper<RC_ITEM>> aItems,
34 std::map<int, SEVERITY>& aSeverities,
35 RC_ITEM* aPinMapSpecialCase ) :
36 wxPanel( aParentWindow ),
37 m_severities( aSeverities ),
38 m_items( std::move( aItems ) ),
39 m_pinMapSpecialCase( aPinMapSpecialCase )
40{
41 wxString severities[] = { _( "Error" ), _( "Warning" ), _( "Ignore" ) };
42 int severityCount = sizeof( severities ) / sizeof( wxString );
43 int baseID = 1000;
44 wxBoxSizer* panelSizer = new wxBoxSizer( wxVERTICAL );
45 wxScrolledWindow* scrollWin = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
46 wxTAB_TRAVERSAL | wxVSCROLL );
47 bool firstLine = true;
48
49 scrollWin->SetScrollRate( 0, 5 );
50
51 wxBoxSizer* scrollWinSizer = new wxBoxSizer( wxVERTICAL );
52 scrollWin->SetSizer( scrollWinSizer );
53
54 wxFlexGridSizer* gridSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
55 gridSizer->SetFlexibleDirection( wxBOTH );
56
57 for( const std::reference_wrapper<RC_ITEM>& item : m_items )
58 {
59 int errorCode = item.get().GetErrorCode();
60 wxString msg = item.get().GetErrorText( true );
61
62 if( m_pinMapSpecialCase && errorCode == m_pinMapSpecialCase->GetErrorCode() )
63 continue;
64
65 if( errorCode == 0 )
66 {
67 wxStaticText* heading = new wxStaticText( scrollWin, wxID_ANY, msg );
68 wxStaticLine* underline1 = new wxStaticLine( scrollWin, wxHORIZONTAL );
69 wxStaticLine* underline2 = new wxStaticLine( scrollWin, wxHORIZONTAL );
70
71 if( !firstLine )
72 {
73 gridSizer->AddSpacer( 5 ); // col 1
74 gridSizer->AddSpacer( 5 ); // col 2
75 }
76
77 gridSizer->Add( heading, 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 13 );
78 gridSizer->AddSpacer( 0 ); // col 2
79
80 gridSizer->Add( underline1, 0, wxTOP | wxBOTTOM | wxEXPAND, 2 );
81 gridSizer->Add( underline2, 0, wxTOP | wxBOTTOM | wxEXPAND, 2 ); // col 2
82 }
83 else if( !msg.IsEmpty() ) // items with no message are for internal use only
84 {
85 wxStaticText* errorLabel = new wxStaticText( scrollWin, wxID_ANY, msg + wxT( ":" ) );
86 gridSizer->Add( errorLabel, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 7 );
87
88 // OSX can't handle more than 100 radio buttons in a single window (yes, seriously),
89 // so we have to create a window for each set
90 wxPanel* radioPanel = new wxPanel( scrollWin );
91 wxBoxSizer* radioSizer = new wxBoxSizer( wxHORIZONTAL );
92
93 for( int i = 0; i < severityCount; ++i )
94 {
95 m_buttonMap[ errorCode ][i] = new wxRadioButton( radioPanel,
96 baseID + errorCode * 10 + i,
97 severities[i],
98 wxDefaultPosition, wxDefaultSize,
99 i == 0 ? wxRB_GROUP : 0 );
100 radioSizer->Add( m_buttonMap[ errorCode ][i], 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 30 );
101 }
102
103 radioPanel->SetSizer( radioSizer );
104 radioPanel->Layout();
105 gridSizer->Add( radioPanel, 0, wxTOP, 5 );
106 }
107
108 firstLine = false;
109 }
110
111
113 {
114 gridSizer->AddSpacer( 5 ); // col 1
115 gridSizer->AddSpacer( 5 ); // col 2
116
117 wxString pinMapSeverities[] = { _( "From Pin Conflicts Map" ), wxT( "" ), _( "Ignore" ) };
118 int errorCode = m_pinMapSpecialCase->GetErrorCode();
119 wxString msg = m_pinMapSpecialCase->GetErrorText( true );
120
121 wxStaticText* errorLabel = new wxStaticText( scrollWin, wxID_ANY, msg + wxT( ":" ) );
122 gridSizer->Add( errorLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 7 );
123
124 wxPanel* radioPanel = new wxPanel( scrollWin );
125 wxBoxSizer* radioSizer = new wxBoxSizer( wxHORIZONTAL );
126
127 for( size_t i = 0; i < sizeof( pinMapSeverities ) / sizeof( wxString ); ++i )
128 {
129 if( pinMapSeverities[i] == wxT( "" ) )
130 {
131 wxStaticText* spacer = new wxStaticText( radioPanel, wxID_ANY, wxT( "" ) );
132 radioSizer->Add( spacer, 0, wxRIGHT | wxEXPAND, 22 );
133 }
134 else
135 {
136 m_buttonMap[ errorCode ][i] = new wxRadioButton( radioPanel,
137 baseID + errorCode * 10 + i,
138 pinMapSeverities[i],
139 wxDefaultPosition, wxDefaultSize,
140 i == 0 ? wxRB_GROUP : 0 );
141 radioSizer->Add( m_buttonMap[ errorCode ][i], 0, wxEXPAND );
142 }
143 }
144
145 radioPanel->SetSizer( radioSizer );
146 radioPanel->Layout();
147 gridSizer->Add( radioPanel, 0, wxALIGN_CENTER_VERTICAL );
148 }
149
150 scrollWinSizer->Add( gridSizer, 1, wxEXPAND | wxALL, 5 );
151 panelSizer->Add( scrollWin, 1, wxEXPAND, 0 );
152
153 Bind( wxEVT_IDLE,
154 [this]( wxIdleEvent& aEvent )
155 {
157 {
158 wxWindow* dialog = wxGetTopLevelParent( this );
159 wxWindow* topLevelFocus = wxGetTopLevelParent( wxWindow::FindFocus() );
160
161 if( topLevelFocus == dialog )
162 checkReload();
163 }
164 } );
165
166 SetSizer( panelSizer );
167 Layout();
168 panelSizer->Fit( this );
169}
170
171
173{
174 // MUST update lastLoaded before calling IsOK (or we'll end up re-entering through the idle
175 // event until we crash the stack).
177
178 if( IsOK( m_parent, _( "The violation severities have been changed outside the Setup dialog.\n"
179 "Do you wish to reload them?" ) ) )
180 {
182 }
183}
184
185
186void PANEL_SETUP_SEVERITIES::ImportSettingsFrom( std::map<int, SEVERITY>& aSettings )
187{
188 for( const std::reference_wrapper<RC_ITEM>& item : m_items )
189 {
190 int errorCode = item.get().GetErrorCode();
191
192 wxRadioButton* button = nullptr;
193
194 switch( aSettings[ errorCode ] )
195 {
196 case RPT_SEVERITY_ERROR: button = m_buttonMap[ errorCode ][0]; break;
197 case RPT_SEVERITY_WARNING: button = m_buttonMap[ errorCode ][1]; break;
198 case RPT_SEVERITY_IGNORE: button = m_buttonMap[ errorCode ][2]; break;
199 default: break;
200 }
201
202 if( button ) // this entry must actually exist
203 button->SetValue( true );
204 }
205
207 {
208 int pinMapCode = m_pinMapSpecialCase->GetErrorCode();
209 int newSeverity = aSettings[ pinMapCode ];
210
211 m_buttonMap[ pinMapCode ][0]->SetValue( newSeverity != RPT_SEVERITY_IGNORE );
212 m_buttonMap[ pinMapCode ][2]->SetValue( newSeverity == RPT_SEVERITY_IGNORE );
213 }
214}
215
216
218{
220
221 for( const std::reference_wrapper<RC_ITEM>& item : m_items )
222 {
223 int errorCode = item.get().GetErrorCode();
224
225 if( !m_buttonMap[ errorCode ][0] ) // this entry does not actually exist
226 continue;
227
228 if( m_pinMapSpecialCase && errorCode == m_pinMapSpecialCase->GetErrorCode() )
229 continue;
230
231 switch( m_severities[ errorCode ] )
232 {
233 case RPT_SEVERITY_ERROR: m_buttonMap[ errorCode ][0]->SetValue( true ); break;
234 case RPT_SEVERITY_WARNING: m_buttonMap[ errorCode ][1]->SetValue( true ); break;
235 case RPT_SEVERITY_IGNORE: m_buttonMap[ errorCode ][2]->SetValue( true ); break;
236 default: break;
237 }
238 }
239
241 {
242 int pinMapCode = m_pinMapSpecialCase->GetErrorCode();
243 int severity = m_severities[pinMapCode];
244
245 m_buttonMap[ pinMapCode ][0]->SetValue( severity != RPT_SEVERITY_IGNORE );
246 m_buttonMap[ pinMapCode ][2]->SetValue( severity == RPT_SEVERITY_IGNORE );
247 }
248
249 return true;
250}
251
252
254{
255 for( const std::reference_wrapper<RC_ITEM>& item : m_items )
256 {
257 int errorCode = item.get().GetErrorCode();
258
259 if( m_pinMapSpecialCase && m_pinMapSpecialCase->GetErrorCode() == errorCode )
260 continue;
261
262 if( !m_buttonMap[ errorCode ][0] ) // this entry does not actually exist
263 continue;
264
266
267 if( m_buttonMap[ errorCode ][0]->GetValue() ) severity = RPT_SEVERITY_ERROR;
268 else if( m_buttonMap[ errorCode ][1]->GetValue() ) severity = RPT_SEVERITY_WARNING;
269 else if( m_buttonMap[ errorCode ][2]->GetValue() ) severity = RPT_SEVERITY_IGNORE;
270
271 m_severities[ errorCode ] = severity;
272 }
273
275 {
276 int pinMapCode = m_pinMapSpecialCase->GetErrorCode();
278
279 if( m_buttonMap[ pinMapCode ][0]->GetValue() ) severity = RPT_SEVERITY_ERROR;
280 else if( m_buttonMap[ pinMapCode ][2]->GetValue() ) severity = RPT_SEVERITY_IGNORE;
281
282 m_severities[ pinMapCode ] = severity;
283 }
284
285 return true;
286}
void ImportSettingsFrom(std::map< int, SEVERITY > &aSettings)
std::map< int, SEVERITY > & m_severities
RC_ITEM * m_pinMapSpecialCase
For ERC settings; a pointer to ERC_ITEM::pinTableConflict.
PANEL_SETUP_SEVERITIES(wxWindow *aParentWindow, std::vector< std::reference_wrapper< RC_ITEM > > aItems, std::map< int, SEVERITY > &aSeverities, RC_ITEM *aPinMapSpecialCase=nullptr)
Create the severities setup panel.
std::map< int, wxRadioButton *[4]> m_buttonMap
std::map< int, SEVERITY > m_lastLoaded
std::vector< std::reference_wrapper< RC_ITEM > > m_items
A list of item templates (to get descriptive text and error codes from)
A holder for a rule check item, DRC in Pcbnew or ERC in Eeschema.
Definition rc_item.h:79
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
This file is part of the common library.
#define _(s)
STL namespace.
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_UNDEFINED
@ RPT_SEVERITY_IGNORE
Functions to provide common constants and other functions to assist in making a consistent UI.