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 
33 #include <base_screen.h>
34 #include <base_struct.h>
35 #include <base_units.h>
36 #include <common.h>
37 #include <fctsys.h>
38 #include <id.h>
39 #include <math/util.h> // for KiROUND
40 #include <macros.h>
41 #include <trace_helpers.h>
42 
43 
44 wxString BASE_SCREEN::m_PageLayoutDescrFileName; // the name of the page layout descr file.
45 
46 
48  EDA_ITEM( aType )
49 {
51  m_Initialized = false;
52  m_ScreenNumber = 1;
53  m_NumberOfScreens = 1; // Hierarchy: Root: ScreenNumber = 1
54  m_Zoom = 32.0;
55  m_Grid.m_Size = wxRealPoint( 50, 50 ); // Default grid size
57  m_Center = true;
58  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 
64 
65 void BASE_SCREEN::InitDataPoints( const wxSize& aPageSizeIU )
66 {
67  if( m_Center )
68  {
71 
72  m_DrawOrg.x = -aPageSizeIU.x / 2;
73  m_DrawOrg.y = -aPageSizeIU.y / 2;
74  }
75  else
76  {
77  m_crossHairPosition.x = aPageSizeIU.x / 2;
78  m_crossHairPosition.y = aPageSizeIU.y / 2;
79 
80  m_DrawOrg.x = 0;
81  m_DrawOrg.y = 0;
82  }
83 
84  m_LocalOrigin = { 0, 0 };
85 }
86 
87 
88 bool BASE_SCREEN::SetZoom( double iu_per_du )
89 {
90  if( iu_per_du == m_Zoom )
91  return false;
92 
93  wxLogTrace( traceScreen, "Zoom:%.16g 1/Zoom:%.16g", iu_per_du, 1/iu_per_du );
94 
95  if( iu_per_du < GetMinAllowedZoom() )
96  return false;
97 
98  if( iu_per_du > GetMaxAllowedZoom() )
99  return false;
100 
101  m_Zoom = iu_per_du;
102 
103  return true;
104 }
105 
106 
107 int BASE_SCREEN::BuildGridsChoiceList( wxArrayString& aGridsList, bool aMmFirst) const
108 {
109  wxString msg;
110  wxRealPoint curr_grid_size = GetGridSize();
111  int idx = -1;
112  int idx_usergrid = -1;
113 
114  for( size_t i = 0; i < GetGridCount(); i++ )
115  {
116  const GRID_TYPE& grid = m_grids[i];
117  double gridValueMils = To_User_Unit( EDA_UNITS::INCHES, grid.m_Size.x ) * 1000;
118  double gridValue_mm = To_User_Unit( EDA_UNITS::MILLIMETRES, grid.m_Size.x );
119 
120  if( grid.m_CmdId == ID_POPUP_GRID_USER )
121  {
122  if( aMmFirst )
123  msg.Printf( _( "User grid: %.4f mm (%.2f mils)" ),
124  gridValue_mm, gridValueMils );
125  else
126  msg.Printf( _( "User grid: %.2f mils (%.4f mm)" ),
127  gridValueMils, gridValue_mm );
128  idx_usergrid = i;
129  }
130  else
131  {
132  if( aMmFirst )
133  msg.Printf( _( "Grid: %.4f mm (%.2f mils)" ),
134  gridValue_mm, gridValueMils );
135  else
136  msg.Printf( _( "Grid: %.2f mils (%.4f mm)" ),
137  gridValueMils, gridValue_mm );
138  }
139 
140  aGridsList.Add( msg );
141 
142  if( curr_grid_size == grid.m_Size )
143  idx = i;
144  }
145 
146  if( idx < 0 )
147  idx = idx_usergrid;
148 
149  return idx;
150 }
151 
152 
153 int BASE_SCREEN::SetGrid( const wxRealPoint& size )
154 {
155  wxASSERT( !m_grids.empty() );
156 
157  GRID_TYPE nearest_grid = m_grids[0];
158  int gridIdx = 0;
159 
160  for( GRID_TYPE& grid : m_grids )
161  {
162  if( grid.m_Size == size )
163  {
164  m_Grid = grid;
165  return grid.m_CmdId - ID_POPUP_GRID_LEVEL_1000;
166  }
167 
168  // keep track of the nearest larger grid size, if the exact size is not found
169  if ( size.x < grid.m_Size.x )
170  {
171  gridIdx = grid.m_CmdId - ID_POPUP_GRID_LEVEL_1000;
172  nearest_grid = grid;
173  }
174  }
175 
176  m_Grid = nearest_grid;
177  return gridIdx;
178 }
179 
180 
181 int BASE_SCREEN::SetGrid( int aCommandId )
182 {
183  wxASSERT( !m_grids.empty() );
184 
185  for( GRID_TYPE& grid : m_grids )
186  {
187  if( grid.m_CmdId == aCommandId )
188  {
189  m_Grid = grid;
190  return grid.m_CmdId - ID_POPUP_GRID_LEVEL_1000;
191  }
192  }
193 
194  m_Grid = m_grids[0];
195  return m_grids[0].m_CmdId - ID_POPUP_GRID_LEVEL_1000;
196 }
197 
198 
199 void BASE_SCREEN::AddGrid( const GRID_TYPE& aGrid )
200 {
201  for( GRID_TYPE& existing : m_grids )
202  {
203  if( existing.m_Size == aGrid.m_Size && aGrid.m_CmdId != ID_POPUP_GRID_USER )
204  {
205  wxLogTrace( traceScreen, "Discarding duplicate grid size( %g, %g ).",
206  aGrid.m_Size.x, aGrid.m_Size.y );
207  return;
208  }
209 
210  if( existing.m_CmdId == aGrid.m_CmdId )
211  {
212  wxLogTrace( traceScreen, wxT( "Changing grid ID %d from size( %g, %g ) to " ) \
213  wxT( "size( %g, %g )." ),
214  aGrid.m_CmdId, existing.m_Size.x,
215  existing.m_Size.y, aGrid.m_Size.x, aGrid.m_Size.y );
216  existing.m_Size = aGrid.m_Size;
217  return;
218  }
219  }
220 
221  m_grids.push_back( aGrid );
222 }
223 
224 
225 void BASE_SCREEN::AddGrid( const wxRealPoint& size, EDA_UNITS aUnit, int id )
226 {
227  wxRealPoint new_size;
228  GRID_TYPE new_grid;
229 
230  new_size.x = From_User_Unit( aUnit, size.x );
231  new_size.y = From_User_Unit( aUnit, size.y );
232  new_grid.m_CmdId = id;
233  new_grid.m_Size = new_size;
234 
235  AddGrid( new_grid );
236 }
237 
238 
240 {
241  wxCHECK_MSG( !m_grids.empty() && aIndex < m_grids.size(), m_Grid,
242  wxT( "Cannot get grid object outside the bounds of the grid list." ) );
243 
244  return m_grids[ aIndex ];
245 }
246 
247 
248 bool BASE_SCREEN::GridExists( int aCommandId )
249 {
250  // tests for grid command ID (not an index in grid list, but a wxID) exists in grid list.
251  for( GRID_TYPE& grid : m_grids)
252  {
253  if( grid.m_CmdId == aCommandId )
254  return true;
255  }
256 
257  return false;
258 }
259 
260 
262  const wxPoint& aGridOrigin ) const
263 {
264  wxPoint pt;
265  wxRealPoint gridSize = GetGridSize();
266 
267  double offset = fmod( aGridOrigin.x, gridSize.x );
268  int x = KiROUND( (aPosition.x - offset) / gridSize.x );
269 
270  pt.x = KiROUND( x * gridSize.x + offset );
271 
272  offset = fmod( aGridOrigin.y, gridSize.y );
273 
274  int y = KiROUND( (aPosition.y - offset) / gridSize.y );
275  pt.y = KiROUND ( y * gridSize.y + offset );
276 
277  return pt;
278 }
279 
280 
282 {
285 }
286 
287 
289 {
290  m_UndoList.PushCommand( aNewitem );
291 
292  // Delete the extra items, if count max reached
293  if( m_UndoRedoCountMax > 0 )
294  {
295  int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
296 
297  if( extraitems > 0 )
298  ClearUndoORRedoList( m_UndoList, extraitems );
299  }
300 }
301 
302 
304 {
305  m_RedoList.PushCommand( aNewitem );
306 
307  // Delete the extra items, if count max reached
308  if( m_UndoRedoCountMax > 0 )
309  {
310  int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
311 
312  if( extraitems > 0 )
313  ClearUndoORRedoList( m_RedoList, extraitems );
314  }
315 }
316 
317 
319 {
320  return m_UndoList.PopCommand();
321 }
322 
323 
325 {
326  return m_RedoList.PopCommand();
327 }
328 
329 
330 #if defined(DEBUG)
331 
332 void BASE_SCREEN::Show( int nestLevel, std::ostream& os ) const
333 {
334  // for now, make it look like XML, expand on this later.
335  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
336 
337  /* this class will eventually go away, but here's a place holder until then.
338  for( EDA_ITEM* item = m_drawList; item; item = item->Next() )
339  {
340  item->Show( nestLevel+1, os );
341  }
342  */
343 
344  NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
345 }
346 
347 #endif
double GetMinAllowedZoom() const
Function GetMinAllowedZoom returns the minimum allowed zoom factor, which was established as the firs...
Definition: base_screen.h:263
double To_User_Unit(EDA_UNITS 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:95
EDA_UNITS
Definition: common.h:184
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
double From_User_Unit(EDA_UNITS 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:306
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
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:65
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
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:88
PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
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 ...
GRID_TYPE is for grid arrays.
Definition: base_screen.h:43
#define _(s)
Definition: 3d_actions.cpp:33
BASE_SCREEN(KICAD_T aType=SCREEN_T)
Definition: base_screen.cpp:47
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
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:166
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
VECTOR2D m_LocalOrigin
Relative Screen cursor coordinate (on grid) in user units.
Definition: base_screen.h:114