コード例 #1
0
int PCBNEW_CONTROL::PanControl( const TOOL_EVENT& aEvent )
{
    long type = aEvent.Parameter<long>();
    KIGFX::VIEW* view = getView();
    GRID_HELPER gridHelper( m_frame );
    VECTOR2D center = view->GetCenter();
    VECTOR2I gridSize = gridHelper.GetGrid() * 10;

    switch( type )
    {
        case COMMON_ACTIONS::CURSOR_UP:
            center -= VECTOR2D( 0, gridSize.y );
            break;

        case COMMON_ACTIONS::CURSOR_DOWN:
            center += VECTOR2D( 0, gridSize.y );
            break;

        case COMMON_ACTIONS::CURSOR_LEFT:
            center -= VECTOR2D( gridSize.x, 0 );
            break;

        case COMMON_ACTIONS::CURSOR_RIGHT:
            center += VECTOR2D( gridSize.x, 0 );
            break;

        default:
            assert( false );
            break;
    }

    view->SetCenter( center );

    return 0;
}
コード例 #2
0
void EDA_DRAW_FRAME::UseGalCanvas()
{
    KIGFX::GAL* gal = GetGalCanvas()->GetGAL();

    // Set up grid settings
    gal->SetGridVisibility( IsGridVisible() );
    gal->SetGridSize( VECTOR2D( GetScreen()->GetGridSize() ) );
    gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) );

    // Transfer EDA_DRAW_PANEL settings
    KIGFX::VIEW_CONTROLS* viewControls = GetGalCanvas()->GetViewControls();
    viewControls->EnableCursorWarping( !m_canvas->GetEnableZoomNoCenter() );
    viewControls->EnableMousewheelPan( m_canvas->GetEnableMousewheelPan() );
    viewControls->EnableAutoPan( m_canvas->GetEnableAutoPan() );

    m_canvas->SetEvtHandlerEnabled( false );
    GetGalCanvas()->SetEvtHandlerEnabled( true );

    GetGalCanvas()->StartDrawing();

    // Switch panes
    // JEY TODO: drop down to a single pane....
    m_auimgr.GetPane( "DrawFrame" ).Show( false );
    m_auimgr.GetPane( "DrawFrameGal" ).Show( true );
    m_auimgr.Update();

    // Reset current tool on switch();
    SetNoToolSelected();
}
コード例 #3
0
void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable )
{
    KIGFX::VIEW* view = GetGalCanvas()->GetView();
    KIGFX::GAL* gal = GetGalCanvas()->GetGAL();

    double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();

    // Display the same view after canvas switching
    if( aEnable )
    {
        BASE_SCREEN* screen = GetScreen();

        // Switch to GAL rendering
        if( !IsGalCanvasActive() )
        {
            // Set up viewport
            double zoom = 1.0 / ( zoomFactor * m_canvas->GetZoom() );
            view->SetScale( zoom );
            view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) );
        }

        // Set up grid settings
        gal->SetGridVisibility( IsGridVisible() );
        gal->SetGridSize( VECTOR2D( screen->GetGridSize().x, screen->GetGridSize().y ) );
        gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) );
    }
    else
    {
        // Switch to standard rendering
        if( IsGalCanvasActive() )
        {
            // Change view settings only if GAL was active previously
            double zoom = 1.0 / ( zoomFactor * view->GetScale() );
            m_canvas->SetZoom( zoom );

            VECTOR2D center = view->GetCenter();
            RedrawScreen( wxPoint( center.x, center.y ), false );
        }
    }

    m_canvas->SetEvtHandlerEnabled( !aEnable );
    GetGalCanvas()->SetEvtHandlerEnabled( aEnable );

    // Switch panes
    m_auimgr.GetPane( wxT( "DrawFrame" ) ).Show( !aEnable );
    m_auimgr.GetPane( wxT( "DrawFrameGal" ) ).Show( aEnable );
    m_auimgr.Update();

    // Reset current tool on switch();
    SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );

    m_galCanvasActive = aEnable;
}
コード例 #4
0
bool SHAPE_ARC::ConstructFromCorners( VECTOR2I aP0, VECTOR2I aP1, double aCenterAngle )
{
    VECTOR2D mid = ( VECTOR2D( aP0 ) + VECTOR2D( aP1 ) ) * 0.5;
    VECTOR2D chord = VECTOR2D( aP1 ) - VECTOR2D( aP0 );
    double c = (aP1 - aP0).EuclideanNorm() / 2;
    VECTOR2D d = chord.Rotate( M_PI / 2.0 ).Resize( c );

    m_pc = mid + d * ( 1.0 / tan( aCenterAngle / 2.0 * M_PI / 180.0 ) );
    m_p0 = aP0;
    m_p1 = aP1;

    return true;
}
コード例 #5
0
ファイル: draw_frame.cpp プロジェクト: cpavlina/kicad
void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable )
{
    KIGFX::VIEW* view = GetGalCanvas()->GetView();
    KIGFX::GAL* gal = GetGalCanvas()->GetGAL();

    // Display the same view after canvas switching
    if( aEnable )
    {
        // Switch to GAL renderer from legacy
        if( !m_galCanvasActive )
        {
            // Set up viewport
            double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
            double zoom = 1.0 / ( zoomFactor * m_canvas->GetZoom() );
            view->SetScale( zoom );
            view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) );
        }

        // Set up grid settings
        gal->SetGridVisibility( IsGridVisible() );
        gal->SetGridSize( VECTOR2D( GetScreen()->GetGridSize() ) );
        gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) );

        // Transfer EDA_DRAW_PANEL settings
        GetGalCanvas()->GetViewControls()->EnableCursorWarping( !m_canvas->GetEnableZoomNoCenter() );
        GetGalCanvas()->GetViewControls()->EnableMousewheelPan( m_canvas->GetEnableMousewheelPan() );
        GetGalCanvas()->GetViewControls()->EnableAutoPan( m_canvas->GetEnableAutoPan() );
    }
    else if( m_galCanvasActive )
    {
        // Switch to legacy renderer from GAL
        double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
        // TODO replace it with EDA_DRAW_PANEL_GAL::GetLegacyZoom
        m_canvas->SetZoom( 1.0 / ( zoomFactor * view->GetScale() ) );
        VECTOR2D center = view->GetCenter();
        AdjustScrollBars( wxPoint( center.x, center.y ) );
    }

    m_canvas->SetEvtHandlerEnabled( !aEnable );
    GetGalCanvas()->SetEvtHandlerEnabled( aEnable );

    // Switch panes
    m_auimgr.GetPane( wxT( "DrawFrame" ) ).Show( !aEnable );
    m_auimgr.GetPane( wxT( "DrawFrameGal" ) ).Show( aEnable );
    m_auimgr.Update();

    // Reset current tool on switch();
    SetNoToolSelected();

    m_galCanvasActive = aEnable;
}
コード例 #6
0
ファイル: dialog_drc.cpp プロジェクト: chgans/kicad
void DIALOG_DRC_CONTROL::OnLeftDClickClearance( wxMouseEvent& event )
{
    event.Skip();

    // I am assuming that the double click actually changed the selected item.
    // please verify this.
    int selection = m_ClearanceListBox->GetSelection();

    if( selection != wxNOT_FOUND )
    {
        // Find the selected MARKER in the PCB, position cursor there.
        // Then close the dialog.
        const DRC_ITEM* item = m_ClearanceListBox->GetItem( selection );
        if( item )
        {
            /*
             *  // after the goto, process a button OK command later.
             *  wxCommandEvent  cmd( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK );
             *  ::wxPostEvent( GetEventHandler(), cmd );
             */

            m_Parent->CursorGoto( item->GetPointA() );
            m_Parent->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) );

            // turn control over to m_Parent, hide this DIALOG_DRC_CONTROL window,
            // no destruction so we can preserve listbox cursor
            Show( false );

            // We do not want the clarification popup window.
            // when releasing the left button in the main window
            m_Parent->SkipNextLeftButtonReleaseEvent();
        }
    }
}
コード例 #7
0
int PCBNEW_CONTROL::ZoomFitScreen( const TOOL_EVENT& aEvent )
{
    KIGFX::VIEW* view = getView();
    EDA_DRAW_PANEL_GAL* galCanvas = m_frame->GetGalCanvas();
    BOARD* board = getModel<BOARD>();
    board->ComputeBoundingBox();

    BOX2I boardBBox = board->ViewBBox();
    VECTOR2D scrollbarSize = VECTOR2D( galCanvas->GetSize() - galCanvas->GetClientSize() );
    VECTOR2D screenSize = view->ToWorld( galCanvas->GetClientSize(), false );

    if( boardBBox.GetWidth() == 0 || boardBBox.GetHeight() == 0 )
    {
        // Empty view
        view->SetScale( 17.0 );     // works fine for the standard worksheet frame

        view->SetCenter( screenSize / 2.0 );
    }
    else
    {
        VECTOR2D vsize = boardBBox.GetSize();
        double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
                                                    fabs( vsize.y / screenSize.y ) );

        view->SetScale( scale );
        view->SetCenter( boardBBox.Centre() );
    }


    // Take scrollbars into account
    VECTOR2D worldScrollbarSize = view->ToWorld( scrollbarSize, false );
    view->SetCenter( view->GetCenter() + worldScrollbarSize / 2.0 );

    return 0;
}
コード例 #8
0
void DIALOG_DRC_CONTROL::OnLeftDClickClearance( wxMouseEvent& event )
{
    event.Skip();

    // I am assuming that the double click actually changed the selected item.
    // please verify this.
    int selection = m_ClearanceListBox->GetSelection();

    if( selection != wxNOT_FOUND )
    {
        // Find the selected MARKER in the PCB, position cursor there.
        // Then close the dialog.
        const DRC_ITEM* item = m_ClearanceListBox->GetItem( selection );

        if( item )
        {
            m_brdEditor->CursorGoto( item->GetPointA() );
            m_brdEditor->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) );

            if( !IsModal() )
            {
                // turn control over to m_brdEditor, hide this DIALOG_DRC_CONTROL window,
                // no destruction so we can preserve listbox cursor
                Show( false );

                // We do not want the clarification popup window.
                // when releasing the left button in the main window
                m_brdEditor->SkipNextLeftButtonReleaseEvent();
            }
        }
    }
}
コード例 #9
0
void DIALOG_DRC_CONTROL::OnLeftDClickUnconnected( wxMouseEvent& event )
{
    event.Skip();

    // I am assuming that the double click actually changed the selected item.
    // please verify this.
    int selection = m_UnconnectedListBox->GetSelection();

    if( selection != wxNOT_FOUND )
    {
        // Find the selected DRC_ITEM in the listbox, position cursor there,
        // at the first of the two pads.
        // Then hide the dialog.
        const DRC_ITEM* item = m_UnconnectedListBox->GetItem( selection );
        if( item )
        {
            m_brdEditor->CursorGoto( item->GetPointA() );
            m_brdEditor->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) );

            if( !IsModal() )
            {
                Show( false );

                // We do not want the clarification popup window.
                // when releasing the left button in the main window
                m_brdEditor->SkipNextLeftButtonReleaseEvent();
            }
        }
    }
}
コード例 #10
0
int PCBNEW_CONTROL::ZoomFitScreen( const TOOL_EVENT& aEvent )
{
    KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView();
    KIGFX::GAL* gal = m_frame->GetGalCanvas()->GetGAL();
    BOARD* board = getModel<BOARD>();
    board->ComputeBoundingBox();
    BOX2I boardBBox = board->ViewBBox();
    VECTOR2I screenSize = gal->GetScreenPixelSize();

    if( boardBBox.GetSize().x == 0 || boardBBox.GetSize().y == 0 )
    {
        // Empty view
        view->SetCenter( view->ToWorld( VECTOR2D( screenSize.x / 2, screenSize.y / 2 ) ) );
        view->SetScale( 17.0 );
    }
    else
    {
        // Autozoom to board
        double iuPerX = screenSize.x ? boardBBox.GetWidth() / screenSize.x : 1.0;
        double iuPerY = screenSize.y ? boardBBox.GetHeight() / screenSize.y : 1.0;

        double bestZoom = std::max( iuPerX, iuPerY );
        double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
        double zoom = 1.0 / ( zoomFactor * bestZoom );

        view->SetCenter( boardBBox.Centre() );
        view->SetScale( zoom );
    }

    return 0;
}
コード例 #11
0
DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, D_PAD* aPad ) :
    DIALOG_PAD_PROPERTIES_BASE( aParent ),
    m_OrientValidator( 1, &m_OrientValue )
{
    m_canUpdate  = false;
    m_parent     = aParent;
    m_currentPad = aPad;        // aPad can be NULL, if the dialog is called
                                // from the footprint editor to set default pad setup

    m_board      = m_parent->GetBoard();

    m_OrientValidator.SetRange( -360.0, 360.0 );
    m_PadOrientCtrl->SetValidator( m_OrientValidator );
    m_OrientValidator.SetWindow( m_PadOrientCtrl );

    m_padMaster  = &m_parent->GetDesignSettings().m_Pad_Master;
    m_dummyPad   = new D_PAD( (MODULE*) NULL );

    if( aPad )
        *m_dummyPad = *aPad;
    else    // We are editing a "master" pad, i.e. a template to create new pads
        *m_dummyPad = *m_padMaster;

    // Show the X and Y axis. It is usefull because pad shape can have an offset
    // or be a complex shape.
    m_axisOrigin = new KIGFX::ORIGIN_VIEWITEM( KIGFX::COLOR4D(0.0, 0.0, 0.8, 1.0),
                                               KIGFX::ORIGIN_VIEWITEM::CROSS,
                                               Millimeter2iu( 0.2 ),
                                               VECTOR2D( m_dummyPad->GetPosition() ) );
    m_axisOrigin->SetDrawAtZero( true );

    if( m_parent->IsGalCanvasActive() )
    {
        m_panelShowPadGal->UseColorScheme( m_board->GetColorsSettings() );
        m_panelShowPadGal->SwitchBackend( m_parent->GetGalCanvas()->GetBackend() );
        m_panelShowPadGal->Show();
        m_panelShowPad->Hide();
        m_panelShowPadGal->GetView()->Add( m_dummyPad );
        m_panelShowPadGal->GetView()->Add( m_axisOrigin );
        m_panelShowPadGal->StartDrawing();
        Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
    }
    else
    {
        m_panelShowPad->Show();
        m_panelShowPadGal->Hide();
    }

    initValues();
    TransferDataToWindow();

    m_sdbSizerOK->SetDefault();
    m_PadNumCtrl->SetFocus();
    m_canUpdate = true;

    FixOSXCancelButtonIssue();

    // Now all widgets have the size fixed, call FinishDialogSettings
    FinishDialogSettings();
}
コード例 #12
0
void PCB_BASE_EDIT_FRAME::SetBoard( BOARD* aBoard )
{
    bool new_board = ( aBoard != m_Pcb );

    // The active tool might store a reference to the BOARD that is about to be deleted.
    if( m_toolManager )
        m_toolManager->DeactivateTool();

    // It has to be done before the previous board is destroyed by SetBoard()
    if( new_board )
        GetGalCanvas()->GetView()->Clear();

    PCB_BASE_FRAME::SetBoard( aBoard );

    GetGalCanvas()->GetGAL()->SetGridOrigin( VECTOR2D( aBoard->GetGridOrigin() ) );

    // update the tool manager with the new board and its view.
    if( m_toolManager )
    {
        PCB_DRAW_PANEL_GAL* drawPanel = static_cast<PCB_DRAW_PANEL_GAL*>( GetGalCanvas() );

        drawPanel->DisplayBoard( aBoard );
        m_toolManager->SetEnvironment( aBoard, drawPanel->GetView(),
                                       drawPanel->GetViewControls(), this );

        if( new_board )
            m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
    }
}
コード例 #13
0
void PCBNEW_CONTROL::updateGrid()
{
    BASE_SCREEN* screen = m_frame->GetScreen();
    //GRID_TYPE grid = screen->GetGrid( idx );
    getView()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGridSize() ) );
    getView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
}
コード例 #14
0
bool SHAPE_ARC::ConstructFromCornerAndAngles( VECTOR2I aP0,
        double aStartAngle,
        double aCenterAngle,
        double aRadius )
{
    m_p0 = aP0;
    auto d1 = VECTOR2D( 1.0, 0.0 ).Rotate( aStartAngle * M_PI / 180.0 ) * aRadius;
    auto d2 =
        VECTOR2D( 1.0, 0.0 ).Rotate( (aStartAngle + aCenterAngle) * M_PI / 180.0 ) * aRadius;

    m_pc = m_p0 - (VECTOR2I) d1;
    m_p1 = m_pc + (VECTOR2I) d2;

    if( aCenterAngle < 0 )
        std::swap( m_p0, m_p1 );

    return true;
}
コード例 #15
0
int GraphicTextWidth( const wxString& aText, const wxSize& aSize, bool aItalic, bool aBold )
{
    basic_gal.SetFontItalic( aItalic );
    basic_gal.SetFontBold( aBold );
    basic_gal.SetGlyphSize( VECTOR2D( aSize ) );

    VECTOR2D tsize = basic_gal.GetTextLineSize( aText );

    return KiROUND( tsize.x );
}
コード例 #16
0
/**
 * Function DrawGraphicText
 * Draw a graphic text (like module texts)
 *  @param aClipBox = the clipping rect, or NULL if no clipping
 *  @param aDC = the current Device Context. NULL if draw within a 3D GL Canvas
 *  @param aPos = text position (according to h_justify, v_justify)
 *  @param aColor (COLOR4D) = text color
 *  @param aText = text to draw
 *  @param aOrient = angle in 0.1 degree
 *  @param aSize = text size (size.x or size.y can be < 0 for mirrored texts)
 *  @param aH_justify = horizontal justification (Left, center, right)
 *  @param aV_justify = vertical justification (bottom, center, top)
 *  @param aWidth = line width (pen width) (use default width if aWidth = 0)
 *      if width < 0 : draw segments in sketch mode, width = abs(width)
 *      Use a value min(aSize.x, aSize.y) / 5 for a bold text
 *  @param aItalic = true to simulate an italic font
 *  @param aBold = true to use a bold font. Useful only with default width value (aWidth = 0)
 *  @param aCallback() = function called (if non null) to draw each segment.
 *                  used to draw 3D texts or for plotting, NULL for normal drawings
 *  @param aPlotter = a pointer to a PLOTTER instance, when this function is used to plot
 *                  the text. NULL to draw this text.
 */
