kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #31084
Need testers for a patch to merge hotkeys and accelerators
Hi All,
Currently, when a key is used as hotkey and if we want to display it in a sub-menu of the main menu,
because it becomes a accelerator key, we need to modify it (adding shift or alt modifier) when the
action differs (uses the mouse position) when called from a menu or a key.
Although there are not a lot of cases (zoom in and out are 2 cases, and there are more cases in
Eeschema), this is annoying for 2 reasons:
- Many users do not know the difference between a accelerator key and a hotkey.
- 2 similar actions use 2 keys instead of only one key, and we do not have a lot of available keys
for hotkeys, so wasting a few keys is very annoying.
I wrote a patch to use the same key as accelerator key and hotkey.
In fact, if a menu uses (for a accelerator key) the same key as a hotkey, the key event is not sent
to this menu, and the "accelerator key" becomes just a comment in menu.
To do that, the EVT_CHAR_HOOK key event is now managed by the main frame and is filtered, and not
sent to the GUI if a hotkey handles this key event (this is the normal way to handle keys whenn we
have special requirements).
Unfortunately, the way EVT_CHAR_HOOK and EVT_CHAR key events are exactly working is highly dependent
of platforms, and a bit tricky.
I tested this patch on Windows 32 bits, and partially on Linux (I was not able to test the python
console), but not on OSX.
Obviously, it must be tested (both in legacy canvas and GEL canvas) on OSX, and Linux (and of course
on Windows 64 bits), and especially with Pcbnew in python console:
are all chars captured in the console, especially the 2 accelerators 'O' and 'X'
Thanks.
--
Jean-Pierre CHARRAS
common/draw_frame.cpp | 16 ++++++++++++++++
common/draw_panel.cpp | 2 +-
common/tool/tool_dispatcher.cpp | 31 +++++++++++--------------------
common/tool/tool_manager.cpp | 12 ++++++++----
eeschema/menubar.cpp | 32 ++++++++++++++++----------------
eeschema/schframe.h | 1 -
include/class_draw_panel_gal.h | 9 +++++++++
include/draw_frame.h | 8 ++++++++
include/tool/tool_manager.h | 6 ++++--
pcbnew/menubar_modedit.cpp | 4 ++--
pcbnew/menubar_pcbframe.cpp | 6 +++---
11 files changed, 78 insertions(+), 49 deletions(-)
diff --git a/common/draw_frame.cpp b/common/draw_frame.cpp
index d559a84..5389963 100644
--- a/common/draw_frame.cpp
+++ b/common/draw_frame.cpp
@@ -95,6 +95,8 @@ const wxChar EDA_DRAW_FRAME::CANVAS_TYPE_KEY[] = wxT( "canvas_type" );
static const wxString MaxUndoItemsEntry(wxT( "DevelMaxUndoItems" ) );
BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER )
+ EVT_CHAR_HOOK( EDA_DRAW_FRAME::OnCharHook )
+
EVT_MOUSEWHEEL( EDA_DRAW_FRAME::OnMouseEvent )
EVT_MENU_OPEN( EDA_DRAW_FRAME::OnMenuOpen )
EVT_ACTIVATE( EDA_DRAW_FRAME::OnActivate )
@@ -227,6 +229,20 @@ EDA_DRAW_FRAME::~EDA_DRAW_FRAME()
}
+void EDA_DRAW_FRAME::OnCharHook( wxKeyEvent& event )
+{
+ // This event is filtered: if the key is a hotkey, it will
+ // not be skipped ( sent to the GUI) but if this is not a hotkey
+ // it will be sent to the GUI because it can be an accelerator key
+ if( IsGalCanvasActive() && GetGalCanvas() )
+ GetGalCanvas()->OnKeyEvent( event );
+ else if( GetCanvas() )
+ GetCanvas()->OnKeyEvent( event );
+ else // no active canvas (should not occur)
+ event.Skip();
+}
+
+
void EDA_DRAW_FRAME::ReleaseFile()
{
m_file_checker = nullptr;
diff --git a/common/draw_panel.cpp b/common/draw_panel.cpp
index baf5e98..27cfdbe 100644
--- a/common/draw_panel.cpp
+++ b/common/draw_panel.cpp
@@ -82,7 +82,7 @@ BEGIN_EVENT_TABLE( EDA_DRAW_PANEL, wxScrolledWindow )
#endif
EVT_MOUSE_EVENTS( EDA_DRAW_PANEL::OnMouseEvent )
EVT_CHAR( EDA_DRAW_PANEL::OnKeyEvent )
- EVT_CHAR_HOOK( EDA_DRAW_PANEL::OnCharHook )
+ //EVT_CHAR_HOOK( EDA_DRAW_PANEL::OnCharHook )
EVT_PAINT( EDA_DRAW_PANEL::OnPaint )
EVT_ERASE_BACKGROUND( EDA_DRAW_PANEL::OnEraseBackground )
EVT_SCROLLWIN( EDA_DRAW_PANEL::OnScroll )
diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp
index 5c9113f..45388bf 100644
--- a/common/tool/tool_dispatcher.cpp
+++ b/common/tool/tool_dispatcher.cpp
@@ -254,7 +254,7 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti
// the GUI. These key codes are known to be used in pcbnew to move the cursor
// or change active layer, and have a default action (moving scrollbar button) if
// the event is skipped
-bool isKeySpecialCode( int aKeyCode )
+/*bool isKeySpecialCode( int aKeyCode )
{
const enum wxKeyCode special_keys[] =
{
@@ -274,6 +274,7 @@ bool isKeySpecialCode( int aKeyCode )
return isInList;
}
+*/
/* aHelper class that convert some special key codes to an equivalent.
* WXK_NUMPAD_UP to WXK_UP,
@@ -309,7 +310,8 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
bool motion = false, buttonEvents = false;
boost::optional<TOOL_EVENT> evt;
int key = 0; // key = 0 if the event is not a key event
- bool keyIsSpecial = false; // True if the key is a special key code
+ //bool keyIsSpecial = false; // True if the key is a special key code
+ bool key_handled = false;
int type = aEvent.GetEventType();
@@ -358,21 +360,9 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
{
wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
key = ke->GetKeyCode();
- keyIsSpecial = isKeySpecialCode( key );
+ //keyIsSpecial = isKeySpecialCode( key );
- // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK
- // and do nothing.
- // a wxEVT_CHAR will be fired by wxWidgets later for this key.
- if( type == wxEVT_CHAR_HOOK )
- {
- if( !keyIsSpecial )
- {
- aEvent.Skip();
- return;
- }
- else
- key = translateSpecialCode( key );
- }
+ key = translateSpecialCode( key );
int mods = decodeModifiers( ke );
@@ -396,7 +386,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
}
if( evt )
- m_toolMgr->ProcessEvent( *evt );
+ key_handled = m_toolMgr->ProcessEvent( *evt );
// pass the event to the GUI, it might still be interested in it
// Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by kicad
@@ -418,10 +408,11 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
// The suitable Skip is already called, but the wxEVT_CHAR
// must be Skipped (sent to GUI).
// Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
-#ifndef __APPLE__
- if( type == wxEVT_CHAR && !keyIsSpecial )
+//#ifndef __APPLE__
+ if( (type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK )
+ /*&& !keyIsSpecial*/ && !key_handled )
aEvent.Skip();
-#endif
+//#endif
updateUI();
}
diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp
index d1c7f95..9c869ed 100644
--- a/common/tool/tool_manager.cpp
+++ b/common/tool/tool_manager.cpp
@@ -728,9 +728,9 @@ TOOL_MANAGER::ID_LIST::iterator TOOL_MANAGER::finishTool( TOOL_STATE* aState )
}
-void TOOL_MANAGER::ProcessEvent( const TOOL_EVENT& aEvent )
+bool TOOL_MANAGER::ProcessEvent( const TOOL_EVENT& aEvent )
{
- processEvent( aEvent );
+ bool hotkey_handled = processEvent( aEvent );
if( TOOL_STATE* active = GetCurrentToolState() )
{
@@ -742,6 +742,8 @@ void TOOL_MANAGER::ProcessEvent( const TOOL_EVENT& aEvent )
EDA_DRAW_FRAME* f = static_cast<EDA_DRAW_FRAME*>( GetEditFrame() );
f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER.
}
+
+ return hotkey_handled;
}
@@ -859,11 +861,11 @@ void TOOL_MANAGER::popViewControls()
}
-void TOOL_MANAGER::processEvent( const TOOL_EVENT& aEvent )
+bool TOOL_MANAGER::processEvent( const TOOL_EVENT& aEvent )
{
// Early dispatch of events destined for the TOOL_MANAGER
if( !dispatchStandardEvents( aEvent ) )
- return;
+ return true;
dispatchInternal( aEvent );
dispatchActivation( aEvent );
@@ -876,6 +878,8 @@ void TOOL_MANAGER::processEvent( const TOOL_EVENT& aEvent )
m_eventQueue.pop_front();
processEvent( event );
}
+
+ return false;
}
bool TOOL_MANAGER::IsToolActive( TOOL_ID aId ) const
diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp
index 056a8ac..c7fb23e 100644
--- a/eeschema/menubar.cpp
+++ b/eeschema/menubar.cpp
@@ -153,11 +153,11 @@ void prepareViewMenu( wxMenu* aParentMenu )
*/
text = AddHotkeyName( _( "Zoom &In" ), g_Schematic_Hokeys_Descr,
- HK_ZOOM_IN, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ZOOM_IN/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_ZOOM_IN, text, HELP_ZOOM_IN, KiBitmap( zoom_in_xpm ) );
text = AddHotkeyName( _( "Zoom &Out" ), g_Schematic_Hokeys_Descr,
- HK_ZOOM_OUT, IS_ACCELERATOR ); // add accelerator, not a shortcut
+ HK_ZOOM_OUT/*, IS_ACCELERATOR*/ ); // add accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_ZOOM_OUT, text, HELP_ZOOM_OUT, KiBitmap( zoom_out_xpm ) );
text = AddHotkeyName( _( "&Fit on Screen" ), g_Schematic_Hokeys_Descr, HK_ZOOM_AUTO );
@@ -191,59 +191,59 @@ void preparePlaceMenu( wxMenu* aParentMenu )
wxString text;
text = AddHotkeyName( _( "&Component" ), g_Schematic_Hokeys_Descr,
- HK_ADD_NEW_COMPONENT, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_NEW_COMPONENT/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_SCH_PLACE_COMPONENT, text,
HELP_PLACE_COMPONENTS,
KiBitmap( add_component_xpm ) );
text = AddHotkeyName( _( "&Power Port" ), g_Schematic_Hokeys_Descr,
- HK_ADD_NEW_POWER, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_NEW_POWER/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_PLACE_POWER_BUTT, text,
HELP_PLACE_POWERPORT,
KiBitmap( add_power_xpm ) );
text = AddHotkeyName( _( "&Wire" ), g_Schematic_Hokeys_Descr,
- HK_BEGIN_WIRE, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_BEGIN_WIRE/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_WIRE_BUTT, text,
HELP_PLACE_WIRE,
KiBitmap( add_line_xpm ) );
text = AddHotkeyName( _( "&Bus" ), g_Schematic_Hokeys_Descr,
- HK_BEGIN_BUS, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_BEGIN_BUS/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_BUS_BUTT, text,
HELP_PLACE_BUS,
KiBitmap( add_bus_xpm ) );
text = AddHotkeyName( _( "Wire to Bus &Entry" ), g_Schematic_Hokeys_Descr,
- HK_ADD_WIRE_ENTRY, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_WIRE_ENTRY/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_WIRETOBUS_ENTRY_BUTT, text,
HELP_PLACE_WIRE2BUS_ENTRY,
KiBitmap( add_line2bus_xpm ) );
text = AddHotkeyName( _( "Bus &to Bus Entry" ), g_Schematic_Hokeys_Descr,
- HK_ADD_BUS_ENTRY, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_BUS_ENTRY/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_BUSTOBUS_ENTRY_BUTT, text,
HELP_PLACE_BUS2BUS_ENTRY,
KiBitmap( add_bus2bus_xpm ) );
text = AddHotkeyName( _( "&No Connect Flag" ), g_Schematic_Hokeys_Descr,
- HK_ADD_NOCONN_FLAG, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_NOCONN_FLAG/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_NOCONN_BUTT, text, HELP_PLACE_NC_FLAG, KiBitmap( noconn_xpm ) );
text = AddHotkeyName( _( "&Junction" ), g_Schematic_Hokeys_Descr,
- HK_ADD_JUNCTION, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_JUNCTION/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_JUNCTION_BUTT, text,
HELP_PLACE_JUNCTION,
KiBitmap( add_junction_xpm ) );
text = AddHotkeyName( _( "&Label" ), g_Schematic_Hokeys_Descr,
- HK_ADD_LABEL, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_LABEL/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_LABEL_BUTT, text,
HELP_PLACE_NETLABEL,
KiBitmap( add_line_label_xpm ) );
text = AddHotkeyName( _( "Gl&obal Label" ), g_Schematic_Hokeys_Descr,
- HK_ADD_GLABEL, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_GLABEL/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_GLABEL_BUTT, text,
HELP_PLACE_GLOBALLABEL,
KiBitmap( add_glabel_xpm ) );
@@ -251,14 +251,14 @@ void preparePlaceMenu( wxMenu* aParentMenu )
aParentMenu->AppendSeparator();
text = AddHotkeyName( _( "&Hierarchical Label" ), g_Schematic_Hokeys_Descr,
- HK_ADD_HLABEL, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_HLABEL/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_HIERLABEL_BUTT,
text, HELP_PLACE_HIER_LABEL,
KiBitmap( add_hierarchical_label_xpm ) );
text = AddHotkeyName( _( "Hierarchical &Sheet" ), g_Schematic_Hokeys_Descr,
- HK_ADD_HIER_SHEET, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_HIER_SHEET/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_SHEET_SYMBOL_BUTT, text,
HELP_PLACE_SHEET,
KiBitmap( add_hierarchical_subsheet_xpm ) );
@@ -278,13 +278,13 @@ void preparePlaceMenu( wxMenu* aParentMenu )
aParentMenu->AppendSeparator();
text = AddHotkeyName( _( "Graphic Pol&yline" ), g_Schematic_Hokeys_Descr,
- HK_ADD_GRAPHIC_POLYLINE, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_GRAPHIC_POLYLINE/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_LINE_COMMENT_BUTT, text,
HELP_PLACE_GRAPHICLINES,
KiBitmap( add_dashed_line_xpm ) );
text = AddHotkeyName( _( "&Graphic Text" ), g_Schematic_Hokeys_Descr,
- HK_ADD_GRAPHIC_TEXT, IS_ACCELERATOR ); // add an accelerator, not a shortcut
+ HK_ADD_GRAPHIC_TEXT/*, IS_ACCELERATOR*/ ); // add an accelerator, not a shortcut
AddMenuItem( aParentMenu, ID_TEXT_COMMENT_BUTT, text,
HELP_PLACE_GRAPHICTEXTS,
KiBitmap( text_xpm ) );
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index c990fc2..0a5b212 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -1089,7 +1089,6 @@ public:
int GetLabelIncrement() const { return m_repeatLabelDelta; }
private:
-
/**
* Function Load_Component
* loads from a library and places a component.
diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h
index 3e33b67..2710b32 100644
--- a/include/class_draw_panel_gal.h
+++ b/include/class_draw_panel_gal.h
@@ -223,6 +223,15 @@ public:
*/
int GetCurrentCursor() const { return m_currentCursor; }
+ /**
+ * A accessor to send key events to the gal canvas.
+ * used to send a wxEVT_CHAR_HOOK from the editor frame
+ * to the gal canvas and filter it
+ */
+ void OnKeyEvent( wxKeyEvent& aEvent )
+ {
+ onEvent( aEvent );
+ }
protected:
void onPaint( wxPaintEvent& WXUNUSED( aEvent ) );
diff --git a/include/draw_frame.h b/include/draw_frame.h
index 6c17ffd..9f2ae35 100644
--- a/include/draw_frame.h
+++ b/include/draw_frame.h
@@ -194,6 +194,14 @@ public:
~EDA_DRAW_FRAME();
+ /** this function capture the key event before it is sent to the GUI.
+ * the basic frame does not capture this event.
+ * editor frames should override this event function to capture and filter
+ * these keys when they are used as hotkeys, and skip it if the key is not
+ * used as hotkey (otherwise the key events will be not sent to menus)
+ */
+ virtual void OnCharHook( wxKeyEvent& event );
+
/**
* Function LockFile
* marks a schematic file as being in use. Use ReleaseFile() to undo this.
diff --git a/include/tool/tool_manager.h b/include/tool/tool_manager.h
index 19b3316..2762fd8 100644
--- a/include/tool/tool_manager.h
+++ b/include/tool/tool_manager.h
@@ -227,8 +227,9 @@ public:
/**
* Propagates an event to tools that requested events of matching type(s).
* @param aEvent is the event to be processed.
+ * @return true if the event is a managed hotkey
*/
- void ProcessEvent( const TOOL_EVENT& aEvent );
+ bool ProcessEvent( const TOOL_EVENT& aEvent );
/**
* Puts an event to the event queue to be processed at the end of event processing cycle.
@@ -491,7 +492,8 @@ private:
void popViewControls();
///> Main function for event processing.
- void processEvent( const TOOL_EVENT& aEvent );
+ ///> @return true if a hotkey was handled
+ bool processEvent( const TOOL_EVENT& aEvent );
/// Index of registered tools current states, associated by tools' objects.
TOOL_STATE_MAP m_toolState;
diff --git a/pcbnew/menubar_modedit.cpp b/pcbnew/menubar_modedit.cpp
index 9b6be27..bbeee3e 100644
--- a/pcbnew/menubar_modedit.cpp
+++ b/pcbnew/menubar_modedit.cpp
@@ -228,11 +228,11 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
* for Zoom in and Zoom out sub menus
*/
text = AddHotkeyName( _( "Zoom &In" ), m_hotkeysDescrList,
- HK_ZOOM_IN, IS_ACCELERATOR );
+ HK_ZOOM_IN/*, IS_ACCELERATOR*/ );
AddMenuItem( viewMenu, ID_ZOOM_IN, text, HELP_ZOOM_IN, KiBitmap( zoom_in_xpm ) );
text = AddHotkeyName( _( "Zoom &Out" ), m_hotkeysDescrList,
- HK_ZOOM_OUT, IS_ACCELERATOR );
+ HK_ZOOM_OUT/*, IS_ACCELERATOR*/ );
AddMenuItem( viewMenu, ID_ZOOM_OUT, text, HELP_ZOOM_OUT, KiBitmap( zoom_out_xpm ) );
text = AddHotkeyName( _( "&Fit on Screen" ), m_hotkeysDescrList,
diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp
index 1b58790..a0ebde6 100644
--- a/pcbnew/menubar_pcbframe.cpp
+++ b/pcbnew/menubar_pcbframe.cpp
@@ -313,7 +313,7 @@ void preparePlaceMenu( wxMenu* aParentMenu )
_( "Add footprints" ), KiBitmap( module_xpm ) );
text = AddHotkeyName( _( "&Track" ), g_Pcbnew_Editor_Hokeys_Descr,
- HK_ADD_NEW_TRACK, IS_ACCELERATOR );
+ HK_ADD_NEW_TRACK/*, IS_ACCELERATOR*/ );
AddMenuItem( aParentMenu, ID_TRACK_BUTT, text,
_( "Add tracks and vias" ), KiBitmap( add_tracks_xpm ) );
@@ -530,11 +530,11 @@ void prepareViewMenu( wxMenu* aParentMenu )
* for Zoom in and Zoom out sub menus
*/
text = AddHotkeyName( _( "Zoom &In" ), g_Pcbnew_Editor_Hokeys_Descr,
- HK_ZOOM_IN, IS_ACCELERATOR );
+ HK_ZOOM_IN/*, IS_ACCELERATOR*/ );
AddMenuItem( aParentMenu, ID_ZOOM_IN, text, HELP_ZOOM_IN, KiBitmap( zoom_in_xpm ) );
text = AddHotkeyName( _( "Zoom &Out" ), g_Pcbnew_Editor_Hokeys_Descr,
- HK_ZOOM_OUT, IS_ACCELERATOR );
+ HK_ZOOM_OUT/*, IS_ACCELERATOR*/ );
AddMenuItem( aParentMenu, ID_ZOOM_OUT, text, HELP_ZOOM_OUT, KiBitmap( zoom_out_xpm ) );
text = AddHotkeyName( _( "&Fit on Screen" ), g_Pcbnew_Editor_Hokeys_Descr,
Follow ups