/**
 * Function highlightNet()
 * Looks for a BOARD_CONNECTED_ITEM in a given spot, and if one is found - it enables
 * highlight for its net.
 * @param aPoint is the point where an item is expected (world coordinates).
 */
static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
{
    KIGFX::RENDER_SETTINGS* render = aToolMgr->GetView()->GetPainter()->GetSettings();
    GENERAL_COLLECTORS_GUIDE guide = static_cast<PCB_BASE_FRAME*>( aToolMgr->GetEditFrame() )->GetCollectorsGuide();
    BOARD* board = static_cast<BOARD*>( aToolMgr->GetModel() );
    GENERAL_COLLECTOR collector;
    int net = -1;

    // Find a connected item for which we are going to highlight a net
    collector.Collect( board, GENERAL_COLLECTOR::PadsTracksOrZones,
                       wxPoint( aPosition.x, aPosition.y ), guide );
    bool enableHighlight = ( collector.GetCount() > 0 );

    // Obtain net code for the clicked item
    if( enableHighlight )
        net = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] )->GetNetCode();

    // Toggle highlight when the same net was picked
    if( net > 0 && net == render->GetHighlightNetCode() )
        enableHighlight = !render->IsHighlightEnabled();

    if( enableHighlight != render->IsHighlightEnabled() || net != render->GetHighlightNetCode() )
    {
        render->SetHighlight( enableHighlight, net );
        aToolMgr->GetView()->UpdateAllLayersColor();
    }

    return true;
}
/**
 * Function highlightNet()
 * Looks for a BOARD_CONNECTED_ITEM in a given spot, and if one is found - it enables
 * highlight for its net.
 * @param aPoint is the point where an item is expected (world coordinates).
 */
