KiCad PCB EDA Suite
action_menu.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013-2019 CERN
5  * Copyright (C) 2013-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  * @author Maciej Suminski <maciej.suminski@cern.ch>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <eda_base_frame.h>
28 #include <functional>
29 #include <id.h>
30 #include <kiface_i.h>
31 #include <menus_helpers.h>
32 #include <tool/action_menu.h>
33 #include <tool/actions.h>
34 #include <tool/tool_event.h>
35 #include <tool/tool_interactive.h>
36 #include <tool/tool_manager.h>
37 #include <trace_helpers.h>
38 #include <wx/log.h>
39 #include <wx/stc/stc.h>
40 #include <textentry_tricks.h>
41 #include <wx/listctrl.h>
42 
43 using namespace std::placeholders;
44 
45 
46 ACTION_MENU::ACTION_MENU( bool isContextMenu, TOOL_INTERACTIVE* aTool ) :
47  m_dirty( true ),
48  m_titleDisplayed( false ),
49  m_isContextMenu( isContextMenu ),
50  m_icon( nullptr ),
51  m_selected( -1 ),
52  m_tool( aTool )
53 {
54  setupEvents();
55 }
56 
57 
59 {
60  // Set parent to NULL to prevent submenus from unregistering from a notexisting object
61  for( auto menu : m_submenus )
62  menu->SetParent( nullptr );
63 
64  ACTION_MENU* parent = dynamic_cast<ACTION_MENU*>( GetParent() );
65 
66  if( parent )
67  parent->m_submenus.remove( this );
68 }
69 
70 
71 void ACTION_MENU::SetIcon( const BITMAP_OPAQUE* aIcon )
72 {
73  m_icon = aIcon;
74 }
75 
76 
78 {
79 // See wxWidgets hack in TOOL_DISPATCHER::DispatchWxEvent().
80 // Connect( wxEVT_MENU_OPEN, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
81 // Connect( wxEVT_MENU_HIGHLIGHT, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
82 // Connect( wxEVT_MENU_CLOSE, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
83 
84  Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
85  Connect( wxEVT_IDLE, wxIdleEventHandler( ACTION_MENU::OnIdle ), NULL, this );
86 }
87 
88 
89 void ACTION_MENU::SetTitle( const wxString& aTitle )
90 {
91  // Unfortunately wxMenu::SetTitle() does not work very well, so this is an alternative version
92  m_title = aTitle;
93 
94  // Update the menu title
95  if( m_titleDisplayed )
96  DisplayTitle( true );
97 }
98 
99 
100 void ACTION_MENU::DisplayTitle( bool aDisplay )
101 {
102  if( ( !aDisplay || m_title.IsEmpty() ) && m_titleDisplayed )
103  {
104  // Destroy the menu entry keeping the title..
105  wxMenuItem* item = FindItemByPosition( 0 );
106  wxASSERT( item->GetItemLabelText() == GetTitle() );
107  Destroy( item );
108  // ..and separator
109  item = FindItemByPosition( 0 );
110  wxASSERT( item->IsSeparator() );
111  Destroy( item );
112  m_titleDisplayed = false;
113  }
114 
115  else if( aDisplay && !m_title.IsEmpty() )
116  {
117  if( m_titleDisplayed )
118  {
119  // Simply update the title
120  FindItemByPosition( 0 )->SetItemLabel( m_title );
121  }
122  else
123  {
124  // Add a separator and a menu entry to display the title
125  InsertSeparator( 0 );
126  Insert( 0, new wxMenuItem( this, wxID_NONE, m_title, wxEmptyString, wxITEM_NORMAL ) );
127 
128  if( m_icon )
129  AddBitmapToMenuItem( FindItemByPosition( 0 ), KiBitmap( m_icon ) );
130 
131  m_titleDisplayed = true;
132  }
133  }
134 }
135 
136 
137 wxMenuItem* ACTION_MENU::Add( const wxString& aLabel, int aId, const BITMAP_OPAQUE* aIcon )
138 {
139  wxASSERT_MSG( FindItem( aId ) == nullptr, "Duplicate menu IDs!" );
140 
141  wxMenuItem* item = new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL );
142 
143  if( aIcon )
144  AddBitmapToMenuItem( item, KiBitmap( aIcon ) );
145 
146  return Append( item );
147 }
148 
149 
150 wxMenuItem* ACTION_MENU::Add( const wxString& aLabel, const wxString& aTooltip, int aId,
151  const BITMAP_OPAQUE* aIcon, bool aIsCheckmarkEntry )
152 {
153  wxASSERT_MSG( FindItem( aId ) == nullptr, "Duplicate menu IDs!" );
154 
155  wxMenuItem* item = new wxMenuItem( this, aId, aLabel, aTooltip,
156  aIsCheckmarkEntry ? wxITEM_CHECK : wxITEM_NORMAL );
157 
158  if( aIcon )
159  AddBitmapToMenuItem( item, KiBitmap( aIcon ) );
160 
161  return Append( item );
162 }
163 
164 
165 wxMenuItem* ACTION_MENU::Add( const TOOL_ACTION& aAction, bool aIsCheckmarkEntry )
166 {
168  const BITMAP_OPAQUE* icon = aAction.GetIcon();
169 
170  wxMenuItem* item = new wxMenuItem( this, aAction.GetUIId(), aAction.GetMenuItem(),
171  aAction.GetDescription(),
172  aIsCheckmarkEntry ? wxITEM_CHECK : wxITEM_NORMAL );
173  if( icon )
174  AddBitmapToMenuItem( item, KiBitmap( icon ) );
175 
176  m_toolActions[aAction.GetUIId()] = &aAction;
177 
178  return Append( item );
179 }
180 
181 
182 wxMenuItem* ACTION_MENU::Add( ACTION_MENU* aMenu )
183 {
184  ACTION_MENU* menuCopy = aMenu->Clone();
185  m_submenus.push_back( menuCopy );
186 
187  wxASSERT_MSG( !menuCopy->m_title.IsEmpty(), "Set a title for ACTION_MENU using SetTitle()" );
188 
189  if( aMenu->m_icon )
190  {
191  wxMenuItem* newItem = new wxMenuItem( this, -1, menuCopy->m_title );
192  AddBitmapToMenuItem( newItem, KiBitmap( aMenu->m_icon ) );
193  newItem->SetSubMenu( menuCopy );
194  return Append( newItem );
195  }
196  else
197  {
198  return AppendSubMenu( menuCopy, menuCopy->m_title );
199  }
200 }
201 
202 
203 void ACTION_MENU::AddClose( wxString aAppname )
204 {
205  Add( _( "Close" ) + "\tCtrl+W",
206  wxString::Format( _( "Close %s" ), aAppname ),
207  wxID_CLOSE,
208  exit_xpm );
209 }
210 
211 
212 void ACTION_MENU::AddQuitOrClose( KIFACE_I* aKiface, wxString aAppname )
213 {
214  if( !aKiface || aKiface->IsSingle() ) // not when under a project mgr
215  {
216  // Don't use ACTIONS::quit; wxWidgets moves this on OSX and expects to find it via
217  // wxID_EXIT
218  Add( _( "Quit" ),
219  wxString::Format( _( "Quit %s" ), aAppname ),
220  wxID_EXIT,
221  exit_xpm );
222  }
223  else
224  {
225  AddClose( aAppname );
226  }
227 }
228 
229 
231 {
232  m_titleDisplayed = false;
233 
234  for( int i = GetMenuItemCount() - 1; i >= 0; --i )
235  Destroy( FindItemByPosition( i ) );
236 
237  m_toolActions.clear();
238  m_submenus.clear();
239 
240  wxASSERT( GetMenuItemCount() == 0 );
241 }
242 
243 
245 {
246  bool hasEnabled = false;
247 
248  auto& items = GetMenuItems();
249 
250  for( auto item : items )
251  {
252  if( item->IsEnabled() && !item->IsSeparator() )
253  {
254  hasEnabled = true;
255  break;
256  }
257  }
258 
259  return hasEnabled;
260 }
261 
262 
264 {
265  try
266  {
267  update();
268  }
269  catch( std::exception& )
270  {
271  }
272 
273  if( m_tool )
274  updateHotKeys();
275 
276  runOnSubmenus( std::bind( &ACTION_MENU::UpdateAll, _1 ) );
277 }
278 
279 
281 {
282  m_dirty = false;
283  runOnSubmenus( std::bind( &ACTION_MENU::ClearDirty, _1 ) );
284 }
285 
286 
288 {
289  m_dirty = true;
290  runOnSubmenus( std::bind( &ACTION_MENU::SetDirty, _1 ) );
291 }
292 
293 
295 {
296  m_tool = aTool;
297  runOnSubmenus( std::bind( &ACTION_MENU::SetTool, _1, aTool ) );
298 }
299 
300 
302 {
303  ACTION_MENU* clone = create();
304  clone->Clear();
305  clone->copyFrom( *this );
306  return clone;
307 }
308 
309 
311 {
312  ACTION_MENU* menu = new ACTION_MENU( false );
313 
314  wxASSERT_MSG( typeid( *this ) == typeid( *menu ),
315  wxString::Format( "You need to override create() method for class %s", typeid(*this).name() ) );
316 
317  return menu;
318 }
319 
320 
322 {
323  wxASSERT( m_tool );
324  return m_tool ? m_tool->GetManager() : nullptr;
325 }
326 
327 
329 {
330  TOOL_MANAGER* toolMgr = getToolManager();
331 
332  for( auto& ii : m_toolActions )
333  {
334  int id = ii.first;
335  const TOOL_ACTION& action = *ii.second;
336  int key = toolMgr->GetHotKey( action ) & ~MD_MODIFIER_MASK;
337 
338  if( key )
339  {
340  int mod = toolMgr->GetHotKey( action ) & MD_MODIFIER_MASK;
341  int flags = 0;
342  wxMenuItem* item = FindChildItem( id );
343 
344  if( item )
345  {
346  flags |= ( mod & MD_ALT ) ? wxACCEL_ALT : 0;
347  flags |= ( mod & MD_CTRL ) ? wxACCEL_CTRL : 0;
348  flags |= ( mod & MD_SHIFT ) ? wxACCEL_SHIFT : 0;
349 
350  if( !flags )
351  flags = wxACCEL_NORMAL;
352 
353  wxAcceleratorEntry accel( flags, key, id, item );
354  item->SetAccel( &accel );
355  }
356  }
357  }
358 }
359 
360 
361 // wxWidgets doesn't tell us when a menu command was generated from a hotkey or from
362 // a menu selection. It's important to us because a hotkey can be an immediate action
363 // while the menu selection can not (as it has no associated position).
364 //
365 // We get around this by storing the last highlighted menuId. If it matches the command
366 // id then we know this is a menu selection. (You might think we could use the menuOpen
367 // menuClose events, but these are actually generated for hotkeys as well.)
368 
370 
371 // We need to store the position of the mouse when the menu was opened so it can be passed
372 // to the command event generated when the menu item is selected.
374 
375 
376 void ACTION_MENU::OnIdle( wxIdleEvent& event )
377 {
379  g_menu_open_position.x = 0.0;
380  g_menu_open_position.y = 0.0;
381 }
382 
383 
384 void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
385 {
386  OPT_TOOL_EVENT evt;
387  wxString menuText;
388  wxEventType type = aEvent.GetEventType();
389  wxWindow* focus = wxWindow::FindFocus();
390 
391  if( type == wxEVT_MENU_OPEN )
392  {
393  if( m_dirty && m_tool )
394  getToolManager()->RunAction( ACTIONS::updateMenu, true, this );
395 
396  wxMenu* parent = dynamic_cast<wxMenu*>( GetParent() );
397 
398  // Don't update the position if this menu has a parent
399  if( !parent && m_tool )
401 
403  }
404  else if( type == wxEVT_MENU_HIGHLIGHT )
405  {
406  if( aEvent.GetId() > 0 )
407  g_last_menu_highlighted_id = aEvent.GetId();
408 
409  evt = TOOL_EVENT( TC_COMMAND, TA_CHOICE_MENU_UPDATE, aEvent.GetId() );
410  }
411  else if( type == wxEVT_COMMAND_MENU_SELECTED )
412  {
413  // Despite our attempts to catch the theft of text editor CHAR_HOOK and CHAR events
414  // in TOOL_DISPATCHER::DispatchWxEvent, wxWidgets sometimes converts those it knows
415  // about into menu commands without ever generating the appropriate CHAR_HOOK and CHAR
416  // events first.
417  if( dynamic_cast<wxTextEntry*>( focus )
418  || dynamic_cast<wxStyledTextCtrl*>( focus )
419  || dynamic_cast<wxListView*>( focus ) )
420  {
421  // Original key event has been lost, so we have to re-create it from the menu's
422  // wxAcceleratorEntry.
423  wxMenuItem* menuItem = FindItem( aEvent.GetId() );
424  wxAcceleratorEntry* acceleratorKey = menuItem ? menuItem->GetAccel() : nullptr;
425 
426  if( acceleratorKey )
427  {
428  wxKeyEvent keyEvent( wxEVT_CHAR_HOOK );
429  keyEvent.m_keyCode = acceleratorKey->GetKeyCode();
430  keyEvent.m_controlDown = ( acceleratorKey->GetFlags() & wxMOD_CONTROL ) > 0;
431  keyEvent.m_shiftDown = ( acceleratorKey->GetFlags() & wxMOD_SHIFT ) > 0;
432  keyEvent.m_altDown = ( acceleratorKey->GetFlags() & wxMOD_ALT ) > 0;
433 
434  if( auto ctrl = dynamic_cast<wxTextEntry*>( focus ) )
435  TEXTENTRY_TRICKS::OnCharHook( ctrl, keyEvent );
436  else
437  focus->HandleWindowEvent( keyEvent );
438 
439  if( keyEvent.GetSkipped() )
440  {
441  keyEvent.SetEventType( wxEVT_CHAR );
442  focus->HandleWindowEvent( keyEvent );
443  }
444 
445  // If the event was used as KEY event (not skipped) by the focused window,
446  // just finish.
447  // Otherwise this is actually a wxEVT_COMMAND_MENU_SELECTED, or the
448  // focused window is read only
449  if( !keyEvent.GetSkipped() )
450  return;
451  }
452  }
453 
454  // Store the selected position, so it can be checked by the tools
455  m_selected = aEvent.GetId();
456 
457  ACTION_MENU* parent = dynamic_cast<ACTION_MENU*>( GetParent() );
458 
459  while( parent )
460  {
461  parent->m_selected = m_selected;
462  parent = dynamic_cast<ACTION_MENU*>( parent->GetParent() );
463  }
464 
465  // Check if there is a TOOL_ACTION for the given ID
467  evt = findToolAction( m_selected );
468 
469  if( !evt )
470  {
471 #ifdef __WINDOWS__
472  if( !evt )
473  {
474  // Try to find the submenu which holds the selected item
475  wxMenu* menu = nullptr;
476  FindItem( m_selected, &menu );
477 
478  // This conditional compilation is probably not needed.
479  // It will be removed later, for the Kicad V 6.x version.
480  // But in "old" 3.0 version, the "&& menu != this" contition was added to avoid hang
481  // This hang is no longer encountered in wxWidgets 3.0.4 version, and this condition is no longer needed.
482  // And in 3.1.2, we have to remove it, as "menu != this" never happens
483  // ("menu != this" always happens in 3.1.1 and older!).
484  #if wxCHECK_VERSION(3, 1, 2)
485  if( menu )
486  #else
487  if( menu && menu != this )
488  #endif
489  {
490  ACTION_MENU* cxmenu = static_cast<ACTION_MENU*>( menu );
491  evt = cxmenu->eventHandler( aEvent );
492  }
493  }
494 #else
495  if( !evt )
496  runEventHandlers( aEvent, evt );
497 #endif
498 
499  // Handling non-action menu entries (e.g. items in clarification list)
500  // in some context menus, that have IDs explicitly chosen between
501  // ID_POPUP_MENU_START and ID_POPUP_MENU_END
502  // Note also items in clarification list have an id >= 0 and < wxID_LOWEST
503  // in fact 0 to n-1 for n items in clarification list)
504  // id < 0 are automatically created for menuitems created with wxID_ANY
505  #define ID_CONTEXT_MENU_ID_MAX wxID_LOWEST /* = 100 should be enough and better */
506 
507  if( !evt &&
508  ( ( m_selected >= 0 && m_selected < ID_CONTEXT_MENU_ID_MAX ) ||
510  {
511  menuText = GetLabelText( aEvent.GetId() );
513  &menuText );
514  }
515  }
516  }
517 
518  // forward the action/update event to the TOOL_MANAGER
519  // clients that don't supply a tool will have to check GetSelected() themselves
520  if( evt && m_tool )
521  {
522  wxLogTrace( kicadTraceToolStack, "ACTION_MENU::OnMenuEvent %s", evt->Format() );
523 
524  // Pass the position the menu was opened from into the generated event if it is a select event
525  if( type == wxEVT_COMMAND_MENU_SELECTED )
526  evt->SetMousePosition( g_menu_open_position );
527  else
528  evt->SetMousePosition( getToolManager()->GetMousePosition() );
529 
530  if( g_last_menu_highlighted_id == aEvent.GetId() && !m_isContextMenu )
531  evt->SetHasPosition( false );
532 
533  if( m_tool->GetManager() )
534  m_tool->GetManager()->ProcessEvent( *evt );
535  }
536  else
537  {
538  aEvent.Skip();
539  }
540 }
541 
542 
543 void ACTION_MENU::runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent )
544 {
545  aToolEvent = eventHandler( aMenuEvent );
546 
547  if( !aToolEvent )
548  runOnSubmenus( std::bind( &ACTION_MENU::runEventHandlers, _1, aMenuEvent, aToolEvent ) );
549 }
550 
551 
552 void ACTION_MENU::runOnSubmenus( std::function<void(ACTION_MENU*)> aFunction )
553 {
554  try
555  {
556  std::for_each( m_submenus.begin(), m_submenus.end(), [&]( ACTION_MENU* m ) {
557  aFunction( m );
558  m->runOnSubmenus( aFunction );
559  } );
560  }
561  catch( std::exception& )
562  {
563  }
564 }
565 
566 
568 {
569  OPT_TOOL_EVENT evt;
570 
571  auto findFunc = [&]( ACTION_MENU* m ) {
572  if( evt )
573  return;
574 
575  const auto it = m->m_toolActions.find( aId );
576 
577  if( it != m->m_toolActions.end() )
578  evt = it->second->MakeEvent();
579  };
580 
581  findFunc( this );
582 
583  if( !evt )
584  runOnSubmenus( findFunc );
585 
586  return evt;
587 }
588 
589 
590 void ACTION_MENU::copyFrom( const ACTION_MENU& aMenu )
591 {
592  m_icon = aMenu.m_icon;
593  m_title = aMenu.m_title;
595  m_selected = -1; // aMenu.m_selected;
596  m_tool = aMenu.m_tool;
598 
599  // Copy all menu entries
600  for( int i = 0; i < (int) aMenu.GetMenuItemCount(); ++i )
601  {
602  wxMenuItem* item = aMenu.FindItemByPosition( i );
603  appendCopy( item );
604  }
605 }
606 
607 
608 wxMenuItem* ACTION_MENU::appendCopy( const wxMenuItem* aSource )
609 {
610  wxMenuItem* newItem = new wxMenuItem( this, aSource->GetId(), aSource->GetItemLabel(),
611  aSource->GetHelp(), aSource->GetKind() );
612 
613  // Add the source bitmap if it is not the wxNullBitmap
614  // On Windows, for Checkable Menu items, adding a bitmap adds also
615  // our predefined checked alternate bitmap
616  // On other OS, wxITEM_CHECK and wxITEM_RADIO Menu items do not use custom bitmaps.
617 #if defined(_WIN32)
618  // On Windows, AddBitmapToMenuItem() uses the unchecked bitmap for wxITEM_CHECK and wxITEM_RADIO menuitems
619  // and autoamtically adds a checked bitmap.
620  // For other menuitrms, use the "checked" bitmap.
621  bool use_checked_bm = ( aSource->GetKind() == wxITEM_CHECK || aSource->GetKind() == wxITEM_RADIO ) ? false : true;
622  const wxBitmap& src_bitmap = aSource->GetBitmap( use_checked_bm );
623 #else
624  const wxBitmap& src_bitmap = aSource->GetBitmap();
625 #endif
626 
627  if( src_bitmap.IsOk() && src_bitmap.GetHeight() > 1 ) // a null bitmap has a 0 size
628  AddBitmapToMenuItem( newItem, src_bitmap );
629 
630  if( aSource->IsSubMenu() )
631  {
632  ACTION_MENU* menu = dynamic_cast<ACTION_MENU*>( aSource->GetSubMenu() );
633  wxASSERT_MSG( menu, "Submenus are expected to be a ACTION_MENU" );
634 
635  if( menu )
636  {
637  ACTION_MENU* menuCopy = menu->Clone();
638  newItem->SetSubMenu( menuCopy );
639  m_submenus.push_back( menuCopy );
640  }
641  }
642 
643  // wxMenuItem has to be added before enabling/disabling or checking
644  Append( newItem );
645 
646  if( aSource->IsCheckable() )
647  newItem->Check( aSource->IsChecked() );
648 
649  newItem->Enable( aSource->IsEnabled() );
650 
651  return newItem;
652 }
wxMenuItem * Add(const wxString &aLabel, int aId, const BITMAP_OPAQUE *aIcon)
Adds a wxWidgets-style entry to the menu.
KIFACE_I is a KIFACE (I)mplementation, with some features useful for DSOs which implement a KIFACE.
Definition: kiface_i.h:37
virtual void update()
Update menu state stub.
Definition: action_menu.h:175
bool m_titleDisplayed
Definition: action_menu.h:222
OPT_TOOL_EVENT findToolAction(int aId)
Checks if any of submenus contains a TOOL_ACTION with a specific ID.
int GetHotKey(const TOOL_ACTION &aAction)
PNG memory record (file in memory).
Definition: bitmap_def.h:29
static int g_last_menu_highlighted_id
int GetUIId() const
Definition: tool_action.h:102
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:43
const BITMAP_OPAQUE * m_icon
Optional icon
Definition: action_menu.h:229
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:141
void runEventHandlers(const wxMenuEvent &aMenuEvent, OPT_TOOL_EVENT &aToolEvent)
Traverses the submenus tree looking for a submenu capable of handling a particular menu event.
void ClearDirty()
Clears the dirty flag on the menu and all descendants.
void UpdateAll()
Runs update handlers for the menu and its submenus.
virtual ACTION_MENU * create() const
Returns an instance of this class. It has to be overridden in inheriting classes.
static int GetBaseUIId()
Definition: tool_action.h:107
const BITMAP_OPAQUE * GetIcon() const
Returns an icon associated with the action.
Definition: tool_action.h:155
void SetTool(TOOL_INTERACTIVE *aTool)
Sets a tool that is the creator of the menu.
TOOL_MANAGER * GetManager() const
Function GetManager() Returns the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:143
virtual OPT_TOOL_EVENT eventHandler(const wxMenuEvent &)
Event handler stub.
Definition: action_menu.h:183
TOOL_MANAGER.
Definition: tool_manager.h:51
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:82
#define ID_CONTEXT_MENU_ID_MAX
void copyFrom(const ACTION_MENU &aMenu)
Copies another menus data to this instance.
void AddBitmapToMenuItem(wxMenuItem *aMenu, const wxBitmap &aImage)
Add a bitmap to a menuitem.
Definition: bitmap.cpp:207
#define NULL
bool IsSingle() const
Function IsSingle is this KIFACE_I running under single_top?
Definition: kiface_i.h:117
bool m_isContextMenu
Definition: action_menu.h:223
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
const BITMAP_OPAQUE exit_xpm[1]
Definition: exit.cpp:63
wxString m_title
Menu title
Definition: action_menu.h:226
std::list< ACTION_MENU * > m_submenus
List of submenus.
Definition: action_menu.h:241
void SetIcon(const BITMAP_OPAQUE *aIcon)
Assigns an icon for the entry.
Definition: action_menu.cpp:71
TOOL_EVENT.
Definition: tool_event.h:171
static VECTOR2D g_menu_open_position
Base window classes and related definitions.
int m_selected
Stores the id number of selected item.
Definition: action_menu.h:232
wxLogTrace helper definitions.
ACTION_MENU * Clone() const
Creates a deep, recursive copy of this ACTION_MENU.
static TOOL_ACTION updateMenu
Definition: actions.h:167
All active tools
Definition: tool_event.h:147
TOOL_INTERACTIVE * m_tool
Creator of the menu
Definition: action_menu.h:235
wxString GetDescription(bool aIncludeHotkey=true) const
Definition: tool_action.cpp:83
wxMenuItem * appendCopy(const wxMenuItem *aSource)
Function appendCopy Appends a copy of wxMenuItem.
void runOnSubmenus(std::function< void(ACTION_MENU *)> aFunction)
Runs a function on the menu and all its submenus.
std::map< int, const TOOL_ACTION * > m_toolActions
Associates tool actions with menu item IDs. Non-owning.
Definition: action_menu.h:238
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void OnMenuEvent(wxMenuEvent &aEvent)
void SetTitle(const wxString &aTitle) override
Sets title for the menu.
Definition: action_menu.cpp:89
void AddQuitOrClose(KIFACE_I *aKiface, wxString aAppname="")
Adds either a standard Quit or Close item to the menu.
ACTION_MENU(bool isContextMenu, TOOL_INTERACTIVE *aTool=nullptr)
Default constructor
Definition: action_menu.cpp:46
#define _(s)
Definition: 3d_actions.cpp:33
static void OnCharHook(wxTextEntry *aTextEntry, wxKeyEvent &aEvent)
TOOL_MANAGER * getToolManager() const
Returns an instance of TOOL_MANAGER class.
Represents a single user action.
Definition: tool_action.h:44
void setupEvents()
Initializes handlers for events.
Definition: action_menu.cpp:77
void Clear()
Removes all the entries from the menu (as well as its title).
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
bool HasEnabledItems() const
Returns true if the menu has any enabled items.
void OnIdle(wxIdleEvent &event)
VECTOR2D GetMousePosition()
void updateHotKeys()
Updates hot key settings for TOOL_ACTIONs in this menu.
wxString GetMenuItem() const
Definition: tool_action.cpp:75
~ACTION_MENU() override
Definition: action_menu.cpp:58
void SetDirty()
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:556
void AddClose(wxString aAppname="")
Add a standard close item to the menu with the accelerator key CTRL-W.
void DisplayTitle(bool aDisplay=true)
Decides whether a title for a pop up menu should be displayed.