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.

228 lines
6.2 KiB

3 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013-2023 CERN
  5. * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
  6. * @author Maciej Suminski <maciej.suminski@cern.ch>
  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. #include <optional>
  26. #include <tool/tool_action.h>
  27. #include <tool/tool_event.h>
  28. #include <tool/action_manager.h>
  29. #include <algorithm>
  30. #include <bitmaps.h>
  31. #include <hotkeys_basic.h>
  32. #include <core/wx_stl_compat.h>
  33. #include <wx/string.h>
  34. #include <wx/translation.h>
  35. TOOL_ACTION::TOOL_ACTION( const std::string& aName, TOOL_ACTION_SCOPE aScope,
  36. int aDefaultHotKey, const std::string& aLegacyHotKeyName,
  37. const wxString& aLabel, const wxString& aTooltip,
  38. BITMAPS aIcon, TOOL_ACTION_FLAGS aFlags ) :
  39. m_name( aName ),
  40. m_scope( aScope ),
  41. m_group( std::nullopt ),
  42. m_defaultHotKey( aDefaultHotKey ),
  43. m_defaultHotKeyAlt( 0 ),
  44. m_legacyName( aLegacyHotKeyName ),
  45. m_menuLabel( aLabel ),
  46. m_tooltip( aTooltip ),
  47. m_icon( aIcon ),
  48. m_id( -1 ),
  49. m_flags( aFlags )
  50. {
  51. SetHotKey( aDefaultHotKey );
  52. ACTION_MANAGER::GetActionList().push_back( this );
  53. }
  54. TOOL_ACTION::TOOL_ACTION() :
  55. m_scope( AS_GLOBAL ),
  56. m_group( std::nullopt ),
  57. m_defaultHotKey( 0 ),
  58. m_defaultHotKeyAlt( 0 ),
  59. m_icon( BITMAPS::INVALID_BITMAP ),
  60. m_id( -1 ),
  61. m_flags( AF_NONE )
  62. {
  63. SetHotKey( 0 );
  64. }
  65. TOOL_ACTION::TOOL_ACTION( const TOOL_ACTION_ARGS& aArgs ) :
  66. m_name( aArgs.m_name.value_or( "" ) ),
  67. m_scope( aArgs.m_scope.value_or( AS_CONTEXT ) ),
  68. m_defaultHotKey( aArgs.m_defaultHotKey.value_or( 0 ) ),
  69. m_defaultHotKeyAlt( aArgs.m_defaultHotKeyAlt.value_or( 0 ) ),
  70. m_hotKey( aArgs.m_defaultHotKey.value_or( 0 ) ),
  71. m_hotKeyAlt( 0 ),
  72. m_legacyName( aArgs.m_legacyName.value_or( "" ) ),
  73. m_friendlyName( TowxString( aArgs.m_friendlyName.value_or( "" ) ) ),
  74. m_tooltip( TowxString( aArgs.m_tooltip.value_or( "" ) ) ),
  75. m_icon( aArgs.m_icon.value_or( BITMAPS::INVALID_BITMAP) ),
  76. m_id( -1 ),
  77. m_uiid( std::nullopt ),
  78. m_flags( aArgs.m_flags.value_or( AF_NONE ) )
  79. {
  80. // Action name is the only mandatory part
  81. assert( !m_name.empty() );
  82. if( aArgs.m_menuText.has_value() )
  83. m_menuLabel = TowxString( aArgs.m_menuText.value() );
  84. if( aArgs.m_uiid.has_value() )
  85. m_uiid = aArgs.m_uiid.value();
  86. if( aArgs.m_param.has_value() )
  87. m_param = aArgs.m_param;
  88. if( aArgs.m_description.has_value() )
  89. m_description = TowxString( aArgs.m_description.value() );
  90. if( aArgs.m_group.has_value() )
  91. m_group = aArgs.m_group;
  92. ACTION_MANAGER::GetActionList().push_back( this );
  93. }
  94. TOOL_ACTION::~TOOL_ACTION()
  95. {
  96. ACTION_MANAGER::GetActionList().remove( this );
  97. }
  98. TOOL_EVENT TOOL_ACTION::MakeEvent() const
  99. {
  100. TOOL_EVENT evt;
  101. if( IsActivation() )
  102. evt = TOOL_EVENT( TC_COMMAND, TA_ACTIVATE, m_name, m_scope );
  103. else if( IsNotification() )
  104. evt = TOOL_EVENT( TC_MESSAGE, TA_NONE, m_name, m_scope );
  105. else
  106. evt = TOOL_EVENT( TC_COMMAND, TA_ACTION, m_name, m_scope );
  107. if( m_group.has_value() )
  108. {
  109. evt.SetActionGroup( m_group.value() );
  110. }
  111. if( m_param.has_value() )
  112. evt.SetParameter( m_param );
  113. return evt;
  114. }
  115. wxString TOOL_ACTION::GetFriendlyName() const
  116. {
  117. if( m_friendlyName.empty() )
  118. return wxEmptyString;
  119. return wxGetTranslation( m_friendlyName );
  120. }
  121. wxString TOOL_ACTION::GetMenuLabel() const
  122. {
  123. if( m_menuLabel.has_value() )
  124. return wxGetTranslation( m_menuLabel.value() );
  125. return GetFriendlyName();
  126. }
  127. wxString TOOL_ACTION::GetMenuItem() const
  128. {
  129. wxString label = GetMenuLabel();
  130. label.Replace( wxS( "&" ), wxS( "&&" ) );
  131. return AddHotkeyName( label, m_hotKey, IS_HOTKEY );
  132. }
  133. wxString TOOL_ACTION::GetDescription() const
  134. {
  135. // If no description provided, use the tooltip without a hotkey
  136. if( !m_description.has_value() )
  137. return GetTooltip( false );
  138. return wxGetTranslation( m_description.value() );
  139. }
  140. wxString TOOL_ACTION::GetTooltip( bool aIncludeHotkey ) const
  141. {
  142. wxString tooltip = wxGetTranslation( m_tooltip );
  143. if( aIncludeHotkey && GetHotKey() )
  144. tooltip += wxString::Format( wxT( " (%s)" ), KeyNameFromKeyCode( GetHotKey() ) );
  145. return tooltip;
  146. }
  147. wxString TOOL_ACTION::GetButtonTooltip() const
  148. {
  149. // We don't show button text so use the action name as the first line of the tooltip
  150. wxString tooltip = GetFriendlyName();
  151. if( GetHotKey() )
  152. tooltip += wxString::Format( wxT( " (%s)" ), KeyNameFromKeyCode( GetHotKey() ) );
  153. if( !GetTooltip( false ).IsEmpty() )
  154. tooltip += '\n' + GetTooltip( false );
  155. return tooltip;
  156. }
  157. void TOOL_ACTION::SetHotKey( int aKeycode, int aKeycodeAlt )
  158. {
  159. m_hotKey = aKeycode;
  160. m_hotKeyAlt = aKeycodeAlt;
  161. }
  162. std::string TOOL_ACTION::GetToolName() const
  163. {
  164. int dotCount = std::count( m_name.begin(), m_name.end(), '.' );
  165. switch( dotCount )
  166. {
  167. case 0:
  168. assert( false ); // Invalid action name format
  169. return "";
  170. case 1:
  171. return m_name;
  172. case 2:
  173. return m_name.substr( 0, m_name.rfind( '.' ) );
  174. default:
  175. assert( false ); // TODO not implemented
  176. return "";
  177. }
  178. }