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