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 
178 int BASE_SCREEN::BuildGridsChoiceList( wxArrayString& aGridsList, bool aMmFirst) const
179 {
180  wxString msg;
181  wxRealPoint curr_grid_size = GetGridSize();
182  int idx = -1;
183  int idx_usergrid = -1;
184 
185  for( size_t i = 0; i < GetGridCount(); i++ )
186  {
187  const GRID_TYPE& grid = m_grids[i];
188  double gridValueMils = To_User_Unit( INCHES, grid.m_Size.x ) * 1000;
189  double gridValue_mm = To_User_Unit( MILLIMETRES, grid.m_Size.x );
190 
191  if( grid.m_CmdId == ID_POPUP_GRID_USER )
192  {
193  if( aMmFirst )
194  msg.Printf( _( "User grid: %.4f mm (%.2f mils)" ),
195  gridValue_mm, gridValueMils );
196  else
197  msg.Printf( _( "User grid: %.2f mils (%.4f mm)" ),
198  gridValueMils, gridValue_mm );
199  idx_usergrid = i;
200  }
201  else
202  {
203  if( aMmFirst )
204  msg.Printf( _( "Grid: %.4f mm (%.2f mils)" ),
205  gridValue_mm, gridValueMils );
206  else
207  msg.Printf( _( "Grid: %.2f mils (%.4f mm)" ),
208  gridValueMils, gridValue_mm );
209  }
210 
211  aGridsList.Add( msg );
212 
213  if( curr_grid_size == grid.m_Size )
214  idx = i;
215  }
216 
217  if( idx < 0 )
218  idx = idx_usergrid;
219 
220  return idx;
221 }
222 
223 
225 {
226  if( !m_grids.empty() )
227  m_grids.clear();
228 
229  m_grids = gridlist;
230 }
231 
232 
233 int BASE_SCREEN::SetGrid( const wxRealPoint& size )
234 {
235  wxASSERT( !m_grids.empty() );
236 
237  GRID_TYPE nearest_grid = m_grids[0];
238  int gridIdx = 0;
239 
240  for( unsigned i = 0; i < m_grids.size(); i++ )
241  {
242  if( m_grids[i].m_Size == size )
243  {
244  m_Grid = m_grids[i];
245  return m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
246  }
247 
248  // keep track of the nearest larger grid size, if the exact size is not found
249  if ( size.x < m_grids[i].m_Size.x )
250  {
251  gridIdx = m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
252  nearest_grid = m_grids[i];
253  }
254  }
255 
256  m_Grid = nearest_grid;
257  return gridIdx;
258 }
259 
260 
261 int BASE_SCREEN::SetGrid( int aCommandId )
262 {
263  wxASSERT( !m_grids.empty() );
264 
265  for( unsigned i = 0; i < m_grids.size(); i++ )
266  {
267  if( m_grids[i].m_CmdId == aCommandId )
268  {
269  m_Grid = m_grids[i];
270  return m_grids[i].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
271  }
272  }
273 
274  m_Grid = m_grids[0];
275  return m_grids[0].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
276 }
277 
278 
279 void BASE_SCREEN::AddGrid( const GRID_TYPE& grid )
280 {
281  for( unsigned i = 0; i < m_grids.size(); i++ )
282  {
283  if( m_grids[i].m_Size == grid.m_Size && grid.m_CmdId != ID_POPUP_GRID_USER )
284  {
285  wxLogTrace( traceScreen, "Discarding duplicate grid size( %g, %g ).",
286  grid.m_Size.x, grid.m_Size.y );
287  return;
288  }
289 
290  if( m_grids[i].m_CmdId == grid.m_CmdId )
291  {
292  wxLogTrace( traceScreen, wxT( "Changing grid ID %d from size( %g, %g ) to " ) \
293  wxT( "size( %g, %g )." ),
294  grid.m_CmdId, m_grids[i].m_Size.x,
295  m_grids[i].m_Size.y, grid.m_Size.x, grid.m_Size.y );
296  m_grids[i].m_Size = grid.m_Size;
297  return;
298  }
299  }
300 
301  m_grids.push_back( grid );
302 }
303 
304 
305 void BASE_SCREEN::AddGrid( const wxRealPoint& size, int id )
306 {
307  GRID_TYPE grid;
308 
309  grid.m_Size = size;
310  grid.m_CmdId = id;
311  AddGrid( grid );
312 }
313 
314 
315 void BASE_SCREEN::AddGrid( const wxRealPoint& size, EDA_UNITS_T aUnit, int id )
316 {
317  wxRealPoint new_size;
318  GRID_TYPE new_grid;
319 
320  new_size.x = From_User_Unit( aUnit, size.x );
321  new_size.y = From_User_Unit( aUnit, size.y );
322  new_grid.m_CmdId = id;
323  new_grid.m_Size = new_size;
324 
325  AddGrid( new_grid );
326 }
327 
328 
330 {
331  wxCHECK_MSG( !m_grids.empty() && aIndex < m_grids.size(), m_Grid,
332  wxT( "Cannot get grid object outside the bounds of the grid list." ) );
333 
334  return m_grids[ aIndex ];
335 }
336 
337 
338 bool BASE_SCREEN::GridExists( int aCommandId )
339 {
340  // tests for grid command ID (not an index in grid list, but a wxID) exists in grid list.
341  for( unsigned i = 0; i < m_grids.size(); i++ )
342  {
343  if( m_grids[i].m_CmdId == aCommandId )
344  return true;
345  }
346 
347  return false;
348 }
349 
350 
351 wxPoint BASE_SCREEN::getNearestGridPosition( const wxPoint& aPosition,
352  const wxPoint& aGridOrigin, wxRealPoint* aGridSize ) const
353 {
354  wxPoint pt;
355  wxRealPoint gridSize;
356 
357  if( aGridSize )
358  gridSize = *aGridSize;
359  else
360  gridSize = GetGridSize();
361 
362  double offset = fmod( aGridOrigin.x, gridSize.x );
363  int x = KiROUND( (aPosition.x - offset) / gridSize.x );
364 
365  pt.x = KiROUND( x * gridSize.x + offset );
366 
367  offset = fmod( aGridOrigin.y, gridSize.y );
368 
369  int y = KiROUND( (aPosition.y - offset) / gridSize.y );
370  pt.y = KiROUND ( y * gridSize.y + offset );
371 
372  return pt;
373 }
374 
375 
376 wxPoint BASE_SCREEN::getCursorPosition( bool aOnGrid, const wxPoint& aGridOrigin,
377  wxRealPoint* aGridSize ) const
378 {
379  if( aOnGrid )
380  return getNearestGridPosition( m_crossHairPosition, aGridOrigin, aGridSize );
381 
382  return m_crossHairPosition;
383 }
384 
385 
387 {
388  wxPoint pos = m_crossHairPosition - m_DrawOrg;
389  double scalar = GetScalingFactor();
390 
391  pos.x = KiROUND( (double) pos.x * scalar );
392  pos.y = KiROUND( (double) pos.y * scalar );
393 
394  return pos;
395 }
396 
397 
398 void BASE_SCREEN::setCrossHairPosition( const wxPoint& aPosition, const wxPoint& aGridOrigin,
399  bool aSnapToGrid )
400 {
401  if( aSnapToGrid )
402  m_crossHairPosition = getNearestGridPosition( aPosition, aGridOrigin, NULL );
403  else
404  m_crossHairPosition = aPosition;
405 }
406 
407 
409 {
412 }
413 
414 
416 {
417  m_UndoList.PushCommand( aNewitem );
418 
419  // Delete the extra items, if count max reached
420  if( m_UndoRedoCountMax > 0 )
421  {
422  int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
423 
424  if( extraitems > 0 )
425  ClearUndoORRedoList( m_UndoList, extraitems );
426  }
427 }
428 
429 
431 {
432  m_RedoList.PushCommand( aNewitem );
433 
434  // Delete the extra items, if count max reached
435  if( m_UndoRedoCountMax > 0 )
436  {
437  int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
438 
439  if( extraitems > 0 )
440  ClearUndoORRedoList( m_RedoList, extraitems );
441  }
442 }
443 
444 
446 {
447  return m_UndoList.PopCommand();
448 }
449 
450 
452 {
453  return m_RedoList.PopCommand();
454 }
455 
456 
457 #if defined(DEBUG)
458 
459 void BASE_SCREEN::Show( int nestLevel, std::ostream& os ) const
460 {
461  // for now, make it look like XML, expand on this later.
462  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
463 
464  /* this class will eventually go away, but here's a place holder until then.
465  for( EDA_ITEM* item = m_drawList; item; item = item->Next() )
466  {
467  item->Show( nestLevel+1, os );
468  }
469  */
470 
471  NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
472 }
473 
474 #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'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