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