int PCBNEW_CONTROL::ZoneDisplayMode( const TOOL_EVENT& aEvent )
{
    KIGFX::PCB_PAINTER* painter =
            static_cast<KIGFX::PCB_PAINTER*>( m_frame->GetGalCanvas()->GetView()->GetPainter() );
    KIGFX::PCB_RENDER_SETTINGS* settings =
            static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
    DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)m_frame->GetDisplayOptions();

    // Apply new display options to the GAL canvas
    if( aEvent.IsAction( &COMMON_ACTIONS::zoneDisplayEnable ) )
        displ_opts->m_DisplayZonesMode = 0;
    else if( aEvent.IsAction( &COMMON_ACTIONS::zoneDisplayDisable ) )
        displ_opts->m_DisplayZonesMode = 1;
    else if( aEvent.IsAction( &COMMON_ACTIONS::zoneDisplayOutlines ) )
        displ_opts->m_DisplayZonesMode = 2;
    else
        assert( false );

    settings->LoadDisplayOptions( displ_opts );

    BOARD* board = getModel<BOARD>();
    for( int i = 0; i < board->GetAreaCount(); ++i )
        board->GetArea( i )->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );

    m_frame->GetGalCanvas()->Refresh();

    return 0;
}
void LENGTH_TUNER_TOOL::handleCommonEvents( const TOOL_EVENT& aEvent )
{
    if( aEvent.IsAction( &ACT_RouterOptions ) )
    {
        DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );

        if( settingsDlg.ShowModal() )
        {
            // FIXME: do we need an explicit update?
        }
    }

    PNS_MEANDER_PLACER_BASE* placer = static_cast<PNS_MEANDER_PLACER_BASE*>( m_router->Placer() );

    if( !placer )
        return;

    if( aEvent.IsAction( &ACT_Settings ) )
    {
        PNS_MEANDER_SETTINGS settings = placer->MeanderSettings();
        DIALOG_PNS_LENGTH_TUNING_SETTINGS settingsDlg( m_frame, settings, m_router->Mode() );

        if( settingsDlg.ShowModal() )
        {
            placer->UpdateSettings( settings );
        }

        m_savedMeanderSettings = placer->MeanderSettings();
    }
}
Пример #3
0
bool TOOL_MANAGER::dispatchStandardEvents( const TOOL_EVENT& aEvent )
{
    if( aEvent.Action() == TA_KEY_PRESSED )
    {
        // Check if there is a hotkey associated
        if( m_actionMgr->RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ) )
            return false;                 // hotkey event was handled so it does not go any further
    }

    return true;
}
Пример #4
0
void TOOL_BASE::updateEndItem( const TOOL_EVENT& aEvent )
{
    int layer;
    bool snapEnabled = !aEvent.Modifier( MD_SHIFT );
    m_gridHelper->SetUseGrid( !aEvent.Modifier( MD_ALT ) );
    m_gridHelper->SetSnap( snapEnabled );

    controls()->ForceCursorPosition( false );
    VECTOR2I mousePos = controls()->GetMousePosition();

    if( m_router->Settings().Mode() != RM_MarkObstacles &&
        ( m_router->GetCurrentNets().empty() || m_router->GetCurrentNets().front() < 0 ) )
    {
        m_endSnapPoint = snapToItem( snapEnabled, nullptr, mousePos );
        controls()->ForceCursorPosition( true, m_endSnapPoint );
        m_endItem = nullptr;

        return;
    }

    if( m_router->IsPlacingVia() )
        layer = -1;
    else
        layer = m_router->GetCurrentLayer();

    ITEM* endItem = nullptr;

    std::vector<int> nets = m_router->GetCurrentNets();

    for( int net : nets )
    {
        endItem = pickSingleItem( mousePos, net, layer, false, { m_startItem } );

        if( endItem )
            break;
    }

    if( checkSnap( endItem ) )
    {
        m_endItem = endItem;
        m_endSnapPoint = snapToItem( snapEnabled, endItem, mousePos );
    } else {
        m_endItem = nullptr;
        m_endSnapPoint = m_gridHelper->Align( mousePos );
    }

    controls()->ForceCursorPosition( true, m_endSnapPoint );

    if( m_endItem )
    {
        wxLogTrace( "PNS", "%s, layer : %d", m_endItem->KindStr().c_str(), m_endItem->Layers().Start() );
    }
}
Пример #5
0
void TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction, bool aNow, void* aParam )
{
    TOOL_EVENT event = aAction.MakeEvent();

    // Allow to override the action parameter
    if( aParam )
        event.SetParameter( aParam );

    if( aNow )
        ProcessEvent( event );
    else
        PostEvent( event );
}
int PCBNEW_CONTROL::ZoomInOut( const TOOL_EVENT& aEvent )
{
    KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView();
    double zoomScale = 1.0;

    if( aEvent.IsAction( &COMMON_ACTIONS::zoomIn ) )
        zoomScale = 1.3;
    else if( aEvent.IsAction( &COMMON_ACTIONS::zoomOut ) )
        zoomScale = 0.7;

    view->SetScale( view->GetScale() * zoomScale, getViewControls()->GetCursorPosition() );

    return 0;
}
Пример #7
0
void PNS_TOOL_BASE::updateStartItem( TOOL_EVENT& aEvent )
{
    int tl = getView()->GetTopLayer();
    VECTOR2I cp = m_ctls->GetCursorPosition();
    VECTOR2I p;

    PNS_ITEM* startItem = NULL;
    bool snapEnabled = true;

    if( aEvent.IsMotion() || aEvent.IsClick() )
    {
        snapEnabled = !aEvent.Modifier( MD_SHIFT );
        p = aEvent.Position();
    }
    else
    {
        p = cp;
    }

    startItem = pickSingleItem( p );
    m_router->EnableSnapping( snapEnabled );

    if( !snapEnabled && startItem && !startItem->Layers().Overlaps( tl ) )
        startItem = NULL;

    if( startItem && startItem->Net() >= 0 )
    {
        bool dummy;
        VECTOR2I psnap = snapToItem( startItem, p, dummy );

        if( snapEnabled )
        {
            m_startSnapPoint = psnap;
            m_ctls->ForceCursorPosition( true, psnap );
        }
        else
        {
            m_startSnapPoint = cp;
            m_ctls->ForceCursorPosition( false );
        }

        m_startItem = startItem;
    }
    else
    {
        m_startItem = NULL;
        m_startSnapPoint = cp;
        m_ctls->ForceCursorPosition( false );
    }
}
int PCBNEW_CONTROL::ZoomInOutCenter( const TOOL_EVENT& aEvent )
{
    KIGFX::VIEW* view = getView();
    double zoomScale = 1.0;

    if( aEvent.IsAction( &COMMON_ACTIONS::zoomInCenter ) )
        zoomScale = 1.3;
    else if( aEvent.IsAction( &COMMON_ACTIONS::zoomOutCenter ) )
        zoomScale = 0.7;

    view->SetScale( view->GetScale() * zoomScale );

    return 0;
}
Пример #9
0
void ROUTER_TOOL::handleCommonEvents( const TOOL_EVENT& aEvent )
{
#ifdef DEBUG
    if( aEvent.IsKeyPressed() )
    {
        switch( aEvent.KeyCode() )
        {
        case '0':
            wxLogTrace( "PNS", "saving drag/route log...\n" );
            m_router->DumpLog();
            break;
        }
    }
#endif
}
Пример #10
0
bool TOOL_MANAGER::dispatchActivation( const TOOL_EVENT& aEvent )
{
    if( aEvent.IsActivate() )
    {
        std::map<std::string, TOOL_STATE*>::iterator tool = m_toolNameIndex.find( *aEvent.GetCommandStr() );

        if( tool != m_toolNameIndex.end() )
        {
            runTool( tool->second->theTool );
            return true;
        }
    }

    return false;
}
Пример #11
0
void POINT_EDITOR::updateEditedPoint( const TOOL_EVENT& aEvent )
{
    EDIT_POINT* point = m_editedPoint;

    if( aEvent.IsMotion() )
    {
        point = m_editPoints->FindPoint( aEvent.Position() );
    }
    else if( aEvent.IsDrag( BUT_LEFT ) )
    {
        point = m_editPoints->FindPoint( aEvent.DragOrigin() );
    }

    if( m_editedPoint != point )
        setEditedPoint( point );
}
bool PCB_BASE_FRAME::InvokeDialogGrid()
{
    wxPoint grid_origin = GetGridOrigin();

    DIALOG_SET_GRID dlg( this, &m_UserGridUnit, g_UserUnit, &m_UserGridSize,
        &grid_origin, &m_FastGrid1, &m_FastGrid2,
        m_gridSelectBox->GetStrings() );

    int ret = dlg.ShowModal();

    if( ret == wxID_OK )
    {
        if( GetGridOrigin() != grid_origin && IsType( FRAME_PCB ) )
            OnModify();     // because grid origin is saved in board, show as modified

        SetGridOrigin( grid_origin );

        BASE_SCREEN* screen = GetScreen();

        screen->AddGrid( m_UserGridSize, m_UserGridUnit, ID_POPUP_GRID_USER );

        // If the user grid is the current option, recall SetGrid()
        // to force new values put in list as current grid value
        if( screen->GetGridCmdId() == ID_POPUP_GRID_USER )
            screen->SetGrid( ID_POPUP_GRID_USER );

        // Notify GAL
        TOOL_MANAGER* mgr = GetToolManager();

        if( mgr && IsGalCanvasActive() )
        {
            mgr->RunAction( "common.Control.gridPreset", true,
                    screen->GetGridCmdId() - ID_POPUP_GRID_LEVEL_1000 );

            TOOL_EVENT gridOriginUpdate = COMMON_ACTIONS::gridSetOrigin.MakeEvent();
            gridOriginUpdate.SetParameter( new VECTOR2D( grid_origin ) );
            mgr->ProcessEvent( gridOriginUpdate );
        }

        m_canvas->Refresh();

        return true;
    }

    return false;
}
Пример #13
0
void TOOL_BASE::updateStartItem( const TOOL_EVENT& aEvent, bool aIgnorePads )
{
    int tl = getView()->GetTopLayer();
    VECTOR2I cp = controls()->GetCursorPosition( !aEvent.Modifier( MD_SHIFT ) );
    VECTOR2I p;

    controls()->ForceCursorPosition( false );
    m_gridHelper->SetUseGrid( !aEvent.Modifier( MD_ALT ) );
    m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );

    bool snapEnabled = true;

    if( aEvent.IsMotion() || aEvent.IsClick() )
    {
        snapEnabled = !aEvent.Modifier( MD_SHIFT );
        p = aEvent.Position();
    }
    else
    {
        p = cp;
    }

    m_startItem = pickSingleItem( p, -1, -1, aIgnorePads );

    if( !snapEnabled && m_startItem && !m_startItem->Layers().Overlaps( tl ) )
        m_startItem = nullptr;

    m_startSnapPoint = snapToItem( snapEnabled, m_startItem, p );

    if( checkSnap( m_startItem ) )
    {
        controls()->ForceCursorPosition( true, m_startSnapPoint );
    }
}
Пример #14
0
int PCBNEW_CONTROL::ZoomInOutCenter( TOOL_EVENT& aEvent )
{
    KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView();
    KIGFX::GAL* gal = m_frame->GetGalCanvas()->GetGAL();

    if( aEvent.IsAction( &COMMON_ACTIONS::zoomInCenter ) )
        m_frame->SetPrevZoom();
    else if( aEvent.IsAction( &COMMON_ACTIONS::zoomOutCenter ) )
        m_frame->SetNextZoom();

    double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
    double zoom = 1.0 / ( zoomFactor * m_frame->GetZoom() );

    view->SetScale( zoom );
    setTransitions();

    return 0;
}
void TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction, bool aNow, void* aParam )
{
    TOOL_EVENT event = aAction.MakeEvent();

    // Allow to override the action parameter
    if( aParam )
        event.SetParameter( aParam );

    if( aNow )
    {
        TOOL_STATE* current = m_activeState;
        processEvent( event );
        setActiveState( current );
    }
    else
    {
        PostEvent( event );
    }
}
Пример #16
0
void PNS_TOOL_BASE::updateEndItem( TOOL_EVENT& aEvent )
{
    VECTOR2I mp = m_ctls->GetMousePosition();
    VECTOR2I p = getView()->ToWorld( mp );
    VECTOR2I cp = m_ctls->GetCursorPosition();
    int layer;
    bool snapEnabled = !aEvent.Modifier( MD_SHIFT );

    m_router->EnableSnapping( snapEnabled );

    if( m_router->GetCurrentNets().empty() || m_router->GetCurrentNets().front() < 0 )
    {
        m_endItem = NULL;
        m_endSnapPoint = cp;
        return;
    }

    bool dummy;

    if( m_router->IsPlacingVia() )
        layer = -1;
    else
        layer = m_router->GetCurrentLayer();

    PNS_ITEM* endItem = NULL;

    std::vector<int> nets = m_router->GetCurrentNets();

    for( int net : nets )
    {
        endItem = pickSingleItem( p, net, layer );

        if( endItem )
            break;
    }

    if( endItem )
    {
        VECTOR2I cursorPos = snapToItem( endItem, p, dummy );
        m_ctls->ForceCursorPosition( true, cursorPos );
        m_endItem = endItem;
        m_endSnapPoint = cursorPos;
    }
    else
    {
        m_endItem = NULL;
        m_endSnapPoint = cp;
        m_ctls->ForceCursorPosition( false );
    }

    if( m_endItem )
    {
        wxLogTrace( "PNS", "%s, layer : %d", m_endItem->KindStr().c_str(), m_endItem->Layers().Start() );
    }
}
Пример #17
0
void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent )
{
    for( TOOL_ID toolId : m_activeTools )
    {
        TOOL_STATE* st = m_toolIdIndex[toolId];

        // the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode)
        // or immediately (CMENU_NOW) mode. The latter is used for clarification lists.
        if( st->contextMenuTrigger != CMENU_OFF )
        {
            if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( BUT_RIGHT ) )
                break;

            st->pendingWait = true;
            st->waitEvents = TOOL_EVENT( TC_ANY, TA_ANY );

            // Store the menu pointer in case it is changed by the TOOL when handling menu events
            CONTEXT_MENU* m = st->contextMenu;

            if( st->contextMenuTrigger == CMENU_NOW )
                st->contextMenuTrigger = CMENU_OFF;

            // Temporarily store the cursor position, so the tools could execute actions
            // using the point where the user has invoked a context menu
            bool forcedCursor = m_viewControls->IsCursorPositionForced();
            VECTOR2D cursorPos = m_viewControls->GetCursorPosition();
            m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() );

            // Run update handlers
            m->UpdateAll();

            boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *m ) );
            GetEditFrame()->PopupMenu( menu.get() );

            // If nothing was chosen from the context menu, we must notify the tool as well
            if( menu->GetSelected() < 0 )
            {
                TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, -1 );
                evt.SetParameter( m );
                dispatchInternal( evt );
            }

            TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CLOSED );
            evt.SetParameter( m );
            dispatchInternal( evt );

            m_viewControls->ForceCursorPosition( forcedCursor, cursorPos );

            break;
        }
    }
}
Пример #18
0
bool TOOL_MANAGER::RunAction( const std::string& aActionName, bool aNow, void* aParam )
{
    TOOL_ACTION* action = m_actionMgr->FindAction( aActionName );

    if( action )
    {
        TOOL_EVENT event = action->MakeEvent();

        // Allow to override the action parameter
        if( aParam )
            event.SetParameter( aParam );

        if( aNow )
            ProcessEvent( event );
        else
            PostEvent( event );

        return true;
    }

    wxASSERT_MSG( action != NULL, wxString::Format( wxT( "Could not find action %s." ), aActionName ) );

    return false;
}
Пример #19
0
void ROUTER_TOOL::handleCommonEvents( const TOOL_EVENT& aEvent )
{
#ifdef DEBUG
    if( aEvent.IsKeyPressed() )
    {
        switch( aEvent.KeyCode() )
        {
            case '0':
                TRACEn( 2, "saving drag/route log...\n" );
                m_router->DumpLog();
                break;
        }
    }
    else
#endif
    if( aEvent.IsAction( &ACT_RouterOptions ) )
    {
        DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );

        if( settingsDlg.ShowModal() )
        {
            // FIXME: do we need an explicit update?
        }
    }
    else if( aEvent.IsAction( &ACT_SetDpDimensions ) )
    {
        PNS_SIZES_SETTINGS sizes = m_router->Sizes();
        DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( m_frame, sizes );

        if( settingsDlg.ShowModal() )
        {
            m_router->UpdateSizes( sizes );
        }
    }
    else if( aEvent.IsAction( &ACT_CustomTrackWidth ) )
    {
        BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
        DIALOG_TRACK_VIA_SIZE sizeDlg( m_frame, bds );

        if( sizeDlg.ShowModal() )
        {
            bds.UseCustomTrackViaSize( true );
            m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged );
        }
    }

    else if( aEvent.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) )
    {

        PNS_SIZES_SETTINGS sizes( m_router->Sizes() );
        sizes.ImportCurrent( m_board->GetDesignSettings() );
        m_router->UpdateSizes( sizes );
    }
}
Пример #20
0
int PL_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
{
    // We might be running as the same shape in another co-routine.  Make sure that one
    // gets whacked.
    m_toolMgr->DeactivateTool();

    bool isDrawLine;
    bool isImmediate = false;

    if( aEvent.IsAction( &PL_ACTIONS::drawLine ) )
    {
        isDrawLine = true;
        m_frame->SetToolID( ID_PL_LINE_TOOL, wxCURSOR_PENCIL, _( "Draw line" ) );
    }
    else if( aEvent.IsAction( &PL_ACTIONS::drawRectangle ) )
    {
        isDrawLine = false;
        m_frame->SetToolID( ID_PL_RECTANGLE_TOOL, wxCURSOR_PENCIL, _( "Draw rectangle" ) );
    }
    else if( aEvent.IsAction( &PL_ACTIONS::addLine ) )
    {
        isDrawLine = true;
        isImmediate = true;
    }
    else if( aEvent.IsAction( &PL_ACTIONS::addRectangle ) )
    {
        isDrawLine = false;
        isImmediate = true;
    }
    else
        wxCHECK_MSG( false, 0, "Unknown action in PL_DRAWING_TOOLS::DrawShape()" );

    m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );
    getViewControls()->ShowCursor( true );

    Activate();

    WS_DRAW_ITEM_BASE* item = nullptr;

    // Main loop: keep receiving events
    while( auto evt = Wait() )
    {
        VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );

        if( TOOL_EVT_UTILS::IsCancelInteractive( evt.get() ) )
        {
            m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );

            if( item )
            {
                item = nullptr;
                m_frame->RollbackFromUndo();

                if( !evt->IsActivate() && !isImmediate )
                    continue;
            }

            break;
        }

        else if( evt->IsClick( BUT_LEFT ) || ( isImmediate && !item ) )
        {
            if( !item ) // start drawing
            {
                m_frame->SaveCopyInUndoList();
                m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );

                WS_DATA_ITEM::WS_ITEM_TYPE dataType;

                if( isDrawLine )
                    dataType = WS_DATA_ITEM::WS_SEGMENT;
                else
                    dataType = WS_DATA_ITEM::WS_RECT;

                WS_DATA_ITEM* dataItem = m_frame->AddPageLayoutItem( dataType );
                dataItem->MoveToUi( (wxPoint) cursorPos );

                item = dataItem->GetDrawItems()[0];
                item->SetFlags( IS_NEW );
                m_selectionTool->AddItemToSel( item );
            }
            else    // finish drawing
            {
                item->ClearEditFlags();
                item = nullptr;

                m_frame->OnModify();

                if( isImmediate )
                {
                    m_toolMgr->RunAction( ACTIONS::activatePointEditor );
                    break;
                }
            }
        }

        else if( evt->IsAction( &PL_ACTIONS::refreshPreview ) || evt->IsMotion() )
        {
            if( item )
            {
                item->GetPeer()->MoveEndPointToUi( (wxPoint) cursorPos );
                item->SetEnd( item->GetPeer()->GetEndPosUi( 0 ) );
                getView()->Update( item );
            }
        }

        else if( evt->IsClick( BUT_RIGHT ) )
        {
            // Warp after context menu only if dragging...
            if( !item )
                m_toolMgr->VetoContextMenuMouseWarp();

            m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
        }

        // Enable autopanning and cursor capture only when there is a shape being drawn
        getViewControls()->SetAutoPan( !!item );
        getViewControls()->CaptureCursor( !!item );
    }

    m_frame->SetNoToolSelected();

    return 0;
}
Пример #21
0
int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
{
    // Note: original items are no more modified.

    bool increment = aEvent.IsAction( &COMMON_ACTIONS::duplicateIncrement );

    // first, check if we have a selection, or try to get one
    SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
    const SELECTION& selection = selTool->GetSelection();

    // Be sure that there is at least one item that we can modify
    if( !hoverSelection() )
        return 0;

    // we have a selection to work on now, so start the tool process
    PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();

    std::vector<BOARD_ITEM*> old_items;

    for( int i = 0; i < selection.Size(); ++i )
    {
        BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i );

        if( item )
            old_items.push_back( item );
    }

    for( unsigned i = 0; i < old_items.size(); ++i )
    {
        BOARD_ITEM* item = old_items[i];

        // Unselect the item, so we won't pick it up again
        // Do this first, so a single-item duplicate will correctly call
        // SetCurItem and show the item properties
        m_toolMgr->RunAction( COMMON_ACTIONS::unselectItem, true, item );

        BOARD_ITEM* new_item = NULL;

        if( m_editModules )
            new_item = editFrame->GetBoard()->m_Modules->Duplicate( item, increment );
        else
        {
#if 0
            // @TODO: see if we allow zone duplication here
            // Duplicate zones is especially tricky (overlaping zones must be merged)
            // so zones are not duplicated
            if( item->Type() != PCB_ZONE_AREA_T )
#endif
            new_item = editFrame->GetBoard()->Duplicate( item );
        }

        if( new_item )
        {
            m_commit->Add( new_item );

            // Select the new item, so we can pick it up
            m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, new_item );
        }
    }

    // record the new items as added
    if( !selection.Empty() )
    {
        editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ),
                (int) old_items.size() ) );

        // If items were duplicated, pick them up
        // this works well for "dropping" copies around and pushes the commit
        TOOL_EVENT evt = COMMON_ACTIONS::editActivate.MakeEvent();
        Main( evt );
    }

    return 0;
};
void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent )
{
    // iterate over all registered tools
    for( auto it = m_activeTools.begin(); it != m_activeTools.end(); ++it )
    {
        TOOL_STATE* st = m_toolIdIndex[*it];

        // forward context menu events to the tool that created the menu
        if( aEvent.IsMenu() )
        {
            if( *it != m_menuOwner )
                continue;
        }

        // the tool state handler is waiting for events (i.e. called Wait() method)
        if( st->pendingWait )
        {
            if( st->waitEvents.Matches( aEvent ) )
            {
                // By default only messages are passed further
                m_passEvent = ( aEvent.Category() == TC_MESSAGE );

                // got matching event? clear wait list and wake up the coroutine
                st->wakeupEvent = aEvent;
                st->pendingWait = false;
                st->waitEvents.clear();

                if( st->cofunc )
                {
                    setActiveState( st );
                    bool end = !st->cofunc->Resume();

                    if( end )
                        it = finishTool( st );
                }

                // If the tool did not request to propagate
                // the event to other tools, we should stop it now
                if( !m_passEvent )
                    break;
            }
        }
    }

    for( auto& state : m_toolState )
    {
        TOOL_STATE* st = state.second;
        bool finished = false;

        // no state handler in progress - check if there are any transitions (defined by
        // Go() method that match the event.
        if( !st->transitions.empty() )
        {
            for( TRANSITION& tr : st->transitions )
            {
                if( tr.first.Matches( aEvent ) )
                {
                    auto func_copy = tr.second;

                    // if there is already a context, then push it on the stack
                    // and transfer the previous view control settings to the new context
                    if( st->cofunc )
                    {
                        auto vc = st->vcSettings;
                        st->Push();
                        st->vcSettings = vc;
                    }

                    st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( std::move( func_copy ) );

                    // as the state changes, the transition table has to be set up again
                    st->transitions.clear();

                    // got match? Run the handler.
                    setActiveState( st );
                    st->idle = false;
                    st->cofunc->Call( aEvent );

                    if( !st->cofunc->Running() )
                        finishTool( st ); // The couroutine has finished immediately?

                    // if it is a message, continue processing
                    finished = !( aEvent.Category() == TC_MESSAGE );

                    // there is no point in further checking, as transitions got cleared
                    break;
                }
            }
        }

        if( finished )
            break;      // only the first tool gets the event
    }
}
Пример #23
0
void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent )
{
    // iterate over all registered tools
    for( auto it = m_activeTools.begin(); it != m_activeTools.end(); /* iteration is done inside */)
    {
        auto curIt = it;
        TOOL_STATE* st = m_toolIdIndex[*it];
        ++it;       // it might be overwritten, if the tool is removed the m_activeTools deque

        // the tool state handler is waiting for events (i.e. called Wait() method)
        if( st->pendingWait )
        {
            if( st->waitEvents.Matches( aEvent ) )
            {
                // By default, only messages are passed further
                m_passEvent = ( aEvent.Category() == TC_MESSAGE );

                // got matching event? clear wait list and wake up the coroutine
                st->wakeupEvent = aEvent;
                st->pendingWait = false;
                st->waitEvents.clear();

                if( st->cofunc && !st->cofunc->Resume() )
                {
                    if( finishTool( st, false ) ) // The couroutine has finished
                        it = m_activeTools.erase( curIt );
                }

                // If the tool did not request to propagate
                // the event to other tools, we should stop it now
                if( !m_passEvent )
                    break;
            }
        }
    }

    for( TOOL_STATE* st : ( m_toolState | boost::adaptors::map_values ) )
    {
        // no state handler in progress - check if there are any transitions (defined by
        // Go() method that match the event.
        if( !st->pendingWait && !st->transitions.empty() )
        {
            for( TRANSITION& tr : st->transitions )
            {
                if( tr.first.Matches( aEvent ) )
                {
                    auto func_copy = tr.second;

                    // if there is already a context, then store it
                    if( st->cofunc )
                        st->Push();

                    st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( std::move( func_copy ) );

                    // as the state changes, the transition table has to be set up again
                    st->transitions.clear();

                    // got match? Run the handler.
                    st->cofunc->Call( aEvent );

                    if( !st->cofunc->Running() )
                        finishTool( st ); // The couroutine has finished immediately?

                    // there is no point in further checking, as transitions got cleared
                    break;
                }
            }
        }
    }
}
void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent )
{
    for( TOOL_ID toolId : m_activeTools )
    {
        TOOL_STATE* st = m_toolIdIndex[toolId];

        // the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode)
        // or immediately (CMENU_NOW) mode. The latter is used for clarification lists.
        if( st->contextMenuTrigger == CMENU_OFF )
            continue;

        if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( BUT_RIGHT ) )
            break;

        st->pendingWait = true;
        st->waitEvents = TOOL_EVENT( TC_ANY, TA_ANY );

        // Store the menu pointer in case it is changed by the TOOL when handling menu events
        CONTEXT_MENU* m = st->contextMenu;

        if( st->contextMenuTrigger == CMENU_NOW )
            st->contextMenuTrigger = CMENU_OFF;

        // Store the cursor position, so the tools could execute actions
        // using the point where the user has invoked a context menu
        m_menuCursor = m_viewControls->GetCursorPosition();

        // Save all tools cursor settings, as they will be overridden
        for( auto idState : m_toolIdIndex )
        {
            TOOL_STATE* s = idState.second;
            const auto& vc = s->vcSettings;

            if( vc.m_forceCursorPosition )
                m_cursorSettings[idState.first] = vc.m_forcedPosition;
            else
                m_cursorSettings[idState.first] = NULLOPT;
        }

        m_viewControls->ForceCursorPosition( true, m_menuCursor );

        // Display a copy of menu
        std::unique_ptr<CONTEXT_MENU> menu( m->Clone() );

        // Run update handlers on the created copy
        menu->UpdateAll();
        m_menuOwner = toolId;
        m_menuActive = true;

        auto frame = dynamic_cast<wxFrame*>( m_editFrame );

        if( frame )
            frame->PopupMenu( menu.get() );

        // Warp the cursor as long as the menu wasn't clicked out of
        if( menu->GetSelected() >= 0 )
            m_viewControls->WarpCursor( m_menuCursor, true, false );
        // Otherwise notify the tool of a cancelled menu
        else
        {
            TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, -1 );
            evt.SetParameter( m );
            dispatchInternal( evt );
        }

        // Notify the tools that menu has been closed
        TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CLOSED );
        evt.SetParameter( m );
        dispatchInternal( evt );

        m_menuActive = false;
        m_menuOwner = -1;

        // Restore cursor settings
        for( auto cursorSetting : m_cursorSettings )
        {
            auto it = m_toolIdIndex.find( cursorSetting.first );
            wxASSERT( it != m_toolIdIndex.end() );

            if( it == m_toolIdIndex.end() )
                continue;

            KIGFX::VC_SETTINGS& vc = it->second->vcSettings;
            vc.m_forceCursorPosition = (bool) cursorSetting.second;
            vc.m_forcedPosition = cursorSetting.second ? *cursorSetting.second : VECTOR2D( 0, 0 );
        }

        m_cursorSettings.clear();
        break;
    }
}
Пример #25
0
int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
{
    bool increment = aEvent.IsAction( &COMMON_ACTIONS::duplicateIncrement );

    // first, check if we have a selection, or try to get one
    SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
    const SELECTION& selection = selTool->GetSelection();

    // Be sure that there is at least one item that we can modify
    if( !hoverSelection( selection ) )
        return 0;

    // we have a selection to work on now, so start the tool process

    PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
    editFrame->OnModify();

    // prevent other tools making undo points while the duplicate is going on
    // so that if you cancel, you don't get a duplicate object hiding over
    // the original
    incUndoInhibit();

    if( m_editModules )
        editFrame->SaveCopyInUndoList( editFrame->GetBoard()->m_Modules, UR_MODEDIT );

    std::vector<BOARD_ITEM*> old_items;

    for( int i = 0; i < selection.Size(); ++i )
    {
        BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i );

        if( item )
            old_items.push_back( item );
    }

    for( unsigned i = 0; i < old_items.size(); ++i )
    {
        BOARD_ITEM* item = old_items[i];

        // Unselect the item, so we won't pick it up again
        // Do this first, so a single-item duplicate will correctly call
        // SetCurItem and show the item properties
        m_toolMgr->RunAction( COMMON_ACTIONS::unselectItem, true, item );

        BOARD_ITEM* new_item = NULL;

        if( m_editModules )
            new_item = editFrame->GetBoard()->m_Modules->DuplicateAndAddItem( item, increment );
        else
        {
#if 0
            // @TODO: see if we allow zone duplication here
            // Duplicate zones is especially tricky (overlaping zones must be merged)
            // so zones are not duplicated
            if( item->Type() != PCB_ZONE_AREA_T )
#endif
                new_item = editFrame->GetBoard()->DuplicateAndAddItem( item, increment );
        }

        if( new_item )
        {
            if( new_item->Type() == PCB_MODULE_T )
            {
                static_cast<MODULE*>( new_item )->RunOnChildren( boost::bind( &KIGFX::VIEW::Add,
                        getView(), _1 ) );
            }

            editFrame->GetGalCanvas()->GetView()->Add( new_item );

            // Select the new item, so we can pick it up
            m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, new_item );
        }
    }

    // record the new items as added
    if( !m_editModules )
        editFrame->SaveCopyInUndoList( selection.items, UR_NEW );

    editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ),
                               (int) old_items.size() ) );

    // pick up the selected item(s) and start moving
    // this works well for "dropping" copies around
    TOOL_EVENT evt = COMMON_ACTIONS::editActivate.MakeEvent();
    Main( evt );

    // and re-enable undos
    decUndoInhibit();

    return 0;
}
Пример #26
0
int PL_DRAWING_TOOLS::PlaceItem( const TOOL_EVENT& aEvent )
{
    bool isText;
    bool isImmediate = false;

    if( aEvent.IsAction( &PL_ACTIONS::placeText ) )
    {
        isText = true;
        m_frame->SetToolID( ID_PL_TEXT_TOOL, wxCURSOR_PENCIL, _( "Add text" ) );
    }
    else if( aEvent.IsAction( &PL_ACTIONS::placeImage ) )
    {
        isText = false;
        m_frame->SetToolID( ID_PL_IMAGE_TOOL, wxCURSOR_PENCIL, _( "Add image" ) );
    }
    else if( aEvent.IsAction( & PL_ACTIONS::addText ) )
    {
        isText = true;
        isImmediate = true;
    }
    else if( aEvent.IsAction( & PL_ACTIONS::addImage ) )
    {
        isText = false;
        isImmediate = true;
    }
    else
        wxCHECK_MSG( false, 0, "Unknown action in PL_DRAWING_TOOLS::PlaceItem()" );

    VECTOR2I           cursorPos;
    WS_DRAW_ITEM_BASE* item = nullptr;

    m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );
    getViewControls()->ShowCursor( true );

    Activate();

    // Main loop: keep receiving events
    while( OPT_TOOL_EVENT evt = Wait() )
    {
        cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );

        if( TOOL_EVT_UTILS::IsCancelInteractive( evt.get() ) )
        {
            if( item )
            {
                m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );
                delete item;
                item = nullptr;

                // There's nothing to roll-back, but we still need to pop the undo stack
                m_frame->RollbackFromUndo();

                if( !evt->IsActivate() && !isImmediate )
                    continue;
            }

            break;
        }

        else if( evt->IsClick( BUT_LEFT ) || ( isImmediate && !item ) )
        {
            // First click creates...
            if( !item )
            {
                m_frame->SaveCopyInUndoList();

                m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );

                WS_DATA_ITEM* dataItem;
                dataItem = m_frame->AddPageLayoutItem( isText ? WS_DATA_ITEM::WS_TEXT
                                                              : WS_DATA_ITEM::WS_BITMAP );
                item = dataItem->GetDrawItems()[0];
                item->SetFlags( IS_NEW | IS_MOVED );
                m_selectionTool->AddItemToSel( item );
            }

            // ... and second click places:
            else
            {
                item->GetPeer()->MoveStartPointToUi( (wxPoint) cursorPos );
                item->SetPosition( item->GetPeer()->GetStartPosUi( 0 ) );
                item->ClearEditFlags();
                getView()->Update( item );

                item = nullptr;

                m_frame->OnModify();

                if( isImmediate )
                    break;
            }
        }
        else if( evt->IsClick( BUT_RIGHT ) )
        {
            // Warp after context menu only if dragging...
            if( !item )
                m_toolMgr->VetoContextMenuMouseWarp();

            m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
        }

        else if( item && ( evt->IsAction( &PL_ACTIONS::refreshPreview ) || evt->IsMotion() ) )
        {
            item->GetPeer()->MoveStartPointToUi( (wxPoint) cursorPos );
            item->SetPosition( item->GetPeer()->GetStartPosUi( 0 ) );
            getView()->Update( item );
        }

        // Enable autopanning and cursor capture only when there is an item to be placed
        getViewControls()->SetAutoPan( !!item );
        getViewControls()->CaptureCursor( !!item );
    }

    m_frame->SetNoToolSelected();

    return 0;
}
bool TOOL_EVT_UTILS::IsRotateToolEvt( const TOOL_EVENT& aEvt )
{
    return aEvt.IsAction( &PCB_ACTIONS::rotateCw )
            || aEvt.IsAction( &PCB_ACTIONS::rotateCcw );
}
bool TOOL_EVT_UTILS::IsCancelInteractive( const TOOL_EVENT& aEvt )
{
    return aEvt.IsAction( &ACTIONS::cancelInteractive )
            || aEvt.IsActivate()
            || aEvt.IsCancel();
}