KiCad PCB EDA Suite
base_screen.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) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
7  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
32 #include <fctsys.h>
33 #include <macros.h>
34 #include <common.h>
35 #include <base_struct.h>
36 #include <base_screen.h>
37 #include <id.h>
38 #include <base_units.h>
39 #include <trace_helpers.h>
40 
41 
42 wxString BASE_SCREEN::m_PageLayoutDescrFileName; // the name of the page layout descr file.
43 
44 
46  EDA_ITEM( aType )
47 {
49  m_Initialized = false;
50  m_ScreenNumber = 1;
51  m_NumberOfScreens = 1; // Hierarchy: Root: ScreenNumber = 1
52  m_Zoom = 32.0;
53  m_Grid.m_Size = wxRealPoint( 50, 50 ); // Default grid size
55  m_Center = true;
56  m_IsPrinting = false;
59 
60  m_FlagModified = false; // Set when any change is made on board.
61  m_FlagSave = false; // Used in auto save set when an auto save is required.
62 
63  SetCurItem( NULL );
64 }
65 
66 
68 {
69 }
70 
71 
72 void BASE_SCREEN::InitDataPoints( const wxSize& aPageSizeIU )
73 {
74  if( m_Center )
75  {
76  m_crossHairPosition.x = 0;
77  m_crossHairPosition.y = 0;
78 
79  m_DrawOrg.x = -aPageSizeIU.x / 2;
80  m_DrawOrg.y = -aPageSizeIU.y / 2;
81  }
82  else
83  {
84  m_crossHairPosition.x = aPageSizeIU.x / 2;
85  m_crossHairPosition.y = aPageSizeIU.y / 2;
86 
87  m_DrawOrg.x = 0;
88  m_DrawOrg.y = 0;
89  }
90 
91  m_O_Curseur.x = m_O_Curseur.y = 0;
92 }
93 
94 
96 {
97  double scale = 1.0 / GetZoom();
98  return scale;
99 }
100 
101 
102 void BASE_SCREEN::SetScalingFactor( double aScale )
103 {
104  // Limit zoom to max and min allowed values:
105  double zoom = Clamp( GetMinAllowedZoom(), aScale, GetMaxAllowedZoom() );
106 
107  SetZoom( zoom );
108 }
109 
110 
112 {
113  return SetZoom( GetMinAllowedZoom() );
114 }
115 
116 
118 {
119  return SetZoom( GetMaxAllowedZoom() );
120 }
121 
122 
123 bool BASE_SCREEN::SetZoom( double iu_per_du )
124 {
125  if( iu_per_du == m_Zoom )
126  return false;
127 
128  wxLogTrace( traceScreen, "Zoom:%.16g 1/Zoom:%.16g", iu_per_du, 1/iu_per_du );
129 
130  if( iu_per_du < GetMinAllowedZoom() )
131  return false;
132 
133  if( iu_per_du > GetMaxAllowedZoom() )
134  return false;
135 
136  m_Zoom = iu_per_du;
137 
138  return true;
139 }
140 
141 
143 {
144  // Step must be AT LEAST 1.2
145  double target = m_Zoom * 1.2;
146 
147  for( unsigned i=0; i < m_ZoomList.size(); ++i )
148  {
149  if( target < m_ZoomList[i] )
150  {
151  SetZoom( m_ZoomList[i] );
152  return true;
153  }
154  }
155 
156  return false;
157 }
158 
159 
161 {
162  // Step must be AT LEAST 1.2
163  double target = m_Zoom / 1.2;
164 
165  for( unsigned i = m_ZoomList.size(); i != 0; --i )
166  {
167  if( target > m_ZoomList[i - 1] )
168  {
169  SetZoom( m_ZoomList[i - 1] );
170  return true;
171  }
172  }
173 
174  return false;
175 }
176 
177 /* Build the list of human readable grid list.
178  * The list shows the grid size both in mils or mm.
179  * aMmFirst = true to have mm first and mils after
180  * false to have mils first and mm after
181  */
182 int BASE_SCREEN::BuildGridsChoiceList( wxArrayString& aGridsList, bool aMmFirst) const
183 {
184  wxString msg;
185  wxRealPoint curr_grid_size = GetGridSize();
186  int idx = -1;
187  int idx_usergrid = -1;
188 
189  for( size_t i = 0; i < GetGridCount(); i++ )
190  {
191  const GRID_TYPE& grid = m_grids[i];
192  double gridValueMils = To_User_Unit( INCHES, grid.m_Size.x ) * 1000;
193  double gridValue_mm = To_User_Unit( MILLIMETRES, grid.m_Size.x );
194 
195  if( grid.m_CmdId == ID_POPUP_GRID_USER )
196  {
197  if( aMmFirst )
198  msg.Printf( _( "User grid: %.4f mm (%.2f mils)" ),
199  gridValue_mm, gridValueMils );
200  else
201  msg.Printf( _( "User grid: %.2f mils (%.4f mm)" ),
202  gridValueMils, gridValue_mm );
203  idx_usergrid = i;
204  }
205  else
206  {
207  if( aMmFirst )
208  msg.Printf( _( "Grid: %.4f mm (%.2f mils)" ),
209  gridValue_mm, gridValueMils );
210  else
211  msg.Printf( _( "Grid: %.2f mils (%.4f mm)" ),
212  gridValueMils, gridValue_mm );
213  }
214 
215  aGridsList.Add( msg );
216 
217  if( curr_grid_size == grid.m_Size )
218  idx = i;
219  }
220 
221  if( idx < 0 )
222  idx = idx_usergrid;
223 
224  return idx;
225 }
226 
227 
229 {
230  if( !m_grids.empty() )
231  m_grids.clear();
232 
233  m_grids = gridlist;
234 }
235 
236 
237 int BASE_SCREEN::SetGrid( const wxRealPoint& size )
238 {
239  wxASSERT( !m_grids.empty() );
240 
241  GRID_TYPE nearest_grid = m_grids[0];
242  int gridIdx = 0;
243 
244  for( unsigned i = 0; i < m_grids.size(); i++ )
245  {
246  if( m_grids[i].m_Size == size )
247  {
248  m_Grid = m_grids[i];
249  return m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
250  }
251 
252  // keep track of the nearest larger grid size, if the exact size is not found
253  if ( size.x < m_grids[i].m_Size.x )
254  {
255  gridIdx = m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
256  nearest_grid = m_grids[i];
257  }
258  }
259 
260  m_Grid = nearest_grid;
261 
262  wxLogWarning( _( "Grid size( %f, %f ) not in grid list, falling back "
263  "to grid size( %f, %f )." ),
264  size.x, size.y, m_Grid.m_Size.x, m_Grid.m_Size.y );
265 
266  return gridIdx;
267 }
268 
269 
270 int BASE_SCREEN::SetGrid( int aCommandId )
271 {
272  wxASSERT( !m_grids.empty() );
273 
274  for( unsigned i = 0; i < m_grids.size(); i++ )
275  {
276  if( m_grids[i].m_CmdId == aCommandId )
277  {
278  m_Grid = m_grids[i];
279  return m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
280  }
281  }
282 
283  m_Grid = m_grids[0];
284 
285  wxLogWarning( _( "Grid ID %d not in grid list, falling back to "
286  "grid size( %g, %g )." ), aCommandId,
287  m_Grid.m_Size.x, m_Grid.m_Size.y );
288 
289  return m_grids[0].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
290 }
291 
292 
293 void BASE_SCREEN::AddGrid( const GRID_TYPE& grid )
294 {
295  for( unsigned i = 0; i < m_grids.size(); i++ )
296  {
297  if( m_grids[i].m_Size == grid.m_Size && grid.m_CmdId != ID_POPUP_GRID_USER )
298  {
299  wxLogTrace( traceScreen, "Discarding duplicate grid size( %g, %g ).",
300  grid.m_Size.x, grid.m_Size.y );
301  return;
302  }
303 
304  if( m_grids[i].m_CmdId == grid.m_CmdId )
305  {
306  wxLogTrace( traceScreen, wxT( "Changing grid ID %d from size( %g, %g ) to " ) \
307  wxT( "size( %g, %g )." ),
308  grid.m_CmdId, m_grids[i].m_Size.x,
309  m_grids[i].m_Size.y, grid.m_Size.x, grid.m_Size.y );
310  m_grids[i].m_Size = grid.m_Size;
311  return;
312  }
313  }
314 
315  m_grids.push_back( grid );
316 }
317 
318 
319 void BASE_SCREEN::AddGrid( const wxRealPoint& size, int id )
320 {
321  GRID_TYPE grid;
322 
323  grid.m_Size = size;
324  grid.m_CmdId = id;
325  AddGrid( grid );
326 }
327 
328 
329 void BASE_SCREEN::AddGrid( const wxRealPoint& size, EDA_UNITS_T aUnit, int id )
330 {
331  wxRealPoint new_size;
332  GRID_TYPE new_grid;
333 
334  new_size.x = From_User_Unit( aUnit, size.x );
335  new_size.y = From_User_Unit( aUnit, size.y );
336  new_grid.m_CmdId = id;
337  new_grid.m_Size = new_size;
338 
339  AddGrid( new_grid );
340 }
341 
342 
344 {
345  wxCHECK_MSG( !m_grids.empty() && aIndex < m_grids.size(), m_Grid,
346  wxT( "Cannot get grid object outside the bounds of the grid list." ) );
347 
348  return m_grids[ aIndex ];
349 }
350 
351 
352 bool BASE_SCREEN::GridExists( int aCommandId )
353 {
354  // tests for grid command ID (not an index in grid list, but a wxID) exists in grid list.
355  for( unsigned i = 0; i < m_grids.size(); i++ )
356  {
357  if( m_grids[i].m_CmdId == aCommandId )
358  return true;
359  }
360 
361  return false;
362 }
363 
364 
365 wxPoint BASE_SCREEN::getNearestGridPosition( const wxPoint& aPosition,
366  const wxPoint& aGridOrigin, wxRealPoint* aGridSize ) const
367 {
368  wxPoint pt;
369  wxRealPoint gridSize;
370 
371  if( aGridSize )
372  gridSize = *aGridSize;
373  else
374  gridSize = GetGridSize();
375 
376  double offset = fmod( aGridOrigin.x, gridSize.x );
377  int x = KiROUND( (aPosition.x - offset) / gridSize.x );
378 
379  pt.x = KiROUND( x * gridSize.x + offset );
380 
381  offset = fmod( aGridOrigin.y, gridSize.y );
382 
383  int y = KiROUND( (aPosition.y - offset) / gridSize.y );
384  pt.y = KiROUND ( y * gridSize.y + offset );
385 
386  return pt;
387 }
388 
389 
390 wxPoint BASE_SCREEN::getCursorPosition( bool aOnGrid, const wxPoint& aGridOrigin,
391  wxRealPoint* aGridSize ) const
392 {
393  if( aOnGrid )
394  return getNearestGridPosition( m_crossHairPosition, aGridOrigin, aGridSize );
395 
396  return m_crossHairPosition;
397 }
398 
399 
401 {
402  wxPoint pos = m_crossHairPosition - m_DrawOrg;
403  double scalar = GetScalingFactor();
404 
405  pos.x = KiROUND( (double) pos.x * scalar );
406  pos.y = KiROUND( (double) pos.y * scalar );
407 
408  return pos;
409 }
410 
411 
412 void BASE_SCREEN::setCrossHairPosition( const wxPoint& aPosition, const wxPoint& aGridOrigin,
413  bool aSnapToGrid )
414 {
415  if( aSnapToGrid )
416  m_crossHairPosition = getNearestGridPosition( aPosition, aGridOrigin, NULL );
417  else
418  m_crossHairPosition = aPosition;
419 }
420 
421 
423 {
426 }
427 
428 
430 {
431  m_UndoList.PushCommand( aNewitem );
432 
433  // Delete the extra items, if count max reached
434  if( m_UndoRedoCountMax > 0 )
435  {
436  int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
437 
438  if( extraitems > 0 )
439  ClearUndoORRedoList( m_UndoList, extraitems );
440  }
441 }
442 
443 
445 {
446  m_RedoList.PushCommand( aNewitem );
447 
448  // Delete the extra items, if count max reached
449  if( m_UndoRedoCountMax > 0 )
450  {
451  int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
452 
453  if( extraitems > 0 )
454  ClearUndoORRedoList( m_RedoList, extraitems );
455  }
456 }
457 
458 
460 {
461  return m_UndoList.PopCommand();
462 }
463 
464 
466 {
467  return m_RedoList.PopCommand();
468 }
469 
470 
471 #if defined(DEBUG)
472 
473 void BASE_SCREEN::Show( int nestLevel, std::ostream& os ) const
474 {
475  // for now, make it look like XML, expand on this later.
476  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
477 
478  /* this class will eventually go away, but here's a place holder until then.
479  for( EDA_ITEM* item = m_drawList; item; item = item->Next() )
480  {
481  item->Show( nestLevel+1, os );
482  }
483  */
484 
485  NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
486 }
487 
488 #endif
double GetMinAllowedZoom() const
Function GetMinAllowedZoom returns the minimum allowed zoom factor, which was established as the firs...
Definition: base_screen.h:368
virtual void PushCommandToUndoList(PICKED_ITEMS_LIST *aItem)
Function PushCommandToUndoList add a command to undo in undo list delete the very old commands when t...
void SetGridList(GRIDS &sizelist)
long y
Definition: auxiliary.h:25
const wxRealPoint & GetGridSize() const
Return the grid size of the currently selected grid.
Definition: base_screen.h:410
void SetCurItem(EDA_ITEM *aItem)
Function SetCurItem sets the currently selected object, m_CurrentItem.
Definition: base_screen.h:231
int m_UndoRedoCountMax
undo/Redo command Max depth
Definition: base_screen.h:86
int m_ScreenNumber
Definition: base_screen.h:216
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: macros.h:130
bool m_FlagModified
Indicates current drawing has been modified.
Definition: base_screen.h:80
int m_ScrollPixelsPerUnitY
Pixels per scroll unit in the vertical direction.
Definition: base_screen.h:190
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
int BuildGridsChoiceList(wxArrayString &aGridsList, bool aMmFirst) const
Function BuildGridsChoiceList().
Implementation of conversion functions that require both schematic and board internal units...
virtual wxString GetClass() const override
Function GetClass returns the class name.
Definition: base_screen.h:494
wxPoint m_crossHairPosition
The cross hair position in logical (drawing) units.
Definition: base_screen.h:93
#define DEFAULT_MAX_UNDO_ITEMS
Definition: draw_frame.h:47
double GetZoom() const
Function GetZoom returns the current "zoom factor", which is a measure of "internal units per device ...
Definition: base_screen.h:340
wxPoint getCursorPosition(bool aOnGrid, const wxPoint &aGridOrigin, wxRealPoint *aGridSize) const
Function getCursorPosition returns the current cursor position in logical (drawing) units...
const wxChar *const traceScreen
Flag to enable debug output of BASE_SCREEN and it&#39;s derivatives.
wxPoint getNearestGridPosition(const wxPoint &aPosition, const wxPoint &aGridOrigin, wxRealPoint *aGridSize) const
Function getNearestGridPosition returns the nearest aGridSize location to aPosition.
int GetUndoCommandCount() const
Definition: base_screen.h:301
GRID_TYPE m_Grid
Current grid selection.
Definition: base_screen.h:83
const GRID_TYPE & GetGrid() const
Return the grid object of the currently selected grid.
Definition: base_screen.h:417
double From_User_Unit(EDA_UNITS_T aUnits, double aValue, bool aUseMils)
Return in internal units the value "val" given in a real unit such as "in", "mm" or "deg"...
Definition: base_units.cpp:278
virtual void ClearUndoORRedoList(UNDO_REDO_CONTAINER &aList, int aItemCount=-1)=0
Function ClearUndoORRedoList (virtual).
bool SetPreviousZoom()
wxPoint m_O_Curseur
Relative Screen cursor coordinate (on grid) in user units.
Definition: base_screen.h:185
PICKED_ITEMS_LIST * PopCommand()
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
bool SetNextZoom()
This file contains miscellaneous commonly used macros and functions.
void PushCommand(PICKED_ITEMS_LIST *aCommand)
static wxString m_PageLayoutDescrFileName
the name of the page layout descr file, or emty to used the default pagelayout
Definition: base_screen.h:180
virtual PICKED_ITEMS_LIST * PopCommandFromUndoList()
PopCommandFromUndoList return the last command to undo and remove it from list nothing is deleted...
void InitDataPoints(const wxSize &aPageSizeInternalUnits)
Definition: base_screen.cpp:72
std::vector< GRID_TYPE > GRIDS
Definition: base_screen.h:69
long x
Definition: auxiliary.h:24
bool m_Center
Center on screen.
Definition: base_screen.h:202
UNDO_REDO_CONTAINER m_UndoList
Objects list for the undo command (old data)
Definition: base_screen.h:210
bool m_Initialized
Definition: base_screen.h:207
double To_User_Unit(EDA_UNITS_T aUnit, double aValue, bool aUseMils)
Function To_User_Unit convert aValue in internal units to the appropriate user units defined by aUnit...
Definition: base_units.cpp:93
void SetScalingFactor(double iu_per_du)
Function SetScalingFactor sets the scaling factor of "internal unit per device unit".
Definition: common.h:161
virtual PICKED_ITEMS_LIST * PopCommandFromRedoList()
PopCommandFromRedoList return the last command to undo and remove it from list nothing is deleted...
virtual void ClearUndoRedoList()
Function ClearUndoRedoList clear undo and redo list, using ClearUndoORRedoList() picked items are del...
int m_ScrollPixelsPerUnitX
Pixels per scroll unit in the horizontal direction.
Definition: base_screen.h:189
wxRealPoint m_Size
Definition: base_screen.h:49
wxLogTrace helper definitions.
virtual bool SetZoom(double iu_per_du)
Function SetZoom adjusts the current zoom factor.
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
wxPoint getCrossHairScreenPosition() const
Function getCursorScreenPosition returns the cross hair position in device (display) units...
bool m_IsPrinting
Definition: base_screen.h:220
UNDO_REDO_CONTAINER m_RedoList
Objects list for the redo command (old data)
Definition: base_screen.h:211
double GetMaxAllowedZoom() const
Function GetMaxAllowedZoom returns the maximum allowed zoom factor, which was established as the last...
Definition: base_screen.h:361
void setCrossHairPosition(const wxPoint &aPosition, const wxPoint &aGridOrigin, bool aSnapToGrid)
Function setCrossHairPosition sets the screen cross hair position to aPosition in logical (drawing) u...
void AddGrid(const GRID_TYPE &grid)
GRIDS m_grids
List of valid grid sizes.
Definition: base_screen.h:79
const int scale
bool GridExists(int aCommandId)
Function GridExists tests for grid command ID (not an index in grid list, but a wxID) exists in grid ...
Class GRID_TYPE is for grid arrays.
Definition: base_screen.h:45
double GetScalingFactor() const
Function GetScalingFactor returns the inverse of the current scale used to draw items on screen...
Definition: base_screen.cpp:95
BASE_SCREEN(KICAD_T aType=SCREEN_T)
Definition: base_screen.cpp:45
size_t i
Definition: json11.cpp:597
size_t GetGridCount() const
Function GetGridCount().
Definition: base_screen.h:457
virtual void PushCommandToRedoList(PICKED_ITEMS_LIST *aItem)
Function PushCommandToRedoList add a command to redo in redo list delete the very old commands when t...
wxPoint m_DrawOrg
offsets for drawing the circuit on the screen
Definition: base_screen.h:183
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:154
The common library.
bool m_FlagSave
Indicates automatic file save.
Definition: base_screen.h:81
int m_NumberOfScreens
Definition: base_screen.h:217
double m_Zoom
Current zoom coefficient.
Definition: base_screen.h:95
Basic classes for most KiCad items.
int SetGrid(const wxRealPoint &size)
set the current grid size m_Grid.
int m_CmdId
Definition: base_screen.h:48
BASE_SCREEN class implementation.
bool SetLastZoom()
bool SetFirstZoom()
int GetRedoCommandCount() const
Definition: base_screen.h:306
EDA_UNITS_T
Definition: common.h:160
std::vector< double > m_ZoomList
standard zoom (i.e. scale) coefficients.
Definition: base_screen.h:219