KiCad PCB EDA Suite
dialog_edit_label.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>
37 #include <dialog_edit_label.h>
38 #include <kicad_string.h>
39 #include <tool/actions.h>
40 #include <scintilla_tricks.h>
41 
42 class SCH_EDIT_FRAME;
43 class SCH_TEXT;
44 
45 
47  DIALOG_LABEL_EDITOR_BASE( aParent ),
48  m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits, false ),
49  m_netNameValidator( true ),
50  m_scintillaTricks( nullptr ),
51  m_helpWindow( nullptr )
52 {
53  m_Parent = aParent;
54  m_CurrentText = aTextItem;
55 
56  m_valueMultiLine->SetEOLMode( wxSTC_EOL_LF );
57 
58  m_scintillaTricks = new SCINTILLA_TRICKS( m_valueMultiLine, wxT( "{}" ), false,
59  [this]()
60  {
61  wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
62  } );
63 
65  {
67  m_activeTextEntry = nullptr;
68 
69  m_labelSingleLine->Show( false );
70  m_valueSingleLine->Show( false );
71  m_labelCombo->Show( false );
72  m_valueCombo->Show( false );
73 
74  m_textEntrySizer->AddGrowableRow( 0 );
75  }
77  {
80 
81  m_labelSingleLine->Show( false ); m_valueSingleLine->Show( false );
82  m_labelMultiLine->Show( false ); m_valueMultiLine->Show( false );
83 
84  m_valueCombo->SetValidator( m_netNameValidator );
85  }
86  else
87  {
90 
91  m_labelCombo->Show( false );
92  m_valueCombo->Show( false );
93  m_labelMultiLine->Show( false );
94  m_valueMultiLine->Show( false );
95 
96  if( m_CurrentText->Type() != SCH_TEXT_T )
97  m_valueSingleLine->SetValidator( m_netNameValidator );
98 
99  m_valueCombo->SetValidator( m_netNameValidator );
100  }
101 
102  switch( m_CurrentText->Type() )
103  {
104  case SCH_GLOBAL_LABEL_T: SetTitle( _( "Global Label Properties" ) ); break;
105  case SCH_HIER_LABEL_T: SetTitle( _( "Hierarchical Label Properties" ) ); break;
106  case SCH_LABEL_T: SetTitle( _( "Label Properties" ) ); break;
107  case SCH_SHEET_PIN_T: SetTitle( _( "Hierarchical Sheet Pin Properties" ) ); break;
108  default: SetTitle( _( "Text Properties" ) ); break;
109  }
110 
112 
115 
117  {
118  wxFont infoFont = KIUI::GetInfoFont();
119  infoFont.SetSymbolicSize( wxFONTSIZE_X_SMALL );
120  m_note1->SetFont( infoFont );
121  m_note2->SetFont( infoFont );
122  }
123  else
124  {
125  m_note1->Show( false );
126  m_note2->Show( false );
127  }
128 
129  m_sdbSizer1OK->SetDefault();
130  Layout();
131 
132  m_valueMultiLine->Bind( wxEVT_STC_CHARADDED, &DIALOG_LABEL_EDITOR::onScintillaCharAdded, this );
133 
134  // DIALOG_SHIM needs a unique hash_key because classname is not sufficient because the
135  // various versions have different controls so we want to store sizes for each version.
136  m_hash_key = TO_UTF8( GetTitle() );
137 
138 
139  // Now all widgets have the size fixed, call FinishDialogSettings
141 }
142 
143 
145 {
146  delete m_scintillaTricks;
147 
148  if( m_helpWindow )
149  m_helpWindow->Destroy();
150 }
151 
152 
153 void DIALOG_LABEL_EDITOR::SetTitle( const wxString& aTitle )
154 {
155  // This class is shared for numerous tasks: a couple of single line labels and
156  // multi-line text fields. Since the desired size of the multi-line text field editor
157  // is often larger, we retain separate sizes based on the dialog titles.
158  switch( m_CurrentText->Type() )
159  {
160  case SCH_GLOBAL_LABEL_T:
161  case SCH_HIER_LABEL_T:
162  case SCH_LABEL_T:
163  // labels can share retained settings probably.
164  break;
165 
166  default:
167  m_hash_key = TO_UTF8( aTitle );
168  m_hash_key += typeid(*this).name();
169  }
170 
171  DIALOG_LABEL_EDITOR_BASE::SetTitle( aTitle );
172 }
173 
174 
176 {
177  if( !wxDialog::TransferDataToWindow() )
178  return false;
179 
180  if( m_CurrentText->Type() == SCH_TEXT_T )
181  {
182  SCHEMATIC& schematic = m_Parent->Schematic();
183 
184  // show text variable cross-references in a human-readable format
185  m_valueMultiLine->SetValue( schematic.ConvertKIIDsToRefs( m_CurrentText->GetText() ) );
186  }
187  else
188  {
189  // show control characters in a human-readable format
191  }
192 
193  if( m_valueCombo->IsShown() )
194  {
195  // Load the combobox with the existing labels of the same type
196  std::set<wxString> existingLabels;
197  SCH_SCREENS allScreens( m_Parent->Schematic().Root() );
198 
199  for( SCH_SCREEN* screen = allScreens.GetFirst(); screen; screen = allScreens.GetNext() )
200  {
201  for( SCH_ITEM* item : screen->Items().OfType( m_CurrentText->Type() ) )
202  {
203  auto textItem = static_cast<const SCH_TEXT*>( item );
204  existingLabels.insert( UnescapeString( textItem->GetText() ) );
205  }
206  }
207 
208  wxArrayString existingLabelArray;
209 
210  for( const wxString& label : existingLabels )
211  existingLabelArray.push_back( label );
212 
213  // existingLabelArray.Sort();
214  m_valueCombo->Append( existingLabelArray );
215  }
216 
217  // Set text options:
218  m_TextOrient->SetSelection( static_cast<int>( m_CurrentText->GetLabelSpinStyle() ) );
219 
220  m_TextShape->SetSelection( static_cast<int>( m_CurrentText->GetShape() ) );
221 
222  int style = 0;
223 
224  if( m_CurrentText->IsItalic() )
225  style = 1;
226 
227  if( m_CurrentText->IsBold() )
228  style += 2;
229 
230  m_TextStyle->SetSelection( style );
231 
233 
234  return true;
235 }
236 
237 
241 void DIALOG_LABEL_EDITOR::OnEnterKey( wxCommandEvent& aEvent )
242 {
243  wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
244 }
245 
246 
247 void DIALOG_LABEL_EDITOR::onScintillaCharAdded( wxStyledTextEvent &aEvent )
248 {
249  wxStyledTextCtrl* te = m_valueMultiLine;
250  wxArrayString autocompleteTokens;
251  int text_pos = te->GetCurrentPos();
252  int start = te->WordStartPosition( text_pos, true );
253  wxString partial;
254 
255  auto textVarRef =
256  [&]( int pos )
257  {
258  return pos >= 2 && te->GetCharAt( pos-2 ) == '$' && te->GetCharAt( pos-1 ) == '{';
259  };
260 
261  // Check for cross-reference
262  if( start > 1 && te->GetCharAt( start-1 ) == ':' )
263  {
264  int refStart = te->WordStartPosition( start-1, true );
265 
266  if( textVarRef( refStart ) )
267  {
268  partial = te->GetRange( start+1, text_pos );
269 
270  wxString ref = te->GetRange( refStart, start-1 );
272  SCH_REFERENCE_LIST refs;
273  SCH_SYMBOL* refSymbol = nullptr;
274 
275  sheets.GetSymbols( refs );
276 
277  for( size_t jj = 0; jj < refs.GetCount(); jj++ )
278  {
279  if( refs[ jj ].GetSymbol()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref )
280  {
281  refSymbol = refs[ jj ].GetSymbol();
282  break;
283  }
284  }
285 
286  if( refSymbol )
287  refSymbol->GetContextualTextVars( &autocompleteTokens );
288  }
289  }
290  else if( textVarRef( start ) )
291  {
292  partial = te->GetTextRange( start, text_pos );
293 
294  m_CurrentText->GetContextualTextVars( &autocompleteTokens );
295 
296  SCHEMATIC* schematic = m_CurrentText->Schematic();
297 
298  if( schematic && schematic->CurrentSheet().Last() )
299  schematic->CurrentSheet().Last()->GetContextualTextVars( &autocompleteTokens );
300 
301  for( std::pair<wxString, wxString> entry : Prj().GetTextVars() )
302  autocompleteTokens.push_back( entry.first );
303  }
304 
305  m_scintillaTricks->DoAutocomplete( partial, autocompleteTokens );
306  m_valueMultiLine->SetFocus();
307 }
308 
309 
311 {
312  if( !wxDialog::TransferDataFromWindow() )
313  return false;
314 
315  // Don't allow text to disappear; it can be difficult to correct if you can't select it
316  if( !m_textSize.Validate( 0.01, 1000.0, EDA_UNITS::MILLIMETRES ) )
317  return false;
318 
319  wxString text;
320 
321  /* save old text in undo list if not already in edit */
322  if( m_CurrentText->GetEditFlags() == 0 )
324 
325  m_Parent->GetCanvas()->Refresh();
326 
327  if( m_CurrentText->Type() == SCH_TEXT_T )
328  {
329  // convert any text variable cross-references to their UUIDs
331  }
332  else
333  {
334  // labels need escaping
336  }
337 
338  if( !text.IsEmpty() )
339  {
340 #ifdef __WXMAC__
341  // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting
342  text.Replace( "\r", "\n" );
343 #endif
345  }
346  else if( !m_CurrentText->IsNew() )
347  {
348  DisplayError( this, _( "Label requires non-empty text." ) );
349  return false;
350  }
351 
353 
355 
356  if( m_TextShape )
358 
359  int style = m_TextStyle->GetSelection();
360 
361  m_CurrentText->SetItalic( ( style & 1 ) );
362 
363  if( ( style & 2 ) )
364  {
365  m_CurrentText->SetBold( true );
367  }
368  else
369  {
370  m_CurrentText->SetBold( false );
371  m_CurrentText->SetTextThickness( 0 ); // Use default pen width
372  }
373 
375  m_Parent->GetCanvas()->Refresh();
376  m_Parent->OnModify();
377 
379  {
380  SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( m_CurrentText );
381  label->UpdateIntersheetRefProps();
382  }
383 
384  return true;
385 }
386 
387 
388 void DIALOG_LABEL_EDITOR::OnFormattingHelp( wxHyperlinkEvent& aEvent )
389 {
391 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:252
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
bool IsBold() const
Definition: eda_text.h:183
void SetTitle(const wxString &aTitle) override
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:163
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
wxTextEntry * m_activeTextEntry
int GetPenSizeForBold(int aTextSize)
Definition: gr_text.cpp:47
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.
void onScintillaCharAdded(wxStyledTextEvent &aEvent)
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
void OnEnterKey(wxCommandEvent &aEvent) override
bool TransferDataToWindow() override
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:97
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this sheet.
Definition: sch_sheet.cpp:197
Schematic editor (Eeschema) main window.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:237
Class DIALOG_LABEL_EDITOR_BASE.
SCH_EDIT_FRAME * m_Parent
wxFlexGridSizer * m_textEntrySizer
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
DIALOG_LABEL_EDITOR(SCH_EDIT_FRAME *parent, SCH_TEXT *aTextItem)
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:567
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
Definition: sch_symbol.cpp:919
void OnFormattingHelp(wxHyperlinkEvent &aEvent) override
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
wxString ConvertRefsToKIIDs(const wxString &aSource) const
Definition: schematic.cpp:285
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
SCH_NETNAME_VALIDATOR m_netNameValidator
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
#define _(s)
LABEL_SPIN_STYLE GetLabelSpinStyle() const
Definition: sch_text.h:159
SCINTILLA_TRICKS * m_scintillaTricks
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:158
void UpdateIntersheetRefProps()
Definition: sch_text.cpp:1172
bool IsMultilineAllowed() const
Definition: eda_text.h:196
bool TransferDataFromWindow() override
wxString ConvertKIIDsToRefs(const wxString &aSource) const
Definition: schematic.cpp:341
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:1655
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
wxFont GetInfoFont()
Definition: ui_common.cpp:97
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.
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:222
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
Definition: string.cpp:141
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...
HTML_MESSAGE_BOX * m_helpWindow
virtual long long int GetValue()
Return the current value in Internal Units.
wxStyledTextCtrl * m_valueMultiLine
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...
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:318
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:197
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:551
PINSHEETLABEL_SHAPE GetShape() const
Definition: sch_text.h:161
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113