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.

177 lines
5.4 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
  5. * @author Jon Evans <jon@craftyjon.com>
  6. *
  7. * This program is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation, either version 3 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <string_utils.h>
  21. #include <wx/stc/stc.h>
  22. #include <widgets/grid_text_helpers.h>
  23. #include <scintilla_tricks.h>
  24. //-------- GRID_CELL_ESCAPED_TEXT_RENDERER ------------------------------------------------------
  25. //
  26. GRID_CELL_ESCAPED_TEXT_RENDERER::GRID_CELL_ESCAPED_TEXT_RENDERER() :
  27. wxGridCellStringRenderer()
  28. {
  29. }
  30. void GRID_CELL_ESCAPED_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC,
  31. const wxRect& aRect, int aRow, int aCol,
  32. bool isSelected )
  33. {
  34. wxString unescaped = UnescapeString( aGrid.GetCellValue( aRow, aCol ) );
  35. wxRect rect = aRect;
  36. rect.Inflate( -1 );
  37. // erase background
  38. wxGridCellRenderer::Draw( aGrid, aAttr, aDC, aRect, aRow, aCol, isSelected );
  39. SetTextColoursAndFont( aGrid, aAttr, aDC, isSelected );
  40. aGrid.DrawTextRectangle( aDC, unescaped, rect, wxALIGN_LEFT, wxALIGN_CENTRE );
  41. }
  42. wxSize GRID_CELL_ESCAPED_TEXT_RENDERER::GetBestSize( wxGrid & aGrid, wxGridCellAttr & aAttr,
  43. wxDC & aDC, int aRow, int aCol )
  44. {
  45. wxString unescaped = UnescapeString( aGrid.GetCellValue( aRow, aCol ) );
  46. return wxGridCellStringRenderer::DoGetBestSize( aAttr, aDC, unescaped );
  47. }
  48. //-------- GRID_CELL_STC_EDITOR -----------------------------------------------------------------
  49. //
  50. GRID_CELL_STC_EDITOR::GRID_CELL_STC_EDITOR( bool aIgnoreCase,
  51. std::function<void( wxStyledTextEvent&,
  52. SCINTILLA_TRICKS* )> aOnChar ) :
  53. m_scintillaTricks( nullptr ),
  54. m_ignoreCase( aIgnoreCase ),
  55. m_onChar( aOnChar )
  56. { }
  57. void GRID_CELL_STC_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler )
  58. {
  59. m_control = new wxStyledTextCtrl( aParent );
  60. stc_ctrl()->SetTabIndents( false );
  61. stc_ctrl()->SetBackSpaceUnIndents( false );
  62. stc_ctrl()->SetViewEOL( false );
  63. stc_ctrl()->SetViewWhiteSpace( false );
  64. stc_ctrl()->SetIndentationGuides( false );
  65. stc_ctrl()->SetMarginWidth( 0, 0 ); // Symbol margin
  66. stc_ctrl()->SetMarginWidth( 1, 0 ); // Line-number margin
  67. stc_ctrl()->SetEOLMode( wxSTC_EOL_LF );
  68. stc_ctrl()->AutoCompSetMaxWidth( 25 );
  69. stc_ctrl()->AutoCompSetIgnoreCase( m_ignoreCase );
  70. stc_ctrl()->UsePopUp( 0 );
  71. // A hack which causes Scintilla to auto-size the text editor canvas
  72. // See: https://github.com/jacobslusser/ScintillaNET/issues/216
  73. stc_ctrl()->SetScrollWidth( 1 );
  74. stc_ctrl()->SetScrollWidthTracking( true );
  75. m_scintillaTricks = new SCINTILLA_TRICKS(
  76. stc_ctrl(), wxEmptyString, true,
  77. // onAccept handler
  78. [this]( wxKeyEvent& aEvent )
  79. {
  80. HandleReturn( aEvent );
  81. },
  82. // onCharAdded handler
  83. [this]( wxStyledTextEvent& aEvent )
  84. {
  85. m_onChar( aEvent, m_scintillaTricks );
  86. } );
  87. stc_ctrl()->Bind( wxEVT_KILL_FOCUS, &GRID_CELL_STC_EDITOR::onFocusLoss, this );
  88. wxGridCellEditor::Create( aParent, aId, aEventHandler );
  89. }
  90. wxStyledTextCtrl* GRID_CELL_STC_EDITOR::stc_ctrl() const
  91. {
  92. return static_cast<wxStyledTextCtrl*>( m_control );
  93. }
  94. wxString GRID_CELL_STC_EDITOR::GetValue() const
  95. {
  96. return stc_ctrl()->GetText();
  97. }
  98. void GRID_CELL_STC_EDITOR::Show( bool aShow, wxGridCellAttr* aAttr )
  99. {
  100. if( !aShow )
  101. stc_ctrl()->AutoCompCancel();
  102. wxGridCellEditor::Show( aShow, aAttr );
  103. }
  104. void GRID_CELL_STC_EDITOR::BeginEdit( int aRow, int aCol, wxGrid* aGrid )
  105. {
  106. auto evtHandler = static_cast<wxGridCellEditorEvtHandler*>( m_control->GetEventHandler()
  107. );
  108. // Don't immediately end if we get a kill focus event within BeginEdit
  109. evtHandler->SetInSetFocus( true );
  110. m_value = aGrid->GetTable()->GetValue( aRow, aCol );
  111. stc_ctrl()->SetFocus();
  112. stc_ctrl()->SetText( m_value );
  113. stc_ctrl()->SelectAll();
  114. }
  115. bool GRID_CELL_STC_EDITOR::EndEdit( int, int, const wxGrid*, const wxString&, wxString *aNewVal )
  116. {
  117. const wxString value = stc_ctrl()->GetText();
  118. if( value == m_value )
  119. return false;
  120. m_value = value;
  121. if( aNewVal )
  122. *aNewVal = value;
  123. return true;
  124. }
  125. void GRID_CELL_STC_EDITOR::ApplyEdit( int aRow, int aCol, wxGrid* aGrid )
  126. {
  127. aGrid->GetTable()->SetValue( aRow, aCol, m_value );
  128. }
  129. void GRID_CELL_STC_EDITOR::onFocusLoss( wxFocusEvent& aEvent )
  130. {
  131. if( stc_ctrl() )
  132. stc_ctrl()->AutoCompCancel();
  133. aEvent.Skip();
  134. }