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.

318 lines
9.7 KiB

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