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 (C) 2022-2023 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_alignLeft->SetBitmap( KiBitmapBundle( BITMAPS::text_align_left ) );
100 m_alignCenter->SetBitmap( KiBitmapBundle( BITMAPS::text_align_center ) );
102 m_alignRight->SetBitmap( KiBitmapBundle( BITMAPS::text_align_right ) );
103
105
107 m_mirrored->SetBitmap( KiBitmapBundle( BITMAPS::text_mirrored ) );
108
110
111 // Configure the layers list selector. Note that footprints are built outside the current
112 // board and so we may need to show all layers if the text is on an unactivated layer.
115
119
120 m_orientation.SetUnits( EDA_UNITS::DEGREES );
122
123 // Set predefined rotations in combo dropdown, according to the locale floating point
124 // separator notation
125 double rot_list[] = { 0.0, 90.0, -90.0, 180.0 };
126
127 for( size_t ii = 0; ii < m_OrientCtrl->GetCount() && ii < 4; ++ii )
128 m_OrientCtrl->SetString( ii, wxString::Format( "%.1f", rot_list[ii] ) );
129
130 for( const auto& [ lineStyle, lineStyleDesc ] : lineTypeNames )
131 m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmapBundle( lineStyleDesc.bitmap ) );
132
134
136
137 // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set,
138 // so we have to listen to wxEVT_CHAR_HOOK events instead.
139 Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
140 nullptr, this );
141
143}
144
145
147{
148 Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
149 nullptr, this );
150
151 delete m_scintillaTricks;
152}
153
154
156{
157 DIALOG_TEXTBOX_PROPERTIES dlg( this, aTextBox );
158
159 // QuasiModal required for Scintilla auto-complete
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_textBox->IsLocked() );
175
177
179
183
186
187 switch ( m_textBox->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;
193 }
194
196
197 EDA_ANGLE orientation = m_textBox->GetTextAngle();
199
202
204 m_borderWidth.SetValue( stroke.GetWidth() );
205
206 LINE_STYLE style = stroke.GetLineStyle();
207
208 if( style == LINE_STYLE::DEFAULT )
209 style = LINE_STYLE::SOLID;
210
211 if( (int) style < (int) lineTypeNames.size() )
212 m_borderStyleCombo->SetSelection( (int) style );
213
217
218 return DIALOG_TEXTBOX_PROPERTIES_BASE::TransferDataToWindow();
219}
220
221
222void DIALOG_TEXTBOX_PROPERTIES::onFontSelected( wxCommandEvent & aEvent )
223{
224 if( KIFONT::FONT::IsStroke( aEvent.GetString() ) )
225 {
226 m_thickness.Show( true );
227
228 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
229 int thickness = m_thickness.GetValue();
230
231 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
232 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
233 }
234 else
235 {
236 m_thickness.Show( false );
237 }
238}
239
240
241void DIALOG_TEXTBOX_PROPERTIES::onBoldToggle( wxCommandEvent & aEvent )
242{
243 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
244
245 if( aEvent.IsChecked() )
247 else
249
250 aEvent.Skip();
251}
252
253
254void DIALOG_TEXTBOX_PROPERTIES::onAlignButton( wxCommandEvent& aEvent )
255{
257 {
258 if( btn->IsChecked() && btn != aEvent.GetEventObject() )
259 btn->Check( false );
260 }
261}
262
263
264void DIALOG_TEXTBOX_PROPERTIES::onThickness( wxCommandEvent& event )
265{
266 int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() );
267 int thickness = m_thickness.GetValue();
268
269 m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) )
270 < abs( thickness - GetPenSizeForNormal( textSize ) ) );
271}
272
273
275{
276 bool border = m_borderCheckbox->GetValue();
277
278 if( border && m_borderWidth.GetValue() <= 0 )
279 {
282 }
283
284 m_borderWidth.Enable( border );
285 m_borderStyleLabel->Enable( border );
286 m_borderStyleCombo->Enable( border );
287}
288
289
291{
292 if( !DIALOG_TEXTBOX_PROPERTIES_BASE::TransferDataFromWindow() )
293 return false;
294
296 int maxSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
297
298 if( !m_textWidth.Validate( minSize, maxSize ) || !m_textHeight.Validate( minSize, maxSize ) )
299 return false;
300
301 BOARD_COMMIT commit( m_frame );
302 commit.Modify( m_textBox );
303
304 // If no other command in progress, prepare undo command
305 // (for a command in progress, will be made later, at the completion of command)
306 bool pushCommit = ( m_textBox->GetEditFlags() == 0 );
307
308 // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
309 // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
310 if( !pushCommit )
312
313 BOARD* board = m_frame->GetBoard();
314 wxString txt = board->ConvertCrossReferencesToKIIDs( m_MultiLineText->GetValue() );
315
316#ifdef __WXMAC__
317 // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
318 // Replace it now.
319 txt.Replace( "\r", "\n" );
320#elif defined( __WINDOWS__ )
321 // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
322 // drawing routines so strip the \r char.
323 txt.Replace( "\r", "" );
324#endif
325
327 m_textBox->SetLocked( m_cbLocked->GetValue() );
329
331 {
333 m_italic->IsChecked() ) );
334 }
335
338
339 // Test for acceptable values for thickness and size and clamp if fails
341
342 if( m_textBox->GetTextThickness() > maxPenWidth )
343 {
344 DisplayError( this, _( "The text thickness is too large for the text size.\n"
345 "It will be clamped." ) );
346 m_textBox->SetTextThickness( maxPenWidth );
347 }
348
352
353 if( m_alignLeft->IsChecked() )
355 else if( m_alignCenter->IsChecked() )
357 else
359
361
364
366 stroke.SetWidth( m_borderWidth.GetValue() );
367
368 auto it = lineTypeNames.begin();
369 std::advance( it, m_borderStyleCombo->GetSelection() );
370
371 if( it == lineTypeNames.end() )
372 stroke.SetLineStyle( LINE_STYLE::DEFAULT );
373 else
374 stroke.SetLineStyle( it->first );
375
376 m_textBox->SetStroke( stroke );
377
380
381 if( pushCommit )
382 commit.Push( _( "Edit Text Box Properties" ) );
383
384 return true;
385}
386
387
389{
392
393 event.Skip();
394}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
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
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.
virtual void SetLocked(bool aLocked)
Definition: board_item.h:300
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:248
virtual bool IsLocked() const
Definition: board_item.cpp:74
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:282
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:706
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:1436
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:797
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1490
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:98
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, PCB_TEXTBOX *aTextBox)
void onMultiLineTCLostFocus(wxFocusEvent &event) override
void onFontSelected(wxCommandEvent &aEvent) override
void onBorderChecked(wxCommandEvent &event) override
EDA_ANGLE Normalize()
Definition: eda_angle.h:255
EDA_ANGLE Normalize180()
Definition: eda_angle.h:294
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:132
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:126
bool IsItalic() const
Definition: eda_text.h:144
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:374
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:211
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:252
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:164
void SetBoldFlag(bool aBold)
Definition: eda_text.cpp:237
virtual void ClearBoundingBoxCache()
Definition: eda_text.cpp:505
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:197
virtual void ClearRenderCache()
Definition: eda_text.cpp:499
bool IsMirrored() const
Definition: eda_text.h:154
bool IsBold() const
Definition: eda_text.h:148
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:183
int GetTextThickness() const
Definition: eda_text.h:126
void SetItalic(bool aItalic)
Definition: eda_text.cpp:213
void SetFont(KIFONT::FONT *aFont)
Definition: eda_text.cpp:358
VECTOR2I GetTextSize() const
Definition: eda_text.h:222
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:268
bool HaveFontSelection() const
Definition: font_choice.cpp:94
void SetFontSelection(KIFONT::FONT *aFont)
Definition: font_choice.cpp:73
KIFONT::FONT * GetFontSelection(bool aBold, bool aItalic) const
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:314
STROKE_PARAMS GetStroke() const override
Definition: pcb_shape.h:85
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:86
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_shape.h:70
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:81
int GetWidth() const
Definition: stroke_params.h:91
void SetLineStyle(LINE_STYLE aLineStyle)
Definition: stroke_params.h:95
void SetWidth(int aWidth)
Definition: stroke_params.h:92
LINE_STYLE GetLineStyle() const
Definition: stroke_params.h:94
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:280
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:45
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition: eda_text.h:46
int GetPenSizeForBold(int aTextSize)
Definition: gr_text.cpp:40
int GetPenSizeForNormal(int aTextSize)
Definition: gr_text.cpp:64
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:87
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:1022
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
LINE_STYLE
Dashed line types.
Definition: stroke_params.h:48
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
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588