KiCad PCB EDA Suite
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) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2004-2018 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 
30 #include <fctsys.h>
31 #include <gr_basic.h>
32 #include <base_struct.h>
33 #include <draw_graphic_text.h>
34 #include <sch_draw_panel.h>
35 #include <confirm.h>
36 #include <sch_edit_frame.h>
37 #include <kicad_device_context.h>
38 
39 #include <general.h>
40 #include <sch_text.h>
41 #include <eeschema_id.h>
42 
43 
45 static int lastTextOrientation = 0;
46 static bool lastTextBold = false;
47 static bool lastTextItalic = false;
48 
49 
51 {
52  wxCHECK_RET( (aTextItem != NULL) && aTextItem->CanIncrementLabel(),
53  wxT( "Invalid schematic text item." ) );
54 
55  int orient = ( aTextItem->GetLabelSpinStyle() + 1 ) & 3;
56 
57  // Save current text orientation in undo list if is not already in edit.
58  if( aTextItem->GetFlags() == 0 )
59  SaveCopyInUndoList( aTextItem, UR_CHANGED );
60 
61  aTextItem->SetLabelSpinStyle( orient );
62 
63  RefreshItem( aTextItem );
64  OnModify();
65 }
66 
67 
69 {
70  SCH_TEXT* textItem = NULL;
71 
72  SetRepeatItem( NULL );
73 
74  switch( aType )
75  {
76  case LAYER_NOTES:
77  textItem = new SCH_TEXT( GetCrossHairPosition() );
78  break;
79 
80  case LAYER_LOCLABEL:
81  textItem = new SCH_LABEL( GetCrossHairPosition() );
82  break;
83 
84  case LAYER_HIERLABEL:
85  textItem = new SCH_HIERLABEL( GetCrossHairPosition() );
86  textItem->SetShape( lastGlobalLabelShape );
87  break;
88 
89  case LAYER_GLOBLABEL:
90  textItem = new SCH_GLOBALLABEL( GetCrossHairPosition() );
91  textItem->SetShape( lastGlobalLabelShape );
92  break;
93 
94  default:
95  DisplayError( this, wxT( "SCH_EDIT_FRAME::CreateNewText() Internal error" ) );
96  return NULL;
97  }
98 
99  textItem->SetBold( lastTextBold );
100  textItem->SetItalic( lastTextItalic );
102  textItem->SetTextSize( wxSize( GetDefaultTextSize(), GetDefaultTextSize() ) );
103  textItem->SetFlags( IS_NEW | IS_MOVED );
104 
105  EditSchematicText( textItem );
106 
107  if( textItem->GetText().IsEmpty() )
108  {
109  delete textItem;
110  return NULL;
111  }
112 
113  lastTextBold = textItem->IsBold();
114  lastTextItalic = textItem->IsItalic();
116 
117  if( textItem->Type() == SCH_GLOBAL_LABEL_T || textItem->Type() == SCH_HIERARCHICAL_LABEL_T )
118  lastGlobalLabelShape = textItem->GetShape();
119 
120  // Prepare display to move the new item
121  PrepareMoveItem( textItem );
122 
123  return textItem;
124 }
125 
126 
127 /*
128  * OnConvertTextType is a command event handler to change a text type to another one.
129  * The new text, label, hierarchical label, or global label is created from the old text
130  * The old text is deleted.
131  * A tricky case is when the 'old" text is being edited (i.e. moving)
132  * because we must create a new text, and prepare the undo/redo command data for this
133  * change and the current move/edit command
134  */
135 void SCH_EDIT_FRAME::OnConvertTextType( wxCommandEvent& aEvent )
136 {
137  SCH_SCREEN* screen = GetScreen();
138  SCH_TEXT* text = (SCH_TEXT*) screen->GetCurItem();
139 
140  wxCHECK_RET( (text != NULL) && text->CanIncrementLabel(), "Cannot convert text type." );
141 
142  KICAD_T type;
143 
144  switch( aEvent.GetId() )
145  {
147  type = SCH_LABEL_T;
148  break;
149 
151  type = SCH_GLOBAL_LABEL_T;
152  break;
153 
156  break;
157 
159  type = SCH_TEXT_T;
160  break;
161 
162  default:
163  wxFAIL_MSG( wxString::Format( "Invalid text type command ID %d.", aEvent.GetId() ) );
164  return;
165  }
166 
167  if( text->Type() == type )
168  return;
169 
170  SCH_TEXT* newtext = nullptr;
171  const wxPoint &position = text->GetPosition();
172  const wxString &txt = text->GetText();
173 
174  switch( type )
175  {
176  case SCH_LABEL_T:
177  newtext = new SCH_LABEL( position, txt );
178  break;
179 
180  case SCH_GLOBAL_LABEL_T:
181  newtext = new SCH_GLOBALLABEL( position, txt );
182  break;
183 
185  newtext = new SCH_HIERLABEL( position, txt );
186  break;
187 
188  case SCH_TEXT_T:
189  newtext = new SCH_TEXT( position, txt );
190  break;
191 
192  default:
193  wxASSERT_MSG( false, wxString::Format( "Invalid text type: %d.", type ) );
194  return;
195  }
196 
197  /* Copy the old text item settings to the new one. Justifications are not copied because
198  * they are not used in labels. Justifications will be set to default value in the new
199  * text item type.
200  */
201  newtext->SetFlags( text->GetFlags() );
202  newtext->SetShape( text->GetShape() );
203  newtext->SetLabelSpinStyle( text->GetLabelSpinStyle() );
204  newtext->SetTextSize( text->GetTextSize() );
205  newtext->SetThickness( text->GetThickness() );
206  newtext->SetItalic( text->IsItalic() );
207  newtext->SetBold( text->IsBold() );
208  newtext->SetIsDangling( text->IsDangling() );
209 
210  /* Save the new text in undo list if the old text was not itself a "new created text"
211  * In this case, the old text is already in undo list as a deleted item.
212  * Of course if the old text was a "new created text" the new text will be
213  * put in undo list later, at the end of the current command (if not aborted)
214  */
215 
216  m_canvas->CrossHairOff(); // Erase schematic cursor
217 
218  // For an exiting item (i.e. already in list):
219  // replace the existing item by the new text in list
220  for( SCH_ITEM* item = screen->GetDrawItems(); item != NULL; item = item->Next() )
221  {
222  if( item == text )
223  {
224  RemoveFromScreen( text );
225  AddToScreen( newtext );
226  break;
227  }
228  }
229 
230  SetRepeatItem( NULL );
231  OnModify();
232  m_canvas->CrossHairOn( ); // redraw schematic cursor
233 
234  // if the old item is the current schematic item, replace it by the new text:
235  if( screen->GetCurItem() == text )
236  screen->SetCurItem( newtext );
237 
238  if( text->IsNew() )
239  {
240  // if the previous text is new, no undo command to prepare here
241  // just delete this previous text.
242  delete text;
243  return;
244  }
245 
246  // previous text is not new and we replace text by new text.
247  // So this is equivalent to delete text and add newtext
248  // If text if being currently edited (i.e. moved)
249  // we also save the initial copy of text, and prepare undo command for new text modifications.
250  // we must save it as modified text,if it is currently edited, then save as deleted text,
251  // and replace text with newtext
252  PICKED_ITEMS_LIST pickList;
253  ITEM_PICKER picker( text, UR_CHANGED );
254 
255  if( text->GetFlags() )
256  {
257  // text is being edited, save initial text for undo command
258  picker.SetLink( GetUndoItem() );
259  pickList.PushItem( picker );
260 
261  // the owner of undoItem is no more "this", it is now "picker":
262  SetUndoItem( NULL );
263 
264  // save current newtext copy for undo/abort current command
265  SetUndoItem( newtext );
266  }
267 
268  // Prepare undo command for delete old text
269  picker.SetStatus( UR_DELETED );
270  picker.SetLink( NULL );
271  pickList.PushItem( picker );
272 
273  // Prepare undo command for new text
274  picker.SetStatus( UR_NEW );
275  picker.SetItem(newtext);
276  pickList.PushItem( picker );
277 
278  SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
279 }
280 
281 
282 /* Function to increment bus label members numbers,
283  * i.e. when a text is ending with a number, adds
284  * aIncrement to this number
285  */
286 void IncrementLabelMember( wxString& name, int aIncrement )
287 {
288  int ii, nn;
289  long number = 0;
290 
291  ii = name.Len() - 1; nn = 0;
292 
293  if( !isdigit( name.GetChar( ii ) ) )
294  return;
295 
296  while( (ii >= 0) && isdigit( name.GetChar( ii ) ) )
297  {
298  ii--; nn++;
299  }
300 
301  ii++; /* digits are starting at ii position */
302  wxString litt_number = name.Right( nn );
303 
304  if( litt_number.ToLong( &number ) )
305  {
306  number += aIncrement;
307  name.Remove( ii ); name << number;
308  }
309 }
virtual void SetIsDangling(bool aIsDangling)
Definition: sch_text.h:179
PINSHEETLABEL_SHAPE GetShape() const
Definition: sch_text.h:118
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:120
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:258
virtual bool CanIncrementLabel() const override
Definition: sch_text.h:185
SCH_TEXT * CreateNewText(int aType)
Definition: edit_label.cpp:68
virtual bool IsDangling() const override
Definition: sch_text.h:177
bool IsItalic() const
Definition: eda_text.h:183
This file is part of the common library.
bool IsNew() const
Definition: base_struct.h:219
static int lastTextOrientation
Definition: edit_label.cpp:45
void OnModify()
Must be called after a schematic change in order to set the "modify" flag of the current screen* and ...
void SetStatus(UNDO_REDO_T aStatus)
static PINSHEETLABEL_SHAPE lastGlobalLabelShape
Definition: edit_label.cpp:44
virtual void SetLabelSpinStyle(int aSpinStyle)
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:240
void OnConvertTextType(wxCommandEvent &aEvent)
Command event handler to change a text type to another one.
Definition: edit_label.cpp:135
void ChangeTextOrient(SCH_TEXT *aTextItem)
Definition: edit_label.cpp:50
void SetItalic(bool isItalic)
Definition: eda_text.h:182
void RemoveFromScreen(SCH_ITEM *aItem)
Remove an item from the screen (and view)
int GetLabelSpinStyle() const
Definition: sch_text.h:116
void PushItem(const ITEM_PICKER &aItem)
Function PushItem pushes aItem to the top of the list.
SCH_ITEM * GetUndoItem() const
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:227
static bool lastTextItalic
Definition: edit_label.cpp:47
void SetLink(EDA_ITEM *aItem)
SCH_ITEM * Next() const
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
bool IsBold() const
Definition: eda_text.h:186
void SetRepeatItem(SCH_ITEM *aItem)
Clone aItem and owns that clone in this container.
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:167
#define IS_NEW
New item, just created.
Definition: base_struct.h:114
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
a helper to handle the real device context used in KiCad
void PrepareMoveItem(SCH_ITEM *aItem)
Start moving aItem using the mouse.
Definition: schedit.cpp:762
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:256
SCH_ITEM * GetCurItem() const
Return the currently selected SCH_ITEM, overriding BASE_SCREEN::GetCurItem().
Definition: sch_screen.h:196
virtual void CrossHairOn(wxDC *DC=nullptr)
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
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.
virtual void CrossHairOff(wxDC *DC=nullptr)
void EditSchematicText(SCH_TEXT *TextStruct)
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
void SetItem(EDA_ITEM *aItem)
virtual wxPoint GetPosition() const override
Function GetPosition.
Definition: sch_text.h:194
void AddToScreen(SCH_ITEM *aItem)
Add an item to the screen (and view)
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:123
SCH_ITEM * GetDrawItems() const
Definition: sch_screen.h:160
PINSHEETLABEL_SHAPE
Definition: sch_text.h:46
const char * name
Definition: DXF_plotter.cpp:61
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void RefreshItem(SCH_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
void SetCurItem(SCH_ITEM *aItem)
Sets the currently selected object, m_CurrentItem.
Definition: sch_screen.h:204
const wxSize & GetTextSize() const
Definition: eda_text.h:228
void SetUndoItem(const SCH_ITEM *aItem)
Clone aItem which can be used to restore the state of the item being edited when the user cancels the...
Basic classes for most KiCad items.
static bool lastTextBold
Definition: edit_label.cpp:46
void IncrementLabelMember(wxString &name, int aIncrement)
Definition: edit_label.cpp:286
void SetBold(bool aBold)
Definition: eda_text.h:185
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:245
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Return the current cross hair position in logical (drawing) coordinates.
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Implementation of the label properties dialog.
void SetThickness(int aNewThickness)
Function SetThickness sets pen width.
Definition: eda_text.h:161
int GetDefaultTextSize()
Default size for text in general.
#define IS_MOVED
Item being moved.
Definition: base_struct.h:113