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;
57 
58  m_FlagModified = false; // Set when any change is made on board.
59  m_FlagSave = false; // Used in auto save set when an auto save is required.
60 }
61 
62 
63 void BASE_SCREEN::InitDataPoints( const wxSize& aPageSizeIU )
64 {
65  if( m_Center )
66  {
67  m_crossHairPosition.x = 0;
68  m_crossHairPosition.y = 0;
69 
70  m_DrawOrg.x = -aPageSizeIU.x / 2;
71  m_DrawOrg.y = -aPageSizeIU.y / 2;
72  }
73  else
74  {
75  m_crossHairPosition.x = aPageSizeIU.x / 2;
76  m_crossHairPosition.y = aPageSizeIU.y / 2;
77 
78  m_DrawOrg.x = 0;
79  m_DrawOrg.y = 0;
80  }
81 
82  m_LocalOrigin = { 0, 0 };
83 }
84 
85 
86 bool BASE_SCREEN::SetZoom( double iu_per_du )
87 {
88  if( iu_per_du == m_Zoom )
89  return false;
90 
91  wxLogTrace( traceScreen, "Zoom:%.16g 1/Zoom:%.16g", iu_per_du, 1/iu_per_du );
92 
93  if( iu_per_du < GetMinAllowedZoom() )
94  return false;
95 
96  if( iu_per_du > GetMaxAllowedZoom() )
97  return false;
98 
99  m_Zoom = iu_per_du;
100 
101  return true;
102 }
103 
104 
105 int BASE_SCREEN::BuildGridsChoiceList( wxArrayString& aGridsList, bool aMmFirst) const
106 {
107  wxString msg;
108  wxRealPoint curr_grid_size = GetGridSize();
109  int idx = -1;
110  int idx_usergrid = -1;
111 
112  for( size_t i = 0; i < GetGridCount(); i++ )
113  {
114  const GRID_TYPE& grid = m_grids[i];
115  double gridValueMils = To_User_Unit( INCHES, grid.m_Size.x ) * 1000;
116  double gridValue_mm = To_User_Unit( MILLIMETRES, grid.m_Size.x );
117 
118  if( grid.m_CmdId == ID_POPUP_GRID_USER )
119  {
120  if( aMmFirst )
121  msg.Printf( _( "User grid: %.4f mm (%.2f mils)" ),
122  gridValue_mm, gridValueMils );
123  else
124  msg.Printf( _( "User grid: %.2f mils (%.4f mm)" ),
125  gridValueMils, gridValue_mm );
126  idx_usergrid = i;
127  }
128  else
129  {
130  if( aMmFirst )
131  msg.Printf( _( "Grid: %.4f mm (%.2f mils)" ),
132  gridValue_mm, gridValueMils );
133  else
134  msg.Printf( _( "Grid: %.2f mils (%.4f mm)" ),
135  gridValueMils, gridValue_mm );
136  }
137 
138  aGridsList.Add( msg );
139 
140  if( curr_grid_size == grid.m_Size )
141  idx = i;
142  }
143 
144  if( idx < 0 )
145  idx = idx_usergrid;
146 
147  return idx;
148 }
149 
150 
151 int BASE_SCREEN::SetGrid( const wxRealPoint& size )
152 {
153  wxASSERT( !m_grids.empty() );
154 
155  GRID_TYPE nearest_grid = m_grids[0];
156  int gridIdx = 0;
157 
158  for( GRID_TYPE& grid : m_grids )
159  {
160  if( grid.m_Size == size )
161  {
162  m_Grid = grid;
163  return grid.m_CmdId - ID_POPUP_GRID_LEVEL_1000;
164  }
165 
166  // keep track of the nearest larger grid size, if the exact size is not found
167  if ( size.x < grid.m_Size.x )
168  {
169  gridIdx = grid.m_CmdId - ID_POPUP_GRID_LEVEL_1000;
170  nearest_grid = grid;
171  }
172  }
173 
174  m_Grid = nearest_grid;
175  return gridIdx;
176 }
177 
178 
179 int BASE_SCREEN::SetGrid( int aCommandId )
180 {
181  wxASSERT( !m_grids.empty() );
182 
183  for( GRID_TYPE& grid : m_grids )
184  {
185  if( grid.m_CmdId == aCommandId )
186  {
187  m_Grid = grid;
188  return grid.m_CmdId - ID_POPUP_GRID_LEVEL_1000;
189  }
190  }
191 
192  m_Grid = m_grids[0];
193  return m_grids[0].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
194 }
195 
196 
197 void BASE_SCREEN::AddGrid( const GRID_TYPE& aGrid )
198 {
199  for( GRID_TYPE& existing : m_grids )
200  {
201  if( existing.m_Size == aGrid.m_Size && aGrid.m_CmdId != ID_POPUP_GRID_USER )
202  {
203  wxLogTrace( traceScreen, "Discarding duplicate grid size( %g, %g ).",
204  aGrid.m_Size.x, aGrid.m_Size.y );
205  return;
206  }
207 
208  if( existing.m_CmdId == aGrid.m_CmdId )
209  {
210  wxLogTrace( traceScreen, wxT( "Changing grid ID %d from size( %g, %g ) to " ) \
211  wxT( "size( %g, %g )." ),
212  aGrid.m_CmdId, existing.m_Size.x,
213  existing.m_Size.y, aGrid.m_Size.x, aGrid.m_Size.y );
214  existing.m_Size = aGrid.m_Size;
215  return;
216  }
217  }
218 
219  m_grids.push_back( aGrid );
220 }
221 
222 
223 void BASE_SCREEN::AddGrid( const wxRealPoint& size, EDA_UNITS_T aUnit, int id )
224 {
225  wxRealPoint new_size;
226  GRID_TYPE new_grid;
227 
228  new_size.x = From_User_Unit( aUnit, size.x );
229  new_size.y = From_User_Unit( aUnit, size.y );
230  new_grid.m_CmdId = id;
231  new_grid.m_Size = new_size;
232 
233  AddGrid( new_grid );
234 }
235 
236 
238 {
239  wxCHECK_MSG( !m_grids.empty() && aIndex < m_grids.size(), m_Grid,
240  wxT( "Cannot get grid object outside the bounds of the grid list." ) );
241 
242  return m_grids[ aIndex ];
243 }
244 
245 
246 bool BASE_SCREEN::GridExists( int aCommandId )
247 {
248  // tests for grid command ID (not an index in grid list, but a wxID) exists in grid list.
249  for( GRID_TYPE& grid : m_grids)
250  {
251  if( grid.m_CmdId == aCommandId )
252  return true;
253  }
254 
255  return false;
256 }
257 
258 
259 wxPoint BASE_SCREEN::getNearestGridPosition( const wxPoint& aPosition,
260  const wxPoint& aGridOrigin ) const
261 {
262  wxPoint pt;
263  wxRealPoint gridSize = GetGridSize();
264 
265  double offset = fmod( aGridOrigin.x, gridSize.x );
266  int x = KiROUND( (aPosition.x - offset) / gridSize.x );
267 
268  pt.x = KiROUND( x * gridSize.x + offset );
269 
270  offset = fmod( aGridOrigin.y, gridSize.y );
271 
272  int y = KiROUND( (aPosition.y - offset) / gridSize.y );
273  pt.y = KiROUND ( y * gridSize.y + offset );
274 
275  return pt;
276 }
277 
278 
280 {
283 }
284 
285 
287 {
288  m_UndoList.PushCommand( aNewitem );
289 
290  // Delete the extra items, if count max reached
291  if( m_UndoRedoCountMax > 0 )
292  {
293  int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
294 
295  if( extraitems > 0 )
296  ClearUndoORRedoList( m_UndoList, extraitems );
297  }
298 }
299 
300 
302 {
303  m_RedoList.PushCommand( aNewitem );
304 
305  // Delete the extra items, if count max reached
306  if( m_UndoRedoCountMax > 0 )
307  {
308  int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
309 
310  if( extraitems > 0 )
311  ClearUndoORRedoList( m_RedoList, extraitems );
312  }
313 }
314 
315 
317 {
318  return m_UndoList.PopCommand();
319 }
320 
321 
323 {
324  return m_RedoList.PopCommand();
325 }
326 
327 
328 #if defined(DEBUG)
329 
330 void BASE_SCREEN::Show( int nestLevel, std::ostream& os ) const
331 {
332  // for now, make it look like XML, expand on this later.
333  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
334 
335  /* this class will eventually go away, but here's a place holder until then.
336  for( EDA_ITEM* item = m_drawList; item; item = item->Next() )
337  {
338  item->Show( nestLevel+1, os );
339  }
340  */
341 
342  NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
343 }
344 
345 #endif
double GetMinAllowedZoom() const
Function GetMinAllowedZoom returns the minimum allowed zoom factor, which was established as the firs...
Definition: base_screen.h:263
virtual void PushCommandToUndoList(PICKED_ITEMS_LIST *aItem)
Function PushCommandToUndoList add a command to undo in undo list delete the very old commands when t...
const wxRealPoint & GetGridSize() const
Return the grid size of the currently selected grid.
Definition: base_screen.h:279
int m_UndoRedoCountMax
undo/Redo command Max depth
Definition: base_screen.h:79
int m_ScreenNumber
Definition: base_screen.h:135
bool m_FlagModified
Indicates current drawing has been modified.
Definition: base_screen.h:77
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:361
wxPoint m_crossHairPosition
The cross hair position in logical (drawing) units.
Definition: base_screen.h:86
const wxChar *const traceScreen
Flag to enable debug output of BASE_SCREEN and it's derivatives.
void AddGrid(const GRID_TYPE &aGrid)
int GetUndoCommandCount() const
Definition: base_screen.h:201
GRID_TYPE m_Grid
Current grid selection.
Definition: base_screen.h:89
const GRID_TYPE & GetGrid() const
Return the grid object of the currently selected grid.
Definition: base_screen.h:286
#define DEFAULT_MAX_UNDO_ITEMS
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:289
virtual void ClearUndoORRedoList(UNDO_REDO_CONTAINER &aList, int aItemCount=-1)=0
Function ClearUndoORRedoList (virtual).
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
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:109
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:63
bool m_Center
Center on screen.
Definition: base_screen.h:121
UNDO_REDO_CONTAINER m_UndoList
Objects list for the undo command (old data)
Definition: base_screen.h:132
bool m_Initialized
Definition: base_screen.h:129
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
Definition: common.h:134
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...
wxRealPoint m_Size
Definition: base_screen.h:47
wxLogTrace helper definitions.
virtual bool SetZoom(double iu_per_du)
Function SetZoom adjusts the current zoom factor.
Definition: base_screen.cpp:86
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
#define _(s)
bool m_IsPrinting
Definition: base_screen.h:139
UNDO_REDO_CONTAINER m_RedoList
Objects list for the redo command (old data)
Definition: base_screen.h:133
double GetMaxAllowedZoom() const
Function GetMaxAllowedZoom returns the maximum allowed zoom factor, which was established as the last...
Definition: base_screen.h:256
GRIDS m_grids
List of valid grid sizes.
Definition: base_screen.h:88
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:43
BASE_SCREEN(KICAD_T aType=SCREEN_T)
Definition: base_screen.cpp:45
size_t i
Definition: json11.cpp:649
size_t GetGridCount() const
Function GetGridCount().
Definition: base_screen.h:324
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:112
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:163
The common library.
bool m_FlagSave
Indicates automatic file save.
Definition: base_screen.h:78
int m_NumberOfScreens
Definition: base_screen.h:136
wxPoint getNearestGridPosition(const wxPoint &aPosition, const wxPoint &aGridOrigin) const
Function getNearestGridPosition returns the nearest aGridSize location to aPosition.
double m_Zoom
Current zoom coefficient.
Definition: base_screen.h:90
int SetGrid(const wxRealPoint &size)
set the current grid size m_Grid.
int m_CmdId
Definition: base_screen.h:46
BASE_SCREEN class implementation.
int GetRedoCommandCount() const
Definition: base_screen.h:206
EDA_UNITS_T
Definition: common.h:133
VECTOR2D m_LocalOrigin
Relative Screen cursor coordinate (on grid) in user units.
Definition: base_screen.h:114
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:114