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 (C) 2024 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
128
130 Layout();
131
132 // Now all widgets have the size fixed, call FinishDialogSettings
134}
135
136
138{
139 // Delete the GRID_TRICKS.
140 m_grid->PopEventHandler( true );
141}
142
143
145{
146 if( !wxDialog::TransferDataToWindow() )
147 return false;
148
149 //
150 // Cell Contents
151 //
152
153 wxColour coveredColor = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
154
156 coveredColor = coveredColor.ChangeLightness( 140 );
157 else
158 coveredColor = coveredColor.ChangeLightness( 100 );
159
160 for( int row = 0; row < m_table->GetRowCount(); ++row )
161 {
162 for( int col = 0; col < m_table->GetColCount(); ++col )
163 {
164 PCB_TABLECELL* tableCell;
165
166 if( IsBackLayer( m_table->GetLayer() ) )
167 tableCell = m_table->GetCell( row, m_table->GetColCount() - 1 - col );
168 else
169 tableCell = m_table->GetCell( row, col );
170
171 if( tableCell->GetColSpan() == 0 || tableCell->GetRowSpan() == 0 )
172 m_grid->SetCellValue( row, col, coveredColor.GetAsString() );
173 else
174 m_grid->SetCellValue( row, col, tableCell->GetText() );
175 }
176 }
177
178 CallAfter( [this]()
179 {
180 for( int row = 0; row < m_table->GetRowCount(); ++row )
181 {
182 for( int col = 0; col < m_table->GetColCount(); ++col )
183 {
184 PCB_TABLECELL* tableCell = m_table->GetCell( row, col );
185
186 if( tableCell->IsSelected() )
187 {
188 m_grid->SetGridCursor( row, col );
189 m_grid->EnableCellEditControl();
190 m_grid->ShowCellEditControl();
191 return;
192 }
193 }
194 }
195 } );
196
198
199 //
200 // Table Properties
201 //
202
204 m_cbLocked->SetValue( m_table->IsLocked() );
205
207 m_headerBorder->SetValue( m_table->StrokeHeader() );
208
209 if( m_table->GetBorderStroke().GetWidth() >= 0 )
211
212 int style = static_cast<int>( m_table->GetBorderStroke().GetLineStyle() );
213
214 if( style == -1 )
215 m_borderStyleCombo->SetStringSelection( DEFAULT_STYLE );
216 else if( style < (int) lineTypeNames.size() )
217 m_borderStyleCombo->SetSelection( style );
218 else
219 wxFAIL_MSG( "Line type not found in the type lookup map" );
220
224
225 bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
226 bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
227
228 m_rowSeparators->SetValue( rows );
229 m_colSeparators->SetValue( cols );
230
231 if( m_table->GetSeparatorsStroke().GetWidth() >= 0 )
233
234 style = static_cast<int>( m_table->GetSeparatorsStroke().GetLineStyle() );
235
236 if( style == -1 )
237 m_separatorsStyleCombo->SetStringSelection( DEFAULT_STYLE );
238 else if( style < (int) lineTypeNames.size() )
239 m_separatorsStyleCombo->SetSelection( style );
240 else
241 wxFAIL_MSG( "Line type not found in the type lookup map" );
242
243 m_separatorsWidth.Enable( rows || cols );
244 m_separatorsStyleLabel->Enable( rows || cols );
245 m_separatorsStyleCombo->Enable( rows || cols );
246
247 return true;
248}
249
250
251void DIALOG_TABLE_PROPERTIES::onBorderChecked( wxCommandEvent& aEvent )
252{
253 BOARD_DESIGN_SETTINGS& bds = m_frame->GetDesignSettings();
255 int defaultLineThickness = bds.GetLineThickness( currentLayer );
256
257 bool border = m_borderCheckbox->GetValue();
258
259 if( border && m_borderWidth.GetValue() < 0 )
260 m_borderWidth.SetValue( defaultLineThickness );
261
262 m_borderWidth.Enable( border );
263 m_borderStyleLabel->Enable( border );
264 m_borderStyleCombo->Enable( border );
265
266 bool row = m_rowSeparators->GetValue();
267 bool col = m_colSeparators->GetValue();
268
269 if( ( row || col ) && m_separatorsWidth.GetValue() < 0 )
270 m_separatorsWidth.SetValue( defaultLineThickness );
271
272 m_separatorsWidth.Enable( row || col );
273 m_separatorsStyleLabel->Enable( row || col );
274 m_separatorsStyleCombo->Enable( row || col );
275}
276
277
279{
281 return false;
282
283 if( !wxDialog::TransferDataFromWindow() )
284 return false;
285
286 BOARD_COMMIT commit( m_frame );
287 commit.Modify( m_table );
288
289 // If no other command in progress, prepare undo command
290 // (for a command in progress, will be made later, at the completion of command)
291 bool pushCommit = ( m_table->GetEditFlags() == 0 );
292
293 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
294 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
295 if( !pushCommit )
297
298 for( int row = 0; row < m_table->GetRowCount(); ++row )
299 {
300 for( int col = 0; col < m_table->GetColCount(); ++col )
301 {
302 PCB_TABLECELL* tableCell;
303
304 if( IsBackLayer( m_table->GetLayer() ) )
305 tableCell = m_table->GetCell( row, m_table->GetColCount() - 1 - col );
306 else
307 tableCell = m_table->GetCell( row, col );
308
309 wxString txt = m_grid->GetCellValue( row, col );
310
311#ifdef __WXMAC__
312 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
313 // Replace it now.
314 txt.Replace( "\r", "\n" );
315#elif defined( __WINDOWS__ )
316 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
317 // drawing routines so strip the \r char.
318 txt.Replace( "\r", "" );
319#endif
320
321 tableCell->SetText( txt );
322 }
323 }
324
326 m_table->SetLocked( m_cbLocked->GetValue() );
327
329 m_table->SetStrokeHeader( m_headerBorder->GetValue() );
330 {
332
333 if( m_borderCheckbox->GetValue() )
334 stroke.SetWidth( std::max( 0, m_borderWidth.GetIntValue() ) );
335 else
336 stroke.SetWidth( -1 );
337
338 auto it = lineTypeNames.begin();
339 std::advance( it, m_borderStyleCombo->GetSelection() );
340
341 if( it == lineTypeNames.end() )
342 stroke.SetLineStyle( LINE_STYLE::DEFAULT );
343 else
344 stroke.SetLineStyle( it->first );
345
346 m_table->SetBorderStroke( stroke );
347 }
348
349 m_table->SetStrokeRows( m_rowSeparators->GetValue() );
351 {
353
354 if( m_rowSeparators->GetValue() || m_colSeparators->GetValue() )
355 stroke.SetWidth( std::max( 0, m_separatorsWidth.GetIntValue() ) );
356 else
357 stroke.SetWidth( -1 );
358
359 auto it = lineTypeNames.begin();
360 std::advance( it, m_separatorsStyleCombo->GetSelection() );
361
362 if( it == lineTypeNames.end() )
363 stroke.SetLineStyle( LINE_STYLE::DEFAULT );
364 else
365 stroke.SetLineStyle( it->first );
366
367 m_table->SetSeparatorsStroke( stroke );
368 }
369
370 if( pushCommit )
371 commit.Push( _( "Edit Table" ), SKIP_CONNECTIVITY );
372
373 return true;
374}
375
376
378{
379 Layout(); // Make sure we get the current client size for the grid
380
381 wxSize availableGridSize = m_grid->GetClientSize();
382
383 if( availableGridSize.x == 0 || availableGridSize.y == 0 )
384 return;
385
386 BOX2I tableBBox = m_table->GetBoundingBox();
387 double scalerX = static_cast<double>( availableGridSize.x ) / tableBBox.GetWidth();
388 double scalerY = static_cast<double>( availableGridSize.y ) / tableBBox.GetHeight();
389
390 for( int row = 0; row < m_table->GetRowCount(); ++row )
391 m_grid->SetRowSize( row, std::floor( m_table->GetRowHeight( row ) * scalerY ) );
392
393 for( int col = 0; col < m_table->GetColCount(); ++col )
394 m_grid->SetColSize( col, std::floor( m_table->GetColWidth( col ) * scalerX ) );
395}
396
397
398void DIALOG_TABLE_PROPERTIES::onSize( wxSizeEvent& aEvent )
399{
400 if( m_table )
402
403 aEvent.Skip();
404}
405
406
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:42
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.
size_type GetHeight() const
Definition: box2.h:205
size_type GetWidth() const
Definition: box2.h:204
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 onSize(wxSizeEvent &aEvent) override
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:132
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:126
bool IsSelected() const
Definition: eda_item.h:109
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:181
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)
int GetRowSpan() const
Definition: pcb_tablecell.h:65
int GetColSpan() const
Definition: pcb_tablecell.h:62
virtual bool IsLocked() const
Definition: sch_item.h:268
virtual void SetLocked(bool aLocked)
Definition: sch_item.h:269
void SetLayer(SCH_LAYER_ID aLayer)
Definition: sch_item.h:282
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:281
const STROKE_PARAMS & GetSeparatorsStroke() const
Definition: sch_table.h:72
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_table.cpp:362
bool StrokeExternal() const
Definition: sch_table.h:54
int GetRowHeight(int aRow) const
Definition: sch_table.h:123
void SetStrokeHeader(bool aDoStroke)
Definition: sch_table.h:56
int GetColWidth(int aCol) const
Definition: sch_table.h:113
const STROKE_PARAMS & GetBorderStroke() const
Definition: sch_table.h:60
void SetStrokeExternal(bool aDoStroke)
Definition: sch_table.h:53
int GetColCount() const
Definition: sch_table.h:104
void SetStrokeColumns(bool aDoStroke)
Definition: sch_table.h:83
SCH_TABLECELL * GetCell(int aRow, int aCol) const
Definition: sch_table.h:131
bool StrokeColumns() const
Definition: sch_table.h:84
void SetSeparatorsStroke(const STROKE_PARAMS &aParams)
Definition: sch_table.h:71
bool StrokeRows() const
Definition: sch_table.h:87
int GetRowCount() const
Definition: sch_table.h:106
void SetStrokeRows(bool aDoStroke)
Definition: sch_table.h:86
void SetBorderStroke(const STROKE_PARAMS &aParams)
Definition: sch_table.h:59
bool StrokeHeader() const
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:81
int GetWidth() const
Definition: stroke_params.h:91
void SetLineStyle(LINE_STYLE aLineStyle)
Definition: stroke_params.h:95
void SetWidth(int aWidth)
Definition: stroke_params.h:92
LINE_STYLE GetLineStyle() const
Definition: stroke_params.h:94
int GetIntValue()
Definition: unit_binder.h:127
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:246
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:594
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:979
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:1022
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition: wxgtk/ui.cpp:48
const std::map< LINE_STYLE, struct LINE_STYLE_DESC > lineTypeNames