示例#1
0
SCH_LINE* SCH_SCREEN::GetWireOrBus( const wxPoint& aPosition )
{
    for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
    {
        if( (item->Type() == SCH_LINE_T) && item->HitTest( aPosition )
            && (item->GetLayer() == LAYER_BUS || item->GetLayer() == LAYER_WIRE) )
        {
            return (SCH_LINE*) item;
        }
    }

    return NULL;
}
bool SCH_COLLECTOR::IsNode( bool aIncludePins ) const
{
    for( size_t i = 0;  i < m_List.size();  i++ )
    {
        SCH_ITEM* item = (SCH_ITEM*) m_List[ i ];
        KICAD_T type = item->Type();

        if( type == SCH_JUNCTION_T )
            continue;

        if( type == SCH_LINE_T )
        {
            if( item->GetLayer() != LAYER_WIRE )
                return false;

            continue;
        }

        if( type == LIB_PIN_T )
        {
            if( !aIncludePins )
                return false;

            continue;
        }

        // Any other item types indicate that this collection is not a node.
        return false;
    }

    return true;
}
示例#3
0
bool SCH_SCREEN::BreakSegment( const wxPoint& aPoint )
{
    SCH_LINE* segment;
    SCH_LINE* newSegment;
    bool brokenSegments = false;

    for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
    {
        if( (item->Type() != SCH_LINE_T) || (item->GetLayer() == LAYER_NOTES) )
            continue;

        segment = (SCH_LINE*) item;

        if( !segment->HitTest( aPoint, 0 ) || segment->IsEndPoint( aPoint ) )
            continue;

        // Break the segment at aPoint and create a new segment.
        newSegment = new SCH_LINE( *segment );
        newSegment->SetStartPoint( aPoint );
        segment->SetEndPoint( aPoint );
        m_drawList.Insert( newSegment, segment->Next() );
        item = newSegment;
        brokenSegments = true;
    }

    return brokenSegments;
}
示例#4
0
SCH_LINE* SCH_SCREEN::GetLine( const wxPoint& aPosition, int aAccuracy, int aLayer,
                               SCH_LINE_TEST_T aSearchType )
{
    for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
    {
        if( item->Type() != SCH_LINE_T )
            continue;

        if( item->GetLayer() != aLayer )
            continue;

        if( !item->HitTest( aPosition, aAccuracy ) )
            continue;

        switch( aSearchType )
        {
        case ENTIRE_LENGTH_T:
            return (SCH_LINE*) item;

        case EXCLUDE_END_POINTS_T:
            if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
                return (SCH_LINE*) item;
            break;

        case END_POINTS_ONLY_T:
            if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
                return (SCH_LINE*) item;
        }
    }

    return NULL;
}
示例#5
0
int SCH_SCREEN::GetNode( const wxPoint& aPosition, EDA_ITEMS& aList )
{
    for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
    {
        if( item->Type() == SCH_LINE_T && item->HitTest( aPosition )
            && (item->GetLayer() == LAYER_BUS || item->GetLayer() == LAYER_WIRE) )
        {
            aList.push_back( item );
        }
        else if( item->Type() == SCH_JUNCTION_T && item->HitTest( aPosition ) )
        {
            aList.push_back( item );
        }
    }

    return (int) aList.size();
}
bool SCH_COLLECTOR::IsDraggableJunction() const
{
    int wireEndCount = 0;
    int wireMidPoint = 0;
    int junctionCount = 0;

    for( size_t i = 0;  i < m_List.size();  i++ )
    {
        SCH_ITEM* item = (SCH_ITEM*) m_List[ i ];
        KICAD_T type = item->Type();

        if( type == SCH_JUNCTION_T )
        {
            junctionCount++;
            continue;
        }

        if( type == SCH_LINE_T )
        {
            if( item->GetLayer() != LAYER_WIRE )
                return false;

            SCH_LINE* line = (SCH_LINE*) item;

            if( line->IsEndPoint( m_RefPos ) )
                wireEndCount++;
            else
                wireMidPoint++;

            continue;
        }

        // Any other item types indicate that this collection is not a draggable junction.
        return false;
    }

    return (wireEndCount >= 3) || ((wireEndCount >= 1) && (wireMidPoint == 1))
        || ((wireMidPoint >= 2) && (junctionCount == 1));
}
示例#7
0
void SCH_EDIT_FRAME::OnDragItem( wxCommandEvent& aEvent )
{
    SCH_SCREEN* screen = GetScreen();
    SCH_ITEM* item = screen->GetCurItem();

    INSTALL_UNBUFFERED_DC( dc, m_canvas );

    if( item == NULL )
    {
        // If we didn't get here by a hot key, then something has gone wrong.
        if( aEvent.GetInt() == 0 )
            return;

        EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject();

        wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );

        item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::DraggableItems,
                                  aEvent.GetInt() );

        // Exit if no item found at the current location or the item is already being edited.
        if( (item == NULL) || (item->GetFlags() != 0) )
            return;
    }

    switch( item->Type() )
    {
    case SCH_BUS_BUS_ENTRY_T:
    case SCH_BUS_WIRE_ENTRY_T:
    case SCH_LINE_T:
    case SCH_JUNCTION_T:
        if( item->GetLayer() == LAYER_BUS )
            break;

        // Fall thru if item is not on bus layer.
    case SCH_COMPONENT_T:
    case SCH_LABEL_T:
    case SCH_GLOBAL_LABEL_T:
    case SCH_HIERARCHICAL_LABEL_T:
    case SCH_SHEET_T:
        m_canvas->MoveCursorToCrossHair();

        // The easiest way to handle a drag component or sheet command
        // is to simulate a block drag command
        if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK )
        {
            if( !HandleBlockBegin( &dc, BLOCK_DRAG, GetCrossHairPosition() ) )
                break;

            // Give a non null size to the search block:
            screen->m_BlockLocate.Inflate( 1 );
            HandleBlockEnd( &dc );
        }

        break;

    default:
        wxFAIL_MSG( wxString::Format( wxT( "Cannot drag schematic item type %s." ),
                                      GetChars( item->GetClass() ) ) );
    }
}
示例#8
0
bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu )
{
    SCH_ITEM*   item = GetScreen()->GetCurItem();
    bool        blockActive = GetScreen()->IsBlockActive();
    wxString    msg;

    // Do not start a block command  on context menu.
    m_canvas->SetCanStartBlock( -1 );

    if( blockActive )
    {
        AddMenusForBlock( PopMenu, this );
        PopMenu->AppendSeparator();

        // If we have a block containing only one main element
        // we append its edition submenu
        if( item != NULL )
        {
            switch( item->Type() )
            {
            case SCH_COMPONENT_T:
                AddMenusForEditComponent( PopMenu, (SCH_COMPONENT *) item, Prj().SchLibs() );
                PopMenu->AppendSeparator();
                break;

            case SCH_TEXT_T:
                msg = AddHotkeyName( _( "Edit Text" ), g_Schematic_Hokeys_Descr, HK_EDIT );
                AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_text_xpm ) );
                PopMenu->AppendSeparator();
                break;

            case SCH_LABEL_T:
                msg = AddHotkeyName( _( "Edit Label" ), g_Schematic_Hokeys_Descr, HK_EDIT );
                AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_text_xpm ) );
                PopMenu->AppendSeparator();
                break;

            case SCH_GLOBAL_LABEL_T:
                msg = AddHotkeyName( _( "Edit Global Label" ), g_Schematic_Hokeys_Descr,
                                     HK_EDIT );
                AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_text_xpm ) );
                PopMenu->AppendSeparator();
                break;

            case SCH_HIERARCHICAL_LABEL_T:
                msg = AddHotkeyName( _( "Edit Hierarchical Label" ), g_Schematic_Hokeys_Descr,
                                     HK_EDIT );
                AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_text_xpm ) );
                PopMenu->AppendSeparator();
                break;

            case SCH_BITMAP_T:
                msg = AddHotkeyName( _( "Edit Image" ), g_Schematic_Hokeys_Descr, HK_EDIT );
                AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( image_xpm ) );
                PopMenu->AppendSeparator();
                break;

            default:
                break;
            }
        }
        return true;
    }

    // Try to locate items at cursor position.
    if( (item == NULL) || (item->GetFlags() == 0) )
    {
        item = LocateAndShowItem( aPosition, SCH_COLLECTOR::AllItemsButPins );

        // If the clarify item selection context menu is aborted, don't show the context menu.
        if( item == NULL && m_canvas->GetAbortRequest() )
        {
            m_canvas->SetAbortRequest( false );
            return false;
        }
    }

    // If a command is in progress: add "cancel" and "end tool" menu
    // If
    if( GetToolId() != ID_NO_TOOL_SELECTED )
    {
        if( item && item->GetFlags() )
        {
            AddMenuItem( PopMenu, ID_CANCEL_CURRENT_COMMAND, _( "Cancel" ),
                         KiBitmap( cancel_xpm ) );
        }
        else
        {
            AddMenuItem( PopMenu, ID_CANCEL_CURRENT_COMMAND, _( "End Tool" ),
                         KiBitmap( cursor_xpm ) );
        }

        PopMenu->AppendSeparator();

        switch( GetToolId() )
        {
        case ID_WIRE_BUTT:
            AddMenusForWire( PopMenu, NULL, this );
            if( item == NULL )
                PopMenu->AppendSeparator();
            break;

        case ID_BUS_BUTT:
            AddMenusForBus( PopMenu, NULL, this );
            if( item == NULL )
                PopMenu->AppendSeparator();
            break;

        default:
            break;
        }
    }
    else
    {
        if( item && item->GetFlags() )
        {
            AddMenuItem( PopMenu, ID_CANCEL_CURRENT_COMMAND, _( "Cancel" ),
                         KiBitmap( cancel_xpm ) );
            PopMenu->AppendSeparator();
        }
    }

    if( item == NULL )
    {
        if( m_CurrentSheet->Last() != g_RootSheet )
        {
            msg = AddHotkeyName( _( "Leave Sheet" ), g_Schematic_Hokeys_Descr, HK_LEAVE_SHEET );
            AddMenuItem( PopMenu, ID_POPUP_SCH_LEAVE_SHEET, msg,
                         KiBitmap( leave_sheet_xpm ) );
            PopMenu->AppendSeparator();
        }
        return true;
    }

    bool is_new = item->IsNew();

    switch( item->Type() )
    {
    case SCH_NO_CONNECT_T:
        AddMenuItem( PopMenu, ID_POPUP_SCH_DELETE, _( "Delete No Connect" ),
                     KiBitmap( delete_xpm ) );
        break;

    case SCH_JUNCTION_T:
        addJunctionMenuEntries( PopMenu, (SCH_JUNCTION*) item );
        break;

    case SCH_BUS_BUS_ENTRY_T:
    case SCH_BUS_WIRE_ENTRY_T:
        AddMenusForBusEntry( PopMenu, static_cast<SCH_BUS_ENTRY_BASE*>( item ) );
        break;

    case SCH_MARKER_T:
        AddMenusForMarkers( PopMenu, (SCH_MARKER*) item, this );
        break;

    case SCH_TEXT_T:
        AddMenusForText( PopMenu, (SCH_TEXT*) item );
        break;

    case SCH_LABEL_T:
        AddMenusForLabel( PopMenu, (SCH_LABEL*) item );
        break;

    case SCH_GLOBAL_LABEL_T:
        AddMenusForGLabel( PopMenu, (SCH_GLOBALLABEL*) item );
        break;

    case SCH_HIERARCHICAL_LABEL_T:
        AddMenusForHLabel( PopMenu, (SCH_HIERLABEL*) item );
        break;

    case SCH_FIELD_T:
        AddMenusForComponentField( PopMenu, (SCH_FIELD*) item );
        break;

    case SCH_COMPONENT_T:
        AddMenusForComponent( PopMenu, (SCH_COMPONENT*) item, Prj().SchLibs() );
        break;

    case SCH_BITMAP_T:
        AddMenusForBitmap( PopMenu, (SCH_BITMAP*) item );
        break;

    case SCH_LINE_T:
        switch( item->GetLayer() )
        {
        case LAYER_WIRE:
            AddMenusForWire( PopMenu, (SCH_LINE*) item, this );
            break;

        case LAYER_BUS:
            AddMenusForBus( PopMenu, (SCH_LINE*) item, this );
            break;

        default:
            if( is_new )
                AddMenuItem( PopMenu, ID_POPUP_END_LINE, _( "End Drawing" ),
                             KiBitmap( checked_ok_xpm ) );

            AddMenuItem( PopMenu, ID_POPUP_SCH_DELETE, _( "Delete Drawing" ),
                         KiBitmap( delete_xpm ) );
            break;
        }
        break;

    case SCH_SHEET_T:
        AddMenusForHierchicalSheet( PopMenu, (SCH_SHEET*) item );
        break;

    case SCH_SHEET_PIN_T:
        AddMenusForSheetPin( PopMenu, (SCH_SHEET_PIN*) item );
        break;

    default:
        wxFAIL_MSG( wxString::Format( wxT( "Cannot create context menu for unknown type %d" ),
                                      item->Type() ) );
        break;
    }

    PopMenu->AppendSeparator();
    return true;
}
示例#9
0
bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
{
    bool    has_nonparallel[2] = { false };
    int     end_count[2] = { 0 };
    int     pin_count = 0;

    std::vector<SCH_LINE*> lines[2];

    for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
    {
        if( item->GetFlags() & STRUCT_DELETED )
            continue;

        if( aNew && ( item->Type() == SCH_JUNCTION_T ) && ( item->HitTest( aPosition ) ) )
            return false;

        if( ( item->Type() == SCH_LINE_T )
            && ( item->HitTest( aPosition, 0 ) ) )
        {
            if( item->GetLayer() == LAYER_WIRE )
                lines[0].push_back( (SCH_LINE*) item );
            else if( item->GetLayer() == LAYER_BUS )
                lines[1].push_back( (SCH_LINE*) item );
        }

        if( ( item->Type() == SCH_COMPONENT_T )
                && ( item->IsConnected( aPosition ) ) )
            pin_count++;
    }

    for( int i = 0; i < 2; i++ )
    {
        bool removed_overlapping = false;
        end_count[i] = lines[i].size();

        for( auto line = lines[i].begin(); line < lines[i].end(); line++ )
        {
            // Consider ending on a line to be equivalent to two endpoints because
            // we will want to split the line if anything else connects
            if( !(*line)->IsEndPoint( aPosition ) )
                end_count[i]++;

            for( auto second_line = lines[i].end() - 1; second_line > line; second_line-- )
            {
                if( !(*line)->IsParallel( *second_line ) )
                    has_nonparallel[i] = true;
                else if( !removed_overlapping
                         && (*line)->IsSameQuadrant( *second_line, aPosition ) )
                {
                    /**
                     * Overlapping lines that point in the same direction should not be counted
                     * as extra end_points.  We remove the overlapping lines, being careful to only
                     * remove them once.
                     */
                    removed_overlapping = true;
                    end_count[i]--;
                }
            }
        }
    }

    //

    // If there are three or more endpoints
    if( pin_count + end_count[0] > 2 )
        return true;

    // If there is at least one segment that ends on a non-parallel line or
    // junction of two other lines
    if( has_nonparallel[0] && end_count[0] > 2 )
        return true;

    // Check for bus - bus junction requirements
    if( has_nonparallel[1] && end_count[1] > 2 )
        return true;

    return false;
}