Commit 8df0f769 authored by Maciej Suminski's avatar Maciej Suminski
Browse files

Added KiCad-style modification methods (hover over an item and press a hot...

Added KiCad-style modification methods (hover over an item and press a hot key, without selecting first).
Modification point is selected basing on the number of selected items.
Rotation angle setting (Preferences->General) is taken into account while rotating.
parent 625dcddb
Loading
Loading
Loading
Loading
+96 −26
Original line number Original line Diff line number Diff line
@@ -49,10 +49,9 @@ EDIT_TOOL::EDIT_TOOL() :
bool EDIT_TOOL::Init()
bool EDIT_TOOL::Init()
{
{
    // Find the selection tool, so they can cooperate
    // Find the selection tool, so they can cooperate
    TOOL_BASE* selectionTool = m_toolMgr->FindTool( "pcbnew.InteractiveSelection" );
    m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) );


    m_selectionTool = static_cast<SELECTION_TOOL*>( selectionTool );
    if( !m_selectionTool )
    if( !selectionTool )
    {
    {
        DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) );
        DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) );
        return false;
        return false;
@@ -75,15 +74,15 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent )
{
{
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();


    if( selection.Empty() )
    // Shall the selection be cleared at the end?
    {
    bool unselect = selection.Empty();
        setTransitions();   // this is necessary, so later the tool may

                            // be activated upon reception of the activation event
    // Be sure that there is at least one item that we can modify
        return 0;           // there are no items to operate on, so we can end now
    if( !makeSelection( selection ) )
    }
        return 0;


    VECTOR2D dragPosition;      // The last position of the cursor while dragging
    VECTOR2D dragPosition;      // The last position of the cursor while dragging
    m_dragging = false;
    m_dragging = false;         // Are selected items being dragged?
    bool restore = false;       // Should items' state be restored when finishing the tool?
    bool restore = false;       // Should items' state be restored when finishing the tool?


    // By default, modified items need to update their geometry
    // By default, modified items need to update their geometry
@@ -173,6 +172,9 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent )
        selection.group->ItemsViewUpdate( m_updateFlag );
        selection.group->ItemsViewUpdate( m_updateFlag );
    }
    }


    if( unselect )
        m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" );

    RN_DATA* ratsnest = getModel<BOARD>( PCB_T )->GetRatsnest();
    RN_DATA* ratsnest = getModel<BOARD>( PCB_T )->GetRatsnest();
    ratsnest->ClearSimple();
    ratsnest->ClearSimple();
    ratsnest->Recalculate();
    ratsnest->Recalculate();
@@ -192,27 +194,33 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent )
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );


    // Shall the selection be cleared at the end?
    bool unselect = selection.Empty();

    if( !makeSelection( selection ) )
        return 0;

    // Properties are displayed when there is only one item selected
    // Properties are displayed when there is only one item selected
    if( selection.Size() == 1 )
    if( selection.Size() == 1 )
    {
    {
        // Display properties dialog
        // Display properties dialog
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( 0 ) );
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( 0 ) );


        if( !m_dragging )   // If it is being dragged, then it is already saved with UR_CHANGED flag
        {
        editFrame->SaveCopyInUndoList( item, UR_CHANGED );
        editFrame->SaveCopyInUndoList( item, UR_CHANGED );
        editFrame->OnModify();
        editFrame->OnModify();
        }

        editFrame->OnEditItemRequest( NULL, item );
        editFrame->OnEditItemRequest( NULL, item );


        item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
        item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
    }


    setTransitions();
        updateRatsnest( true );
        updateRatsnest( true );
        getModel<BOARD>( PCB_T )->GetRatsnest()->Recalculate();
        getModel<BOARD>( PCB_T )->GetRatsnest()->Recalculate();


        if( unselect )
            m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" );
    }

    setTransitions();

    return 0;
    return 0;
}
}


@@ -220,20 +228,28 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent )
int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent )
int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent )
{
{
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    VECTOR2D cursor = getView()->ToWorld( getViewControls()->GetCursorPosition() );
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );


    // Shall the selection be cleared at the end?
    bool unselect = selection.Empty();

    if( !makeSelection( selection ) )
        return 0;

    wxPoint rotatePoint = getModificationPoint( selection );

    if( !m_dragging )   // If it is being dragged, then it is already saved with UR_CHANGED flag
    if( !m_dragging )   // If it is being dragged, then it is already saved with UR_CHANGED flag
    {
    {
        editFrame->OnModify();
        editFrame->OnModify();
        editFrame->SaveCopyInUndoList( selection.items, UR_ROTATED, wxPoint( cursor.x, cursor.y ) );
        editFrame->SaveCopyInUndoList( selection.items, UR_ROTATED, rotatePoint );
    }
    }


    for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
    for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
    {
    {
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );


        item->Rotate( wxPoint( cursor.x, cursor.y ), 900.0 );
        item->Rotate( rotatePoint, editFrame->GetRotationAngle() );

        if( !m_dragging )
        if( !m_dragging )
            item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
            item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
    }
    }
@@ -246,6 +262,9 @@ int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent )
    else
    else
        getModel<BOARD>( PCB_T )->GetRatsnest()->Recalculate();
        getModel<BOARD>( PCB_T )->GetRatsnest()->Recalculate();


    if( unselect )
        m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" );

    return 0;
    return 0;
}
}