void DrawGraphicText( EDA_RECT* aClipBox,
                      wxDC* aDC,
                      const wxPoint& aPos,
                      COLOR4D aColor,
                      const wxString& aText,
                      double aOrient,
                      const wxSize& aSize,
                      enum EDA_TEXT_HJUSTIFY_T aH_justify,
                      enum EDA_TEXT_VJUSTIFY_T aV_justify,
                      int aWidth,
                      bool aItalic,
                      bool aBold,
                      void (* aCallback)( int x0, int y0, int xf, int yf ),
                      PLOTTER* aPlotter )
{
    bool    fill_mode = true;

    if( aWidth == 0 && aBold ) // Use default values if aWidth == 0
        aWidth = GetPenSizeForBold( std::min( aSize.x, aSize.y ) );

    if( aWidth < 0 )
    {
        aWidth = -aWidth;
        fill_mode = false;
    }

    basic_gal.SetIsFill( fill_mode );
    basic_gal.SetLineWidth( aWidth );

    EDA_TEXT dummy;
    dummy.SetItalic( aItalic );
    dummy.SetBold( aBold );
    dummy.SetHorizJustify( aH_justify );
    dummy.SetVertJustify( aV_justify );

    wxSize size = aSize;
    dummy.SetMirrored( size.x < 0 );

    if( size.x < 0 )
        size.x = - size.x;

    dummy.SetTextSize( size );

    basic_gal.SetTextAttributes( &dummy );
    basic_gal.SetPlotter( aPlotter );
    basic_gal.SetCallback( aCallback );
    basic_gal.m_DC = aDC;
    basic_gal.m_Color = aColor;
    basic_gal.SetClipBox( aClipBox );

    basic_gal.StrokeText( aText, VECTOR2D( aPos ), aOrient * M_PI/1800 );
}
コード例 #17
0
int PCBNEW_CONTROL::GridPreset( const TOOL_EVENT& aEvent )
{
    long idx = aEvent.Parameter<long>();

    m_frame->SetPresetGrid( idx );
    BASE_SCREEN* screen = m_frame->GetScreen();
    GRID_TYPE grid = screen->GetGrid( idx );

    getView()->GetGAL()->SetGridSize( VECTOR2D( grid.m_Size ) );
    getView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );

    return 0;
}
コード例 #18
0
const BOX2I D_PAD::ViewBBox() const
{
    // Bounding box includes soldermask too
    int solderMaskMargin       = GetSolderMaskMargin();
    VECTOR2I solderPasteMargin = VECTOR2D( GetSolderPasteMargin() );
    EDA_RECT bbox              = GetBoundingBox();

    // Look for the biggest possible bounding box
    int xMargin = std::max( solderMaskMargin, solderPasteMargin.x );
    int yMargin = std::max( solderMaskMargin, solderPasteMargin.y );

    return BOX2I( VECTOR2I( bbox.GetOrigin() ) - VECTOR2I( xMargin, yMargin ),
                  VECTOR2I( bbox.GetSize() ) + VECTOR2I( 2 * xMargin, 2 * yMargin ) );
}
コード例 #19
0
int PCB_EDITOR_CONTROL::CrossProbeSchToPcb( const TOOL_EVENT& aEvent )
{
    BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();

    if( item )
    {
        m_probingSchToPcb = true;
        getView()->SetCenter( VECTOR2D( item->GetPosition() ) );
        m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
        m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item );
    }

    return 0;
}
コード例 #20
0
void SELECTION_TOOL::findCallback( BOARD_ITEM* aItem )
{
    clearSelection();

    if( aItem )
    {
        clearSelection();
        select( aItem );
        getView()->SetCenter( VECTOR2D( aItem->GetPosition() ) );

        // Inform other potentially interested tools
        m_toolMgr->ProcessEvent( SelectedEvent );
    }

    m_frame->GetGalCanvas()->ForceRefresh();
}
コード例 #21
0
void DIALOG_DRC_CONTROL::OnPopupMenu( wxCommandEvent& event )
{
    int             source = event.GetId();

    const DRC_ITEM* item = 0;
    wxPoint         pos;

    int             selection;

    switch( source )
    {
    case ID_POPUP_UNCONNECTED_A:
        selection = m_UnconnectedListBox->GetSelection();
        item = m_UnconnectedListBox->GetItem( selection );
        pos  = item->GetPointA();
        break;

    case ID_POPUP_UNCONNECTED_B:
        selection = m_UnconnectedListBox->GetSelection();
        item = m_UnconnectedListBox->GetItem( selection );
        pos  = item->GetPointB();
        break;

    case ID_POPUP_MARKERS_A:
        selection = m_ClearanceListBox->GetSelection();
        item = m_ClearanceListBox->GetItem( selection );
        pos  = item->GetPointA();
        break;

    case ID_POPUP_MARKERS_B:
        selection = m_ClearanceListBox->GetSelection();
        item = m_ClearanceListBox->GetItem( selection );
        pos  = item->GetPointB();
        break;
    }

    if( item )
    {
        m_brdEditor->CursorGoto( pos );
        m_brdEditor->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) );

        if( !IsModal() )
            Show( false );
    }
}
コード例 #22
0
bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
{
    const unsigned GRIP_MARGIN = 20;
    VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false );

    // Check if the point is located within any of the currently selected items bounding boxes
    for( unsigned int i = 0; i < m_selection.items.GetCount(); ++i )
    {
        BOARD_ITEM* item = m_selection.Item<BOARD_ITEM>( i );
        BOX2I itemBox = item->ViewBBox();
        itemBox.Inflate( margin.x, margin.y );    // Give some margin for gripping an item

        if( itemBox.Contains( aPoint ) )
            return true;
    }

    return false;
}
コード例 #23
0
void DIALOG_DRC_CONTROL::OnUnconnectedSelectionEvent( wxCommandEvent& event )
{
    int selection = event.GetSelection();

    if( selection != wxNOT_FOUND )
    {
        // until a MARKER is selected, this button is not enabled.
        m_DeleteCurrentMarkerButton->Enable( true );

        // Find the selected DRC_ITEM in the listbox, position cursor there,
        // at the first of the two pads.
        const DRC_ITEM* item = m_UnconnectedListBox->GetItem( selection );
        if( item )
        {
            m_brdEditor->CursorGoto( item->GetPointA(), false );
            m_brdEditor->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) );
        }
    }

    event.Skip();
}
コード例 #24
0
ファイル: dialog_set_grid.cpp プロジェクト: myutwo/kicad
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->GetGridId() == ID_POPUP_GRID_USER )
            screen->SetGrid( ID_POPUP_GRID_USER );

        if( IsGalCanvasActive() )
        {
            GetGalCanvas()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGrid().m_Size.x,
                                                             screen->GetGrid().m_Size.y ) );
            GetGalCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
        }

        m_canvas->Refresh();

        return true;
    }

    return false;
}
コード例 #25
0
PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
        EDA_DRAW_FRAME( aKiway, aParent, FRAME_PL_EDITOR, wxT( "PlEditorFrame" ),
                        wxDefaultPosition, wxDefaultSize,
                        KICAD_DEFAULT_DRAWFRAME_STYLE, PL_EDITOR_FRAME_NAME )
{
    m_UserUnits = MILLIMETRES;
    m_zoomLevelCoeff = 290.0;   // Adjusted to roughly displays zoom level = 1
                                // when the screen shows a 1:1 image
                                // obviously depends on the monitor,
                                // but this is an acceptable value

    m_showAxis = false;                 // true to show X and Y axis on screen
    m_showGridAxis = true;
    m_showBorderAndTitleBlock   = true; // true for reference drawings.
    m_hotkeysDescrList = PlEditorHotkeysDescr;
    m_originSelectChoice = 0;
    SetDrawBgColor( WHITE );            // default value, user option (WHITE/BLACK)
    WS_DATA_MODEL::GetTheInstance().m_EditMode = true;
    SetShowPageLimits( true );
    m_AboutTitle = "PlEditor";

    m_propertiesFrameWidth = 200;

    // Give an icon
    wxIcon icon;
    icon.CopyFromBitmap( KiBitmap( icon_pagelayout_editor_xpm ) );
    SetIcon( icon );

    // Create GAL canvas
#ifdef __WXMAC__
    // Cairo renderer doesn't handle Retina displays
    m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL;
#else
    m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO;
#endif

    auto* drawPanel = new PL_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize,
                                             GetGalDisplayOptions(), m_canvasType );
    SetGalCanvas( drawPanel );

    LoadSettings( config() );
    SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );

    wxSize pageSizeIU = GetPageLayout().GetPageSettings().GetSizeIU();
    SetScreen( new PL_EDITOR_SCREEN( pageSizeIU ) );

    if( !GetScreen()->GridExists( m_LastGridSizeId + ID_POPUP_GRID_LEVEL_1000 ) )
        m_LastGridSizeId = ID_POPUP_GRID_LEVEL_1MM - ID_POPUP_GRID_LEVEL_1000;

    GetScreen()->SetGrid( m_LastGridSizeId + ID_POPUP_GRID_LEVEL_1000 );

    setupTools();
    ReCreateMenuBar();
    ReCreateHToolbar();
    ReCreateVToolbar();

    wxWindow* stsbar = GetStatusBar();
    int dims[] = {

        // balance of status bar on far left is set to a default or whatever is left over.
        -1,

        // When using GetTextSize() remember the width of '1' is not the same
        // as the width of '0' unless the font is fixed width, and it usually won't be.

        // zoom:
        GetTextSize( wxT( "Z 762000" ), stsbar ).x + 10,

        // cursor coords
        GetTextSize( wxT( "X 0234.567  Y 0234.567" ), stsbar ).x + 10,

        // delta distances
        GetTextSize( wxT( "dx 0234.567  dx 0234.567" ), stsbar ).x + 10,

        // Coord origin (use the bigger message)
        GetTextSize( _( "coord origin: Right Bottom page corner" ), stsbar ).x + 10,

        // units display, Inches is bigger than mm
        GetTextSize( _( "Inches" ), stsbar ).x + 10
    };

    SetStatusWidths( arrayDim( dims ), dims );

    m_auimgr.SetManagedWindow( this );
    m_auimgr.SetArtProvider( new EDA_DOCKART( this ) );

    m_propertiesPagelayout = new PROPERTIES_FRAME( this );

    // Horizontal items; layers 4 - 6
    m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) );
    m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) );

    // Vertical items; layers 1 - 3
    m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(1) );

    m_auimgr.AddPane( m_propertiesPagelayout, EDA_PANE().Palette().Name( "Props" ).Right().Layer(2)
                      .Caption( _( "Properties" ) ).MinSize( m_propertiesPagelayout->GetMinSize() )
                      .BestSize( m_propertiesFrameWidth, -1 ) );

    m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( "DrawFrame" ).Center() );
    m_auimgr.AddPane( GetGalCanvas(), EDA_PANE().Canvas().Name( "DrawFrameGal" ).Center().Hide() );

    // Set up viewport
    KIGFX::VIEW* view = GetGalCanvas()->GetView();
    view->SetScale( GetZoomLevelCoeff() / m_canvas->GetZoom() );
    view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) );

    UseGalCanvas();

    m_auimgr.Update();

    // Initialize the current page layout
    WS_DATA_MODEL& pglayout = WS_DATA_MODEL::GetTheInstance();
