2011-10-15 13:25:57 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2012-06-09 09:38:58 +00:00
|
|
|
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
|
|
|
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
|
|
|
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
|
|
|
|
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
2011-10-15 13:25:57 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-10-15 13:25:57 +00:00
|
|
|
/**
|
|
|
|
* @file base_screen.cpp
|
|
|
|
* @brief BASE_SCREEN object implementation.
|
|
|
|
*/
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <fctsys.h>
|
|
|
|
#include <common.h>
|
|
|
|
#include <base_struct.h>
|
|
|
|
#include <class_base_screen.h>
|
|
|
|
#include <id.h>
|
2012-04-16 23:31:29 +00:00
|
|
|
#include <base_units.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2013-07-19 18:27:22 +00:00
|
|
|
wxString BASE_SCREEN::m_PageLayoutDescrFileName; // the name of the page layout descr file.
|
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
BASE_SCREEN::BASE_SCREEN( KICAD_T aType ) :
|
|
|
|
EDA_ITEM( aType )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-12-31 05:44:00 +00:00
|
|
|
m_UndoRedoCountMax = 10; // undo/Redo command Max depth, 10 is a reasonable value
|
2011-11-08 16:37:25 +00:00
|
|
|
m_FirstRedraw = true;
|
2008-12-05 16:03:05 +00:00
|
|
|
m_ScreenNumber = 1;
|
2012-05-27 00:19:12 +00:00
|
|
|
m_NumberOfScreens = 1; // Hierarchy: Root: ScreenNumber = 1
|
2011-10-15 13:25:57 +00:00
|
|
|
m_Zoom = 32.0;
|
2011-12-31 05:44:00 +00:00
|
|
|
m_Grid.m_Size = wxRealPoint( 50, 50 ); // Default grid size
|
2009-10-14 19:43:31 +00:00
|
|
|
m_Grid.m_Id = ID_POPUP_GRID_LEVEL_50;
|
2008-12-05 16:03:05 +00:00
|
|
|
m_Center = true;
|
2009-04-05 20:49:15 +00:00
|
|
|
m_IsPrinting = false;
|
2010-02-14 18:14:33 +00:00
|
|
|
m_ScrollPixelsPerUnitX = 1;
|
|
|
|
m_ScrollPixelsPerUnitY = 1;
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
m_FlagModified = false; // Set when any change is made on board.
|
|
|
|
m_FlagSave = false; // Used in auto save set when an auto save is required.
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
SetCurItem( NULL );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
BASE_SCREEN::~BASE_SCREEN()
|
2011-12-22 21:57:50 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
void BASE_SCREEN::InitDataPoints( const wxSize& aPageSizeIU )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
if( m_Center )
|
|
|
|
{
|
2012-04-23 21:56:26 +00:00
|
|
|
m_crossHairPosition.x = 0;
|
|
|
|
m_crossHairPosition.y = 0;
|
2011-12-22 21:57:50 +00:00
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
m_DrawOrg.x = -aPageSizeIU.x / 2;
|
|
|
|
m_DrawOrg.y = -aPageSizeIU.y / 2;
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-12-31 05:44:00 +00:00
|
|
|
m_crossHairPosition.x = aPageSizeIU.x / 2;
|
|
|
|
m_crossHairPosition.y = aPageSizeIU.y / 2;
|
2012-04-23 21:56:26 +00:00
|
|
|
|
|
|
|
m_DrawOrg.x = 0;
|
|
|
|
m_DrawOrg.y = 0;
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
2010-03-20 19:57:59 +00:00
|
|
|
m_O_Curseur.x = m_O_Curseur.y = 0;
|
2008-12-05 16:03:05 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 21:07:00 +00:00
|
|
|
|
2011-04-01 17:10:16 +00:00
|
|
|
double BASE_SCREEN::GetScalingFactor() const
|
|
|
|
{
|
2011-07-05 12:46:14 +00:00
|
|
|
double scale = 1.0 / GetZoom();
|
2011-04-01 17:10:16 +00:00
|
|
|
return scale;
|
|
|
|
}
|
|
|
|
|
2011-11-07 19:04:24 +00:00
|
|
|
|
2012-04-17 14:18:14 +00:00
|
|
|
void BASE_SCREEN::SetScalingFactor( double aScale )
|
2009-02-02 12:12:18 +00:00
|
|
|
{
|
|
|
|
// Limit zoom to max and min allowed values:
|
2012-05-06 20:10:43 +00:00
|
|
|
double zoom = Clamp( GetMinAllowedZoom(), aScale, GetMaxAllowedZoom() );
|
2009-02-02 12:12:18 +00:00
|
|
|
|
|
|
|
SetZoom( zoom );
|
|
|
|
}
|
|
|
|
|
2011-11-07 19:04:24 +00:00
|
|
|
|
2009-02-11 19:39:55 +00:00
|
|
|
bool BASE_SCREEN::SetFirstZoom()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-05-06 20:10:43 +00:00
|
|
|
return SetZoom( GetMinAllowedZoom() );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-06 20:10:43 +00:00
|
|
|
bool BASE_SCREEN::SetLastZoom()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-05-06 20:10:43 +00:00
|
|
|
return SetZoom( GetMaxAllowedZoom() );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-05-06 20:10:43 +00:00
|
|
|
bool BASE_SCREEN::SetZoom( double iu_per_du )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-05-06 20:10:43 +00:00
|
|
|
if( iu_per_du == m_Zoom )
|
|
|
|
return false;
|
|
|
|
|
2012-08-15 17:55:48 +00:00
|
|
|
//wxLogDebug( "Zoom:%.16g 1/Zoom:%.16g", iu_per_du, 1/iu_per_du );
|
2012-05-06 20:10:43 +00:00
|
|
|
|
|
|
|
if( iu_per_du < GetMinAllowedZoom() )
|
2009-02-11 19:39:55 +00:00
|
|
|
return false;
|
|
|
|
|
2012-05-06 20:10:43 +00:00
|
|
|
if( iu_per_du > GetMaxAllowedZoom() )
|
|
|
|
return false;
|
2012-04-23 21:56:26 +00:00
|
|
|
|
2012-05-06 20:10:43 +00:00
|
|
|
m_Zoom = iu_per_du;
|
2009-01-29 14:26:20 +00:00
|
|
|
|
2009-02-11 19:39:55 +00:00
|
|
|
return true;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-11 19:39:55 +00:00
|
|
|
bool BASE_SCREEN::SetNextZoom()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-05-06 20:10:43 +00:00
|
|
|
for( unsigned i=0; i < m_ZoomList.size(); ++i )
|
2009-01-29 14:26:20 +00:00
|
|
|
{
|
|
|
|
if( m_Zoom < m_ZoomList[i] )
|
|
|
|
{
|
2011-12-31 05:44:00 +00:00
|
|
|
SetZoom( m_ZoomList[i] );
|
2009-02-11 19:39:55 +00:00
|
|
|
return true;
|
2009-01-29 14:26:20 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-11 19:39:55 +00:00
|
|
|
|
|
|
|
return false;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-11 19:39:55 +00:00
|
|
|
bool BASE_SCREEN::SetPreviousZoom()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-05-06 20:10:43 +00:00
|
|
|
for( unsigned i = m_ZoomList.size(); i != 0; --i )
|
2009-01-29 14:26:20 +00:00
|
|
|
{
|
|
|
|
if( m_Zoom > m_ZoomList[i - 1] )
|
|
|
|
{
|
2011-12-31 05:44:00 +00:00
|
|
|
SetZoom( m_ZoomList[i - 1] );
|
2009-02-11 19:39:55 +00:00
|
|
|
return true;
|
2009-01-29 14:26:20 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-11 19:39:55 +00:00
|
|
|
|
|
|
|
return false;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
void BASE_SCREEN::SetGridList( GRIDS& gridlist )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
if( !m_grids.empty() )
|
|
|
|
m_grids.clear();
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
m_grids = gridlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BASE_SCREEN::GetGrids( GRIDS& aList )
|
|
|
|
{
|
|
|
|
for( size_t i = 0; i < m_grids.size(); i++ )
|
|
|
|
aList.push_back( m_grids[ i ] );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-02-07 08:33:25 +00:00
|
|
|
void BASE_SCREEN::SetGrid( const wxRealPoint& size )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
wxASSERT( !m_grids.empty() );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
GRID_TYPE nearest_grid = m_grids[0];
|
2009-10-14 19:43:31 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
for( unsigned i = 0; i < m_grids.size(); i++ )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
if( m_grids[i].m_Size == size )
|
2008-12-05 16:03:05 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
m_Grid = m_grids[i];
|
2008-12-05 16:03:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-02-07 08:33:25 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
// keep track of the nearest larger grid size, if the exact size is not found
|
2010-12-08 20:12:46 +00:00
|
|
|
if ( size.x < m_grids[i].m_Size.x )
|
|
|
|
nearest_grid = m_grids[i];
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2009-02-06 11:45:35 +00:00
|
|
|
m_Grid = nearest_grid;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-05-21 17:42:42 +00:00
|
|
|
wxLogWarning( wxT( "Grid size( %f, %f ) not in grid list, falling back " ) \
|
|
|
|
wxT( "to grid size( %f, %f )." ),
|
2009-10-14 19:43:31 +00:00
|
|
|
size.x, size.y, m_Grid.m_Size.x, m_Grid.m_Size.y );
|
2008-12-05 16:03:05 +00:00
|
|
|
}
|
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
|
2008-12-05 16:03:05 +00:00
|
|
|
void BASE_SCREEN::SetGrid( int id )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
wxASSERT( !m_grids.empty() );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
for( unsigned i = 0; i < m_grids.size(); i++ )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
if( m_grids[i].m_Id == id )
|
2008-12-05 16:03:05 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
m_Grid = m_grids[i];
|
2008-12-05 16:03:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
m_Grid = m_grids[0];
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2009-05-21 17:42:42 +00:00
|
|
|
wxLogWarning( wxT( "Grid ID %d not in grid list, falling back to " ) \
|
2009-10-14 19:43:31 +00:00
|
|
|
wxT( "grid size( %g, %g )." ), id, m_Grid.m_Size.x,
|
|
|
|
m_Grid.m_Size.y );
|
2008-12-05 16:03:05 +00:00
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
|
2008-12-05 16:03:05 +00:00
|
|
|
void BASE_SCREEN::AddGrid( const GRID_TYPE& grid )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-04-23 21:56:26 +00:00
|
|
|
for( unsigned i = 0; i < m_grids.size(); i++ )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
if( m_grids[i].m_Size == grid.m_Size && grid.m_Id != ID_POPUP_GRID_USER )
|
2008-12-05 16:03:05 +00:00
|
|
|
{
|
2009-02-07 14:13:16 +00:00
|
|
|
wxLogDebug( wxT( "Discarding duplicate grid size( %g, %g )." ),
|
2008-12-05 16:03:05 +00:00
|
|
|
grid.m_Size.x, grid.m_Size.y );
|
|
|
|
return;
|
|
|
|
}
|
2010-12-08 20:12:46 +00:00
|
|
|
|
|
|
|
if( m_grids[i].m_Id == grid.m_Id )
|
2008-12-05 16:03:05 +00:00
|
|
|
{
|
2009-05-21 17:42:42 +00:00
|
|
|
wxLogDebug( wxT( "Changing grid ID %d from size( %g, %g ) to " ) \
|
|
|
|
wxT( "size( %g, %g )." ),
|
2010-12-08 20:12:46 +00:00
|
|
|
grid.m_Id, m_grids[i].m_Size.x,
|
|
|
|
m_grids[i].m_Size.y, grid.m_Size.x, grid.m_Size.y );
|
|
|
|
m_grids[i].m_Size = grid.m_Size;
|
2008-12-05 16:03:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
m_grids.push_back( grid );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
|
2009-02-07 08:33:25 +00:00
|
|
|
void BASE_SCREEN::AddGrid( const wxRealPoint& size, int id )
|
2008-12-05 16:03:05 +00:00
|
|
|
{
|
|
|
|
GRID_TYPE grid;
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2008-12-05 16:03:05 +00:00
|
|
|
grid.m_Size = size;
|
|
|
|
grid.m_Id = id;
|
|
|
|
AddGrid( grid );
|
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
|
2011-09-06 19:42:46 +00:00
|
|
|
void BASE_SCREEN::AddGrid( const wxRealPoint& size, EDA_UNITS_T aUnit, int id )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-02-07 08:33:25 +00:00
|
|
|
wxRealPoint new_size;
|
2008-12-05 16:03:05 +00:00
|
|
|
GRID_TYPE new_grid;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-04-16 23:31:29 +00:00
|
|
|
new_size.x = From_User_Unit( aUnit, size.x );
|
|
|
|
new_size.y = From_User_Unit( aUnit, size.y );
|
2008-12-05 16:03:05 +00:00
|
|
|
new_grid.m_Id = id;
|
|
|
|
new_grid.m_Size = new_size;
|
2012-04-16 23:31:29 +00:00
|
|
|
|
2008-12-05 16:03:05 +00:00
|
|
|
AddGrid( new_grid );
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2009-10-14 19:43:31 +00:00
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
GRID_TYPE& BASE_SCREEN::GetGrid( size_t aIndex )
|
|
|
|
{
|
|
|
|
wxCHECK_MSG( !m_grids.empty() && aIndex < m_grids.size(), m_Grid,
|
|
|
|
wxT( "Cannot get grid object outside the bounds of the grid list." ) );
|
|
|
|
|
|
|
|
return m_grids[ aIndex ];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-09 09:38:58 +00:00
|
|
|
wxPoint BASE_SCREEN::GetNearestGridPosition( const wxPoint& aPosition,
|
2012-05-27 00:19:12 +00:00
|
|
|
wxRealPoint* aGridSize ) const
|
2011-02-02 19:01:21 +00:00
|
|
|
{
|
|
|
|
wxPoint pt;
|
|
|
|
wxRealPoint gridSize;
|
|
|
|
|
|
|
|
if( aGridSize )
|
|
|
|
gridSize = *aGridSize;
|
|
|
|
else
|
|
|
|
gridSize = GetGridSize();
|
|
|
|
|
|
|
|
wxPoint gridOrigin = m_GridOrigin;
|
|
|
|
|
|
|
|
double offset = fmod( gridOrigin.x, gridSize.x );
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
int x = KiROUND( (aPosition.x - offset) / gridSize.x );
|
|
|
|
pt.x = KiROUND( x * gridSize.x + offset );
|
2011-02-02 19:01:21 +00:00
|
|
|
|
|
|
|
offset = fmod( gridOrigin.y, gridSize.y );
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
int y = KiROUND( (aPosition.y - offset) / gridSize.y );
|
|
|
|
pt.y = KiROUND ( y * gridSize.y + offset );
|
2011-02-02 19:01:21 +00:00
|
|
|
|
|
|
|
return pt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-27 00:19:12 +00:00
|
|
|
wxPoint BASE_SCREEN::GetCursorPosition( bool aOnGrid, wxRealPoint* aGridSize ) const
|
2011-02-02 19:01:21 +00:00
|
|
|
{
|
|
|
|
if( aOnGrid )
|
2011-02-11 20:48:13 +00:00
|
|
|
return GetNearestGridPosition( m_crossHairPosition, aGridSize );
|
2011-02-02 19:01:21 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
return m_crossHairPosition;
|
2011-02-02 19:01:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
wxPoint BASE_SCREEN::GetCrossHairScreenPosition() const
|
|
|
|
{
|
2011-02-11 20:48:13 +00:00
|
|
|
wxPoint pos = m_crossHairPosition - m_DrawOrg;
|
2011-02-09 19:47:33 +00:00
|
|
|
double scalar = GetScalingFactor();
|
|
|
|
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
pos.x = KiROUND( (double) pos.x * scalar );
|
|
|
|
pos.y = KiROUND( (double) pos.y * scalar );
|
2011-02-09 19:47:33 +00:00
|
|
|
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2011-11-07 19:04:24 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
void BASE_SCREEN::SetCrossHairPosition( const wxPoint& aPosition, bool aSnapToGrid )
|
|
|
|
{
|
|
|
|
if( aSnapToGrid )
|
|
|
|
m_crossHairPosition = GetNearestGridPosition( aPosition );
|
|
|
|
else
|
|
|
|
m_crossHairPosition = aPosition;
|
|
|
|
}
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
void BASE_SCREEN::ClearUndoRedoList()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-07-29 13:10:36 +00:00
|
|
|
ClearUndoORRedoList( m_UndoList );
|
|
|
|
ClearUndoORRedoList( m_RedoList );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
void BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aNewitem )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-07-29 13:10:36 +00:00
|
|
|
m_UndoList.PushCommand( aNewitem );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
// Delete the extra items, if count max reached
|
2009-07-29 13:10:36 +00:00
|
|
|
int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2009-07-29 13:10:36 +00:00
|
|
|
if( extraitems > 0 ) // Delete the extra items
|
|
|
|
ClearUndoORRedoList( m_UndoList, extraitems );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-07-23 15:37:00 +00:00
|
|
|
void BASE_SCREEN::PushCommandToRedoList( PICKED_ITEMS_LIST* aNewitem )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-07-29 13:10:36 +00:00
|
|
|
m_RedoList.PushCommand( aNewitem );
|
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
// Delete the extra items, if count max reached
|
2009-07-29 13:10:36 +00:00
|
|
|
int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2009-07-29 13:10:36 +00:00
|
|
|
if( extraitems > 0 ) // Delete the extra items
|
|
|
|
ClearUndoORRedoList( m_RedoList, extraitems );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-07-23 15:37:00 +00:00
|
|
|
PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromUndoList( )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-07-23 15:37:00 +00:00
|
|
|
return m_UndoList.PopCommand( );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-07-23 15:37:00 +00:00
|
|
|
PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromRedoList( )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-07-23 15:37:00 +00:00
|
|
|
return m_RedoList.PopCommand( );
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
2007-09-20 21:06:49 +00:00
|
|
|
|
|
|
|
#if defined(DEBUG)
|
2011-10-15 13:25:57 +00:00
|
|
|
|
2011-12-14 17:25:42 +00:00
|
|
|
void BASE_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
2010-11-03 14:13:15 +00:00
|
|
|
{
|
2007-09-20 21:06:49 +00:00
|
|
|
// for now, make it look like XML, expand on this later.
|
2010-12-08 20:12:46 +00:00
|
|
|
NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
|
2010-11-03 14:13:15 +00:00
|
|
|
|
2012-01-05 16:30:58 +00:00
|
|
|
/* this class will eventually go away, but here's a place holder until then.
|
|
|
|
for( EDA_ITEM* item = m_drawList; item; item = item->Next() )
|
2007-09-20 21:06:49 +00:00
|
|
|
{
|
|
|
|
item->Show( nestLevel+1, os );
|
|
|
|
}
|
2012-01-05 16:30:58 +00:00
|
|
|
*/
|
2010-11-03 14:13:15 +00:00
|
|
|
|
2007-09-20 21:06:49 +00:00
|
|
|
NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
|
2010-11-03 14:13:15 +00:00
|
|
|
}
|
|
|
|
|
2007-09-20 21:06:49 +00:00
|
|
|
#endif
|