KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_textbox_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, 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
25#include <widgets/font_choice.h>
27#include <confirm.h>
28#include <board_commit.h>
30#include <board.h>
31#include <footprint.h>
32#include <pcb_textbox.h>
33#include <project.h>
34#include <pcb_edit_frame.h>
36#include <scintilla_tricks.h>
37
39 PCB_TEXTBOX* aTextBox ) :
41 m_frame( aParent ),
42 m_textBox( aTextBox ),
43 m_textWidth( aParent, m_SizeXLabel, m_SizeXCtrl, m_SizeXUnits ),
44 m_textHeight( aParent, m_SizeYLabel, m_SizeYCtrl, m_SizeYUnits ),
45 m_thickness( aParent, m_ThicknessLabel, m_ThicknessCtrl, m_ThicknessUnits ),
46 m_orientation( aParent, m_OrientLabel, m_OrientCtrl, nullptr ),
47 m_borderWidth( aParent, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits )
48{
49 m_MultiLineText->SetEOLMode( wxSTC_EOL_LF );
50
51#ifdef _WIN32
52 // Without this setting, on Windows, some esoteric unicode chars create display issue
53 // in a wxStyledTextCtrl.
54 // for SetTechnology() info, see https://www.scintilla.org/ScintillaDoc.html#SCI_SETTECHNOLOGY
55 m_MultiLineText->SetTechnology(wxSTC_TECHNOLOGY_DIRECTWRITE);
56#endif
57
58 m_scintillaTricks = new SCINTILLA_TRICKS( m_MultiLineText, wxT( "{}" ), false,
59 // onAcceptFn
60 [this]( wxKeyEvent& aEvent )
61 {
62 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
63 },
64 // onCharFn
65 [this]( wxStyledTextEvent& aEvent )
66 {
68 // getTokensFn
69 [this]( const wxString& xRef, wxArrayString* tokens )
70 {
71 m_frame->GetContextualTextVars( m_textBox, xRef, tokens );
72 } );
73 } );
74
75 // A hack which causes Scintilla to auto-size the text editor canvas
76 // See: https://github.com/jacobslusser/ScintillaNET/issues/216
77 m_MultiLineText->SetScrollWidth( 1 );
78 m_MultiLineText->SetScrollWidthTracking( true );
79
81 {
82 // Do not allow locking items in the footprint editor
83 m_cbLocked->Show( false );
84 }
85
87
89
91 m_bold->SetBitmap( KiBitmapBundle( BITMAPS::text_bold ) );
93 m_italic->SetBitmap( KiBitmapBundle( BITMAPS::text_italic ) );
94
96
98 m_hAlignLeft->SetBitmap( KiBitmapBundle( BITMAPS::text_align_left ) );
100 m_hAlignCenter->SetBitmap( KiBitmapBundle( BITMAPS::text_align_center ) );
102 m_hAlignRight->SetBitmap( KiBitmapBundle( BITMAPS::text_align_right ) );
103
105
107 m_mirrored->SetBitmap( KiBitmapBundle( BITMAPS::text_mirrored ) );
108
110
112 m_vAlignTop->SetBitmap( KiBitmapBundle( BITMAPS::text_valign_top ) );
114 m_vAlignCenter->SetBitmap( KiBitmapBundle( BITMAPS::text_valign_center ) );
116 m_vAlignBottom->SetBitmap( KiBitmapBundle( BITMAPS::text_valign_bottom ) );
117
119
120 m_adjustTextThickness->SetBitmap( KiBitmapBundle( BITMAPS::refresh ) );
121
122 // Configure the layers list selector. Note that footprints are built outside the current
123 // board and so we may need to show all layers if the text is on an unactivated layer.
126
130
131 m_orientation.SetUnits( EDA_UNITS::DEGREES );
133
134 // Set predefined rotations in combo dropdown, according to the locale floating point
135 // separator notation
136 double rot_list[] = { 0.0, 90.0, -90.0, 180.0 };
137
138 for( size_t ii = 0; ii < m_OrientCtrl->GetCount() && ii < 4; ++ii )
139 m_OrientCtrl->SetString( ii, wxString::Format( "%.1f", rot_list[ii] ) );
140
141 for( const auto& [ lineStyle, lineStyleDesc ] : lineTypeNames )
142 m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmapBundle( lineStyleDesc.bitmap ) );
143
145
146 // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set,
147 // so we have to listen to wxEVT_CHAR_HOOK events instead.
148 Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
149 nullptr, this );
150
152}
153
154
156{
157 Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
158 nullptr, this );
159
160 delete m_scintillaTricks;
161}
162
163
165{
166 DIALOG_TEXTBOX_PROPERTIES dlg( this, aTextBox );
167
168 // QuasiModal required for Scintilla auto-complete
169 return dlg.ShowQuasiModal();
170}
171
172
174{
175 BOARD* board = m_frame->GetBoard();
176 wxString converted = board->ConvertKIIDsToCrossReferences(
178
179 m_MultiLineText->SetValue( converted );
180 m_MultiLineText->SetSelection( -1, -1 );
181 m_MultiLineText->EmptyUndoBuffer();
182
183 m_cbLocked->SetValue( m_textBox->IsLocked() );
184
186
188
192
195
196 switch( m_textBox->GetHorizJustify() )
197 {
198 case GR_TEXT_H_ALIGN_LEFT: m_hAlignLeft->Check( true ); break;
199 case GR_TEXT_H_ALIGN_CENTER: m_hAlignCenter->Check( true ); break;
200 case GR_TEXT_H_ALIGN_RIGHT: m_hAlignRight->Check( true ); break;
202 }
203
204 switch( m_textBox->GetVertJustify() )
205 {
206 case GR_TEXT_V_ALIGN_TOP: m_vAlignTop->Check( true ); break;
207 case GR_TEXT_V_ALIGN_CENTER: m_vAlignCenter->Check( true ); break;
208 case GR_TEXT_V_ALIGN_BOTTOM: m_vAlignBottom->Check( true ); break;
210 }
211
213
214 EDA_ANGLE orientation = m_textBox->GetTextAngle();
216
219
221 m_borderWidth.SetValue( stroke.GetWidth() );
222
223 LINE_STYLE style = stroke.GetLineStyle();
224
225 if( style == LINE_STYLE::DEFAULT )
226 style = LINE_STYLE::SOLID;
227
228 if( (int) style < (int) lineTypeNames.size() )
229 m_borderStyleCombo->SetSelection( (int) style );
230
234
235 return DIALOG_TEXTBOX_PROPERTIES_BASE::TransferDataToWindow();
236}
237
238void DIALOG_TEXTBOX_PROPERTIES::onValignButton( wxCommandEvent& aEvent )
239{
241 {
242 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
243 btn->Check( false );
244 }
245}
246
247void DIALOG_TEXTBOX_PROPERTIES::onFontSelected( wxCommandEvent & aEvent )
248{
249 if( KIFONT::FONT::IsStroke( aEvent.GetString() ) )
250 {
251 m_thickness.Show( true );
252
253 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
254 int thickness = m_thickness.GetValue();
255
256 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
257 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
258 }
259 else
260 {
261 m_thickness.Show( false );
262 }
263}
264
265
266void DIALOG_TEXTBOX_PROPERTIES::onBoldToggle( wxCommandEvent & aEvent )
267{
268 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
269
270 if( aEvent.IsChecked() )
272 else
274
275 aEvent.Skip();
276}
277
278
279void DIALOG_TEXTBOX_PROPERTIES::onHalignButton( wxCommandEvent& aEvent )
280{
282 {
283 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
284 btn->Check( false );
285 }
286}
287
288
289void DIALOG_TEXTBOX_PROPERTIES::onThickness( wxCommandEvent& event )
290{
291 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
292 int thickness = m_thickness.GetValue();
293
294 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
295 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
296}
297
298
300{
301 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
302 int thickness;
303
304 // Calculate the "best" thickness from text size and bold option:
305 if( m_bold->IsChecked() )
306 thickness = GetPenSizeForBold( textSize );
307 else
308 thickness = GetPenSizeForNormal( textSize );
309
310 m_thickness.SetValue( thickness );
311}
312
313
315{
316 bool border = m_borderCheckbox->GetValue();
317
318 if( border && m_borderWidth.GetValue() <= 0 )
319 {
322 }
323
324 m_borderWidth.Enable( border );
325 m_borderStyleLabel->Enable( border );
326 m_borderStyleCombo->Enable( border );
327}
328
329
331{
332 if( !DIALOG_TEXTBOX_PROPERTIES_BASE::TransferDataFromWindow() )
333 return false;
334
336 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
337
338 if( !m_textWidth.Validate( minSize, maxSize ) || !m_textHeight.Validate( minSize, maxSize ) )
339 return false;
340
341 BOARD_COMMIT commit( m_frame );
342 commit.Modify( m_textBox );
343
344 // If no other command in progress, prepare undo command
345 // (for a command in progress, will be made later, at the completion of command)
346 bool pushCommit = ( m_textBox->GetEditFlags() == 0 );
347
348 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
349 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
350 if( !pushCommit )
352
353 BOARD* board = m_frame->GetBoard();
354 wxString txt = board->ConvertCrossReferencesToKIIDs( m_MultiLineText->GetValue() );
355
356#ifdef __WXMAC__
357 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
358 // Replace it now.
359 txt.Replace( "\r", "\n" );
360#elif defined( __WINDOWS__ )
361 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
362 // drawing routines so strip the \r char.
363 txt.Replace( "\r", "" );
364#endif
365
367 m_textBox->SetLocked( m_cbLocked->GetValue() );
369
371 {
373 m_italic->IsChecked() ) );
374 }
375
378
379 // Test for acceptable values for thickness and size and clamp if fails
381
382 if( m_textBox->GetTextThickness() > maxPenWidth )
383 {
384 DisplayError( this, _( "The text thickness is too large for the text size.\n"
385 "It will be clamped." ) );
386 m_textBox->SetTextThickness( maxPenWidth );
387 }
388
392
393 if( m_hAlignLeft->IsChecked() )
395 else if( m_hAlignCenter->IsChecked() )
397 else
399
400 if( m_vAlignTop->IsChecked() )
402 else if( m_vAlignCenter->IsChecked() )
404 else
406
408
411
413 stroke.SetWidth( m_borderWidth.GetValue() );
414
415 auto it = lineTypeNames.begin();
416 std::advance( it, m_borderStyleCombo->GetSelection() );
417
418 if( it == lineTypeNames.end() )
419 stroke.SetLineStyle( LINE_STYLE::SOLID );
420 else
421 stroke.SetLineStyle( it->first );
422
423 m_textBox->SetStroke( stroke );
424
427
428 if( pushCommit )
429 commit.Push( _( "Edit Text Box Properties" ) );
430
431 return true;
432}
433
434
436{
439
440 event.Skip();
441}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:110
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
A bitmap button widget that behaves like an AUI toolbar item's button when it is drawn.
Definition: bitmap_button.h:42
void SetIsRadioButton()
bool IsChecked() const
void Check(bool aCheck=true)
Check the control.
void SetIsSeparator()
Render button as a toolbar separator.
void SetIsCheckButton()
Setup the control as a two-state button (checked or unchecked).
void SetBitmap(const wxBitmapBundle &aBmp)
Set the bitmap shown when the button is enabled.
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
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.
void SetLocked(bool aLocked) override
Definition: board_item.h:320
bool IsLocked() const override
Definition: board_item.cpp:76
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:48
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:299
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition: board.cpp:855
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:1644
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:946
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1698
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:66
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowQuasiModal()
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)
Class DIALOG_TEXTBOX_PROPERTIES_BASE.
void onHalignButton(wxCommandEvent &aEvent) override
void onThickness(wxCommandEvent &aEvent) override
void updateTextThickness(wxCommandEvent &aEvent) override
void onBoldToggle(wxCommandEvent &aEvent) override
DIALOG_TEXTBOX_PROPERTIES(PCB_BASE_EDIT_FRAME *aParent, PCB_TEXTBOX *aTextBox)
void onMultiLineTCLostFocus(wxFocusEvent &event) override
void onFontSelected(wxCommandEvent &aEvent) override
void onValignButton(wxCommandEvent &aEvent) override
void onBorderChecked(wxCommandEvent &event) override
EDA_ANGLE Normalize()
Definition: eda_angle.h:224
EDA_ANGLE Normalize180()
Definition: eda_angle.h:263
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:144
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:138
bool IsItalic() const
Definition: eda_text.h:156
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:526
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
KIFONT::FONT * GetFont() const
Definition: eda_text.h:234
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:386
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:410
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:187
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
Definition: eda_text.cpp:371
virtual void ClearBoundingBoxCache()
Definition: eda_text.cpp:657
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:284
virtual void ClearRenderCache()
Definition: eda_text.cpp:651
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
Definition: eda_text.cpp:320
bool IsMirrored() const
Definition: eda_text.h:177
bool IsBold() const
Definition: eda_text.h:171
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:190
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
int GetTextThickness() const
Definition: eda_text.h:126
void SetFont(KIFONT::FONT *aFont)
Definition: eda_text.cpp:492
VECTOR2I GetTextSize() const
Definition: eda_text.h:248
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:402
void SetFontSelection(KIFONT::FONT *aFont, bool aSilentMode=false)
Set the selection in wxChoice widget.
Definition: font_choice.cpp:73
KIFONT::FONT * GetFontSelection(bool aBold, bool aItalic, bool aForDrawingSheet=false) const
bool HaveFontSelection() const
Definition: font_choice.cpp:95
virtual bool IsStroke() const
Definition: font.h:138
int SetLayerSelection(int layer)
bool SetLayersHotkeys(bool value)
Common, abstract interface for edit frames.
int ShowTextBoxPropertiesDialog(PCB_TEXTBOX *aTextBox)
void GetContextualTextVars(BOARD_ITEM *aSourceItem, const wxString &aCrossRef, wxArrayString *aTokens)
BOARD * GetBoard() const
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void ShowNonActivatedLayers(bool aShow)
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_shape.cpp:177
STROKE_PARAMS GetStroke() const override
Definition: pcb_shape.h:91
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:92
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_shape.h:71
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
void SetBorderEnabled(bool enabled)
void SetTextAngle(const EDA_ANGLE &aAngle) override
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:94
int GetWidth() const
void SetLineStyle(LINE_STYLE aLineStyle)
void SetWidth(int aWidth)
LINE_STYLE GetLineStyle() const
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 SetPrecision(int aLength)
Normally not needed, but can be used to set the precision when using internal units that are floats (...
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
virtual EDA_ANGLE GetAngleValue()
bool IsIndeterminate() const
Return true if the control holds the indeterminate value (for instance, if it represents a multiple s...
virtual void SetAngleValue(const EDA_ANGLE &aValue)
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Validate the control against the given range, informing the user of any errors found.
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void Show(bool aShow, bool aResize=false)
Show/hide the label, widget and units label.
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
This file is part of the common library.
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
#define IN_EDIT
Item currently edited.
#define TEXT_MIN_SIZE_MM
Minimum text size (1 micron).
Definition: eda_text.h:47
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition: eda_text.h:48
int GetPenSizeForBold(int aTextSize)
Definition: gr_text.cpp:36
int GetPenSizeForNormal(int aTextSize)
Definition: gr_text.cpp:60
int ClampTextPenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
Definition: gr_text.cpp:72
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:747
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_QUOTED_STR
Definition: string_utils.h:57
const std::map< LINE_STYLE, struct LINE_STYLE_DESC > lineTypeNames
Conversion map between LINE_STYLE values and style names displayed.
LINE_STYLE
Dashed line types.
Definition: stroke_params.h:46
constexpr int mmToIU(double mm) const
Definition: base_units.h:90
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_H_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695