static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
{
    auto render = aToolMgr->GetView()->GetPainter()->GetSettings();
    auto frame = static_cast<PCB_EDIT_FRAME*>( aToolMgr->GetEditFrame() );
    auto guide = frame->GetCollectorsGuide();
    BOARD* board = static_cast<BOARD*>( aToolMgr->GetModel() );
    GENERAL_COLLECTOR collector;
    int net = -1;

    // Find a connected item for which we are going to highlight a net
    collector.Collect( board, GENERAL_COLLECTOR::PadsTracksOrZones,
                       wxPoint( aPosition.x, aPosition.y ), guide );

    for( int i = 0; i < collector.GetCount(); i++ )
    {
        if( collector[i]->Type() == PCB_PAD_T )
        {
            frame->SendMessageToEESCHEMA( static_cast<BOARD_CONNECTED_ITEM*>( collector[i] ) );
            break;
        }
    }

    bool enableHighlight = ( collector.GetCount() > 0 );

    // Obtain net code for the clicked item
    if( enableHighlight )
        net = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] )->GetNetCode();

    // Toggle highlight when the same net was picked
    if( net > 0 && net == render->GetHighlightNetCode() )
        enableHighlight = !render->IsHighlightEnabled();

    if( enableHighlight != render->IsHighlightEnabled() || net != render->GetHighlightNetCode() )
    {
        render->SetHighlight( enableHighlight, net );
        aToolMgr->GetView()->UpdateAllLayersColor();
    }

    // Store the highlighted netcode in the current board (for dialogs for instance)
    if( enableHighlight && net >= 0 )
        board->SetHighLightNet( net );
    else
        board->ResetHighLight();

    return true;
}
void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere )
{
    BOARD* pcb = getModel<BOARD>( PCB_T );
    BOARD_ITEM* item;
    GENERAL_COLLECTORS_GUIDE guide = getEditFrame<PCB_EDIT_FRAME>()->GetCollectorsGuide();
    GENERAL_COLLECTOR collector;

    collector.Collect( pcb, GENERAL_COLLECTOR::AllBoardItems,
                       wxPoint( aWhere.x, aWhere.y ), guide );

    switch( collector.GetCount() )
    {
    case 0:
        if( !m_additive )
            clearSelection();
        break;

    case 1:
        toggleSelection( collector[0] );
        break;

    default:
        // Remove unselectable items
        for( int i = collector.GetCount() - 1; i >= 0 ; --i )
        {
            if( !selectable( collector[i] ) )
                collector.Remove( i );
        }

        // Let's see if there is still disambiguation in selection..
        if( collector.GetCount() == 1 )
        {
            toggleSelection( collector[0] );
        }
        else if( collector.GetCount() > 1 )
        {
            item = disambiguationMenu( &collector );

            if( item )
                toggleSelection( item );
        }

        break;
    }
}
void SELECTION_TOOL::highlightNet( const VECTOR2I& aPoint )
{
    KIGFX::RENDER_SETTINGS* render = getView()->GetPainter()->GetSettings();
    GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide();
    GENERAL_COLLECTOR collector;
    int net = -1;

    // Find a connected item for which we are going to highlight a net
    collector.Collect( getModel<BOARD>(), GENERAL_COLLECTOR::PadsTracksOrZones,
                       wxPoint( aPoint.x, aPoint.y ), guide );
    bool enableHighlight = ( collector.GetCount() > 0 );

    // Obtain net code for the clicked item
    if( enableHighlight )
        net = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] )->GetNetCode();

    if( enableHighlight != render->GetHighlight() || net != render->GetHighlightNetCode() )
    {
        render->SetHighlight( enableHighlight, net );
        getView()->UpdateAllLayersColor();
    }
}
bool SELECTION_TOOL::selectCursor( const VECTOR2I& aWhere, bool aOnDrag )
{
    BOARD_ITEM* item;
    GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide();
    GENERAL_COLLECTOR collector;

    if( m_editModules )
        collector.Collect( getModel<BOARD>(), GENERAL_COLLECTOR::ModuleItems,
                           wxPoint( aWhere.x, aWhere.y ), guide );
    else
        collector.Collect( getModel<BOARD>(), GENERAL_COLLECTOR::AllBoardItems,
                           wxPoint( aWhere.x, aWhere.y ), guide );

    bool anyCollected = collector.GetCount() != 0;

    // Remove unselectable items
    for( int i = collector.GetCount() - 1; i >= 0; --i )
    {
        if( !selectable( collector[i] ) || ( aOnDrag && collector[i]->IsLocked() ) )
            collector.Remove( i );
    }

    switch( collector.GetCount() )
    {
    case 0:
        if( !m_additive && anyCollected )
            clearSelection();

        return false;

    case 1:
        toggleSelection( collector[0] );

        return true;

    default:
        // Apply some ugly heuristics to avoid disambiguation menus whenever possible
        guessSelectionCandidates( collector );

        // Let's see if there is still disambiguation in selection..
        if( collector.GetCount() == 1 )
        {
            toggleSelection( collector[0] );

            return true;
        }
        else if( collector.GetCount() > 1 )
        {
            if( aOnDrag )
                Wait( TOOL_EVENT( TC_ANY, TA_MOUSE_UP, BUT_LEFT ) );

            item = disambiguationMenu( &collector );

            if( item )
            {
                toggleSelection( item );

                return true;
            }
        }
        break;
    }

    return false;
}
Example #6
0
int MODULE_TOOLS::EnumeratePads( const TOOL_EVENT& aEvent )
{
    std::list<D_PAD*> pads;
    std::set<D_PAD*> allPads;

    if( !m_board->m_Modules || !m_board->m_Modules->Pads() )
        return 0;

    GENERAL_COLLECTOR collector;
    const KICAD_T types[] = { PCB_PAD_T, EOT };

    GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide();
    guide.SetIgnoreMTextsMarkedNoShow( true );
    guide.SetIgnoreMTextsOnBack( true );
    guide.SetIgnoreMTextsOnFront( true );
    guide.SetIgnoreModulesVals( true );
    guide.SetIgnoreModulesRefs( true );

    // Create a set containing all pads (to avoid double adding to the list)
    for( D_PAD* p = m_board->m_Modules->Pads(); p; p = p->Next() )
        allPads.insert( p );

    DIALOG_ENUM_PADS settingsDlg( m_frame );

    if( settingsDlg.ShowModal() == wxID_CANCEL )
        return 0;

    int padNumber = settingsDlg.GetStartNumber();
    wxString padPrefix = settingsDlg.GetPrefix();

    m_frame->DisplayToolMsg( _( "Hold left mouse button and move cursor over pads to enumerate them" ) );

    Activate();

    m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
    m_controls->ShowCursor( true );
    VECTOR2I oldCursorPos = m_controls->GetCursorPosition();
    std::list<D_PAD*> selectedPads;

    while( OPT_TOOL_EVENT evt = Wait() )
    {
        if( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
        {
            selectedPads.clear();
            VECTOR2I cursorPos = m_controls->GetCursorPosition();

            if( evt->IsClick( BUT_LEFT ) )
            {
                oldCursorPos = m_controls->GetCursorPosition();
                collector.Empty();
                collector.Collect( m_board, types, wxPoint( cursorPos.x, cursorPos.y ), guide );

                for( int i = 0; i < collector.GetCount(); ++i )
                {
                    if( collector[i]->Type() == PCB_PAD_T )
                        selectedPads.push_back( static_cast<D_PAD*>( collector[i] ) );
                }
            }
            else //evt->IsDrag( BUT_LEFT )
            {
                // wxWidgets deliver mouse move events not frequently enough, resulting in skipping
                // pads if the user moves cursor too fast. To solve it, create a line that approximates
                // the mouse move and select items intersecting with the line.
                int distance = ( cursorPos - oldCursorPos ).EuclideanNorm();
                int segments = distance / 100000 + 1;
                const wxPoint LINE_STEP( ( cursorPos - oldCursorPos ).x / segments,
                                         ( cursorPos - oldCursorPos ).y / segments );

                collector.Empty();
                for( int j = 0; j < segments; ++j ) {
                    collector.Collect( m_board, types,
                                       wxPoint( oldCursorPos.x, oldCursorPos.y ) + j * LINE_STEP,
                                       guide );

                    for( int i = 0; i < collector.GetCount(); ++i )
                    {
                        if( collector[i]->Type() == PCB_PAD_T )
                            selectedPads.push_back( static_cast<D_PAD*>( collector[i] ) );
                    }
                }

                selectedPads.unique();
            }

            for( D_PAD* pad : selectedPads )
            {
                std::set<D_PAD*>::iterator it = allPads.find( pad );

                // Add the pad to the list, if it was not selected previously..
                if( it != allPads.end() )
                {
                    allPads.erase( it );
                    pads.push_back( pad );
                    pad->SetSelected();
                }

                // ..or remove it from the list if it was clicked
                else if( evt->IsClick( BUT_LEFT ) )
                {
                    allPads.insert( pad );
                    pads.remove( pad );
                    pad->ClearSelected();
                }
            }

            oldCursorPos = cursorPos;
        }

        else if( ( evt->IsKeyPressed() && evt->KeyCode() == WXK_RETURN ) ||
                   evt->IsDblClick( BUT_LEFT ) )
        {
            // Accept changes
            BOARD_COMMIT commit( m_frame );
            m_frame->OnModify();

            for( D_PAD* pad : pads )
            {
                commit.Modify( pad );
                pad->SetPadName( wxString::Format( wxT( "%s%d" ), padPrefix.c_str(), padNumber++ ) );
            }

            commit.Push( _( "Enumerate pads" ) );

            break;
        }

        else if( evt->IsCancel() || evt->IsActivate() )
        {
            break;
        }
    }

    for( D_PAD* pad : pads )
        pad->ClearSelected();

    m_frame->DisplayToolMsg( wxEmptyString );
    m_controls->ShowCursor( false );

    return 0;
}
bool SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere, bool aAllowDisambiguation )
{
    BOARD_ITEM* item;
    GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide();
    GENERAL_COLLECTOR collector;

    // Preferred types (they have the priority when if they are covered by a bigger item)
    const KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, PCB_LINE_T, PCB_MODULE_TEXT_T, EOT };

    if( m_editModules )
        collector.Collect( getModel<BOARD>(), GENERAL_COLLECTOR::ModuleItems,
                           wxPoint( aWhere.x, aWhere.y ), guide );
    else
        collector.Collect( getModel<BOARD>(), GENERAL_COLLECTOR::AllBoardItems,
                           wxPoint( aWhere.x, aWhere.y ), guide );

    switch( collector.GetCount() )
    {
    case 0:
        if( !m_additive )
            clearSelection();

        return false;

    case 1:
        toggleSelection( collector[0] );

        return true;

    default:
        // Remove unselectable items
        for( int i = collector.GetCount() - 1; i >= 0; --i )
        {
            if( !selectable( collector[i] ) )
                collector.Remove( i );
        }

        // Check if among the selection candidates there is only one instance of preferred type
        item = prefer( collector, types );
        if( item )
        {
            toggleSelection( item );

            return true;
        }

        // Let's see if there is still disambiguation in selection..
        if( collector.GetCount() == 1 )
        {
            toggleSelection( collector[0] );

            return true;
        }

        else if( aAllowDisambiguation && collector.GetCount() > 1 )
        {
            item = disambiguationMenu( &collector );

            if( item )
            {
                toggleSelection( item );

                return true;
            }
        }
        break;
    }

    return false;
}