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.

268 lines
7.0 KiB

11 years ago
11 years ago
11 years ago
11 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2014-2015 CERN
  5. * Author: Maciej Suminski <maciej.suminski@cern.ch>
  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. #include <wx/stattext.h>
  25. #include <wx/textentry.h>
  26. #include <limits>
  27. #include <base_units.h>
  28. #include <draw_frame.h>
  29. #include <confirm.h>
  30. #include "widgets/unit_binder.h"
  31. wxDEFINE_EVENT( DELAY_FOCUS, wxCommandEvent );
  32. UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent,
  33. wxStaticText* aLabel, wxWindow* aValue, wxStaticText* aUnitLabel,
  34. bool aUseMils, bool allowEval ) :
  35. m_label( aLabel ),
  36. m_value( aValue ),
  37. m_unitLabel( aUnitLabel ),
  38. m_eval( aParent->GetUserUnits(), aUseMils )
  39. {
  40. // Fix the units (to the current units) for the life of the binder
  41. m_units = aParent->GetUserUnits();
  42. m_useMils = aUseMils;
  43. m_allowEval = allowEval && dynamic_cast<wxTextEntry*>( m_value );
  44. m_needsEval = false;
  45. auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
  46. if( textEntry )
  47. {
  48. // Use ChangeValue() instead of SetValue() so we don't generate events.
  49. textEntry->ChangeValue( wxT( "0" ) );
  50. }
  51. m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_useMils ) );
  52. m_value->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), NULL, this );
  53. m_value->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), NULL, this );
  54. Connect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), NULL, this );
  55. }
  56. void UNIT_BINDER::SetUnits( EDA_UNITS_T aUnits, bool aUseMils )
  57. {
  58. m_units = aUnits;
  59. m_useMils = aUseMils;
  60. m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_useMils ) );
  61. }
  62. void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
  63. {
  64. auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
  65. if( m_allowEval && textEntry )
  66. {
  67. wxString oldStr = m_eval.OriginalText();
  68. if( oldStr.length() )
  69. textEntry->SetValue( oldStr );
  70. m_needsEval = true;
  71. }
  72. aEvent.Skip();
  73. }
  74. void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
  75. {
  76. auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
  77. if( m_allowEval && textEntry )
  78. {
  79. if( m_eval.Process( textEntry->GetValue() ) )
  80. textEntry->ChangeValue( m_eval.Result() );
  81. m_needsEval = false;
  82. }
  83. aEvent.Skip();
  84. }
  85. wxString valueDescriptionFromLabel( wxStaticText* aLabel )
  86. {
  87. wxString desc = aLabel->GetLabel();
  88. desc.EndsWith( wxT( ":" ), &desc );
  89. return desc;
  90. }
  91. void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
  92. {
  93. if( !m_errorMessage.IsEmpty() )
  94. DisplayError( m_value->GetParent(), m_errorMessage );
  95. m_errorMessage = wxEmptyString;
  96. m_value->SetFocus();
  97. }
  98. bool UNIT_BINDER::Validate( int aMin, int aMax, bool setFocusOnError )
  99. {
  100. auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
  101. if( !textEntry || textEntry->GetValue() == INDETERMINATE )
  102. return true;
  103. if( GetValue() < aMin )
  104. {
  105. m_errorMessage = wxString::Format( _( "%s must be at least %s." ),
  106. valueDescriptionFromLabel( m_label ),
  107. StringFromValue( m_units, aMin, true ) );
  108. if( setFocusOnError )
  109. {
  110. textEntry->SelectAll();
  111. // Don't focus directly; we might be inside a KillFocus event handler
  112. wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
  113. }
  114. return false;
  115. }
  116. if( GetValue() > aMax )
  117. {
  118. m_errorMessage = wxString::Format( _( "%s must be less than %s." ),
  119. valueDescriptionFromLabel( m_label ),
  120. StringFromValue( m_units, aMax, true ) );
  121. if( setFocusOnError )
  122. {
  123. textEntry->SelectAll();
  124. // Don't focus directly; we might be inside a KillFocus event handler
  125. wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
  126. }
  127. return false;
  128. }
  129. return true;
  130. }
  131. void UNIT_BINDER::SetValue( int aValue )
  132. {
  133. SetValue( StringFromValue( m_units, aValue, false, m_useMils ) );
  134. }
  135. void UNIT_BINDER::SetValue( wxString aValue )
  136. {
  137. auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
  138. auto staticText = dynamic_cast<wxStaticText*>( m_value );
  139. if( textEntry )
  140. textEntry->SetValue( aValue );
  141. else if( staticText )
  142. staticText->SetLabel( aValue );
  143. if( m_allowEval )
  144. m_eval.Clear();
  145. m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_useMils ) );
  146. }
  147. void UNIT_BINDER::ChangeValue( int aValue )
  148. {
  149. ChangeValue( StringFromValue( m_units, aValue, false, m_useMils ) );
  150. }
  151. void UNIT_BINDER::ChangeValue( wxString aValue )
  152. {
  153. auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
  154. auto staticText = dynamic_cast<wxStaticText*>( m_value );
  155. if( textEntry )
  156. textEntry->ChangeValue( aValue );
  157. else if( staticText )
  158. staticText->SetLabel( aValue );
  159. if( m_allowEval )
  160. m_eval.Clear();
  161. m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_useMils ) );
  162. }
  163. int UNIT_BINDER::GetValue()
  164. {
  165. auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
  166. auto staticText = dynamic_cast<wxStaticText*>( m_value );
  167. wxString value;
  168. if( textEntry )
  169. {
  170. if( m_needsEval && m_eval.Process( textEntry->GetValue() ) )
  171. value = m_eval.Result();
  172. else
  173. value = textEntry->GetValue();
  174. }
  175. else if( staticText )
  176. value = staticText->GetLabel();
  177. else
  178. return 0;
  179. return ValueFromString( m_units, value, m_useMils );
  180. }
  181. bool UNIT_BINDER::IsIndeterminate() const
  182. {
  183. auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
  184. if( textEntry )
  185. return textEntry->GetValue() == INDETERMINATE;
  186. return false;
  187. }
  188. void UNIT_BINDER::SetLabel( const wxString& aLabel )
  189. {
  190. m_label->SetLabel( aLabel );
  191. }
  192. void UNIT_BINDER::Enable( bool aEnable )
  193. {
  194. m_label->Enable( aEnable );
  195. m_value->Enable( aEnable );
  196. m_unitLabel->Enable( aEnable );
  197. }
  198. void UNIT_BINDER::Show( bool aShow )
  199. {
  200. m_label->Show( aShow );
  201. m_value->Show( aShow );
  202. m_unitLabel->Show( aShow );
  203. }