Centralize zoom-to-fit code.

Fixes a bunch of errors:
- libedit and libbrowser would zoom to bounding box but centre on canvas
- libedit, libbrowser and gerbview didn’t take the scroll bars into account
- pcbnew didn’t take scroll bars into account or apply the 10% margin
- appending a board file would re-centre, but not re-zoom

Fixes: lp:1504302
* https://bugs.launchpad.net/kicad/+bug/1504302
This commit is contained in:
Jeff Young 2018-02-13 21:19:41 +00:00 committed by Wayne Stambaugh
parent ac9fc949bd
commit 4bae901dc8
15 changed files with 107 additions and 125 deletions

View File

@ -107,6 +107,7 @@ int COMMON_TOOLS::ZoomFitScreen( const TOOL_EVENT& aEvent )
KIGFX::VIEW* view = getView(); KIGFX::VIEW* view = getView();
EDA_DRAW_PANEL_GAL* galCanvas = m_frame->GetGalCanvas(); EDA_DRAW_PANEL_GAL* galCanvas = m_frame->GetGalCanvas();
EDA_ITEM* model = getModel<EDA_ITEM>(); EDA_ITEM* model = getModel<EDA_ITEM>();
EDA_BASE_FRAME* frame = getEditFrame<EDA_BASE_FRAME>();
BOX2I bBox = model->ViewBBox(); BOX2I bBox = model->ViewBBox();
VECTOR2D scrollbarSize = VECTOR2D( galCanvas->GetSize() - galCanvas->GetClientSize() ); VECTOR2D scrollbarSize = VECTOR2D( galCanvas->GetSize() - galCanvas->GetClientSize() );
@ -121,7 +122,18 @@ int COMMON_TOOLS::ZoomFitScreen( const TOOL_EVENT& aEvent )
double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ), double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
fabs( vsize.y / screenSize.y ) ); fabs( vsize.y / screenSize.y ) );
view->SetScale( scale ); // Reserve a 10% margin around component bounding box.
double margin_scale_factor = 1.1;
// Leave 20% for library editors & viewers
if( frame->IsType( FRAME_PCB_MODULE_VIEWER ) || frame->IsType( FRAME_PCB_MODULE_VIEWER_MODAL )
|| frame->IsType( FRAME_SCH_VIEWER ) || frame->IsType( FRAME_SCH_VIEWER_MODAL )
|| frame->IsType( FRAME_SCH_LIB_EDITOR ) || frame->IsType( FRAME_PCB_MODULE_EDITOR ) )
{
margin_scale_factor = 1.2;
}
view->SetScale( scale / margin_scale_factor );
view->SetCenter( bBox.Centre() ); view->SetCenter( bBox.Centre() );
// Take scrollbars into account // Take scrollbars into account

View File