#if 0       //start with empty layout
    pglayout.AllowVoidList( true );
    pglayout.ClearList();
#else       // start with the default Kicad layout
    pglayout.SetPageLayout();
#endif
    OnNewPageLayout();
}
コード例 #26
0
bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const
{
    // In case the item has a very tiny width defined, allow it to be selected
    const int MIN_HIT_TEST_RADIUS = Millimeter2iu( 0.01 );

    // calculate aRefPos in XY gerber axis:
    wxPoint ref_pos = GetXYPosition( aRefPos );

    SHAPE_POLY_SET poly;

    switch( m_Shape )
    {
    case GBR_POLYGON:
        poly = m_Polygon;
        return poly.Contains( VECTOR2I( ref_pos ), 0 );

    case GBR_SPOT_POLY:
        poly = GetDcodeDescr()->m_Polygon;
        poly.Move( m_Start );
        return poly.Contains( VECTOR2I( ref_pos ), 0 );

    case GBR_SPOT_RECT:
        return GetBoundingBox().Contains( aRefPos );

    case GBR_ARC:
        {
            double radius = GetLineLength( m_Start, m_ArcCentre );
            VECTOR2D test_radius = VECTOR2D( ref_pos ) - VECTOR2D( m_ArcCentre );

            int size = ( ( m_Size.x < MIN_HIT_TEST_RADIUS ) ? MIN_HIT_TEST_RADIUS
                                                            : m_Size.x );

            // Are we close enough to the radius?
            bool radius_hit = ( std::fabs( test_radius.EuclideanNorm() - radius) < size );

            if( radius_hit )
            {
                // Now check that we are within the arc angle

                VECTOR2D start = VECTOR2D( m_Start ) - VECTOR2D( m_ArcCentre );
                VECTOR2D end = VECTOR2D( m_End ) - VECTOR2D( m_ArcCentre );

                double start_angle = NormalizeAngleRadiansPos( start.Angle() );
                double end_angle = NormalizeAngleRadiansPos( end.Angle() );

                if( m_Start == m_End )
                {
                    start_angle = 0;
                    end_angle = 2 * M_PI;
                }
                else if( end_angle < start_angle )
                {
                    end_angle += 2 * M_PI;
                }

                double test_angle = NormalizeAngleRadiansPos( test_radius.Angle() );

                return ( test_angle > start_angle && test_angle < end_angle );
            }

            return false;
        }

    case GBR_SPOT_MACRO:
        // Aperture macro polygons are already in absolute coordinates
        auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start );
        for( int i = 0; i < p->OutlineCount(); ++i )
        {
            if( p->Contains( VECTOR2I( aRefPos ), i ) )
                return true;
        }
        return false;
    }

    // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items)
    int radius = std::min( m_Size.x, m_Size.y ) >> 1;

    if( radius < MIN_HIT_TEST_RADIUS )
        radius = MIN_HIT_TEST_RADIUS;

    if( m_Flashed )
        return HitTestPoints( m_Start, ref_pos, radius );
    else
        return TestSegmentHit( ref_pos, m_Start, m_End, radius );
}
コード例 #27
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 )
            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;
    }
}
コード例 #28
0
FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
                                            EDA_DRAW_PANEL_GAL::GAL_TYPE aBackend ) :
    PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_PCB_MODULE_EDITOR, wxEmptyString,
                         wxDefaultPosition, wxDefaultSize,
                         KICAD_DEFAULT_DRAWFRAME_STYLE, GetFootprintEditorFrameName() )
{
    m_showBorderAndTitleBlock = false;   // true to show the frame references
    m_showAxis = true;                   // true to show X and Y axis on screen
    m_showGridAxis = true;               // show the grid origin axis
    m_hotkeysDescrList = g_Module_Editor_Hotkeys_Descr;
    m_FrameSize = ConvertDialogToPixels( wxSize( 500, 350 ) );    // default in case of no prefs
    m_canvasType = aBackend;
    m_AboutTitle = "ModEdit";

    // Give an icon
    wxIcon icon;
    icon.CopyFromBitmap( KiBitmap( icon_modedit_xpm ) );
    SetIcon( icon );

    // Create GAL canvas
    if( aBackend == EDA_DRAW_PANEL_GAL::GAL_TYPE_UNKNOWN )
        m_canvasType = LoadCanvasTypeSetting();
    else
        m_canvasType = aBackend;

    PCB_DRAW_PANEL_GAL* drawPanel = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize,
                                                            GetGalDisplayOptions(), m_canvasType );
    SetGalCanvas( drawPanel );

    SetBoard( new BOARD() );
    // In modedit, the default net clearance is not known.
    // (it depends on the actual board)
    // So we do not show the default clearance, by setting it to 0
    // The footprint or pad specific clearance will be shown
    GetBoard()->GetDesignSettings().GetDefault()->SetClearance( 0 );

    // Don't show the default board solder mask clearance in the footprint editor.  Only the
    // footprint or pad clearance setting should be shown if it is not 0.
    GetBoard()->GetDesignSettings().m_SolderMaskMargin = 0;

    // restore the last footprint from the project, if any
    restoreLastFootprint();

    // Ensure all layers and items are visible:
    // In footprint editor, some layers have no meaning or
    // cannot be used, but we show all of them, at least to be able
    // to edit a bad layer
    GetBoard()->SetVisibleAlls();

    // However the "no net" mark on pads is useless, because there is
    // no net in footprint editor: make it non visible
    GetBoard()->SetElementVisibility( LAYER_NO_CONNECTS, false );

    m_Layers = new PCB_LAYER_WIDGET( this, GetCanvas(), true );

    // LoadSettings() *after* creating m_LayersManager, because LoadSettings()
    // initialize parameters in m_LayersManager
    LoadSettings( config() );
    GetGalDisplayOptions().m_axesEnabled = true;

    SetScreen( new PCB_SCREEN( GetPageSettings().GetSizeIU() ) );
    GetScreen()->SetMaxUndoItems( m_UndoRedoCountMax );

    GetScreen()->AddGrid( m_UserGridSize, EDA_UNITS_T::UNSCALED_UNITS, ID_POPUP_GRID_USER );
    GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );

    // In modedit, set the default paper size to A4:
    // this should be OK for all footprint to plot/print
    SetPageSettings( PAGE_INFO( PAGE_INFO::A4 ) );

    SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );

    initLibraryTree();
    m_treePane = new FOOTPRINT_TREE_PANE( this );

    // Create the manager and dispatcher & route draw panel events to the dispatcher
    setupTools();

    // ReCreateMenuBar();       // UseGalCanvas() will do this for us.
    ReCreateHToolbar();
    ReCreateVToolbar();
    ReCreateOptToolbar();

    m_Layers->ReFill();
    m_Layers->ReFillRender();

    GetScreen()->m_Active_Layer = F_SilkS;
    m_Layers->SelectLayer( F_SilkS );
    m_Layers->OnLayerSelected();

    m_auimgr.SetManagedWindow( this );
    m_auimgr.SetArtProvider( new EDA_DOCKART( this ) );

    // Horizontal items; layers 4 - 6
    m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) );
    m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) );

    // Vertical items; layers 1 - 3
    m_auimgr.AddPane( m_optionsToolBar, EDA_PANE().VToolbar().Name( "OptToolbar" ).Left().Layer(3) );
    m_auimgr.AddPane( m_treePane, EDA_PANE().Palette().Name( "Footprints" ).Left().Layer(1)
                      .Caption( _( "Libraries" ) ).MinSize( 250, 400 )
                      .BestSize( m_defaultLibWidth, -1 ) );

    m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(1) );
    m_auimgr.AddPane( m_Layers, EDA_PANE().Palette().Name( "LayersManager" ).Right().Layer(3)
                      .Caption( _( "Layers Manager" ) ).PaneBorder( false )
                      .MinSize( 80, -1 ).BestSize( m_Layers->GetBestSize() ) );

    m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( "DrawFrame" ).Center() );
    m_auimgr.AddPane( GetGalCanvas(), EDA_PANE().Canvas().Name( "DrawFrameGal" ).Center().Hide() );

    GetGalCanvas()->GetGAL()->SetAxesEnabled( true );

    // Set up viewport
    KIGFX::VIEW* view = GetGalCanvas()->GetView();
    view->SetScale( GetZoomLevelCoeff() / m_canvas->GetZoom() );
    view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) );

    UseGalCanvas();

    m_auimgr.Update();
    updateTitle();

    Raise();            // On some window managers, this is needed
    Show( true );

    Zoom_Automatique( false );
}
コード例 #29
0
void EDA_DRAW_FRAME::OnSelectGrid( wxCommandEvent& event )
{
    int* clientData;
    int  eventId = ID_POPUP_GRID_LEVEL_100;

    if( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
    {
        if( m_gridSelectBox == NULL )
            return;

        /*
         * Don't use wxCommandEvent::GetClientData() here.  It always
         * returns NULL in GTK.  This solution is not as elegant but
         * it works.
         */
        int index = m_gridSelectBox->GetSelection();
        wxASSERT( index != wxNOT_FOUND );
        clientData = (int*) m_gridSelectBox->wxItemContainer::GetClientData( index );

        if( clientData != NULL )
            eventId = *clientData;
    }
    else
    {
        eventId = event.GetId();

        /* Update the grid select combobox if the grid size was changed
         * by menu event.
         */
        if( m_gridSelectBox != NULL )
        {
            for( size_t i = 0; i < m_gridSelectBox->GetCount(); i++ )
            {
                clientData = (int*) m_gridSelectBox->wxItemContainer::GetClientData( i );

                if( clientData && eventId == *clientData )
                {
                    m_gridSelectBox->SetSelection( i );
                    break;
                }
            }
        }
    }

    // Be sure m_LastGridSizeId is up to date.
    m_LastGridSizeId = eventId - ID_POPUP_GRID_LEVEL_1000;

    BASE_SCREEN* screen = GetScreen();

    if( screen->GetGridId() == eventId )
        return;

    /*
     * This allows for saving non-sequential command ID offsets used that
     * may be used in the grid size combobox.  Do not use the selection
     * index returned by GetSelection().
     */
    screen->SetGrid( eventId );
    SetCrossHairPosition( RefPos( true ) );

    if( IsGalCanvasActive() )
    {
        GetGalCanvas()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGrid().m_Size.x,
                                                         screen->GetGrid().m_Size.y ) );
        GetGalCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
    }

    m_canvas->Refresh();
}
コード例 #30
0
// Cursor control
int PCBNEW_CONTROL::CursorControl( const TOOL_EVENT& aEvent )
{
    long type = aEvent.Parameter<long>();
    bool fastMove = type & COMMON_ACTIONS::CURSOR_FAST_MOVE;
    type &= ~COMMON_ACTIONS::CURSOR_FAST_MOVE;

    GRID_HELPER gridHelper( m_frame );
    VECTOR2D cursor = getViewControls()->GetCursorPosition();
    VECTOR2I gridSize = gridHelper.GetGrid();
    VECTOR2D newCursor = gridHelper.Align( cursor );

    if( fastMove )
        gridSize = gridSize * 10;

    switch( type )
    {
        case COMMON_ACTIONS::CURSOR_UP:
            newCursor -= VECTOR2D( 0, gridSize.y );
            break;

        case COMMON_ACTIONS::CURSOR_DOWN:
            newCursor += VECTOR2D( 0, gridSize.y );
            break;

        case COMMON_ACTIONS::CURSOR_LEFT:
            newCursor -= VECTOR2D( gridSize.x, 0 );
            break;

        case COMMON_ACTIONS::CURSOR_RIGHT:
            newCursor += VECTOR2D( gridSize.x, 0 );
            break;

        case COMMON_ACTIONS::CURSOR_CLICK:              // fall through
        case COMMON_ACTIONS::CURSOR_DBL_CLICK:
        {
            TOOL_ACTIONS action = TA_NONE;
            int modifiers = 0;

            modifiers |= wxGetKeyState( WXK_SHIFT ) ? MD_SHIFT : 0;
            modifiers |= wxGetKeyState( WXK_CONTROL ) ? MD_CTRL : 0;
            modifiers |= wxGetKeyState( WXK_ALT ) ? MD_ALT : 0;

            if( type == COMMON_ACTIONS::CURSOR_CLICK )
                action = TA_MOUSE_CLICK;
            else if( type == COMMON_ACTIONS::CURSOR_DBL_CLICK )
                action = TA_MOUSE_DBLCLICK;
            else
                assert( false );

            TOOL_EVENT evt( TC_MOUSE, action, BUT_LEFT | modifiers );
            evt.SetMousePosition( getViewControls()->GetCursorPosition() );
            m_toolMgr->ProcessEvent( evt );

            return 0;
        }
        break;
    }

    // Handler cursor movement
    KIGFX::VIEW* view = getView();
    newCursor = view->ToScreen( newCursor );
    newCursor.x = KiROUND( newCursor.x );
    newCursor.y = KiROUND( newCursor.y );

    // Pan the screen if required
    const VECTOR2I& screenSize = view->GetGAL()->GetScreenPixelSize();
    BOX2I screenBox( VECTOR2I( 0, 0 ), screenSize );

    if( !screenBox.Contains( newCursor ) )
    {
        VECTOR2D delta( 0, 0 );

        if( newCursor.x < screenBox.GetLeft() )
        {
            delta.x = newCursor.x - screenBox.GetLeft();
            newCursor.x = screenBox.GetLeft();
        }
        else if( newCursor.x > screenBox.GetRight() )
        {
            delta.x = newCursor.x - screenBox.GetRight();
            // -1 is to keep the cursor within the drawing area,
            // so the cursor coordinates are still updated
            newCursor.x = screenBox.GetRight() - 1;
        }

        if( newCursor.y < screenBox.GetTop() )
        {
            delta.y = newCursor.y - screenBox.GetTop();
            newCursor.y = screenBox.GetTop();
        }
        else if( newCursor.y > screenBox.GetBottom() )
        {
            delta.y = newCursor.y - screenBox.GetBottom();
            // -1 is to keep the cursor within the drawing area,
            // so the cursor coordinates are still updated
            newCursor.y = screenBox.GetBottom() - 1;
        }

        view->SetCenter( view->GetCenter() + view->ToWorld( delta, false ) );
    }

    m_frame->GetGalCanvas()->WarpPointer( newCursor.x, newCursor.y );

    return 0;
}