KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_design_block_properties.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) 2024 Mike Williams <[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, 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
27#include <wx/msgdlg.h>
28#include <wx/tooltip.h>
29#include <grid_tricks.h>
31#include <bitmaps.h>
32
33#include <design_block.h>
34
36 DESIGN_BLOCK* aDesignBlock,
37 bool aDisableName ) :
38 DIALOG_DESIGN_BLOCK_PROPERTIES_BASE( aParent ), m_designBlock( aDesignBlock )
39{
40 m_textName->SetEditable( !aDisableName );
41
42 wxToolTip::Enable( true );
44
45 // Configure button logos
46 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
47 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
48 m_bpMoveUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
49 m_bpMoveDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
50
51 m_fieldsGrid->SetUseNativeColLabels();
52
53 m_fieldsGrid->PushEventHandler( new GRID_TRICKS( m_fieldsGrid,
54 [this]( wxCommandEvent& aEvent )
55 {
56 OnAddField( aEvent );
57 } ) );
58 m_fieldsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
59}
60
61
63{
64 // Delete the GRID_TRICKS.
65 m_fieldsGrid->PopEventHandler( true );
66}
67
68
70{
74
75 // Typical assignment operator does not work here because of the ordered_map
76 auto source = m_designBlock->GetFields();
77 m_fields.clear();
78
79 for( const auto& field : source )
80 {
81 m_fields[field.first] = field.second;
82 }
83
84 return TransferDataToGrid();
85}
86
87
89{
90 unsigned int illegalCh = LIB_ID::FindIllegalLibraryNameChar( m_textName->GetValue() );
91
92 // Also check for / in the name, since this is a path character which is illegal for
93 // design blocks and footprints but not symbols
94 if( illegalCh == 0 && m_textName->GetValue().Find( '/' ) != wxNOT_FOUND )
95 illegalCh = '/';
96
97 if( illegalCh )
98 {
99 wxString msg = wxString::Format( _( "Illegal character '%c' in name '%s'." ),
100 illegalCh,
101 m_textName->GetValue() );
102
103 wxMessageDialog errdlg( this, msg, _( "Error" ) );
104 errdlg.ShowModal();
105 return false;
106 }
107
111
112 return TransferDataFromGrid();
113}
114
115
117{
119 return;
120
121 int row = m_fieldsGrid->GetNumberRows();
122
123 m_fieldsGrid->AppendRows( 1 );
124
125 m_fieldsGrid->SetCellValue( row, 0, _( "Untitled Field" ) );
126 //m_fieldsGrid->SetCellValue( row, 1, wxEmptyString );
127
128 // Set cell properties
129 m_fieldsGrid->SetCellAlignment( row, 0, wxALIGN_LEFT, wxALIGN_CENTRE );
130 m_fieldsGrid->SetCellAlignment( row, 1, wxALIGN_LEFT, wxALIGN_CENTRE );
131
132 // wx documentation is wrong, SetGridCursor does not make visible.
133 m_fieldsGrid->MakeCellVisible( row, 0 );
134 m_fieldsGrid->SetGridCursor( row, 0 );
135}
136
137
139{
141 return;
142
143 wxArrayInt selectedRows = m_fieldsGrid->GetSelectedRows();
144
145 if( selectedRows.empty() && m_fieldsGrid->GetGridCursorRow() >= 0 )
146 selectedRows.push_back( m_fieldsGrid->GetGridCursorRow() );
147
148 if( selectedRows.empty() )
149 return;
150
151 // Reverse sort so deleting a row doesn't change the indexes of the other rows.
152 selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } );
153
154 for( int row : selectedRows )
155 {
156 m_fieldsGrid->DeleteRows( row );
157
158 m_fieldsGrid->MakeCellVisible( std::max( 0, row - 1 ), m_fieldsGrid->GetGridCursorCol() );
159 m_fieldsGrid->SetGridCursor( std::max( 0, row - 1 ), m_fieldsGrid->GetGridCursorCol() );
160 }
161}
162
163
165{
167 return;
168
169 int row = m_fieldsGrid->GetGridCursorRow();
170
171 if( m_fieldsGrid->GetNumberRows() < 2 || row == 0 )
172 return;
173
174 // Swap the grid at row with the grid at row - 1
175 wxString temp0 = m_fieldsGrid->GetCellValue( row, 0 );
176 m_fieldsGrid->SetCellValue( row, 0, m_fieldsGrid->GetCellValue( row - 1, 0 ) );
177 m_fieldsGrid->SetCellValue( row - 1, 0, temp0 );
178
179 wxString temp1 = m_fieldsGrid->GetCellValue( row, 1 );
180 m_fieldsGrid->SetCellValue( row, 1, m_fieldsGrid->GetCellValue( row - 1, 1 ) );
181 m_fieldsGrid->SetCellValue( row - 1, 1, temp1 );
182
183 m_fieldsGrid->SetGridCursor( row - 1, 0 );
184}
185
186
188{
190 return;
191
192 int row = m_fieldsGrid->GetGridCursorRow();
193
194 if( m_fieldsGrid->GetNumberRows() < 2 || row == ( (int) m_fieldsGrid->GetNumberRows() - 1 ) )
195 return;
196
197 // Swap the grid at row with the grid at row + 1
198 wxString temp0 = m_fieldsGrid->GetCellValue( row, 0 );
199 m_fieldsGrid->SetCellValue( row, 0, m_fieldsGrid->GetCellValue( row + 1, 0 ) );
200 m_fieldsGrid->SetCellValue( row + 1, 0, temp0 );
201
202 wxString temp1 = m_fieldsGrid->GetCellValue( row, 1 );
203 m_fieldsGrid->SetCellValue( row, 1, m_fieldsGrid->GetCellValue( row + 1, 1 ) );
204 m_fieldsGrid->SetCellValue( row + 1, 1, temp1 );
205
206 m_fieldsGrid->SetGridCursor( row + 1, 0 );
207}
208
209
211{
212 m_fieldsGrid->Freeze();
213
215 m_fieldsGrid->AppendRows( m_fields.size() );
216
217 int row = 0;
218
219 for( const auto& [fieldName, fieldValue] : m_fields )
220 {
221 m_fieldsGrid->SetCellValue( row, 0, fieldName );
222 m_fieldsGrid->SetCellValue( row, 1, fieldValue );
223
224 // Set cell properties
225 m_fieldsGrid->SetCellAlignment( row, 0, wxALIGN_LEFT, wxALIGN_CENTRE );
226 m_fieldsGrid->SetCellAlignment( row, 1, wxALIGN_LEFT, wxALIGN_CENTRE );
227
228 row++;
229 }
230
231 m_fieldsGrid->Thaw();
232
233 return true;
234}
235
236
238{
240 return false;
241
242 nlohmann::ordered_map<wxString, wxString> newFields;
243
244 for( int row = 0; row < m_fieldsGrid->GetNumberRows(); row++ )
245 {
246 wxString fieldName = m_fieldsGrid->GetCellValue( row, 0 ).Strip();
247 fieldName.Replace( wxT( "\n" ), wxT( "" ), true ); // strip all newlines
248 fieldName.Replace( wxT( " " ), wxT( " " ), true ); // double space to single
249
250 if( newFields.count( fieldName ) )
251 {
252 wxMessageBox( _( "Duplicate fields are not allowed." ) );
253 return false;
254 }
255
256 newFields[fieldName] = m_fieldsGrid->GetCellValue( row, 1 );
257 }
258
259 m_designBlock->SetFields( newFields );
260
261 return true;
262}
263
264
266{
267 if( aWidth <= 0 )
268 return;
269
270 // Account for scroll bars
271 aWidth -= ( m_fieldsGrid->GetSize().x - m_fieldsGrid->GetClientSize().x );
272
273 m_fieldsGrid->SetColSize( 1, aWidth - m_fieldsGrid->GetColSize( 0 ) );
274}
275
276
278{
279 AdjustGridColumns( event.GetSize().GetX() );
280
281 event.Skip();
282}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
void SetLibDescription(const wxString &aDesc)
Definition: design_block.h:40
void SetKeywords(const wxString &aKeywords)
Definition: design_block.h:43
const wxString & GetKeywords() const
Definition: design_block.h:42
const wxString & GetLibDescription() const
Definition: design_block.h:39
void SetLibId(const LIB_ID &aName)
Definition: design_block.h:36
void SetFields(nlohmann::ordered_map< wxString, wxString > &aFields)
Definition: design_block.h:51
const LIB_ID & GetLibId() const
Definition: design_block.h:37
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
Definition: design_block.h:56
Class DIALOG_DESIGN_BLOCK_PROPERTIES_BASE.
void OnDeleteField(wxCommandEvent &aEvent) override
void OnSizeGrid(wxSizeEvent &event) override
void OnMoveFieldUp(wxCommandEvent &aEvent) override
void OnMoveFieldDown(wxCommandEvent &aEvent) override
void OnAddField(wxCommandEvent &aEvent) override
DIALOG_DESIGN_BLOCK_PROPERTIES(wxWindow *aParent, DESIGN_BLOCK *aDesignBlock, bool aDisableName=false)
nlohmann::ordered_map< wxString, wxString > m_fields
void SetupStandardButtons(std::map< int, wxString > aLabels={})
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
static unsigned FindIllegalLibraryNameChar(const UTF8 &aLibraryName)
Looks for characters that are illegal in library nicknames.
Definition: lib_id.cpp:241
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
void SetBitmap(const wxBitmapBundle &aBmp)
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:203
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:649
#define _(s)