@ -78,6 +78,27 @@ void EDA_DRAW_FRAME::RedrawScreen2( const wxPoint& posBefore )
} }
// Factor out the calculation portion of the various BestZoom() implementations.
//
// Note that like it's forerunners this routine has an intentional side-effect: it
// sets the scroll centre position. While I'm not happy about that, it's probably
// not worth fixing as its days are numbered (GAL canvases use a different method).
double EDA_DRAW_FRAME::bestZoom( double sizeX, double sizeY, double scaleFactor, wxPoint centre )
{
double bestzoom = std::max( sizeX * scaleFactor / (double) m_canvas->GetClientSize().x,
sizeY * scaleFactor / (double) m_canvas->GetClientSize().y );
// Take scrollbars into account
DSIZE scrollbarSize = m_canvas->GetSize() - m_canvas->GetClientSize();
centre.x -= int( bestzoom * scrollbarSize.x / 2.0 );
centre.y -= int( bestzoom * scrollbarSize.y / 2.0 );
SetScrollCenterPosition( centre );
return bestzoom;
}
void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer ) void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer )
{ {
BASE_SCREEN* screen = GetScreen(); BASE_SCREEN* screen = GetScreen();

View File

@ -357,49 +357,25 @@ void LIB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
double LIB_EDIT_FRAME::BestZoom() double LIB_EDIT_FRAME::BestZoom()
{ {
/* Please, note: wxMSW before version 2.9 seems have LIB_PART* part = GetCurPart();
* problems with zoom values < 1 ( i.e. userscale > 1) and needs to be patched: double defaultLibraryZoom = 7.33;
* edit file <wxWidgets>/src/msw/dc.cpp
* search for line static const int VIEWPORT_EXTENT = 1000;
* and replace by static const int VIEWPORT_EXTENT = 10000;
*/
int dx, dy;
LIB_PART* part = GetCurPart(); if( !part )
if( part )
{ {
EDA_RECT boundingBox = part->GetUnitBoundingBox( m_unit, m_convert );
dx = boundingBox.GetWidth();
dy = boundingBox.GetHeight();
SetScrollCenterPosition( wxPoint( 0, 0 ) );
}
else
{
const PAGE_INFO& pageInfo = GetScreen()->GetPageSettings();
dx = pageInfo.GetSizeIU().x;
dy = pageInfo.GetSizeIU().y;
SetScrollCenterPosition( wxPoint( 0, 0 ) ); SetScrollCenterPosition( wxPoint( 0, 0 ) );
return defaultLibraryZoom;
} }
wxSize size = m_canvas->GetClientSize(); EDA_RECT boundingBox = part->GetUnitBoundingBox( m_unit, m_convert );
// Reserve a 10% margin around component bounding box. double sizeX = (double) boundingBox.GetWidth();
double margin_scale_factor = 0.8; double sizeY = (double) boundingBox.GetHeight();
double zx =(double) dx / ( margin_scale_factor * (double)size.x ); wxPoint centre = boundingBox.Centre();
double zy = (double) dy / ( margin_scale_factor * (double)size.y );
double bestzoom = std::max( zx, zy ); // Reserve a 20% margin around component bounding box.
double margin_scale_factor = 1.2;
// keep it >= minimal existing zoom (can happen for very small components return bestZoom( sizeX, sizeY, margin_scale_factor, centre);
// for instance when starting a new component
if( bestzoom < GetScreen()->m_ZoomList[0] )
bestzoom = GetScreen()->m_ZoomList[0];
return bestzoom;
} }

View File

@ -435,9 +435,6 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ):
m_auimgr.Update(); m_auimgr.Update();
// Now Drawpanel is sized, we can use BestZoom to show the component (if any)
GetScreen()->SetZoom( BestZoom() );
Zoom_Automatique( false ); Zoom_Automatique( false );
// Net list generator // Net list generator
@ -718,25 +715,15 @@ void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
double SCH_EDIT_FRAME::BestZoom() double SCH_EDIT_FRAME::BestZoom()
{ {
int dx, dy; double sizeX = (double) GetScreen()->GetPageSettings().GetWidthIU();
wxSize size; double sizeY = (double) GetScreen()->GetPageSettings().GetHeightIU();
wxPoint centre( wxPoint( sizeX / 2, sizeY / 2 ) );
dx = GetScreen()->GetPageSettings().GetWidthIU(); // The sheet boundary already affords us some margin, so add only an
dy = GetScreen()->GetPageSettings().GetHeightIU(); // additional 5%.
double margin_scale_factor = 1.05;
size = m_canvas->GetClientSize(); return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
// Reserve no margin because best zoom shows the full page
// and margins are already included in function that draws the sheet refernces
double margin_scale_factor = 1.0;
double zx =(double) dx / ( margin_scale_factor * (double)size.x );
double zy = (double) dy / ( margin_scale_factor * (double)size.y );
double bestzoom = std::max( zx, zy );
SetScrollCenterPosition( wxPoint( dx / 2, dy / 2 ) );
return bestzoom;
} }

View File

@ -237,7 +237,7 @@ LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
// Now Drawpanel is sized, we can use BestZoom to show the component (if any) // Now Drawpanel is sized, we can use BestZoom to show the component (if any)
#ifdef USE_WX_GRAPHICS_CONTEXT #ifdef USE_WX_GRAPHICS_CONTEXT
GetScreen()->SetZoom( BestZoom() ); GetScreen()->SetScalingFactor( BestZoom() );
#else #else
Zoom_Automatique( false ); Zoom_Automatique( false );
#endif #endif
@ -369,20 +369,13 @@ void LIB_VIEW_FRAME::OnUpdateElectricalType( wxUpdateUIEvent& aEvent )
double LIB_VIEW_FRAME::BestZoom() double LIB_VIEW_FRAME::BestZoom()
{ {
/* Please, note: wxMSW before version 2.9 seems have
* problems with zoom values < 1 ( i.e. userscale > 1) and needs to be patched:
* edit file <wxWidgets>/src/msw/dc.cpp
* search for line static const int VIEWPORT_EXTENT = 1000;
* and replace by static const int VIEWPORT_EXTENT = 10000;
*/
LIB_PART* part = NULL; LIB_PART* part = NULL;
double bestzoom = 16.0; // default value for bestzoom double defaultLibraryZoom = 7.33;
if( m_libraryName.IsEmpty() || m_entryName.IsEmpty() ) if( m_libraryName.IsEmpty() || m_entryName.IsEmpty() )
{ {
SetScrollCenterPosition( wxPoint( 0, 0 ) ); SetScrollCenterPosition( wxPoint( 0, 0 ) );
return bestzoom; return defaultLibraryZoom;
} }
LIB_ALIAS* alias = nullptr; LIB_ALIAS* alias = nullptr;
@ -401,29 +394,19 @@ double LIB_VIEW_FRAME::BestZoom()
if( !part ) if( !part )
{ {
SetScrollCenterPosition( wxPoint( 0, 0 ) ); SetScrollCenterPosition( wxPoint( 0, 0 ) );
return bestzoom; return defaultLibraryZoom;
} }
wxSize size = m_canvas->GetClientSize();
EDA_RECT boundingBox = part->GetUnitBoundingBox( m_unit, m_convert ); EDA_RECT boundingBox = part->GetUnitBoundingBox( m_unit, m_convert );
// Reserve a 10% margin around component bounding box. double sizeX = (double) boundingBox.GetWidth();
double margin_scale_factor = 0.8; double sizeY = (double) boundingBox.GetHeight();
double zx =(double) boundingBox.GetWidth() / ( margin_scale_factor * (double)size.x ); wxPoint centre = boundingBox.Centre();
double zy = (double) boundingBox.GetHeight() / ( margin_scale_factor * (double)size.y);
// Calculates the best zoom // Reserve a 20% margin around component bounding box.
bestzoom = std::max( zx, zy ); double margin_scale_factor = 1.2;
// keep it >= minimal existing zoom (can happen for very small components return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
// like small power symbols
if( bestzoom < GetScreen()->m_ZoomList[0] )
bestzoom = GetScreen()->m_ZoomList[0];
SetScrollCenterPosition( boundingBox.Centre() );
return bestzoom;
} }

View File

@ -361,24 +361,23 @@ bool GERBVIEW_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
double GERBVIEW_FRAME::BestZoom() double GERBVIEW_FRAME::BestZoom()
{ {
double defaultGerberZoom = 1.0;
EDA_RECT bbox = GetGerberLayout()->ComputeBoundingBox(); EDA_RECT bbox = GetGerberLayout()->ComputeBoundingBox();
// gives a size to bbox (current page size), if no item in list
if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 ) if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
{ {
wxSize pagesize = GetPageSettings().GetSizeMils(); SetScrollCenterPosition( wxPoint( 0, 0 ) );
bbox.SetSize( wxSize( Mils2iu( pagesize.x ), Mils2iu( pagesize.y ) ) ); return defaultGerberZoom;
} }
// Compute best zoom: double sizeX = (double) bbox.GetWidth();
wxSize size = m_canvas->GetClientSize(); double sizeY = (double) bbox.GetHeight();
double x = (double) bbox.GetWidth() / (double) size.x; wxPoint centre = bbox.Centre();
double y = (double) bbox.GetHeight() / (double) size.y;
double best_zoom = std::max( x, y ) * 1.1;
SetScrollCenterPosition( bbox.Centre() ); // Reserve no margin because GetGerberLayout()->ComputeBoundingBox() builds one in.
double margin_scale_factor = 1.0;
return best_zoom; return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
} }

