KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbnew/dialogs/dialog_table_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 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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <kiplatform/ui.h>
27#include <widgets/font_choice.h>
29#include <widgets/wx_grid.h>
32#include <grid_tricks.h>
33#include <scintilla_tricks.h>
34#include <string_utils.h>
35#include <confirm.h>
36#include <board.h>
37#include <board_commit.h>
39#include <footprint.h>
40#include <pcb_textbox.h>
41#include <pcb_tablecell.h>
42#include <pcb_table.h>
43#include <project.h>
44#include <pcb_edit_frame.h>
46#include <tool/tool_manager.h>
47#include <tools/pcb_actions.h>
48
49
52 m_frame( aFrame ),
53 m_table( aTable ),
56{
57 m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
58
59 m_grid->CreateGrid( m_table->GetRowCount(), m_table->GetColCount() );
60 m_grid->EnableEditing( true );
61 m_grid->EnableGridLines( true );
62 m_grid->EnableDragGridSize( false );
63 m_grid->SetMargins( 0, 0 );
64 m_grid->SetCellHighlightROPenWidth( 0 );
65
66 m_grid->EnableDragColMove( false );
67 m_grid->EnableDragColSize( false );
68 m_grid->SetColLabelSize( 0 );
69 m_grid->EnableDragRowMove( false );
70 m_grid->EnableDragRowSize( false );
71 m_grid->SetRowLabelSize( 0 );
72 m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
73
74 m_gridSizer->Add( m_grid, 1, wxEXPAND, 5 );
75 m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
76
77 for( int row = 0; row < m_table->GetRowCount(); ++row )
78 {
79 for( int col = 0; col < m_table->GetColCount(); ++col )
80 {
81 PCB_TABLECELL* cell = m_table->GetCell( row, col );
82 wxGridCellAttr* attr = new wxGridCellAttr;
83
84 if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 )
85 {
86 attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( this ) );
87 attr->SetReadOnly();
88 }
89 else
90 {
91 attr->SetEditor( new GRID_CELL_STC_EDITOR( true, false,
92 [this, cell]( wxStyledTextEvent& aEvent, SCINTILLA_TRICKS* aScintillaTricks )
93 {
94 aScintillaTricks->DoTextVarAutocomplete(
95 // getTokensFn
96 [this, cell]( const wxString& xRef, wxArrayString* tokens )
97 {
98 m_frame->GetContextualTextVars( cell, xRef, tokens );
99 } );
100 } ) );
101 }
102
103 m_grid->SetAttr( row, col, attr );
104 }
105 }
106
107 if( m_table->GetParentFootprint() )
108 {
109 // Do not allow locking items in the footprint editor
110 m_cbLocked->Show( false );
111 }
112
113 // Configure the layers list selector. Note that footprints are built outside the current
114 // board and so we may need to show all layers if the text is on an unactivated layer.
115 if( !m_frame->GetBoard()->IsLayerEnabled( m_table->GetLayer() ) )
116 m_LayerSelectionCtrl->ShowNonActivatedLayers( true );
117
118 m_LayerSelectionCtrl->SetLayersHotkeys( false );
119 m_LayerSelectionCtrl->SetBoardFrame( m_frame );
120 m_LayerSelectionCtrl->Resync();
121
122 for( const auto& [lineStyle, lineStyleDesc] : lineTypeNames )
123 {
124 m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) );
125 m_separatorsStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) );
126 }
127
129 Layout();
130
131 // Now all widgets have the size fixed, call FinishDialogSettings
133}
134
135
137{
138 // Delete the GRID_TRICKS.
139 m_grid->PopEventHandler( true );
140}
141
142
144{
145 BOARD* board = m_frame->GetBoard();
146
147 if( !wxDialog::TransferDataToWindow() )
148 return false;
149
150 //
151 // Cell Contents
152 //
153
154 wxColour coveredColor = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
155
157 coveredColor = coveredColor.ChangeLightness( 140 );
158 else
159 coveredColor = coveredColor.ChangeLightness( 100 );
160
161 for( int row = 0; row < m_table->GetRowCount(); ++row )
162 {
163 for( int col = 0; col < m_table->GetColCount(); ++col )
164 {
165 PCB_TABLECELL* tableCell;
166
167 if( IsBackLayer( m_table->GetLayer() ) )
168 tableCell = m_table->GetCell( row, m_table->GetColCount() - 1 - col );
169 else
170 tableCell = m_table->GetCell( row, col );
171
172 if( tableCell->GetColSpan() == 0 || tableCell->GetRowSpan() == 0 )
173 {
174 m_grid->SetCellValue( row, col, coveredColor.GetAsString() );
175 continue;
176 }
177
178 wxString text = tableCell->GetText();
179
180 // show text variable cross-references in a human-readable format
182
183 m_grid->SetCellValue( row, col, text );
184 }
185 }
186
187 CallAfter( [this]()
188 {
189 for( int row = 0; row < m_table->GetRowCount(); ++row )
190 {
191 for( int col = 0; col < m_table->GetColCount(); ++col )
192 {
193 PCB_TABLECELL* tableCell = m_table->GetCell( row, col );
194
195 if( tableCell->IsSelected() )
196 {
197 m_grid->SetGridCursor( row, col );
198 m_grid->EnableCellEditControl();
199 m_grid->ShowCellEditControl();
200 return;
201 }
202 }
203 }
204 } );
205
207
208 //
209 // Table Properties
210 //
211
212 m_LayerSelectionCtrl->SetLayerSelection( m_table->GetLayer() );
213 m_cbLocked->SetValue( m_table->IsLocked() );
214
215 m_borderCheckbox->SetValue( m_table->StrokeExternal() );
216 m_headerBorder->SetValue( m_table->StrokeHeaderSeparator() );
217
218 if( m_table->GetBorderStroke().GetWidth() >= 0 )
219 m_borderWidth.SetValue( m_table->GetBorderStroke().GetWidth() );
220
221 int style = static_cast<int>( m_table->GetBorderStroke().GetLineStyle() );
222
223 if( style >= 0 && style < (int) lineTypeNames.size() )
224 m_borderStyleCombo->SetSelection( style );
225 else
226 m_borderStyleCombo->SetSelection( 0 );
227
228 m_borderWidth.Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
229 m_borderStyleLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
230 m_borderStyleCombo->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
231
232 bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
233 bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
234
235 m_rowSeparators->SetValue( rows );
236 m_colSeparators->SetValue( cols );
237
238 if( m_table->GetSeparatorsStroke().GetWidth() >= 0 )
239 m_separatorsWidth.SetValue( m_table->GetSeparatorsStroke().GetWidth() );
240
241 style = static_cast<int>( m_table->GetSeparatorsStroke().GetLineStyle() );
242
243 if( style >= 0 && style < (int) lineTypeNames.size() )
244 m_separatorsStyleCombo->SetSelection( style );
245 else
246 m_separatorsStyleCombo->SetSelection( 0 );
247
248 m_separatorsWidth.Enable( rows || cols );
249 m_separatorsStyleLabel->Enable( rows || cols );
250 m_separatorsStyleCombo->Enable( rows || cols );
251
252 return true;
253}
254
255void DIALOG_TABLE_PROPERTIES::onHeaderChecked( wxCommandEvent& aEvent )
256{
257 BOARD_DESIGN_SETTINGS& bds = m_frame->GetDesignSettings();
258 PCB_LAYER_ID currentLayer = ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() );
259 int defaultLineThickness = bds.GetLineThickness( currentLayer );
260
261 bool border = m_borderCheckbox->GetValue();
262 bool header = m_headerBorder->GetValue();
263
264 if( ( border || header ) && m_borderWidth.GetValue() < 0 )
265 m_borderWidth.SetValue( defaultLineThickness );
266
267 m_borderWidth.Enable( border || header );
268 m_borderStyleLabel->Enable( border || header );
269 m_borderStyleCombo->Enable( border || header );
270
271 bool row = m_rowSeparators->GetValue();
272 bool col = m_colSeparators->GetValue();
273
274 if( ( row || col ) && m_separatorsWidth.GetValue() < 0 )
275 m_separatorsWidth.SetValue( defaultLineThickness );
276
277 m_separatorsWidth.Enable( row || col );
278 m_separatorsStyleLabel->Enable( row || col );
279 m_separatorsStyleCombo->Enable( row || col );
280}
281
282void DIALOG_TABLE_PROPERTIES::onBorderChecked( wxCommandEvent& aEvent )
283{
284 BOARD_DESIGN_SETTINGS& bds = m_frame->GetDesignSettings();
286 int defaultLineThickness = bds.GetLineThickness( currentLayer );
287
288 bool border = m_borderCheckbox->GetValue();
289 bool header = m_headerBorder->GetValue();
290
291 if( ( border || header ) && m_borderWidth.GetValue() < 0 )
292 m_borderWidth.SetValue( defaultLineThickness );
293
294 m_borderWidth.Enable( border || header );
295 m_borderStyleLabel->Enable( border || header );
296 m_borderStyleCombo->Enable( border || header );
297
298 bool row = m_rowSeparators->GetValue();
299 bool col = m_colSeparators->GetValue();
300
301 if( ( row || col ) && m_separatorsWidth.GetValue() < 0 )
302 m_separatorsWidth.SetValue( defaultLineThickness );
303
304 m_separatorsWidth.Enable( row || col );
305 m_separatorsStyleLabel->Enable( row || col );
306 m_separatorsStyleCombo->Enable( row || col );
307}
308
309
311{
312 if( !m_grid->CommitPendingChanges() )
313 return false;
314
315 if( !wxDialog::TransferDataFromWindow() )
316 return false;
317
318 BOARD* board = m_frame->GetBoard();
319 BOARD_COMMIT commit( m_frame );
320 commit.Modify( m_table );
321
322 // If no other command in progress, prepare undo command
323 // (for a command in progress, will be made later, at the completion of command)
324 bool pushCommit = ( m_table->GetEditFlags() == 0 );
325
326 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
327 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
328 if( !pushCommit )
329 m_table->SetFlags( IN_EDIT );
330
331 for( int row = 0; row < m_table->GetRowCount(); ++row )
332 {
333 for( int col = 0; col < m_table->GetColCount(); ++col )
334 {
335 PCB_TABLECELL* tableCell;
336
337 if( IsBackLayer( m_table->GetLayer() ) )
338 tableCell = m_table->GetCell( row, m_table->GetColCount() - 1 - col );
339 else
340 tableCell = m_table->GetCell( row, col );
341
342 wxString txt = m_grid->GetCellValue( row, col );
343
344 // Don't insert grey colour value back in to table cell
345 if( tableCell->GetColSpan() == 0 || tableCell->GetRowSpan() == 0 )
346 txt = wxEmptyString;
347
348 // convert any text variable cross-references to their UUIDs
349 txt = board->ConvertCrossReferencesToKIIDs( txt );
350
351#ifdef __WXMAC__
352 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
353 // Replace it now.
354 txt.Replace( "\r", "\n" );
355#elif defined( __WINDOWS__ )
356 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
357 // drawing routines so strip the \r char.
358 txt.Replace( "\r", "" );
359#endif
360
361 tableCell->SetText( txt );
362 tableCell->SetLayer( ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ) );
363 }
364 }
365
366 m_table->SetLayer( ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ) );
367 m_table->SetLocked( m_cbLocked->GetValue() );
368
369 m_table->SetStrokeExternal( m_borderCheckbox->GetValue() );
370 m_table->SetStrokeHeaderSeparator( m_headerBorder->GetValue() );
371 {
372 STROKE_PARAMS stroke = m_table->GetBorderStroke();
373
374 if( m_borderCheckbox->GetValue() || m_headerBorder->GetValue() )
375 stroke.SetWidth( std::max( 0, m_borderWidth.GetIntValue() ) );
376 else
377 stroke.SetWidth( -1 );
378
379 auto it = lineTypeNames.begin();
380 std::advance( it, m_borderStyleCombo->GetSelection() );
381
382 if( it == lineTypeNames.end() )
384 else
385 stroke.SetLineStyle( it->first );
386
387 m_table->SetBorderStroke( stroke );
388 }
389
390 m_table->SetStrokeRows( m_rowSeparators->GetValue() );
391 m_table->SetStrokeColumns( m_colSeparators->GetValue() );
392 {
393 STROKE_PARAMS stroke = m_table->GetSeparatorsStroke();
394
395 if( m_rowSeparators->GetValue() || m_colSeparators->GetValue() )
396 stroke.SetWidth( std::max( 0, m_separatorsWidth.GetIntValue() ) );
397 else
398 stroke.SetWidth( -1 );
399
400 auto it = lineTypeNames.begin();
401 std::advance( it, m_separatorsStyleCombo->GetSelection() );
402
403 if( it == lineTypeNames.end() )
405 else
406 stroke.SetLineStyle( it->first );
407
408 m_table->SetSeparatorsStroke( stroke );
409 }
410
411 if( pushCommit )
412 commit.Push( _( "Edit Table" ), SKIP_CONNECTIVITY );
413
414 return true;
415}
416
417
419{
420 Layout(); // Make sure we get the current client size for the grid
421
422 wxSize availableGridSize = m_grid->GetClientSize();
423
424 if( availableGridSize.x == 0 || availableGridSize.y == 0 )
425 return;
426
427 BOX2I tableBBox = m_table->GetBoundingBox();
428 double scalerX = static_cast<double>( availableGridSize.x ) / tableBBox.GetWidth();
429 double scalerY = static_cast<double>( availableGridSize.y ) / tableBBox.GetHeight();
430
431 for( int row = 0; row < m_table->GetRowCount(); ++row )
432 m_grid->SetRowSize( row, std::floor( m_table->GetRowHeight( row ) * scalerY ) );
433
434 for( int col = 0; col < m_table->GetColCount(); ++col )
435 m_grid->SetColSize( col, std::floor( m_table->GetColWidth( col ) * scalerX ) );
436}
437
438
439void DIALOG_TABLE_PROPERTIES::onSize( wxSizeEvent& aEvent )
440{
441 if( m_table )
443
444 aEvent.Skip();
445}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:104
#define SKIP_CONNECTIVITY
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
Container for design settings for a BOARD object.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition board.cpp:1771
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition board.cpp:1825
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr size_type GetHeight() const
Definition box2.h:215
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...
DIALOG_TABLE_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Table Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
DIALOG_TABLE_PROPERTIES(SCH_EDIT_FRAME *aParentFrame, SCH_TABLE *aTable)
void onBorderChecked(wxCommandEvent &aEvent) override
void onHeaderChecked(wxCommandEvent &aEvent) override
bool IsSelected() const
Definition eda_item.h:127
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:97
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:271
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:61
Common, abstract interface for edit frames.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
int GetRowSpan() const
int GetColSpan() const
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
void DoTextVarAutocomplete(const std::function< void(const wxString &xRef, wxArrayString *tokens)> &getTokensFn)
void SetLineStyle(LINE_STYLE aLineStyle)
void SetWidth(int aWidth)
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual long long int GetValue() const
Return the current value in Internal Units.
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
This file is part of the common library.
#define _(s)
#define IN_EDIT
Item currently edited.
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition layer_ids.h:799
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:737
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition wxgtk/ui.cpp:48
wxString UnescapeString(const wxString &aSource)
const std::map< LINE_STYLE, struct LINE_STYLE_DESC > lineTypeNames
Conversion map between LINE_STYLE values and style names displayed.