← Back to team overview

kicad-developers team mailing list archive

[PATCH] Zoom to fit on empty canvas

 

Hi,

Here's a small patch to add a bounding box method to the worksheet
item, and use it to enable zoom to full sheet when the canvas is
empty.

It's a rare thing to have an empty canvas, but it does annoy me when
testing things on a blank slate, as the current behaviour is a bit
wierd (zoom to bottom right-ish first, then to top left).

Cheers,

John
From 7d6f23ccc7382d84eba4e1fd359a7630b57be2ea Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Wed, 15 Mar 2017 19:26:41 +0800
Subject: [PATCH] Fix zoom-to-fit on empty Pcbnew canvas

Previously, this did a hardcoded fit, which presumably only works on
sepecific monitors and with specific PCB worksheet frames.

This adds a bounding box method for the worksheet and uses that to
calculate the box to fit when there is nothing on the PCB.
---
 common/tool/common_tools.cpp   | 14 ++++++++++----
 common/worksheet_viewitem.cpp  | 30 ++++++++++++++++++++----------
 include/class_draw_panel_gal.h | 12 ++++++++++++
 include/worksheet_viewitem.h   |  2 ++
 pcbnew/pcb_draw_panel_gal.cpp  | 16 ++++++++++++++++
 pcbnew/pcb_draw_panel_gal.h    |  7 +++++++
 6 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/common/tool/common_tools.cpp b/common/tool/common_tools.cpp
index e2a551cbb..1a6c3793c 100644
--- a/common/tool/common_tools.cpp
+++ b/common/tool/common_tools.cpp
@@ -107,9 +107,14 @@ int COMMON_TOOLS::ZoomFitScreen( const TOOL_EVENT& aEvent )
 
     if( bBox.GetWidth() == 0 || bBox.GetHeight() == 0 )
     {
-        // Empty view
-        view->SetScale( 17.0 );     // works fine for the standard worksheet frame
+        // Empty view, try the page outline
+        bBox = galCanvas->GetEmptyPanelBoundingBox();
+    }
 
+    if( bBox.GetWidth() == 0 || bBox.GetHeight() == 0 )
+    {
+        // Still empty, fallback to a default
+        view->SetScale( 17.0 );     // works fine for the standard worksheet frame
         view->SetCenter( screenSize / 2.0 );
     }
     else
@@ -118,11 +123,12 @@ 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 );
+        // zoom out slightly to leave a margin around the fitted box
+        const double fitAllZoomMargin = 0.95;
+        view->SetScale( scale * fitAllZoomMargin );
         view->SetCenter( bBox.Centre() );
     }
 
-
     // Take scrollbars into account
     VECTOR2D worldScrollbarSize = view->ToWorld( scrollbarSize, false );
     view->SetCenter( view->GetCenter() + worldScrollbarSize / 2.0 );
diff --git a/common/worksheet_viewitem.cpp b/common/worksheet_viewitem.cpp
index 18f8fb98e..754fee9f4 100644
--- a/common/worksheet_viewitem.cpp
+++ b/common/worksheet_viewitem.cpp
@@ -33,6 +33,7 @@
 #include <painter.h>
 #include <layers_id_colors_and_visibility.h>
 #include <class_page_info.h>
+#include <class_eda_rect.h>
 #include <view/view.h>
 
 using namespace KIGFX;
@@ -54,17 +55,27 @@ void WORKSHEET_VIEWITEM::SetTitleBlock( const TITLE_BLOCK* aTitleBlock )
 }
 
 
