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 <tool/action_menu.h>
33#include <tool/actions.h>
34#include <tool/tool_event.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#include <wx/grid.h>
43#include <widgets/ui_common.h>
44
45using namespace std::placeholders;
46
47
48ACTION_MENU::ACTION_MENU( bool isContextMenu, TOOL_INTERACTIVE* aTool ) :
49 m_isForcedPosition( false ),
50 m_dirty( true ),
51 m_titleDisplayed( false ),
52 m_isContextMenu( isContextMenu ),
53 m_icon( BITMAPS::INVALID_BITMAP ),
54 m_selected( -1 ),
55 m_tool( aTool )
56{
58}
59
60
62{
63 Disconnect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ),
64 nullptr, this );
65 Disconnect( wxEVT_IDLE, wxIdleEventHandler( ACTION_MENU::OnIdle ), nullptr, this );
66
67 // Set parent to NULL to prevent submenus from unregistering from a nonexistent object
68 for( ACTION_MENU* menu : m_submenus )
69 menu->SetParent( nullptr );
70
71 ACTION_MENU* parent = dynamic_cast<ACTION_MENU*>( GetParent() );
72
73 if( parent )
74 parent->m_submenus.remove( this );
75}
76
77
79{
80 m_icon = aIcon;
81}
82
83
85{
86 Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), nullptr,
87 this );
88 Connect( wxEVT_IDLE, wxIdleEventHandler( ACTION_MENU::OnIdle ), nullptr, this );
89}
90
91
92void ACTION_MENU::SetTitle( const wxString& aTitle )
93{
94 // Unfortunately wxMenu::SetTitle() does not work very well, so this is an alternative version
95 m_title = aTitle;
96
97 // Update the menu title
99 DisplayTitle( true );
100}
101
102
103void ACTION_MENU::DisplayTitle( bool aDisplay )
104{
105 if( ( !aDisplay || m_title.IsEmpty() ) && m_titleDisplayed )
106 {
107 // Destroy the menu entry keeping the title..
108 wxMenuItem* item = FindItemByPosition( 0 );
109 wxASSERT( item->GetItemLabelText() == GetTitle() );
110 Destroy( item );
111 // ..and separator
112 item = FindItemByPosition( 0 );
113 wxASSERT( item->IsSeparator() );
114 Destroy( item );
115 m_titleDisplayed = false;
116 }
117
118 else if( aDisplay && !m_title.IsEmpty() )
119 {
120 if( m_titleDisplayed )
121 {
122 // Simply update the title
123 FindItemByPosition( 0 )->SetItemLabel( m_title );
124 }
125 else
126 {
127 // Add a separator and a menu entry to display the title
128 InsertSeparator( 0 );
129 Insert( 0, new wxMenuItem( this, wxID_NONE, m_title, wxEmptyString, wxITEM_NORMAL ) );
130
131 if( !!m_icon )
132 KIUI::AddBitmapToMenuItem( FindItemByPosition( 0 ), KiBitmap( m_icon ) );
133
134 m_titleDisplayed = true;
135 }
136 }
137}
138
139
140wxMenuItem* ACTION_MENU::Add( const wxString& aLabel, int aId, BITMAPS aIcon )
141{
142 wxASSERT_MSG( FindItem( aId ) == nullptr, wxS( "Duplicate menu IDs!" ) );
143
144 wxMenuItem* item = new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL );
145
146 if( !!aIcon )
147 KIUI::AddBitmapToMenuItem( item, KiBitmap( aIcon ) );
148
149 return Append( item );
150}
151
152
153wxMenuItem* ACTION_MENU::Add( const wxString& aLabel, const wxString& aTooltip, int aId,
154 BITMAPS aIcon, bool aIsCheckmarkEntry )
155{
156 wxASSERT_MSG( FindItem( aId ) == nullptr, wxS( "Duplicate menu IDs!" ) );
157
158 wxMenuItem* item = new wxMenuItem( this, aId, aLabel, aTooltip,
159 aIsCheckmarkEntry ? wxITEM_CHECK : wxITEM_NORMAL );
160
161 if( !!aIcon )
162 KIUI::AddBitmapToMenuItem( item, KiBitmap( aIcon ) );
163
164 return Append( item );
165}
166
167
168wxMenuItem* ACTION_MENU::Add( const TOOL_ACTION& aAction, bool aIsCheckmarkEntry,
169 const wxString& aOverrideLabel )
170{
172 BITMAPS icon = aAction.GetIcon();
173
174 // Allow the label to be overridden at point of use
175 wxString menuLabel = aOverrideLabel.IsEmpty() ? aAction.GetMenuItem() : aOverrideLabel;
176
177 wxMenuItem* item = new wxMenuItem( this, aAction.GetUIId(), menuLabel,
178 aAction.GetTooltip(),
179 aIsCheckmarkEntry ? wxITEM_CHECK : wxITEM_NORMAL );
180 if( !!icon )
181 KIUI::AddBitmapToMenuItem( item, KiBitmap( icon ) );
182
183 m_toolActions[aAction.GetUIId()] = &aAction;
184
185 return Append( item );
186}
187
188
189wxMenuItem* ACTION_MENU::Add( ACTION_MENU* aMenu )
190{
191 m_submenus.push_back( aMenu );
192
193 wxASSERT_MSG( !aMenu->m_title.IsEmpty(), wxS( "Set a title for ACTION_MENU using SetTitle()" ) );
194
195 if( !!aMenu->m_icon )
196 {
197 wxMenuItem* newItem = new wxMenuItem( this, -1, aMenu->m_title );
198 KIUI::AddBitmapToMenuItem( newItem, KiBitmap( aMenu->m_icon ) );
199 newItem->SetSubMenu( aMenu );
200 return Append( newItem );
201 }
202 else
203 {
204 return AppendSubMenu( aMenu, aMenu->m_title );
205 }
206}
207
208
209void ACTION_MENU::AddClose( const wxString& aAppname )
210{
211#ifdef __WINDOWS__
212 Add( _( "Close" ),
213 wxString::Format( _( "Close %s" ), aAppname ),
214 wxID_CLOSE,
215 BITMAPS::exit );
216#else
217 Add( _( "Close" ) + wxS( "\tCtrl+W" ),
218 wxString::Format( _( "Close %s" ), aAppname ),
219 wxID_CLOSE,
220 BITMAPS::exit );
221#endif
222}
223
224
225void ACTION_MENU::AddQuitOrClose( KIFACE_BASE* aKiface, wxString aAppname )
226{
227 if( !aKiface || aKiface->IsSingle() ) // not when under a project mgr
228 {
229 // Don't use ACTIONS::quit; wxWidgets moves this on OSX and expects to find it via
230 // wxID_EXIT
231 Add( _( "Quit" ) + wxS( "\tCtrl+Q" ),
232 wxString::Format( _( "Quit %s" ), aAppname ),
233 wxID_EXIT,
234 BITMAPS::exit );
235 }
236 else
237 {
238 AddClose( aAppname );
239 }
240}
241
242
243void ACTION_MENU::AddQuit( const wxString& aAppname )
244{
245 // Don't use ACTIONS::quit; wxWidgets moves this on OSX and expects to find it via
246 // wxID_EXIT
247 Add( _( "Quit" ) + wxS( "\tCtrl+Q" ),
248 wxString::Format( _( "Quit %s" ), aAppname ),
249 wxID_EXIT,
250 BITMAPS::exit );
251}
252
253
255{
256 m_titleDisplayed = false;
257
258 for( int i = GetMenuItemCount() - 1; i >= 0; --i )
259 Destroy( FindItemByPosition( i ) );
260
261 m_toolActions.clear();
262 m_submenus.clear();
263
264 wxASSERT( GetMenuItemCount() == 0 );
265}
266
267
269{
270 for( wxMenuItem* item : GetMenuItems() )
271 {
272 if( item->IsEnabled() && !item->IsSeparator() )
273 return true;
274 }
275
276 return false;
277}
278
279
281{
282 try
283 {
284 update();
285 }
286 catch( std::exception& )
287 {
288 }
289
290 if( m_tool )
292
293 runOnSubmenus( std::bind( &ACTION_MENU::UpdateAll, _1 ) );
294}
295
296
298{
299 m_dirty = false;
300 runOnSubmenus( std::bind( &ACTION_MENU::ClearDirty, _1 ) );
301}
302
303
305{
306 m_dirty = true;
307 runOnSubmenus( std::bind( &ACTION_MENU::SetDirty, _1 ) );
308}
309
310
312{
313 m_tool = aTool;
314 runOnSubmenus( std::bind( &ACTION_MENU::SetTool, _1, aTool ) );
315}
316
317
319{
320 ACTION_MENU* clone = create();
321 clone->Clear();
322 clone->copyFrom( *this );
323 return clone;
324}
325
326
328{
329 ACTION_MENU* menu = new ACTION_MENU( false );
330
331 wxASSERT_MSG( typeid( *this ) == typeid( *menu ),
332 wxString::Format( "You need to override create() method for class %s",
333 typeid( *this ).name() ) );
334
335 return menu;
336}
337
338
340{
341 return m_tool ? m_tool->GetManager() : nullptr;
342}
343
344
346{
347 TOOL_MANAGER* toolMgr = getToolManager();
348
349 wxASSERT( toolMgr );
350
351 for( std::pair<const int, const TOOL_ACTION*>& ii : m_toolActions )
352 {
353 int id = ii.first;
354 const TOOL_ACTION& action = *ii.second;
355 int key = toolMgr->GetHotKey( action ) & ~MD_MODIFIER_MASK;
356
357 if( key > 0 )
358 {
359 int mod = toolMgr->GetHotKey( action ) & MD_MODIFIER_MASK;
360 int flags = 0;
361 wxMenuItem* item = FindChildItem( id );
362
363 if( item )
364 {
365 flags |= ( mod & MD_ALT ) ? wxACCEL_ALT : 0;
366 flags |= ( mod & MD_CTRL ) ? wxACCEL_CTRL : 0;
367 flags |= ( mod & MD_SHIFT ) ? wxACCEL_SHIFT : 0;
368
369 if( !flags )
370 flags = wxACCEL_NORMAL;
371
372 wxAcceleratorEntry accel( flags, key, id, item );
373 item->SetAccel( &accel );
374 }
375 }
376 }
377}
378
379
380// wxWidgets doesn't tell us when a menu command was generated from a hotkey or from
381// a menu selection. It's important to us because a hotkey can be an immediate action
382// while the menu selection can not (as it has no associated position).
383//
384// We get around this by storing the last highlighted menuId. If it matches the command
385// id then we know this is a menu selection. (You might think we could use the menuOpen
386// menuClose events, but these are actually generated for hotkeys as well.)
387
389
390
391// We need to store the position of the mouse when the menu was opened so it can be passed
392// to the command event generated when the menu item is selected.
394
395
396void ACTION_MENU::OnIdle( wxIdleEvent& event )
397{
401}
402
403
404void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
405{
406 OPT_TOOL_EVENT evt;
407 wxString menuText;
408 wxEventType type = aEvent.GetEventType();
409 wxWindow* focus = wxWindow::FindFocus();
410 TOOL_MANAGER* toolMgr = getToolManager();
411
412 if( type == wxEVT_MENU_OPEN )
413 {
414 if( m_dirty && toolMgr )
415 toolMgr->RunAction<ACTION_MENU*>( ACTIONS::updateMenu, this );
416
417 wxMenu* parent = dynamic_cast<wxMenu*>( GetParent() );
418
419 // Don't update the position if this menu has a parent or is a menubar menu
420 if( !parent && !IsAttached() && toolMgr )
422
424 }
425 else if( type == wxEVT_MENU_HIGHLIGHT )
426 {
427 if( aEvent.GetId() > 0 )
428 g_last_menu_highlighted_id = aEvent.GetId();
429
430 evt = TOOL_EVENT( TC_COMMAND, TA_CHOICE_MENU_UPDATE, aEvent.GetId() );
431 }
432 else if( type == wxEVT_COMMAND_MENU_SELECTED )
433 {
434 // Despite our attempts to catch the theft of text editor CHAR_HOOK and CHAR events
435 // in TOOL_DISPATCHER::DispatchWxEvent, wxWidgets sometimes converts those it knows
436 // about into menu commands without ever generating the appropriate CHAR_HOOK and CHAR
437 // events first.
438 if( dynamic_cast<wxTextEntry*>( focus )
439 || dynamic_cast<wxStyledTextCtrl*>( focus )
440 || dynamic_cast<wxListView*>( focus )
441 || dynamic_cast<wxGrid*>( focus ) )
442 {
443 // Original key event has been lost, so we have to re-create it from the menu's
444 // wxAcceleratorEntry.
445 wxMenuItem* menuItem = FindItem( aEvent.GetId() );
446 wxAcceleratorEntry* acceleratorKey = menuItem ? menuItem->GetAccel() : nullptr;
447
448 if( acceleratorKey )
449 {
450 wxKeyEvent keyEvent( wxEVT_CHAR_HOOK );
451 keyEvent.m_keyCode = acceleratorKey->GetKeyCode();
452 keyEvent.m_controlDown = ( acceleratorKey->GetFlags() & wxMOD_CONTROL ) > 0;
453 keyEvent.m_shiftDown = ( acceleratorKey->GetFlags() & wxMOD_SHIFT ) > 0;
454 keyEvent.m_altDown = ( acceleratorKey->GetFlags() & wxMOD_ALT ) > 0;
455
456 if( wxTextEntry* ctrl = dynamic_cast<wxTextEntry*>( focus ) )
457 TEXTENTRY_TRICKS::OnCharHook( ctrl, keyEvent );
458 else
459 focus->HandleWindowEvent( keyEvent );
460
461 if( keyEvent.GetSkipped() )
462 {
463 keyEvent.SetEventType( wxEVT_CHAR );
464 focus->HandleWindowEvent( keyEvent );
465 }
466
467 // Don't bubble-up dangerous actions; the target may be behind a modeless dialog.
468 // Cf. https://gitlab.com/kicad/code/kicad/-/issues/17229
469 if( keyEvent.GetKeyCode() == WXK_BACK || keyEvent.GetKeyCode() == WXK_DELETE )
470 return;
471
472 // If the event was used as a KEY event (not skipped) by the focused window,
473 // just finish. Otherwise this is actually a wxEVT_COMMAND_MENU_SELECTED (or the
474 // focused window is read only).
475 if( !keyEvent.GetSkipped() )
476 return;
477 }
478 }
479
480 // Store the selected position, so it can be checked by the tools
481 m_selected = aEvent.GetId();
482
483 ACTION_MENU* parent = dynamic_cast<ACTION_MENU*>( GetParent() );
484
485 while( parent )
486 {
487 parent->m_selected = m_selected;
488 parent = dynamic_cast<ACTION_MENU*>( parent->GetParent() );
489 }
490
491 // Check if there is a TOOL_ACTION for the given UI ID
492 if( toolMgr && toolMgr->GetActionManager()->IsActionUIId( m_selected ) )
493 evt = findToolAction( m_selected );
494
495 if( !evt )
496 {
497#ifdef __WINDOWS__
498 if( !evt )
499 {
500 // Try to find the submenu which holds the selected item
501 wxMenu* menu = nullptr;
502 FindItem( m_selected, &menu );
503
504 // This conditional compilation is probably not needed.
505 if( menu )
506 {
507 ACTION_MENU* cxmenu = static_cast<ACTION_MENU*>( menu );
508 evt = cxmenu->eventHandler( aEvent );
509 }
510 }
511#else
512 if( !evt )
513 runEventHandlers( aEvent, evt );
514#endif
515
516 // Handling non-ACTION menu entries. Two ranges of ids are supported:
517 // between 0 and ID_CONTEXT_MENU_ID_MAX
518 // between ID_POPUP_MENU_START and ID_POPUP_MENU_END
519
520 #define ID_CONTEXT_MENU_ID_MAX wxID_LOWEST /* = 100 should be plenty */
521
522 if( !evt &&
525 {
526 ACTION_MENU* actionMenu = dynamic_cast<ACTION_MENU*>( GetParent() );
527
528 if( actionMenu && actionMenu->PassHelpTextToHandler() )
529 menuText = GetHelpString( aEvent.GetId() );
530 else
531 menuText = GetLabelText( aEvent.GetId() );
532
534 evt->SetParameter( &menuText );
535 }
536 }
537 }
538
539 // forward the action/update event to the TOOL_MANAGER
540 // clients that don't supply a tool will have to check GetSelected() themselves
541 if( evt && toolMgr )
542 {
543 wxLogTrace( kicadTraceToolStack, wxS( "ACTION_MENU::OnMenuEvent %s" ), evt->Format() );
544
545 // WARNING: if you're squeamish, look away.
546 // What follows is a series of egregious hacks necessitated by a lack of information from
547 // wxWidgets on where context-menu-commands and command-key-events originated.
548
549 // If it's a context menu then fetch the mouse position from our context-menu-position
550 // hack.
551 if( m_isContextMenu )
552 {
553 evt->SetMousePosition( g_menu_open_position );
554 }
555 // Check if it is a menubar event, and don't get any position if it is. Note that we
556 // can't use IsAttached() here, as it only differentiates a context menu, and we also
557 // want a hotkey to generate a position.
558 else if( g_last_menu_highlighted_id == aEvent.GetId() )
559 {
560 evt->SetHasPosition( false );
561 }
562 // Otherwise it's a command-key-event and we need to get the mouse position from the tool
563 // manager so that immediate actions work.
564 else
565 {
566 evt->SetMousePosition( toolMgr->GetMousePosition() );
567 }
568
569 toolMgr->ProcessEvent( *evt );
570 }
571 else
572 {
573 aEvent.Skip();
574 }
575}
576
577
578void ACTION_MENU::runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent )
579{
580 aToolEvent = eventHandler( aMenuEvent );
581
582 if( !aToolEvent )
583 runOnSubmenus( std::bind( &ACTION_MENU::runEventHandlers, _1, aMenuEvent, aToolEvent ) );
584}
585
586
587void ACTION_MENU::runOnSubmenus( std::function<void(ACTION_MENU*)> aFunction )
588{
589 try
590 {
591 std::for_each( m_submenus.begin(), m_submenus.end(),
592 [&]( ACTION_MENU* m )
593 {
594 aFunction( m );
595 m->runOnSubmenus( aFunction );
596 } );
597 }
598 catch( std::exception& )
599 {
600 }
601}
602
603
605{
606 OPT_TOOL_EVENT evt;
607
608 auto findFunc =
609 [&]( ACTION_MENU* m )
610 {
611 if( evt )
612 return;
613
614 const auto it = m->m_toolActions.find( aId );
615
616 if( it != m->m_toolActions.end() )
617 evt = it->second->MakeEvent();
618 };
619
620 findFunc( this );
621
622 if( !evt )
623 runOnSubmenus( findFunc );
624
625 return evt;
626}
627
628
630{
631 m_icon = aMenu.m_icon;
632 m_title = aMenu.m_title;
634 m_selected = -1; // aMenu.m_selected;
635 m_tool = aMenu.m_tool;
637
638 // Copy all menu entries
639 for( int i = 0; i < (int) aMenu.GetMenuItemCount(); ++i )
640 {
641 wxMenuItem* item = aMenu.FindItemByPosition( i );
642 appendCopy( item );
643 }
644}
645
646
647wxMenuItem* ACTION_MENU::appendCopy( const wxMenuItem* aSource )
648{
649 wxMenuItem* newItem = new wxMenuItem( this, aSource->GetId(), aSource->GetItemLabel(),
650 aSource->GetHelp(), aSource->GetKind() );
651
652 // Add the source bitmap if it is not the wxNullBitmap
653 // On Windows, for Checkable Menu items, adding a bitmap adds also
654 // our predefined checked alternate bitmap
655 // On other OS, wxITEM_CHECK and wxITEM_RADIO Menu items do not use custom bitmaps.
656#if defined( _WIN32 )
657 // On Windows, AddBitmapToMenuItem() uses the unchecked bitmap for wxITEM_CHECK and
658 // wxITEM_RADIO menuitems and autoamtically adds a checked bitmap.
659 // For other menuitrms, use the "checked" bitmap.
660 bool use_checked_bm = ( aSource->GetKind() == wxITEM_CHECK ||
661 aSource->GetKind() == wxITEM_RADIO ) ? false : true;
662 const wxBitmap& src_bitmap = aSource->GetBitmap( use_checked_bm );
663#else
664 const wxBitmap& src_bitmap = aSource->GetBitmap();
665#endif
666
667 if( src_bitmap.IsOk() && src_bitmap.GetHeight() > 1 ) // a null bitmap has a 0 size
668 KIUI::AddBitmapToMenuItem( newItem, src_bitmap );
669
670 if( aSource->IsSubMenu() )
671 {
672 ACTION_MENU* menu = dynamic_cast<ACTION_MENU*>( aSource->GetSubMenu() );
673 wxASSERT_MSG( menu, wxS( "Submenus are expected to be a ACTION_MENU" ) );
674
675 if( menu )
676 {
677 ACTION_MENU* menuCopy = menu->Clone();
678 newItem->SetSubMenu( menuCopy );
679 m_submenus.push_back( menuCopy );
680 }
681 }
682
683 // wxMenuItem has to be added before enabling/disabling or checking
684 Append( newItem );
685
686 if( aSource->IsCheckable() )
687 newItem->Check( aSource->IsChecked() );
688
689 newItem->Enable( aSource->IsEnabled() );
690
691 return newItem;
692}
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:104
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
@ INVALID_BITMAP
static TOOL_ACTION updateMenu
Definition: actions.h:204
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:48
void SetDirty()
TOOL_MANAGER * getToolManager() const
void setupEvents()
Update hot key settings for TOOL_ACTIONs in this menu.
Definition: action_menu.cpp:84
wxString m_title
Optional icon.
Definition: action_menu.h:269
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:216
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:281
bool m_isContextMenu
Menu title.
Definition: action_menu.h:266
virtual OPT_TOOL_EVENT eventHandler(const wxMenuEvent &)
Event handler stub.
Definition: action_menu.h:226
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.
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:92
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:284
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:78
~ACTION_MENU() override
Definition: action_menu.cpp:61
wxString GetTitle() const
Definition: action_menu.h:68
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
bool m_titleDisplayed
Definition: action_menu.h:265
int m_selected
Creator of the menu.
Definition: action_menu.h:275
BITMAPS m_icon
Stores the id number of selected item.
Definition: action_menu.h:272
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:278
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:198
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:269
wxString GetTooltip(bool aIncludeHotkey=true) const
BITMAPS GetIcon() const
Return an icon associated with the action.
Definition: tool_action.h:422
wxString GetMenuItem() const
int GetUIId() const
Definition: tool_action.h:339
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:297
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
KICOMMON_API void AddBitmapToMenuItem(wxMenuItem *aMenu, const wxBitmap &aImage)
Add a bitmap to a menuitem.
Definition: ui_common.cpp:355
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:629
@ 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.
Functions to provide common constants and other functions to assist in making a consistent UI.