KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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
24#include <kiplatform/ui.h>
25#include <widgets/font_choice.h>
27#include <widgets/wx_grid.h>
30#include <grid_tricks.h>
31#include <scintilla_tricks.h>
32#include <confirm.h>
33#include <board.h>
34#include <board_commit.h>
36#include <footprint.h>
37#include <pcb_textbox.h>
38#include <pcb_tablecell.h>
39#include <pcb_table.h>
40#include <project.h>
41#include <pcb_edit_frame.h>
43#include <tool/tool_manager.h>
44#include <tools/pcb_actions.h>
46
47
50 m_frame( aFrame ),
51 m_table( aTable ),
52 m_borderWidth( aFrame, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits ),
53 m_separatorsWidth( aFrame, m_separatorsWidthLabel, m_separatorsWidthCtrl, m_separatorsWidthUnits )
54{
55 m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
56
57 m_grid->CreateGrid( m_table->GetRowCount(), m_table->GetColCount() );
58 m_grid->EnableEditing( true );
59 m_grid->EnableGridLines( true );
60 m_grid->EnableDragGridSize( false );
61 m_grid->SetMargins( 0, 0 );
62 m_grid->SetCellHighlightROPenWidth( 0 );
63
64 m_grid->EnableDragColMove( false );
65 m_grid->EnableDragColSize( false );
67 m_grid->EnableDragRowMove( false );
68 m_grid->EnableDragRowSize( false );
69 m_grid->SetRowLabelSize( 0 );
70 m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
71
72 m_gridSizer->Add( m_grid, 1, wxEXPAND, 5 );
73 m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
74
75 for( int row = 0; row < m_table->GetRowCount(); ++row )
76 {
77 for( int col = 0; col < m_table->GetColCount(); ++col )
78 {
79 PCB_TABLECELL* cell = m_table->GetCell( row, col );
80 wxGridCellAttr* attr = new wxGridCellAttr;
81
82 if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 )
83 {
84 attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( this ) );
85 attr->SetReadOnly();
86 }
87 else
88 {
89 attr->SetEditor( new GRID_CELL_STC_EDITOR( true,
90 [this, cell]( wxStyledTextEvent& aEvent, SCINTILLA_TRICKS* aScintillaTricks )
91 {
92 aScintillaTricks->DoTextVarAutocomplete(
93 // getTokensFn
94 [this, cell]( const wxString& xRef, wxArrayString* tokens )
95 {
96 m_frame->GetContextualTextVars( cell, xRef, tokens );
97 } );
98 } ) );
99 }
100
101 m_grid->SetAttr( row, col, attr );
102 }
103 }
104
105 if( m_table->GetParentFootprint() )
106 {
107 // Do not allow locking items in the footprint editor
108 m_cbLocked->Show( false );
109 }
110
111 // Configure the layers list selector. Note that footprints are built outside the current
112 // board and so we may need to show all layers if the text is on an unactivated layer.
113 if( !m_frame->GetBoard()->IsLayerEnabled( m_table->GetLayer() ) )
115
119
120 for( const auto& [lineStyle, lineStyleDesc] : lineTypeNames )
121 {
122 m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) );
123 m_separatorsStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) );
124 }
125
127 Layout();
128
129 // Now all widgets have the size fixed, call FinishDialogSettings
131}
132
133
135{
136 // Delete the GRID_TRICKS.
137 m_grid->PopEventHandler( true );
138}
139
140
142{
143 BOARD* board = m_frame->GetBoard();
144
145 if( !wxDialog::TransferDataToWindow() )
146 return false;
147
148 //
149 // Cell Contents
150 //
151
152 wxColour coveredColor = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
153
155 coveredColor = coveredColor.ChangeLightness( 140 );
156 else
157 coveredColor = coveredColor.ChangeLightness( 100 );
158
159 for( int row = 0; row < m_table->GetRowCount(); ++row )
160 {
161 for( int col = 0; col < m_table->GetColCount(); ++col )
162 {
163 PCB_TABLECELL* tableCell;
164
165 if( IsBackLayer( m_table->GetLayer() ) )
166 tableCell = m_table->GetCell( row, m_table->GetColCount() - 1 - col );
167 else
168 tableCell = m_table->GetCell( row, col );
169
170 if( tableCell->GetColSpan() == 0 || tableCell->GetRowSpan() == 0 )
171 {
172 m_grid->SetCellValue( row, col, coveredColor.GetAsString() );
173 continue;
174 }
175
176 wxString text = tableCell->GetText();
177
178 // show text variable cross-references in a human-readable format
180
181 m_grid->SetCellValue( row, col, text );
182 }
183 }
184
185 CallAfter( [this]()
186 {
187 for( int row = 0; row < m_table->GetRowCount(); ++row )
188 {
189 for( int col = 0; col < m_table->GetColCount(); ++col )
190 {
191 PCB_TABLECELL* tableCell = m_table->GetCell( row, col );
192
193 if( tableCell->IsSelected() )
194 {
195 m_grid->SetGridCursor( row, col );
196 m_grid->EnableCellEditControl();
197 m_grid->ShowCellEditControl();
198 return;
199 }
200 }
201 }
202 } );
203
205
206 //
207 // Table Properties
208 //
209
211 m_cbLocked->SetValue( m_table->IsLocked() );
212
215
216 if( m_table->GetBorderStroke().GetWidth() >= 0 )
218
219 int style = static_cast<int>( m_table->GetBorderStroke().GetLineStyle() );
220
221 if( style >= 0 && style < (int) lineTypeNames.size() )
222 m_borderStyleCombo->SetSelection( style );
223 else
224 m_borderStyleCombo->SetSelection( 0 );
225
229
230 bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
231 bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
232
233 m_rowSeparators->SetValue( rows );
234 m_colSeparators->SetValue( cols );
235
236 if( m_table->GetSeparatorsStroke().GetWidth() >= 0 )
238
239 style = static_cast<int>( m_table->GetSeparatorsStroke().GetLineStyle() );
240
241 if( style >= 0 && style < (int) lineTypeNames.size() )
242 m_separatorsStyleCombo->SetSelection( style );
243 else
244 m_separatorsStyleCombo->SetSelection( 0 );
245
246 m_separatorsWidth.Enable( rows || cols );
247 m_separatorsStyleLabel->Enable( rows || cols );
248 m_separatorsStyleCombo->Enable( rows || cols );
249
250 return true;
251}
252
253void DIALOG_TABLE_PROPERTIES::onHeaderChecked( wxCommandEvent& aEvent )
254{
255 BOARD_DESIGN_SETTINGS& bds = m_frame->GetDesignSettings();
257 int defaultLineThickness = bds.GetLineThickness( currentLayer );
258
259 bool border = m_borderCheckbox->GetValue();
260 bool header = m_headerBorder->GetValue();
261
262 if( ( border || header ) && m_borderWidth.GetValue() < 0 )
263 m_borderWidth.SetValue( defaultLineThickness );
264
265 m_borderWidth.Enable( border || header );
266 m_borderStyleLabel->Enable( border || header );
267 m_borderStyleCombo->Enable( border || header );
268
269 bool row = m_rowSeparators->GetValue();
270 bool col = m_colSeparators->GetValue();
271
272 if( ( row || col ) && m_separatorsWidth.GetValue() < 0 )
273 m_separatorsWidth.SetValue( defaultLineThickness );
274
275 m_separatorsWidth.Enable( row || col );
276 m_separatorsStyleLabel->Enable( row || col );
277 m_separatorsStyleCombo->Enable( row || col );
278}
279
280void DIALOG_TABLE_PROPERTIES::onBorderChecked( wxCommandEvent& aEvent )
281{
282 BOARD_DESIGN_SETTINGS& bds = m_frame->GetDesignSettings();
284 int defaultLineThickness = bds.GetLineThickness( currentLayer );
285
286 bool border = m_borderCheckbox->GetValue();
287 bool header = m_headerBorder->GetValue();
288
289 if( ( border || header ) && m_borderWidth.GetValue() < 0 )
290 m_borderWidth.SetValue( defaultLineThickness );
291
292 m_borderWidth.Enable( border || header );
293 m_borderStyleLabel->Enable( border || header );
294 m_borderStyleCombo->Enable( border || header );
295
296 bool row = m_rowSeparators->GetValue();
297 bool col = m_colSeparators->GetValue();
298
299 if( ( row || col ) && m_separatorsWidth.GetValue() < 0 )
300 m_separatorsWidth.SetValue( defaultLineThickness );
301
302 m_separatorsWidth.Enable( row || col );
303 m_separatorsStyleLabel->Enable( row || col );
304 m_separatorsStyleCombo->Enable( row || col );
305}
306
307
309{
311 return false;
312
313 if( !wxDialog::TransferDataFromWindow() )
314 return false;
315
316 BOARD* board = m_frame->GetBoard();
317 BOARD_COMMIT commit( m_frame );
318 commit.Modify( m_table );
319
320 // If no other command in progress, prepare undo command
321 // (for a command in progress, will be made later, at the completion of command)
322 bool pushCommit = ( m_table->GetEditFlags() == 0 );
323
324 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
325 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
326 if( !pushCommit )
328
329 for( int row = 0; row < m_table->GetRowCount(); ++row )
330 {
331 for( int col = 0; col < m_table->GetColCount(); ++col )
332 {
333 PCB_TABLECELL* tableCell;
334
335 if( IsBackLayer( m_table->GetLayer() ) )
336 tableCell = m_table->GetCell( row, m_table->GetColCount() - 1 - col );
337 else
338 tableCell = m_table->GetCell( row, col );
339
340 wxString txt = m_grid->GetCellValue( row, col );
341
342 // Don't insert grey colour value back in to table cell
343 if( tableCell->GetColSpan() == 0 || tableCell->GetRowSpan() == 0 )
344 txt = wxEmptyString;
345
346 // convert any text variable cross-references to their UUIDs
347 txt = board->ConvertCrossReferencesToKIIDs( txt );
348
349#ifdef __WXMAC__
350 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
351 // Replace it now.
352 txt.Replace( "\r", "\n" );
353#elif defined( __WINDOWS__ )
354 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
355 // drawing routines so strip the \r char.
356 txt.Replace( "\r", "" );
357#endif
358
359 tableCell->SetText( txt );
361 }
362 }
363
365 m_table->SetLocked( m_cbLocked->GetValue() );
366
369 {
371
372 if( m_borderCheckbox->GetValue() || m_headerBorder->GetValue() )
373 stroke.SetWidth( std::max( 0, m_borderWidth.GetIntValue() ) );
374 else
375 stroke.SetWidth( -1 );
376
377 auto it = lineTypeNames.begin();
378 std::advance( it, m_borderStyleCombo->GetSelection() );
379
380 if( it == lineTypeNames.end() )
381 stroke.SetLineStyle( LINE_STYLE::SOLID );
382 else
383 stroke.SetLineStyle( it->first );
384
385 m_table->SetBorderStroke( stroke );
386 }
387
388 m_table->SetStrokeRows( m_rowSeparators->GetValue() );
390 {
392
393 if( m_rowSeparators->GetValue() || m_colSeparators->GetValue() )
394 stroke.SetWidth( std::max( 0, m_separatorsWidth.GetIntValue() ) );
395 else
396 stroke.SetWidth( -1 );
397
398 auto it = lineTypeNames.begin();
399 std::advance( it, m_separatorsStyleCombo->GetSelection() );
400
401 if( it == lineTypeNames.end() )
402 stroke.SetLineStyle( LINE_STYLE::SOLID );
403 else
404 stroke.SetLineStyle( it->first );
405
406 m_table->SetSeparatorsStroke( stroke );
407 }
408
409 if( pushCommit )
410 commit.Push( _( "Edit Table" ), SKIP_CONNECTIVITY );
411
412 return true;
413}
414
415
417{
418 Layout(); // Make sure we get the current client size for the grid
419
420 wxSize availableGridSize = m_grid->GetClientSize();
421
422 if( availableGridSize.x == 0 || availableGridSize.y == 0 )
423 return;
424
425 BOX2I tableBBox = m_table->GetBoundingBox();
426 double scalerX = static_cast<double>( availableGridSize.x ) / tableBBox.GetWidth();
427 double scalerY = static_cast<double>( availableGridSize.y ) / tableBBox.GetHeight();
428
429 for( int row = 0; row < m_table->GetRowCount(); ++row )
430 m_grid->SetRowSize( row, std::floor( m_table->GetRowHeight( row ) * scalerY ) );
431
432 for( int col = 0; col < m_table->GetColCount(); ++col )
433 m_grid->SetColSize( col, std::floor( m_table->GetColWidth( col ) * scalerX ) );
434}
435
436
437void DIALOG_TABLE_PROPERTIES::onSize( wxSizeEvent& aEvent )
438{
439 if( m_table )
441
442 aEvent.Skip();
443}
444
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
Definition: board_commit.h:44
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.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:1644
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1698
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(SCH_EDIT_FRAME *aParentFrame, SCH_TABLE *aTable)
void onBorderChecked(wxCommandEvent &aEvent) override
void onHeaderChecked(wxCommandEvent &aEvent) override
void onSize(wxSizeEvent &aEvent) override
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:137
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:131
bool IsSelected() const
Definition: eda_item.h:116
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
int SetLayerSelection(int layer)
bool SetLayersHotkeys(bool value)
Common, abstract interface for edit frames.
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void ShowNonActivatedLayers(bool aShow)
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_shape.cpp:179
int GetRowSpan() const
Definition: pcb_tablecell.h:65
int GetColSpan() const
Definition: pcb_tablecell.h:62
virtual bool IsLocked() const
Definition: sch_item.h:282
virtual void SetLocked(bool aLocked)
Definition: sch_item.h:283
void SetLayer(SCH_LAYER_ID aLayer)
Definition: sch_item.h:296
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:295
const STROKE_PARAMS & GetSeparatorsStroke() const
Definition: sch_table.h:76
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_table.cpp:255
bool StrokeExternal() const
Definition: sch_table.h:52
int GetRowHeight(int aRow) const
Definition: sch_table.h:138
int GetColWidth(int aCol) const
Definition: sch_table.h:128
void SetStrokeHeaderSeparator(bool aDoStroke)
Definition: sch_table.h:54
const STROKE_PARAMS & GetBorderStroke() const
Definition: sch_table.h:58
void SetStrokeExternal(bool aDoStroke)
Definition: sch_table.h:51
int GetColCount() const
Definition: sch_table.h:119
bool StrokeHeaderSeparator() const
Definition: sch_table.h:55
void SetStrokeColumns(bool aDoStroke)
Definition: sch_table.h:97
SCH_TABLECELL * GetCell(int aRow, int aCol) const
Definition: sch_table.h:146
bool StrokeColumns() const
Definition: sch_table.h:98
void SetSeparatorsStroke(const STROKE_PARAMS &aParams)
Definition: sch_table.h:75
bool StrokeRows() const
Definition: sch_table.h:101
int GetRowCount() const
Definition: sch_table.h:121
void SetStrokeRows(bool aDoStroke)
Definition: sch_table.h:100
void SetBorderStroke(const STROKE_PARAMS &aParams)
Definition: sch_table.h:57
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)
Simple container to manage line stroke parameters.
Definition: stroke_params.h:94
int GetWidth() const
void SetLineStyle(LINE_STYLE aLineStyle)
void SetWidth(int aWidth)
LINE_STYLE GetLineStyle() const
int GetIntValue()
Definition: unit_binder.h:129
virtual long long int GetValue()
Return the current value in Internal Units.
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void SetColLabelSize(int aHeight)
Hide wxGrid's SetColLabelSize() method with one which makes sure the size is tall enough for the syst...
Definition: wx_grid.cpp:254
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:644
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:788
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:723
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.