KiCad PCB EDA Suite
zoom.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
29 /*
30  * Manage zoom, grid step, and auto crop.
31  */
32 
33 #include <fctsys.h>
34 #include <id.h>
35 #include <class_drawpanel.h>
36 #include <view/view.h>
37 #include <class_base_screen.h>
38 #include <draw_frame.h>
39 #include <kicad_device_context.h>
40 #include <hotkeys_basic.h>
41 #include <menus_helpers.h>
42 #include <base_units.h>
43 #include <tool/tool_manager.h>
44 
45 
46 void EDA_DRAW_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer )
47 {
48  if( IsGalCanvasActive() )
49  return;
50 
51  AdjustScrollBars( aCenterPoint );
52 
53  // Move the mouse cursor to the on grid graphic cursor position
54  if( aWarpPointer )
56 
57  m_canvas->Refresh();
58  m_canvas->Update();
59 }
60 
61 void EDA_DRAW_FRAME::RedrawScreen2( const wxPoint& posBefore )
62 {
63  if( IsGalCanvasActive() )
64  return;
65 
66  wxPoint dPos = posBefore - m_canvas->GetClientSize() / 2; // relative screen position to center before zoom
67  wxPoint newScreenPos = m_canvas->ToDeviceXY( GetCrossHairPosition() ); // screen position of crosshair after zoom
68  wxPoint newCenter = m_canvas->ToLogicalXY( newScreenPos - dPos );
69 
70  AdjustScrollBars( newCenter );
71 
72  m_canvas->Refresh();
73  m_canvas->Update();
74 }
75 
76 
77 void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer )
78 {
79  BASE_SCREEN* screen = GetScreen();
80 
81  // Set the best zoom and get center point.
82 
83  // BestZoom() can compute an illegal zoom if the client window size
84  // is small, say because frame is not maximized. So use the clamping form
85  // of SetZoom():
86  double bestzoom = BestZoom();
87  screen->SetScalingFactor( bestzoom );
88 
89  if( screen->m_FirstRedraw )
91 
92  if( !IsGalCanvasActive() )
93  RedrawScreen( GetScrollCenterPosition(), aWarpPointer );
94  else
95  m_toolManager->RunAction( "common.Control.zoomFitScreen", true );
96 }
97 
98 
104 {
105  // Compute the best zoom
106  Rect.Normalize();
107 
108  wxSize size = m_canvas->GetClientSize();
109 
110  // Use ceil to at least show the full rect
111  double scalex = (double) Rect.GetSize().x / size.x;
112  double bestscale = (double) Rect.GetSize().y / size.y;
113 
114  bestscale = std::max( bestscale, scalex );
115 
116  GetScreen()->SetScalingFactor( bestscale );
117  RedrawScreen( Rect.Centre(), true );
118 }
119 
120 
125 void EDA_DRAW_FRAME::OnZoom( wxCommandEvent& event )
126 {
127  if( m_canvas == NULL )
128  return;
129 
130  int id = event.GetId();
131  bool zoom_at_cursor = false;
132  BASE_SCREEN* screen = GetScreen();
133  wxPoint center = GetScrollCenterPosition();
134 
135  switch( id )
136  {
139  if( screen->SetPreviousZoom() )
140  RedrawScreen2( center );
141  break;
142 
143  case ID_POPUP_ZOOM_IN:
144  zoom_at_cursor = true;
145  center = GetCrossHairPosition();
146 
147  // fall thru
148  case ID_VIEWER_ZOOM_IN:
149  case ID_ZOOM_IN:
150  if( screen->SetPreviousZoom() )
151  RedrawScreen( center, zoom_at_cursor );
152  break;
153 
156  if( screen->SetNextZoom() )
157  RedrawScreen2( center );
158  break;
159 
160  case ID_POPUP_ZOOM_OUT:
161  zoom_at_cursor = true;
162  center = GetCrossHairPosition();
163 
164  // fall thru
165  case ID_VIEWER_ZOOM_OUT:
166  case ID_ZOOM_OUT:
167  if( screen->SetNextZoom() )
168  RedrawScreen( center, zoom_at_cursor );
169  break;
170 
173  case ID_ZOOM_REDRAW:
174  m_canvas->Refresh();
175  break;
176 
178  center = GetCrossHairPosition();
179  RedrawScreen( center, true );
180  break;
181 
182  case ID_POPUP_ZOOM_PAGE:
183  case ID_VIEWER_ZOOM_PAGE:
184  case ID_ZOOM_PAGE:
185  Zoom_Automatique( false );
186  break;
187 
189  break;
190 
191  case ID_POPUP_CANCEL:
193  break;
194 
195  default:
197  }
198 
199  UpdateStatusBar();
200 }
201 
202 
204 {
205  GetScreen()->SetNextZoom();
206 }
207 
208 
210 {
212 }
213 
214 
216 {
217  BASE_SCREEN* screen = GetScreen();
218 
219  if( aIndex >= (int) screen->m_ZoomList.size() )
220  {
221  wxLogDebug( wxT( "%s %d: index %d is outside the bounds of the zoom list." ),
222  __TFILE__, __LINE__, aIndex );
223  return;
224  }
225 
226  if( m_zoomSelectBox )
227  m_zoomSelectBox->SetSelection( aIndex );
228 
229  if( screen->SetZoom( screen->m_ZoomList[aIndex] ) )
231 
232  UpdateStatusBar();
233 }
234 
235 
236 /* add the zoom list menu the the MasterMenu.
237  * used in OnRightClick(wxMouseEvent& event)
238  */
239 void EDA_DRAW_FRAME::AddMenuZoomAndGrid( wxMenu* MasterMenu )
240 {
241  int maxZoomIds;
242  double zoom;
243  wxString msg;
244  BASE_SCREEN* screen = m_canvas->GetScreen();
245 
246  msg = AddHotkeyName( _( "Center" ), m_hotkeysDescrList, HK_ZOOM_CENTER );
247  AddMenuItem( MasterMenu, ID_POPUP_ZOOM_CENTER, msg, KiBitmap( zoom_center_on_screen_xpm ) );
248  msg = AddHotkeyName( _( "Zoom in" ), m_hotkeysDescrList, HK_ZOOM_IN );
249  AddMenuItem( MasterMenu, ID_POPUP_ZOOM_IN, msg, KiBitmap( zoom_in_xpm ) );
250  msg = AddHotkeyName( _( "Zoom out" ), m_hotkeysDescrList, HK_ZOOM_OUT );
251  AddMenuItem( MasterMenu, ID_POPUP_ZOOM_OUT, msg, KiBitmap( zoom_out_xpm ) );
252  msg = AddHotkeyName( _( "Redraw view" ), m_hotkeysDescrList, HK_ZOOM_REDRAW );
253  AddMenuItem( MasterMenu, ID_POPUP_ZOOM_REDRAW, msg, KiBitmap( zoom_redraw_xpm ) );
254  msg = AddHotkeyName( _( "Zoom auto" ), m_hotkeysDescrList, HK_ZOOM_AUTO );
255  AddMenuItem( MasterMenu, ID_POPUP_ZOOM_PAGE, msg, KiBitmap( zoom_fit_in_page_xpm ) );
256 
257 
258  wxMenu* zoom_choice = new wxMenu;
259  AddMenuItem( MasterMenu, zoom_choice,
260  ID_POPUP_ZOOM_SELECT, _( "Zoom Select" ),
261  KiBitmap( zoom_selection_xpm ) );
262 
263  zoom = screen->GetZoom();
265  maxZoomIds = ( (size_t) maxZoomIds < screen->m_ZoomList.size() ) ?
266  maxZoomIds : screen->m_ZoomList.size();
267 
268  // Populate zoom submenu.
269  for( int i = 0; i < maxZoomIds; i++ )
270  {
271  msg.Printf( wxT( "%.2f" ), m_zoomLevelCoeff / screen->m_ZoomList[i] );
272 
273  zoom_choice->Append( ID_POPUP_ZOOM_LEVEL_START + i, _( "Zoom: " ) + msg,
274  wxEmptyString, wxITEM_CHECK );
275  if( zoom == screen->m_ZoomList[i] )
276  zoom_choice->Check( ID_POPUP_ZOOM_LEVEL_START + i, true );
277  }
278 
279  // Create grid submenu as required.
280  if( screen->GetGridCount() )
281  {
282  wxMenu* gridMenu = new wxMenu;
283  AddMenuItem( MasterMenu, gridMenu, ID_POPUP_GRID_SELECT,
284  _( "Grid Select" ), KiBitmap( grid_select_xpm ) );
285 
286  wxArrayString gridsList;
287  int icurr = screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES );
288 
289  for( unsigned i = 0; i < gridsList.GetCount(); i++ )
290  {
291  GRID_TYPE& grid = screen->GetGrid( i );
292  gridMenu->Append( grid.m_CmdId, gridsList[i], wxEmptyString, wxITEM_CHECK );
293 
294  if( (int)i == icurr )
295  gridMenu->Check( grid.m_CmdId, true );
296  }
297  }
298 
299  MasterMenu->AppendSeparator();
300  AddMenuItem( MasterMenu, ID_POPUP_CANCEL, _( "Close" ), KiBitmap( cancel_xpm ) );
301 }
TOOL_MANAGER * m_toolManager
Definition: draw_frame.h:94
void AdjustScrollBars(const wxPoint &aCenterPosition)
Definition: draw_frame.cpp:888
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Definition: draw_panel.cpp:326
wxPoint ToDeviceXY(const wxPoint &pos)
Function ToDeviceXY transforms logical to device coordinates.
Definition: draw_panel.cpp:196
Implementation of conversion functions that require both schematic and board internal units...
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Function AddMenuItem is an inline helper function to create and insert a menu item with an icon into ...
Definition: bitmap.cpp:55
virtual double BestZoom()=0
Return the zoom level which displays the full page on screen.
double GetZoom() const
Function GetZoom returns the current "zoom factor", which is a measure of "internal units per device ...
Definition: id.h:232
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
const wxPoint & GetScrollCenterPosition() const
virtual void OnZoom(wxCommandEvent &event)
Function OnZoom Called from any zoom event (toolbar , hotkey or popup )
Definition: zoom.cpp:125
void MoveCursorToCrossHair()
Function MoveCursorToCrossHair warps the cursor to the current cross hair position.
Definition: draw_panel.cpp:348
bool SetPreviousZoom()
size_t GetGridCount() const
Function GetGridCount().
bool SetNextZoom()
int BuildGridsChoiceList(wxArrayString &aGridsList, bool aMmFirst) const
Function BuildGridsChoiceList().
wxPoint ToLogicalXY(const wxPoint &pos)
Function ToLogicalXY transforms device to logical coordinates.
Definition: draw_panel.cpp:206
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Function KiBitmap constructs a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:36
void Zoom_Automatique(bool aWarpPointer)
Function Zoom_Automatique redraws the screen with best zoom level and the best centering that shows a...
Definition: zoom.cpp:77
virtual BASE_SCREEN * GetScreen() const
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
Definition: draw_frame.h:309
a helper to handle the real device context used in KiCad
EDA_HOTKEY_CONFIG * m_hotkeysDescrList
Definition: draw_frame.h:76
const GRID_TYPE & GetGrid() const
Return the grid object of the currently selected grid.
Class BASE_SCREEN handles how to draw a screen (a board, a schematic ...)
void SetScalingFactor(double iu_per_du)
Function SetScalingFactor sets the scaling factor of "internal unit per device unit".
Definition: base_screen.cpp:99
Definition: common.h:145
wxChoice * m_zoomSelectBox
Choice box to choose the zoom value.
Definition: draw_frame.h:118
bool IsGalCanvasActive() const
Function IsGalCanvasActive is used to check which canvas (GAL-based or standard) is currently in use...
Definition: draw_frame.h:795
void SetPresetZoom(int aIndex)
Function SetPresetZoom() changes zoom to one of the preset values.
Definition: zoom.cpp:215
bool SetZoom(double iu_per_du)
Function SetZoom adjusts the current zoom factor.
wxPoint Centre() const
void RedrawScreen2(const wxPoint &posBefore)
Function RedrawScreen2 puts the crosshair back to the screen position it had before zooming...
Definition: zoom.cpp:61
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:56
void Normalize()
Function Normalize ensures that the height ant width are positive.
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:92
void RedrawScreen(const wxPoint &aCenterPoint, bool aWarpPointer)
Function RedrawScreen redraws the entire screen area by updating the scroll bars and mouse pointer in...
Definition: zoom.cpp:46
double m_zoomLevelCoeff
a suitable value to convert the internal zoom scaling factor
Definition: draw_frame.h:85
wxString AddHotkeyName(const wxString &aText, EDA_HOTKEY **aList, int aCommandId, HOTKEY_ACTION_TYPE aShortCutType)
Function AddHotkeyName Add the key name from the Command id value ( m_Idcommand member value) ...
BASE_SCREEN class implementation.
Class GRID_TYPE is for grid arrays.
#define max(a, b)
Definition: auxiliary.h:86
Class EDA_RECT handles the component boundary box.
void SetNextZoom()
Function SetNextZoom() changes the zoom to the next one available.
Definition: zoom.cpp:203
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:188
void Window_Zoom(EDA_RECT &Rect)
Compute the zoom factor and the new draw offset to draw the selected area (Rect) in full window scree...
Definition: zoom.cpp:103
virtual void AddMenuZoomAndGrid(wxMenu *aMasterMenu)
Function AddMenuZoomAndGrid (virtual) Add standard zoom commands and submenu zoom and grid selection ...
Definition: zoom.cpp:239
Some functions to handle hotkeys in KiCad.
void SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Function SetCrossHairPosition sets the screen cross hair position to aPosition in logical (drawing) u...
const wxSize & GetSize() const
void SetPrevZoom()
Function SetPrevZoom() changes the zoom to the previous one available.
Definition: zoom.cpp:209
virtual void UpdateStatusBar()
Function UpdateStatusBar updates the status bar information.
Definition: draw_frame.cpp:650
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Function GetCrossHairPosition return the current cross hair position in logical (drawing) coordinates...
std::vector< double > m_ZoomList
standard zoom (i.e. scale) coefficients.