From 15353e3c3312837872779ed3d23efd27300f5f51 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Sun, 11 Apr 2021 18:01:25 +0200 Subject: [PATCH] Eeschema: when placing a new symbol or image, avoid starting the autopan. When activate the new symbol placement, the mouse cursor is outside the canvas. Therefore a autopan was started and not so easy to stop. Now the mouse cursor (and the graphic cursor) are moved to a better location inside the canvas. Fixes #8156 https://gitlab.com/kicad/code/kicad/issues/8156 --- eeschema/tools/sch_drawing_tools.cpp | 64 ++++++++++++++++++++++++++-- eeschema/tools/sch_drawing_tools.h | 7 +++ 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/eeschema/tools/sch_drawing_tools.cpp b/eeschema/tools/sch_drawing_tools.cpp index ab5fcd0d6e..81004bd466 100644 --- a/eeschema/tools/sch_drawing_tools.cpp +++ b/eeschema/tools/sch_drawing_tools.cpp @@ -86,6 +86,24 @@ bool SCH_DRAWING_TOOLS::Init() } +EDA_RECT SCH_DRAWING_TOOLS::GetCanvasFreeAreaPixels() +{ + // calculate thearea of the canvas in pixels that create no autopan when + // is inside this area the mouse cursor + wxSize canvas_size = m_frame->GetCanvas()->GetSize(); + EDA_RECT canvas_area( wxPoint( 0, 0 ), canvas_size ); + const KIGFX::VC_SETTINGS& v_settings = getViewControls()->GetSettings(); + + if( v_settings.m_autoPanEnabled ) + canvas_area.Inflate( - v_settings.m_autoPanMargin ); + + // Gives a margin of 2 pixels + canvas_area.Inflate( -2 ); + + return canvas_area; +} + + int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent ) { SCH_COMPONENT* symbol = aEvent.Parameter(); @@ -209,13 +227,30 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent ) { m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); + // Store the mouse position: if it is outside the canvas, + // (happens when clicking on a toolbar tool) one cannot + // use the last stored cursor position to place the new symbol + // (Current mouse pos after closing the dialog will be used) + KIGFX::VIEW_CONTROLS* controls = getViewControls(); + VECTOR2D initialMousePos = controls->GetMousePosition(false); + // Build the rectangle area acceptable to move the cursor without + // having an auto-pan + EDA_RECT canvas_area = GetCanvasFreeAreaPixels(); + // Pick the footprint to be placed bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview; PICKED_SYMBOL sel = m_frame->PickSymbolFromLibTree( &filter, *historyList, true, 1, 1, footprintPreviews ); + // Restore cursor position after closing the dialog, + // but only if it has meaning (i.e inside the canvas) + VECTOR2D newMousePos = controls->GetMousePosition(false); - // Restore cursor after dialog - getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true ); + if( canvas_area.Contains( wxPoint( initialMousePos ) ) ) + controls->WarpCursor( controls->GetCursorPosition(), true ); + else if( !canvas_area.Contains( wxPoint( newMousePos ) ) ) + // The mouse is outside the canvas area, after closing the dialog, + // thus can creating autopan issues. Warp the mouse to the canvas centre + controls->WarpCursor( canvas_area.Centre(), false ); LIB_PART* part = sel.LibId.IsValid() ? m_frame->GetLibPart( sel.LibId ) : nullptr; @@ -425,6 +460,17 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent ) if( !image ) { m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); + + // Store the mouse position: if it is outside the canvas, + // (happens when clicking on a toolbar tool) one cannot + // use the last stored cursor position to place the new symbol + // (Current mouse pos after closing the dialog will be used) + KIGFX::VIEW_CONTROLS* controls = getViewControls(); + VECTOR2D initialMousePos = controls->GetMousePosition(false); + // Build the rectangle area acceptable to move the cursor without + // having an auto-pan + EDA_RECT canvas_area = GetCanvasFreeAreaPixels(); + wxFileDialog dlg( m_frame, _( "Choose Image" ), wxEmptyString, wxEmptyString, _( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(), wxFD_OPEN ); @@ -432,8 +478,18 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent ) if( dlg.ShowModal() != wxID_OK ) continue; - // Restore cursor after dialog - getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true ); + // Restore cursor position after closing the dialog, + // but only if it has meaning (i.e inside the canvas) + VECTOR2D newMousePos = controls->GetMousePosition( false ); + + if( canvas_area.Contains( wxPoint( initialMousePos ) ) ) + controls->WarpCursor( controls->GetCursorPosition(), true ); + else if( !canvas_area.Contains( wxPoint( newMousePos ) ) ) + // The mouse is outside the canvas area, after closing the dialog, + // thus can creating autopan issues. Warp the mouse to the canvas centre + controls->WarpCursor( canvas_area.Centre(), false ); + + cursorPos = controls->GetMousePosition( true ); wxString fullFilename = dlg.GetPath(); diff --git a/eeschema/tools/sch_drawing_tools.h b/eeschema/tools/sch_drawing_tools.h index 9c836cbf67..f0ec7e6d0d 100644 --- a/eeschema/tools/sch_drawing_tools.h +++ b/eeschema/tools/sch_drawing_tools.h @@ -57,6 +57,13 @@ public: int PlaceImage( const TOOL_EVENT& aEvent ); private: + /** + * @return the "free" area of the canvas in pixels. + * the free area is the area that create no autopan when the mouse cursor + * is inside this area + */ + EDA_RECT GetCanvasFreeAreaPixels(); + /** * Get the next queued text item. *