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-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Tomasz Wlostowski <[email protected]>
7 * @author Maciej Suminski <[email protected]>
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 <bitmaps.h>
28#include <eda_base_frame.h>
29#include <functional>
30#include <id.h>
31#include <kiface_base.h>
32#include <menus_helpers.h>
33#include <tool/action_menu.h>
34#include <tool/actions.h>
35#include <tool/tool_event.h>
37#include <tool/tool_manager.h>
38#include <trace_helpers.h>
39#include <wx/log.h>
40#include <wx/stc/stc.h>
41#include <textentry_tricks.h>
42#include <wx/listctrl.h>
43
44using namespace std::placeholders;
45
46
47ACTION_MENU::ACTION_MENU( bool isContextMenu, TOOL_INTERACTIVE* aTool ) :
48 m_isForcedPosition( false ),
49 m_dirty( true ),
50 m_titleDisplayed( false ),
51 m_isContextMenu( isContextMenu ),
52 m_icon( BITMAPS::INVALID_BITMAP ),
53 m_selected( -1 ),
54 m_tool( aTool )
55{
57}
58
59
61{
62 // Set parent to NULL to prevent submenus from unregistering from a nonexistent object
63 for( ACTION_MENU* menu : m_submenus )
64 menu->SetParent( nullptr );
65
66 ACTION_MENU* parent = dynamic_cast<ACTION_MENU*>( GetParent() );
67
68 if( parent )
69 parent->m_submenus.remove( this );
70}
71
72
74{
75 m_icon = aIcon;
76}
77
78
80{
81 Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), nullptr,
82 this );
83 Connect( wxEVT_IDLE, wxIdleEventHandler( ACTION_MENU::OnIdle ), nullptr, this );
84}
85
86
87void ACTION_MENU::SetTitle( const wxString& aTitle )
88{
89 // Unfortunately wxMenu::SetTitle() does not work very well, so this is an alternative version
90 m_title = aTitle;
91
92 // Update the menu title
94 DisplayTitle( true );
95}
96
97
98void ACTION_MENU::DisplayTitle( bool aDisplay )
99{
100 if( ( !aDisplay || m_title.IsEmpty() ) && m_titleDisplayed )
101 {
102 // Destroy the menu entry keeping the title..
103 wxMenuItem* item = FindItemByPosition( 0 );
104 wxASSERT( item->GetItemLabelText() == GetTitle() );
105 Destroy( item );
106 // ..and separator
107 item = FindItemByPosition( 0 );
108 wxASSERT( item->IsSeparator() );
109 Destroy( item );
110 m_titleDisplayed = false;
111 }
112
113 else if( aDisplay && !m_title.IsEmpty() )
114 {
115 if( m_titleDisplayed )
116 {
117 // Simply update the title
118 FindItemByPosition( 0 )->SetItemLabel( m_title );
119 }
120 else
121 {
122 // Add a separator and a menu entry to display the title
123 InsertSeparator( 0 );
124 Insert( 0, new wxMenuItem( this, wxID_NONE, m_title, wxEmptyString, wxITEM_NORMAL ) );
125
126 if( !!m_icon )
127 AddBitmapToMenuItem( FindItemByPosition( 0 ), KiBitmap( m_icon ) );
128
129 m_titleDisplayed = true;
130 }
131 }
132}
133
134
135wxMenuItem* ACTION_MENU::Add( const wxString& aLabel, int aId, BITMAPS aIcon )
136{
137 wxASSERT_MSG( FindItem( aId ) == nullptr, wxS( "Duplicate menu IDs!" ) );
138
139 wxMenuItem* item = new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL );
140
141 if( !!aIcon )
142 AddBitmapToMenuItem( item, KiBitmap( aIcon ) );
143
144 return Append( item );
145}
146
147
148wxMenuItem* ACTION_MENU::Add( const wxString& aLabel, const wxString& aTooltip, int aId,
149 BITMAPS aIcon, bool aIsCheckmarkEntry )
150{
151 wxASSERT_MSG( FindItem( aId ) == nullptr, wxS( "Duplicate menu IDs!" ) );
152
153 wxMenuItem* item = new wxMenuItem( this, aId, aLabel, aTooltip,
154 aIsCheckmarkEntry ? wxITEM_CHECK : wxITEM_NORMAL );
155
156 if( !!aIcon )
157 AddBitmapToMenuItem( item, KiBitmap( aIcon ) );
158
159 return Append( item );
160}
161
162
163wxMenuItem* ACTION_MENU::Add( const TOOL_ACTION& aAction, bool aIsCheckmarkEntry,
164 const wxString& aOverrideLabel )
165{
167 BITMAPS icon = aAction.GetIcon();
168
169 // Allow the label to be overridden at point of use
170 wxString menuLabel = aOverrideLabel.IsEmpty() ? aAction.GetMenuItem() : aOverrideLabel;
171
172 wxMenuItem* item = new wxMenuItem( this, aAction.GetUIId(), menuLabel,
173 aAction.GetDescription(),
174 aIsCheckmarkEntry ? wxITEM_CHECK : wxITEM_NORMAL );
175 if( !!icon )
176 AddBitmapToMenuItem( item, KiBitmap( icon ) );
177
178 m_toolActions[aAction.GetUIId()] = &aAction;
179
180 return Append( item );
181}
182
183
184wxMenuItem* ACTION_MENU::Add( ACTION_MENU* aMenu )
185{
186 m_submenus.push_back( aMenu );
187
188 wxASSERT_MSG( !aMenu->m_title.IsEmpty(), wxS( "Set a title for ACTION_MENU using SetTitle()" ) );
189
190 if( !!aMenu->m_icon )
191 {
192 wxMenuItem* newItem = new wxMenuItem( this, -1, aMenu->m_title );
193 AddBitmapToMenuItem( newItem, KiBitmap( aMenu->m_icon ) );
194 newItem->SetSubMenu( aMenu );
195 return Append( newItem );
196 }
197 else
198 {
199 return AppendSubMenu( aMenu, aMenu->m_title );
200 }
201}
202
203
204void ACTION_MENU::AddClose( const wxString& aAppname )
205{
206#ifdef __WINDOWS__
207 Add( _( "Close" ),
208 wxString::Format( _( "Close %s" ), aAppname ),
209 wxID_CLOSE,
211#else
212 Add( _( "Close" ) + wxS( "\tCtrl+W" ),
213 wxString::Format( _( "Close %s" ), aAppname ),
214 wxID_CLOSE,
216#endif
217}
218
219
220void ACTION_MENU::AddQuitOrClose( KIFACE_BASE* aKiface, wxString aAppname )
221{
222 if( !aKiface || aKiface->IsSingle() ) // not when under a project mgr
223 {
224 // Don't use ACTIONS::quit; wxWidgets moves this on OSX and expects to find it via
225 // wxID_EXIT
226 Add( _( "Quit" ) + wxS( "\tCtrl+Q" ),
227 wxString::Format( _( "Quit %s" ), aAppname ),
228 wxID_EXIT,
230 }
231 else
232 {
233 AddClose( aAppname );
234 }
235}
236
237
239{
240 m_titleDisplayed = false;
241
242 for( int i = GetMenuItemCount() - 1; i >= 0; --i )
243 Destroy( FindItemByPosition( i ) );
244
245 m_toolActions.clear();
246 m_submenus.clear();
247
248 wxASSERT( GetMenuItemCount() == 0 );
249}
250
251
253{
254 for( wxMenuItem* item : GetMenuItems() )
255 {
256 if( item->IsEnabled() && !item->IsSeparator() )
257 return true;
258 }
259
260 return false;
261}
262
263
265{
266 try
267 {
268 update();
269 }
270 catch( std::exception& )
271 {
272 }
273
274 if( m_tool )
276
277 runOnSubmenus( std::bind( &ACTION_MENU::UpdateAll, _1 ) );
278}
279
280
282{
283 m_dirty = false;
284 runOnSubmenus( std::bind( &ACTION_MENU::ClearDirty, _1 ) );
285}
286
287
289{
290 m_dirty = true;
291 runOnSubmenus( std::bind( &ACTION_MENU::SetDirty, _1 ) );
292}
293
294
296{
297 m_tool = aTool;
298 runOnSubmenus( std::bind( &ACTION_MENU::SetTool, _1, aTool ) );
299}
300
301
303{
304 ACTION_MENU* clone = create();
305 clone->Clear();
306 clone->copyFrom( *this );
307 return clone;
308}
309
310
312{
313 ACTION_MENU* menu = new ACTION_MENU( false );
314
315 wxASSERT_MSG( typeid( *this ) == typeid( *menu ),
316 wxString::Format( "You need to override create() method for class %s",
317 typeid( *this ).name() ) );
318
319 return menu;
320}
321
322
324{
325 wxASSERT( m_tool );
326 return m_tool ? m_tool->GetManager() : nullptr;
327}
328
329
331{
332 TOOL_MANAGER* toolMgr = getToolManager();
333
334 for( std::pair<const int, const TOOL_ACTION*>& ii : m_toolActions )
335 {
336 int id = ii.first;
337 const TOOL_ACTION& action = *ii.second;
338 int key = toolMgr->GetHotKey( action ) & ~MD_MODIFIER_MASK;
339
340 if( key > 0 )
341 {
342 int mod = toolMgr->GetHotKey( action ) & MD_MODIFIER_MASK;
343 int flags = 0;
344 wxMenuItem* item = FindChildItem( id );
345
346 if( item )
347 {
348 flags |= ( mod & MD_ALT ) ? wxACCEL_ALT : 0;
349 flags |= ( mod & MD_CTRL ) ? wxACCEL_CTRL : 0;
350 flags |= ( mod & MD_SHIFT ) ? wxACCEL_SHIFT : 0;
351
352 if( !flags )
353 flags = wxACCEL_NORMAL;
354
355 wxAcceleratorEntry accel( flags, key, id, item );
356 item->SetAccel( &accel );
357 }
358 }
359 }
360}
361
362
363// wxWidgets doesn't tell us when a menu command was generated from a hotkey or from
364// a menu selection. It's important to us because a hotkey can be an immediate action
365// while the menu selection can not (as it has no associated position).
366//
367// We get around this by storing the last highlighted menuId. If it matches the command
368// id then we know this is a menu selection. (You might think we could use the menuOpen
369// menuClose events, but these are actually generated for hotkeys as well.)
370
372
373
374// We need to store the position of the mouse when the menu was opened so it can be passed
375// to the command event generated when the menu item is selected.
377
378
379void ACTION_MENU::OnIdle( wxIdleEvent& event )
380{
384}
385
386
387void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
388{
389 OPT_TOOL_EVENT evt;
390 wxString menuText;
391 wxEventType type = aEvent.GetEventType();
392 wxWindow* focus = wxWindow::FindFocus();
393
394 if( type == wxEVT_MENU_OPEN )
395 {
396 if( m_dirty && m_tool )
398
399 wxMenu* parent = dynamic_cast<wxMenu*>( GetParent() );
400
401 // Don't update the position if this menu has a parent
402 if( !parent && m_tool )
404
406 }
407 else if( type == wxEVT_MENU_HIGHLIGHT )
408 {
409 if( aEvent.GetId() > 0 )
410 g_last_menu_highlighted_id = aEvent.GetId();
411
412 evt = TOOL_EVENT( TC_COMMAND, TA_CHOICE_MENU_UPDATE, aEvent.GetId() );
413 }
414 else if( type == wxEVT_COMMAND_MENU_SELECTED )
415 {
416 // Despite our attempts to catch the theft of text editor CHAR_HOOK and CHAR events
417 // in TOOL_DISPATCHER::DispatchWxEvent, wxWidgets sometimes converts those it knows
418 // about into menu commands without ever generating the appropriate CHAR_HOOK and CHAR
419 // events first.
420 if( dynamic_cast<wxTextEntry*>( focus )
421 || dynamic_cast<wxStyledTextCtrl*>( focus )
422 || dynamic_cast<wxListView*>( focus ) )
423 {
424 // Original key event has been lost, so we have to re-create it from the menu's
425 // wxAcceleratorEntry.
426 wxMenuItem* menuItem = FindItem( aEvent.GetId() );
427 wxAcceleratorEntry* acceleratorKey = menuItem ? menuItem->GetAccel() : nullptr;
428
429 if( acceleratorKey )
430 {
431 wxKeyEvent keyEvent( wxEVT_CHAR_HOOK );
432 keyEvent.m_keyCode = acceleratorKey->GetKeyCode();
433 keyEvent.m_controlDown = ( acceleratorKey->GetFlags() & wxMOD_CONTROL ) > 0;
434 keyEvent.m_shiftDown = ( acceleratorKey->GetFlags() & wxMOD_SHIFT ) > 0;
435 keyEvent.m_altDown = ( acceleratorKey->GetFlags() & wxMOD_ALT ) > 0;
436
437 if( auto ctrl = dynamic_cast<wxTextEntry*>( focus ) )
438 TEXTENTRY_TRICKS::OnCharHook( ctrl, keyEvent );
439 else
440 focus->HandleWindowEvent( keyEvent );
441
442 if( keyEvent.GetSkipped() )
443 {
444 keyEvent.SetEventType( wxEVT_CHAR );
445 focus->HandleWindowEvent( keyEvent );
446 }
447
448 // If the event was used as KEY event (not skipped) by the focused window,
449 // just finish.
450 // Otherwise this is actually a wxEVT_COMMAND_MENU_SELECTED, or the
451 // focused window is read only
452 if( !keyEvent.GetSkipped() )
453 return;
454 }
455 }
456
457 // Store the selected position, so it can be checked by the tools
458 m_selected = aEvent.GetId();
459
460 ACTION_MENU* parent = dynamic_cast<ACTION_MENU*>( GetParent() );
461
462 while( parent )
463 {
464 parent->m_selected = m_selected;
465 parent = dynamic_cast<ACTION_MENU*>( parent->GetParent() );
466 }
467
468 // Check if there is a TOOL_ACTION for the given ID
469 // Note that we also have to check the standard wxWidgets' cut/copy/paste IDs because
470 // we can't use our own IDs there without losing cut/copy/paste in places like search
471 // boxes in standard file dialogs.
472 if( m_selected == wxID_CUT || m_selected == wxID_COPY || m_selected == wxID_PASTE
474 {
475 evt = findToolAction( m_selected );
476 }
477
478 if( !evt )
479 {
480#ifdef __WINDOWS__
481 if( !evt )
482 {
483 // Try to find the submenu which holds the selected item
484 wxMenu* menu = nullptr;
485 FindItem( m_selected, &menu );
486
487 // This conditional compilation is probably not needed.
488 // It will be removed later, for the Kicad V 6.x version.
489 // But in "old" 3.0 version, the "&& menu != this" contition was added to avoid
490 // hang. This hang is no longer encountered in wxWidgets 3.0.4 version, and this
491 // condition is no longer needed. And in 3.1.2, we have to remove it, as
492 // "menu != this" never happens ("menu != this" always happens in 3.1.1 and older!).
493#if wxCHECK_VERSION( 3, 1, 2 )
494 if( menu )
495#else
496 if( menu && menu != this )
497#endif
498 {
499 ACTION_MENU* cxmenu = static_cast<ACTION_MENU*>( menu );
500 evt = cxmenu->eventHandler( aEvent );
501 }
502 }
503#else
504 if( !evt )
505 runEventHandlers( aEvent, evt );
506#endif
507
508 // Handling non-ACTION menu entries. Two ranges of ids are supported:
509 // between 0 and ID_CONTEXT_MENU_ID_MAX
510 // between ID_POPUP_MENU_START and ID_POPUP_MENU_END
511
512 #define ID_CONTEXT_MENU_ID_MAX wxID_LOWEST /* = 100 should be plenty */
513
514 if( !evt &&
517 {
518 ACTION_MENU* actionMenu = dynamic_cast<ACTION_MENU*>( GetParent() );
519
520 if( actionMenu && actionMenu->PassHelpTextToHandler() )
521 menuText = GetHelpString( aEvent.GetId() );
522 else
523 menuText = GetLabelText( aEvent.GetId() );
524
526 &menuText );
527 }
528 }
529 }
530
531 // forward the action/update event to the TOOL_MANAGER
532 // clients that don't supply a tool will have to check GetSelected() themselves
533 if( evt && m_tool )
534 {
535 wxLogTrace( kicadTraceToolStack, wxS( "ACTION_MENU::OnMenuEvent %s" ), evt->Format() );
536
537 // WARNING: if you're squeamish, look away.
538 // What follows is a series of egregious hacks necessitated by a lack of information from
539 // wxWidgets on where context-menu-commands and command-key-events originated.
540
541 // If it's a context menu then fetch the mouse position from our context-menu-position
542 // hack.
543 if( m_isContextMenu )
544 {
545 evt->SetMousePosition( g_menu_open_position );
546 }
547 // Otherwise, if g_last_menu_highlighted_id matches then it's a menubar menu event and has
548 // no position.
549 else if( g_last_menu_highlighted_id == aEvent.GetId() )
550 {
551 evt->SetHasPosition( false );
552 }
553 // Otherwise it's a command-key-event and we need to get the mouse position from the tool
554 // manager so that immediate actions work.
555 else
556 {
557 evt->SetMousePosition( getToolManager()->GetMousePosition() );
558 }
559
560 if( m_tool->GetManager() )
561 m_tool->GetManager()->ProcessEvent( *evt );
562 }
563 else
564 {
565 aEvent.Skip();
566 }
567}
568
569
570void ACTION_MENU::runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent )
571{
572 aToolEvent = eventHandler( aMenuEvent );
573
574 if( !aToolEvent )
575 runOnSubmenus( std::bind( &ACTION_MENU::runEventHandlers, _1, aMenuEvent, aToolEvent ) );
576}
577
578
579void ACTION_MENU::runOnSubmenus( std::function<void(ACTION_MENU*)> aFunction )
580{
581 try
582 {
583 std::for_each( m_submenus.begin(), m_submenus.end(),
584 [&]( ACTION_MENU* m )
585 {
586 aFunction( m );
587 m->runOnSubmenus( aFunction );
588 } );
589 }
590 catch( std::exception& )
591 {
592 }
593}
594
595
597{
598 OPT_TOOL_EVENT evt;
599
600 auto findFunc =
601 [&]( ACTION_MENU* m )
602 {
603 if( evt )
604 return;
605
606 const auto it = m->m_toolActions.find( aId );
607
608 if( it != m->m_toolActions.end() )
609 evt = it->second->MakeEvent();
610 };
611
612 findFunc( this );
613
614 if( !evt )
615 runOnSubmenus( findFunc );
616
617 return evt;
618}
619
620
622{
623 m_icon = aMenu.m_icon;
624 m_title = aMenu.m_title;
626 m_selected = -1; // aMenu.m_selected;
627 m_tool = aMenu.m_tool;
629
630 // Copy all menu entries
631 for( int i = 0; i < (int) aMenu.GetMenuItemCount(); ++i )
632 {
633 wxMenuItem* item = aMenu.FindItemByPosition( i );
634 appendCopy( item );
635 }
636}
637
638
639wxMenuItem* ACTION_MENU::appendCopy( const wxMenuItem* aSource )
640{
641 wxMenuItem* newItem = new wxMenuItem( this, aSource->GetId(), aSource->GetItemLabel(),
642 aSource->GetHelp(), aSource->GetKind() );
643
644 // Add the source bitmap if it is not the wxNullBitmap
645 // On Windows, for Checkable Menu items, adding a bitmap adds also
646 // our predefined checked alternate bitmap
647 // On other OS, wxITEM_CHECK and wxITEM_RADIO Menu items do not use custom bitmaps.
648#if defined( _WIN32 )
649 // On Windows, AddBitmapToMenuItem() uses the unchecked bitmap for wxITEM_CHECK and
650 // wxITEM_RADIO menuitems and autoamtically adds a checked bitmap.
651 // For other menuitrms, use the "checked" bitmap.
652 bool use_checked_bm = ( aSource->GetKind() == wxITEM_CHECK ||
653 aSource->GetKind() == wxITEM_RADIO ) ? false : true;
654 const wxBitmap& src_bitmap = aSource->GetBitmap( use_checked_bm );
655#else
656 const wxBitmap& src_bitmap = aSource->GetBitmap();
657#endif
658
659 if( src_bitmap.IsOk() && src_bitmap.GetHeight() > 1 ) // a null bitmap has a 0 size
660 AddBitmapToMenuItem( newItem, src_bitmap );
661
662 if( aSource->IsSubMenu() )
663 {
664 ACTION_MENU* menu = dynamic_cast<ACTION_MENU*>( aSource->GetSubMenu() );
665 wxASSERT_MSG( menu, wxS( "Submenus are expected to be a ACTION_MENU" ) );
666
667 if( menu )
668 {
669 ACTION_MENU* menuCopy = menu->Clone();
670 newItem->SetSubMenu( menuCopy );
671 m_submenus.push_back( menuCopy );
672 }
673 }
674
675 // wxMenuItem has to be added before enabling/disabling or checking
676 Append( newItem );
677
678 if( aSource->IsCheckable() )
679 newItem->Check( aSource->IsChecked() );
680
681 newItem->Enable( aSource->IsEnabled() );
682
683 return newItem;
684}
static int g_last_menu_highlighted_id
static VECTOR2D g_menu_open_position
#define ID_CONTEXT_MENU_ID_MAX
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void AddBitmapToMenuItem(wxMenuItem *aMenu, const wxBitmap &aImage)
Add a bitmap to a menuitem.
Definition: bitmap.cpp:251
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
@ INVALID_BITMAP
static TOOL_ACTION updateMenu
Definition: actions.h:171
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void updateHotKeys()
Traverse the submenus tree looking for a submenu capable of handling a particular menu event.
ACTION_MENU(bool isContextMenu, TOOL_INTERACTIVE *aTool=nullptr)
< Default constructor
Definition: action_menu.cpp:47
void SetDirty()
TOOL_MANAGER * getToolManager() const
void setupEvents()
Update hot key settings for TOOL_ACTIONs in this menu.
Definition: action_menu.cpp:79
wxString m_title
Optional icon.
Definition: action_menu.h:257
virtual ACTION_MENU * create() const
< Return an instance of this class. It has to be overridden in inheriting classes.
virtual void update()
Update menu state stub.
Definition: action_menu.h:204
void AddQuitOrClose(KIFACE_BASE *aKiface, wxString aAppname="")
Add either a standard Quit or Close item to the menu.
void ClearDirty()
Clear the dirty flag on the menu and all descendants.
wxMenuItem * appendCopy(const wxMenuItem *aSource)
Append a copy of wxMenuItem.
OPT_TOOL_EVENT findToolAction(int aId)
void runEventHandlers(const wxMenuEvent &aMenuEvent, OPT_TOOL_EVENT &aToolEvent)
Run a function on the menu and all its submenus.
std::map< int, const TOOL_ACTION * > m_toolActions
List of submenus.
Definition: action_menu.h:269
bool m_isContextMenu
Menu title.
Definition: action_menu.h:254
virtual OPT_TOOL_EVENT eventHandler(const wxMenuEvent &)
Event handler stub.
Definition: action_menu.h:214
void OnMenuEvent(wxMenuEvent &aEvent)
void AddClose(const wxString &aAppname="")
Add a standard close item to the menu with the accelerator key CTRL-W.
void DisplayTitle(bool aDisplay=true)
Decide whether a title for a pop up menu should be displayed.
Definition: action_menu.cpp:98
ACTION_MENU * Clone() const
Create a deep, recursive copy of this ACTION_MENU.
void Clear()
Remove all the entries from the menu (as well as its title).
void UpdateAll()
Run update handlers for the menu and its submenus.
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:87
void SetTool(TOOL_INTERACTIVE *aTool)
Set a tool that is the creator of the menu.
void OnIdle(wxIdleEvent &event)
std::list< ACTION_MENU * > m_submenus
Definition: action_menu.h:272
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:73
~ACTION_MENU() override
Definition: action_menu.cpp:60
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
bool m_titleDisplayed
Definition: action_menu.h:253
int m_selected
Creator of the menu.
Definition: action_menu.h:263
BITMAPS m_icon
Stores the id number of selected item.
Definition: action_menu.h:260
bool HasEnabledItems() const
Returns true if the menu has any enabled items.
TOOL_INTERACTIVE * m_tool
Associates tool actions with menu item IDs. Non-owning.
Definition: action_menu.h:266
void runOnSubmenus(std::function< void(ACTION_MENU *)> aFunction)
Check if any of submenus contains a TOOL_ACTION with a specific ID.
virtual bool PassHelpTextToHandler()
Definition: action_menu.h:186
void copyFrom(const ACTION_MENU &aMenu)
Copy another menus data to this instance.
A KIFACE implementation.
Definition: kiface_base.h:39
bool IsSingle() const
Is this KIFACE running under single_top?
Definition: kiface_base.h:105
Represent a single user action.
Definition: tool_action.h:68
static int GetBaseUIId()
Definition: tool_action.h:148
const BITMAPS GetIcon() const
Return an icon associated with the action.
Definition: tool_action.h:192
wxString GetDescription(bool aIncludeHotkey=true) const
Definition: tool_action.cpp:97
wxString GetMenuItem() const
Definition: tool_action.cpp:89
int GetUIId() const
Definition: tool_action.h:130
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:144
Generic, UI-independent tool event.
Definition: tool_event.h:156
Master controller class:
Definition: tool_manager.h:55
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
VECTOR2D GetMousePosition() const
int GetHotKey(const TOOL_ACTION &aAction) const
#define _(s)
Base window classes and related definitions.
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
@ ID_POPUP_MENU_START
Definition: id.h:190
@ ID_POPUP_MENU_END
Definition: id.h:193
Macros and inline functions to create menus items in menubars or popup menus.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
static void OnCharHook(wxTextEntry *aTextEntry, wxKeyEvent &aEvent)
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition: tool_action.h:45
std::optional< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:557
@ TA_CHOICE_MENU_CHOICE
Definition: tool_event.h:93
@ TA_CHOICE_MENU_UPDATE
Definition: tool_event.h:89
@ TC_COMMAND
Definition: tool_event.h:52
@ MD_MODIFIER_MASK
Definition: tool_event.h:141
@ MD_ALT
Definition: tool_event.h:140
@ MD_CTRL
Definition: tool_event.h:139
@ MD_SHIFT
Definition: tool_event.h:138
wxLogTrace helper definitions.