KiCad PCB EDA Suite
pcbnew/dialogs/dialog_text_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 (C) 2004-2018 Jean-Pierre Charras jp.charras at wanadoo.fr
5 * Copyright (C) 2010-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26#include <widgets/font_choice.h>
28#include <confirm.h>
29#include <widgets/unit_binder.h>
30#include <board_commit.h>
31#include <board.h>
32#include <footprint.h>
33#include <string_utils.h>
34#include <pcb_text.h>
35#include <fp_text.h>
36#include <pcbnew.h>
37#include <pcb_edit_frame.h>
39#include <wx/valnum.h>
40#include <math/util.h> // for KiROUND
41#include <scintilla_tricks.h>
42
43
46 m_frame( aParent ),
47 m_item( aItem ),
48 m_edaText( nullptr ),
49 m_fpText( nullptr ),
50 m_pcbText( nullptr ),
51 m_textWidth( aParent, m_SizeXLabel, m_SizeXCtrl, m_SizeXUnits ),
52 m_textHeight( aParent, m_SizeYLabel, m_SizeYCtrl, m_SizeYUnits ),
53 m_thickness( aParent, m_ThicknessLabel, m_ThicknessCtrl, m_ThicknessUnits ),
54 m_posX( aParent, m_PositionXLabel, m_PositionXCtrl, m_PositionXUnits ),
55 m_posY( aParent, m_PositionYLabel, m_PositionYCtrl, m_PositionYUnits ),
56 m_orientation( aParent, m_OrientLabel, m_OrientCtrl, nullptr )
57{
58 wxString title;
59
60 // Configure display origin transforms
63
64 m_MultiLineText->SetEOLMode( wxSTC_EOL_LF );
65
66 m_scintillaTricks = new SCINTILLA_TRICKS( m_MultiLineText, wxT( "{}" ), false,
67 [this]()
68 {
69 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
70 } );
71
72 // A hack which causes Scintilla to auto-size the text editor canvas
73 // See: https://github.com/jacobslusser/ScintillaNET/issues/216
74 m_MultiLineText->SetScrollWidth( 1 );
75 m_MultiLineText->SetScrollWidthTracking( true );
76
77 if( m_item->Type() == PCB_FP_TEXT_T )
78 {
80 m_edaText = static_cast<EDA_TEXT*>( m_fpText );
81
82 switch( m_fpText->GetType() )
83 {
84 case FP_TEXT::TEXT_is_REFERENCE: title = _( "Footprint Reference Properties" ); break;
85 case FP_TEXT::TEXT_is_VALUE: title = _( "Footprint Value Properties" ); break;
86 case FP_TEXT::TEXT_is_DIVERS: title = _( "Footprint Text Properties" ); break;
87 }
88
89 switch( m_fpText->GetType() )
90 {
91 case FP_TEXT::TEXT_is_REFERENCE: m_TextLabel->SetLabel( _( "Reference:" ) ); break;
92 case FP_TEXT::TEXT_is_VALUE: m_TextLabel->SetLabel( _( "Value:" ) ); break;
93 case FP_TEXT::TEXT_is_DIVERS: m_TextLabel->SetLabel( _( "Text:" ) ); break;
94 }
95
97 m_MultiLineSizer->Show( false );
98
99 // Do not allow locking items in the footprint editor
100 m_cbLocked->Show( false );
101 }
102 else
103 {
104 title = _( "Text Properties" );
105
106 m_pcbText = (PCB_TEXT*) aItem;
107 m_edaText = static_cast<EDA_TEXT*>( m_pcbText );
108
110 m_SingleLineSizer->Show( false );
111
112 // This option makes sense only for footprint texts; texts on board are always visible.
113 m_Visible->SetValue( true );
114 m_Visible->Show( false );
115
116 m_KeepUpright->Show( false );
117 m_statusLine->Show( false );
118 }
119
121
126
128
135
137
140
142
143 SetTitle( title );
144 m_hash_key = title;
145
146 // Configure the layers list selector. Note that footprints are built outside the current
147 // board and so we may need to show all layers if the text is on an unactivated layer.
148 if( !m_frame->GetBoard()->IsLayerEnabled( m_item->GetLayer() ) )
150
154
157
158 // Set predefined rotations in combo dropdown, according to the locale floating point
159 // separator notation
160 double rot_list[] = { 0.0, 90.0, -90.0, 180.0 };
161
162 for( size_t ii = 0; ii < m_OrientCtrl->GetCount() && ii < 4; ++ii )
163 m_OrientCtrl->SetString( ii, wxString::Format( wxT( "%.1f" ), rot_list[ii] ) );
164
165 // Set font sizes
166 m_statusLine->SetFont( KIUI::GetInfoFont( this ) );
167
169
170 // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set,
171 // so we have to listen to wxEVT_CHAR_HOOK events instead.
172 Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ),
173 nullptr, this );
174
176}
177
178
180{
181 Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ),
182 nullptr, this );
183
184 delete m_scintillaTricks;
185}
186
187
189{
190 DIALOG_TEXT_PROPERTIES dlg( this, aText );
191 dlg.ShowQuasiModal();
192}
193
194
195void DIALOG_TEXT_PROPERTIES::OnSetFocusText( wxFocusEvent& event )
196{
197#ifdef __WXGTK__
198 // Force an update of the text control before setting the text selection
199 // This is needed because GTK seems to ignore the selection on first update
200 //
201 // Note that we can't do this on OSX as it tends to provoke Apple's
202 // "[NSAlert runModal] may not be invoked inside of transaction begin/commit pair"
203 // bug. See: https://bugs.launchpad.net/kicad/+bug/1837225
205 m_SingleLineText->Update();
206#endif
207
209 KIUI::SelectReferenceNumber( static_cast<wxTextEntry*>( m_SingleLineText ) );
210 else
211 m_SingleLineText->SetSelection( -1, -1 );
212
213 event.Skip();
214}
215
216
218{
219 if( m_SingleLineText->IsShown() )
220 {
221 m_SingleLineText->SetValue( m_edaText->GetText() );
222
224 KIUI::SelectReferenceNumber( static_cast<wxTextEntry*>( m_SingleLineText ) );
225 else
226 m_SingleLineText->SetSelection( -1, -1 );
227 }
228 else if( m_MultiLineText->IsShown() )
229 {
230 BOARD* board = m_frame->GetBoard();
231 wxString converted = board->ConvertKIIDsToCrossReferences(
233
234 m_MultiLineText->SetValue( converted );
235 m_MultiLineText->SetSelection( -1, -1 );
236 }
237
238 if( m_item->Type() == PCB_FP_TEXT_T && m_fpText )
239 {
240 FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( m_fpText->GetParent() );
241 wxString msg;
242
243 if( footprint )
244 {
245 msg.Printf( _( "Footprint %s (%s), %s, rotated %.1f deg"),
246 footprint->GetReference(),
247 footprint->GetValue(),
248 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
249 footprint->GetOrientation().AsDegrees() );
250 }
251
252 m_statusLine->SetLabel( msg );
253 }
254 else
255 {
256 m_statusLine->Show( false );
257 }
258
259 m_cbLocked->SetValue( m_item->IsLocked() );
260
262 m_cbKnockout->SetValue( m_item->IsKnockout() );
263
265
271
272 m_Visible->SetValue( m_edaText->IsVisible() );
273
274 if( m_fpText )
275 m_KeepUpright->SetValue( m_fpText->IsKeepUpright() );
276
279
280 switch ( m_edaText->GetHorizJustify() )
281 {
282 case GR_TEXT_H_ALIGN_LEFT: m_alignLeft->Check( true ); break;
283 case GR_TEXT_H_ALIGN_CENTER: m_alignCenter->Check( true ); break;
284 case GR_TEXT_H_ALIGN_RIGHT: m_alignRight->Check( true ); break;
285 }
286
288
289 EDA_ANGLE orientation = m_edaText->GetTextAngle();
291
292 return DIALOG_TEXT_PROPERTIES_BASE::TransferDataToWindow();
293}
294
295
296void DIALOG_TEXT_PROPERTIES::onFontSelected( wxCommandEvent & aEvent )
297{
298 if( KIFONT::FONT::IsStroke( aEvent.GetString() ) )
299 {
300 m_thickness.Show( true );
301
302 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
303 int thickness = m_thickness.GetValue();
304
305 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
306 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
307 }
308 else
309 {
310 m_thickness.Show( false );
311 }
312}
313
314
315void DIALOG_TEXT_PROPERTIES::onBoldToggle( wxCommandEvent & aEvent )
316{
317 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
318
319 if( aEvent.IsChecked() )
321 else
323
324 aEvent.Skip();
325}
326
327
328void DIALOG_TEXT_PROPERTIES::onAlignButton( wxCommandEvent& aEvent )
329{
331 {
332 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
333 btn->Check( false );
334 }
335}
336
337
338void DIALOG_TEXT_PROPERTIES::onThickness( wxCommandEvent& event )
339{
340 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
341 int thickness = m_thickness.GetValue();
342
343 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
344 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
345}
346
347
349{
350 if( !DIALOG_TEXT_PROPERTIES_BASE::TransferDataFromWindow() )
351 return false;
352
355 {
356 return false;
357 }
358
359 BOARD_COMMIT commit( m_frame );
360 commit.Modify( m_item );
361
362 // If no other command in progress, prepare undo command
363 // (for a command in progress, will be made later, at the completion of command)
364 bool pushCommit = ( m_item->GetEditFlags() == 0 );
365
366 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
367 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
368 if( !pushCommit )
370
371 // Set the new text content
372 if( m_SingleLineText->IsShown() )
373 {
374 if( !m_SingleLineText->GetValue().IsEmpty() )
375 m_edaText->SetText( m_SingleLineText->GetValue() );
376 }
377 else if( m_MultiLineText->IsShown() )
378 {
379 if( !m_MultiLineText->GetValue().IsEmpty() )
380 {
381 BOARD* board = m_frame->GetBoard();
382 wxString txt = board->ConvertCrossReferencesToKIIDs( m_MultiLineText->GetValue() );
383
384#ifdef __WXMAC__
385 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
386 // Replace it now.
387 txt.Replace( wxT( "\r" ), wxT( "\n" ) );
388#elif defined( __WINDOWS__ )
389 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
390 // drawing routines so strip the \r char.
391 txt.Replace( wxT( "\r" ), wxT( "" ) );
392#endif
394 }
395 }
396
397 m_item->SetLocked( m_cbLocked->GetValue() );
398
400 m_item->SetIsKnockout( m_cbKnockout->GetValue() );
401
403 {
405 m_italic->IsChecked() ) );
406 }
407
411
412 if( m_fpText )
414
415 // Test for acceptable values for thickness and size and clamp if fails
417
418 if( m_edaText->GetTextThickness() > maxPenWidth )
419 {
420 DisplayError( this, _( "The text thickness is too large for the text size.\n"
421 "It will be clamped." ) );
422 m_edaText->SetTextThickness( maxPenWidth );
423 }
424
426
427 m_edaText->SetVisible( m_Visible->GetValue() );
428
429 if( m_fpText )
430 m_fpText->SetKeepUpright( m_KeepUpright->GetValue() );
431
434
435 if( m_alignLeft->IsChecked() )
437 else if( m_alignCenter->IsChecked() )
439 else
441
443
444 if( pushCommit )
445 commit.Push( _( "Change text properties" ) );
446
447 return true;
448}
449
450
451void DIALOG_TEXT_PROPERTIES::onMultiLineTCLostFocus( wxFocusEvent& event )
452{
455
456 event.Skip();
457}
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:105
@ text_align_right
@ text_align_left
@ text_mirrored
@ text_align_center
A bitmap button widget that behaves like an AUI toolbar item's button when it is drawn.
Definition: bitmap_button.h:41
void SetIsRadioButton()
bool IsChecked() const
void SetBitmap(const wxBitmap &aBmp)
Set the bitmap shown when the button is enabled.
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).
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:50
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:167
virtual void SetLocked(bool aLocked)
Definition: board_item.h:241
virtual bool IsKnockout() const
Definition: board_item.h:237
virtual void SetIsKnockout(bool aKnockout)
Definition: board_item.h:238
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:201
virtual bool IsLocked() const
Definition: board_item.cpp:65
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:150
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:1047
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1101
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowQuasiModal()
std::string m_hash_key
Definition: dialog_shim.h:203
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)
virtual void OnSetFocusText(wxFocusEvent &event) override
Used to select the variant part of some text fields (for instance, the question mark or number in a r...
DIALOG_TEXT_PROPERTIES(SCH_EDIT_FRAME *parent, SCH_ITEM *aTextItem)
void onMultiLineTCLostFocus(wxFocusEvent &event) override
void onFontSelected(wxCommandEvent &aEvent) override
void onBoldToggle(wxCommandEvent &aEvent) override
void onThickness(wxCommandEvent &aEvent) override
void onAlignButton(wxCommandEvent &aEvent) override
EDA_ANGLE Normalize()
Definition: eda_angle.h:249
EDA_ANGLE Normalize180()
Definition: eda_angle.h:271
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:147
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:142
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:198
bool IsItalic() const
Definition: eda_text.h:120
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:117
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
bool IsKeepUpright() const
Definition: eda_text.h:145
virtual bool IsVisible() const
Definition: eda_text.h:126
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:371
KIFONT::FONT * GetFont() const
Definition: eda_text.h:178
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:224
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:139
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:217
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:185
void SetBold(bool aBold)
Definition: eda_text.cpp:209
bool IsMirrored() const
Definition: eda_text.h:129
bool IsBold() const
Definition: eda_text.h:123
void SetKeepUpright(bool aKeepUpright)
Definition: eda_text.cpp:256
void SetTextSize(const VECTOR2I &aNewSize)
Definition: eda_text.cpp:347
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:163
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:193
int GetTextThickness() const
Definition: eda_text.h:109
void SetItalic(bool aItalic)
Definition: eda_text.cpp:201
void SetFont(KIFONT::FONT *aFont)
Definition: eda_text.cpp:331
VECTOR2I GetTextSize() const
Definition: eda_text.h:186
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:240
bool HaveFontSelection() const
Definition: font_choice.cpp:88
void SetFontSelection(KIFONT::FONT *aFont)
Definition: font_choice.cpp:67
KIFONT::FONT * GetFontSelection(bool aBold, bool aItalic) const
bool IsFlipped() const
Definition: footprint.h:319
const wxString & GetValue() const
Definition: footprint.h:541
const wxString & GetReference() const
Definition: footprint.h:519
void SetLocalCoord()
Definition: fp_text.cpp:217
@ TEXT_is_REFERENCE
Definition: fp_text.h:49
@ TEXT_is_DIVERS
Definition: fp_text.h:51
@ TEXT_is_VALUE
Definition: fp_text.h:50
TEXT_TYPE GetType() const
Definition: fp_text.h:120
virtual bool IsStroke() const
Definition: font.h:112
int SetLayerSelection(int layer)
bool SetLayersHotkeys(bool value)
Common, abstract interface for edit frames.
void ShowTextPropertiesDialog(BOARD_ITEM *aText)
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void ShowNonActivatedLayers(bool aShow)
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
virtual long long int GetValue()
Return the current value in Internal Units.
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()
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 SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:186
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:280
This file is part of the common library.
#define _(s)
#define IN_EDIT
Item currently edited.
int GetPenSizeForBold(int aTextSize)
Definition: gr_text.cpp:40
int GetPenSizeForNormal(int aTextSize)
Definition: gr_text.cpp:52
int Clamp_Text_PenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
Definition: gr_text.cpp:75
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:926
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:144
void SelectReferenceNumber(wxTextEntry *aTextEntry)
Select the number (or "?") in a reference for ease of editing.
Definition: ui_common.cpp:218
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
#define TEXTS_MAX_SIZE
Maximum text size in internal units (10 inches)
Definition: pcbnew.h:32
#define TEXTS_MIN_SIZE
Minimum text size in internal units (1 mil)
Definition: pcbnew.h:31
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
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
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92