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@verizon.net>
6  * Copyright (C) 1992-2018 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 <fctsys.h>
27 #include <sch_edit_frame.h>
28 #include <base_units.h>
29 #include <sch_validators.h>
30 #include <tool/tool_manager.h>
31 #include <general.h>
32 #include <gr_text.h>
33 #include <confirm.h>
34 #include <sch_text.h>
35 #include <widgets/unit_binder.h>
36 #include <dialog_edit_label_base.h>
37 #include <kicad_string.h>
38 #include <tool/actions.h>
39 
40 class SCH_EDIT_FRAME;
41 class SCH_TEXT;
42 
43 
45 {
46 public:
47  DIALOG_LABEL_EDITOR( SCH_EDIT_FRAME* parent, SCH_TEXT* aTextItem );
49 
50  void SetTitle( const wxString& aTitle ) override
51  {
52  // This class is shared for numerous tasks: a couple of single line labels and
53  // multi-line text fields. Since the desired size of the multi-line text field editor
54  // is often larger, we retain separate sizes based on the dialog titles.
55  switch( m_CurrentText->Type() )
56  {
57  case SCH_GLOBAL_LABEL_T:
58  case SCH_HIER_LABEL_T:
59  case SCH_LABEL_T:
60  // labels can share retained settings probably.
61  break;
62 
63  default:
64  m_hash_key = TO_UTF8( aTitle );
65  m_hash_key += typeid(*this).name();
66  }
67 
68  DIALOG_LABEL_EDITOR_BASE::SetTitle( aTitle );
69  }
70 
71 private:
72  virtual void OnEnterKey( wxCommandEvent& aEvent ) override;
73  void OnCharHook( wxKeyEvent& aEvt );
74 
75  bool TransferDataToWindow() override;
76  bool TransferDataFromWindow() override;
77 
80  wxWindow* m_activeTextCtrl;
81  wxTextEntry* m_activeTextEntry;
84 };
85 
86 
87 int InvokeDialogLabelEditor( SCH_EDIT_FRAME* aCaller, SCH_TEXT* aTextItem )
88 {
89  DIALOG_LABEL_EDITOR dialog( aCaller, aTextItem );
90 
91  return dialog.ShowModal();
92 }
93 
94 
95 // Don't allow text to disappear; it can be difficult to correct if you can't select it
96 const int MIN_TEXTSIZE = (int)( 0.01 * IU_PER_MM );
97 const int MAX_TEXTSIZE = INT_MAX;
98 
99 
101  DIALOG_LABEL_EDITOR_BASE( aParent ),
102  m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits, false ),
103  m_netNameValidator( true )
104 {
105  m_Parent = aParent;
106  m_CurrentText = aTextItem;
107 
108  switch( m_CurrentText->Type() )
109  {
110  case SCH_GLOBAL_LABEL_T: SetTitle( _( "Global Label Properties" ) ); break;
111  case SCH_HIER_LABEL_T: SetTitle( _( "Hierarchical Label Properties" ) ); break;
112  case SCH_LABEL_T: SetTitle( _( "Label Properties" ) ); break;
113  case SCH_SHEET_PIN_T: SetTitle( _( "Hierarchical Sheet Pin Properties" ) ); break;
114  default: SetTitle( _( "Text Properties" ) ); break;
115  }
116 
117  m_valueMultiLine->SetEOLMode( wxSTC_EOL_LF );
118 
120  {
122  m_activeTextEntry = nullptr;
123 
124  m_labelSingleLine->Show( false );
125  m_valueSingleLine->Show( false );
126  m_labelCombo->Show( false );
127  m_valueCombo->Show( false );
128 
129  m_textEntrySizer->AddGrowableRow( 0 );
130  }
132  {
135 
136  m_labelSingleLine->Show( false ); m_valueSingleLine->Show( false );
137  m_labelMultiLine->Show( false ); m_valueMultiLine->Show( false );
138 
139  m_valueCombo->SetValidator( m_netNameValidator );
140  }
141  else
142  {
145 
146  m_labelCombo->Show( false ); m_valueCombo->Show( false );
147  m_labelMultiLine->Show( false ); m_valueMultiLine->Show( false );
148 
149  if( m_CurrentText->Type() != SCH_TEXT_T )
150  m_valueSingleLine->SetValidator( m_netNameValidator );
151 
152  m_valueCombo->SetValidator( m_netNameValidator );
153  }
154 
156 
159 
160  m_sdbSizer1OK->SetDefault();
161  Layout();
162 
163  // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set,
164  // so we have to listen to wxEVT_CHAR_HOOK events instead.
165  m_valueMultiLine->Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_LABEL_EDITOR::OnCharHook ), nullptr, this );
166 
167  // DIALOG_SHIM needs a unique hash_key because classname is not sufficient because the
168  // various versions have different controls so we want to store sizes for each version.
169  m_hash_key = TO_UTF8( GetTitle() );
170 
171 
172  // Now all widgets have the size fixed, call FinishDialogSettings
174 }
175 
176 
178 {
179  m_valueMultiLine->Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_LABEL_EDITOR::OnCharHook ), nullptr, this );
180 }
181 
182 
184 {
185  if( !wxDialog::TransferDataToWindow() )
186  return false;
187 
188  if( m_activeTextEntry )
190  else
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;
198 
199  for( SCH_SCREEN* screen = allScreens.GetFirst(); screen; screen = allScreens.GetNext() )
200  {
201  for( auto 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 
250 void DIALOG_LABEL_EDITOR::OnCharHook( wxKeyEvent& aEvt )
251 {
252  if( aEvt.GetKeyCode() == WXK_TAB )
253  {
254  if( aEvt.ControlDown() )
255  {
256  int flags = 0;
257 
258  if( !aEvt.ShiftDown() )
259  flags |= wxNavigationKeyEvent::IsForward;
260 
261  NavigateIn( flags );
262  }
263  else
264  {
265  m_valueMultiLine->Tab();
266  }
267  }
268  else if( m_valueMultiLine->IsShown() && IsCtrl( 'Z', aEvt ) )
269  {
270  m_valueMultiLine->Undo();
271  }
272  else if( m_valueMultiLine->IsShown() && ( IsShiftCtrl( 'Z', aEvt ) || IsCtrl( 'Y', aEvt ) ) )
273  {
274  m_valueMultiLine->Redo();
275  }
276  else if( IsCtrl( 'X', aEvt ) )
277  {
278  m_valueMultiLine->Cut();
279  }
280  else if( IsCtrl( 'C', aEvt ) )
281  {
282  m_valueMultiLine->Copy();
283  }
284  else if( IsCtrl( 'V', aEvt ) )
285  {
286  m_valueMultiLine->Paste();
287  }
288  else
289  {
290  aEvt.Skip();
291  }
292 }
293 
294 
296 {
297  if( !wxDialog::TransferDataFromWindow() )
298  return false;
299 
301  return false;
302 
303  wxString text;
304 
305  /* save old text in undo list if not already in edit */
306  if( m_CurrentText->GetEditFlags() == 0 )
308 
309  m_Parent->GetCanvas()->Refresh();
310 
311  // Escape string only if is is a label. For a simple graphic text do not change anything
312  if( m_CurrentText->Type() == SCH_TEXT_T )
313  text = m_valueMultiLine->GetValue();
314  else
315  text = EscapeString( m_activeTextEntry->GetValue(), CTX_NETNAME );
316 
317  if( !text.IsEmpty() )
318  m_CurrentText->SetText( text );
319  else if( !m_CurrentText->IsNew() )
320  {
321  DisplayError( this, _( "Empty Text!" ) );
322  return false;
323  }
324 
325  m_CurrentText->SetLabelSpinStyle( m_TextOrient->GetSelection() );
326 
328 
329  if( m_TextShape )
330  m_CurrentText->SetShape( static_cast<PINSHEETLABEL_SHAPE>( m_TextShape->GetSelection() ) );
331 
332  int style = m_TextStyle->GetSelection();
333 
334  m_CurrentText->SetItalic( ( style & 1 ) );
335 
336  if( ( style & 2 ) )
337  {
338  m_CurrentText->SetBold( true );
340  }
341  else
342  {
343  m_CurrentText->SetBold( false );
345  }
346 
348  m_Parent->GetCanvas()->Refresh();
349  m_Parent->OnModify();
350 
351  // Make the text size the new default size ( if it is a new text ):
352  if( m_CurrentText->IsNew() )
354 
355  return true;
356 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
bool IsBold() const
Definition: eda_text.h:167
const int MIN_TEXTSIZE
void SetTitle(const wxString &aTitle) override
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:245
SCH_SCREEN * GetNext()
Definition: sch_screen.cpp:981
const int MAX_TEXTSIZE
wxTextEntry * m_activeTextEntry
int GetPenSizeForBold(int aTextSize)
Function GetPensizeForBold.
Definition: gr_text.cpp:66
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:197
void SetItalic(bool isItalic)
Definition: eda_text.h:163
virtual void OnEnterKey(wxCommandEvent &aEvent) override
bool TransferDataToWindow() override
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Schematic editor (Eeschema) main window.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:222
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:115
DIALOG_LABEL_EDITOR(SCH_EDIT_FRAME *parent, SCH_TEXT *aTextItem)
bool IsNew() const
Definition: base_struct.h:218
int InvokeDialogLabelEditor(SCH_EDIT_FRAME *aCaller, SCH_TEXT *aTextItem)
Launches the "Edit Text/Label" dialog.
bool IsItalic() const
Definition: eda_text.h:164
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
void SetDefaultTextSize(int aTextSize)
void OnCharHook(wxKeyEvent &aEvt)
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:111
STATUS_FLAGS GetEditFlags() const
Definition: base_struct.h:260
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.
void SaveCopyInUndoList(SCH_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, bool aAppend=false, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
LABEL_SPIN_STYLE GetLabelSpinStyle() const
Definition: sch_text.h:238
virtual bool Validate(long long int aMin, long long int aMax, bool setFocusOnError=true)
Function Validate Validates the control against the given range, informing the user of any errors fou...
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
bool IsMultilineAllowed() const
Definition: eda_text.h:181
bool TransferDataFromWindow() override
int GetTextWidth() const
Definition: eda_text.h:226
void RefreshItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
#define _(s)
Definition: 3d_actions.cpp:31
static bool IsShiftCtrl(int aChar, const wxKeyEvent &e)
Definition: dialog_shim.h:143
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:131
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
These Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which ar...
Definition: string.cpp:50
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
wxStyledTextCtrl * m_valueMultiLine
SCH_SCREEN * GetFirst()
Definition: sch_screen.cpp:970
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:210
static bool IsCtrl(int aChar, const wxKeyEvent &e)
Definition: dialog_shim.h:137
void SetBold(bool aBold)
Definition: eda_text.h:166
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:123
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:498
void SetThickness(int aNewThickness)
Set the pen width.
Definition: eda_text.h:143
PINSHEETLABEL_SHAPE GetShape() const
Definition: sch_text.h:243
KICAD_T Type() const
Function Type()
Definition: base_struct.h:207