KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eeschema/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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <bitmaps.h>
21#include <scintilla_tricks.h>
22#include <kiplatform/ui.h>
23#include <sch_edit_frame.h>
26#include <widgets/wx_grid.h>
28#include <grid_tricks.h>
30#include <widgets/wx_infobar.h>
31#include <sch_table.h>
32#include <sch_commit.h>
33#include <tool/tool_manager.h>
35
36
39 m_frame( aFrame ),
40 m_table( aTable ),
44{
45 m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
46
47 m_grid->CreateGrid( m_table->GetRowCount(), m_table->GetColCount() );
48 m_grid->EnableEditing( true );
49 m_grid->EnableGridLines( true );
50 m_grid->EnableDragGridSize( false );
51 m_grid->SetMargins( 0, 0 );
52 m_grid->SetCellHighlightROPenWidth( 0 );
53
54 m_grid->EnableDragColMove( false );
55 m_grid->EnableDragColSize( false );
56 m_grid->SetColLabelSize( 0 );
57 m_grid->EnableDragRowMove( false );
58 m_grid->EnableDragRowSize( false );
59 m_grid->SetRowLabelSize( 0 );
60 m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
61
62 m_gridSizer->Add( m_grid, 1, wxEXPAND, 5 );
63 m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
64
65 for( int row = 0; row < m_table->GetRowCount(); ++row )
66 {
67 for( int col = 0; col < m_table->GetColCount(); ++col )
68 {
69 const SCH_TABLECELL* cell = m_table->GetCell( row, col );
70 wxGridCellAttr* attr = new wxGridCellAttr;
71
72 if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 )
73 {
74 attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( this ) );
75 attr->SetReadOnly();
76 }
77 else
78 {
79 attr->SetRenderer( new wxGridCellAutoWrapStringRenderer );
80 attr->SetEditor( new GRID_CELL_STC_EDITOR( true, false,
81 // onCharFn
82 [this]( wxStyledTextEvent& aEvent, SCINTILLA_TRICKS* aScintillaTricks )
83 {
84 aScintillaTricks->DoTextVarAutocomplete(
85 // getTokensFn
86 [this]( const wxString& xRef, wxArrayString* tokens )
87 {
88 getContextualTextVars( xRef, tokens );
89 } );
90 } ) );
91 }
92
93 m_grid->SetAttr( row, col, attr );
94 }
95 }
96
97 for( const auto& [lineStyle, lineStyleDesc] : lineTypeNames )
98 {
99 m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) );
100 m_separatorsStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) );
101 }
102
104 m_borderColorSwatch->SetSwatchBackground( canvas );
105 m_separatorsColorSwatch->SetSwatchBackground( canvas );
106
107 if( m_frame->GetColorSettings()->GetOverrideSchItemColors() )
108 m_infoBar->ShowMessage( _( "Note: individual item colors overridden in Preferences." ) );
109
111 Layout();
112
113 // Now all widgets have the size fixed, call FinishDialogSettings
115}
116
117
119{
120 // Delete the GRID_TRICKS.
121 m_grid->PopEventHandler( true );
122}
123
124
126{
127 if( !wxDialog::TransferDataToWindow() )
128 return false;
129
130 //
131 // Cell Contents
132 //
133
134 wxColour coveredColor = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
135
137 coveredColor = coveredColor.ChangeLightness( 140 );
138 else
139 coveredColor = coveredColor.ChangeLightness( 100 );
140
141 for( int row = 0; row < m_table->GetRowCount(); ++row )
142 {
143 for( int col = 0; col < m_table->GetColCount(); ++col )
144 {
145 SCH_TABLECELL* tableCell = m_table->GetCell( row, col );
146
147 if( tableCell->GetColSpan() == 0 || tableCell->GetRowSpan() == 0 )
148 {
149 m_grid->SetCellValue( row, col, coveredColor.GetAsString() );
150 continue;
151 }
152
153 wxString text = tableCell->GetText();
154
155 // show text variable cross-references in a human-readable format
156 if( SCHEMATIC* schematic = tableCell->Schematic() )
157 text = schematic->ConvertKIIDsToRefs( text );
158
159 m_grid->SetCellValue( row, col, text );
160 }
161 }
162
163 CallAfter( [this]()
164 {
165 for( int row = 0; row < m_table->GetRowCount(); ++row )
166 {
167 for( int col = 0; col < m_table->GetColCount(); ++col )
168 {
169 SCH_TABLECELL* tableCell = m_table->GetCell( row, col );
170
171 if( tableCell->IsSelected() )
172 {
173 m_grid->SetGridCursor( row, col );
174 m_grid->EnableCellEditControl();
175 m_grid->ShowCellEditControl();
176 return;
177 }
178 }
179 }
180 } );
181
183
184 //
185 // Table Properties
186 //
187
188 m_borderCheckbox->SetValue( m_table->StrokeExternal() );
189 m_headerBorder->SetValue( m_table->StrokeHeaderSeparator() );
190
191 if( m_table->GetBorderStroke().GetWidth() >= 0 )
192 m_borderWidth.SetValue( m_table->GetBorderStroke().GetWidth() );
193
194 m_borderColorSwatch->SetSwatchColor( m_table->GetBorderStroke().GetColor(), false );
195
196 int style = static_cast<int>( m_table->GetBorderStroke().GetLineStyle() );
197
198 if( style >= 0 && style < (int) lineTypeNames.size() )
199 m_borderStyleCombo->SetSelection( style );
200 else
201 m_borderStyleCombo->SetSelection( 0 );
202
203 m_borderWidth.Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
204 m_borderColorLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
205 m_borderColorSwatch->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
206 m_borderStyleLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
207 m_borderStyleCombo->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
208
209 bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
210 bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
211
212 m_rowSeparators->SetValue( rows );
213 m_colSeparators->SetValue( cols );
214
215 if( m_table->GetSeparatorsStroke().GetWidth() >= 0 )
216 m_separatorsWidth.SetValue( m_table->GetSeparatorsStroke().GetWidth() );
217
218 m_separatorsColorSwatch->SetSwatchColor( m_table->GetSeparatorsStroke().GetColor(), false );
219
220 style = static_cast<int>( m_table->GetSeparatorsStroke().GetLineStyle() );
221
222 if( style >= 0 && style < (int) lineTypeNames.size() )
223 m_separatorsStyleCombo->SetSelection( style );
224 else
225 m_separatorsStyleCombo->SetSelection( 0 );
226
227 m_separatorsWidth.Enable( rows || cols );
228 m_separatorsColorLabel->Enable( rows || cols );
229 m_separatorsColorSwatch->Enable( rows || cols );
230 m_separatorsStyleLabel->Enable( rows || cols );
231 m_separatorsStyleCombo->Enable( rows || cols );
232
233 return true;
234}
235
236
237void DIALOG_TABLE_PROPERTIES::getContextualTextVars( const wxString& aCrossRef, wxArrayString* aTokens )
238{
239 if( !aCrossRef.IsEmpty() )
240 {
242 SCH_SYMBOL* refSymbol = nullptr;
243
244 m_frame->Schematic().Hierarchy().GetSymbols( refs, SYMBOL_FILTER_NON_POWER );
245
246 for( int jj = 0; jj < (int) refs.GetCount(); jj++ )
247 {
248 SCH_REFERENCE& ref = refs[jj];
249
250 if( ref.GetSymbol()->GetRef( &ref.GetSheetPath(), true ) == aCrossRef )
251 {
252 refSymbol = ref.GetSymbol();
253 break;
254 }
255 }
256
257 if( refSymbol )
258 refSymbol->GetContextualTextVars( aTokens );
259 }
260 else
261 {
262 SCHEMATIC* schematic = m_table->Schematic();
263
264 if( schematic && schematic->CurrentSheet().Last() )
265 {
266 schematic->CurrentSheet().Last()->GetContextualTextVars( aTokens );
267 }
268 else
269 {
270 for( std::pair<wxString, wxString> entry : Prj().GetTextVars() )
271 aTokens->push_back( entry.first );
272 }
273 }
274}
275
276
277void DIALOG_TABLE_PROPERTIES::onBorderChecked( wxCommandEvent& aEvent )
278{
279 bool border = m_borderCheckbox->GetValue();
280 bool headerSeparator = m_headerBorder->GetValue();
281
282 if( ( border || headerSeparator ) && m_borderWidth.GetValue() < 0 )
283 m_borderWidth.SetValue( m_frame->eeconfig()->m_Drawing.default_line_thickness );
284
285 m_borderWidth.Enable( border || headerSeparator );
286 m_borderColorLabel->Enable( border || headerSeparator );
287 m_borderColorSwatch->Enable( border || headerSeparator );
288 m_borderStyleLabel->Enable( border || headerSeparator );
289 m_borderStyleCombo->Enable( border || headerSeparator );
290
291 bool row = m_rowSeparators->GetValue();
292 bool col = m_colSeparators->GetValue();
293
294 if( ( row || col ) && m_separatorsWidth.GetValue() < 0 )
295 m_separatorsWidth.SetValue( m_frame->eeconfig()->m_Drawing.default_line_thickness );
296
297 m_separatorsWidth.Enable( row || col );
298 m_separatorsColorLabel->Enable( row || col );
299 m_separatorsColorSwatch->Enable( row || col );
300 m_separatorsStyleLabel->Enable( row || col );
301 m_separatorsStyleCombo->Enable( row || col );
302}
303
304
306{
307 if( !m_grid->CommitPendingChanges() )
308 return false;
309
310 if( !wxDialog::TransferDataFromWindow() )
311 return false;
312
313 SCH_COMMIT commit( m_frame );
314
315 /* save table in undo list if not already in edit */
316 if( m_table->GetEditFlags() == 0 )
317 commit.Modify( m_table, m_frame->GetScreen() );
318
319 for( int row = 0; row < m_table->GetRowCount(); ++row )
320 {
321 for( int col = 0; col < m_table->GetColCount(); ++col )
322 {
323 SCH_TABLECELL* tableCell = m_table->GetCell( row, col );
324 wxString txt = m_grid->GetCellValue( row, col );
325
326 // Don't insert grey colour value back in to table cell
327 if( tableCell->GetColSpan() == 0 || tableCell->GetRowSpan() == 0 )
328 txt = wxEmptyString;
329
330 // convert any text variable cross-references to their UUIDs
331 if( SCHEMATIC* schematic = tableCell->Schematic() )
332 txt = schematic->ConvertRefsToKIIDs( txt );
333
334#ifdef __WXMAC__
335 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
336 // Replace it now.
337 txt.Replace( "\r", "\n" );
338#elif defined( __WINDOWS__ )
339 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
340 // drawing routines so strip the \r char.
341 txt.Replace( "\r", "" );
342#endif
343
344 tableCell->SetText( txt );
345 }
346 }
347
348 m_table->SetStrokeExternal( m_borderCheckbox->GetValue() );
349 m_table->SetStrokeHeaderSeparator( m_headerBorder->GetValue() );
350 {
351 STROKE_PARAMS stroke = m_table->GetBorderStroke();
352
353 if( m_borderCheckbox->GetValue() || m_headerBorder->GetValue() )
354 stroke.SetWidth( std::max( 0, m_borderWidth.GetIntValue() ) );
355 else
356 stroke.SetWidth( -1 );
357
358 auto it = lineTypeNames.begin();
359 std::advance( it, m_borderStyleCombo->GetSelection() );
360
361 if( it == lineTypeNames.end() )
363 else
364 stroke.SetLineStyle( it->first );
365
366 stroke.SetColor( m_borderColorSwatch->GetSwatchColor() );
367
368 m_table->SetBorderStroke( stroke );
369 }
370
371 m_table->SetStrokeRows( m_rowSeparators->GetValue() );
372 m_table->SetStrokeColumns( m_colSeparators->GetValue() );
373 {
374 STROKE_PARAMS stroke = m_table->GetSeparatorsStroke();
375
376 if( m_rowSeparators->GetValue() || m_colSeparators->GetValue() )
377 stroke.SetWidth( std::max( 0, m_separatorsWidth.GetIntValue() ) );
378 else
379 stroke.SetWidth( -1 );
380
381 auto it = lineTypeNames.begin();
382 std::advance( it, m_separatorsStyleCombo->GetSelection() );
383
384 if( it == lineTypeNames.end() )
386 else
387 stroke.SetLineStyle( it->first );
388
389 stroke.SetColor( m_separatorsColorSwatch->GetSwatchColor() );
390
391 m_table->SetSeparatorsStroke( stroke );
392 }
393
394 if( !commit.Empty() )
395 commit.Push( _( "Edit Table" ) );
396
397 return true;
398}
399
400
402{
403 Layout(); // Make sure we get the current client size for the grid
404
405 wxSize availableGridSize = m_grid->GetClientSize();
406
407 if( availableGridSize.x == 0 || availableGridSize.y == 0 )
408 return;
409
410 BOX2I tableBBox = m_table->GetBoundingBox();
411 double scalerX = static_cast<double>( availableGridSize.x ) / tableBBox.GetWidth();
412 double scalerY = static_cast<double>( availableGridSize.y ) / tableBBox.GetHeight();
413
414 for( int row = 0; row < m_table->GetRowCount(); ++row )
415 m_grid->SetRowSize( row, std::floor( m_table->GetRowHeight( row ) * scalerY ) );
416
417 for( int col = 0; col < m_table->GetColCount(); ++col )
418 m_grid->SetColSize( col, std::floor( m_table->GetColWidth( col ) * scalerX ) );
419}
420
421
422void DIALOG_TABLE_PROPERTIES::onSize( wxSizeEvent& aEvent )
423{
424 if( m_table )
426
427 aEvent.Skip();
428}
429
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:100
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr size_type GetHeight() const
Definition box2.h:212
COLOR4D GetColor(int aLayer) const
bool Empty() const
Definition commit.h:145
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
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 getContextualTextVars(const wxString &aCrossRef, wxArrayString *aTokens)
void onBorderChecked(wxCommandEvent &aEvent) override
bool IsSelected() const
Definition eda_item.h:134
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:236
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:57
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
Holds all the data relating to one schematic.
Definition schematic.h:149
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:312
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
Commit for the schematic and symbol editors.
Definition sch_commit.h:54
void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
Schematic editor (Eeschema) main window.
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:302
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
A helper to define a symbol's reference designator in a schematic.
const SCH_SHEET_PATH & GetSheetPath() const
SCH_SYMBOL * GetSymbol() const
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this sheet.
Schematic symbol object.
Definition sch_symbol.h:75
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
int GetColSpan() const
int GetRowSpan() 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)
Simple container to manage line stroke parameters.
void SetLineStyle(LINE_STYLE aLineStyle)
void SetWidth(int aWidth)
void SetColor(const KIGFX::COLOR4D &aColor)
#define _(s)
@ LAYER_SCHEMATIC_BACKGROUND
Definition layer_ids.h:516
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition wxgtk/ui.cpp:54
@ SYMBOL_FILTER_NON_POWER
const std::map< LINE_STYLE, struct LINE_STYLE_DESC > lineTypeNames
Conversion map between LINE_STYLE values and style names displayed.