KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbnew/dialogs/dialog_tablecell_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 <wx/hyperlink.h>
21
23#include <widgets/font_choice.h>
25#include <confirm.h>
26#include <board_commit.h>
28#include <board.h>
29#include <footprint.h>
30#include <pcb_textbox.h>
31#include <pcb_tablecell.h>
32#include <pcb_table.h>
33#include <project.h>
34#include <pcb_edit_frame.h>
36#include <tool/tool_manager.h>
37#include <tools/pcb_actions.h>
38#include <scintilla_tricks.h>
40
42 std::vector<PCB_TABLECELL*> aCells ) :
44 m_frame( aFrame ),
45 m_table( nullptr ),
46 m_cells( std::move( aCells ) ),
50 m_marginLeft( aFrame, nullptr, m_marginLeftCtrl, nullptr ),
51 m_marginTop( aFrame, nullptr, m_marginTopCtrl, m_marginTopUnits ),
52 m_marginRight( aFrame, nullptr, m_marginRightCtrl, nullptr ),
53 m_marginBottom( aFrame, nullptr, m_marginBottomCtrl, nullptr ),
56{
57 wxASSERT( m_cells.size() > 0 && m_cells[0] );
58
59 m_cellText->SetEOLMode( wxSTC_EOL_LF );
60
61 // Wrapping is display-only and does not insert newlines into the stored text.
62 m_cellText->SetWrapMode( wxSTC_WRAP_WORD );
63 m_cellText->SetWrapVisualFlags( wxSTC_WRAPVISUALFLAG_END );
64 m_cellText->SetWrapIndentMode( wxSTC_WRAPINDENT_INDENT );
65
66#ifdef _WIN32
67 // Without this setting, on Windows, some esoteric unicode chars create display issue
68 // in a wxStyledTextCtrl.
69 // for SetTechnology() info, see https://www.scintilla.org/ScintillaDoc.html#SCI_SETTECHNOLOGY
70 m_cellText->SetTechnology( wxSTC_TECHNOLOGY_DIRECTWRITE );
71#endif
72
74 m_cellText, wxT( "{}" ), false,
75 // onAcceptFn
76 [this]( wxKeyEvent& aEvent )
77 {
78 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
79 },
80 // onCharFn
81 [this]( wxStyledTextEvent& aEvent )
82 {
83 m_scintillaTricks->DoTextVarAutocomplete(
84 // getTokensFn
85 [this]( const wxString& xRef, wxArrayString* tokens )
86 {
87 m_frame->GetContextualTextVars( m_table, xRef, tokens );
88 } );
89 } );
90
91 // A hack which causes Scintilla to auto-size the text editor canvas
92 // See: https://github.com/jacobslusser/ScintillaNET/issues/216
93 m_cellText->SetScrollWidth( 1 );
94 m_cellText->SetScrollWidthTracking( true );
95
97
98 m_table = static_cast<PCB_TABLE*>( m_cells[0]->GetParent() );
99
100 m_hAlignLeft->SetIsRadioButton();
102 m_hAlignCenter->SetIsRadioButton();
104 m_hAlignRight->SetIsRadioButton();
106
107 m_separator0->SetIsSeparator();
108
109 m_vAlignTop->SetIsRadioButton();
111 m_vAlignCenter->SetIsRadioButton();
113 m_vAlignBottom->SetIsRadioButton();
115
116 m_separator1->SetIsSeparator();
117
118 m_bold->SetIsCheckButton();
120 m_italic->SetIsCheckButton();
122
123 m_autoTextThickness->SetIsCheckButton();
125
127 Layout();
128
129 m_helpWindow = nullptr;
130
131 Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TABLECELL_PROPERTIES::OnCharHook ), nullptr, this );
132
133 m_hAlignLeft->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onHAlignButton, this );
136 m_vAlignTop->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onVAlignButton, this );
139
140 // Now all widgets have the size fixed, call FinishDialogSettings
142}
143
145{
146 Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TABLECELL_PROPERTIES::OnCharHook ), nullptr, this );
147
148 delete m_scintillaTricks;
149 m_scintillaTricks = nullptr;
150
151 if( m_helpWindow )
152 m_helpWindow->Destroy();
153}
154
155
157{
158 if( !wxDialog::TransferDataToWindow() )
159 return false;
160
161 bool firstCell = true;
164 int textThickness = 0;
165 int effectivePenWidth = 0;
166
167 for( PCB_TABLECELL* cell : m_cells )
168 {
169 if( firstCell )
170 {
171 m_cellTextCtrl->SetValue( cell->GetText() );
172
173 m_fontCtrl->SetFontSelection( cell->GetFont() );
174 m_textWidth.SetValue( cell->GetTextWidth() );
175 m_textHeight.SetValue( cell->GetTextHeight() );
176 textThickness = cell->GetTextThickness();
177 effectivePenWidth = cell->GetEffectiveTextPenWidth();
178
179 hAlign = cell->GetHorizJustify();
180 vAlign = cell->GetVertJustify();
181
182 m_marginLeft.SetValue( cell->GetMarginLeft() );
183 m_marginTop.SetValue( cell->GetMarginTop() );
184 m_marginRight.SetValue( cell->GetMarginRight() );
185 m_marginBottom.SetValue( cell->GetMarginBottom() );
186
187 // wxCheckBoxState bold = cell->IsBold() ? wxCHK_CHECKED : wxCHK_UNCHECKED;
188 m_bold->Check( cell->IsBold() );
189
190 // wxCheckBoxState italic = cell->IsItalic() ? wxCHK_CHECKED : wxCHK_UNCHECKED;
191 m_italic->Check( cell->IsItalic() );
192
193 m_cbKnockout->SetValue( cell->IsKnockout() );
194
195 firstCell = false;
196 }
197 else
198 {
199 if( cell->GetText() != m_cellTextCtrl->GetValue() )
201
202 if( cell->GetFont() != m_fontCtrl->GetFontSelection( cell->IsBold(), cell->IsItalic() ) )
203 m_fontCtrl->SetSelection( -1 );
204
205 if( cell->GetTextWidth() != m_textWidth.GetValue() )
207
208 if( cell->GetTextHeight() != m_textHeight.GetValue() )
210
211 if( cell->GetTextThickness() != textThickness )
212 textThickness = -1;
213
214 if( cell->GetEffectiveTextPenWidth() != effectivePenWidth )
215 effectivePenWidth = -1;
216
217 if( cell->GetHorizJustify() != hAlign )
219
220 if( cell->GetVertJustify() != vAlign )
222
223 if( cell->GetMarginLeft() != m_marginLeft.GetIntValue() )
225
226 if( cell->GetMarginTop() != m_marginTop.GetIntValue() )
228
229 if( cell->GetMarginRight() != m_marginRight.GetIntValue() )
231
232 if( cell->GetMarginBottom() != m_marginBottom.GetIntValue() )
234 }
235
236 switch( hAlign )
237 {
238 case GR_TEXT_H_ALIGN_LEFT: m_hAlignLeft->Check(); break;
239 case GR_TEXT_H_ALIGN_CENTER: m_hAlignCenter->Check(); break;
240 case GR_TEXT_H_ALIGN_RIGHT: m_hAlignRight->Check(); break;
242 }
243
244 switch( vAlign )
245 {
246 case GR_TEXT_V_ALIGN_TOP: m_vAlignTop->Check(); break;
247 case GR_TEXT_V_ALIGN_CENTER: m_vAlignCenter->Check(); break;
248 case GR_TEXT_V_ALIGN_BOTTOM: m_vAlignBottom->Check(); break;
250 }
251 }
252
254 m_autoTextThickness->Check( false );
255
256 if( textThickness == 0 )
257 {
258 if( effectivePenWidth > 0 )
259 m_textThickness.SetValue( effectivePenWidth );
260
261 m_autoTextThickness->Check( true );
262 m_textThickness.Enable( false );
263 }
264 else if( textThickness > 0 )
265 {
266 m_textThickness.SetValue( textThickness );
267 }
268
269 return true;
270}
271
272void DIALOG_TABLECELL_PROPERTIES::onBoldToggle( wxCommandEvent& aEvent )
273{
274 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
275
276 if( aEvent.IsChecked() )
277 m_textThickness.ChangeValue( GetPenSizeForBold( textSize ) );
278 else
279 m_textThickness.ChangeValue( GetPenSizeForNormal( textSize ) );
280
281 aEvent.Skip();
282}
283
284void DIALOG_TABLECELL_PROPERTIES::onTextSize( wxCommandEvent& aEvent )
285{
286 if( m_autoTextThickness->IsChecked() )
287 {
288 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
289 int thickness;
290
291 // Calculate the "best" thickness from text size and bold option:
292 if( m_bold->IsChecked() )
293 thickness = GetPenSizeForBold( textSize );
294 else
295 thickness = GetPenSizeForNormal( textSize );
296
297 m_textThickness.SetValue( thickness );
298 }
299}
300
301
303{
304 if( aEvent.IsChecked() )
305 {
306 m_autoTextThickness->Check( true );
307
308 if( !m_textWidth.IsIndeterminate() && !m_textHeight.IsIndeterminate() )
309 {
310 wxCommandEvent dummy;
311 onTextSize( dummy );
312 }
313
314 m_textThickness.Enable( false );
315 }
316 else
317 {
318 m_textThickness.Enable( true );
319 }
320}
321
322
323void DIALOG_TABLECELL_PROPERTIES::onHAlignButton( wxCommandEvent& aEvent )
324{
326 {
327 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
328 btn->Check( false );
329 }
330}
331
332
333void DIALOG_TABLECELL_PROPERTIES::onVAlignButton( wxCommandEvent& aEvent )
334{
335 for( BITMAP_BUTTON* btn : { m_vAlignTop, m_vAlignCenter, m_vAlignBottom } )
336 {
337 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
338 btn->Check( false );
339 }
340}
341
342
344{
345 if( !wxDialog::TransferDataFromWindow() )
346 return false;
347
348 BOARD_COMMIT commit( m_frame );
349 commit.Modify( m_table );
350
351 // If no other command in progress, prepare undo command
352 // (for a command in progress, will be made later, at the completion of command)
353 bool pushCommit = ( m_table->GetEditFlags() == 0 );
354
355 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
356 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
357 if( !pushCommit )
358 m_table->SetFlags( IN_EDIT );
359
360 for( PCB_TABLECELL* cell : m_cells )
361 {
362 if( m_cellTextCtrl->GetValue() != INDETERMINATE_STATE )
363 {
364 wxString txt = m_cellTextCtrl->GetValue();
365
366#ifdef __WXMAC__
367 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
368 // Replace it now.
369 txt.Replace( "\r", "\n" );
370#elif defined( __WINDOWS__ )
371 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
372 // drawing routines so strip the \r char.
373 txt.Replace( "\r", "" );
374#endif
375
376 cell->SetText( txt );
377 }
378
379 cell->SetBold( m_bold->IsChecked() );
380 cell->SetItalic( m_italic->IsChecked() );
381 cell->SetIsKnockout( m_cbKnockout->IsChecked() );
382
383 if( m_fontCtrl->HaveFontSelection() )
384 cell->SetFont( m_fontCtrl->GetFontSelection( cell->IsBold(), cell->IsItalic() ) );
385
386 if( !m_textWidth.IsIndeterminate() )
387 cell->SetTextWidth( m_textWidth.GetIntValue() );
388
389 if( !m_textHeight.IsIndeterminate() )
390 cell->SetTextHeight( m_textHeight.GetIntValue() );
391
392 if( m_autoTextThickness->IsChecked() )
393 cell->SetAutoThickness( true );
394 else if( !m_textThickness.IsIndeterminate() )
395 cell->SetTextThickness( m_textThickness.GetIntValue() );
396
397 if( m_hAlignLeft->IsChecked() )
398 cell->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
399 else if( m_hAlignRight->IsChecked() )
400 cell->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
401 else if( m_hAlignCenter->IsChecked() )
402 cell->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
403
404 if( m_vAlignTop->IsChecked() )
405 cell->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
406 else if( m_vAlignBottom->IsChecked() )
407 cell->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
408 else if( m_vAlignCenter->IsChecked() )
409 cell->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
410
411 if( !m_marginLeft.IsIndeterminate() )
412 cell->SetMarginLeft( m_marginLeft.GetIntValue() );
413
414 if( !m_marginTop.IsIndeterminate() )
415 cell->SetMarginTop( m_marginTop.GetIntValue() );
416
417 if( !m_marginRight.IsIndeterminate() )
418 cell->SetMarginRight( m_marginRight.GetIntValue() );
419
420 if( !m_marginBottom.IsIndeterminate() )
421 cell->SetMarginBottom( m_marginBottom.GetIntValue() );
422 }
423
424 if( !commit.Empty() )
425 commit.Push( _( "Edit Table Cell Properties" ), SKIP_CONNECTIVITY );
426
428 return true;
429}
430
431
432void DIALOG_TABLECELL_PROPERTIES::onEditTable( wxCommandEvent& aEvent )
433{
435 {
437 Close();
438 }
439}
440
441
442void DIALOG_TABLECELL_PROPERTIES::onSyntaxHelp( wxHyperlinkEvent& aEvent )
443{
444 if( m_helpWindow )
445 {
446 m_helpWindow->Raise();
447 m_helpWindow->Show( true );
448 return;
449 }
450
452}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
@ text_align_right
@ text_valign_top
@ text_align_left
@ text_valign_center
@ text_align_center
@ text_valign_bottom
@ edit_cmp_symb_links
#define SKIP_CONNECTIVITY
A bitmap button widget that behaves like an AUI toolbar item's button when it is drawn.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:79
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...
virtual void OnCharHook(wxKeyEvent &aEvt)
DIALOG_TABLECELL_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Table Cell Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
void onBoldToggle(wxCommandEvent &aEvent) override
void onAutoTextThickness(wxCommandEvent &aEvent) override
DIALOG_TABLECELL_PROPERTIES(SCH_EDIT_FRAME *aParentFrame, std::vector< SCH_TABLECELL * > aCells)
void onSyntaxHelp(wxHyperlinkEvent &aEvent) override
Common, abstract interface for edit frames.
static HTML_MESSAGE_BOX * ShowSyntaxHelp(wxWindow *aParentWindow)
Display a syntax help window for text variables and expressions.
Definition pcb_text.cpp:873
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
This file is part of the common library.
#define _(s)
#define IN_EDIT
Item currently edited.
int GetPenSizeForBold(int aTextSize)
Definition gr_text.cpp:33
int GetPenSizeForNormal(int aTextSize)
Definition gr_text.cpp:57
STL namespace.
std::vector< FAB_LAYER_COLOR > dummy
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_H_ALIGN_INDETERMINATE
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
Definition ui_common.h:46