KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 // Configure the layers list selector. Note that footprints are built outside the current
121 // board and so we may need to show all layers if the text is on an unactivated layer.
124
128
129 m_orientation.SetUnits( EDA_UNITS::DEGREES );
131
132 // Set predefined rotations in combo dropdown, according to the locale floating point
133 // separator notation
134 double rot_list[] = { 0.0, 90.0, -90.0, 180.0 };
135
136 for( size_t ii = 0; ii < m_OrientCtrl->GetCount() && ii < 4; ++ii )
137 m_OrientCtrl->SetString( ii, wxString::Format( "%.1f", rot_list[ii] ) );
138
139 for( const auto& [ lineStyle, lineStyleDesc ] : lineTypeNames )
140 m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmapBundle( lineStyleDesc.bitmap ) );
141
143
144 // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set,
145 // so we have to listen to wxEVT_CHAR_HOOK events instead.
146 Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
147 nullptr, this );
148
150}
151
152
154{
155 Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
156 nullptr, this );
157
158 delete m_scintillaTricks;
159}
160
161
163{
164 DIALOG_TEXTBOX_PROPERTIES dlg( this, aTextBox );
165
166 // QuasiModal required for Scintilla auto-complete
167 return dlg.ShowQuasiModal();
168}
169
170
172{
173 BOARD* board = m_frame->GetBoard();
174 wxString converted = board->ConvertKIIDsToCrossReferences(
176
177 m_MultiLineText->SetValue( converted );
178 m_MultiLineText->SetSelection( -1, -1 );
179 m_MultiLineText->EmptyUndoBuffer();
180
181 m_cbLocked->SetValue( m_textBox->IsLocked() );
182
184
186
190
193
194 switch( m_textBox->GetHorizJustify() )
195 {
196 case GR_TEXT_H_ALIGN_LEFT: m_hAlignLeft->Check( true ); break;
197 case GR_TEXT_H_ALIGN_CENTER: m_hAlignCenter->Check( true ); break;
198 case GR_TEXT_H_ALIGN_RIGHT: m_hAlignRight->Check( true ); break;
200 }
201
202 switch( m_textBox->GetVertJustify() )
203 {
204 case GR_TEXT_V_ALIGN_TOP: m_vAlignTop->Check( true ); break;
205 case GR_TEXT_V_ALIGN_CENTER: m_vAlignCenter->Check( true ); break;
206 case GR_TEXT_V_ALIGN_BOTTOM: m_vAlignBottom->Check( true ); break;
208 }
209
211
212 EDA_ANGLE orientation = m_textBox->GetTextAngle();
214
217
219 m_borderWidth.SetValue( stroke.GetWidth() );
220
221 LINE_STYLE style = stroke.GetLineStyle();
222
223 if( style == LINE_STYLE::DEFAULT )
224 style = LINE_STYLE::SOLID;
225
226 if( (int) style < (int) lineTypeNames.size() )
227 m_borderStyleCombo->SetSelection( (int) style );
228
232
233 return DIALOG_TEXTBOX_PROPERTIES_BASE::TransferDataToWindow();
234}
235
236void DIALOG_TEXTBOX_PROPERTIES::onValignButton( wxCommandEvent& aEvent )
237{
239 {
240 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
241 btn->Check( false );
242 }
243}
244
245void DIALOG_TEXTBOX_PROPERTIES::onFontSelected( wxCommandEvent & aEvent )
246{
247 if( KIFONT::FONT::IsStroke( aEvent.GetString() ) )
248 {
249 m_thickness.Show( true );
250
251 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
252 int thickness = m_thickness.GetValue();
253
254 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
255 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
256 }
257 else
258 {
259 m_thickness.Show( false );
260 }
261}
262
263
264void DIALOG_TEXTBOX_PROPERTIES::onBoldToggle( wxCommandEvent & aEvent )
265{
266 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
267
268 if( aEvent.IsChecked() )
270 else
272
273 aEvent.Skip();
274}
275
276
277void DIALOG_TEXTBOX_PROPERTIES::onHalignButton( wxCommandEvent& aEvent )
278{
280 {
281 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
282 btn->Check( false );
283 }
284}
285
286
287void DIALOG_TEXTBOX_PROPERTIES::onThickness( wxCommandEvent& event )
288{
289 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
290 int thickness = m_thickness.GetValue();
291
292 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
293 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
294}
295
296
298{
299 bool border = m_borderCheckbox->GetValue();
300
301 if( border && m_borderWidth.GetValue() <= 0 )
302 {
305 }
306
307 m_borderWidth.Enable( border );
308 m_borderStyleLabel->Enable( border );
309 m_borderStyleCombo->Enable( border );
310}
311
312
314{
315 if( !DIALOG_TEXTBOX_PROPERTIES_BASE::TransferDataFromWindow() )
316 return false;
317
319 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
320
321 if( !m_textWidth.Validate( minSize, maxSize ) || !m_textHeight.Validate( minSize, maxSize ) )
322 return false;
323
324 BOARD_COMMIT commit( m_frame );
325 commit.Modify( m_textBox );
326
327 // If no other command in progress, prepare undo command
328 // (for a command in progress, will be made later, at the completion of command)
329 bool pushCommit = ( m_textBox->GetEditFlags() == 0 );
330
331 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
332 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
333 if( !pushCommit )
335
336 BOARD* board = m_frame->GetBoard();
337 wxString txt = board->ConvertCrossReferencesToKIIDs( m_MultiLineText->GetValue() );
338
339#ifdef __WXMAC__
340 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
341 // Replace it now.
342 txt.Replace( "\r", "\n" );
343#elif defined( __WINDOWS__ )
344 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
345 // drawing routines so strip the \r char.
346 txt.Replace( "\r", "" );
347#endif
348
350 m_textBox->SetLocked( m_cbLocked->GetValue() );
352
354 {
356 m_italic->IsChecked() ) );
357 }
358
361
362 // Test for acceptable values for thickness and size and clamp if fails
364
365 if( m_textBox->GetTextThickness() > maxPenWidth )
366 {
367 DisplayError( this, _( "The text thickness is too large for the text size.\n"
368 "It will be clamped." ) );
369 m_textBox->SetTextThickness( maxPenWidth );
370 }
371
375
376 if( m_hAlignLeft->IsChecked() )
378 else if( m_hAlignCenter->IsChecked() )
380 else
382
383 if( m_vAlignTop->IsChecked() )
385 else if( m_vAlignCenter->IsChecked() )
387 else
389
391
394
396 stroke.SetWidth( m_borderWidth.GetValue() );
397
398 auto it = lineTypeNames.begin();
399 std::advance( it, m_borderStyleCombo->GetSelection() );
400
401 if( it == lineTypeNames.end() )
402 stroke.SetLineStyle( LINE_STYLE::SOLID );
403 else
404 stroke.SetLineStyle( it->first );
405
406 m_textBox->SetStroke( stroke );
407
410
411 if( pushCommit )
412 commit.Push( _( "Edit Text Box Properties" ) );
413
414 return true;
415}
416
417
419{
422
423 event.Skip();
424}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
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.
virtual void SetLocked(bool aLocked)
Definition: board_item.h:326
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:54
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:305
virtual bool IsLocked() const
Definition: board_item.cpp:82
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 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:221
EDA_ANGLE Normalize180()
Definition: eda_angle.h:260
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:137
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:131
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:179
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:723
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:88
@ 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