View File

@ -149,6 +149,8 @@ protected:
void SetScreen( BASE_SCREEN* aScreen ) { m_currentScreen = aScreen; } void SetScreen( BASE_SCREEN* aScreen ) { m_currentScreen = aScreen; }
double bestZoom( double sizeX, double sizeY, double scaleFactor, wxPoint centre );
/** /**
* Function unitsChangeRefresh * Function unitsChangeRefresh
* is called when when the units setting has changed to allow for any derived classes * is called when when the units setting has changed to allow for any derived classes

View File

@ -277,25 +277,15 @@ void PL_EDITOR_FRAME::OnCloseWindow( wxCloseEvent& Event )
double PL_EDITOR_FRAME::BestZoom() double PL_EDITOR_FRAME::BestZoom()
{ {
int dx, dy; double sizeX = (double) GetPageLayout().GetPageSettings().GetWidthIU();
wxSize size; double sizeY = (double) GetPageLayout().GetPageSettings().GetHeightIU();
wxPoint centre( sizeX / 2, sizeY / 2 );
dx = GetPageLayout().GetPageSettings().GetWidthIU(); // The sheet boundary already affords us some margin, so add only an
dy = GetPageLayout().GetPageSettings().GetHeightIU(); // additional 5%.
double margin_scale_factor = 1.05;
size = m_canvas->GetClientSize(); return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
// Reserve no margin because best zoom shows the full page
// and margins are already included in function that draws the sheet refernces
double margin_scale_factor = 1.0;
double zx =(double) dx / ( margin_scale_factor * (double)size.x );
double zy = (double) dy / ( margin_scale_factor * (double)size.y );
double bestzoom = std::max( zx, zy );
SetScrollCenterPosition( wxPoint( dx / 2, dy / 2 ) );
return bestzoom;
} }

View File

@ -207,7 +207,7 @@ bool PCB_EDIT_FRAME::AppendBoardFile( const wxString& aFullFileName, int aCtl )
GetBoard()->SynchronizeNetsAndNetClasses(); GetBoard()->SynchronizeNetsAndNetClasses();
SetStatusText( wxEmptyString ); SetStatusText( wxEmptyString );
BestZoom(); Zoom_Automatique( false );
// Finish block move command: // Finish block move command:
wxPoint cpos = GetNearestGridPosition( bbox.Centre() ); wxPoint cpos = GetNearestGridPosition( bbox.Centre() );

View File

@ -533,7 +533,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
loadedBoard->SynchronizeNetsAndNetClasses(); loadedBoard->SynchronizeNetsAndNetClasses();
SetStatusText( wxEmptyString ); SetStatusText( wxEmptyString );
BestZoom(); Zoom_Automatique( false );
// update the layer names in the listbox // update the layer names in the listbox
ReCreateLayerBox( false ); ReCreateLayerBox( false );

View File

@ -532,6 +532,21 @@ void FOOTPRINT_EDIT_FRAME::SaveSettings( wxConfigBase* aCfg )
} }
double FOOTPRINT_EDIT_FRAME::BestZoom()
{
EDA_RECT ibbbox = GetBoardBoundingBox();
double sizeX = (double) ibbbox.GetWidth();
double sizeY = (double) ibbbox.GetHeight();
wxPoint centre = ibbbox.Centre();
// Reserve a 20% margin around "board" bounding box.
double margin_scale_factor = 1.2;
return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
}
void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
{ {
if( GetScreen()->IsModify() ) if( GetScreen()->IsModify() )

View File

@ -64,6 +64,8 @@ public:
void LoadSettings( wxConfigBase* aCfg ) override; void LoadSettings( wxConfigBase* aCfg ) override;
void SaveSettings( wxConfigBase* aCfg ) override; void SaveSettings( wxConfigBase* aCfg ) override;
double BestZoom() override;
/** /**
* Function GetConfigurationSettings * Function GetConfigurationSettings
* returns the footpr<EFBFBD>int editor settings list. * returns the footpr<EFBFBD>int editor settings list.

View File

@ -294,7 +294,7 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent
// Now Drawpanel is sized, we can use BestZoom to show the component (if any) // Now Drawpanel is sized, we can use BestZoom to show the component (if any)
#ifdef USE_WX_GRAPHICS_CONTEXT #ifdef USE_WX_GRAPHICS_CONTEXT
GetScreen()->SetZoom( BestZoom() ); GetScreen()->SetScalingFactor( BestZoom() );
#else #else
Zoom_Automatique( false ); Zoom_Automatique( false );
#endif #endif

View File

@ -211,7 +211,7 @@ FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway,
// Now Drawpanel is sized, we can use BestZoom to show the component (if any) // Now Drawpanel is sized, we can use BestZoom to show the component (if any)
#ifdef USE_WX_GRAPHICS_CONTEXT #ifdef USE_WX_GRAPHICS_CONTEXT
GetScreen()->SetZoom( BestZoom() ); GetScreen()->SetScalingFactor( BestZoom() );
#else #else
Zoom_Automatique( false ); Zoom_Automatique( false );
#endif #endif

View File

@ -322,21 +322,16 @@ EDA_RECT PCB_BASE_FRAME::GetBoardBoundingBox( bool aBoardEdgesOnly ) const
double PCB_BASE_FRAME::BestZoom() double PCB_BASE_FRAME::BestZoom()
{ {
if( m_Pcb == NULL )
return 1.0;
EDA_RECT ibbbox = GetBoardBoundingBox(); EDA_RECT ibbbox = GetBoardBoundingBox();
DSIZE clientz = m_canvas->GetClientSize();
DSIZE boardz( ibbbox.GetWidth(), ibbbox.GetHeight() );
double iu_per_du_X = clientz.x ? boardz.x / clientz.x : 1.0; double sizeX = (double) ibbbox.GetWidth();
double iu_per_du_Y = clientz.y ? boardz.y / clientz.y : 1.0; double sizeY = (double) ibbbox.GetHeight();
wxPoint centre = ibbbox.Centre();
double bestzoom = std::max( iu_per_du_X, iu_per_du_Y ); // Reserve a 10% margin around board bounding box.
double margin_scale_factor = 1.1;
SetScrollCenterPosition( ibbbox.Centre() ); return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
return bestzoom;
} }