From fa84babefe247670b75e3ea9b95f8d6527e9d856 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 26 Jun 2019 19:35:56 +0100 Subject: [PATCH] Re-implement sch->pcb cross-probing using net highlighting architecture. Fixes: lp:1827853 * https://bugs.launchpad.net/kicad/+bug/1827853 --- eeschema/cross-probing.cpp | 16 +- eeschema/sch_view.cpp | 21 ++- include/painter.h | 7 +- pcbnew/class_board.h | 4 +- pcbnew/cross-probing.cpp | 248 +++++++++++++--------------- pcbnew/initpcb.cpp | 2 +- pcbnew/pcb_painter.cpp | 8 + pcbnew/tools/pcb_actions.cpp | 3 - pcbnew/tools/pcb_actions.h | 1 - pcbnew/tools/pcb_editor_control.cpp | 36 +--- pcbnew/tools/pcb_editor_control.h | 3 - 11 files changed, 148 insertions(+), 201 deletions(-) diff --git a/eeschema/cross-probing.cpp b/eeschema/cross-probing.cpp index 8d3eece4f5..99e32173f1 100644 --- a/eeschema/cross-probing.cpp +++ b/eeschema/cross-probing.cpp @@ -127,11 +127,15 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline ) if( strcmp( idcmd, "$REF:" ) == 0 ) { - FindComponentAndItem( part_ref, true, FIND_REFERENCE, msg ); + // Highlighting the reference itself isn't actually that useful, and it's harder to + // see. Highlight the parent and display the message. + FindComponentAndItem( part_ref, true, FIND_COMPONENT_ONLY, msg ); } else if( strcmp( idcmd, "$VAL:" ) == 0 ) { - FindComponentAndItem( part_ref, true, FIND_VALUE, msg ); + // Highlighting the value itself isn't actually that useful, and it's harder to see. + // Highlight the parent and display the message. + FindComponentAndItem( part_ref, true, FIND_COMPONENT_ONLY, msg ); } else if( strcmp( idcmd, "$PAD:" ) == 0 ) { @@ -151,14 +155,6 @@ std::string FormatProbeItem( EDA_ITEM* aItem, SCH_COMPONENT* aComp ) // Cross probing to Pcbnew if a pin or a component is found switch( aItem->Type() ) { - case LIB_PIN_T: - wxFAIL_MSG( "What are we doing with LIB_* items here?" ); - break; - - case LIB_FIELD_T: - wxFAIL_MSG( "What are we doing with LIB_* items here?" ); - // fall through to SCH_FIELD_T: - case SCH_FIELD_T: if( aComp ) return StrPrintf( "$PART: \"%s\"", TO_UTF8( aComp->GetField( REFERENCE )->GetText() ) ); diff --git a/eeschema/sch_view.cpp b/eeschema/sch_view.cpp index 24797f2276..73aa3ab6fa 100644 --- a/eeschema/sch_view.cpp +++ b/eeschema/sch_view.cpp @@ -190,13 +190,21 @@ void SCH_VIEW::HideWorksheet() void SCH_VIEW::HighlightItem( EDA_ITEM *aItem, LIB_PIN* aPin ) { - if( !aItem ) + if( aItem && aItem->Type() == SCH_COMPONENT_T && aPin ) + { + static_cast( aItem )->HighlightPin( aPin ); + } + else if( aItem ) + { + aItem->SetFlags( HIGHLIGHTED ); + } + else { for( auto item : *m_allItems ) { // Not all view items can be highlighted, only EDA_ITEMs // So clear flag of only EDA_ITEMs. - auto eitem = dynamic_cast( item ); + EDA_ITEM* eitem = dynamic_cast( item ); if( eitem ) { @@ -210,15 +218,6 @@ void SCH_VIEW::HighlightItem( EDA_ITEM *aItem, LIB_PIN* aPin ) } } } - else - { - if( ( aItem->Type() == SCH_COMPONENT_T ) && aPin ) - { - static_cast( aItem )->HighlightPin( aPin ); - } - else - aItem->SetFlags( HIGHLIGHTED ); - } // ugly but I guess OK for the moment... UpdateAllItems( ALL ); diff --git a/include/painter.h b/include/painter.h index 9aa8100d2d..67c9c7a853 100644 --- a/include/painter.h +++ b/include/painter.h @@ -132,15 +132,17 @@ public: /** * Function SetHighlight - * Turns on/off highlighting - it may be done for the active layer or the specified net. + * Turns on/off highlighting - it may be done for the active layer, the specified net, or + * items with their HIGHLIGHTED flags set. * @param aEnabled tells if highlighting should be enabled. * @param aNetcode is optional and if specified, turns on higlighting only for the net with * number given as the parameter. */ - inline void SetHighlight( bool aEnabled, int aNetcode = -1 ) + inline void SetHighlight( bool aEnabled, int aNetcode = -1, bool aHighlightItems = false ) { m_highlightEnabled = aEnabled; m_highlightNetcode = aEnabled ? aNetcode : -1; + m_highlightItems = aEnabled ? aHighlightItems : false; } /** @@ -282,6 +284,7 @@ protected: int m_highlightNetcode; ///< Net number that is displayed in highlight ///< -1 means that there is no specific net, and whole active ///< layer is highlighted + bool m_highlightItems; ///< Highlight items with their HIGHLIGHT flags set float m_highlightFactor; ///< Factor used for computing hightlight color float m_selectFactor; ///< Specifies how color of selected items is changed diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index be0bb8329f..3823cbf487 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -377,10 +377,10 @@ public: const wxPoint& GetGridOrigin() const { return m_designSettings.m_GridOrigin; } /** - * Function ResetHighLight + * Function ResetNetHighLight * Reset all high light data to the init state */ - void ResetHighLight() + void ResetNetHighLight() { m_highLight.Clear(); m_highLightPrevious.Clear(); diff --git a/pcbnew/cross-probing.cpp b/pcbnew/cross-probing.cpp index d4163b108a..a43f262fa3 100644 --- a/pcbnew/cross-probing.cpp +++ b/pcbnew/cross-probing.cpp @@ -73,10 +73,13 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline ) wxString modName; char* idcmd; char* text; + int netcode = -1; MODULE* module = NULL; D_PAD* pad = NULL; BOARD* pcb = GetBoard(); - wxPoint pos; + + KIGFX::VIEW* view = m_toolManager->GetView(); + KIGFX::RENDER_SETTINGS* renderSettings = view->GetPainter()->GetSettings(); strncpy( line, cmdline, sizeof(line) - 1 ); line[sizeof(line) - 1] = 0; @@ -89,125 +92,22 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline ) if( strcmp( idcmd, "$NET:" ) == 0 ) { - if( IsCurrentTool( PCB_ACTIONS::highlightNetTool ) ) + wxString net_name = FROM_UTF8( text ); + + NETINFO_ITEM* netinfo = pcb->FindNet( net_name ); + + if( netinfo ) { - wxString net_name = FROM_UTF8( text ); - NETINFO_ITEM* netinfo = pcb->FindNet( net_name ); - int netcode = -1; + netcode = netinfo->GetNet(); - if( netinfo ) - netcode = netinfo->GetNet(); - - if( netcode > 0 ) - { - pcb->SetHighLightNet( netcode ); - - if( netinfo ) - { - MSG_PANEL_ITEMS items; - netinfo->GetMsgPanelInfo( GetUserUnits(), items ); - SetMsgPanel( items ); - } - } - - auto view = m_toolManager->GetView(); - auto rs = view->GetPainter()->GetSettings(); - rs->SetHighlight( ( netcode >= 0 ), netcode ); - view->UpdateAllLayersColor(); - - BOX2I bbox; - bool first = true; - - auto merge_area = [netcode, &bbox, &first]( BOARD_CONNECTED_ITEM* aItem ) - { - if( aItem->GetNetCode() == netcode ) - { - if( first ) - { - bbox = aItem->GetBoundingBox(); - first = false; - } - else - { - bbox.Merge( aItem->GetBoundingBox() ); - } - } - }; - - for( auto zone : pcb->Zones() ) - merge_area( zone ); - - for( auto track : pcb->Tracks() ) - merge_area( track ); - - for( auto mod : pcb->Modules() ) - for ( auto mod_pad : mod->Pads() ) - merge_area( mod_pad ); - - if( netcode > 0 && bbox.GetWidth() > 0 && bbox.GetHeight() > 0 ) - { - auto bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize(); - auto screenSize = view->ToWorld( GetCanvas()->GetClientSize(), false ); - double ratio = std::max( fabs( bbSize.x / screenSize.x ), - fabs( bbSize.y / screenSize.y ) ); - double scale = view->GetScale() / ratio; - - view->SetScale( scale ); - view->SetCenter( bbox.Centre() ); - } - - GetCanvas()->Refresh(); + MSG_PANEL_ITEMS items; + netinfo->GetMsgPanelInfo( GetUserUnits(), items ); + SetMsgPanel( items ); } - - return; - } - else if( strcmp( idcmd, "$CLEAR" ) == 0 ) - { - auto view = m_toolManager->GetView(); - auto rs = view->GetPainter()->GetSettings(); - rs->SetHighlight( false ); - view->UpdateAllLayersColor(); - - pcb->ResetHighLight(); - SetMsgPanel( pcb ); - - GetCanvas()->Refresh(); - } - - if( text == NULL ) - return; - - if( strcmp( idcmd, "$PART:" ) == 0 ) - { - modName = FROM_UTF8( text ); - - module = pcb->FindModuleByReference( modName ); - - if( module ) - msg.Printf( _( "%s found" ), modName ); - else - msg.Printf( _( "%s not found" ), modName ); - - SetStatusText( msg ); - - if( module ) - pos = module->GetPosition(); - } - else if( strcmp( idcmd, "$SHEET:" ) == 0 ) - { - msg.Printf( _( "Selecting all from sheet \"%s\"" ), FROM_UTF8( text ) ); - wxString sheetStamp( FROM_UTF8( text ) ); - SetStatusText( msg ); - GetToolManager()->RunAction( PCB_ACTIONS::selectOnSheetFromEeschema, true, - static_cast( &sheetStamp ) ); - return; } else if( strcmp( idcmd, "$PIN:" ) == 0 ) { - wxString pinName; - int netcode = -1; - - pinName = FROM_UTF8( text ); + wxString pinName = FROM_UTF8( text ); text = strtok( NULL, " \n\r" ); @@ -222,24 +122,8 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline ) pad = module->FindPadByName( pinName ); if( pad ) - { netcode = pad->GetNetCode(); - // put cursor on the pad: - pos = pad->GetPosition(); - } - - if( netcode > 0 ) // highlight the pad net - { - pcb->HighLightON(); - pcb->SetHighLightNet( netcode ); - } - else - { - pcb->HighLightOFF(); - pcb->SetHighLightNet( -1 ); - } - if( module == NULL ) msg.Printf( _( "%s not found" ), modName ); else if( pad == NULL ) @@ -249,12 +133,108 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline ) SetStatusText( msg ); } - - if( module ) // if found, center the module on screen, and redraw the screen. + else if( strcmp( idcmd, "$PART:" ) == 0 ) { - GetToolManager()->RunAction( PCB_ACTIONS::crossProbeSchToPcb, true, - pad ? (BOARD_ITEM*) pad : (BOARD_ITEM*) module ); + pcb->ResetNetHighLight(); + + modName = FROM_UTF8( text ); + + module = pcb->FindModuleByReference( modName ); + + if( module ) + msg.Printf( _( "%s found" ), modName ); + else + msg.Printf( _( "%s not found" ), modName ); + + SetStatusText( msg ); } + else if( strcmp( idcmd, "$SHEET:" ) == 0 ) + { + msg.Printf( _( "Selecting all from sheet \"%s\"" ), FROM_UTF8( text ) ); + wxString sheetStamp( FROM_UTF8( text ) ); + SetStatusText( msg ); + GetToolManager()->RunAction( PCB_ACTIONS::selectOnSheetFromEeschema, true, + static_cast( &sheetStamp ) ); + return; + } + else if( strcmp( idcmd, "$CLEAR" ) == 0 ) + { + renderSettings->SetHighlight( false ); + view->UpdateAllLayersColor(); + + pcb->ResetNetHighLight(); + SetMsgPanel( pcb ); + + GetCanvas()->Refresh(); + return; + } + + if( module ) + { + renderSettings->SetHighlight( true, -1, true ); + + for( MODULE* mod : pcb->Modules() ) + { + mod->ClearHighlighted(); + mod->RunOnChildren( []( BOARD_ITEM* child ) { child->ClearHighlighted(); } ); + } + + module->SetHighlighted(); + module->RunOnChildren( []( BOARD_ITEM* child ) { child->SetHighlighted(); } ); + + view->SetCenter( VECTOR2D( module->GetPosition() ) ); + } + else if( netcode > 0 ) + { + renderSettings->SetHighlight( ( netcode >= 0 ), netcode ); + + pcb->SetHighLightNet( netcode ); + + BOX2I bbox; + + auto merge_area = [netcode, &bbox]( BOARD_CONNECTED_ITEM* aItem ) + { + if( aItem->GetNetCode() == netcode ) + { + if( bbox.GetWidth() == 0 ) + bbox = aItem->GetBoundingBox(); + else + bbox.Merge( aItem->GetBoundingBox() ); + } + }; + + for( auto zone : pcb->Zones() ) + merge_area( zone ); + + for( auto track : pcb->Tracks() ) + merge_area( track ); + + for( auto mod : pcb->Modules() ) + for ( auto mod_pad : mod->Pads() ) + merge_area( mod_pad ); + + if( bbox.GetWidth() > 0 && bbox.GetHeight() > 0 ) + { + auto bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize(); + auto screenSize = view->ToWorld( GetCanvas()->GetClientSize(), false ); + double ratio = std::max( fabs( bbSize.x / screenSize.x ), + fabs( bbSize.y / screenSize.y ) ); + double scale = view->GetScale() / ratio; + + view->SetScale( scale ); + view->SetCenter( bbox.Centre() ); + } + } + else + { + renderSettings->SetHighlight( false ); + } + + view->UpdateAllLayersColor(); + // Ensure the display is refreshed, because in some installs the refresh is done only + // when the gal canvas has the focus, and that is not the case when crossprobing from + // Eeschema: + GetCanvas()->Refresh(); } diff --git a/pcbnew/initpcb.cpp b/pcbnew/initpcb.cpp index f3ec088a18..0c470ca08b 100644 --- a/pcbnew/initpcb.cpp +++ b/pcbnew/initpcb.cpp @@ -73,7 +73,7 @@ bool PCB_EDIT_FRAME::Clear_Pcb( bool aQuery, bool aFinal ) GetScreen()->InitDataPoints( GetPageSizeIU() ); - GetBoard()->ResetHighLight(); + GetBoard()->ResetNetHighLight(); // Enable all layers (SetCopperLayerCount() will adjust the copper layers enabled) GetBoard()->SetEnabledLayers( LSET().set() ); diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 2019584f80..c1a45a61d9 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -241,6 +241,14 @@ const COLOR4D& PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer return m_layerColorsSel[aLayer]; } + if( m_highlightEnabled && m_highlightItems ) + { + if( item->IsHighlighted() ) + return m_layerColorsHi[aLayer]; + else + return m_layerColorsDark[aLayer]; + } + // Try to obtain the netcode for the item if( const BOARD_CONNECTED_ITEM* conItem = dyn_cast ( item ) ) netCode = conItem->GetNetCode(); diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp index 0b14cf44c1..85fcac22c6 100644 --- a/pcbnew/tools/pcb_actions.cpp +++ b/pcbnew/tools/pcb_actions.cpp @@ -560,9 +560,6 @@ TOOL_ACTION PCB_ACTIONS::drillOrigin( "pcbnew.EditorControl.drillOrigin", _( "Drill and Place Offset" ), _( "Place origin point for drill and place files" ), pcb_offset_xpm ); -TOOL_ACTION PCB_ACTIONS::crossProbeSchToPcb( "pcbnew.EditorControl.crossProbSchToPcb", - AS_GLOBAL ); - TOOL_ACTION PCB_ACTIONS::toggleLock( "pcbnew.EditorControl.toggleLock", AS_GLOBAL, 'L', LEGACY_HK_NAME( "Lock/Unlock Footprint" ), diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index 795a0bc61c..57269d3fa9 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -412,7 +412,6 @@ public: static TOOL_ACTION highlightNetTool; static TOOL_ACTION highlightNetSelection; static TOOL_ACTION drillOrigin; - static TOOL_ACTION crossProbeSchToPcb; static TOOL_ACTION appendBoard; // Ratsnest diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp index b295a75a29..76870b8af4 100644 --- a/pcbnew/tools/pcb_editor_control.cpp +++ b/pcbnew/tools/pcb_editor_control.cpp @@ -954,37 +954,6 @@ int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent ) } -int PCB_EDITOR_CONTROL::CrossProbeSchToPcb( const TOOL_EVENT& aEvent ) -{ - BOARD_ITEM* item = aEvent.Parameter(); - - if( item ) - { - m_probingSchToPcb = true; - getView()->SetCenter( VECTOR2D( item->GetPosition() ) ); - m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); - - // If it is a pad and the net highlighting tool is enabled, highlight the net - if( item->Type() == PCB_PAD_T && m_frame->IsCurrentTool( PCB_ACTIONS::highlightNetTool ) ) - { - int net = static_cast( item )->GetNetCode(); - m_toolMgr->RunAction( PCB_ACTIONS::highlightNet, false, net ); - } - else - // Otherwise simply select the corresponding item - { - m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, item ); - // Ensure the display is refreshed, because in some installs - // the refresh is done only when the gal canvas has the focus, and - // that is not the case when crossprobing from Eeschema: - m_frame->GetCanvas()->Refresh(); - } - } - - return 0; -} - - void PCB_EDITOR_CONTROL::DoSetDrillOrigin( KIGFX::VIEW* aView, PCB_BASE_FRAME* aFrame, BOARD_ITEM* originViewItem, const VECTOR2D& aPosition ) { @@ -1122,7 +1091,7 @@ int PCB_EDITOR_CONTROL::DrillOrigin( const TOOL_EVENT& aEvent ) } else { - board->ResetHighLight(); + board->ResetNetHighLight(); frame->SetMsgPanel( board ); frame->SendCrossProbeNetName( "" ); } @@ -1164,7 +1133,7 @@ int PCB_EDITOR_CONTROL::ClearHighlight( const TOOL_EVENT& aEvent ) auto board = static_cast( m_toolMgr->GetModel() ); KIGFX::RENDER_SETTINGS* render = m_toolMgr->GetView()->GetPainter()->GetSettings(); - board->ResetHighLight(); + board->ResetNetHighLight(); render->SetHighlight( false ); m_toolMgr->GetView()->UpdateAllLayersColor(); frame->SetMsgPanel( board ); @@ -1430,7 +1399,6 @@ void PCB_EDITOR_CONTROL::setTransitions() Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, EVENTS::SelectedEvent ); Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, EVENTS::UnselectedEvent ); Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, EVENTS::ClearedEvent ); - Go( &PCB_EDITOR_CONTROL::CrossProbeSchToPcb, PCB_ACTIONS::crossProbeSchToPcb.MakeEvent() ); Go( &PCB_EDITOR_CONTROL::HighlightNet, PCB_ACTIONS::highlightNet.MakeEvent() ); Go( &PCB_EDITOR_CONTROL::HighlightNet, PCB_ACTIONS::toggleLastNetHighlight.MakeEvent() ); Go( &PCB_EDITOR_CONTROL::ClearHighlight, PCB_ACTIONS::clearHighlight.MakeEvent() ); diff --git a/pcbnew/tools/pcb_editor_control.h b/pcbnew/tools/pcb_editor_control.h index e8cf533849..fdb1527108 100644 --- a/pcbnew/tools/pcb_editor_control.h +++ b/pcbnew/tools/pcb_editor_control.h @@ -108,9 +108,6 @@ public: ///> Notifies eeschema about the selected item. int CrossProbePcbToSch( const TOOL_EVENT& aEvent ); - ///> Reacts to selection change in eeschema. - int CrossProbeSchToPcb( const TOOL_EVENT& aEvent ); - ///> Runs the drill origin tool for setting the origin for drill and pick-and-place files. int DrillOrigin( const TOOL_EVENT& aEvent );