You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

306 lines
9.1 KiB

15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
  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. /**
  25. * @file edit_label.cpp
  26. * @brief Label, global label and text creation and editing.
  27. */
  28. #include <fctsys.h>
  29. #include <gr_basic.h>
  30. #include <base_struct.h>
  31. #include <draw_graphic_text.h>
  32. #include <sch_draw_panel.h>
  33. #include <confirm.h>
  34. #include <sch_edit_frame.h>
  35. #include <kicad_device_context.h>
  36. #include <general.h>
  37. #include <sch_text.h>
  38. #include <eeschema_id.h>
  39. static PINSHEETLABEL_SHAPE lastGlobalLabelShape = NET_INPUT;
  40. static int lastTextOrientation = 0;
  41. static bool lastTextBold = false;
  42. static bool lastTextItalic = false;
  43. void SCH_EDIT_FRAME::ChangeTextOrient( SCH_TEXT* aTextItem )
  44. {
  45. wxCHECK_RET( (aTextItem != NULL) && aTextItem->CanIncrementLabel(),
  46. wxT( "Invalid schematic text item." ) );
  47. int orient = ( aTextItem->GetLabelSpinStyle() + 1 ) & 3;
  48. // Save current text orientation in undo list if is not already in edit.
  49. if( aTextItem->GetEditFlags() == 0 )
  50. SaveCopyInUndoList( aTextItem, UR_CHANGED );
  51. aTextItem->SetLabelSpinStyle( orient );
  52. RefreshItem( aTextItem );
  53. OnModify();
  54. }
  55. SCH_TEXT* SCH_EDIT_FRAME::CreateNewText( int aType )
  56. {
  57. SCH_TEXT* textItem = NULL;
  58. SetRepeatItem( NULL );
  59. switch( aType )
  60. {
  61. case LAYER_NOTES:
  62. textItem = new SCH_TEXT( GetCrossHairPosition() );
  63. break;
  64. case LAYER_LOCLABEL:
  65. textItem = new SCH_LABEL( GetCrossHairPosition() );
  66. break;
  67. case LAYER_HIERLABEL:
  68. textItem = new SCH_HIERLABEL( GetCrossHairPosition() );
  69. textItem->SetShape( lastGlobalLabelShape );
  70. break;
  71. case LAYER_GLOBLABEL:
  72. textItem = new SCH_GLOBALLABEL( GetCrossHairPosition() );
  73. textItem->SetShape( lastGlobalLabelShape );
  74. break;
  75. default:
  76. DisplayError( this, wxT( "SCH_EDIT_FRAME::CreateNewText() Internal error" ) );
  77. return NULL;
  78. }
  79. textItem->SetBold( lastTextBold );
  80. textItem->SetItalic( lastTextItalic );
  81. textItem->SetLabelSpinStyle( lastTextOrientation );
  82. textItem->SetTextSize( wxSize( GetDefaultTextSize(), GetDefaultTextSize() ) );
  83. textItem->SetFlags( IS_NEW | IS_MOVED );
  84. EditSchematicText( textItem );
  85. if( textItem->GetText().IsEmpty() )
  86. {
  87. delete textItem;
  88. return NULL;
  89. }
  90. lastTextBold = textItem->IsBold();
  91. lastTextItalic = textItem->IsItalic();
  92. lastTextOrientation = textItem->GetLabelSpinStyle();
  93. if( textItem->Type() == SCH_GLOBAL_LABEL_T || textItem->Type() == SCH_HIER_LABEL_T )
  94. lastGlobalLabelShape = textItem->GetShape();
  95. return textItem;
  96. }
  97. /*
  98. * OnConvertTextType is a command event handler to change a text type to another one.
  99. * The new text, label, hierarchical label, or global label is created from the old text
  100. * The old text is deleted.
  101. * A tricky case is when the 'old" text is being edited (i.e. moving)
  102. * because we must create a new text, and prepare the undo/redo command data for this
  103. * change and the current move/edit command
  104. */
  105. void SCH_EDIT_FRAME::OnConvertTextType( wxCommandEvent& aEvent )
  106. {
  107. SCH_SCREEN* screen = GetScreen();
  108. SCH_TEXT* text = (SCH_TEXT*) screen->GetCurItem();
  109. wxCHECK_RET( (text != NULL) && text->CanIncrementLabel(), "Cannot convert text type." );
  110. KICAD_T type;
  111. switch( aEvent.GetId() )
  112. {
  113. case ID_POPUP_SCH_CHANGE_TYPE_TEXT_TO_LABEL:
  114. type = SCH_LABEL_T;
  115. break;
  116. case ID_POPUP_SCH_CHANGE_TYPE_TEXT_TO_GLABEL:
  117. type = SCH_GLOBAL_LABEL_T;
  118. break;
  119. case ID_POPUP_SCH_CHANGE_TYPE_TEXT_TO_HLABEL:
  120. type = SCH_HIER_LABEL_T;
  121. break;
  122. case ID_POPUP_SCH_CHANGE_TYPE_TEXT_TO_COMMENT:
  123. type = SCH_TEXT_T;
  124. break;
  125. default:
  126. wxFAIL_MSG( wxString::Format( "Invalid text type command ID %d.", aEvent.GetId() ) );
  127. return;
  128. }
  129. if( text->Type() == type )
  130. return;
  131. SCH_TEXT* newtext = nullptr;
  132. const wxPoint& position = text->GetPosition();
  133. const wxString txt = text->GetText();
  134. switch( type )
  135. {
  136. case SCH_LABEL_T:
  137. newtext = new SCH_LABEL( position, txt );
  138. break;
  139. case SCH_GLOBAL_LABEL_T:
  140. newtext = new SCH_GLOBALLABEL( position, txt );
  141. break;
  142. case SCH_HIER_LABEL_T:
  143. newtext = new SCH_HIERLABEL( position, txt );
  144. break;
  145. case SCH_TEXT_T:
  146. newtext = new SCH_TEXT( position, txt );
  147. break;
  148. default:
  149. wxASSERT_MSG( false, wxString::Format( "Invalid text type: %d.", type ) );
  150. return;
  151. }
  152. /* Copy the old text item settings to the new one. Justifications are not copied because
  153. * they are not used in labels. Justifications will be set to default value in the new
  154. * text item type.
  155. */
  156. newtext->SetFlags( text->GetFlags() );
  157. newtext->SetShape( text->GetShape() );
  158. newtext->SetLabelSpinStyle( text->GetLabelSpinStyle() );
  159. newtext->SetTextSize( text->GetTextSize() );
  160. newtext->SetThickness( text->GetThickness() );
  161. newtext->SetItalic( text->IsItalic() );
  162. newtext->SetBold( text->IsBold() );
  163. newtext->SetIsDangling( text->IsDangling() );
  164. /* Save the new text in undo list if the old text was not itself a "new created text"
  165. * In this case, the old text is already in undo list as a deleted item.
  166. * Of course if the old text was a "new created text" the new text will be
  167. * put in undo list later, at the end of the current command (if not aborted)
  168. */
  169. m_canvas->CrossHairOff(); // Erase schematic cursor
  170. // For an exiting item (i.e. already in list):
  171. // replace the existing item by the new text in list
  172. for( SCH_ITEM* item = screen->GetDrawItems(); item != NULL; item = item->Next() )
  173. {
  174. if( item == text )
  175. {
  176. RemoveFromScreen( text );
  177. AddToScreen( newtext );
  178. break;
  179. }
  180. }
  181. SetRepeatItem( NULL );
  182. OnModify();
  183. m_canvas->CrossHairOn( ); // redraw schematic cursor
  184. // if the old item is the current schematic item, replace it by the new text:
  185. if( screen->GetCurItem() == text )
  186. screen->SetCurItem( newtext );
  187. if( text->IsNew() )
  188. {
  189. // if the previous text is new, no undo command to prepare here
  190. // just delete this previous text.
  191. delete text;
  192. return;
  193. }
  194. // previous text is not new and we replace text by new text.
  195. // So this is equivalent to delete text and add newtext
  196. // If text if being currently edited (i.e. moved)
  197. // we also save the initial copy of text, and prepare undo command for new text modifications.
  198. // we must save it as modified text,if it is currently edited, then save as deleted text,
  199. // and replace text with newtext
  200. PICKED_ITEMS_LIST pickList;
  201. ITEM_PICKER picker( text, UR_CHANGED );
  202. if( text->GetEditFlags() )
  203. {
  204. // text is being edited, save initial text for undo command
  205. picker.SetLink( GetUndoItem() );
  206. pickList.PushItem( picker );
  207. // the owner of undoItem is no more "this", it is now "picker":
  208. SetUndoItem( NULL );
  209. // save current newtext copy for undo/abort current command
  210. SetUndoItem( newtext );
  211. }
  212. // Prepare undo command for delete old text
  213. picker.SetStatus( UR_DELETED );
  214. picker.SetLink( NULL );
  215. pickList.PushItem( picker );
  216. // Prepare undo command for new text
  217. picker.SetStatus( UR_NEW );
  218. picker.SetItem(newtext);
  219. pickList.PushItem( picker );
  220. SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
  221. }
  222. /* Function to increment bus label members numbers,
  223. * i.e. when a text is ending with a number, adds
  224. * aIncrement to this number
  225. */
  226. void IncrementLabelMember( wxString& name, int aIncrement )
  227. {
  228. int ii, nn;
  229. long number = 0;
  230. ii = name.Len() - 1; nn = 0;
  231. if( !wxIsdigit( name.GetChar( ii ) ) )
  232. return;
  233. while( (ii >= 0) && wxIsdigit( name.GetChar( ii ) ) )
  234. {
  235. ii--; nn++;
  236. }
  237. ii++; /* digits are starting at ii position */
  238. wxString litt_number = name.Right( nn );
  239. if( litt_number.ToLong( &number ) )
  240. {
  241. number += aIncrement;
  242. name.Remove( ii ); name << number;
  243. }
  244. }