KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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.GetTooltip(),
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,
210 BITMAPS::exit );
211#else
212 Add( _( "Close" ) + wxS( "\tCtrl+W" ),
213 wxString::Format( _( "Close %s" ), aAppname ),
214 wxID_CLOSE,
215 BITMAPS::exit );
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,
229 BITMAPS::exit );
230 }
231 else
232 {
233 AddClose( aAppname );
234 }
235}
236
237
238void ACTION_MENU::AddQuit( const wxString& aAppname )
239{
240 // Don't use ACTIONS::quit; wxWidgets moves this on OSX and expects to find it via
241 // wxID_EXIT
242 Add( _( "Quit" ) + wxS( "\tCtrl+Q" ),
243 wxString::Format( _( "Quit %s" ), aAppname ),
244 wxID_EXIT,
245 BITMAPS::exit );
246}
247
248
250{
251 m_titleDisplayed = false;
252
253 for( int i = GetMenuItemCount() - 1; i >= 0; --i )
254 Destroy( FindItemByPosition( i ) );
255
256 m_toolActions.clear();
257 m_submenus.clear();
258
259 wxASSERT( GetMenuItemCount() == 0 );
260}
261
262
264{
265 for( wxMenuItem* item : GetMenuItems() )
266 {
267 if( item->IsEnabled() && !item->IsSeparator() )
268 return true;
269 }
270
271 return false;
272}
273
274
276{
277 try
278 {
279 update();
280 }
281 catch( std::exception& )
282 {
283 }
284
285 if( m_tool )
287
288 runOnSubmenus( std::bind( &ACTION_MENU::UpdateAll, _1 ) );
289}
290
291
293{
294 m_dirty = false;
295 runOnSubmenus( std::bind( &ACTION_MENU::ClearDirty, _1 ) );
296}
297
298
300{
301 m_dirty = true;
302 runOnSubmenus( std::bind( &ACTION_MENU::SetDirty, _1 ) );
303}
304
305
307{
308 m_tool = aTool;
309 runOnSubmenus( std::bind( &ACTION_MENU::SetTool, _1, aTool ) );
310}
311
312
314{
315 ACTION_MENU* clone = create();
316 clone->Clear();
317 clone->copyFrom( *this );
318 return clone;
319}
320
321
323{
324 ACTION_MENU* menu = new ACTION_MENU( false );
325
326 wxASSERT_MSG( typeid( *this ) == typeid( *menu ),
327 wxString::Format( "You need to override create() method for class %s",
328 typeid( *this ).name() ) );
329
330 return menu;
331}
332
333
335{
336 return m_tool ? m_tool->GetManager() : nullptr;
337}
338
339
341{
342 TOOL_MANAGER* toolMgr = getToolManager();
343
344 wxASSERT( toolMgr );
345
346 for( std::pair<const int, const TOOL_ACTION*>& ii : m_toolActions )
347 {
348 int id = ii.first;
349 const TOOL_ACTION& action = *ii.second;
350 int key = toolMgr->GetHotKey( action ) & ~MD_MODIFIER_MASK;
351
352 if( key > 0 )
353 {
354 int mod = toolMgr->GetHotKey( action ) & MD_MODIFIER_MASK;
355 int flags = 0;
356 wxMenuItem* item = FindChildItem( id );
357
358 if( item )
359 {
360 flags |= ( mod & MD_ALT ) ? wxACCEL_ALT : 0;
361 flags |= ( mod & MD_CTRL ) ? wxACCEL_CTRL : 0;
362 flags |= ( mod & MD_SHIFT ) ? wxACCEL_SHIFT : 0;
363
364 if( !flags )
365 flags = wxACCEL_NORMAL;
366
367 wxAcceleratorEntry accel( flags, key, id, item );
368 item->SetAccel( &accel );
369 }
370 }
371 }
372}
373
374
375// wxWidgets doesn't tell us when a menu command was generated from a hotkey or from
376// a menu selection. It's important to us because a hotkey can be an immediate action
377// while the menu selection can not (as it has no associated position).
378//
379// We get around this by storing the last highlighted menuId. If it matches the command
380// id then we know this is a menu selection. (You might think we could use the menuOpen
381// menuClose events, but these are actually generated for hotkeys as well.)
382
384
385
386// We need to store the position of the mouse when the menu was opened so it can be passed
387// to the command event generated when the menu item is selected.
389
390
391void ACTION_MENU::OnIdle( wxIdleEvent& event )
392{
396}
397
398
399void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
400{
401 OPT_TOOL_EVENT evt;
402 wxString menuText;
403 wxEventType type = aEvent.GetEventType();
404 wxWindow* focus = wxWindow::FindFocus();
405 TOOL_MANAGER* toolMgr = getToolManager();
406
407 if( type == wxEVT_MENU_OPEN )
408 {
409 if( m_dirty && toolMgr )
410 toolMgr->RunAction<ACTION_MENU*>( ACTIONS::updateMenu, this );
411
412 wxMenu* parent = dynamic_cast<wxMenu*>( GetParent() );
413
414 // Don't update the position if this menu has a parent
415 if( !parent && toolMgr )
417
419 }
420 else if( type == wxEVT_MENU_HIGHLIGHT )
421 {
422 if( aEvent.GetId() > 0 )
423 g_last_menu_highlighted_id = aEvent.GetId();
424
425 evt = TOOL_EVENT( TC_COMMAND, TA_CHOICE_MENU_UPDATE, aEvent.GetId() );
426 }
427 else if( type == wxEVT_COMMAND_MENU_SELECTED )
428 {
429 // Despite our attempts to catch the theft of text editor CHAR_HOOK and CHAR events
430 // in TOOL_DISPATCHER::DispatchWxEvent, wxWidgets sometimes converts those it knows
431 // about into menu commands without ever generating the appropriate CHAR_HOOK and CHAR
432 // events first.
433 if( dynamic_cast<wxTextEntry*>( focus )
434 || dynamic_cast<wxStyledTextCtrl*>( focus )
435 || dynamic_cast<wxListView*>( focus ) )
436 {
437 // Original key event has been lost, so we have to re-create it from the menu's
438 // wxAcceleratorEntry.
439 wxMenuItem* menuItem = FindItem( aEvent.GetId() );
440 wxAcceleratorEntry* acceleratorKey = menuItem ? menuItem->GetAccel() : nullptr;
441
442 if( acceleratorKey )
443 {
444 wxKeyEvent keyEvent( wxEVT_CHAR_HOOK );
445 keyEvent.m_keyCode = acceleratorKey->GetKeyCode();
446 keyEvent.m_controlDown = ( acceleratorKey->GetFlags() & wxMOD_CONTROL ) > 0;
447 keyEvent.m_shiftDown = ( acceleratorKey->GetFlags() & wxMOD_SHIFT ) > 0;
448 keyEvent.m_altDown = ( acceleratorKey->GetFlags() & wxMOD_ALT ) > 0;
449
450 if( auto ctrl = dynamic_cast<wxTextEntry*>( focus ) )
451 TEXTENTRY_TRICKS::OnCharHook( ctrl, keyEvent );
452 else
453 focus->HandleWindowEvent( keyEvent );
454
455 if( keyEvent.GetSkipped() )
456 {
457 keyEvent.SetEventType( wxEVT_CHAR );
458 focus->HandleWindowEvent( keyEvent );
459 }
460
461 // If the event was used as KEY event (not skipped) by the focused window,
462 // just finish.
463 // Otherwise this is actually a wxEVT_COMMAND_MENU_SELECTED, or the
464 // focused window is read only
465 if( !keyEvent.GetSkipped() )
466 return;
467 }
468 }
469
470 // Store the selected position, so it can be checked by the tools
471 m_selected = aEvent.GetId();
472
473 ACTION_MENU* parent = dynamic_cast<ACTION_MENU*>( GetParent() );
474
475 while( parent )
476 {
477 parent->m_selected = m_selected;
478 parent = dynamic_cast<ACTION_MENU*>( parent->GetParent() );
479 }
480
481 // Check if there is a TOOL_ACTION for the given UI ID
482 if( toolMgr && toolMgr->GetActionManager()->IsActionUIId( m_selected ) )
483 evt = findToolAction( m_selected );
484
485 if( !evt )
486 {
487#ifdef __WINDOWS__
488 if( !evt )
489 {
490 // Try to find the submenu which holds the selected item
491 wxMenu* menu = nullptr;
492 FindItem( m_selected, &menu );
493
494 // This conditional compilation is probably not needed.
495 if( menu )
496 {
497 ACTION_MENU* cxmenu = static_cast<ACTION_MENU*>( menu );
498 evt = cxmenu->eventHandler( aEvent );
499 }
500 }
501#else
502 if( !evt )
503 runEventHandlers( aEvent, evt );
504#endif
505
506 // Handling non-ACTION menu entries. Two ranges of ids are supported:
507 // between 0 and ID_CONTEXT_MENU_ID_MAX
508 // between ID_POPUP_MENU_START and ID_POPUP_MENU_END
509
510 #define ID_CONTEXT_MENU_ID_MAX wxID_LOWEST /* = 100 should be plenty */
511
512 if( !evt &&
515 {
516 ACTION_MENU* actionMenu = dynamic_cast<ACTION_MENU*>( GetParent() );
517
518 if( actionMenu && actionMenu->PassHelpTextToHandler() )
519 menuText = GetHelpString( aEvent.GetId() );
520 else
521 menuText = GetLabelText( aEvent.GetId() );
522
524 evt->SetParameter( &menuText );
525 }
526 }
527 }
528
529 // forward the action/update event to the TOOL_MANAGER
530 // clients that don't supply a tool will have to check GetSelected() themselves
531 if( evt && toolMgr )
532 {
533 wxLogTrace( kicadTraceToolStack, wxS( "ACTION_MENU::OnMenuEvent %s" ), evt->Format() );
534
535 // WARNING: if you're squeamish, look away.
536 // What follows is a series of egregious hacks necessitated by a lack of information from
537 // wxWidgets on where context-menu-commands and command-key-events originated.
538
539 // If it's a context menu then fetch the mouse position from our context-menu-position
540 // hack.
541 if( m_isContextMenu )
542 {
543 evt->SetMousePosition( g_menu_open_position );
544 }
545 // Otherwise, if g_last_menu_highlighted_id matches then it's a menubar menu event and has
546 // no position.
547 else if( g_last_menu_highlighted_id == aEvent.GetId() )
548 {
549 evt->SetHasPosition( false );
550 }
551 // Otherwise it's a command-key-event and we need to get the mouse position from the tool
552 // manager so that immediate actions work.
553 else
554 {
555 evt->SetMousePosition( toolMgr->GetMousePosition() );
556 }
557
558 toolMgr->ProcessEvent( *evt );
559 }
560 else
561 {
562 aEvent.Skip();
563 }
564}
565
566
567void ACTION_MENU::runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent )
568{
569 aToolEvent = eventHandler( aMenuEvent );
570
571 if( !aToolEvent )
572 runOnSubmenus( std::bind( &ACTION_MENU::runEventHandlers, _1, aMenuEvent, aToolEvent ) );
573}
574
575
576void ACTION_MENU::runOnSubmenus( std::function<void(ACTION_MENU*)> aFunction )
577{
578 try
579 {
580 std::for_each( m_submenus.begin(), m_submenus.end(),
581 [&]( ACTION_MENU* m )
582 {
583 aFunction( m );
584 m->runOnSubmenus( aFunction );
585 } );
586 }
587 catch( std::exception& )
588 {
589 }
590}
591
592
594{
595 OPT_TOOL_EVENT evt;
596
597 auto findFunc =
598 [&]( ACTION_MENU* m )
599 {
600 if( evt )
601 return;
602
603 const auto it = m->m_toolActions.find( aId );
604
605 if( it != m->m_toolActions.end() )
606 evt = it->second->MakeEvent();
607 };
608
609 findFunc( this );
610
611 if( !evt )
612 runOnSubmenus( findFunc );
613
614 return evt;
615}
616
617
619{
620 m_icon = aMenu.m_icon;
621 m_title = aMenu.m_title;
623 m_selected = -1; // aMenu.m_selected;
624 m_tool = aMenu.m_tool;
626
627 // Copy all menu entries
628 for( int i = 0; i < (int) aMenu.GetMenuItemCount(); ++i )
629 {
630 wxMenuItem* item = aMenu.FindItemByPosition( i );
631 appendCopy( item );
632 }
633}
634
635
636wxMenuItem* ACTION_MENU::appendCopy( const wxMenuItem* aSource )
637{
638 wxMenuItem* newItem = new wxMenuItem( this, aSource->GetId(), aSource->GetItemLabel(),
639 aSource->GetHelp(), aSource->GetKind() );
640
641 // Add the source bitmap if it is not the wxNullBitmap
642 // On Windows, for Checkable Menu items, adding a bitmap adds also
643 // our predefined checked alternate bitmap
644 // On other OS, wxITEM_CHECK and wxITEM_RADIO Menu items do not use custom bitmaps.
645#if defined( _WIN32 )
646 // On Windows, AddBitmapToMenuItem() uses the unchecked bitmap for wxITEM_CHECK and
647 // wxITEM_RADIO menuitems and autoamtically adds a checked bitmap.
648 // For other menuitrms, use the "checked" bitmap.
649 bool use_checked_bm = ( aSource->GetKind() == wxITEM_CHECK ||
650 aSource->GetKind() == wxITEM_RADIO ) ? false : true;
651 const wxBitmap& src_bitmap = aSource->GetBitmap( use_checked_bm );
652#else
653 const wxBitmap& src_bitmap = aSource->GetBitmap();
654#endif
655
656 if( src_bitmap.IsOk() && src_bitmap.GetHeight() > 1 ) // a null bitmap has a 0 size
657 AddBitmapToMenuItem( newItem, src_bitmap );
658
659 if( aSource->IsSubMenu() )
660 {
661 ACTION_MENU* menu = dynamic_cast<ACTION_MENU*>( aSource->GetSubMenu() );
662 wxASSERT_MSG( menu, wxS( "Submenus are expected to be a ACTION_MENU" ) );
663
664 if( menu )
665 {
666 ACTION_MENU* menuCopy = menu->Clone();
667 newItem->SetSubMenu( menuCopy );
668 m_submenus.push_back( menuCopy );
669 }
670 }
671
672 // wxMenuItem has to be added before enabling/disabling or checking
673 Append( newItem );
674
675 if( aSource->IsCheckable() )
676 newItem->Check( aSource->IsChecked() );
677
678 newItem->Enable( aSource->IsEnabled() );
679
680 return newItem;
681}
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:106
void AddBitmapToMenuItem(wxMenuItem *aMenu, const wxBitmap &aImage)
Add a bitmap to a menuitem.
Definition: bitmap.cpp:252
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
@ INVALID_BITMAP
static TOOL_ACTION updateMenu
Definition: actions.h:177
bool IsActionUIId(int aId) const
Test if a UI ID corresponds to an action ID in our system.
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:266
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:213
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:278
bool m_isContextMenu
Menu title.
Definition: action_menu.h:263
virtual OPT_TOOL_EVENT eventHandler(const wxMenuEvent &)
Event handler stub.
Definition: action_menu.h:223
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
void AddQuit(const wxString &aAppname="")
Add a standard Quit item to the menu.
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:281
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:262
int m_selected
Creator of the menu.
Definition: action_menu.h:272
BITMAPS m_icon
Stores the id number of selected item.
Definition: action_menu.h:269
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:275
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:195
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:107
Represent a single user action.
Definition: tool_action.h:219
wxString GetTooltip(bool aIncludeHotkey=true) const
BITMAPS GetIcon() const
Return an icon associated with the action.
Definition: tool_action.h:365
wxString GetMenuItem() const
int GetUIId() const
Definition: tool_action.h:289
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:145
Generic, UI-independent tool event.
Definition: tool_event.h:167
Master controller class:
Definition: tool_manager.h:57
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:145
ACTION_MANAGER * GetActionManager() const
Definition: tool_manager.h:289
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:189
@ ID_POPUP_MENU_END
Definition: id.h:192
Macros and inline functions to create menus items in menubars or popup menus.
static void OnCharHook(wxTextEntry *aTextEntry, wxKeyEvent &aEvent)
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition: tool_action.h:48
std::optional< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:615
@ TA_CHOICE_MENU_CHOICE
Definition: tool_event.h:97
@ TA_CHOICE_MENU_UPDATE
Definition: tool_event.h:93
@ TC_COMMAND
Definition: tool_event.h:56
@ MD_MODIFIER_MASK
Definition: tool_event.h:145
@ MD_ALT
Definition: tool_event.h:144
@ MD_CTRL
Definition: tool_event.h:143
@ MD_SHIFT
Definition: tool_event.h:142
wxLogTrace helper definitions.