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();
EDA_DRAW_PANEL_GAL* galCanvas = m_frame->GetGalCanvas();
EDA_ITEM* model = getModel<EDA_ITEM>();
EDA_BASE_FRAME* frame = getEditFrame<EDA_BASE_FRAME>();
BOX2I bBox = model->ViewBBox();
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 ),
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() );
// 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 )
{
BASE_SCREEN* screen = GetScreen();

View File

@ -357,49 +357,25 @@ void LIB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
double LIB_EDIT_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;
*/
int dx, dy;
LIB_PART* part = GetCurPart();
double defaultLibraryZoom = 7.33;
if( part )
if( !part )
{
SetScrollCenterPosition( wxPoint( 0, 0 ) );
return defaultLibraryZoom;
}
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();
double sizeX = (double) boundingBox.GetWidth();
double sizeY = (double) boundingBox.GetHeight();
wxPoint centre = boundingBox.Centre();
dx = pageInfo.GetSizeIU().x;
dy = pageInfo.GetSizeIU().y;
// Reserve a 20% margin around component bounding box.
double margin_scale_factor = 1.2;
SetScrollCenterPosition( wxPoint( 0, 0 ) );
}
wxSize size = m_canvas->GetClientSize();
// Reserve a 10% margin around component bounding box.
double margin_scale_factor = 0.8;
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 );
// keep it >= minimal existing zoom (can happen for very small components
// for instance when starting a new component
if( bestzoom < GetScreen()->m_ZoomList[0] )
bestzoom = GetScreen()->m_ZoomList[0];
return bestzoom;
return bestZoom( sizeX, sizeY, margin_scale_factor, centre);
}

View File

@ -435,9 +435,6 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ):
m_auimgr.Update();
// Now Drawpanel is sized, we can use BestZoom to show the component (if any)
GetScreen()->SetZoom( BestZoom() );
Zoom_Automatique( false );
// Net list generator
@ -718,25 +715,15 @@ void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
double SCH_EDIT_FRAME::BestZoom()
{
int dx, dy;
wxSize size;
double sizeX = (double) GetScreen()->GetPageSettings().GetWidthIU();
double sizeY = (double) GetScreen()->GetPageSettings().GetHeightIU();
wxPoint centre( wxPoint( sizeX / 2, sizeY / 2 ) );
dx = GetScreen()->GetPageSettings().GetWidthIU();
dy = GetScreen()->GetPageSettings().GetHeightIU();
// The sheet boundary already affords us some margin, so add only an
// additional 5%.
double margin_scale_factor = 1.05;
size = m_canvas->GetClientSize();
// 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;
return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
}

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)
#ifdef USE_WX_GRAPHICS_CONTEXT
GetScreen()->SetZoom( BestZoom() );
GetScreen()->SetScalingFactor( BestZoom() );
#else
Zoom_Automatique( false );
#endif
@ -369,20 +369,13 @@ void LIB_VIEW_FRAME::OnUpdateElectricalType( wxUpdateUIEvent& aEvent )
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;
double bestzoom = 16.0; // default value for bestzoom
double defaultLibraryZoom = 7.33;
if( m_libraryName.IsEmpty() || m_entryName.IsEmpty() )
{
SetScrollCenterPosition( wxPoint( 0, 0 ) );
return bestzoom;
return defaultLibraryZoom;
}
LIB_ALIAS* alias = nullptr;
@ -401,29 +394,19 @@ double LIB_VIEW_FRAME::BestZoom()
if( !part )
{
SetScrollCenterPosition( wxPoint( 0, 0 ) );
return bestzoom;
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 margin_scale_factor = 0.8;
double zx =(double) boundingBox.GetWidth() / ( margin_scale_factor * (double)size.x );
double zy = (double) boundingBox.GetHeight() / ( margin_scale_factor * (double)size.y);
double sizeX = (double) boundingBox.GetWidth();
double sizeY = (double) boundingBox.GetHeight();
wxPoint centre = boundingBox.Centre();
// Calculates the best zoom
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
// like small power symbols
if( bestzoom < GetScreen()->m_ZoomList[0] )
bestzoom = GetScreen()->m_ZoomList[0];
SetScrollCenterPosition( boundingBox.Centre() );
return bestzoom;
return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
}

View File

@ -361,24 +361,23 @@ bool GERBVIEW_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
double GERBVIEW_FRAME::BestZoom()
{
double defaultGerberZoom = 1.0;
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 )
{
wxSize pagesize = GetPageSettings().GetSizeMils();
bbox.SetSize( wxSize( Mils2iu( pagesize.x ), Mils2iu( pagesize.y ) ) );
SetScrollCenterPosition( wxPoint( 0, 0 ) );
return defaultGerberZoom;
}
// Compute best zoom:
wxSize size = m_canvas->GetClientSize();
double x = (double) bbox.GetWidth() / (double) size.x;
double y = (double) bbox.GetHeight() / (double) size.y;
double best_zoom = std::max( x, y ) * 1.1;
double sizeX = (double) bbox.GetWidth();
double sizeY = (double) bbox.GetHeight();
wxPoint centre = bbox.Centre();
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; }
double bestZoom( double sizeX, double sizeY, double scaleFactor, wxPoint centre );
/**
* Function unitsChangeRefresh
* 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()
{
int dx, dy;
wxSize size;
double sizeX = (double) GetPageLayout().GetPageSettings().GetWidthIU();
double sizeY = (double) GetPageLayout().GetPageSettings().GetHeightIU();
wxPoint centre( sizeX / 2, sizeY / 2 );
dx = GetPageLayout().GetPageSettings().GetWidthIU();
dy = GetPageLayout().GetPageSettings().GetHeightIU();
// The sheet boundary already affords us some margin, so add only an
// additional 5%.
double margin_scale_factor = 1.05;
size = m_canvas->GetClientSize();
// 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;
return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
}

View File

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

View File

@ -533,7 +533,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
loadedBoard->SynchronizeNetsAndNetClasses();
SetStatusText( wxEmptyString );
BestZoom();
Zoom_Automatique( false );
// update the layer names in the listbox
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 )
{
if( GetScreen()->IsModify() )

View File

@ -64,6 +64,8 @@ public:
void LoadSettings( wxConfigBase* aCfg ) override;
void SaveSettings( wxConfigBase* aCfg ) override;
double BestZoom() override;
/**
* Function GetConfigurationSettings
* 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)
#ifdef USE_WX_GRAPHICS_CONTEXT
GetScreen()->SetZoom( BestZoom() );
GetScreen()->SetScalingFactor( BestZoom() );
#else
Zoom_Automatique( false );
#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)
#ifdef USE_WX_GRAPHICS_CONTEXT
GetScreen()->SetZoom( BestZoom() );
GetScreen()->SetScalingFactor( BestZoom() );
#else
Zoom_Automatique( false );
#endif

View File

@ -322,21 +322,16 @@ EDA_RECT PCB_BASE_FRAME::GetBoardBoundingBox( bool aBoardEdgesOnly ) const
double PCB_BASE_FRAME::BestZoom()
{
if( m_Pcb == NULL )
return 1.0;
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 iu_per_du_Y = clientz.y ? boardz.y / clientz.y : 1.0;
double sizeX = (double) ibbbox.GetWidth();
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;
return bestZoom( sizeX, sizeY, margin_scale_factor, centre );
}