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  {
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  msg = _( "Custom User Grid" );
198  idx_usergrid = i;
199  }
200  else
201  {
202  if( aMmFirst )
203  msg.Printf( _( "Grid: %.4f mm (%.2f mils)" ),
204  gridValue_mm, gridValueMils );
205  else
206  msg.Printf( _( "Grid: %.2f mils (%.4f mm)" ),
207  gridValueMils, gridValue_mm );
208  }
209 
210  aGridsList.Add( msg );
211 
212  if( curr_grid_size == grid.m_Size )
213  idx = i;
214  }
215 
216  if( idx < 0 )
217  idx = idx_usergrid;
218 
219  return idx;
220 }
221 
222 
224 {
225  if( !m_grids.empty() )
226  m_grids.clear();
227 
228  m_grids = gridlist;
229 }
230 
231 
232 int BASE_SCREEN::SetGrid( const wxRealPoint& size )
233 {
234  wxASSERT( !m_grids.empty() );
235 
236  GRID_TYPE nearest_grid = m_grids[0];
237  int gridIdx = 0;
238 
239  for( unsigned i = 0; i < m_grids.size(); i++ )
240  {
241  if( m_grids[i].m_Size == size )
242  {
243  m_Grid = m_grids[i];
244  return m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
245  }
246 
247  // keep track of the nearest larger grid size, if the exact size is not found
248  if ( size.x < m_grids[i].m_Size.x )
249  {
250  gridIdx = m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
251  nearest_grid = m_grids[i];
252  }
253  }
254 
255  m_Grid = nearest_grid;
256 
257  wxLogWarning( _( "Grid size( %f, %f ) not in grid list, falling back "
258  "to grid size( %f, %f )." ),
259  size.x, size.y, m_Grid.m_Size.x, m_Grid.m_Size.y );
260 
261  return gridIdx;
262 }
263 
264 
265 int BASE_SCREEN::SetGrid( int aCommandId )
266 {
267  wxASSERT( !m_grids.empty() );
268 
269  for( unsigned i = 0; i < m_grids.size(); i++ )
270  {
271  if( m_grids[i].m_CmdId == aCommandId )
272  {
273  m_Grid = m_grids[i];
274  return m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
275  }
276  }
277 
278  m_Grid = m_grids[0];
279 
280  wxLogWarning( _( "Grid ID %d not in grid list, falling back to "
281  "grid size( %g, %g )." ), aCommandId,
282  m_Grid.m_Size.x, m_Grid.m_Size.y );
283 
284  return m_grids[0].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
285 }
286 
287 
288 void BASE_SCREEN::AddGrid( const GRID_TYPE& grid )
289 {
290  for( unsigned i = 0; i < m_grids.size(); i++ )
291  {
292  if( m_grids[i].m_Size == grid.m_Size && grid.m_CmdId != ID_POPUP_GRID_USER )
293  {
294  wxLogTrace( traceScreen, "Discarding duplicate grid size( %g, %g ).",
295  grid.m_Size.x, grid.m_Size.y );
296  return;
297  }
298 
299  if( m_grids[i].m_CmdId == grid.m_CmdId )
300  {
301  wxLogTrace( traceScreen, wxT( "Changing grid ID %d from size( %g, %g ) to " ) \
302  wxT( "size( %g, %g )." ),
303  grid.m_CmdId, m_grids[i].m_Size.x,
304  m_grids[i].m_Size.y, grid.m_Size.x, grid.m_Size.y );
305  m_grids[i].m_Size = grid.m_Size;
306  return;
307  }
308  }
309 
310  m_grids.push_back( grid );
311 }
312 
313 
314 void BASE_SCREEN::AddGrid( const wxRealPoint& size, int id )
315 {
316  GRID_TYPE grid;
317 
318  grid.m_Size = size;
319  grid.m_CmdId = id;
320  AddGrid( grid );
321 }
322 
323 
324 void BASE_SCREEN::AddGrid( const wxRealPoint& size, EDA_UNITS_T aUnit, int id )
325 {
326  wxRealPoint new_size;
327  GRID_TYPE new_grid;
328 
329  new_size.x = From_User_Unit( aUnit, size.x );
330  new_size.y = From_User_Unit( aUnit, size.y );
331  new_grid.m_CmdId = id;
332  new_grid.m_Size = new_size;
333 
334  AddGrid( new_grid );
335 }
336 
337 
339 {
340  wxCHECK_MSG( !m_grids.empty() && aIndex < m_grids.size(), m_Grid,
341  wxT( "Cannot get grid object outside the bounds of the grid list." ) );
342 
343  return m_grids[ aIndex ];
344 }
345 
346 
347 bool BASE_SCREEN::GridExists( int aCommandId )
348 {
349  // tests for grid command ID (not an index in grid list, but a wxID) exists in grid list.
350  for( unsigned i = 0; i < m_grids.size(); i++ )
351  {
352  if( m_grids[i].m_CmdId == aCommandId )
353  return true;
354  }
355 
356  return false;
357 }
358 
359 
361  const wxPoint& aGridOrigin, wxRealPoint* aGridSize ) const
362 {
363  wxPoint pt;
364  wxRealPoint gridSize;
365 
366  if( aGridSize )
367  gridSize = *aGridSize;
368  else
369  gridSize = GetGridSize();
370 
371  double offset = fmod( aGridOrigin.x, gridSize.x );
372  int x = KiROUND( (aPosition.x - offset) / gridSize.x );
373 
374  pt.x = KiROUND( x * gridSize.x + offset );
375 
376  offset = fmod( aGridOrigin.y, gridSize.y );
377 
378  int y = KiROUND( (aPosition.y - offset) / gridSize.y );
379  pt.y = KiROUND ( y * gridSize.y + offset );
380 
381  return pt;
382 }
383 
384 
385 wxPoint BASE_SCREEN::getCursorPosition( bool aOnGrid, const wxPoint& aGridOrigin,
386  wxRealPoint* aGridSize ) const
387 {
388  if( aOnGrid )
389  return getNearestGridPosition( m_crossHairPosition, aGridOrigin, aGridSize );
390 
391  return m_crossHairPosition;
392 }
393 
394 
396 {
398  double scalar = GetScalingFactor();
399 
400  pos.x = KiROUND( (double) pos.x * scalar );
401  pos.y = KiROUND( (double) pos.y * scalar );
402 
403  return pos;
404 }
405 
406 
407 void BASE_SCREEN::setCrossHairPosition( const wxPoint& aPosition, const wxPoint& aGridOrigin,
408  bool aSnapToGrid )
409 {
410  if( aSnapToGrid )
411  m_crossHairPosition = getNearestGridPosition( aPosition, aGridOrigin, NULL );
412  else
413  m_crossHairPosition = aPosition;
414 }
415 
416 
418 {
421 }
422 
423 
425 {
426  m_UndoList.PushCommand( aNewitem );
427 
428  // Delete the extra items, if count max reached
429  if( m_UndoRedoCountMax > 0 )
430  {
431  int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
432 
433  if( extraitems > 0 )
434  ClearUndoORRedoList( m_UndoList, extraitems );
435  }
436 }
437 
438 
440 {
441  m_RedoList.PushCommand( aNewitem );
442 
443  // Delete the extra items, if count max reached
444  if( m_UndoRedoCountMax > 0 )
445  {
446  int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
447 
448  if( extraitems > 0 )
449  ClearUndoORRedoList( m_RedoList, extraitems );
450  }
451 }
452 
453 
455 {
456  return m_UndoList.PopCommand();
457 }
458 
459 
461 {
462  return m_RedoList.PopCommand();
463 }
464 
465 
466 #if defined(DEBUG)
467 
468 void BASE_SCREEN::Show( int nestLevel, std::ostream& os ) const
469 {
470  // for now, make it look like XML, expand on this later.
471  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
472 
473  /* this class will eventually go away, but here's a place holder until then.
474  for( EDA_ITEM* item = m_drawList; item; item = item->Next() )
475  {
476  item->Show( nestLevel+1, os );
477  }
478  */
479 
480  NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
481 }
482 
483 #endif
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
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
wxPoint getCursorPosition(bool aOnGrid, const wxPoint &aGridOrigin, wxRealPoint *aGridSize) const
Function getCursorPosition returns the current cursor position in logical (drawing) units...
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:127
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:120
double GetScalingFactor() const
Function GetScalingFactor returns the inverse of the current scale used to draw items on screen...
Definition: base_screen.cpp:95
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
const wxChar *const traceScreen
Flag to enable debug output of BASE_SCREEN and it&#39;s derivatives.
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 getCrossHairScreenPosition() const
Function getCursorScreenPosition returns the cross hair position in device (display) units...
GRID_TYPE m_Grid
Current grid selection.
Definition: base_screen.h:83
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
size_t GetGridCount() const
Function GetGridCount().
Definition: base_screen.h:457
double GetMinAllowedZoom() const
Function GetMinAllowedZoom returns the minimum allowed zoom factor, which was established as the firs...
Definition: base_screen.h:368
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
int BuildGridsChoiceList(wxArrayString &aGridsList, bool aMmFirst) const
Function BuildGridsChoiceList().
int GetUndoCommandCount() const
Definition: base_screen.h:301
std::vector< GRID_TYPE > GRIDS
Definition: base_screen.h:69
const GRID_TYPE & GetGrid() const
Return the grid object of the currently selected grid.
Definition: base_screen.h:417
long x
Definition: auxiliary.h:24
wxPoint getNearestGridPosition(const wxPoint &aPosition, const wxPoint &aGridOrigin, wxRealPoint *aGridSize) const
Function getNearestGridPosition returns the nearest aGridSize location to aPosition.
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:160
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.
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
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
BASE_SCREEN(KICAD_T aType=SCREEN_T)
Definition: base_screen.cpp:45
size_t i
Definition: json11.cpp:597
const wxRealPoint & GetGridSize() const
Return the grid size of the currently selected grid.
Definition: base_screen.h:410
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 GetMaxAllowedZoom() const
Function GetMaxAllowedZoom returns the maximum allowed zoom factor, which was established as the last...
Definition: base_screen.h:361
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()
EDA_UNITS_T
Definition: common.h:159
int GetRedoCommandCount() const
Definition: base_screen.h:306
std::vector< double > m_ZoomList
standard zoom (i.e. scale) coefficients.
Definition: base_screen.h:219