diff --git a/3d-viewer/3d_viewer/3d_menubar.cpp b/3d-viewer/3d_viewer/3d_menubar.cpp index a4e261d7e5..5a0e935085 100644 --- a/3d-viewer/3d_viewer/3d_menubar.cpp +++ b/3d-viewer/3d_viewer/3d_menubar.cpp @@ -45,278 +45,197 @@ void EDA_3D_VIEWER::CreateMenuBar() //-- File menu ----------------------------------------------------------- // - CONDITIONAL_MENU* fileMenu = new CONDITIONAL_MENU( false, tool ); + ACTION_MENU* fileMenu = new ACTION_MENU( false, tool ); - fileMenu->AddItem( ID_MENU_SCREENCOPY_PNG, _( "Export Current View as PNG..." ), "", - export_xpm, SELECTION_CONDITIONS::ShowAlways ); + fileMenu->Add( _( "Export Current View as PNG..." ), + "", + ID_MENU_SCREENCOPY_PNG, + export_xpm ); - fileMenu->AddItem( ID_MENU_SCREENCOPY_JPEG, _( "Export Current View as JPEG..." ), "", - export_xpm, SELECTION_CONDITIONS::ShowAlways ); + fileMenu->Add( _( "Export Current View as JPEG..." ), + "", + ID_MENU_SCREENCOPY_JPEG, + export_xpm ); - fileMenu->AddSeparator(); + fileMenu->AppendSeparator(); fileMenu->AddClose( _( "3D Viewer" ) ); - fileMenu->Resolve(); //-- Edit menu ------------------------------------------------------- // Avoid to translate hotkey modifiers like Ctrl and Shift. // The translated modifiers do not always work - CONDITIONAL_MENU* editMenu = new CONDITIONAL_MENU( false, tool ); + ACTION_MENU* editMenu = new ACTION_MENU( false, tool ); - editMenu->AddItem( ID_TOOL_SCREENCOPY_TOCLIBBOARD, _( "Copy 3D Image" ), "", - copy_xpm, SELECTION_CONDITIONS::ShowAlways ); + editMenu->Add( _( "Copy 3D Image" ), + "", + ID_TOOL_SCREENCOPY_TOCLIBBOARD, + copy_xpm ); - editMenu->Resolve(); //-- View menu ------------------------------------------------------- // - CONDITIONAL_MENU* viewMenu = new CONDITIONAL_MENU( false, tool ); + ACTION_MENU* viewMenu = new ACTION_MENU( false, tool ); - viewMenu->AddItem( ACTIONS::zoomIn, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( ACTIONS::zoomOut, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( ACTIONS::zoomFitScreen, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( ACTIONS::zoomRedraw, SELECTION_CONDITIONS::ShowAlways ); + viewMenu->Add( ACTIONS::zoomIn ); + viewMenu->Add( ACTIONS::zoomOut ); + viewMenu->Add( ACTIONS::zoomFitScreen ); + viewMenu->Add( ACTIONS::zoomRedraw ); - viewMenu->AddSeparator(); - viewMenu->AddItem( EDA_3D_ACTIONS::rotateXCW, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( EDA_3D_ACTIONS::rotateXCCW, SELECTION_CONDITIONS::ShowAlways ); + viewMenu->AppendSeparator(); + viewMenu->Add( EDA_3D_ACTIONS::rotateXCW ); + viewMenu->Add( EDA_3D_ACTIONS::rotateXCCW ); - viewMenu->AddSeparator(); - viewMenu->AddItem( EDA_3D_ACTIONS::rotateYCW, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( EDA_3D_ACTIONS::rotateYCCW, SELECTION_CONDITIONS::ShowAlways ); + viewMenu->AppendSeparator(); + viewMenu->Add( EDA_3D_ACTIONS::rotateYCW ); + viewMenu->Add( EDA_3D_ACTIONS::rotateYCCW ); - viewMenu->AddSeparator(); - viewMenu->AddItem( EDA_3D_ACTIONS::rotateZCW, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( EDA_3D_ACTIONS::rotateZCCW, SELECTION_CONDITIONS::ShowAlways ); + viewMenu->AppendSeparator(); + viewMenu->Add( EDA_3D_ACTIONS::rotateZCW ); + viewMenu->Add( EDA_3D_ACTIONS::rotateZCCW ); - viewMenu->AddSeparator(); - viewMenu->AddItem( EDA_3D_ACTIONS::moveLeft, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( EDA_3D_ACTIONS::moveRight, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( EDA_3D_ACTIONS::moveUp, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( EDA_3D_ACTIONS::moveDown, SELECTION_CONDITIONS::ShowAlways ); + viewMenu->AppendSeparator(); + viewMenu->Add( EDA_3D_ACTIONS::moveLeft ); + viewMenu->Add( EDA_3D_ACTIONS::moveRight ); + viewMenu->Add( EDA_3D_ACTIONS::moveUp ); + viewMenu->Add( EDA_3D_ACTIONS::moveDown ); - viewMenu->Resolve(); //-- Preferences menu ----------------------------------------------- // - CONDITIONAL_MENU* prefsMenu = new CONDITIONAL_MENU( false, tool ); + ACTION_MENU* prefsMenu = new ACTION_MENU( false, tool ); - //clang-format off - auto raytracingCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.RenderEngineGet() != RENDER_ENGINE::OPENGL_LEGACY; - }; + prefsMenu->Add( _( "Display Options" ), "", + ID_TOOL_SET_VISIBLE_ITEMS, + read_setup_xpm ); - auto NormalModeCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.MaterialModeGet() == MATERIAL_MODE::NORMAL; - }; - - auto DiffuseModeCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.MaterialModeGet() == MATERIAL_MODE::DIFFUSE_ONLY; - }; - - auto CADModeCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.MaterialModeGet() == MATERIAL_MODE::CAD_MODE; - }; - - auto boundingBoxesCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_RENDER_OPENGL_SHOW_MODEL_BBOX ); - }; - - auto renderShadowsCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_SHADOWS ); - }; - - auto proceduralTexturesCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES ); - }; - - auto showFloorCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_BACKFLOOR ); - }; - - auto useRefractionsCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_REFRACTIONS ); - }; - - auto useReflectionsCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_REFLECTIONS ); - }; - - auto antiAliasingCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_ANTI_ALIASING ); - }; - - auto postProcessCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_POST_PROCESSING ); - }; - - auto showAxesCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GetFlag( FL_AXIS ); - }; - //clang-format on - - prefsMenu->AddItem( ID_TOOL_SET_VISIBLE_ITEMS, _( "Display Options" ), "", - read_setup_xpm, SELECTION_CONDITIONS::ShowAlways ); - - prefsMenu->AddCheckItem( ID_RENDER_CURRENT_VIEW, _( "Raytracing" ), "", - tools_xpm, raytracingCondition ); + prefsMenu->Add( _( "Raytracing" ), "", + ID_RENDER_CURRENT_VIEW, + tools_xpm, + ACTION_MENU::CHECK ); // Render options submenu - CONDITIONAL_MENU* optsSubmenu = new CONDITIONAL_MENU( false, tool ); + ACTION_MENU* optsSubmenu = new ACTION_MENU( false, tool ); optsSubmenu->SetTitle( _( "Render Options" ) ); optsSubmenu->SetIcon( options_3drender_xpm ); // Material properties submenu - CONDITIONAL_MENU* propsSubmenu = new CONDITIONAL_MENU( false, tool ); + ACTION_MENU* propsSubmenu = new ACTION_MENU( false, tool ); propsSubmenu->SetTitle( _( "Material Properties" ) ); propsSubmenu->SetIcon( color_materials_xpm ); - propsSubmenu->AddCheckItem( ID_MENU3D_FL_RENDER_MATERIAL_MODE_NORMAL, - _( "Use All Properties" ), - _( "Use all material properties from each 3D model file" ), - nullptr, NormalModeCondition ); + propsSubmenu->Add( _( "Use All Properties" ), + _( "Use all material properties from each 3D model file" ), + ID_MENU3D_FL_RENDER_MATERIAL_MODE_NORMAL, + nullptr, + ACTION_MENU::CHECK ); - propsSubmenu->AddCheckItem( ID_MENU3D_FL_RENDER_MATERIAL_MODE_DIFFUSE_ONLY, - _( "Use Diffuse Only" ), - _( "Use only the diffuse color property from model 3D model file" ), - nullptr, DiffuseModeCondition ); + propsSubmenu->Add( _( "Use Diffuse Only" ), + _( "Use only the diffuse color property from model 3D model file" ), + ID_MENU3D_FL_RENDER_MATERIAL_MODE_DIFFUSE_ONLY, + nullptr, + ACTION_MENU::CHECK ); - propsSubmenu->AddCheckItem( ID_MENU3D_FL_RENDER_MATERIAL_MODE_CAD_MODE, - _( "CAD Color Style" ), - _( "Use a CAD color style based on the diffuse color of the material" ), - nullptr, CADModeCondition ); + propsSubmenu->Add( _( "CAD Color Style" ), + _( "Use a CAD color style based on the diffuse color of the material" ), + ID_MENU3D_FL_RENDER_MATERIAL_MODE_CAD_MODE, + nullptr, + ACTION_MENU::CHECK ); - optsSubmenu->AddMenu( propsSubmenu, SELECTION_CONDITIONS::ShowAlways ); + optsSubmenu->Add( propsSubmenu ); - optsSubmenu->AddCheckItem( EDA_3D_ACTIONS::showBoundingBoxes, boundingBoxesCondition ); + optsSubmenu->Add( EDA_3D_ACTIONS::showBoundingBoxes, ACTION_MENU::CHECK ); // Raytracing submenu - CONDITIONAL_MENU* raySubmenu = new CONDITIONAL_MENU( false, tool ); + ACTION_MENU* raySubmenu = new ACTION_MENU( false, tool ); raySubmenu->SetTitle( _( "Raytracing Options" ) ); raySubmenu->SetIcon( tools_xpm ); - raySubmenu->AddCheckItem( EDA_3D_ACTIONS::renderShadows, renderShadowsCondition ); - raySubmenu->AddCheckItem( EDA_3D_ACTIONS::proceduralTextures, proceduralTexturesCondition ); - raySubmenu->AddCheckItem( EDA_3D_ACTIONS::addFloor, showFloorCondition ); - raySubmenu->AddCheckItem( EDA_3D_ACTIONS::showRefractions, useRefractionsCondition ); - raySubmenu->AddCheckItem( EDA_3D_ACTIONS::showReflections, useReflectionsCondition ); - raySubmenu->AddCheckItem( EDA_3D_ACTIONS::antiAliasing, antiAliasingCondition ); + raySubmenu->Add( EDA_3D_ACTIONS::renderShadows, ACTION_MENU::CHECK ); + raySubmenu->Add( EDA_3D_ACTIONS::proceduralTextures, ACTION_MENU::CHECK ); + raySubmenu->Add( EDA_3D_ACTIONS::addFloor, ACTION_MENU::CHECK ); + raySubmenu->Add( EDA_3D_ACTIONS::showRefractions, ACTION_MENU::CHECK ); + raySubmenu->Add( EDA_3D_ACTIONS::showReflections, ACTION_MENU::CHECK ); + raySubmenu->Add( EDA_3D_ACTIONS::antiAliasing, ACTION_MENU::CHECK ); + raySubmenu->Add( EDA_3D_ACTIONS::postProcessing, ACTION_MENU::CHECK ); - raySubmenu->AddCheckItem( EDA_3D_ACTIONS::postProcessing, postProcessCondition ); + optsSubmenu->Add( raySubmenu ); + prefsMenu->Add( optsSubmenu ); - optsSubmenu->AddMenu( raySubmenu, SELECTION_CONDITIONS::ShowAlways ); - prefsMenu->AddMenu( optsSubmenu, SELECTION_CONDITIONS::ShowAlways ); - - prefsMenu->AddSeparator(); + prefsMenu->AppendSeparator(); // Color submenu - CONDITIONAL_MENU* colorSubmenu = new CONDITIONAL_MENU( false, tool ); + ACTION_MENU* colorSubmenu = new ACTION_MENU( false, tool ); colorSubmenu->SetTitle( _( "Choose Colors" ) ); colorSubmenu->SetIcon( palette_xpm ); - colorSubmenu->AddItem( ID_MENU3D_BGCOLOR_TOP, _( "Background Top Color..." ), "", - setcolor_3d_bg_xpm, SELECTION_CONDITIONS::ShowAlways ); + colorSubmenu->Add( _( "Background Top Color..." ), + ID_MENU3D_BGCOLOR_TOP, + setcolor_3d_bg_xpm ); - colorSubmenu->AddItem( ID_MENU3D_BGCOLOR_BOTTOM, _( "Background Bottom Color..." ), "", - setcolor_3d_bg_xpm, SELECTION_CONDITIONS::ShowAlways ); + colorSubmenu->Add( _( "Background Bottom Color..." ), + ID_MENU3D_BGCOLOR_BOTTOM, + setcolor_3d_bg_xpm ); - colorSubmenu->AddItem( ID_MENU3D_SILKSCREEN_COLOR, _( "Silkscreen Color..." ), "", - setcolor_silkscreen_xpm, SELECTION_CONDITIONS::ShowAlways ); + colorSubmenu->Add( _( "Silkscreen Color..." ), + ID_MENU3D_SILKSCREEN_COLOR, + setcolor_silkscreen_xpm ); - colorSubmenu->AddItem( ID_MENU3D_SOLDERMASK_COLOR, _( "Solder Mask Color..." ), "", - setcolor_soldermask_xpm, SELECTION_CONDITIONS::ShowAlways ); + colorSubmenu->Add( _( "Solder Mask Color..." ), + ID_MENU3D_SOLDERMASK_COLOR, + setcolor_soldermask_xpm ); - colorSubmenu->AddItem( ID_MENU3D_SOLDERPASTE_COLOR, _( "Solder Paste Color..." ), "", - setcolor_solderpaste_xpm, SELECTION_CONDITIONS::ShowAlways ); + colorSubmenu->Add( _( "Solder Paste Color..." ), + ID_MENU3D_SOLDERPASTE_COLOR, + setcolor_solderpaste_xpm ); - colorSubmenu->AddItem( ID_MENU3D_COPPER_COLOR, _( "Copper/Surface Finish Color..." ), "", - setcolor_copper_xpm, SELECTION_CONDITIONS::ShowAlways ); + colorSubmenu->Add( _( "Copper/Surface Finish Color..." ), + ID_MENU3D_COPPER_COLOR, + setcolor_copper_xpm ); - colorSubmenu->AddItem( ID_MENU3D_PCB_BODY_COLOR, _( "Board Body Color..." ), "", - setcolor_board_body_xpm, SELECTION_CONDITIONS::ShowAlways ); + colorSubmenu->Add( _( "Board Body Color..." ), + ID_MENU3D_PCB_BODY_COLOR, + setcolor_board_body_xpm ); // Only allow the stackup to be used in the PCB editor, since it isn't editable in the other frames if( Parent()->IsType( FRAME_PCB_EDITOR ) ) { - colorSubmenu->AddItem( ID_MENU3D_STACKUP_COLORS, _( "Get colors from physical stackup" ), "", - nullptr, SELECTION_CONDITIONS::ShowAlways ); + colorSubmenu->Add( _( "Get colors from physical stackup" ), + ID_MENU3D_STACKUP_COLORS, + nullptr ); } - prefsMenu->AddMenu( colorSubmenu ); + prefsMenu->Add( colorSubmenu ); - prefsMenu->AddCheckItem( EDA_3D_ACTIONS::showAxis, showAxesCondition ); + prefsMenu->Add( EDA_3D_ACTIONS::showAxis, ACTION_MENU::CHECK ); - // Grid submenu - CONDITIONAL_MENU* gridSubmenu = new CONDITIONAL_MENU( false, tool ); + // Grid submenu + ACTION_MENU* gridSubmenu = new ACTION_MENU( false, tool ); gridSubmenu->SetTitle( _( "3D Grid" ) ); gridSubmenu->SetIcon( grid_xpm ); - //clang-format off - auto noGridCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GridGet() == GRID3D_TYPE::NONE; - }; + gridSubmenu->Add( EDA_3D_ACTIONS::noGrid, ACTION_MENU::CHECK); + gridSubmenu->Add( EDA_3D_ACTIONS::show10mmGrid, ACTION_MENU::CHECK); + gridSubmenu->Add( EDA_3D_ACTIONS::show5mmGrid, ACTION_MENU::CHECK); + gridSubmenu->Add( EDA_3D_ACTIONS::show2_5mmGrid, ACTION_MENU::CHECK); + gridSubmenu->Add( EDA_3D_ACTIONS::show1mmGrid, ACTION_MENU::CHECK); - auto grid10mmCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GridGet() == GRID3D_TYPE::GRID_10MM; - }; + prefsMenu->Add( gridSubmenu ); - auto grid5mmCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GridGet() == GRID3D_TYPE::GRID_5MM; - }; - - auto grid2p5mmCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GridGet() == GRID3D_TYPE::GRID_2P5MM; - }; - - auto grid_1mmCondition = [this]( const SELECTION& aSel ) - { - return m_boardAdapter.GridGet() == GRID3D_TYPE::GRID_1MM; - }; - //clang-format on - - gridSubmenu->AddCheckItem( EDA_3D_ACTIONS::noGrid, noGridCondition ); - gridSubmenu->AddCheckItem( EDA_3D_ACTIONS::show10mmGrid, grid10mmCondition ); - gridSubmenu->AddCheckItem( EDA_3D_ACTIONS::show5mmGrid, grid5mmCondition ); - gridSubmenu->AddCheckItem( EDA_3D_ACTIONS::show2_5mmGrid, grid2p5mmCondition ); - gridSubmenu->AddCheckItem( EDA_3D_ACTIONS::show1mmGrid, grid_1mmCondition ); - - prefsMenu->AddMenu( gridSubmenu, SELECTION_CONDITIONS::ShowAlways ); - - prefsMenu->AddSeparator(); - prefsMenu->AddItem( ID_MENU3D_RESET_DEFAULTS, _( "Reset to Default Settings" ), "", - tools_xpm, SELECTION_CONDITIONS::ShowAlways ); + prefsMenu->AppendSeparator(); + prefsMenu->Add( _( "Reset to Default Settings" ), ID_MENU3D_RESET_DEFAULTS, tools_xpm ); #ifdef __APPLE__ // Note: will get moved to Apple menu by wxWidgets - prefsMenu->AddItem( wxID_PREFERENCES, - _( "Preferences...\tCTRL+," ), - _( "Show preferences for all open tools" ), - preference_xpm, SELECTION_CONDITIONS::ShowAlways ); + prefsMenu->Add( _( "Preferences...\tCTRL+," ), + _( "Show preferences for all open tools" ), + wxID_PREFERENCES, + preference_xpm ); #endif - prefsMenu->Resolve(); - //-- Menubar ------------------------------------------------------------- // - menuBar->Append( fileMenu, _( "&File" ) ); - menuBar->Append( editMenu, _( "&Edit" ) ); - menuBar->Append( viewMenu, _( "&View" ) ); + menuBar->Append( fileMenu, _( "&File" ) ); + menuBar->Append( editMenu, _( "&Edit" ) ); + menuBar->Append( viewMenu, _( "&View" ) ); menuBar->Append( prefsMenu, _( "&Preferences" ) ); AddStandardHelpMenu( menuBar ); diff --git a/3d-viewer/3d_viewer/3d_toolbar.cpp b/3d-viewer/3d_viewer/3d_toolbar.cpp index c85588e687..9a15563193 100644 --- a/3d-viewer/3d_viewer/3d_toolbar.cpp +++ b/3d-viewer/3d_viewer/3d_toolbar.cpp @@ -99,12 +99,3 @@ void EDA_3D_VIEWER::ReCreateMainToolbar() m_mainToolBar->Realize(); } - - -void EDA_3D_VIEWER::SyncToolbars() -{ - bool isOrtho = m_currentCamera.GetProjection() == PROJECTION_TYPE::ORTHO; - - m_mainToolBar->Toggle( EDA_3D_ACTIONS::toggleOrtho, isOrtho ); - m_mainToolBar->Refresh(); -} diff --git a/3d-viewer/3d_viewer/eda_3d_viewer.cpp b/3d-viewer/3d_viewer/eda_3d_viewer.cpp index 33e638992f..5a4b628d63 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer.cpp +++ b/3d-viewer/3d_viewer/eda_3d_viewer.cpp @@ -34,6 +34,7 @@ #include "../common_ogl/cogl_att_list.h" #include <3d_viewer/tools/3d_actions.h> #include <3d_viewer/tools/3d_controller.h> +#include <3d_viewer/tools/3d_conditions.h> #include #include #include @@ -44,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -75,11 +77,6 @@ BEGIN_EVENT_TABLE( EDA_3D_VIEWER, EDA_BASE_FRAME ) EVT_MENU( ID_RENDER_CURRENT_VIEW, EDA_3D_VIEWER::OnRenderEngineSelection ) EVT_MENU( ID_DISABLE_RAY_TRACING, EDA_3D_VIEWER::OnDisableRayTracing ) - EVT_UPDATE_UI( ID_RENDER_CURRENT_VIEW, EDA_3D_VIEWER::OnUpdateUIEngine ) - EVT_UPDATE_UI_RANGE( ID_MENU3D_FL_RENDER_MATERIAL_MODE_NORMAL, - ID_MENU3D_FL_RENDER_MATERIAL_MODE_CAD_MODE, - EDA_3D_VIEWER::OnUpdateUIMaterial ) - EVT_CLOSE( EDA_3D_VIEWER::OnCloseWindow ) END_EVENT_TABLE() @@ -132,6 +129,8 @@ EDA_3D_VIEWER::EDA_3D_VIEWER( KIWAY *aKiway, PCB_BASE_FRAME *aParent, const wxSt m_toolManager->RegisterTool( new EDA_3D_CONTROLLER ); m_toolManager->InitTools(); + setupUIConditions(); + if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool() ) ctrlTool->SetRotationIncrement( config->m_Camera.rotation_increment ); @@ -187,6 +186,74 @@ EDA_3D_VIEWER::~EDA_3D_VIEWER() } +void EDA_3D_VIEWER::setupUIConditions() +{ + EDA_BASE_FRAME::setupUIConditions(); + + ACTION_MANAGER* mgr = m_toolManager->GetActionManager(); + EDA_3D_CONDITIONS cond( &m_boardAdapter ); + +// Helper to define check conditions +#define MaterialCheck( x ) ACTION_CONDITIONS().SetCheckCondition( cond.MaterialMode( x ) ) +#define FlagCheck( x ) ACTION_CONDITIONS().SetCheckCondition( cond.Flag( x ) ) +#define GridSizeCheck( x ) ACTION_CONDITIONS().SetCheckCondition( cond.GridSize( x ) ) + + auto raytracingCondition = [this]( const SELECTION& aSel ) + { + return m_boardAdapter.RenderEngineGet() != RENDER_ENGINE::OPENGL_LEGACY; + }; + + RegisterUIUpdateHandler( ID_RENDER_CURRENT_VIEW, + ACTION_CONDITIONS().SetCheckCondition( raytracingCondition ) ); + + mgr->SetConditions( ID_MENU3D_FL_RENDER_MATERIAL_MODE_NORMAL,, + MaterialCheck( MATERIAL_MODE::NORMAL ) ); + mgr->SetConditions( ID_MENU3D_FL_RENDER_MATERIAL_MODE_DIFFUSE_ONLY,, + MaterialCheck( MATERIAL_MODE::DIFFUSE_ONLY ) ); + mgr->SetConditions( ID_MENU3D_FL_RENDER_MATERIAL_MODE_CAD_MODE,, + MaterialCheck( MATERIAL_MODE::CAD_MODE ) ); + + mgr->SetConditions( EDA_3D_ACTIONS::renderShadows, + FlagCheck( FL_RENDER_RAYTRACING_SHADOWS ) ); + mgr->SetConditions( EDA_3D_ACTIONS::proceduralTextures, + FlagCheck( FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES ) ); + mgr->SetConditions( EDA_3D_ACTIONS::addFloor, + FlagCheck( FL_RENDER_RAYTRACING_BACKFLOOR ) ); + mgr->SetConditions( EDA_3D_ACTIONS::showRefractions, + FlagCheck( FL_RENDER_RAYTRACING_REFRACTIONS ) ); + mgr->SetConditions( EDA_3D_ACTIONS::showReflections, + FlagCheck( FL_RENDER_RAYTRACING_REFLECTIONS ) ); + mgr->SetConditions( EDA_3D_ACTIONS::antiAliasing, + FlagCheck( FL_RENDER_RAYTRACING_ANTI_ALIASING ) ); + mgr->SetConditions( EDA_3D_ACTIONS::postProcessing, + FlagCheck( FL_RENDER_RAYTRACING_POST_PROCESSING ) ); + mgr->SetConditions( EDA_3D_ACTIONS::showBoundingBoxes, + FlagCheck( FL_RENDER_OPENGL_SHOW_MODEL_BBOX ) ); + mgr->SetConditions( EDA_3D_ACTIONS::showAxis, + FlagCheck( FL_AXIS ) ); + + mgr->SetConditions( EDA_3D_ACTIONS::noGrid, GridSizeCheck( GRID3D_TYPE::NONE ) ); + mgr->SetConditions( EDA_3D_ACTIONS::show10mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_10MM ) ); + mgr->SetConditions( EDA_3D_ACTIONS::show5mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_5MM ) ); + mgr->SetConditions( EDA_3D_ACTIONS::show2_5mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_2P5MM ) ); + mgr->SetConditions( EDA_3D_ACTIONS::show1mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_1MM ) ); + + + auto orthoCondition = + [this] ( const SELECTION& ) + { + return m_currentCamera.GetProjection() == PROJECTION_TYPE::ORTHO; + }; + + mgr->SetConditions( EDA_3D_ACTIONS::toggleOrtho, + ACTION_CONDITIONS().SetCheckCondition( orthoCondition ) ); + +#undef MaterialCheck +#undef FlagCheck +#undef GridSizeCheck +} + + void EDA_3D_VIEWER::ReloadRequest() { // This will schedule a request to load later @@ -916,35 +983,6 @@ bool EDA_3D_VIEWER::Set3DSolderPasteColorFromUser() } -void EDA_3D_VIEWER::OnUpdateUIEngine( wxUpdateUIEvent& aEvent ) -{ - aEvent.Check( m_boardAdapter.RenderEngineGet() != RENDER_ENGINE::OPENGL_LEGACY ); -} - - -void EDA_3D_VIEWER::OnUpdateUIMaterial( wxUpdateUIEvent& aEvent ) -{ - // Set the state of toggle menus according to the current display options - switch( aEvent.GetId() ) - { - case ID_MENU3D_FL_RENDER_MATERIAL_MODE_NORMAL: - aEvent.Check( m_boardAdapter.MaterialModeGet() == MATERIAL_MODE::NORMAL ); - break; - - case ID_MENU3D_FL_RENDER_MATERIAL_MODE_DIFFUSE_ONLY: - aEvent.Check( m_boardAdapter.MaterialModeGet() == MATERIAL_MODE::DIFFUSE_ONLY ); - break; - - case ID_MENU3D_FL_RENDER_MATERIAL_MODE_CAD_MODE: - aEvent.Check( m_boardAdapter.MaterialModeGet() == MATERIAL_MODE::CAD_MODE ); - break; - - default: - wxFAIL_MSG( "Invalid event in EDA_3D_VIEWER::OnUpdateUIMaterial()" ); - } -} - - void EDA_3D_VIEWER::loadCommonSettings() { wxCHECK_RET( m_canvas, "Cannot load settings to null canvas" ); diff --git a/3d-viewer/3d_viewer/eda_3d_viewer.h b/3d-viewer/3d_viewer/eda_3d_viewer.h index 474168c336..64e0c2c930 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer.h +++ b/3d-viewer/3d_viewer/eda_3d_viewer.h @@ -157,6 +157,9 @@ class EDA_3D_VIEWER : public EDA_3D_BOARD_HOLDER, public KIWAY_PLAYER void SynchroniseColoursWithBoard(); +protected: + void setupUIConditions() override; + private: /// Called when user press the File->Exit void Exit3DFrame( wxCommandEvent &event ); @@ -174,12 +177,8 @@ private: void Install3DViewOptionDialog( wxCommandEvent &event ); - void OnUpdateUIEngine( wxUpdateUIEvent& aEvent ); - void OnUpdateUIMaterial( wxUpdateUIEvent& aEvent ); - void CreateMenuBar(); void ReCreateMainToolbar(); - void SyncToolbars() override; void SaveSettings( APP_SETTINGS_BASE *aCfg ) override; diff --git a/3d-viewer/3d_viewer/tools/3d_conditions.cpp b/3d-viewer/3d_viewer/tools/3d_conditions.cpp new file mode 100644 index 0000000000..d646d8e9e3 --- /dev/null +++ b/3d-viewer/3d_viewer/tools/3d_conditions.cpp @@ -0,0 +1,72 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2020 Ian McInerney + * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <3d_canvas/board_adapter.h> +#include <3d_viewer/tools/3d_conditions.h> + +#include + +using namespace std::placeholders; + + +SELECTION_CONDITION EDA_3D_CONDITIONS::MaterialMode( MATERIAL_MODE aMaterial ) +{ + return std::bind( &EDA_3D_CONDITIONS::materialModeFunction, _1, m_adapter, aMaterial ); +} + + +SELECTION_CONDITION EDA_3D_CONDITIONS::Flag( DISPLAY3D_FLG aFlag ) +{ + return std::bind( &EDA_3D_CONDITIONS::flagFunction, _1, m_adapter, aFlag ); +} + + +SELECTION_CONDITION EDA_3D_CONDITIONS::GridSize( GRID3D_TYPE aGridSize ) +{ + return std::bind( &EDA_3D_CONDITIONS::gridSizeFunction, _1, m_adapter, aGridSize ); +} + + +bool EDA_3D_CONDITIONS::materialModeFunction( const SELECTION& aSelection, + BOARD_ADAPTER* aAdapter, + MATERIAL_MODE aMaterial ) +{ + return aAdapter->MaterialModeGet() == aMaterial; +} + + +bool EDA_3D_CONDITIONS::flagFunction( const SELECTION& aSelection, + BOARD_ADAPTER* aAdapter, + DISPLAY3D_FLG aFlag ) +{ + return aAdapter->GetFlag( aFlag ); +} + + +bool EDA_3D_CONDITIONS::gridSizeFunction( const SELECTION& aSelection, + BOARD_ADAPTER* aAdapter, + GRID3D_TYPE aGridSize ) +{ + return aAdapter->GridGet() == aGridSize; +} diff --git a/3d-viewer/3d_viewer/tools/3d_conditions.h b/3d-viewer/3d_viewer/tools/3d_conditions.h new file mode 100644 index 0000000000..0633714624 --- /dev/null +++ b/3d-viewer/3d_viewer/tools/3d_conditions.h @@ -0,0 +1,91 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2020 Ian McInerney + * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _3D_CONDITIONS_H_ +#define _3D_CONDITIONS_H_ + +#include <3d_enums.h> +#include +#include + + +class BOARD_ADAPTER; + +class EDA_3D_CONDITIONS : public SELECTION_CONDITIONS +{ +public: + /** + * Define conditions for a 3D viewer frame. + * + * @param aAdapter is the board adapter to query for information. + */ + EDA_3D_CONDITIONS( BOARD_ADAPTER* aAdapter ) : + m_adapter( aAdapter ) + {} + + /** + * Creates a functor that tests if a specific material mode is active. + * + * @param aAdapter is the board adapter the setting is in + * @param aMaterial is the material mode to test for. + * @return Functor testing if a material mode is active. + */ + SELECTION_CONDITION MaterialMode( MATERIAL_MODE aMaterial ); + + /** + * Creates a functor that tests if the board adapter has a flag set currently. + * + * @param aAdapter is the board adapter the setting is in + * @param aFlag is the flag to test for. + * @return Functor testing if the flag is set. + */ + SELECTION_CONDITION Flag( DISPLAY3D_FLG aFlag ); + + /** + * Creates a functor that tests the current grid size. + * + * @param aAdapter is the board adapter the setting is in + * @param aGridSize is the grid size to test for. + * @return Functor testing if the flag is set. + */ + SELECTION_CONDITION GridSize( GRID3D_TYPE aGridSize ); + +private: + ///> Helper function used by MaterialMode() + static bool materialModeFunction( const SELECTION& aSelection, BOARD_ADAPTER* aAdapter, + MATERIAL_MODE aMaterial ); + + ///> Helper function used by Flag() + static bool flagFunction( const SELECTION& aSelection, BOARD_ADAPTER* aAdapter, + DISPLAY3D_FLG aFlag ); + + ///> Helper function used by GridDize() + static bool gridSizeFunction( const SELECTION& aSelection, BOARD_ADAPTER* aAdapter, + GRID3D_TYPE aGridSize ); + + ///> The board adapter to read the 3D viewer state from + BOARD_ADAPTER* m_adapter; +}; + +#endif /* _3D_CONDITIONS_H_ */ diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt index 34a15a66d7..dbf217f8b9 100644 --- a/3d-viewer/CMakeLists.txt +++ b/3d-viewer/CMakeLists.txt @@ -92,6 +92,7 @@ set(3D-VIEWER_SRCS 3d_viewer/dialogs/dialog_3D_view_option.cpp 3d_viewer/dialogs/dialog_3D_view_option_base.cpp 3d_viewer/tools/3d_actions.cpp + 3d_viewer/tools/3d_conditions.cpp 3d_viewer/tools/3d_controller.cpp 3d_viewer/eda_3d_viewer.cpp 3d_viewer/3d_viewer_settings.cpp diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 7b156683a3..5fc9bf3bec 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -69,6 +69,7 @@ set( GAL_SRCS add_library( gal STATIC ${GAL_SRCS} ) target_link_libraries( gal + common # This is needed until the circular dependency is removed kimath bitmaps ${GLEW_LIBRARIES} diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp index 96d3d825a4..3b28f7214b 100644 --- a/common/eda_base_frame.cpp +++ b/common/eda_base_frame.cpp @@ -48,6 +48,8 @@ #include #include +#include + wxDEFINE_EVENT( UNITS_CHANGED, wxCommandEvent ); @@ -290,6 +292,89 @@ void EDA_BASE_FRAME::OnMenuEvent( wxMenuEvent& aEvent ) } +void EDA_BASE_FRAME::RegisterUIUpdateHandler( int aID, const ACTION_CONDITIONS& aConditions ) +{ + UIUpdateHandler evtFunc = std::bind( &EDA_BASE_FRAME::HandleUpdateUIEvent, + std::placeholders::_1, + this, + aConditions ); + + m_uiUpdateMap[aID] = evtFunc; + + Bind( wxEVT_UPDATE_UI, evtFunc, aID ); +} + + +void EDA_BASE_FRAME::UnregisterUIUpdateHandler( int aID ) +{ + const auto it = m_uiUpdateMap.find( aID ); + + if( it == m_uiUpdateMap.end() ) + return; + + Unbind( wxEVT_UPDATE_UI, it->second, aID ); +} + + +void EDA_BASE_FRAME::HandleUpdateUIEvent( wxUpdateUIEvent& aEvent, EDA_BASE_FRAME* aFrame, + ACTION_CONDITIONS aCond ) +{ + bool checkRes = false; + bool enableRes = true; + bool showRes = true; + SELECTION& selection = aFrame->GetCurrentSelection(); + + try + { + checkRes = aCond.checkCondition( selection ); + enableRes = aCond.enableCondition( selection ); + showRes = aCond.showCondition( selection ); + } + catch( std::exception& ) + { + // Something broke with the conditions, just skip the event. + aEvent.Skip(); + return; + } + + aEvent.Enable( enableRes ); + aEvent.Show( showRes ); + + bool canCheck = true; + + // wxMenuItems don't want to be checked unless they actually are checkable, so we have to check to + // see if they can be and can't just universally apply a check in this event. + if( auto menu = dynamic_cast( aEvent.GetEventObject() ) ) + canCheck = menu->FindItem( aEvent.GetId() )->IsCheckable(); + + if( canCheck ) + aEvent.Check( checkRes ); +} + + +// Contained inside pgm_base.cpp +extern LANGUAGE_DESCR LanguagesList[]; + +void EDA_BASE_FRAME::setupUIConditions() +{ + // Setup the conditions to check a language menu item + auto isCurrentLang = + [] ( const SELECTION& aSel, int aLangIdentifier ) + { + return Pgm().GetSelectedLanguageIdentifier() == aLangIdentifier; + }; + + for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ ) + { + ACTION_CONDITIONS cond; + cond.SetCheckCondition( std::bind( isCurrentLang, std::placeholders::_1, + LanguagesList[ii].m_WX_Lang_Identifier ) ); + + RegisterUIUpdateHandler( LanguagesList[ii].m_KI_Lang_Identifier, cond ); + } +} + + void EDA_BASE_FRAME::ReCreateMenuBar() { } @@ -298,9 +383,7 @@ void EDA_BASE_FRAME::ReCreateMenuBar() void EDA_BASE_FRAME::AddStandardHelpMenu( wxMenuBar* aMenuBar ) { COMMON_CONTROL* commonControl = m_toolManager->GetTool(); - ACTION_MENU* helpMenu = new ACTION_MENU( false ); - - helpMenu->SetTool( commonControl ); + ACTION_MENU* helpMenu = new ACTION_MENU( false, commonControl ); helpMenu->Add( ACTIONS::help ); helpMenu->Add( ACTIONS::gettingStarted ); diff --git a/common/languages_menu.cpp b/common/languages_menu.cpp index c5c2bc103e..de33e389f1 100644 --- a/common/languages_menu.cpp +++ b/common/languages_menu.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,33 +31,29 @@ #include #include +#include #include +#include #include #include - +// Contained inside pgm_base.cpp extern LANGUAGE_DESCR LanguagesList[]; -using namespace std::placeholders; - /** * Function AddMenuLanguageList * creates a menu list for language choice, and add it as submenu to \a MasterMenu. * - * @param aMasterMenu The main menu. + * @param aMasterMenu is the main menu. + * @param aControlTool is the tool to associate with the menu */ - -void AddMenuLanguageList( CONDITIONAL_MENU* aMasterMenu, TOOL_INTERACTIVE* aControlTool ) +void AddMenuLanguageList( ACTION_MENU* aMasterMenu, TOOL_INTERACTIVE* aControlTool ) { - CONDITIONAL_MENU* langsMenu = new CONDITIONAL_MENU( false, aControlTool ); + ACTION_MENU* langsMenu = new ACTION_MENU( false, aControlTool ); langsMenu->SetTitle( _( "Set Language" ) ); langsMenu->SetIcon( language_xpm ); - aMasterMenu->AddMenu( langsMenu ); - wxString tooltip; - auto isCurrentLang = [] ( int aLangIdentifier ) { - return Pgm().GetSelectedLanguageIdentifier() == aLangIdentifier; - }; + wxString tooltip; for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ ) { @@ -68,8 +64,17 @@ void AddMenuLanguageList( CONDITIONAL_MENU* aMasterMenu, TOOL_INTERACTIVE* aCont else label = wxGetTranslation( LanguagesList[ii].m_Lang_Label ); - langsMenu->AddCheckItem( LanguagesList[ii].m_KI_Lang_Identifier, // wxMenuItem wxID - label, tooltip, LanguagesList[ii].m_Lang_Icon, - std::bind( isCurrentLang, LanguagesList[ii].m_WX_Lang_Identifier ) ); + wxMenuItem* item = new wxMenuItem( langsMenu, + LanguagesList[ii].m_KI_Lang_Identifier, // wxMenuItem wxID + label, + tooltip, + wxITEM_CHECK ); + + AddBitmapToMenuItem( item, KiBitmap( LanguagesList[ii].m_Lang_Icon ) ); + + langsMenu->Append( item ); } + + // This must be done after the items are added + aMasterMenu->Add( langsMenu ); } diff --git a/common/tool/action_manager.cpp b/common/tool/action_manager.cpp index 3d8d2b95c1..e4d875f80d 100644 --- a/common/tool/action_manager.cpp +++ b/common/tool/action_manager.cpp @@ -66,6 +66,32 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) } +void ACTION_MANAGER::SetConditions( const TOOL_ACTION& aAction, const ACTION_CONDITIONS& aConditions ) +{ + // Remove any existing handlers with the old conditions to ensure the UI layer doesn't have stale data + if( m_toolMgr ) + m_toolMgr->GetToolHolder()->UnregisterUIUpdateHandler( aAction ); + + m_uiConditions[aAction.GetId()] = aConditions; + + // Register a new handler with the new conditions + if( m_toolMgr ) + m_toolMgr->GetToolHolder()->RegisterUIUpdateHandler( aAction, aConditions ); +} + + +const ACTION_CONDITIONS* ACTION_MANAGER::GetCondition( const TOOL_ACTION& aAction ) const +{ + const auto it = m_uiConditions.find( aAction.GetUIId() ); + + // If the action doesn't have something registered, then return null + if( it == m_uiConditions.end() ) + return nullptr; + else + return &it->second; +} + + int ACTION_MANAGER::MakeActionId( const std::string& aActionName ) { static int currentActionId = 1; diff --git a/common/tool/action_menu.cpp b/common/tool/action_menu.cpp index 41576da2c8..8018bb0294 100644 --- a/common/tool/action_menu.cpp +++ b/common/tool/action_menu.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -42,13 +43,13 @@ using namespace std::placeholders; -ACTION_MENU::ACTION_MENU( bool isContextMenu ) : +ACTION_MENU::ACTION_MENU( bool isContextMenu, TOOL_INTERACTIVE* aTool ) : m_dirty( true ), m_titleDisplayed( false ), m_isContextMenu( isContextMenu ), m_icon( nullptr ), m_selected( -1 ), - m_tool( nullptr ) + m_tool( aTool ) { setupEvents(); } @@ -147,11 +148,12 @@ wxMenuItem* ACTION_MENU::Add( const wxString& aLabel, int aId, const BITMAP_OPAQ wxMenuItem* ACTION_MENU::Add( const wxString& aLabel, const wxString& aTooltip, int aId, - const BITMAP_OPAQUE* aIcon ) + const BITMAP_OPAQUE* aIcon, bool aIsCheckmarkEntry ) { wxASSERT_MSG( FindItem( aId ) == nullptr, "Duplicate menu IDs!" ); - wxMenuItem* item = new wxMenuItem( this, aId, aLabel, aTooltip, wxITEM_NORMAL ); + wxMenuItem* item = new wxMenuItem( this, aId, aLabel, aTooltip, + aIsCheckmarkEntry ? wxITEM_CHECK : wxITEM_NORMAL ); if( aIcon ) AddBitmapToMenuItem( item, KiBitmap( aIcon ) ); @@ -199,6 +201,33 @@ wxMenuItem* ACTION_MENU::Add( ACTION_MENU* aMenu ) } +void ACTION_MENU::AddClose( wxString aAppname ) +{ + Add( _( "Close\tCTRL+W" ), + wxString::Format( "Close %s", aAppname ), + wxID_CLOSE, + exit_xpm ); +} + + +void ACTION_MENU::AddQuitOrClose( KIFACE_I* aKiface, wxString aAppname ) +{ + if( !aKiface || aKiface->IsSingle() ) // not when under a project mgr + { + // Don't use ACTIONS::quit; wxWidgets moves this on OSX and expects to find it via + // wxID_EXIT + Add( _( "Quit" ), + wxString::Format( "Quit %s", aAppname ), + wxID_EXIT, + exit_xpm ); + } + else + { + AddClose( aAppname ); + } +} + + void ACTION_MENU::Clear() { m_titleDisplayed = false; diff --git a/common/tool/conditional_menu.cpp b/common/tool/conditional_menu.cpp index a0b71541f6..ac67972d55 100644 --- a/common/tool/conditional_menu.cpp +++ b/common/tool/conditional_menu.cpp @@ -30,9 +30,8 @@ CONDITIONAL_MENU::CONDITIONAL_MENU( bool isContextMenu, TOOL_INTERACTIVE* aTool ) : - ACTION_MENU( isContextMenu ) + ACTION_MENU( isContextMenu, aTool ) { - m_tool = aTool; } @@ -99,29 +98,6 @@ void CONDITIONAL_MENU::AddSeparator( int aOrder ) } -void CONDITIONAL_MENU::AddClose( wxString aAppname ) -{ - AddItem( wxID_CLOSE, _( "Close\tCTRL+W" ), wxString::Format( "Close %s", aAppname ), exit_xpm, - SELECTION_CONDITIONS::ShowAlways ); -} - - -void CONDITIONAL_MENU::AddQuitOrClose( KIFACE_I* aKiface, wxString aAppname ) -{ - if( !aKiface || aKiface->IsSingle() ) // not when under a project mgr - { - // Don't use ACTIONS::quit; wxWidgets moves this on OSX and expects to find it via - // wxID_EXIT - AddItem( wxID_EXIT, _( "Quit" ), wxString::Format( "Quit %s", aAppname ), exit_xpm, - SELECTION_CONDITIONS::ShowAlways ); - } - else - { - AddClose( aAppname ); - } -} - - SELECTION g_resolveDummySelection; diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp index d5b166dab1..57969af78e 100644 --- a/common/tool/tool_dispatcher.cpp +++ b/common/tool/tool_dispatcher.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013 CERN - * Copyright (C) 2013-2019 KiCad Developers, see CHANGELOG.txt for contributors. + * Copyright (C) 2013-2020 KiCad Developers, see CHANGELOG.txt for contributors. * @author Tomasz Wlostowski * * This program is free software; you can redistribute it and/or @@ -27,8 +27,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -338,7 +340,7 @@ OPT TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent, bool* keyI return evt; } - wxLogTrace( kicadTraceKeyEvent, "TOOL_DISPATCHER::DispatchWxEvent %s", dump( *aKeyEvent ) ); + wxLogTrace( kicadTraceKeyEvent, "TOOL_DISPATCHER::GetToolEvent %s", dump( *aKeyEvent ) ); // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK // and do nothing. @@ -613,5 +615,3 @@ void TOOL_DISPATCHER::DispatchWxCommand( wxCommandEvent& aEvent ) else aEvent.Skip(); } - - diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index f055852cfc..adb797d952 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -37,8 +37,6 @@ #include "sch_edit_frame.h" #include -extern void AddMenuLanguageList( CONDITIONAL_MENU* aMasterMenu, TOOL_INTERACTIVE* aControlTool ); - void SCH_EDIT_FRAME::ReCreateMenuBar() { diff --git a/include/eda_base_frame.h b/include/eda_base_frame.h index cc30128951..9fd29e1fba 100644 --- a/include/eda_base_frame.h +++ b/include/eda_base_frame.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +90,9 @@ enum id_librarytype { #define DEFAULT_MAX_UNDO_ITEMS 0 #define ABS_MAX_UNDO_ITEMS (INT_MAX / 2) +/// This is the handler functor for the update UI events +typedef std::function< void( wxUpdateUIEvent& ) > UIUpdateHandler; + wxDECLARE_EVENT( UNITS_CHANGED, wxCommandEvent ); @@ -159,6 +163,9 @@ protected: EDA_UNITS m_userUnits; + // Map containing the UI update handlers registered with wx for each action + std::map m_uiUpdateMap; + ///> Default style flags used for wxAUI toolbars static constexpr int KICAD_AUI_TB_STYLE = wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_PLAIN_BACKGROUND; @@ -205,6 +212,11 @@ protected: */ virtual void unitsChangeRefresh() { } + /** + * Setup the UI conditions for the various actions and their controls in this frame. + */ + virtual void setupUIConditions(); + DECLARE_EVENT_TABLE() public: @@ -258,6 +270,43 @@ public: */ void OnMenuEvent( wxMenuEvent& event ); + virtual void RegisterUIUpdateHandler( const TOOL_ACTION& aAction, + const ACTION_CONDITIONS& aConditions ) override + { + RegisterUIUpdateHandler( aAction.GetUIId(), aConditions ); + } + + /** + * Register a UI update handler for the control with ID @c aID + * + * @param aID is the control ID to register the handler for + * @param aConditions are the UI conditions to use for the control states + */ + virtual void RegisterUIUpdateHandler( int aID, const ACTION_CONDITIONS& aConditions ); + + virtual void UnregisterUIUpdateHandler( const TOOL_ACTION& aAction ) override + { + UnregisterUIUpdateHandler( aAction.GetUIId() ); + } + + /** + * Unregister a UI handler for a given ID that was registered using @c RegisterUIUpdateHandler + * + * @param aID is the control ID to unregister the handler for + */ + virtual void UnregisterUIUpdateHandler( int aID ); + + /** + * Handles events generated when the UI is trying to figure out the current state of the UI controls + * related to TOOL_ACTIONS (e.g. enabled, checked, etc.). + * + * @param aEvent is the wxUpdateUIEvent to be processed. + * @param aFrame is the frame to get the selection from + * @param aCond are the UI SELECTION_CONDITIONS used + */ + static void HandleUpdateUIEvent( wxUpdateUIEvent& aEvent, EDA_BASE_FRAME* aFrame, + ACTION_CONDITIONS aCond ); + virtual void OnMove( wxMoveEvent& aEvent ) { aEvent.Skip(); diff --git a/include/menus_helpers.h b/include/menus_helpers.h index 2bac0b44f2..8048b896c8 100644 --- a/include/menus_helpers.h +++ b/include/menus_helpers.h @@ -35,11 +35,10 @@ #include #include -class CONDITIONAL_MENU; +class ACTION_MENU; class TOOL_INTERACTIVE; -void AddMenuLanguageList( CONDITIONAL_MENU* aMasterMenu, TOOL_INTERACTIVE* aControlTool ); - +void AddMenuLanguageList( ACTION_MENU* aMasterMenu, TOOL_INTERACTIVE* aControlTool ); /** * Add a bitmap to a menuitem diff --git a/include/tool/action_manager.h b/include/tool/action_manager.h index 5260aeefa6..bd970d7c2e 100644 --- a/include/tool/action_manager.h +++ b/include/tool/action_manager.h @@ -30,10 +30,51 @@ #include #include +#include + class TOOL_BASE; class TOOL_MANAGER; class TOOL_ACTION; +/** + * Functors that can be used to figure out how the action controls should be displayed in the UI + * and if an action should be enabled given the current selection. + * + * @note @c checkCondition is also used for determing the state of a toggled toolbar item + * (the item is toggled when the condition is true). + */ +struct ACTION_CONDITIONS +{ + SELECTION_CONDITION checkCondition; ///< Returns true if the UI control should be checked + SELECTION_CONDITION enableCondition; ///< Returns true if the UI control should be enabled + SELECTION_CONDITION showCondition; ///< Returns true if the UI control should be shown + + ACTION_CONDITIONS() + { + checkCondition = SELECTION_CONDITIONS::ShowNever; // Never check by default + enableCondition = SELECTION_CONDITIONS::ShowAlways; // Always enable by default + showCondition = SELECTION_CONDITIONS::ShowAlways; // Always show by default + } + + ACTION_CONDITIONS& SetCheckCondition( const SELECTION_CONDITION& aCondition ) + { + checkCondition = aCondition; + return *this; + } + + ACTION_CONDITIONS& SetEnableCondition( const SELECTION_CONDITION& aCondition ) + { + enableCondition = aCondition; + return *this; + } + + ACTION_CONDITIONS& SetShowCondition( const SELECTION_CONDITION& aCondition ) + { + showCondition = aCondition; + return *this; + } +}; + /** * ACTION_MANAGER * @@ -44,21 +85,19 @@ class ACTION_MANAGER { public: /** - * Constructor. * @param aToolManager is a tool manager instance that is used to pass events to tools. */ ACTION_MANAGER( TOOL_MANAGER* aToolManager ); /** - * Destructor. * Unregisters every registered action. */ ~ACTION_MANAGER(); /** - * Function RegisterAction() * Adds a tool action to the manager and sets it up. After that is is possible to invoke * the action using hotkeys or sending a command event with its name. + * * @param aAction: action to be added. Ownership is not transferred. */ void RegisterAction( TOOL_ACTION* aAction ); @@ -74,36 +113,34 @@ public: const std::map& GetActions(); /** - * Function FindAction() * Finds an action with a given name (if there is one available). + * * @param aActionName is the searched action. * @return Pointer to a TOOL_ACTION object or NULL if there is no such action. */ TOOL_ACTION* FindAction( const std::string& aActionName ) const; /** - * Function RunHotKey() * Runs an action associated with a hotkey (if there is one available). + * * @param aHotKey is the hotkey to be handled. * @return True if there was an action associated with the hotkey, false otherwise. */ bool RunHotKey( int aHotKey ) const; /** - * Function GetHotKey() * Returns the hot key associated with a given action or 0 if there is none. + * * @param aAction is the queried action. */ int GetHotKey( const TOOL_ACTION& aAction ) const; /** - * Function UpdateHotKeys() * Optionally reads the hotkey config files and then rebuilds the internal hotkey maps. */ void UpdateHotKeys( bool aFullUpdate ); /** - * Function GetActionList() * Returns list of TOOL_ACTIONs. TOOL_ACTIONs add themselves to the list upon their * creation. * @return List of TOOL_ACTIONs. @@ -115,6 +152,23 @@ public: return actionList; } + /** + * Set the conditions the UI elements for activating a specific tool action should use + * for determining the current UI state (e.g. checked, enabled, shown) + * + * @param aAction is the tool action using these conditions + * @param aConditions are the conditions to use for the action + */ + void SetConditions( const TOOL_ACTION& aAction, const ACTION_CONDITIONS& aConditions ); + + /** + * Get the conditions to use for a specific tool action. + * + * @param aAction is the tool action + * @return the action conditions, returns nullptr if no conditions are registered + */ + const ACTION_CONDITIONS* GetCondition( const TOOL_ACTION& aAction ) const; + private: // Resolves a hotkey by applying legacy and current settings over the action's // default hotkey. @@ -133,6 +187,10 @@ private: ///> Quick action<->hot key lookup std::map m_hotkeys; + + /// Map the command ID that wx uses for the action to the UI conditions for the + /// menu/toolbar items + std::map m_uiConditions; }; #endif /* ACTION_MANAGER_H_ */ diff --git a/include/tool/action_menu.h b/include/tool/action_menu.h index ed45aeee70..cba07c9f18 100644 --- a/include/tool/action_menu.h +++ b/include/tool/action_menu.h @@ -34,6 +34,7 @@ #include #include +class KIFACE_I; class TOOL_INTERACTIVE; /** @@ -43,7 +44,7 @@ class ACTION_MENU : public wxMenu { public: ///> Default constructor - ACTION_MENU( bool isContextMenu ); + ACTION_MENU( bool isContextMenu, TOOL_INTERACTIVE* aTool = nullptr ); ~ACTION_MENU() override; @@ -76,7 +77,7 @@ public: */ wxMenuItem* Add( const wxString& aLabel, int aId, const BITMAP_OPAQUE* aIcon ); wxMenuItem* Add( const wxString& aLabel, const wxString& aToolTip, int aId, - const BITMAP_OPAQUE* aIcon ); + const BITMAP_OPAQUE* aIcon, bool aIsCheckmarkEntry = false ); /** * Adds an entry to the menu, basing on the TOOL_ACTION object. After selecting the entry, @@ -94,6 +95,22 @@ public: */ wxMenuItem* Add( ACTION_MENU* aMenu ); + /** + * Add a standard close item to the menu with the accelerator key CTRL-W. + * Emits the wxID_CLOSE event. + * + * @param aAppname is the application name to append to the tooltip + */ + void AddClose( wxString aAppname = "" ); + + /** + * Adds either a standard Quit or Close item to the menu. If aKiface is NULL or in + * single-instance then Quite (wxID_QUIT) is used, otherwise Close (wxID_CLOSE) is used. + * + * @param aAppname is the application name to append to the tooltip + */ + void AddQuitOrClose( KIFACE_I* aKiface, wxString aAppname = "" ); + /** * Removes all the entries from the menu (as well as its title). It leaves the menu in the * initial state. @@ -142,6 +159,8 @@ public: void OnMenuEvent( wxMenuEvent& aEvent ); void OnIdle( wxIdleEvent& event ); + static constexpr bool CHECK = true; + protected: ///> Returns an instance of this class. It has to be overridden in inheriting classes. virtual ACTION_MENU* create() const; diff --git a/include/tool/action_toolbar.h b/include/tool/action_toolbar.h index 6bf6415475..e8612814ad 100644 --- a/include/tool/action_toolbar.h +++ b/include/tool/action_toolbar.h @@ -98,7 +98,7 @@ public: void Toggle( const TOOL_ACTION& aAction, bool aEnabled, bool aChecked ); - static const bool TOGGLE = true; + static constexpr bool TOGGLE = true; protected: ///> The default tool event handler. diff --git a/include/tool/conditional_menu.h b/include/tool/conditional_menu.h index b431d1edb3..340bf8ca25 100644 --- a/include/tool/conditional_menu.h +++ b/include/tool/conditional_menu.h @@ -33,7 +33,6 @@ class SELECTION_TOOL; class TOOL_ACTION; class TOOL_INTERACTIVE; -class KIFACE_I; class CONDITIONAL_MENU : public ACTION_MENU @@ -100,26 +99,6 @@ public: */ void AddSeparator( int aOrder = ANY_ORDER ); - /** - * Function AddClose() - * - * Add a standard close item to the menu with the accelerator key CTRL-W. - * Emits the wxID_CLOSE event. - * - * @param aAppname is the application name to append to the tooltip - */ - void AddClose( wxString aAppname = "" ); - - /** - * Functions AddQuitOrClose() - * - * Adds either a standard Quit or Close item to the menu. If aKiface is NULL or in - * single-instance then Quite (wxID_QUIT) is used, otherwise Close (wxID_CLOSE) is used. - * - * @param aAppname is the application name to append to the tooltip - */ - void AddQuitOrClose( KIFACE_I* aKiface, wxString aAppname = "" ); - /** * Function Evaluate() * diff --git a/include/tool/selection_conditions.h b/include/tool/selection_conditions.h index 7cffb8d8e1..6f4dd14fa8 100644 --- a/include/tool/selection_conditions.h +++ b/include/tool/selection_conditions.h @@ -49,10 +49,10 @@ class SELECTION_CONDITIONS { public: /** - * Function ShowAlways * The default condition function (always returns true). + * * @param aSelection is the selection to be tested. - * @return Always true; + * @return Always true. */ static bool ShowAlways( const SELECTION& aSelection ) { @@ -60,32 +60,43 @@ public: } /** - * Function NotEmpty + * Always returns false. + * + * @param aSelection is the selection to be tested. + * @return Always false. + */ + static bool ShowNever( const SELECTION& aSelection ) + { + return false; + } + + /** * Tests if there are any items selected. + * * @param aSelection is the selection to be tested. * @return True if there is at least one item selected. */ static bool NotEmpty( const SELECTION& aSelection ); /** - * Function HasType * Creates a functor that tests if among the selected items there is at least one of a given type. + * * @param aType is the type that is searched. * @return Functor testing for presence of items of a given type. */ static SELECTION_CONDITION HasType( KICAD_T aType ); /** - * Function OnlyType * Creates a functor that tests if the selected items are *only* of given type. + * * @param aType is the type that is searched. * @return Functor testing if selected items are exclusively of one type. */ static SELECTION_CONDITION OnlyType( KICAD_T aType ); /** - * Function OnlyTypes * Creates a functor that tests if the selected items are *only* of given types. + * * @param aTypes is an array containing types that are searched. It has to be ended with * KICAD_T::EOT as end marker. * @return Functor testing if selected items are exclusively of the requested types. @@ -93,27 +104,27 @@ public: static SELECTION_CONDITION OnlyTypes( const KICAD_T aTypes[] ); /** - * Function Count * Creates a functor that tests if the number of selected items is equal to the value given as * parameter. + * * @param aNumber is the number of expected items. * @return Functor testing if the number of selected items is equal aNumber. */ static SELECTION_CONDITION Count( int aNumber ); /** - * Function MoreThan * Creates a functor that tests if the number of selected items is greater than the value given * as parameter. + * * @param aNumber is the number used for comparison. * @return Functor testing if the number of selected items is greater than aNumber. */ static SELECTION_CONDITION MoreThan( int aNumber ); /** - * Function LessThan * Creates a functor that tests if the number of selected items is smaller than the value given * as parameter. + * * @param aNumber is the number used for comparison. * @return Functor testing if the number of selected items is smaller than aNumber. */ diff --git a/include/tool/tool_dispatcher.h b/include/tool/tool_dispatcher.h index 442a314186..e0a15c899d 100644 --- a/include/tool/tool_dispatcher.h +++ b/include/tool/tool_dispatcher.h @@ -39,8 +39,6 @@ class VIEW; } /** - * TOOL_DISPATCHER - * * - takes wx events, * - fixes all wx quirks (mouse warping, panning, ordering problems, etc) * - translates coordinates to world space @@ -52,8 +50,6 @@ class TOOL_DISPATCHER : public wxEvtHandler { public: /** - * Constructor - * * @param aToolMgr: tool manager instance the events will be sent to * @param aActions: ACTIONS subclass instance for ACTIONS::TranslateLegacyId() */ @@ -62,29 +58,27 @@ public: virtual ~TOOL_DISPATCHER(); /** - * Function ResetState() * Brings the dispatcher to its initial state. */ virtual void ResetState(); /** - * Function DispatchWxEvent() * Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools * handle those. + * * @param aEvent is the wxWidgets event to be processed. */ virtual void DispatchWxEvent( wxEvent& aEvent ); /** - * Function GetToolEvent() * Maps a wxWidgets key event to a TOOL_EVENT. */ OPT GetToolEvent( wxKeyEvent* aKeyEvent, bool* aSpecialKeyFlag ); /** - * Function DispatchWxCommand() * Processes wxCommands (mostly menu related events) and runs appropriate actions (eg. run the * specified tool). + * * @param aEvent is the wxCommandEvent to be processed. */ virtual void DispatchWxCommand( wxCommandEvent& aEvent ); diff --git a/include/tool/tools_holder.h b/include/tool/tools_holder.h index 224fa3ddbb..159a71c4ff 100644 --- a/include/tool/tools_holder.h +++ b/include/tool/tools_holder.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include @@ -49,6 +51,8 @@ protected: ACTIONS* m_actions; TOOL_DISPATCHER* m_toolDispatcher; + SELECTION m_dummySelection; // Empty dummy selection + std::vector m_toolStack; // Stack of user-level "tools". This is NOT a // stack of TOOL instances, because somewhat // confusingly most TOOLs implement more than one @@ -73,6 +77,35 @@ public: */ TOOL_MANAGER* GetToolManager() const { return m_toolManager; } + /** + * Register an action's update conditions with the UI layer to allow the UI to appropriately + * display the state of its controls. + * + * @param aAction is the action to register + * @param aConditions are the UI conditions to use for the control states + */ + virtual void RegisterUIUpdateHandler( const TOOL_ACTION& aAction, + const ACTION_CONDITIONS& aConditions ) + {} + + /** + * Unregister a UI handler for an action that was registered using @c RegisterUIUpdateHandler + * + * @param aAction is the action to unregister the handler for + */ + virtual void UnregisterUIUpdateHandler( const TOOL_ACTION& aAction ) + {} + + /** + * Get the current selection from the canvas area. + * + * @return the current selection + */ + virtual SELECTION& GetCurrentSelection() + { + return m_dummySelection; + } + /** * NB: the definition of "tool" is different at the user level. The implementation uses * a single TOOL_BASE derived class to implement several user "tools", such as rectangle diff --git a/kicad/kicad_manager_frame.cpp b/kicad/kicad_manager_frame.cpp index 76424b2e90..4f0aa989d3 100644 --- a/kicad/kicad_manager_frame.cpp +++ b/kicad/kicad_manager_frame.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -121,22 +122,8 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& titl wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxBORDER_NONE ); - // Create the manager - m_toolManager = new TOOL_MANAGER; - m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this ); - m_actions = new KICAD_MANAGER_ACTIONS(); - - m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, m_actions ); - - // Attach the events to the tool dispatcher - Bind( wxEVT_TOOL, &TOOL_DISPATCHER::DispatchWxCommand, m_toolDispatcher ); - Bind( wxEVT_CHAR, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher ); - Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher ); - - // Register tools - m_toolManager->RegisterTool( new COMMON_CONTROL ); - m_toolManager->RegisterTool( new KICAD_MANAGER_CONTROL ); - m_toolManager->InitTools(); + setupTools(); + setupUIConditions(); RecreateBaseHToolbar(); RecreateLauncher(); @@ -188,6 +175,56 @@ KICAD_MANAGER_FRAME::~KICAD_MANAGER_FRAME() } +void KICAD_MANAGER_FRAME::setupTools() +{ + // Create the manager + m_toolManager = new TOOL_MANAGER; + m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this ); + m_actions = new KICAD_MANAGER_ACTIONS(); + + m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, m_actions ); + + // Attach the events to the tool dispatcher + Bind( wxEVT_TOOL, &TOOL_DISPATCHER::DispatchWxCommand, m_toolDispatcher ); + Bind( wxEVT_CHAR, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher ); + Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher ); + + // Register tools + m_toolManager->RegisterTool( new COMMON_CONTROL ); + m_toolManager->RegisterTool( new KICAD_MANAGER_CONTROL ); + m_toolManager->InitTools(); +} + + +void KICAD_MANAGER_FRAME::setupUIConditions() +{ + EDA_BASE_FRAME::setupUIConditions(); + + ACTION_MANAGER* manager = m_toolManager->GetActionManager(); + + wxASSERT( manager ); + + auto activeProject = + [this] ( const SELECTION& ) + { + return m_active_project; + }; + + ACTION_CONDITIONS activeProjectCond; + activeProjectCond.SetEnableCondition( activeProject ); + + manager->SetConditions( KICAD_MANAGER_ACTIONS::editSchematic, activeProjectCond ); + manager->SetConditions( KICAD_MANAGER_ACTIONS::editSymbols, activeProjectCond ); + manager->SetConditions( KICAD_MANAGER_ACTIONS::editPCB, activeProjectCond ); + manager->SetConditions( KICAD_MANAGER_ACTIONS::editFootprints, activeProjectCond ); + manager->SetConditions( ACTIONS::saveAs, activeProjectCond ); + manager->SetConditions( KICAD_MANAGER_ACTIONS::closeProject, activeProjectCond ); + + // TODO: Switch this to an action + RegisterUIUpdateHandler( ID_SAVE_AND_ZIP_FILES, activeProjectCond ); +} + + wxWindow* KICAD_MANAGER_FRAME::GetToolCanvas() const { return m_leftWin; @@ -537,8 +574,7 @@ void KICAD_MANAGER_FRAME::ShowChangedLanguage() void KICAD_MANAGER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged ) { - int historySize = Pgm().GetCommonSettings()->m_System.file_history_size; - GetFileHistory().SetMaxFiles( (unsigned) std::max( 0, historySize ) ); + EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged ); } diff --git a/kicad/kicad_manager_frame.h b/kicad/kicad_manager_frame.h index 6c84e57196..f2de35d7e2 100644 --- a/kicad/kicad_manager_frame.h +++ b/kicad/kicad_manager_frame.h @@ -163,8 +163,6 @@ public: */ void OnChangeWatchedPaths( wxCommandEvent& aEvent ); - void SyncToolbars() override; - void InstallPreferences( PAGED_DIALOG* aParent, PANEL_HOTKEYS_EDITOR* aHotkeysPanel ) override; const wxString GetProjectFileName() const; @@ -182,7 +180,13 @@ public: DECLARE_EVENT_TABLE() +protected: + virtual void setupUIConditions() override; + private: + void setupTools(); + void setupActions(); + APP_SETTINGS_BASE* config() const override; KICAD_SETTINGS* kicadSettings() const; diff --git a/kicad/menubar.cpp b/kicad/menubar.cpp index b2193f47e3..f0ec05e6ea 100644 --- a/kicad/menubar.cpp +++ b/kicad/menubar.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2009 Wayne Stambaugh - * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019 CERN * * This program is free software; you can redistribute it and/or @@ -27,8 +27,9 @@ #include #include #include -#include +#include #include +#include #include #include #include "kicad_manager_frame.h" @@ -47,8 +48,8 @@ void KICAD_MANAGER_FRAME::ReCreateMenuBar() //-- File menu ----------------------------------------------------------- // - CONDITIONAL_MENU* fileMenu = new CONDITIONAL_MENU( false, controlTool ); - FILE_HISTORY& fileHistory = GetFileHistory(); + ACTION_MENU* fileMenu = new ACTION_MENU( false, controlTool ); + FILE_HISTORY& fileHistory = GetFileHistory(); fileHistory.SetClearText( _( "Clear Recent Projects" ) ); @@ -58,8 +59,7 @@ void KICAD_MANAGER_FRAME::ReCreateMenuBar() // will automatically refresh the menu. if( !openRecentMenu ) { - openRecentMenu = new ACTION_MENU( false ); - openRecentMenu->SetTool( controlTool ); + openRecentMenu = new ACTION_MENU( false, controlTool ); openRecentMenu->SetTitle( _( "Open Recent" ) ); openRecentMenu->SetIcon( recent_xpm ); @@ -67,100 +67,101 @@ void KICAD_MANAGER_FRAME::ReCreateMenuBar() fileHistory.AddFilesToMenu(); } - fileMenu->AddItem( KICAD_MANAGER_ACTIONS::newProject, SELECTION_CONDITIONS::ShowAlways ); - fileMenu->AddItem( KICAD_MANAGER_ACTIONS::newFromTemplate, SELECTION_CONDITIONS::ShowAlways ); - fileMenu->AddItem( KICAD_MANAGER_ACTIONS::openProject, SELECTION_CONDITIONS::ShowAlways ); - fileMenu->AddMenu( openRecentMenu, - FILE_HISTORY::FileHistoryNotEmpty( fileHistory ) ); + fileMenu->Add( KICAD_MANAGER_ACTIONS::newProject ); + fileMenu->Add( KICAD_MANAGER_ACTIONS::newFromTemplate ); + fileMenu->Add( KICAD_MANAGER_ACTIONS::openProject ); - fileMenu->AddItem( KICAD_MANAGER_ACTIONS::closeProject, SELECTION_CONDITIONS::ShowAlways ); + wxMenuItem* item = fileMenu->Add( openRecentMenu ); - fileMenu->AddSeparator(); - fileMenu->AddItem( ACTIONS::saveAs, SELECTION_CONDITIONS::ShowAlways ); + // Add the file menu condition here since it needs the item ID for the submenu + ACTION_CONDITIONS cond; + cond.SetEnableCondition( FILE_HISTORY::FileHistoryNotEmpty( fileHistory ) ); + RegisterUIUpdateHandler( item->GetId(), cond ); - fileMenu->AddSeparator(); - fileMenu->AddItem( ID_IMPORT_EAGLE_PROJECT, - _( "Import EAGLE Project..." ), - _( "Import EAGLE CAD XML schematic and board" ), - import_project_xpm, SELECTION_CONDITIONS::ShowAlways ); + fileMenu->Add( KICAD_MANAGER_ACTIONS::closeProject ); - fileMenu->AddSeparator(); - fileMenu->AddItem( ID_SAVE_AND_ZIP_FILES, - _( "&Archive Project..." ), - _( "Archive all needed project files into zip archive" ), - zip_xpm, SELECTION_CONDITIONS::ShowAlways ); + fileMenu->AppendSeparator(); + fileMenu->Add( ACTIONS::saveAs ); - fileMenu->AddItem( ID_READ_ZIP_ARCHIVE, - _( "&Unarchive Project..." ), - _( "Unarchive project files from zip archive" ), - unzip_xpm, SELECTION_CONDITIONS::ShowAlways ); + fileMenu->AppendSeparator(); + fileMenu->Add( _( "Import EAGLE Project..." ), + _( "Import EAGLE CAD XML schematic and board" ), + ID_IMPORT_EAGLE_PROJECT, + import_project_xpm ); - fileMenu->AddSeparator(); + fileMenu->AppendSeparator(); + fileMenu->Add( _( "&Archive Project..." ), + _( "Archive all needed project files into zip archive" ), + ID_SAVE_AND_ZIP_FILES, + zip_xpm ); + + fileMenu->Add( _( "&Unarchive Project..." ), + _( "Unarchive project files from zip archive" ), + ID_READ_ZIP_ARCHIVE, + unzip_xpm ); + + fileMenu->AppendSeparator(); fileMenu->AddQuitOrClose( nullptr, "KiCad" ); - fileMenu->Resolve(); - //-- View menu ----------------------------------------------------------- // - CONDITIONAL_MENU* viewMenu = new CONDITIONAL_MENU( false, controlTool ); + ACTION_MENU* viewMenu = new ACTION_MENU( false, controlTool ); - viewMenu->AddItem( ACTIONS::zoomRedraw, SELECTION_CONDITIONS::ShowAlways ); + viewMenu->Add( ACTIONS::zoomRedraw ); - viewMenu->AddSeparator(); - viewMenu->AddItem( KICAD_MANAGER_ACTIONS::openTextEditor, SELECTION_CONDITIONS::ShowAlways ); - viewMenu->AddItem( ID_BROWSE_IN_FILE_EXPLORER, - _( "Browse Project Files" ), _( "Open project directory in file browser" ), - directory_browser_xpm, SELECTION_CONDITIONS::ShowAlways ); + viewMenu->AppendSeparator(); + viewMenu->Add( KICAD_MANAGER_ACTIONS::openTextEditor ); + viewMenu->Add( _( "Browse Project Files" ), + _( "Open project directory in file browser" ), + ID_BROWSE_IN_FILE_EXPLORER, + directory_browser_xpm ); #ifdef __APPLE__ - viewMenu->AddSeparator(); + // Add a separator only on macOS because the OS adds menu items to the view menu after ours + viewMenu->AppendSeparator(); #endif - viewMenu->Resolve(); - //-- Tools menu ----------------------------------------------- // - CONDITIONAL_MENU* toolsMenu = new CONDITIONAL_MENU( false, controlTool ); + ACTION_MENU* toolsMenu = new ACTION_MENU( false, controlTool ); - toolsMenu->AddItem( KICAD_MANAGER_ACTIONS::editSchematic, SELECTION_CONDITIONS::ShowAlways ); - toolsMenu->AddItem( KICAD_MANAGER_ACTIONS::editSymbols, SELECTION_CONDITIONS::ShowAlways ); - toolsMenu->AddItem( KICAD_MANAGER_ACTIONS::editPCB, SELECTION_CONDITIONS::ShowAlways ); - toolsMenu->AddItem( KICAD_MANAGER_ACTIONS::editFootprints, SELECTION_CONDITIONS::ShowAlways ); + toolsMenu->Add( KICAD_MANAGER_ACTIONS::editSchematic ); + toolsMenu->Add( KICAD_MANAGER_ACTIONS::editSymbols ); + toolsMenu->Add( KICAD_MANAGER_ACTIONS::editPCB ); + toolsMenu->Add( KICAD_MANAGER_ACTIONS::editFootprints ); - toolsMenu->AddSeparator(); - toolsMenu->AddItem( KICAD_MANAGER_ACTIONS::viewGerbers, SELECTION_CONDITIONS::ShowAlways ); - toolsMenu->AddItem( KICAD_MANAGER_ACTIONS::convertImage, SELECTION_CONDITIONS::ShowAlways ); - toolsMenu->AddItem( KICAD_MANAGER_ACTIONS::showCalculator, SELECTION_CONDITIONS::ShowAlways ); - toolsMenu->AddItem( KICAD_MANAGER_ACTIONS::editWorksheet, SELECTION_CONDITIONS::ShowAlways ); + toolsMenu->AppendSeparator(); + toolsMenu->Add( KICAD_MANAGER_ACTIONS::viewGerbers ); + toolsMenu->Add( KICAD_MANAGER_ACTIONS::convertImage ); + toolsMenu->Add( KICAD_MANAGER_ACTIONS::showCalculator ); + toolsMenu->Add( KICAD_MANAGER_ACTIONS::editWorksheet ); - toolsMenu->AddSeparator(); - toolsMenu->AddItem( ID_EDIT_LOCAL_FILE_IN_TEXT_EDITOR, - _( "Edit Local File..." ), _( "Edit local file in text editor" ), - browse_files_xpm, SELECTION_CONDITIONS::ShowAlways ); - - toolsMenu->Resolve(); + toolsMenu->AppendSeparator(); + toolsMenu->Add( _( "Edit Local File..." ), + _( "Edit local file in text editor" ), + ID_EDIT_LOCAL_FILE_IN_TEXT_EDITOR, + browse_files_xpm ); //-- Preferences menu ----------------------------------------------- // - CONDITIONAL_MENU* prefsMenu = new CONDITIONAL_MENU( false, controlTool ); + ACTION_MENU* prefsMenu = new ACTION_MENU( false, controlTool ); - prefsMenu->AddItem( ACTIONS::configurePaths, SELECTION_CONDITIONS::ShowAlways ); - prefsMenu->AddItem( ACTIONS::showSymbolLibTable, SELECTION_CONDITIONS::ShowAlways ); - prefsMenu->AddItem( ACTIONS::showFootprintLibTable, SELECTION_CONDITIONS::ShowAlways ); - prefsMenu->AddItem( wxID_PREFERENCES, - _( "Preferences...\tCTRL+," ), - _( "Show preferences for all open tools" ), - preference_xpm, SELECTION_CONDITIONS::ShowAlways ); + prefsMenu->Add( ACTIONS::configurePaths ); + prefsMenu->Add( ACTIONS::showSymbolLibTable ); + prefsMenu->Add( ACTIONS::showFootprintLibTable ); + prefsMenu->Add( _( "Preferences...\tCTRL+," ), + _( "Show preferences for all open tools" ), + wxID_PREFERENCES, + preference_xpm ); - prefsMenu->AddSeparator(); + prefsMenu->AppendSeparator(); AddMenuLanguageList( prefsMenu, controlTool ); - prefsMenu->Resolve(); //-- Menubar ------------------------------------------------------------- // - menuBar->Append( fileMenu, _( "&File" ) ); - menuBar->Append( viewMenu, _( "&View" ) ); + menuBar->Append( fileMenu, _( "&File" ) ); + menuBar->Append( viewMenu, _( "&View" ) ); menuBar->Append( toolsMenu, _( "&Tools" ) ); menuBar->Append( prefsMenu, _( "&Preferences" ) ); AddStandardHelpMenu( menuBar ); @@ -255,17 +256,4 @@ void KICAD_MANAGER_FRAME::RecreateLauncher() // Create mlauncher m_launcher->Realize(); - - // And update the visual tools state: - SyncToolbars(); } - - -void KICAD_MANAGER_FRAME::SyncToolbars() -{ - m_launcher->Toggle( KICAD_MANAGER_ACTIONS::editSchematic, m_active_project ); - m_launcher->Toggle( KICAD_MANAGER_ACTIONS::editPCB, m_active_project ); - m_launcher->Refresh(); -} - -