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.

304 lines
9.7 KiB

  1. /**
  2. * @file dialog_edit_one_field.cpp
  3. * @brief dialog to editing a field ( not a graphic text) in current component.
  4. */
  5. /*
  6. * This program source code file is part of KiCad, a free EDA CAD application.
  7. *
  8. * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com
  9. * Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
  10. * Copyright (C) 2004-2018 KiCad Developers, see change_log.txt for contributors.
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License
  14. * as published by the Free Software Foundation; either version 2
  15. * of the License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, you may find one here:
  24. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  25. * or you may search the http://www.gnu.org website for the version 2 license,
  26. * or you may write to the Free Software Foundation, Inc.,
  27. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  28. */
  29. #include <fctsys.h>
  30. #include <common.h>
  31. #include <kiway.h>
  32. #include <confirm.h>
  33. #include <sch_base_frame.h>
  34. #include <sch_component.h>
  35. #include <class_libentry.h>
  36. #include <lib_field.h>
  37. #include <sch_component.h>
  38. #include <template_fieldnames.h>
  39. #include <class_library.h>
  40. #include <sch_validators.h>
  41. #include <dialog_edit_one_field.h>
  42. // These should probably moved into some other file as helpers.
  43. EDA_TEXT_HJUSTIFY_T IntToEdaTextHorizJustify( int aHorizJustify )
  44. {
  45. wxASSERT( aHorizJustify >= GR_TEXT_HJUSTIFY_LEFT && aHorizJustify <= GR_TEXT_HJUSTIFY_RIGHT );
  46. if( aHorizJustify > GR_TEXT_HJUSTIFY_RIGHT )
  47. return GR_TEXT_HJUSTIFY_RIGHT;
  48. if( aHorizJustify < GR_TEXT_HJUSTIFY_LEFT )
  49. return GR_TEXT_HJUSTIFY_LEFT;
  50. return (EDA_TEXT_HJUSTIFY_T) aHorizJustify;
  51. }
  52. EDA_TEXT_VJUSTIFY_T IntToEdaTextVertJustify( int aVertJustify )
  53. {
  54. wxASSERT( aVertJustify >= GR_TEXT_VJUSTIFY_TOP && aVertJustify <= GR_TEXT_VJUSTIFY_BOTTOM );
  55. if( aVertJustify > GR_TEXT_VJUSTIFY_BOTTOM )
  56. return GR_TEXT_VJUSTIFY_BOTTOM;
  57. if( aVertJustify < GR_TEXT_VJUSTIFY_TOP )
  58. return GR_TEXT_VJUSTIFY_TOP;
  59. return (EDA_TEXT_VJUSTIFY_T) aVertJustify;
  60. }
  61. DIALOG_EDIT_ONE_FIELD::DIALOG_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxString& aTitle,
  62. const EDA_TEXT* aTextItem ) :
  63. DIALOG_LIB_EDIT_TEXT_BASE( aParent ),
  64. m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits, true, 0 )
  65. {
  66. SetTitle( aTitle );
  67. // The field ID and power status are Initialized in the derived object's ctor.
  68. m_fieldId = VALUE;
  69. m_isPower = false;
  70. m_text = aTextItem->GetText();
  71. m_style = aTextItem->IsItalic() ? 1 : 0;
  72. m_style += aTextItem->IsBold() ? 2 : 0;
  73. m_size = aTextItem->GetTextWidth();
  74. m_orientation = ( aTextItem->GetTextAngle() == TEXT_ANGLE_VERT );
  75. m_verticalJustification = aTextItem->GetVertJustify() + 1;
  76. m_horizontalJustification = aTextItem->GetHorizJustify() + 1;
  77. m_isVisible = aTextItem->IsVisible();
  78. }
  79. void DIALOG_EDIT_ONE_FIELD::init()
  80. {
  81. wxString msg;
  82. SetInitialFocus( m_TextValue );
  83. SCH_BASE_FRAME* parent = GetParent();
  84. m_TextValue->SetValidator( SCH_FIELD_VALIDATOR(
  85. parent->IsType( FRAME_SCH_LIB_EDITOR ),
  86. m_fieldId, &m_text ) );
  87. // Disable options for graphic text editing which are not needed for fields.
  88. m_CommonConvert->Show( false );
  89. m_CommonUnit->Show( false );
  90. // Show the footprint selection dialog if this is the footprint field.
  91. m_TextValueSelectButton->Show( m_fieldId == FOOTPRINT );
  92. // Value fields of power components cannot be modified. This will grey out
  93. // the text box and display an explanation.
  94. if( m_fieldId == VALUE && m_isPower )
  95. {
  96. m_PowerComponentValues->Show( true );
  97. m_TextValue->Enable( false );
  98. }
  99. else
  100. {
  101. m_PowerComponentValues->Show( false );
  102. m_TextValue->Enable( true );
  103. }
  104. m_sdbSizerButtonsOK->SetDefault();
  105. // Now all widgets have the size fixed, call FinishDialogSettings
  106. FinishDialogSettings();
  107. }
  108. void DIALOG_EDIT_ONE_FIELD::OnTextValueSelectButtonClick( wxCommandEvent& aEvent )
  109. {
  110. // pick a footprint using the footprint picker.
  111. wxString fpid = m_TextValue->GetValue();
  112. KIWAY_PLAYER* frame = Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true );
  113. if( frame->ShowModal( &fpid, this ) )
  114. {
  115. m_TextValue->SetValue( fpid );
  116. }
  117. frame->Destroy();
  118. }
  119. bool DIALOG_EDIT_ONE_FIELD::TransferDataToWindow()
  120. {
  121. m_TextValue->SetValue( m_text );
  122. if( m_fieldId == REFERENCE )
  123. {
  124. if( m_text.find_first_of( '?' ) != m_text.npos )
  125. {
  126. m_TextValue->SetSelection( m_text.find_first_of( '?' ), m_text.find_last_of( '?' ) + 1 );
  127. }
  128. else
  129. {
  130. wxString num = m_text;
  131. while( !num.IsEmpty() && ( !isdigit( num.Last() ) || !isdigit( num.GetChar( 0 ) ) ) )
  132. {
  133. if( !isdigit( num.Last() ) )
  134. num.RemoveLast();
  135. if( !isdigit( num.GetChar ( 0 ) ) )
  136. num = num.Right( num.Length() - 1);
  137. }
  138. m_TextValue->SetSelection( m_text.Find( num ), m_text.Find( num ) + num.Length() );
  139. if( num.IsEmpty() )
  140. m_TextValue->SetSelection( -1, -1 );
  141. }
  142. }
  143. else
  144. {
  145. m_TextValue->SetSelection( -1, -1 );
  146. }
  147. m_Orient->SetValue( m_orientation );
  148. m_textSize.SetValue( m_size );
  149. m_TextHJustificationOpt->SetSelection( m_horizontalJustification );
  150. m_TextVJustificationOpt->SetSelection( m_verticalJustification );
  151. m_visible->SetValue( m_isVisible );
  152. m_TextShapeOpt->SetSelection( m_style );
  153. return true;
  154. }
  155. bool DIALOG_EDIT_ONE_FIELD::TransferDataFromWindow()
  156. {
  157. m_text = m_TextValue->GetValue();
  158. // There are lots of specific tests required to validate field text.
  159. if( m_fieldId == REFERENCE )
  160. {
  161. // Test if the reference string is valid:
  162. if( !SCH_COMPONENT::IsReferenceStringValid( m_text ) )
  163. {
  164. DisplayError( this, _( "Illegal reference field value!" ) );
  165. return false;
  166. }
  167. }
  168. m_orientation = m_Orient->GetValue();
  169. m_size = m_textSize.GetValue();
  170. m_horizontalJustification = m_TextHJustificationOpt->GetSelection();
  171. m_verticalJustification = m_TextVJustificationOpt->GetSelection();
  172. m_isVisible = m_visible->GetValue();
  173. m_style = m_TextShapeOpt->GetSelection();
  174. return true;
  175. }
  176. void DIALOG_EDIT_ONE_FIELD::updateText( EDA_TEXT* aText )
  177. {
  178. aText->SetTextSize( wxSize( m_size, m_size ) );
  179. aText->SetVisible( m_isVisible );
  180. aText->SetTextAngle( m_orientation ? TEXT_ANGLE_VERT : TEXT_ANGLE_HORIZ );
  181. aText->SetItalic( (m_style & 1) != 0 );
  182. aText->SetBold( (m_style & 2) != 0 );
  183. aText->SetHorizJustify( IntToEdaTextHorizJustify( m_horizontalJustification - 1 ) );
  184. aText->SetVertJustify( IntToEdaTextVertJustify( m_verticalJustification - 1 ) );
  185. }
  186. DIALOG_LIB_EDIT_ONE_FIELD::DIALOG_LIB_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
  187. const wxString& aTitle,
  188. const LIB_FIELD* aField ) :
  189. DIALOG_EDIT_ONE_FIELD( aParent, aTitle, dynamic_cast< const EDA_TEXT* >( aField ) )
  190. {
  191. m_fieldId = aField->GetId();
  192. // When in the library editor, power components can be renamed.
  193. m_isPower = false;
  194. init();
  195. }
  196. DIALOG_SCH_EDIT_ONE_FIELD::DIALOG_SCH_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
  197. const wxString& aTitle,
  198. const SCH_FIELD* aField ) :
  199. DIALOG_EDIT_ONE_FIELD( aParent, aTitle, dynamic_cast< const EDA_TEXT* >( aField ) )
  200. {
  201. m_fieldId = aField->GetId();
  202. const SCH_COMPONENT* component = (SCH_COMPONENT*) aField->GetParent();
  203. wxASSERT_MSG( component && component->Type() == SCH_COMPONENT_T,
  204. wxT( "Invalid schematic field parent item." ) );
  205. // The library symbol may have been removed so using SCH_COMPONENT::GetPartRef() here
  206. // could result in a segfault. If the library symbol is no longer available, the
  207. // schematic fields can still edit so set the power symbol flag to false. This may not
  208. // be entirely accurate if the power library is missing but it's better then a segfault.
  209. const LIB_PART* part = GetParent()->GetLibPart( component->GetLibId(), true );
  210. m_isPower = ( part ) ? part->IsPower() : false;
  211. init();
  212. }
  213. void DIALOG_SCH_EDIT_ONE_FIELD::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH* aSheetPath )
  214. {
  215. if( aField->GetId() == REFERENCE )
  216. {
  217. wxASSERT( aSheetPath );
  218. SCH_COMPONENT* component = dynamic_cast< SCH_COMPONENT* >( aField->GetParent() );
  219. wxASSERT( component );
  220. if( component )
  221. component->SetRef( aSheetPath, m_text );
  222. }
  223. bool modified = false;
  224. if( ( aField->GetTextAngle() == TEXT_ANGLE_VERT ) != m_orientation )
  225. modified = true;
  226. if( ( aField->GetHorizJustify() != IntToEdaTextHorizJustify( m_horizontalJustification - 1 ) ) )
  227. modified = true;
  228. if( ( aField->GetVertJustify() != IntToEdaTextVertJustify( m_verticalJustification - 1 ) ) )
  229. modified = true;
  230. aField->SetText( m_text );
  231. updateText( aField );
  232. if( modified )
  233. {
  234. auto component = static_cast< SCH_COMPONENT* >( aField->GetParent() );
  235. component->ClearFieldsAutoplaced();
  236. }
  237. }