KiCad PCB EDA Suite
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-2021 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 
25 #include <dialog_text_properties.h>
26 #include <confirm.h>
27 #include <widgets/unit_binder.h>
28 #include <board_commit.h>
29 #include <board.h>
30 #include <footprint.h>
31 #include <string_utils.h>
32 #include <pcb_text.h>
33 #include <fp_text.h>
34 #include <pcbnew.h>
35 #include <pcb_edit_frame.h>
36 #include <pcb_layer_box_selector.h>
37 #include <wx/valnum.h>
38 #include <math/util.h> // for KiROUND
39 #include <scintilla_tricks.h>
40 
41 
43  DIALOG_TEXT_PROPERTIES_BASE( aParent ),
44  m_Parent( aParent ),
45  m_item( aItem ),
46  m_edaText( nullptr ),
47  m_fpText( nullptr ),
48  m_pcbText( nullptr ),
49  m_textWidth( aParent, m_SizeXLabel, m_SizeXCtrl, m_SizeXUnits ),
50  m_textHeight( aParent, m_SizeYLabel, m_SizeYCtrl, m_SizeYUnits ),
51  m_thickness( aParent, m_ThicknessLabel, m_ThicknessCtrl, m_ThicknessUnits ),
52  m_posX( aParent, m_PositionXLabel, m_PositionXCtrl, m_PositionXUnits ),
53  m_posY( aParent, m_PositionYLabel, m_PositionYCtrl, m_PositionYUnits ),
54  m_orientation( aParent, m_OrientLabel, m_OrientCtrl, nullptr )
55 {
56  wxString title;
57 
58  // Configure display origin transforms
61 
62  m_MultiLineText->SetEOLMode( wxSTC_EOL_LF );
63 
64  m_scintillaTricks = new SCINTILLA_TRICKS( m_MultiLineText, wxT( "{}" ), false,
65  [this]()
66  {
67  wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
68  } );
69 
70  // A hack which causes Scintilla to auto-size the text editor canvas
71  // See: https://github.com/jacobslusser/ScintillaNET/issues/216
72  m_MultiLineText->SetScrollWidth( 1 );
73  m_MultiLineText->SetScrollWidthTracking( true );
74 
75  if( m_item->Type() == PCB_FP_TEXT_T )
76  {
77  title = _( "Footprint Text Properties" );
78 
79  m_fpText = (FP_TEXT*) m_item;
80  m_edaText = static_cast<EDA_TEXT*>( m_fpText );
81 
82  switch( m_fpText->GetType() )
83  {
84  case FP_TEXT::TEXT_is_REFERENCE: m_TextLabel->SetLabel( _( "Reference:" ) ); break;
85  case FP_TEXT::TEXT_is_VALUE: m_TextLabel->SetLabel( _( "Value:" ) ); break;
86  case FP_TEXT::TEXT_is_DIVERS: m_TextLabel->SetLabel( _( "Text:" ) ); break;
87  }
88 
90  m_MultiLineSizer->Show( false );
91  }
92  else
93  {
94  title = _( "Text Properties" );
95 
96  m_pcbText = (PCB_TEXT*) aItem;
97  m_edaText = static_cast<EDA_TEXT*>( m_pcbText );
98 
100  m_SingleLineSizer->Show( false );
101 
102  // This option makes sense only for footprint texts; texts on board are always visible.
103  m_Visible->SetValue( true );
104  m_Visible->Enable( false );
105 
106  m_KeepUpright->Show( false );
107  m_statusLine->Show( false );
108  }
109 
110  SetTitle( title );
111  m_hash_key = title;
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 
122  m_OrientValue = 0.0;
125 
126  // Set predefined rotations in combo dropdown, according to the locale floating point
127  // separator notation
128  double rot_list[] = { 0.0, 90.0, -90.0, 180.0 };
129 
130  for( size_t ii = 0; ii < m_OrientCtrl->GetCount() && ii < 4; ++ii )
131  m_OrientCtrl->SetString( ii, wxString::Format( "%.1f", rot_list[ii] ) );
132 
133  // Set font sizes
134  m_statusLine->SetFont( KIUI::GetInfoFont( this ) );
135 
136  m_sdbSizerOK->SetDefault();
137 
138  // We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
139  // implementation on MSW
140  m_tabOrder = {
141  m_LayerLabel,
143  m_SizeXCtrl,
144  m_SizeYCtrl,
148  m_Visible,
149  m_Italic,
151  m_OrientCtrl,
152  m_Mirrored,
154  m_sdbSizerOK,
156  };
157 
158  // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set,
159  // so we have to listen to wxEVT_CHAR_HOOK events instead.
160  Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ),
161  nullptr, this );
162 
164 }
165 
166 
168 {
169  Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ),
170  nullptr, this );
171 
172  delete m_scintillaTricks;
173 }
174 
175 
177 {
178  DIALOG_TEXT_PROPERTIES dlg( this, aText );
179  dlg.ShowQuasiModal();
180 }
181 
182 
183 void DIALOG_TEXT_PROPERTIES::OnSetFocusText( wxFocusEvent& event )
184 {
185 #ifdef __WXGTK__
186  // Force an update of the text control before setting the text selection
187  // This is needed because GTK seems to ignore the selection on first update
188  //
189  // Note that we can't do this on OSX as it tends to provoke Apple's
190  // "[NSAlert runModal] may not be invoked inside of transaction begin/commit pair"
191  // bug. See: https://bugs.launchpad.net/kicad/+bug/1837225
193  m_SingleLineText->Update();
194 #endif
195 
197  KIUI::SelectReferenceNumber( static_cast<wxTextEntry*>( m_SingleLineText ) );
198  else
199  m_SingleLineText->SetSelection( -1, -1 );
200 
201  event.Skip();
202 }
203 
204 
206 {
207  if( m_SingleLineText->IsShown() )
208  {
209  m_SingleLineText->SetValue( m_edaText->GetText() );
210 
212  KIUI::SelectReferenceNumber( static_cast<wxTextEntry*>( m_SingleLineText ) );
213  else
214  m_SingleLineText->SetSelection( -1, -1 );
215  }
216  else if( m_MultiLineText->IsShown() )
217  {
218  BOARD* board = m_Parent->GetBoard();
219  wxString converted = board->ConvertKIIDsToCrossReferences( m_edaText->GetText() );
220 
221  m_MultiLineText->SetValue( converted );
222  m_MultiLineText->SetSelection( -1, -1 );
223  }
224 
225  if( m_item->Type() == PCB_FP_TEXT_T && m_fpText )
226  {
227  FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( m_fpText->GetParent() );
228  wxString msg;
229 
230  if( footprint )
231  {
232  msg.Printf( _( "Footprint %s (%s), %s, rotated %.1f deg"),
233  footprint->GetReference(),
234  footprint->GetValue(),
235  footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
236  footprint->GetOrientation() / 10.0 );
237  }
238 
239  m_statusLine->SetLabel( msg );
240  }
241  else
242  {
243  m_statusLine->Show( false );
244  }
245 
246  m_cbLocked->SetValue( m_item->IsLocked() );
247 
249 
255 
256  m_Visible->SetValue( m_edaText->IsVisible() );
257  m_Italic->SetValue( m_edaText->IsItalic() );
259  m_JustifyChoice->SetSelection( (int) hJustify + 1 );
262  m_Mirrored->SetValue( m_edaText->IsMirrored() );
263 
264  if( m_fpText )
265  m_KeepUpright->SetValue( m_fpText->IsKeepUpright() );
266 
267  return DIALOG_TEXT_PROPERTIES_BASE::TransferDataToWindow();
268 }
269 
270 
272 {
273  if( !DIALOG_TEXT_PROPERTIES_BASE::TransferDataFromWindow() )
274  return false;
275 
278  {
279  return false;
280  }
281 
282  BOARD_COMMIT commit( m_Parent );
283  commit.Modify( m_item );
284 
285  // If no other command in progress, prepare undo command
286  // (for a command in progress, will be made later, at the completion of command)
287  bool pushCommit = ( m_item->GetEditFlags() == 0 );
288 
289  // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to
290  // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc....
291  if( !pushCommit )
292  m_item->SetFlags( IN_EDIT );
293 
294  // Set the new text content
295  if( m_SingleLineText->IsShown() )
296  {
297  if( !m_SingleLineText->GetValue().IsEmpty() )
298  m_edaText->SetText( m_SingleLineText->GetValue() );
299  }
300  else if( m_MultiLineText->IsShown() )
301  {
302  if( !m_MultiLineText->GetValue().IsEmpty() )
303  {
304  BOARD* board = m_Parent->GetBoard();
305  wxString txt = board->ConvertCrossReferencesToKIIDs( m_MultiLineText->GetValue() );
306 
307 #ifdef __WXMAC__
308  // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting.
309  // Replace it now.
310  txt.Replace( "\r", "\n" );
311 #elif defined( __WINDOWS__ )
312  // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in
313  // drawing routines so strip the \r char.
314  txt.Replace( "\r", "" );
315 #endif
317  }
318  }
319 
320  m_item->SetLocked( m_cbLocked->GetValue() );
321 
323 
326  m_edaText->SetTextPos( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
327 
328  if( m_fpText )
330 
331  // Test for acceptable values for thickness and size and clamp if fails
333 
334  if( m_edaText->GetTextThickness() > maxPenWidth )
335  {
336  DisplayError( this, _( "The text thickness is too large for the text size.\n"
337  "It will be clamped." ) );
338  m_edaText->SetTextThickness( maxPenWidth );
339  }
340 
341  m_edaText->SetVisible( m_Visible->GetValue() );
342  m_edaText->SetItalic( m_Italic->GetValue() );
345  m_edaText->SetMirrored( m_Mirrored->GetValue() );
346 
347  if( m_fpText )
348  m_fpText->SetKeepUpright( m_KeepUpright->GetValue() );
349 
350  switch( m_JustifyChoice->GetSelection() )
351  {
355  default: break;
356  }
357 
358  if( pushCommit )
359  commit.Push( _( "Change text properties" ) );
360 
361  return true;
362 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:188
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:271
void SelectReferenceNumber(wxTextEntry *aTextEntry)
Select the number (or "?") in a reference for ease of editing.
Definition: ui_common.cpp:182
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
EDA_TEXT_HJUSTIFY_T
Definition: eda_text.h:61
bool IsMirrored() const
Definition: eda_text.h:189
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
DIALOG_TEXT_PROPERTIES(PCB_BASE_EDIT_FRAME *aParent, BOARD_ITEM *aItem)
Class DIALOG_TEXT_PROPERTIES_BASE.
const wxString & GetValue() const
Definition: footprint.h:452
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:192
This file is part of the common library.
bool IsKeepUpright() const
Definition: fp_text.h:110
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
std::string m_hash_key
Definition: dialog_shim.h:199
Add cut/copy/paste, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
std::vector< wxWindow * > m_tabOrder
Definition: dialog_shim.h:218
void SetItalic(bool isItalic)
Definition: eda_text.h:179
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:246
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:141
double GetOrientation() const
Definition: footprint.h:190
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:153
double GetTextAngle() const
Definition: eda_text.h:174
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:237
virtual void SetLocked(bool aLocked)
Modify the 'lock' status for of the item.
Definition: board_item.h:252
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
int GetTextThickness() const
Definition: eda_text.h:160
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:492
virtual bool IsLocked() const
Definition: board_item.cpp:78
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 ShowTextPropertiesDialog(BOARD_ITEM *aText)
bool IsItalic() const
Definition: eda_text.h:180
LAYER_NUM GetLayerSelection() const
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 SetVisible(bool aVisible)
Definition: eda_text.h:185
int Clamp_Text_PenSize(int aPenSize, int aSize, bool aBold)
Don't allow text to become cluttered up in its own fatness.
Definition: gr_text.cpp:67
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:198
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
TEXT_TYPE GetType() const
Definition: fp_text.h:141
virtual bool IsVisible() const
Definition: eda_text.h:186
int ShowQuasiModal()
void ShowNonActivatedLayers(bool aShow)
const wxSize & GetTextSize() const
Definition: eda_text.h:238
const wxString & GetReference() const
Definition: footprint.h:430
#define _(s)
int SetLayerSelection(LAYER_NUM layer)
#define TEXTS_MAX_SIZE
Maximum text size in internal units (10 inches)
Definition: pcbnew.h:32
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:158
bool SetLayersHotkeys(bool value)
PCB_BASE_EDIT_FRAME * m_Parent
#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
bool IsFlipped() const
Definition: footprint.h:270
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)
void SetKeepUpright(bool aKeepUpright)
Definition: fp_text.h:115
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...
Definition: unit_binder.cpp:92
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.
PCB_LAYER_BOX_SELECTOR * m_LayerSelectionCtrl
Common, abstract interface for edit frames.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
virtual void SetValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:983
void SetLocalCoord()
Definition: fp_text.cpp:209
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
virtual long long int GetValue()
Return the current value in Internal Units.
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1037
const wxPoint & GetTextPos() const
Definition: eda_text.h:247
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:159
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...
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:177
#define IN_EDIT
Item currently edited.
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:167
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
BOARD * GetBoard() const
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
virtual double GetDoubleValue()
Return the current value in Internal Units.
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:166
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:171
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:905
SCINTILLA_TRICKS * m_scintillaTricks
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113