KiCad PCB EDA Suite
dialog_text_and_label_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) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <sch_edit_frame.h>
27 #include <base_units.h>
28 #include <sch_validators.h>
29 #include <tool/tool_manager.h>
30 #include <general.h>
31 #include <gr_text.h>
32 #include <confirm.h>
33 #include <sch_symbol.h>
34 #include <sch_reference_list.h>
35 #include <schematic.h>
38 #include <string_utils.h>
39 #include <tool/actions.h>
40 #include <scintilla_tricks.h>
41 
42 class SCH_EDIT_FRAME;
43 class SCH_TEXT;
44 
45 
47  SCH_TEXT* aTextItem ) :
49  m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits, false ),
50  m_netNameValidator( true ),
51  m_scintillaTricks( nullptr ),
52  m_helpWindow( nullptr )
53 {
54  m_Parent = aParent;
55  m_CurrentText = aTextItem;
56 
57  m_valueMultiLine->SetEOLMode( wxSTC_EOL_LF );
58 
59  m_scintillaTricks = new SCINTILLA_TRICKS( m_valueMultiLine, wxT( "{}" ), false,
60  [this]()
61  {
62  wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
63  } );
64 
66  {
68  m_activeTextEntry = nullptr;
69 
70  m_labelSingleLine->Show( false );
71  m_valueSingleLine->Show( false );
72  m_labelCombo->Show( false );
73  m_valueCombo->Show( false );
74 
75  m_textEntrySizer->AddGrowableRow( 0 );
76  }
78  {
81 
82  m_labelSingleLine->Show( false ); m_valueSingleLine->Show( false );
83  m_labelMultiLine->Show( false ); m_valueMultiLine->Show( false );
84 
85  m_valueCombo->SetValidator( m_netNameValidator );
86  }
87  else
88  {
91 
92  m_labelCombo->Show( false );
93  m_valueCombo->Show( false );
94  m_labelMultiLine->Show( false );
95  m_valueMultiLine->Show( false );
96 
97  if( m_CurrentText->Type() != SCH_TEXT_T )
98  m_valueSingleLine->SetValidator( m_netNameValidator );
99 
100  m_valueCombo->SetValidator( m_netNameValidator );
101  }
102 
103  switch( m_CurrentText->Type() )
104  {
105  case SCH_GLOBAL_LABEL_T: SetTitle( _( "Global Label Properties" ) ); break;
106  case SCH_HIER_LABEL_T: SetTitle( _( "Hierarchical Label Properties" ) ); break;
107  case SCH_LABEL_T: SetTitle( _( "Label Properties" ) ); break;
108  case SCH_SHEET_PIN_T: SetTitle( _( "Hierarchical Sheet Pin Properties" ) ); break;
109  default: SetTitle( _( "Text Properties" ) ); break;
110  }
111 
113 
116 
118  {
119  m_note1->SetFont( KIUI::GetInfoFont( this ).Italic() );
120  m_note2->SetFont( KIUI::GetInfoFont( this ).Italic() );
121  }
122  else
123  {
124  m_note1->Show( false );
125  m_note2->Show( false );
126  }
127 
128  m_sdbSizer1OK->SetDefault();
129  Layout();
130 
132 
133  // DIALOG_SHIM needs a unique hash_key because classname is not sufficient because the
134  // various versions have different controls so we want to store sizes for each version.
135  m_hash_key = TO_UTF8( GetTitle() );
136 
137 
138  // Now all widgets have the size fixed, call FinishDialogSettings
140 }
141 
142 
144 {
145  delete m_scintillaTricks;
146 
147  if( m_helpWindow )
148  m_helpWindow->Destroy();
149 }
150 
151 
152 void DIALOG_TEXT_AND_LABEL_PROPERTIES::SetTitle( const wxString& aTitle )
153 {
154  // This class is shared for numerous tasks: a couple of single line labels and
155  // multi-line text fields. Since the desired size of the multi-line text field editor
156  // is often larger, we retain separate sizes based on the dialog titles.
157  switch( m_CurrentText->Type() )
158  {
159  case SCH_GLOBAL_LABEL_T:
160  case SCH_HIER_LABEL_T:
161  case SCH_LABEL_T:
162  // labels can share retained settings probably.
163  break;
164 
165  default:
166  m_hash_key = TO_UTF8( aTitle );
167  m_hash_key += typeid(*this).name();
168  }
169 
170  DIALOG_TEXT_AND_LABEL_PROPERTIES_BASE::SetTitle( aTitle );
171 }
172 
173 
175 {
176  if( !wxDialog::TransferDataToWindow() )
177  return false;
178 
179  if( m_CurrentText->Type() == SCH_TEXT_T )
180  {
181  SCHEMATIC& schematic = m_Parent->Schematic();
182 
183  // show text variable cross-references in a human-readable format
184  m_valueMultiLine->SetValue( schematic.ConvertKIIDsToRefs( m_CurrentText->GetText() ) );
185  }
186  else
187  {
188  // show control characters in a human-readable format
190  }
191 
192  if( m_valueCombo->IsShown() )
193  {
194  // Load the combobox with the existing labels of the same type
195  std::set<wxString> existingLabels;
196  SCH_SCREENS allScreens( m_Parent->Schematic().Root() );
197 
198  for( SCH_SCREEN* screen = allScreens.GetFirst(); screen; screen = allScreens.GetNext() )
199  {
200  for( SCH_ITEM* item : screen->Items().OfType( m_CurrentText->Type() ) )
201  {
202  auto textItem = static_cast<const SCH_TEXT*>( item );
203  existingLabels.insert( UnescapeString( textItem->GetText() ) );
204  }
205  }
206 
207  wxArrayString existingLabelArray;
208 
209  for( const wxString& label : existingLabels )
210  existingLabelArray.push_back( label );
211 
212  // existingLabelArray.Sort();
213  m_valueCombo->Append( existingLabelArray );
214  }
215 
216  // Set text options:
217  m_TextOrient->SetSelection( static_cast<int>( m_CurrentText->GetLabelSpinStyle() ) );
218 
219  m_TextShape->SetSelection( static_cast<int>( m_CurrentText->GetShape() ) );
220 
221  int style = 0;
222 
223  if( m_CurrentText->IsItalic() )
224  style = 1;
225 
226  if( m_CurrentText->IsBold() )
227  style += 2;
228 
229  m_TextStyle->SetSelection( style );
230 
232 
233  return true;
234 }
235 
236 
240 void DIALOG_TEXT_AND_LABEL_PROPERTIES::OnEnterKey( wxCommandEvent& aEvent )
241 {
242  wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
243 }
244 
245 
247 {
248  wxStyledTextCtrl* te = m_valueMultiLine;
249  wxArrayString autocompleteTokens;
250  int text_pos = te->GetCurrentPos();
251  int start = te->WordStartPosition( text_pos, true );
252  wxString partial;
253 
254  auto textVarRef =
255  [&]( int pos )
256  {
257  return pos >= 2 && te->GetCharAt( pos-2 ) == '$' && te->GetCharAt( pos-1 ) == '{';
258  };
259 
260  // Check for cross-reference
261  if( start > 1 && te->GetCharAt( start-1 ) == ':' )
262  {
263  int refStart = te->WordStartPosition( start-1, true );
264 
265  if( textVarRef( refStart ) )
266  {
267  partial = te->GetRange( start+1, text_pos );
268 
269  wxString ref = te->GetRange( refStart, start-1 );
271  SCH_REFERENCE_LIST refs;
272  SCH_SYMBOL* refSymbol = nullptr;
273 
274  sheets.GetSymbols( refs );
275 
276  for( size_t jj = 0; jj < refs.GetCount(); jj++ )
277  {
278  if( refs[ jj ].GetSymbol()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref )
279  {
280  refSymbol = refs[ jj ].GetSymbol();
281  break;
282  }
283  }
284 
285  if( refSymbol )
286  refSymbol->GetContextualTextVars( &autocompleteTokens );
287  }
288  }
289  else if( textVarRef( start ) )
290  {
291  partial = te->GetTextRange( start, text_pos );
292 
293  m_CurrentText->GetContextualTextVars( &autocompleteTokens );
294 
295  SCHEMATIC* schematic = m_CurrentText->Schematic();
296 
297  if( schematic && schematic->CurrentSheet().Last() )
298  schematic->CurrentSheet().Last()->GetContextualTextVars( &autocompleteTokens );
299 
300  for( std::pair<wxString, wxString> entry : Prj().GetTextVars() )
301  autocompleteTokens.push_back( entry.first );
302  }
303 
304  m_scintillaTricks->DoAutocomplete( partial, autocompleteTokens );
305  m_valueMultiLine->SetFocus();
306 }
307 
308 
310 {
311  if( !wxDialog::TransferDataFromWindow() )
312  return false;
313 
314  // Don't allow text to disappear; it can be difficult to correct if you can't select it
315  if( !m_textSize.Validate( 0.01, 1000.0, EDA_UNITS::MILLIMETRES ) )
316  return false;
317 
318  wxString text;
319 
320  /* save old text in undo list if not already in edit */
321  if( m_CurrentText->GetEditFlags() == 0 )
323 
324  m_Parent->GetCanvas()->Refresh();
325 
326  if( m_CurrentText->Type() == SCH_TEXT_T )
327  {
328  // convert any text variable cross-references to their UUIDs
330  }
331  else
332  {
333  // labels need escaping
335  }
336 
337  if( !text.IsEmpty() )
338  {
339 #ifdef __WXMAC__
340  // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting
341  text.Replace( "\r", "\n" );
342 #endif
344  }
345  else if( !m_CurrentText->IsNew() )
346  {
347  DisplayError( this, _( "Label requires non-empty text." ) );
348  return false;
349  }
350 
351  LABEL_SPIN_STYLE selectedSpinStyle(
352  static_cast<LABEL_SPIN_STYLE::SPIN>( m_TextOrient->GetSelection() ) );
353 
354  if( m_CurrentText->GetLabelSpinStyle() != selectedSpinStyle )
355  m_CurrentText->SetLabelSpinStyle( selectedSpinStyle );
356 
359 
360  if( m_TextShape )
362 
363  int style = m_TextStyle->GetSelection();
364  bool wantItalic = ( style & 1 ) > 0;
365  bool wantBold = (style & 2 ) > 0;
366 
367  m_CurrentText->SetItalic( wantItalic );
368 
369  if( wantBold != m_CurrentText->IsBold() )
370  {
371  if( wantBold )
372  {
373  m_CurrentText->SetBold( true );
375  }
376  else
377  {
378  m_CurrentText->SetBold( false );
379  m_CurrentText->SetTextThickness( 0 ); // Use default pen width
380  }
381  }
382 
383  m_Parent->UpdateItem( m_CurrentText, false, true );
384  m_Parent->GetCanvas()->Refresh();
385  m_Parent->OnModify();
386 
388  {
389  SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( m_CurrentText );
390  label->UpdateIntersheetRefProps();
391  }
392 
393  return true;
394 }
395 
396 
398 {
400 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:279
Class DIALOG_TEXT_AND_LABEL_PROPERTIES_BASE.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
bool IsBold() const
Definition: eda_text.h:183
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:163
int GetPenSizeForBold(int aTextSize)
Definition: gr_text.cpp:46
void onScintillaCharAdded(wxStyledTextEvent &aEvent)
Holds all the data relating to one schematic.
Definition: schematic.h:59
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
std::string m_hash_key
Definition: dialog_shim.h:199
Add cut/copy/paste, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
void DoAutocomplete(const wxString &aPartial, const wxArrayString &aTokens)
void SetItalic(bool isItalic)
Definition: eda_text.h:179
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:97
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:144
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this sheet.
Definition: sch_sheet.cpp:196
Schematic editor (Eeschema) main window.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:237
void OnEnterKey(wxCommandEvent &aEvent) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
bool IsNew() const
Definition: eda_item.h:119
bool IsItalic() const
Definition: eda_text.h:180
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
void GetContextualTextVars(wxArrayString *aVars) const
Return the set of contextual text variable tokens for this text item.
Definition: sch_text.cpp:580
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
Definition: sch_symbol.cpp:928
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
wxString ConvertRefsToKIIDs(const wxString &aSource) const
Definition: schematic.cpp:288
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
Definitions of control validators for schematic dialogs.
SCHEMATIC & Schematic() const
size_t GetCount() const
DIALOG_TEXT_AND_LABEL_PROPERTIES(SCH_EDIT_FRAME *parent, SCH_TEXT *aTextItem)
#define _(s)
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false)
Mark an item for refresh.
LABEL_SPIN_STYLE GetLabelSpinStyle() const
Definition: sch_text.h:159
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:158
void UpdateIntersheetRefProps()
Definition: sch_text.cpp:1181
wxString UnescapeString(const wxString &aSource)
bool IsMultilineAllowed() const
Definition: eda_text.h:196
wxString ConvertKIIDsToRefs(const wxString &aSource) const
Definition: schematic.cpp:344
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
static HTML_MESSAGE_BOX * ShowSyntaxHelp(wxWindow *aParentWindow)
Definition: sch_text.cpp:1718
PINSHEETLABEL_SHAPE
Definition: sch_text.h:95
SCH_SHEET & Root() const
Definition: schematic.h: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.
int GetTextWidth() const
Definition: eda_text.h:241
Schematic symbol object.
Definition: sch_symbol.h:78
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend)
Create a copy of the current schematic item, and put it in the undo list.
virtual void SetValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
virtual long long int GetValue()
Return the current value in Internal Units.
void OnFormattingHelp(wxHyperlinkEvent &aEvent) override
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:159
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
void SetTitle(const wxString &aTitle) override
virtual void SetLabelSpinStyle(LABEL_SPIN_STYLE aSpinStyle)
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:320
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:121
void SetBold(bool aBold)
Definition: eda_text.h:182
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:182
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:568
PINSHEETLABEL_SHAPE GetShape() const
Definition: sch_text.h:161
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113