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.

284 lines
8.1 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
  5. * Copyright (C) 2004-2013 KiCad Developers, see change_log.txt for contributors.
  6. * Copyright (C) 2018 CERN
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. /**
  26. * @file validators.cpp
  27. * @brief Custom text control validator implementations.
  28. */
  29. #include <kicad_string.h>
  30. #include <confirm.h>
  31. #include <validators.h>
  32. #include <wx/grid.h>
  33. #include <wx/textctrl.h>
  34. #include <wx/textentry.h>
  35. #include <wx/log.h>
  36. GRID_CELL_TEXT_EDITOR::GRID_CELL_TEXT_EDITOR() : wxGridCellTextEditor()
  37. {
  38. }
  39. void GRID_CELL_TEXT_EDITOR::SetValidator( const wxValidator& validator )
  40. {
  41. // keep our own copy because wxGridCellTextEditor's is annoyingly private
  42. m_validator.reset( static_cast<wxValidator*>( validator.Clone() ) );
  43. wxGridCellTextEditor::SetValidator( *m_validator );
  44. }
  45. void GRID_CELL_TEXT_EDITOR::StartingKey( wxKeyEvent& event )
  46. {
  47. if( m_validator )
  48. {
  49. m_validator.get()->SetWindow( Text() );
  50. m_validator.get()->ProcessEvent( event );
  51. }
  52. if( event.GetSkipped() )
  53. {
  54. wxGridCellTextEditor::StartingKey( event );
  55. event.Skip( false );
  56. }
  57. }
  58. FILE_NAME_CHAR_VALIDATOR::FILE_NAME_CHAR_VALIDATOR( wxString* aValue ) :
  59. wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST, aValue )
  60. {
  61. // The Windows (DOS) file system forbidden characters already include the forbidden
  62. // file name characters for both Posix and OSX systems. The characters \/:*?|"<> are
  63. // illegal and filtered by the validator.
  64. wxString illegalChars = wxFileName::GetForbiddenChars( wxPATH_DOS );
  65. wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
  66. wxArrayString illegalCharList;
  67. for( unsigned i = 0; i < illegalChars.size(); i++ )
  68. illegalCharList.Add( wxString( illegalChars[i] ) );
  69. SetExcludes( illegalCharList );
  70. }
  71. FILE_NAME_WITH_PATH_CHAR_VALIDATOR::FILE_NAME_WITH_PATH_CHAR_VALIDATOR( wxString* aValue ) :
  72. wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST | wxFILTER_EMPTY, aValue )
  73. {
  74. // The Windows (DOS) file system forbidden characters already include the forbidden
  75. // file name characters for both Posix and OSX systems. The characters *?|"<> are
  76. // illegal and filtered by the validator, but /\: are valid (\ and : only on Windows.
  77. wxString illegalChars = wxFileName::GetForbiddenChars( wxPATH_DOS );
  78. wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
  79. wxArrayString illegalCharList;
  80. for( unsigned i = 0; i < illegalChars.size(); i++ )
  81. {
  82. if( illegalChars[i] == '/' )
  83. continue;
  84. #if defined (__WINDOWS__)
  85. if( illegalChars[i] == '\\' || illegalChars[i] == ':' )
  86. continue;
  87. #endif
  88. illegalCharList.Add( wxString( illegalChars[i] ) );
  89. }
  90. SetExcludes( illegalCharList );
  91. }
  92. ENV_VAR_NAME_VALIDATOR::ENV_VAR_NAME_VALIDATOR( wxString* aValue ) :
  93. wxTextValidator()
  94. {
  95. Connect( wxEVT_CHAR, wxKeyEventHandler( ENV_VAR_NAME_VALIDATOR::OnChar ) );
  96. }
  97. ENV_VAR_NAME_VALIDATOR::ENV_VAR_NAME_VALIDATOR( const ENV_VAR_NAME_VALIDATOR& val )
  98. : wxTextValidator()
  99. {
  100. wxValidator::Copy( val );
  101. Connect( wxEVT_CHAR, wxKeyEventHandler( ENV_VAR_NAME_VALIDATOR::OnChar ) );
  102. }
  103. ENV_VAR_NAME_VALIDATOR::~ENV_VAR_NAME_VALIDATOR()
  104. {
  105. Disconnect( wxEVT_CHAR, wxKeyEventHandler( ENV_VAR_NAME_VALIDATOR::OnChar ) );
  106. }
  107. void ENV_VAR_NAME_VALIDATOR::OnChar( wxKeyEvent& aEvent )
  108. {
  109. if (!m_validatorWindow)
  110. {
  111. aEvent.Skip();
  112. return;
  113. }
  114. int keyCode = aEvent.GetKeyCode();
  115. // we don't filter special keys and delete
  116. if (keyCode < WXK_SPACE || keyCode == WXK_DELETE || keyCode >= WXK_START)
  117. {
  118. aEvent.Skip();
  119. return;
  120. }
  121. wxUniChar c = (wxUChar) keyCode;
  122. if( c == wxT( '_' ) )
  123. {
  124. // OK anywhere
  125. aEvent.Skip();
  126. }
  127. else if( wxIsdigit( c ) )
  128. {
  129. // not as first character
  130. long from, to;
  131. GetTextEntry()->GetSelection( &from, &to );
  132. if( from < 1 )
  133. wxBell();
  134. else
  135. aEvent.Skip();
  136. }
  137. else if( wxIsalpha( c ) )
  138. {
  139. // Capitals only.
  140. if( wxIslower( c ) )
  141. {
  142. // You may wonder why this scope is so twisted, so make yourself comfortable and read:
  143. // 1. Changing the keyCode and/or uniChar in the event and passing it on
  144. // doesn't work. Some platforms look at the original copy as long as the event
  145. // isn't vetoed.
  146. // 2. Inserting characters by hand does not move the cursor, meaning either you insert
  147. // text backwards (lp:#1798869) or always append, no matter where is the cursor.
  148. // wxTextEntry::{Get/Set}InsertionPoint() do not work at all here.
  149. // 3. There is wxTextEntry::ForceUpper(), but it is not yet available in common
  150. // wxWidgets packages.
  151. //
  152. // So here we are, with a command event handler that converts
  153. // the text to upper case upon every change.
  154. wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( GetTextEntry() );
  155. if( textCtrl )
  156. {
  157. textCtrl->Connect( textCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED,
  158. (wxObjectEventFunction) &ENV_VAR_NAME_VALIDATOR::OnTextChanged );
  159. }
  160. }
  161. aEvent.Skip();
  162. }
  163. else
  164. {
  165. wxBell();
  166. }
  167. }
  168. void ENV_VAR_NAME_VALIDATOR::OnTextChanged( wxCommandEvent& event )
  169. {
  170. wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( event.GetEventObject() );
  171. if( textCtrl )
  172. {
  173. if( !textCtrl->IsModified() )
  174. return;
  175. long insertionPoint = textCtrl->GetInsertionPoint();
  176. textCtrl->ChangeValue( textCtrl->GetValue().Upper() );
  177. textCtrl->SetInsertionPoint( insertionPoint );
  178. textCtrl->Disconnect( textCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED );
  179. }
  180. event.Skip();
  181. }
  182. bool REGEX_VALIDATOR::Validate( wxWindow* aParent )
  183. {
  184. // If window is disabled, simply return
  185. if( !m_validatorWindow->IsEnabled() )
  186. return true;
  187. wxTextEntry* const textEntry = GetTextEntry();
  188. if( !textEntry )
  189. return false;
  190. bool valid = true;
  191. const wxString& value = textEntry->GetValue();
  192. if( m_regEx.Matches( value ) )
  193. {
  194. size_t start, len;
  195. m_regEx.GetMatch( &start, &len );
  196. if( start != 0 || len != value.Length() ) // whole string must match
  197. valid = false;
  198. }
  199. else // no match at all
  200. {
  201. valid = false;
  202. }
  203. if( !valid )
  204. {
  205. m_validatorWindow->SetFocus();
  206. DisplayError( aParent, wxString::Format( _( "Incorrect value: %s" ), value ) );
  207. return false;
  208. }
  209. return true;
  210. }
  211. void REGEX_VALIDATOR::compileRegEx( const wxString& aRegEx, int aFlags )
  212. {
  213. if( !m_regEx.Compile( aRegEx, aFlags ) )
  214. {
  215. throw std::runtime_error( "REGEX_VALIDATOR: Invalid regular expression: "
  216. + aRegEx.ToStdString() );
  217. }
  218. m_regExString = aRegEx;
  219. m_regExFlags = aFlags;
  220. }
  221. void KIUI::ValidatorTransferToWindowWithoutEvents( wxValidator& aValidator )
  222. {
  223. wxWindow* ctrl = aValidator.GetWindow();
  224. wxCHECK_RET( ctrl != nullptr, "Transferring validator data without a control" );
  225. wxEventBlocker orient_update_blocker( ctrl, wxEVT_ANY );
  226. aValidator.TransferToWindow();
  227. }