KiCad PCB EDA Suite
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 (C) 2022 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 <widgets/unit_binder.h>
29#include <board_commit.h>
31#include <board.h>
32#include <footprint.h>
33#include <string_utils.h>
34#include <pcb_textbox.h>
35#include <fp_textbox.h>
36#include <pcbnew.h>
37#include <pcb_edit_frame.h>
39#include <math/util.h> // for KiROUND
40#include <scintilla_tricks.h>
41#include "macros.h"
42
44 BOARD_ITEM* aItem ) :
46 m_frame( aParent ),
47 m_item( aItem ),
48 m_edaText( nullptr ),
49 m_fpTextBox( nullptr ),
50 m_pcbTextBox( 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_orientation( aParent, m_OrientLabel, m_OrientCtrl, nullptr ),
55 m_borderWidth( aParent, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits )
56{
57 m_MultiLineText->SetEOLMode( wxSTC_EOL_LF );
58
59 m_scintillaTricks = new SCINTILLA_TRICKS( m_MultiLineText, wxT( "{}" ), false,
60 [this]()
61 {
62 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
63 } );
64
65 // A hack which causes Scintilla to auto-size the text editor canvas
66 // See: https://github.com/jacobslusser/ScintillaNET/issues/216
67 m_MultiLineText->SetScrollWidth( 1 );
68 m_MultiLineText->SetScrollWidthTracking( true );
69
70 if( m_item->Type() == PCB_FP_TEXTBOX_T )
71 {
72 m_fpTextBox = static_cast<FP_TEXTBOX*>( m_item );
74
75 // Do not allow locking items in the footprint editor
76 m_cbLocked->Show( false );
77 }
78 else if( m_item->Type() == PCB_TEXTBOX_T )
79 {
80 m_pcbTextBox = static_cast<PCB_TEXTBOX*>( m_item );
82 }
83 else
84 {
86 }
87
89
91
96
98
105
107
110
112
113 // Configure the layers list selector. Note that footprints are built outside the current
114 // board and so we may need to show all layers if the text is on an unactivated layer.
117
121
124
125 // Set predefined rotations in combo dropdown, according to the locale floating point
126 // separator notation
127 double rot_list[] = { 0.0, 90.0, -90.0, 180.0 };
128
129 for( size_t ii = 0; ii < m_OrientCtrl->GetCount() && ii < 4; ++ii )
130 m_OrientCtrl->SetString( ii, wxString::Format( "%.1f", rot_list[ii] ) );
131
132 for( const std::pair<const PLOT_DASH_TYPE, lineTypeStruct>& typeEntry : lineTypeNames )
133 m_borderStyleCombo->Append( typeEntry.second.name, KiBitmap( typeEntry.second.bitmap ) );
134
136
138
139 // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set,
140 // so we have to listen to wxEVT_CHAR_HOOK events instead.
141 Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
142 nullptr, this );
143
145}
146
147
149{
150 Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
151 nullptr, this );
152
153 delete m_scintillaTricks;
154}
155
156
158{
159 DIALOG_TEXTBOX_PROPERTIES dlg( this, aText );
160 return dlg.ShowQuasiModal();
161}
162
163
165{
166 BOARD* board = m_frame->GetBoard();
167 wxString converted = board->ConvertKIIDsToCrossReferences(
169
170 m_MultiLineText->SetValue( converted );
171 m_MultiLineText->SetSelection( -1, -1 );
172 m_MultiLineText->EmptyUndoBuffer();
173
174 m_cbLocked->SetValue( m_item->IsLocked() );
175
177
179
183
186
187 switch ( m_edaText->GetHorizJustify() )
188 {
189 case GR_TEXT_H_ALIGN_LEFT: m_alignLeft->Check( true ); break;
190 case GR_TEXT_H_ALIGN_CENTER: m_alignCenter->Check( true ); break;
191 case GR_TEXT_H_ALIGN_RIGHT: m_alignRight->Check( true ); break;
192 }
193
195
196 EDA_ANGLE orientation = m_edaText->GetTextAngle();
198
199 STROKE_PARAMS stroke;
200
201 if( m_fpTextBox )
202 stroke = m_fpTextBox->GetStroke();
203 else if( m_pcbTextBox )
204 stroke = m_pcbTextBox->GetStroke();
205
206 m_borderCheckbox->SetValue( stroke.GetWidth() >= 0 );
207
208 if( stroke.GetWidth() >= 0 )
209 m_borderWidth.SetValue( stroke.GetWidth() );
210
211 PLOT_DASH_TYPE style = stroke.GetPlotStyle();
212
213 if( style == PLOT_DASH_TYPE::DEFAULT )
214 style = PLOT_DASH_TYPE::SOLID;
215
216 if( (int) style < (int) lineTypeNames.size() )
217 m_borderStyleCombo->SetSelection( (int) style );
218
219 m_borderWidth.Enable( stroke.GetWidth() >= 0 );
220 m_borderStyleLabel->Enable( stroke.GetWidth() >= 0 );
221 m_borderStyleCombo->Enable( stroke.GetWidth() >= 0 );
222
223 return DIALOG_TEXTBOX_PROPERTIES_BASE::TransferDataToWindow();
224}
225
226
227void DIALOG_TEXTBOX_PROPERTIES::onFontSelected( wxCommandEvent & aEvent )
228{
229 if( KIFONT::FONT::IsStroke( aEvent.GetString() ) )
230 {
231 m_thickness.Show( true );
232
233 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
234 int thickness = m_thickness.GetValue();
235
236 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
237 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
238 }
239 else
240 {
241 m_thickness.Show( false );
242 }
243}
244
245
246void DIALOG_TEXTBOX_PROPERTIES::onBoldToggle( wxCommandEvent & aEvent )
247{
248 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
249
250 if( aEvent.IsChecked() )
252 else
254
255 aEvent.Skip();
256}
257
258
259void DIALOG_TEXTBOX_PROPERTIES::onAlignButton( wxCommandEvent& aEvent )
260{
262 {
263 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
264 btn->Check( false );
265 }
266}
267
268
269void DIALOG_TEXTBOX_PROPERTIES::onThickness( wxCommandEvent& event )
270{
271 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
272 int thickness = m_thickness.GetValue();
273
274 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
275 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
276}
277
278
280{
281 bool border = m_borderCheckbox->GetValue();
282
283 if( border && m_borderWidth.GetValue() <= 0 )
284 {
287 }
288
289 m_borderWidth.Enable( border );
290 m_borderStyleLabel->Enable( border );
291 m_borderStyleCombo->Enable( border );
292}
293
294
296{
297 if( !DIALOG_TEXTBOX_PROPERTIES_BASE::TransferDataFromWindow() )
298 return false;
299
302 {
303 return false;
304 }
305
306 BOARD_COMMIT commit( m_frame );
307 commit.Modify( m_item );
308
309 // If no other command in progress, prepare undo command
310 // (for a command in progress, will be made later, at the completion of command)
311 bool pushCommit = ( m_item->GetEditFlags() == 0 );
312
313 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
314 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
315 if( !pushCommit )
317
318 BOARD* board = m_frame->GetBoard();
319 wxString txt = board->ConvertCrossReferencesToKIIDs( m_MultiLineText->GetValue() );
320
321#ifdef __WXMAC__
322 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
323 // Replace it now.
324 txt.Replace( "\r", "\n" );
325#elif defined( __WINDOWS__ )
326 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
327 // drawing routines so strip the \r char.
328 txt.Replace( "\r", "" );
329#endif
330
332
333 m_item->SetLocked( m_cbLocked->GetValue() );
334
336
338 {
340 m_italic->IsChecked() ) );
341 }
342
345
346 if( m_fpTextBox )
348
349 // Test for acceptable values for thickness and size and clamp if fails
351
352 if( m_edaText->GetTextThickness() > maxPenWidth )
353 {
354 DisplayError( this, _( "The text thickness is too large for the text size.\n"
355 "It will be clamped." ) );
356 m_edaText->SetTextThickness( maxPenWidth );
357 }
358
360
361 if( m_fpTextBox )
363 else if( m_pcbTextBox )
365
367
370
371 if( m_alignLeft->IsChecked() )
373 else if( m_alignCenter->IsChecked() )
375 else
377
379
380 STROKE_PARAMS stroke;
381
382 if( m_fpTextBox )
383 stroke = m_fpTextBox->GetStroke();
384 else if( m_pcbTextBox )
385 stroke = m_pcbTextBox->GetStroke();
386
387 if( m_borderCheckbox->GetValue() )
388 {
390 stroke.SetWidth( m_borderWidth.GetValue() );
391 }
392 else
393 {
394 stroke.SetWidth( -1 );
395 }
396
397 auto it = lineTypeNames.begin();
398 std::advance( it, m_borderStyleCombo->GetSelection() );
399
400 if( it == lineTypeNames.end() )
402 else
403 stroke.SetPlotStyle( it->first );
404
405 if( m_fpTextBox )
406 m_fpTextBox->SetStroke( stroke );
407 else if( m_pcbTextBox )
408 m_pcbTextBox->SetStroke( stroke );
409
410 if( pushCommit )
411 commit.Push( _( "Change text box properties" ) );
412
413 return true;
414}
415
416
418{
421
422 event.Skip();
423}
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).
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
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.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:58
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:180
virtual void SetLocked(bool aLocked)
Definition: board_item.h:254
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:214
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:43
virtual bool IsLocked() const
Definition: board_item.cpp:71
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
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:591
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:1112
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:682
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1166
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
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()
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 onAlignButton(wxCommandEvent &aEvent) override
void onThickness(wxCommandEvent &aEvent) override
void onBoldToggle(wxCommandEvent &aEvent) override
DIALOG_TEXTBOX_PROPERTIES(PCB_BASE_EDIT_FRAME *aParent, BOARD_ITEM *aItem)
void onMultiLineTCLostFocus(wxFocusEvent &event) override
void onFontSelected(wxCommandEvent &aEvent) override
void onBorderChecked(wxCommandEvent &event) 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:145
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:139
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual wxString GetClass() const =0
Return the class name.
bool IsItalic() const
Definition: eda_text.h:130
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:120
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
KIFONT::FONT * GetFont() const
Definition: eda_text.h:188
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:224
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:149
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:139
bool IsBold() const
Definition: eda_text.h:133
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:112
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:196
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
virtual void SetLocalCoord()
Set relative coordinates from draw coordinates.
Definition: fp_shape.cpp:52
void Rotate(const VECTOR2I &aOffset, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: fp_textbox.cpp:259
virtual bool IsStroke() const
Definition: font.h:112
int SetLayerSelection(int layer)
bool SetLayersHotkeys(bool value)
Common, abstract interface for edit frames.
int ShowTextBoxPropertiesDialog(BOARD_ITEM *aText)
BOARD * GetBoard() const
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void ShowNonActivatedLayers(bool aShow)
STROKE_PARAMS GetStroke() const override
Definition: pcb_shape.h:71
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:72
VECTOR2I GetPosition() const override
Definition: pcb_shape.h:65
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
int GetWidth() const
Definition: stroke_params.h:98
void SetWidth(int aWidth)
Definition: stroke_params.h:99
PLOT_DASH_TYPE GetPlotStyle() const
void SetPlotStyle(PLOT_DASH_TYPE aPlotStyle)
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, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:300
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:932
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:120
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
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
const std::map< PLOT_DASH_TYPE, struct lineTypeStruct > lineTypeNames
Definition: stroke_params.h:70
constexpr int delta
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
Definition: typeinfo.h:93
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91