diff --git a/eeschema/onrightclick.cpp b/eeschema/onrightclick.cpp index 7ec5bfcba0..c0652e8794 100644 --- a/eeschema/onrightclick.cpp +++ b/eeschema/onrightclick.cpp @@ -784,56 +784,10 @@ void AddMenusForBus( wxMenu* PopMenu, SCH_LINE* Bus, SCH_EDIT_FRAME* frame ) } // Bus unfolding menu (only available if bus is properly defined) - auto connection = Bus->Connection( *g_CurrentSheet ); + wxMenu* bus_unfold_menu = frame->GetUnfoldBusMenu( Bus ); - if( connection && connection->IsBus() && connection->Members().size() > 0 ) - { - int idx = 0; - wxMenu* bus_unfolding_menu = new wxMenu; - - PopMenu->AppendSubMenu( bus_unfolding_menu, _( "Unfold Bus" ) ); - - for( const auto& member : connection->Members() ) - { - int id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ ); - auto name = member->Name( true ); - - if( member->Type() == CONNECTION_BUS ) - { - wxMenu* submenu = new wxMenu; - bus_unfolding_menu->AppendSubMenu( submenu, _( name ) ); - - for( const auto& sub_member : member->Members() ) - { - id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ ); - - submenu->Append( id, sub_member->Name( true ), wxEmptyString ); - - // See comment in else clause below - auto sub_item_clone = new wxMenuItem(); - sub_item_clone->SetItemLabel( sub_member->Name( true ) ); - - frame->Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, - frame, id, id, sub_item_clone ); - } - } - else - { - bus_unfolding_menu->Append( id, name, wxEmptyString ); - - // Because Bind() takes ownership of the user data item, we - // make a new menu item here and set its label. Why create a - // menu item instead of just a wxString or something? Because - // Bind() requires a pointer to wxObject rather than a void - // pointer. Maybe at some point I'll think of a better way... - auto item_clone = new wxMenuItem(); - item_clone->SetItemLabel( name ); - - frame->Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, - frame, id, id, item_clone ); - } - } - } + if( bus_unfold_menu ) + PopMenu->AppendSubMenu( bus_unfold_menu, _( "Unfold Bus" ) ); PopMenu->AppendSeparator(); msg = AddHotkeyName( _( "Add Junction" ), g_Schematic_Hotkeys_Descr, HK_ADD_JUNCTION ); diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h index ae0ae30162..459d9257ba 100644 --- a/eeschema/sch_edit_frame.h +++ b/eeschema/sch_edit_frame.h @@ -260,6 +260,11 @@ public: */ void OnUnfoldBus( wxCommandEvent& event ); + /** + * Builds the context menu for unfolding a bus + */ + wxMenu* GetUnfoldBusMenu( SCH_LINE* aBus ); + bool GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey ) override; /** diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp index e182ef6624..7589d6f1e2 100644 --- a/eeschema/schedit.cpp +++ b/eeschema/schedit.cpp @@ -316,10 +316,14 @@ void SCH_EDIT_FRAME::OnUnfoldBus( wxCommandEvent& event ) { - wxMenuItem* item = static_cast< wxMenuItem* >( event.GetEventUserData() ); - static wxString net = item->GetItemLabelText(); + wxMenuItem* item = static_cast( event.GetEventUserData() ); + wxString net = item->GetItemLabelText(); - GetToolManager()->RunAction( SCH_ACTIONS::unfoldBus, true, &net ); + GetToolManager()->RunAction( SCH_ACTIONS::unfoldBus, true, &net ); + + // Now that we have handled the chosen bus unfold, disconnect all the events so they can be + // recreated with updated data on the next unfold + Unbind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this ); } @@ -1182,57 +1186,72 @@ void SCH_EDIT_FRAME::OnUnfoldBusHotkey( wxCommandEvent& aEvent ) return; } - auto connection = item->Connection( *g_CurrentSheet ); + if( item->Type() != SCH_LINE_T ) + return; - if( connection && connection->IsBus() ) + wxMenu* bus_unfold_menu = GetUnfoldBusMenu( static_cast( item ) ); + + if( bus_unfold_menu ) { - int idx = 0; - wxMenu* bus_unfolding_menu = new wxMenu; - - for( const auto& member : connection->Members() ) - { - int id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ ); - - if( member->Type() == CONNECTION_BUS ) - { - wxMenu* submenu = new wxMenu; - bus_unfolding_menu->AppendSubMenu( submenu, _( member->Name() ) ); - - for( const auto& sub_member : member->Members() ) - { - id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ ); - - submenu->Append( id, sub_member->Name(), wxEmptyString ); - - // See comment in else clause below - auto sub_item_clone = new wxMenuItem(); - sub_item_clone->SetItemLabel( sub_member->Name() ); - - Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, - this, id, id, sub_item_clone ); - } - } - else - { - bus_unfolding_menu->Append( id, member->Name(), wxEmptyString ); - - // Because Bind() takes ownership of the user data item, we - // make a new menu item here and set its label. Why create a - // menu item instead of just a wxString or something? Because - // Bind() requires a pointer to wxObject rather than a void - // pointer. Maybe at some point I'll think of a better way... - auto item_clone = new wxMenuItem(); - item_clone->SetItemLabel( member->Name() ); - - Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, - this, id, id, item_clone ); - } - } - auto controls = GetCanvas()->GetViewControls(); auto vmp = controls->GetMousePosition( false ); wxPoint mouse_pos( (int) vmp.x, (int) vmp.y ); - GetGalCanvas()->PopupMenu( bus_unfolding_menu, mouse_pos ); + GetGalCanvas()->PopupMenu( bus_unfold_menu, mouse_pos ); } } + + +wxMenu* SCH_EDIT_FRAME::GetUnfoldBusMenu( SCH_LINE* aBus ) +{ + auto connection = aBus->Connection( *g_CurrentSheet ); + + if( !connection || !connection->IsBus() || connection->Members().empty() ) + return nullptr; + + int idx = 0; + wxMenu* bus_unfolding_menu = new wxMenu; + + for( const auto& member : connection->Members() ) + { + int id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ ); + wxString name = member->Name( true ); + + if( member->Type() == CONNECTION_BUS ) + { + wxMenu* submenu = new wxMenu; + bus_unfolding_menu->AppendSubMenu( submenu, _( name ) ); + + for( const auto& sub_member : member->Members() ) + { + id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ ); + + submenu->Append( id, sub_member->Name( true ), wxEmptyString ); + + // See comment in else clause below + auto sub_item_clone = new wxMenuItem(); + sub_item_clone->SetItemLabel( sub_member->Name( true ) ); + + Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this, id, id, + sub_item_clone ); + } + } + else + { + bus_unfolding_menu->Append( id, name, wxEmptyString ); + + // Because Bind() takes ownership of the user data item, we + // make a new menu item here and set its label. Why create a + // menu item instead of just a wxString or something? Because + // Bind() requires a pointer to wxObject rather than a void + // pointer. Maybe at some point I'll think of a better way... + auto item_clone = new wxMenuItem(); + item_clone->SetItemLabel( name ); + + Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this, id, id, + item_clone ); + } + } + + return bus_unfolding_menu; +}