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_commit.h>
35#include <footprint.h>
36#include <pcb_textbox.h>
37#include <pcb_tablecell.h>
38#include <pcb_table.h>
39#include <project.h>
40#include <pcb_edit_frame.h>
42#include <tool/tool_manager.h>
43#include <tools/pcb_actions.h>
45
46
49 m_frame( aFrame ),
50 m_table( aTable ),
51 m_borderWidth( aFrame, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits ),
52 m_separatorsWidth( aFrame, m_separatorsWidthLabel, m_separatorsWidthCtrl, m_separatorsWidthUnits )
53{
54 m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
55
56 m_grid->CreateGrid( m_table->GetRowCount(), m_table->GetColCount() );
57 m_grid->EnableEditing( true );
58 m_grid->EnableGridLines( true );
59 m_grid->EnableDragGridSize( false );
60 m_grid->SetMargins( 0, 0 );
61 m_grid->SetCellHighlightROPenWidth( 0 );
62
63 m_grid->EnableDragColMove( false );
64 m_grid->EnableDragColSize( false );
66 m_grid->EnableDragRowMove( false );
67 m_grid->EnableDragRowSize( false );
68 m_grid->SetRowLabelSize( 0 );
69 m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
70
71 m_gridSizer->Add( m_grid, 1, wxEXPAND, 5 );
72 m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
73
74 for( int row = 0; row < m_table->GetRowCount(); ++row )
75 {
76 for( int col = 0; col < m_table->GetColCount(); ++col )
77 {
78 PCB_TABLECELL* cell = m_table->GetCell( row, col );
79 wxGridCellAttr* attr = new wxGridCellAttr;
80
81 if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 )
82 {
83 attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( this ) );
84 attr->SetReadOnly();
85 }
86 else
87 {
88 attr->SetEditor( new GRID_CELL_STC_EDITOR( true,
89 [this, cell]( wxStyledTextEvent& aEvent, SCINTILLA_TRICKS* aScintillaTricks )
90 {
91 aScintillaTricks->DoTextVarAutocomplete(
92 // getTokensFn
93 [this, cell]( const wxString& xRef, wxArrayString* tokens )
94 {
95 m_frame->GetContextualTextVars( cell, xRef, tokens );
96 } );
97 } ) );
98 }
99
100 m_grid->SetAttr( row, col, attr );
101 }
102 }
103
104 if( m_table->GetParentFootprint() )
105 {
106 // Do not allow locking items in the footprint editor
107 m_cbLocked->Show( false );
108 }
109
110 // Configure the layers list selector. Note that footprints are built outside the current
111 // board and so we may need to show all layers if the text is on an unactivated layer.
112 if( !m_frame->GetBoard()->IsLayerEnabled( m_table->GetLayer() ) )
114
118
119 for( const auto& [lineStyle, lineStyleDesc] : lineTypeNames )
120 {
121 m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) );
122 m_separatorsStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) );
123 }
124
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 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 m_grid->SetCellValue( row, col, coveredColor.GetAsString() );
172 else
173 m_grid->SetCellValue( row, col, tableCell->GetText() );
174 }
175 }
176
177 CallAfter( [this]()
178 {
179 for( int row = 0; row < m_table->GetRowCount(); ++row )
180 {
181 for( int col = 0; col < m_table->GetColCount(); ++col )
182 {
183 PCB_TABLECELL* tableCell = m_table->GetCell( row, col );
184
185 if( tableCell->IsSelected() )
186 {
187 m_grid->SetGridCursor( row, col );
188 m_grid->EnableCellEditControl();
189 m_grid->ShowCellEditControl();
190 return;
191 }
192 }
193 }
194 } );
195
197
198 //
199 // Table Properties
200 //
201
203 m_cbLocked->SetValue( m_table->IsLocked() );
204
206 m_headerBorder->SetValue( m_table->StrokeHeader() );
207
208 if( m_table->GetBorderStroke().GetWidth() >= 0 )
210
211 int style = static_cast<int>( m_table->GetBorderStroke().GetLineStyle() );
212
213 if( style == -1 )
214 m_borderStyleCombo->SetStringSelection( DEFAULT_STYLE );
215 else if( style < (int) lineTypeNames.size() )
216 m_borderStyleCombo->SetSelection( style );
217 else
218 wxFAIL_MSG( "Line type not found in the type lookup map" );
219
223
224 bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
225 bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
226
227 m_rowSeparators->SetValue( rows );
228 m_colSeparators->SetValue( cols );
229
230 if( m_table->GetSeparatorsStroke().GetWidth() >= 0 )
232
233 style = static_cast<int>( m_table->GetSeparatorsStroke().GetLineStyle() );
234
235 if( style == -1 )
236 m_separatorsStyleCombo->SetStringSelection( DEFAULT_STYLE );
237 else if( style < (int) lineTypeNames.size() )
238 m_separatorsStyleCombo->SetSelection( style );
239 else
240 wxFAIL_MSG( "Line type not found in the type lookup map" );
241
242 m_separatorsWidth.Enable( rows || cols );
243 m_separatorsStyleLabel->Enable( rows || cols );
244 m_separatorsStyleCombo->Enable( rows || cols );
245
246 return true;
247}
248
249
250void DIALOG_TABLE_PROPERTIES::onBorderChecked( wxCommandEvent& aEvent )
251{
252 BOARD_DESIGN_SETTINGS& bds = m_frame->GetDesignSettings();
254 int defaultLineThickness = bds.GetLineThickness( currentLayer );
255
256 bool border = m_borderCheckbox->GetValue();
257
258 if( border && m_borderWidth.GetValue() < 0 )
259 m_borderWidth.SetValue( defaultLineThickness );
260
261 m_borderWidth.Enable( border );
262 m_borderStyleLabel->Enable( border );
263 m_borderStyleCombo->Enable( border );
264
265 bool row = m_rowSeparators->GetValue();
266 bool col = m_colSeparators->GetValue();
267
268 if( ( row || col ) && m_separatorsWidth.GetValue() < 0 )
269 m_separatorsWidth.SetValue( defaultLineThickness );
270
271 m_separatorsWidth.Enable( row || col );
272 m_separatorsStyleLabel->Enable( row || col );
273 m_separatorsStyleCombo->Enable( row || col );
274}
275
276
278{
280 return false;
281
282 if( !wxDialog::TransferDataFromWindow() )
283 return false;
284
285 BOARD_COMMIT commit( m_frame );
286 commit.Modify( m_table );
287
288 // If no other command in progress, prepare undo command
289 // (for a command in progress, will be made later, at the completion of command)
290 bool pushCommit = ( m_table->GetEditFlags() == 0 );
291
292 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
293 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
294 if( !pushCommit )
296
297 for( int row = 0; row < m_table->GetRowCount(); ++row )
298 {
299 for( int col = 0; col < m_table->GetColCount(); ++col )
300 {
301 PCB_TABLECELL* tableCell;
302
303 if( IsBackLayer( m_table->GetLayer() ) )
304 tableCell = m_table->GetCell( row, m_table->GetColCount() - 1 - col );
305 else
306 tableCell = m_table->GetCell( row, col );
307
308 wxString txt = m_grid->GetCellValue( row, col );
309
310#ifdef __WXMAC__
311 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
312 // Replace it now.
313 txt.Replace( "\r", "\n" );
314#elif defined( __WINDOWS__ )
315 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
316 // drawing routines so strip the \r char.
317 txt.Replace( "\r", "" );
318#endif
319
320 tableCell->SetText( txt );
321 }
322 }
323
325 m_table->SetLocked( m_cbLocked->GetValue() );
326
328 m_table->SetStrokeHeader( m_headerBorder->GetValue() );
329 {
331
332 if( m_borderCheckbox->GetValue() )
333 stroke.SetWidth( std::max( 0, m_borderWidth.GetIntValue() ) );
334 else
335 stroke.SetWidth( -1 );
336
337 auto it = lineTypeNames.begin();
338 std::advance( it, m_borderStyleCombo->GetSelection() );
339
340 if( it == lineTypeNames.end() )
341 stroke.SetLineStyle( LINE_STYLE::DEFAULT );
342 else
343 stroke.SetLineStyle( it->first );
344
345 m_table->SetBorderStroke( stroke );
346 }
347
348 m_table->SetStrokeRows( m_rowSeparators->GetValue() );
350 {
352
353 if( m_rowSeparators->GetValue() || m_colSeparators->GetValue() )
354 stroke.SetWidth( std::max( 0, m_separatorsWidth.GetIntValue() ) );
355 else
356 stroke.SetWidth( -1 );
357
358 auto it = lineTypeNames.begin();
359 std::advance( it, m_separatorsStyleCombo->GetSelection() );
360
361 if( it == lineTypeNames.end() )
362 stroke.SetLineStyle( LINE_STYLE::DEFAULT );
363 else
364 stroke.SetLineStyle( it->first );
365
366 m_table->SetSeparatorsStroke( stroke );
367 }
368
369 if( !commit.Empty() )
370 commit.Push( _( "Edit Table" ), SKIP_CONNECTIVITY );
371
372 return true;
373}
374
375
377{
378 Layout(); // Make sure we get the current client size for the grid
379
380 wxSize availableGridSize = m_grid->GetClientSize();
381
382 if( availableGridSize.x == 0 || availableGridSize.y == 0 )
383 return;
384
385 BOX2I tableBBox = m_table->GetBoundingBox();
386 double scalerX = static_cast<double>( availableGridSize.x ) / tableBBox.GetWidth();
387 double scalerY = static_cast<double>( availableGridSize.y ) / tableBBox.GetHeight();
388
389 for( int row = 0; row < m_table->GetRowCount(); ++row )
390 m_grid->SetRowSize( row, std::floor( m_table->GetRowHeight( row ) * scalerY ) );
391
392 for( int col = 0; col < m_table->GetColCount(); ++col )
393 m_grid->SetColSize( col, std::floor( m_table->GetColWidth( col ) * scalerX ) );
394}
395
396
397void DIALOG_TABLE_PROPERTIES::onSize( wxSizeEvent& aEvent )
398{
399 if( m_table )
401
402 aEvent.Skip();
403}
404
405
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:183
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:276
virtual void SetLocked(bool aLocked)
Definition: sch_item.h:277
void SetLayer(SCH_LAYER_ID aLayer)
Definition: sch_item.h:290
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:289
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:211
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:558
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:978
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: gtk/ui.cpp:48
const std::map< LINE_STYLE, struct LINE_STYLE_DESC > lineTypeNames