@@ -253,20 +272,28 @@ int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent )
int EDIT_TOOL::Flip( TOOL_EVENT& aEvent )
int EDIT_TOOL::Flip( TOOL_EVENT& aEvent )
{
{
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection();
    VECTOR2D cursor = getView()->ToWorld( getViewControls()->GetCursorPosition() );
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );


    // Shall the selection be cleared at the end?
    bool unselect = selection.Empty();

    if( !makeSelection( selection ) )
        return 0;

    wxPoint flipPoint = getModificationPoint( selection );

    if( !m_dragging )   // If it is being dragged, then it is already saved with UR_CHANGED flag
    if( !m_dragging )   // If it is being dragged, then it is already saved with UR_CHANGED flag
    {
    {
        editFrame->OnModify();
        editFrame->OnModify();
        editFrame->SaveCopyInUndoList( selection.items, UR_FLIPPED, wxPoint( cursor.x, cursor.y ) );
        editFrame->SaveCopyInUndoList( selection.items, UR_FLIPPED, flipPoint );
    }
    }


    for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
    for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
    {
    {
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );


        item->Flip( wxPoint( cursor.x, cursor.y ) );
        item->Flip( flipPoint );

        if( !m_dragging )
        if( !m_dragging )
            item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS );
            item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS );
    }
    }
@@ -279,14 +306,22 @@ int EDIT_TOOL::Flip( TOOL_EVENT& aEvent )
    else
    else
        getModel<BOARD>( PCB_T )->GetRatsnest()->Recalculate();
        getModel<BOARD>( PCB_T )->GetRatsnest()->Recalculate();


    if( unselect )
        m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" );

    return 0;
    return 0;
}
}




int EDIT_TOOL::Remove( TOOL_EVENT& aEvent )
int EDIT_TOOL::Remove( TOOL_EVENT& aEvent )
{
{
    const SELECTION_TOOL::SELECTION selection = m_selectionTool->GetSelection();

    if( !makeSelection( selection ) )
        return 0;

    // Get a copy of the selected items set
    // Get a copy of the selected items set
    PICKED_ITEMS_LIST selectedItems = m_selectionTool->GetSelection().items;
    PICKED_ITEMS_LIST selectedItems = selection.items;
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );
    PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( m_toolMgr->GetEditFrame() );


    // As we are about to remove items, they have to be removed from the selection first
    // As we are about to remove items, they have to be removed from the selection first
@@ -385,9 +420,44 @@ void EDIT_TOOL::updateRatsnest( bool aRedraw )
    {
    {
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );
        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( i ) );


        ratsnest->Update( static_cast<BOARD_CONNECTED_ITEM*>( item ) );
        ratsnest->Update( item );


        if( aRedraw )
        if( aRedraw )
            ratsnest->AddSimple( item );
            ratsnest->AddSimple( item );
    }
    }
}
}


wxPoint EDIT_TOOL::getModificationPoint( const SELECTION_TOOL::SELECTION& aSelection )
{
    if( aSelection.Size() == 1 )
    {
        return static_cast<BOARD_ITEM*>( aSelection.items.GetPickedItem( 0 ) )->GetPosition();
    }
    else
    {
        VECTOR2I cursor = getView()->ToWorld( getViewControls()->GetCursorPosition() );
        return wxPoint( cursor.x, cursor.y );
    }
}


bool EDIT_TOOL::makeSelection( const SELECTION_TOOL::SELECTION& aSelection )
{
    if( aSelection.Empty() )
    {
        // Try to find an item that could be modified
        m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Single" );

        if( aSelection.Empty() )
        {
            // This is necessary, so later the tool may be activated upon
            // reception of the activation event
            setTransitions();

            return false;   // Still no items to work with
        }
    }

    return true;
}
+8 −0
Original line number Original line Diff line number Diff line
@@ -115,6 +115,14 @@ private:
    }
    }


    void updateRatsnest( bool aRedraw );
    void updateRatsnest( bool aRedraw );

    ///> Returns the right modification point (e.g. for rotation), depending on the number of
    ///> selected items.
    wxPoint getModificationPoint( const SELECTION_TOOL::SELECTION& aSelection );

    ///> If there are no items currently selected, it tries to choose the item that is under
    ///> the cursor or displays a disambiguation menu if there are multpile items.
    bool makeSelection( const SELECTION_TOOL::SELECTION& aSelection );
};
};


#endif
#endif
+1 −1
Original line number Original line Diff line number Diff line
@@ -112,12 +112,12 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
            selectSingle( evt->Position() );
            selectSingle( evt->Position() );
        }
        }


        // double click? Display the properties window
        else if( evt->IsDblClick( BUT_LEFT ) )
        else if( evt->IsDblClick( BUT_LEFT ) )
        {
        {
            if( m_selection.Empty() )
            if( m_selection.Empty() )
                selectSingle( evt->Position() );
                selectSingle( evt->Position() );


            // Display properties window
            m_toolMgr->RunAction( "pcbnew.InteractiveEdit.properties" );
            m_toolMgr->RunAction( "pcbnew.InteractiveEdit.properties" );
        }
        }