KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_assign_netclass.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
22#include <wx/regex.h>
23
25#include <project.h>
28#include <eda_base_frame.h>
29#include <string_utils.h>
30
31
32wxString UpgradeGlobStarToRegex( const wxString& aPattern )
33{
34 // Match a '*' that is NOT preceded by '.'
35 // (needs lookbehind, so no std::regex)
36 static const wxRegEx globStarPattern( wxT( R"((?<!\.)\*)" ) );
37
38 wxString result = aPattern;
39 globStarPattern.ReplaceAll( &result, ".*" );
40 return result;
41}
42
43
44static wxString GetStringCommonPrefix( const wxArrayString& aSet )
45{
46 if( aSet.empty() )
47 return wxEmptyString;
48
49 wxString commonPrefix = *aSet.begin();
50
51 for( const wxString& str : aSet )
52 {
53 const size_t minLength = std::min( commonPrefix.size(), str.size() );
54 size_t matchUntil = 0;
55 while( matchUntil < minLength && commonPrefix[matchUntil] == str[matchUntil] )
56 {
57 ++matchUntil;
58 }
59
60 commonPrefix = commonPrefix.substr( 0, matchUntil );
61
62 // If the common prefix is empty, we can stop early
63 // as there is no common prefix.
64 if( commonPrefix.empty() )
65 break;
66 }
67
68 return commonPrefix;
69}
70
71
86static wxString GetNetclassPatternForSet( const std::set<wxString>& aNetNames )
87{
88 if( aNetNames.empty() )
89 return wxEmptyString;
90
91 if( aNetNames.size() == 1 )
92 {
93 return *aNetNames.begin();
94 }
95
96 wxArrayString netNames;
97 for( const wxString& netName : aNetNames )
98 {
99 // If the net name contains a '*' (e..g it was a bus prefix),
100 // we CAN use it in a pipe-separated regex pattern, but it has to be
101 // upgraded from a glob star to a regex star.
102 netNames.Add( UpgradeGlobStarToRegex( netName ) );
103 }
104
105 // Sort the net names to have a consistent order.
107
108 // Get the common prefix of all net names.
109 const wxString commonPrefix = GetStringCommonPrefix( netNames );
110
111 if( !commonPrefix.IsEmpty() && commonPrefix != wxT( "/" ) )
112 {
113 // If the common prefix is not empty, we can use it to simplify the pattern.
114 // This only works for one prefix, but with tries or similar, we can find
115 // multiple prefixes if that's something we want to do.
116
117 wxArrayString netTails;
118
119 for( const wxString& netName : netNames )
120 {
121 // Add the tail of the net name after the common prefix.
122 netTails.Add( netName.Mid( commonPrefix.size() ) );
123 }
124
125 return commonPrefix + + wxT("(") + wxJoin( netTails, wxT( '|' ) ) + wxT(")");
126 }
127
128 // No better ideas, just a straight pipe-separated list of net names.
129 return wxJoin( netNames, wxT( '|' ) );
130}
131
132
134 const std::set<wxString>& aNetNames,
135 const std::set<wxString> aCandidateNetNames,
136 const std::function<void( const std::vector<wxString>& )>& aPreviewer ) :
138 m_frame( aParent ),
139 m_selectedNetNames( aNetNames ),
140 m_netCandidates( aCandidateNetNames ),
141 m_previewer( aPreviewer )
142{
143 m_matchingNets->SetFont( KIUI::GetInfoFont( this ) );
144 m_info->SetFont( KIUI::GetInfoFont( this ).Italic() );
145
146 // @translate the string below.
147 if( aParent->GetFrameType() == FRAME_PCB_EDITOR )
148 m_info->SetLabel( wxT( "Note: complete netclass assignments can be edited in Board "
149 "Setup > Project." ) );
150
152
154}
155
156
158{
159 if( !wxWindow::TransferDataToWindow() )
160 return false;
161
162 std::shared_ptr<NET_SETTINGS>& netSettings = m_frame->Prj().GetProjectFile().m_NetSettings;
163
165
166 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
167 m_netclassCtrl->Append( name );
168
169 if( m_netclassCtrl->GetCount() > 1 )
170 m_netclassCtrl->SetSelection( 1 ); // First non-Default netclass
171 else
172 m_netclassCtrl->SetSelection( 0 ); // Default netclass
173
174 const wxString initialNetclassPattern = GetNetclassPatternForSet( m_selectedNetNames );
175 m_patternCtrl->SetValue( initialNetclassPattern );
176
177 return true;
178}
179
180
182{
183 std::shared_ptr<NET_SETTINGS>& netSettings = m_frame->Prj().GetProjectFile().m_NetSettings;
184
185 if( m_patternCtrl->GetValue().IsEmpty() )
186 return true;
187
188 netSettings->SetNetclassPatternAssignment( m_patternCtrl->GetValue(),
189 m_netclassCtrl->GetStringSelection() );
190
191 return true;
192}
193
194
195void DIALOG_ASSIGN_NETCLASS::onPatternText( wxCommandEvent& aEvent )
196{
197 wxString pattern = m_patternCtrl->GetValue();
198
199 if( pattern != m_lastPattern )
200 {
201 m_matchingNets->Clear();
202
203 std::vector<wxString> matchingNetNames;
204
205 if( !pattern.IsEmpty() )
206 {
207 EDA_COMBINED_MATCHER matcher( pattern, CTX_NETCLASS );
208
209 m_matchingNets->Report( _( "<b>Currently matching nets:</b>" ) );
210
211 for( const wxString& net : m_netCandidates )
212 {
213 if( matcher.StartsWith( net ) )
214 {
215 m_matchingNets->Report( net );
216 matchingNetNames.push_back( net );
217 }
218 }
219 }
220
221 m_matchingNets->Flush();
222
223 m_previewer( matchingNetNames );
224 m_lastPattern = pattern;
225 }
226}
const char * name
DIALOG_ASSIGN_NETCLASS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Add Netclass Assignment"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE)
void onPatternText(wxCommandEvent &aEvent) override
const std::set< wxString > m_selectedNetNames
std::function< void(const std::vector< wxString > &)> m_previewer
DIALOG_ASSIGN_NETCLASS(EDA_BASE_FRAME *aParent, const std::set< wxString > &aNetNames, const std::set< wxString > aCandidateNetNames, const std::function< void(const std::vector< wxString > &)> &aPreviewer)
std::set< wxString > m_netCandidates
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
The base frame for deriving all KiCad main window classes.
FRAME_T GetFrameType() const
bool StartsWith(const wxString &aTerm)
static const char Default[]
the name of the default NETCLASS
Definition netclass.h:40
static wxString GetStringCommonPrefix(const wxArrayString &aSet)
static wxString GetNetclassPatternForSet(const std::set< wxString > &aNetNames)
Propose a netclass pattern for a set of net names.
wxString UpgradeGlobStarToRegex(const wxString &aPattern)
#define _(s)
Base window classes and related definitions.
@ CTX_NETCLASS
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
void StrNumSort(T &aList, CASE_SENSITIVITY aCaseSensitivity)
Sort a container of wxString objects, in place, using the StrNumCmp() function.
wxString result
Test unit parsing edge cases and error handling.