-const BOX2I WORKSHEET_VIEWITEM::ViewBBox() const
+const EDA_RECT WORKSHEET_VIEWITEM::GetBoundingBox() const
 {
-    BOX2I bbox;
+    EDA_RECT bbox;
 
-    if( m_pageInfo != NULL )
+    if( m_pageInfo != nullptr )
     {
-        bbox.SetOrigin( VECTOR2I( 0, 0 ) );
-        bbox.SetEnd( VECTOR2I( m_pageInfo->GetWidthMils() * 25400,
-                               m_pageInfo->GetHeightMils() * 25400 ) );
+        bbox.SetOrigin( { 0, 0 } );
+        bbox.SetEnd( { m_pageInfo->GetWidthMils() * 25400,
+                       m_pageInfo->GetHeightMils() * 25400 } );
     }
-    else
+
+    return bbox;
+}
+
+
+const BOX2I WORKSHEET_VIEWITEM::ViewBBox() const
+{
+    BOX2I bbox( VECTOR2I( GetBoundingBox().GetPosition() ),
+                VECTOR2I( GetBoundingBox().GetSize() ) );
+
+    if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
     {
         bbox.SetMaximum();
     }
@@ -198,9 +209,8 @@ void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const
 
 void WORKSHEET_VIEWITEM::drawBorder( GAL* aGal ) const
 {
-    VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
-    VECTOR2D end = VECTOR2D( m_pageInfo->GetWidthMils() * 25400,
-                             m_pageInfo->GetHeightMils() * 25400 );
+    const VECTOR2D origin( GetBoundingBox().GetPosition() );
+    const VECTOR2D end( GetBoundingBox().GetSize() );
 
     aGal->SetIsStroke( true );
     // Use a gray color for the border color
diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h
index 282442401..fcf664cc9 100644
--- a/include/class_draw_panel_gal.h
+++ b/include/class_draw_panel_gal.h
@@ -34,6 +34,7 @@
 #include <wx/window.h>
 #include <wx/timer.h>
 #include <math/vector2d.h>
+#include <math/box2.h>
 #include <msgpanel.h>
 
 class BOARD;
@@ -201,6 +202,17 @@ public:
         return m_stealsFocus;
     }
 
+    /**
+     * Get the bounding box of the canvas without anything on it.
+     *
+     * For example, for canvases with worksheets, this can be the
+     * worksheet bounding box. Default implementation returns a null box.
+     */
+    virtual BOX2I GetEmptyPanelBoundingBox() const
+    {
+        return BOX2I();
+    }
+
 protected:
     void onPaint( wxPaintEvent& WXUNUSED( aEvent ) );
     void onSize( wxSizeEvent& aEvent );
diff --git a/include/worksheet_viewitem.h b/include/worksheet_viewitem.h
index efbb6d013..09282c705 100644
--- a/include/worksheet_viewitem.h
+++ b/include/worksheet_viewitem.h
@@ -134,6 +134,8 @@ public:
         return wxT( "WORKSHEET_VIEWITEM" );
     }
 
+    const EDA_RECT GetBoundingBox() const override;
+
 protected:
     /// File name displayed in the title block
     std::string m_fileName;
diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp
index 7eeefad3a..2ddf470cd 100644
--- a/pcbnew/pcb_draw_panel_gal.cpp
+++ b/pcbnew/pcb_draw_panel_gal.cpp
@@ -169,6 +169,22 @@ void PCB_DRAW_PANEL_GAL::SetWorksheet( KIGFX::WORKSHEET_VIEWITEM* aWorksheet )
 }
 
 
+BOX2I PCB_DRAW_PANEL_GAL::GetEmptyPanelBoundingBox() const
+{
+    BOX2I bbox;
+
+    if( m_worksheet )
+    {
+        const EDA_RECT worksheetBBox = m_worksheet->GetBoundingBox();
+
+        bbox = BOX2I( { worksheetBBox.GetPosition() },
+                      { worksheetBBox.GetSize() } );
+    }
+
+    return bbox;
+}
+
+
 void PCB_DRAW_PANEL_GAL::UseColorScheme( const COLORS_DESIGN_SETTINGS* aSettings )
 {
     KIGFX::PCB_RENDER_SETTINGS* rs;
diff --git a/pcbnew/pcb_draw_panel_gal.h b/pcbnew/pcb_draw_panel_gal.h
index dfd3a9808..f26f22db2 100644
--- a/pcbnew/pcb_draw_panel_gal.h
+++ b/pcbnew/pcb_draw_panel_gal.h
@@ -60,6 +60,13 @@ public:
     void SetWorksheet( KIGFX::WORKSHEET_VIEWITEM* aWorksheet );
 
     /**
+     * Function GetPanelEmptyBBox
+     *
+     * @return the current worksheet's bounding box
+     */
+    BOX2I GetEmptyPanelBoundingBox() const override;
+
+    /**
      * Function UseColorScheme
      * Applies layer color settings.
      * @param aSettings are the new settings.
-- 
2.12.0


Follow ups