2011-10-13 19:56:32 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2016-03-13 15:39:18 +00:00
|
|
|
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
2015-02-18 09:13:17 +00:00
|
|
|
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
|
|
|
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
|
2016-03-13 15:39:18 +00:00
|
|
|
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
2011-10-13 19:56:32 +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
|
|
|
|
*/
|
|
|
|
|
2011-09-23 13:57:12 +00:00
|
|
|
/**
|
|
|
|
* @file class_module.cpp
|
|
|
|
* @brief MODULE class implementation.
|
|
|
|
*/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <fctsys.h>
|
|
|
|
#include <gr_basic.h>
|
|
|
|
#include <wxstruct.h>
|
|
|
|
#include <plot_common.h>
|
|
|
|
#include <class_drawpanel.h>
|
|
|
|
#include <trigo.h>
|
|
|
|
#include <confirm.h>
|
|
|
|
#include <kicad_string.h>
|
|
|
|
#include <pcbnew.h>
|
|
|
|
#include <colors_selection.h>
|
|
|
|
#include <richio.h>
|
|
|
|
#include <filter_reader.h>
|
|
|
|
#include <macros.h>
|
|
|
|
#include <3d_struct.h>
|
2013-01-12 17:32:24 +00:00
|
|
|
#include <msgpanel.h>
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <class_board.h>
|
|
|
|
#include <class_edge_mod.h>
|
|
|
|
#include <class_module.h>
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
2008-02-19 00:30:10 +00:00
|
|
|
MODULE::MODULE( BOARD* parent ) :
|
2013-06-23 19:18:33 +00:00
|
|
|
BOARD_ITEM( (BOARD_ITEM*) parent, PCB_MODULE_T ),
|
|
|
|
m_initial_comments( 0 )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2007-08-06 02:02:39 +00:00
|
|
|
m_Attributs = MOD_DEFAULT;
|
2014-06-24 16:17:18 +00:00
|
|
|
m_Layer = F_Cu;
|
2007-08-06 02:02:39 +00:00
|
|
|
m_Orient = 0;
|
2015-02-17 23:58:14 +00:00
|
|
|
m_ModuleStatus = MODULE_PADS_LOCKED;
|
2015-03-23 08:28:12 +00:00
|
|
|
m_arflag = 0;
|
2007-08-06 02:02:39 +00:00
|
|
|
m_CntRot90 = m_CntRot180 = 0;
|
2010-07-11 16:24:44 +00:00
|
|
|
m_Surface = 0.0;
|
2009-11-04 19:08:08 +00:00
|
|
|
m_Link = 0;
|
2015-03-12 17:43:39 +00:00
|
|
|
m_LastEditTime = 0;
|
2009-11-04 19:08:08 +00:00
|
|
|
m_LocalClearance = 0;
|
|
|
|
m_LocalSolderMaskMargin = 0;
|
|
|
|
m_LocalSolderPasteMargin = 0;
|
|
|
|
m_LocalSolderPasteMarginRatio = 0.0;
|
2015-08-18 14:19:17 +00:00
|
|
|
m_ZoneConnection = PAD_ZONE_CONN_INHERITED; // Use zone setting by default
|
2015-02-18 09:13:17 +00:00
|
|
|
m_ThermalWidth = 0; // Use zone setting by default
|
|
|
|
m_ThermalGap = 0; // Use zone setting by default
|
2008-11-24 06:53:43 +00:00
|
|
|
|
2014-09-10 15:18:42 +00:00
|
|
|
// These are special and mandatory text fields
|
2013-04-07 11:55:18 +00:00
|
|
|
m_Reference = new TEXTE_MODULE( this, TEXTE_MODULE::TEXT_is_REFERENCE );
|
|
|
|
m_Value = new TEXTE_MODULE( this, TEXTE_MODULE::TEXT_is_VALUE );
|
2008-11-24 06:53:43 +00:00
|
|
|
|
2009-08-04 18:21:32 +00:00
|
|
|
// Reserve one void 3D entry, to avoid problems with void list
|
|
|
|
m_3D_Drawings.PushBack( new S3D_MASTER( this ) );
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2012-01-14 19:50:32 +00:00
|
|
|
MODULE::MODULE( const MODULE& aModule ) :
|
2013-06-23 22:41:35 +00:00
|
|
|
BOARD_ITEM( aModule )
|
2012-01-14 19:50:32 +00:00
|
|
|
{
|
|
|
|
m_Pos = aModule.m_Pos;
|
2013-09-08 18:31:21 +00:00
|
|
|
m_fpid = aModule.m_fpid;
|
2012-01-30 13:25:46 +00:00
|
|
|
m_Layer = aModule.m_Layer;
|
2012-01-14 19:50:32 +00:00
|
|
|
m_Attributs = aModule.m_Attributs;
|
2012-01-30 13:25:46 +00:00
|
|
|
m_ModuleStatus = aModule.m_ModuleStatus;
|
2012-01-14 19:50:32 +00:00
|
|
|
m_Orient = aModule.m_Orient;
|
|
|
|
m_BoundaryBox = aModule.m_BoundaryBox;
|
|
|
|
m_CntRot90 = aModule.m_CntRot90;
|
|
|
|
m_CntRot180 = aModule.m_CntRot180;
|
2013-03-13 18:53:58 +00:00
|
|
|
m_LastEditTime = aModule.m_LastEditTime;
|
2012-01-14 19:50:32 +00:00
|
|
|
m_Link = aModule.m_Link;
|
|
|
|
m_Path = aModule.m_Path; //is this correct behavior?
|
|
|
|
|
|
|
|
m_LocalClearance = aModule.m_LocalClearance;
|
|
|
|
m_LocalSolderMaskMargin = aModule.m_LocalSolderMaskMargin;
|
|
|
|
m_LocalSolderPasteMargin = aModule.m_LocalSolderPasteMargin;
|
|
|
|
m_LocalSolderPasteMarginRatio = aModule.m_LocalSolderPasteMarginRatio;
|
2012-02-24 23:23:46 +00:00
|
|
|
m_ZoneConnection = aModule.m_ZoneConnection;
|
2012-03-08 20:44:03 +00:00
|
|
|
m_ThermalWidth = aModule.m_ThermalWidth;
|
|
|
|
m_ThermalGap = aModule.m_ThermalGap;
|
2012-01-14 19:50:32 +00:00
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Copy reference and value.
|
2012-01-14 19:50:32 +00:00
|
|
|
m_Reference = new TEXTE_MODULE( *aModule.m_Reference );
|
|
|
|
m_Reference->SetParent( this );
|
2012-04-17 01:35:43 +00:00
|
|
|
|
2012-01-14 19:50:32 +00:00
|
|
|
m_Value = new TEXTE_MODULE( *aModule.m_Value );
|
|
|
|
m_Value->SetParent( this );
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Copy auxiliary data: Pads
|
2012-01-14 19:50:32 +00:00
|
|
|
for( D_PAD* pad = aModule.m_Pads; pad; pad = pad->Next() )
|
|
|
|
{
|
|
|
|
D_PAD* newpad = new D_PAD( *pad );
|
2016-01-29 14:43:40 +00:00
|
|
|
assert( newpad->GetNet() == pad->GetNet() );
|
2012-01-14 19:50:32 +00:00
|
|
|
newpad->SetParent( this );
|
|
|
|
m_Pads.PushBack( newpad );
|
|
|
|
}
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Copy auxiliary data: Drawings
|
2012-01-14 19:50:32 +00:00
|
|
|
for( BOARD_ITEM* item = aModule.m_Drawings; item; item = item->Next() )
|
|
|
|
{
|
2012-05-24 15:00:59 +00:00
|
|
|
BOARD_ITEM* newItem;
|
|
|
|
|
2012-01-14 19:50:32 +00:00
|
|
|
switch( item->Type() )
|
|
|
|
{
|
|
|
|
case PCB_MODULE_TEXT_T:
|
|
|
|
case PCB_MODULE_EDGE_T:
|
2014-09-10 15:18:42 +00:00
|
|
|
newItem = static_cast<BOARD_ITEM*>( item->Clone() );
|
2012-01-14 19:50:32 +00:00
|
|
|
newItem->SetParent( this );
|
|
|
|
m_Drawings.PushBack( newItem );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-12-10 11:18:42 +00:00
|
|
|
wxLogMessage( wxT( "MODULE::Copy() Internal Err: unknown type" ) );
|
2012-01-14 19:50:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Copy auxiliary data: 3D_Drawings info
|
2012-01-14 19:50:32 +00:00
|
|
|
for( S3D_MASTER* item = aModule.m_3D_Drawings; item; item = item->Next() )
|
|
|
|
{
|
2014-01-25 12:23:29 +00:00
|
|
|
if( item->GetShape3DName().IsEmpty() ) // do not copy empty shapes.
|
2012-01-14 19:50:32 +00:00
|
|
|
continue;
|
|
|
|
|
2015-02-22 09:39:58 +00:00
|
|
|
S3D_MASTER* t3d = new S3D_MASTER( this );
|
2012-01-14 19:50:32 +00:00
|
|
|
t3d->Copy( item );
|
|
|
|
m_3D_Drawings.PushBack( t3d );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure there is at least one item in m_3D_Drawings.
|
|
|
|
if( m_3D_Drawings.GetCount() == 0 )
|
|
|
|
m_3D_Drawings.PushBack( new S3D_MASTER( this ) ); // push a void item
|
|
|
|
|
|
|
|
m_Doc = aModule.m_Doc;
|
|
|
|
m_KeyWord = aModule.m_KeyWord;
|
2013-01-02 21:49:56 +00:00
|
|
|
|
2015-03-23 08:28:12 +00:00
|
|
|
m_arflag = 0;
|
|
|
|
|
2013-01-02 21:49:56 +00:00
|
|
|
// Ensure auxiliary data is up to date
|
|
|
|
CalculateBoundingBox();
|
2013-06-23 22:41:35 +00:00
|
|
|
|
|
|
|
m_initial_comments = aModule.m_initial_comments ?
|
|
|
|
new wxArrayString( *aModule.m_initial_comments ) : 0;
|
2012-01-14 19:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-01 12:00:30 +00:00
|
|
|
MODULE::~MODULE()
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2007-08-06 02:02:39 +00:00
|
|
|
delete m_Reference;
|
|
|
|
delete m_Value;
|
2013-06-23 19:18:33 +00:00
|
|
|
delete m_initial_comments;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
2015-02-18 09:13:17 +00:00
|
|
|
/**
|
|
|
|
* Function ClearAllNets
|
|
|
|
* Clear (i.e. force the ORPHANED dummy net info) the net info which
|
|
|
|
* depends on a given board for all pads of the footprint.
|
|
|
|
* This is needed when a footprint is copied between the fp editor and
|
|
|
|
* the board editor for instance, because net info become fully broken
|
|
|
|
*/
|
|
|
|
void MODULE::ClearAllNets()
|
|
|
|
{
|
|
|
|
// Force the ORPHANED dummy net info for all pads.
|
|
|
|
// ORPHANED dummy net does not depend on a board
|
|
|
|
for( D_PAD* pad = Pads(); pad; pad = pad->Next() )
|
2016-01-29 10:29:56 +00:00
|
|
|
pad->SetNetCode( NETINFO_LIST::ORPHANED );
|
2015-02-18 09:13:17 +00:00
|
|
|
}
|
|
|
|
|
2010-07-20 10:30:40 +00:00
|
|
|
|
2009-11-12 15:43:38 +00:00
|
|
|
/* Draw the anchor cross (vertical)
|
|
|
|
* Must be done after the pads, because drawing the hole will erase overwrite
|
|
|
|
* every thing already drawn.
|
|
|
|
*/
|
2011-01-21 19:30:59 +00:00
|
|
|
void MODULE::DrawAncre( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
|
2012-09-01 13:38:27 +00:00
|
|
|
int dim_ancre, GR_DRAWMODE draw_mode )
|
2009-08-01 19:26:05 +00:00
|
|
|
{
|
|
|
|
GRSetDrawMode( DC, draw_mode );
|
|
|
|
|
2010-01-31 20:01:46 +00:00
|
|
|
if( GetBoard()->IsElementVisible( ANCHOR_VISIBLE ) )
|
2009-08-01 19:26:05 +00:00
|
|
|
{
|
2013-06-23 19:18:33 +00:00
|
|
|
GRDrawAnchor( panel->GetClipBox(), DC, m_Pos.x, m_Pos.y,
|
2013-04-09 16:00:46 +00:00
|
|
|
dim_ancre,
|
|
|
|
g_ColorsSettings.GetItemColor( ANCHOR_VISIBLE ) );
|
2009-08-01 19:26:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-04 19:08:08 +00:00
|
|
|
|
2008-12-06 08:21:54 +00:00
|
|
|
void MODULE::Copy( MODULE* aModule )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2008-12-06 08:21:54 +00:00
|
|
|
m_Pos = aModule->m_Pos;
|
|
|
|
m_Layer = aModule->m_Layer;
|
2013-09-08 18:31:21 +00:00
|
|
|
m_fpid = aModule->m_fpid;
|
2008-12-06 08:21:54 +00:00
|
|
|
m_Attributs = aModule->m_Attributs;
|
2012-01-30 13:25:46 +00:00
|
|
|
m_ModuleStatus = aModule->m_ModuleStatus;
|
2008-12-06 08:21:54 +00:00
|
|
|
m_Orient = aModule->m_Orient;
|
|
|
|
m_BoundaryBox = aModule->m_BoundaryBox;
|
|
|
|
m_CntRot90 = aModule->m_CntRot90;
|
|
|
|
m_CntRot180 = aModule->m_CntRot180;
|
2013-03-13 18:53:58 +00:00
|
|
|
m_LastEditTime = aModule->m_LastEditTime;
|
2010-06-14 20:16:47 +00:00
|
|
|
m_Link = aModule->m_Link;
|
2008-12-06 08:21:54 +00:00
|
|
|
m_Path = aModule->m_Path; //is this correct behavior?
|
2011-12-12 08:37:05 +00:00
|
|
|
SetTimeStamp( GetNewTimeStamp() );
|
2011-08-09 03:37:48 +00:00
|
|
|
|
|
|
|
m_LocalClearance = aModule->m_LocalClearance;
|
|
|
|
m_LocalSolderMaskMargin = aModule->m_LocalSolderMaskMargin;
|
|
|
|
m_LocalSolderPasteMargin = aModule->m_LocalSolderPasteMargin;
|
|
|
|
m_LocalSolderPasteMarginRatio = aModule->m_LocalSolderPasteMarginRatio;
|
2012-02-24 23:23:46 +00:00
|
|
|
m_ZoneConnection = aModule->m_ZoneConnection;
|
2012-03-08 20:44:03 +00:00
|
|
|
m_ThermalWidth = aModule->m_ThermalWidth;
|
|
|
|
m_ThermalGap = aModule->m_ThermalGap;
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Copy reference and value.
|
2008-12-06 08:21:54 +00:00
|
|
|
m_Reference->Copy( aModule->m_Reference );
|
|
|
|
m_Value->Copy( aModule->m_Value );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Copy auxiliary data: Pads
|
2009-08-03 18:54:48 +00:00
|
|
|
m_Pads.DeleteAll();
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2008-12-06 08:21:54 +00:00
|
|
|
for( D_PAD* pad = aModule->m_Pads; pad; pad = pad->Next() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
|
|
|
D_PAD* newpad = new D_PAD( this );
|
|
|
|
newpad->Copy( pad );
|
2008-12-04 04:28:11 +00:00
|
|
|
m_Pads.PushBack( newpad );
|
2007-08-06 02:02:39 +00:00
|
|
|
}
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Copy auxiliary data: Drawings
|
2009-08-03 18:54:48 +00:00
|
|
|
m_Drawings.DeleteAll();
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2008-12-06 08:21:54 +00:00
|
|
|
for( BOARD_ITEM* item = aModule->m_Drawings; item; item = item->Next() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2008-12-04 04:28:11 +00:00
|
|
|
switch( item->Type() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_MODULE_TEXT_T:
|
2014-11-15 19:06:05 +00:00
|
|
|
{
|
|
|
|
TEXTE_MODULE* textm = new TEXTE_MODULE( this );
|
|
|
|
textm->Copy( static_cast<TEXTE_MODULE*>( item ) );
|
|
|
|
m_Drawings.PushBack( textm );
|
|
|
|
break;
|
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_MODULE_EDGE_T:
|
2014-11-15 19:06:05 +00:00
|
|
|
{
|
|
|
|
EDGE_MODULE * edge;
|
|
|
|
edge = new EDGE_MODULE( this );
|
|
|
|
edge->Copy( (EDGE_MODULE*) item );
|
|
|
|
m_Drawings.PushBack( edge );
|
|
|
|
break;
|
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
|
|
|
|
default:
|
2012-12-10 11:18:42 +00:00
|
|
|
wxLogMessage( wxT( "MODULE::Copy() Internal Err: unknown type" ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Copy auxiliary data: 3D_Drawings info
|
2009-08-04 18:21:32 +00:00
|
|
|
m_3D_Drawings.DeleteAll();
|
2009-11-04 19:08:08 +00:00
|
|
|
|
2009-08-04 18:21:32 +00:00
|
|
|
// Ensure there is one (or more) item in m_3D_Drawings
|
2009-11-12 15:43:38 +00:00
|
|
|
m_3D_Drawings.PushBack( new S3D_MASTER( this ) ); // push a void item
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2008-12-06 08:21:54 +00:00
|
|
|
for( S3D_MASTER* item = aModule->m_3D_Drawings; item; item = item->Next() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2014-01-25 12:23:29 +00:00
|
|
|
if( item->GetShape3DName().IsEmpty() ) // do not copy empty shapes.
|
2009-04-15 07:20:30 +00:00
|
|
|
continue;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2009-04-15 06:32:15 +00:00
|
|
|
S3D_MASTER* t3d = m_3D_Drawings;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2014-01-25 12:23:29 +00:00
|
|
|
if( t3d && t3d->GetShape3DName().IsEmpty() ) // The first entry can
|
2011-09-07 19:41:04 +00:00
|
|
|
{ // exist, but is empty : use it.
|
2009-04-15 06:32:15 +00:00
|
|
|
t3d->Copy( item );
|
2011-09-07 19:41:04 +00:00
|
|
|
}
|
2009-04-15 06:32:15 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
t3d = new S3D_MASTER( this );
|
|
|
|
t3d->Copy( item );
|
|
|
|
m_3D_Drawings.PushBack( t3d );
|
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
}
|
|
|
|
|
2008-12-06 08:21:54 +00:00
|
|
|
m_Doc = aModule->m_Doc;
|
|
|
|
m_KeyWord = aModule->m_KeyWord;
|
2013-01-02 21:49:56 +00:00
|
|
|
|
|
|
|
// Ensure auxiliary data is up to date
|
|
|
|
CalculateBoundingBox();
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-07-09 12:22:29 +00:00
|
|
|
void MODULE::Add( BOARD_ITEM* aBoardItem, bool doAppend )
|
|
|
|
{
|
|
|
|
switch( aBoardItem->Type() )
|
|
|
|
{
|
|
|
|
case PCB_MODULE_TEXT_T:
|
2014-09-10 15:18:42 +00:00
|
|
|
// Only user texts can be added this way. Reference and value are not hold in the DLIST.
|
2014-07-09 12:22:29 +00:00
|
|
|
assert( static_cast<TEXTE_MODULE*>( aBoardItem )->GetType() == TEXTE_MODULE::TEXT_is_DIVERS );
|
2014-09-10 15:18:42 +00:00
|
|
|
|
|
|
|
// no break
|
2014-07-09 12:22:29 +00:00
|
|
|
|
|
|
|
case PCB_MODULE_EDGE_T:
|
|
|
|
if( doAppend )
|
2015-11-04 08:48:34 +00:00
|
|
|
m_Drawings.PushBack( aBoardItem );
|
2014-07-09 12:22:29 +00:00
|
|
|
else
|
2015-11-04 08:48:34 +00:00
|
|
|
m_Drawings.PushFront( aBoardItem );
|
2014-07-09 12:22:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PCB_PAD_T:
|
|
|
|
if( doAppend )
|
|
|
|
m_Pads.PushBack( static_cast<D_PAD*>( aBoardItem ) );
|
|
|
|
else
|
|
|
|
m_Pads.PushFront( static_cast<D_PAD*>( aBoardItem ) );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2014-11-15 19:06:05 +00:00
|
|
|
{
|
|
|
|
wxString msg;
|
|
|
|
msg.Printf( wxT( "MODULE::Add() needs work: BOARD_ITEM type (%d) not handled" ),
|
|
|
|
aBoardItem->Type() );
|
|
|
|
wxFAIL_MSG( msg );
|
2014-07-09 12:22:29 +00:00
|
|
|
|
2014-11-15 19:06:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-07-09 12:22:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
aBoardItem->SetParent( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOARD_ITEM* MODULE::Remove( BOARD_ITEM* aBoardItem )
|
|
|
|
{
|
|
|
|
switch( aBoardItem->Type() )
|
|
|
|
{
|
|
|
|
case PCB_MODULE_TEXT_T:
|
2014-09-10 15:18:42 +00:00
|
|
|
// Only user texts can be removed this way. Reference and value are not hold in the DLIST.
|
2014-07-09 12:22:29 +00:00
|
|
|
assert( static_cast<TEXTE_MODULE*>( aBoardItem )->GetType() == TEXTE_MODULE::TEXT_is_DIVERS );
|
2014-09-10 15:18:42 +00:00
|
|
|
|
|
|
|
// no break
|
2014-07-09 12:22:29 +00:00
|
|
|
|
|
|
|
case PCB_MODULE_EDGE_T:
|
2015-11-04 08:48:34 +00:00
|
|
|
return m_Drawings.Remove( aBoardItem );
|
2014-07-09 12:22:29 +00:00
|
|
|
|
|
|
|
case PCB_PAD_T:
|
|
|
|
return m_Pads.Remove( static_cast<D_PAD*>( aBoardItem ) );
|
|
|
|
|
|
|
|
default:
|
2014-11-15 19:06:05 +00:00
|
|
|
{
|
|
|
|
wxString msg;
|
|
|
|
msg.Printf( wxT( "MODULE::Remove() needs work: BOARD_ITEM type (%d) not handled" ),
|
|
|
|
aBoardItem->Type() );
|
|
|
|
wxFAIL_MSG( msg );
|
|
|
|
}
|
2014-07-09 12:22:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-22 16:50:27 +00:00
|
|
|
void MODULE::CopyNetlistSettings( MODULE* aModule, bool aCopyLocalSettings )
|
2013-04-25 16:29:35 +00:00
|
|
|
{
|
|
|
|
// Don't do anything foolish like trying to copy to yourself.
|
|
|
|
wxCHECK_RET( aModule != NULL && aModule != this, wxT( "Cannot copy to NULL or yourself." ) );
|
|
|
|
|
|
|
|
// Not sure what to do with the value field. Use netlist for now.
|
|
|
|
aModule->SetPosition( GetPosition() );
|
|
|
|
|
|
|
|
if( aModule->GetLayer() != GetLayer() )
|
|
|
|
aModule->Flip( aModule->GetPosition() );
|
|
|
|
|
|
|
|
if( aModule->GetOrientation() != GetOrientation() )
|
|
|
|
aModule->Rotate( aModule->GetPosition(), GetOrientation() );
|
|
|
|
|
2015-10-22 16:50:27 +00:00
|
|
|
aModule->SetLocked( IsLocked() );
|
|
|
|
|
|
|
|
if( aCopyLocalSettings )
|
|
|
|
{
|
|
|
|
aModule->SetLocalSolderMaskMargin( GetLocalSolderMaskMargin() );
|
|
|
|
aModule->SetLocalClearance( GetLocalClearance() );
|
|
|
|
aModule->SetLocalSolderPasteMargin( GetLocalSolderPasteMargin() );
|
|
|
|
aModule->SetLocalSolderPasteMarginRatio( GetLocalSolderPasteMarginRatio() );
|
|
|
|
aModule->SetZoneConnection( GetZoneConnection() );
|
|
|
|
aModule->SetThermalWidth( GetThermalWidth() );
|
|
|
|
aModule->SetThermalGap( GetThermalGap() );
|
|
|
|
}
|
2013-04-25 16:29:35 +00:00
|
|
|
|
2015-10-28 18:45:20 +00:00
|
|
|
for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
|
2013-04-25 16:29:35 +00:00
|
|
|
{
|
2015-10-28 18:45:20 +00:00
|
|
|
// Fix me: if aCopyLocalSettings == true, for "multiple" pads
|
|
|
|
// (set of pads having the same name/number) this is broken
|
|
|
|
// because we copy settings from the first pad found.
|
|
|
|
// When old and new footprints have very few differences, a better
|
|
|
|
// algo can be used.
|
|
|
|
D_PAD* oldPad = FindPadByName( pad->GetPadName() );
|
|
|
|
|
|
|
|
if( oldPad )
|
|
|
|
oldPad->CopyNetlistSettings( pad, aCopyLocalSettings );
|
2013-04-25 16:29:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Not sure about copying description, keywords, 3D models or any other
|
|
|
|
// local user changes to footprint. Stick with the new footprint settings
|
|
|
|
// called out in the footprint loaded in the netlist.
|
|
|
|
aModule->CalculateBoundingBox();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MODULE::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode,
|
|
|
|
const wxPoint& aOffset )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2011-12-21 13:42:02 +00:00
|
|
|
if( (m_Flags & DO_NOT_DRAW) || (IsMoving()) )
|
2008-03-15 10:24:32 +00:00
|
|
|
return;
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2008-11-24 06:53:43 +00:00
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2011-12-21 13:42:02 +00:00
|
|
|
if( pad->IsMoving() )
|
2007-08-06 02:02:39 +00:00
|
|
|
continue;
|
2008-11-24 06:53:43 +00:00
|
|
|
|
2010-12-29 17:47:32 +00:00
|
|
|
pad->Draw( aPanel, aDC, aDrawMode, aOffset );
|
2007-08-06 02:02:39 +00:00
|
|
|
}
|
|
|
|
|
2010-07-20 10:30:40 +00:00
|
|
|
BOARD* brd = GetBoard();
|
2010-01-31 20:01:46 +00:00
|
|
|
|
2009-11-12 15:43:38 +00:00
|
|
|
// Draws footprint anchor
|
2010-12-29 17:47:32 +00:00
|
|
|
DrawAncre( aPanel, aDC, aOffset, DIM_ANCRE_MODULE, aDrawMode );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Draw graphic items
|
2010-01-31 20:01:46 +00:00
|
|
|
if( brd->IsElementVisible( MOD_REFERENCES_VISIBLE ) )
|
2010-01-28 13:10:46 +00:00
|
|
|
{
|
2011-12-21 13:42:02 +00:00
|
|
|
if( !(m_Reference->IsMoving()) )
|
2010-12-29 17:47:32 +00:00
|
|
|
m_Reference->Draw( aPanel, aDC, aDrawMode, aOffset );
|
2010-01-28 13:10:46 +00:00
|
|
|
}
|
2008-04-01 05:21:50 +00:00
|
|
|
|
2010-01-31 20:01:46 +00:00
|
|
|
if( brd->IsElementVisible( MOD_VALUES_VISIBLE ) )
|
2010-01-28 13:10:46 +00:00
|
|
|
{
|
2011-12-21 13:42:02 +00:00
|
|
|
if( !(m_Value->IsMoving()) )
|
2010-12-29 17:47:32 +00:00
|
|
|
m_Value->Draw( aPanel, aDC, aDrawMode, aOffset );
|
2010-01-28 13:10:46 +00:00
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2008-04-01 05:21:50 +00:00
|
|
|
for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2011-12-21 13:42:02 +00:00
|
|
|
if( item->IsMoving() )
|
2007-08-06 02:02:39 +00:00
|
|
|
continue;
|
|
|
|
|
2008-04-01 05:21:50 +00:00
|
|
|
switch( item->Type() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_MODULE_TEXT_T:
|
|
|
|
case PCB_MODULE_EDGE_T:
|
2010-12-29 17:47:32 +00:00
|
|
|
item->Draw( aPanel, aDC, aDrawMode, aOffset );
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-10-29 12:01:59 +00:00
|
|
|
|
|
|
|
// Enable these line to draw m_BoundaryBox (debug tests purposes only)
|
|
|
|
#if 0
|
2011-12-29 20:11:42 +00:00
|
|
|
GRRect( aPanel->GetClipBox(), aDC, m_BoundaryBox, 0, BROWN );
|
2011-10-29 12:01:59 +00:00
|
|
|
#endif
|
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-01 13:38:27 +00:00
|
|
|
void MODULE::DrawEdgesOnly( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
|
|
|
|
GR_DRAWMODE draw_mode )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2008-04-01 05:21:50 +00:00
|
|
|
for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2008-04-01 05:21:50 +00:00
|
|
|
switch( item->Type() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_MODULE_EDGE_T:
|
2008-04-01 05:21:50 +00:00
|
|
|
item->Draw( panel, DC, draw_mode, offset );
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-07 19:41:04 +00:00
|
|
|
void MODULE::CalculateBoundingBox()
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2013-11-24 17:48:14 +00:00
|
|
|
m_BoundaryBox = GetFootprintRect();
|
2012-09-22 11:19:37 +00:00
|
|
|
m_Surface = std::abs( (double) m_BoundaryBox.GetWidth() * m_BoundaryBox.GetHeight() );
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-24 17:48:14 +00:00
|
|
|
EDA_RECT MODULE::GetFootprintRect() const
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2011-03-29 19:33:07 +00:00
|
|
|
EDA_RECT area;
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2011-12-21 13:42:02 +00:00
|
|
|
area.SetOrigin( m_Pos );
|
2010-12-10 19:47:44 +00:00
|
|
|
area.SetEnd( m_Pos );
|
2013-01-02 21:49:56 +00:00
|
|
|
area.Inflate( Millimeter2iu( 0.25 ) ); // Give a min size to the area
|
2010-12-10 19:47:44 +00:00
|
|
|
|
2014-04-30 19:16:22 +00:00
|
|
|
for( const BOARD_ITEM* item = m_Drawings.GetFirst(); item; item = item->Next() )
|
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
const EDGE_MODULE* edge = dyn_cast<const EDGE_MODULE*>( item );
|
2014-06-06 09:44:21 +00:00
|
|
|
|
2014-04-30 19:16:22 +00:00
|
|
|
if( edge )
|
2011-09-01 21:39:38 +00:00
|
|
|
area.Merge( edge->GetBoundingBox() );
|
2014-04-30 19:16:22 +00:00
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2008-11-24 06:53:43 +00:00
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
2010-12-10 19:47:44 +00:00
|
|
|
area.Merge( pad->GetBoundingBox() );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2010-12-10 19:47:44 +00:00
|
|
|
return area;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-24 17:48:14 +00:00
|
|
|
const EDA_RECT MODULE::GetBoundingBox() const
|
2008-03-13 10:08:42 +00:00
|
|
|
{
|
2013-11-24 17:48:14 +00:00
|
|
|
EDA_RECT area = GetFootprintRect();
|
2008-03-15 10:24:32 +00:00
|
|
|
|
2011-09-01 22:11:54 +00:00
|
|
|
// Calculate extended area including text fields
|
2011-09-01 21:39:38 +00:00
|
|
|
area.Merge( m_Reference->GetBoundingBox() );
|
|
|
|
area.Merge( m_Value->GetBoundingBox() );
|
2008-03-13 21:18:05 +00:00
|
|
|
|
2009-11-12 15:43:38 +00:00
|
|
|
// Add the Clearance shape size: (shape around the pads when the
|
|
|
|
// clearance is shown. Not optimized, but the draw cost is small
|
|
|
|
// (perhaps smaller than optimization).
|
2014-07-09 09:22:42 +00:00
|
|
|
BOARD* board = GetBoard();
|
|
|
|
if( board )
|
|
|
|
{
|
|
|
|
int biggest_clearance = board->GetDesignSettings().GetBiggestClearanceValue();
|
|
|
|
area.Inflate( biggest_clearance );
|
|
|
|
}
|
2008-03-18 11:53:52 +00:00
|
|
|
|
2008-03-15 10:24:32 +00:00
|
|
|
return area;
|
2008-03-13 10:08:42 +00:00
|
|
|
}
|
|
|
|
|
2008-03-15 10:24:32 +00:00
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
/* Virtual function, from EDA_ITEM.
|
2009-01-31 21:42:05 +00:00
|
|
|
* display module info on MsgPanel
|
2009-11-04 19:08:08 +00:00
|
|
|
*/
|
2013-01-12 17:32:24 +00:00
|
|
|
void MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2007-08-06 02:02:39 +00:00
|
|
|
int nbpad;
|
|
|
|
wxString msg;
|
|
|
|
|
2014-09-13 18:15:45 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( m_Reference->GetShownText(), m_Value->GetShownText(), DARKCYAN ) );
|
2010-12-10 19:47:44 +00:00
|
|
|
|
2013-01-12 17:32:24 +00:00
|
|
|
// Display last date the component was edited (useful in Module Editor).
|
2015-03-11 13:59:43 +00:00
|
|
|
wxDateTime date( m_LastEditTime );
|
2015-03-12 17:43:39 +00:00
|
|
|
|
|
|
|
if( m_LastEditTime && date.IsValid() )
|
2015-03-11 13:59:43 +00:00
|
|
|
// Date format: see http://www.cplusplus.com/reference/ctime/strftime
|
2015-03-12 17:43:39 +00:00
|
|
|
msg = date.Format( wxT( "%b %d, %Y" ) ); // Abbreviated_month_name Day, Year
|
|
|
|
else
|
|
|
|
msg = _( "Unknown" );
|
|
|
|
|
2013-01-12 17:32:24 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "Last Change" ), msg, BROWN ) );
|
2009-10-11 13:04:47 +00:00
|
|
|
|
2013-12-14 19:03:38 +00:00
|
|
|
// display schematic path
|
2014-11-15 19:06:05 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "Netlist Path" ), m_Path, BROWN ) );
|
2013-12-14 19:03:38 +00:00
|
|
|
|
2013-04-07 11:55:18 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), RED ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
EDA_ITEM* PtStruct = m_Pads;
|
2007-08-06 02:02:39 +00:00
|
|
|
nbpad = 0;
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2007-08-06 02:02:39 +00:00
|
|
|
while( PtStruct )
|
|
|
|
{
|
2008-02-19 00:30:10 +00:00
|
|
|
nbpad++;
|
2008-11-24 06:53:43 +00:00
|
|
|
PtStruct = PtStruct->Next();
|
2007-08-06 02:02:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
msg.Printf( wxT( "%d" ), nbpad );
|
2013-01-12 17:32:24 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "Pads" ), msg, BLUE ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2009-11-04 19:08:08 +00:00
|
|
|
msg = wxT( ".." );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2007-09-09 02:27:56 +00:00
|
|
|
if( IsLocked() )
|
2007-09-21 10:38:50 +00:00
|
|
|
msg[0] = 'L';
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2007-08-06 02:02:39 +00:00
|
|
|
if( m_ModuleStatus & MODULE_is_PLACED )
|
|
|
|
msg[1] = 'P';
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2014-11-15 19:06:05 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "Status" ), msg, MAGENTA ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2013-05-01 17:32:36 +00:00
|
|
|
msg.Printf( wxT( "%.1f" ), m_Orient / 10.0 );
|
2014-11-15 19:06:05 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "Angle" ), msg, BROWN ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2013-04-07 11:55:18 +00:00
|
|
|
// Controls on right side of the dialog
|
2012-12-06 21:53:00 +00:00
|
|
|
switch( m_Attributs & 255 )
|
|
|
|
{
|
|
|
|
case 0:
|
2014-11-15 19:06:05 +00:00
|
|
|
msg = _( "Normal" );
|
2012-12-06 21:53:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MOD_CMS:
|
2014-11-15 19:06:05 +00:00
|
|
|
msg = _( "Insert" );
|
2012-12-06 21:53:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MOD_VIRTUAL:
|
2014-11-15 19:06:05 +00:00
|
|
|
msg = _( "Virtual" );
|
2012-12-06 21:53:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2014-11-15 19:06:05 +00:00
|
|
|
msg = wxT( "???" );
|
2012-12-06 21:53:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-11-15 19:06:05 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "Attributes" ), msg, BROWN ) );
|
2014-10-08 06:26:26 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), FROM_UTF8( m_fpid.Format().c_str() ), BLUE ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2013-01-17 17:34:03 +00:00
|
|
|
msg = _( "No 3D shape" );
|
|
|
|
// Search the first active 3D shape in list
|
|
|
|
for( S3D_MASTER* struct3D = m_3D_Drawings; struct3D; struct3D = struct3D->Next() )
|
|
|
|
{
|
2014-01-25 12:23:29 +00:00
|
|
|
if( !struct3D->GetShape3DName().IsEmpty() )
|
2013-01-17 17:34:03 +00:00
|
|
|
{
|
2014-01-25 12:23:29 +00:00
|
|
|
msg = struct3D->GetShape3DName();
|
2013-01-17 17:34:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2013-01-12 17:32:24 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( _( "3D-Shape" ), msg, RED ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2013-04-09 17:49:01 +00:00
|
|
|
wxString doc, keyword;
|
|
|
|
doc.Printf( _( "Doc: %s" ), GetChars( m_Doc ) );
|
2014-11-15 19:06:05 +00:00
|
|
|
keyword.Printf( _( "Key Words: %s" ), GetChars( m_KeyWord ) );
|
2013-01-12 17:32:24 +00:00
|
|
|
aList.push_back( MSG_PANEL_ITEM( doc, keyword, BLACK ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
}
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-05-04 17:08:36 +00:00
|
|
|
bool MODULE::HitTest( const wxPoint& aPosition ) const
|
2007-08-08 03:50:44 +00:00
|
|
|
{
|
2015-11-04 08:48:34 +00:00
|
|
|
return m_BoundaryBox.Contains( aPosition );
|
2007-08-08 03:50:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-21 18:09:41 +00:00
|
|
|
bool MODULE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
|
2008-01-06 12:43:57 +00:00
|
|
|
{
|
2013-09-21 18:09:41 +00:00
|
|
|
EDA_RECT arect = aRect;
|
|
|
|
arect.Inflate( aAccuracy );
|
2011-09-01 21:39:38 +00:00
|
|
|
|
2013-09-21 18:09:41 +00:00
|
|
|
if( aContained )
|
|
|
|
return arect.Contains( m_BoundaryBox );
|
|
|
|
else
|
|
|
|
return m_BoundaryBox.Intersects( arect );
|
2008-01-06 12:43:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-04 04:22:27 +00:00
|
|
|
D_PAD* MODULE::FindPadByName( const wxString& aPadName ) const
|
|
|
|
{
|
|
|
|
wxString buf;
|
|
|
|
|
2008-03-15 10:24:32 +00:00
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
2008-03-04 04:22:27 +00:00
|
|
|
{
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
pad->StringPadName( buf );
|
2008-03-04 04:22:27 +00:00
|
|
|
#if 1
|
|
|
|
if( buf.CmpNoCase( aPadName ) == 0 ) // why case insensitive?
|
|
|
|
#else
|
|
|
|
if( buf == aPadName )
|
|
|
|
#endif
|
|
|
|
return pad;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
D_PAD* MODULE::GetPad( const wxPoint& aPosition, LSET aLayerMask )
|
2011-09-15 17:58:35 +00:00
|
|
|
{
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
2011-09-15 17:58:35 +00:00
|
|
|
{
|
2012-02-19 04:02:19 +00:00
|
|
|
// ... and on the correct layer.
|
2014-06-24 18:30:39 +00:00
|
|
|
if( !( pad->GetLayerSet() & aLayerMask ).any() )
|
2011-09-15 17:58:35 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if( pad->HitTest( aPosition ) )
|
|
|
|
return pad;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-07 13:17:52 +00:00
|
|
|
unsigned MODULE::GetPadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
|
|
|
|
{
|
|
|
|
if( aIncludeNPTH )
|
|
|
|
return m_Pads.GetCount();
|
|
|
|
|
|
|
|
unsigned cnt = 0;
|
|
|
|
|
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
|
|
|
{
|
2015-08-23 19:40:33 +00:00
|
|
|
if( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED )
|
2013-06-07 13:17:52 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-11 18:35:26 +00:00
|
|
|
unsigned MODULE::GetUniquePadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
|
|
|
|
{
|
2015-11-13 11:32:42 +00:00
|
|
|
std::set<wxUint32> usedNames;
|
2015-11-11 18:35:26 +00:00
|
|
|
|
|
|
|
// Create a set of used pad numbers
|
|
|
|
for( D_PAD* pad = Pads(); pad; pad = pad->Next() )
|
|
|
|
{
|
2015-11-13 11:32:42 +00:00
|
|
|
// Skip pads not on copper layers (used to build complex
|
|
|
|
// solder paste shapes for instance)
|
|
|
|
if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none() )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Skip pads with no name, because they are usually "mechanical"
|
|
|
|
// pads, not "electrical" pads
|
|
|
|
if( pad->GetPadName().IsEmpty() )
|
|
|
|
continue;
|
|
|
|
|
2015-11-11 18:35:26 +00:00
|
|
|
if( !aIncludeNPTH )
|
|
|
|
{
|
2015-11-13 11:32:42 +00:00
|
|
|
// skip NPTH
|
2015-11-11 18:35:26 +00:00
|
|
|
if( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-13 11:32:42 +00:00
|
|
|
usedNames.insert( pad->GetPackedPadName() );
|
2015-11-11 18:35:26 +00:00
|
|
|
}
|
|
|
|
|
2015-11-13 11:32:42 +00:00
|
|
|
return usedNames.size();
|
2015-11-11 18:35:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-09 17:00:13 +00:00
|
|
|
void MODULE::Add3DModel( S3D_MASTER* a3DModel )
|
|
|
|
{
|
|
|
|
a3DModel->SetParent( this );
|
|
|
|
m_3D_Drawings.PushBack( a3DModel );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-19 00:30:10 +00:00
|
|
|
// see class_module.h
|
|
|
|
SEARCH_RESULT MODULE::Visit( INSPECTOR* inspector, const void* testData,
|
2008-03-15 10:24:32 +00:00
|
|
|
const KICAD_T scanTypes[] )
|
2007-08-09 21:15:08 +00:00
|
|
|
{
|
2008-03-15 10:24:32 +00:00
|
|
|
KICAD_T stype;
|
|
|
|
SEARCH_RESULT result = SEARCH_CONTINUE;
|
|
|
|
const KICAD_T* p = scanTypes;
|
|
|
|
bool done = false;
|
2008-02-19 00:30:10 +00:00
|
|
|
|
2009-11-04 19:08:08 +00:00
|
|
|
#if 0 && defined(DEBUG)
|
2008-03-15 10:24:32 +00:00
|
|
|
std::cout << GetClass().mb_str() << ' ';
|
2008-02-19 00:30:10 +00:00
|
|
|
#endif
|
2007-08-09 21:15:08 +00:00
|
|
|
|
2007-08-24 03:40:04 +00:00
|
|
|
while( !done )
|
2007-08-09 21:15:08 +00:00
|
|
|
{
|
2007-08-24 03:40:04 +00:00
|
|
|
stype = *p;
|
2008-03-15 10:24:32 +00:00
|
|
|
|
2007-08-09 21:15:08 +00:00
|
|
|
switch( stype )
|
|
|
|
{
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_MODULE_T:
|
2007-08-09 21:15:08 +00:00
|
|
|
result = inspector->Inspect( this, testData ); // inspect me
|
2007-08-24 03:40:04 +00:00
|
|
|
++p;
|
2007-08-09 21:15:08 +00:00
|
|
|
break;
|
2008-02-19 00:30:10 +00:00
|
|
|
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_PAD_T:
|
2007-08-24 03:40:04 +00:00
|
|
|
result = IterateForward( m_Pads, inspector, testData, p );
|
|
|
|
++p;
|
2007-08-09 21:15:08 +00:00
|
|
|
break;
|
2008-02-19 00:30:10 +00:00
|
|
|
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_MODULE_TEXT_T:
|
2007-08-09 21:15:08 +00:00
|
|
|
result = inspector->Inspect( m_Reference, testData );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2007-08-09 21:15:08 +00:00
|
|
|
if( result == SEARCH_QUIT )
|
|
|
|
break;
|
2008-02-19 00:30:10 +00:00
|
|
|
|
2007-08-09 21:15:08 +00:00
|
|
|
result = inspector->Inspect( m_Value, testData );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2007-08-09 21:15:08 +00:00
|
|
|
if( result == SEARCH_QUIT )
|
|
|
|
break;
|
|
|
|
|
2009-11-04 19:08:08 +00:00
|
|
|
// m_Drawings can hold TYPETEXTMODULE also, so fall thru
|
2008-02-19 00:30:10 +00:00
|
|
|
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_MODULE_EDGE_T:
|
2007-08-24 03:40:04 +00:00
|
|
|
result = IterateForward( m_Drawings, inspector, testData, p );
|
2008-03-15 10:24:32 +00:00
|
|
|
|
2007-08-24 03:40:04 +00:00
|
|
|
// skip over any types handled in the above call.
|
2008-03-15 10:24:32 +00:00
|
|
|
for( ; ; )
|
2007-08-24 03:40:04 +00:00
|
|
|
{
|
|
|
|
switch( stype = *++p )
|
|
|
|
{
|
2011-10-01 19:24:27 +00:00
|
|
|
case PCB_MODULE_TEXT_T:
|
|
|
|
case PCB_MODULE_EDGE_T:
|
2007-08-24 03:40:04 +00:00
|
|
|
continue;
|
2008-03-15 10:24:32 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
;
|
2007-08-24 03:40:04 +00:00
|
|
|
}
|
2008-03-15 10:24:32 +00:00
|
|
|
|
2007-08-24 03:40:04 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-03-15 10:24:32 +00:00
|
|
|
|
2007-08-09 21:15:08 +00:00
|
|
|
break;
|
2008-02-19 00:30:10 +00:00
|
|
|
|
2007-08-09 21:15:08 +00:00
|
|
|
default:
|
2007-08-24 03:40:04 +00:00
|
|
|
done = true;
|
2007-08-09 21:15:08 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-02-19 00:30:10 +00:00
|
|
|
|
2007-08-09 21:15:08 +00:00
|
|
|
if( result == SEARCH_QUIT )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-02-19 00:30:10 +00:00
|
|
|
return result;
|
2007-08-09 21:15:08 +00:00
|
|
|
}
|
|
|
|
|
2007-08-08 03:50:44 +00:00
|
|
|
|
2011-07-14 15:42:44 +00:00
|
|
|
wxString MODULE::GetSelectMenuText() const
|
|
|
|
{
|
|
|
|
wxString text;
|
2013-04-09 17:49:01 +00:00
|
|
|
text.Printf( _( "Footprint %s on %s" ),
|
|
|
|
GetChars ( GetReference() ),
|
|
|
|
GetChars ( GetLayerName() ) );
|
2011-07-14 15:42:44 +00:00
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-17 14:39:27 +00:00
|
|
|
EDA_ITEM* MODULE::Clone() const
|
2012-01-14 19:50:32 +00:00
|
|
|
{
|
|
|
|
return new MODULE( *this );
|
|
|
|
}
|
|
|
|
|
2013-04-25 16:29:35 +00:00
|
|
|
|
2013-12-18 12:39:11 +00:00
|
|
|
void MODULE::RunOnChildren( boost::function<void (BOARD_ITEM*)> aFunction )
|
|
|
|
{
|
2015-02-15 22:21:52 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
|
|
|
aFunction( static_cast<BOARD_ITEM*>( pad ) );
|
2013-12-18 12:39:11 +00:00
|
|
|
|
2015-02-15 22:21:52 +00:00
|
|
|
for( BOARD_ITEM* drawing = m_Drawings; drawing; drawing = drawing->Next() )
|
|
|
|
aFunction( drawing );
|
2013-12-18 12:39:11 +00:00
|
|
|
|
2015-02-15 22:21:52 +00:00
|
|
|
aFunction( static_cast<BOARD_ITEM*>( m_Reference ) );
|
|
|
|
aFunction( static_cast<BOARD_ITEM*>( m_Value ) );
|
|
|
|
}
|
|
|
|
catch( boost::bad_function_call& e )
|
|
|
|
{
|
|
|
|
DisplayError( NULL, wxT( "Error running MODULE::RunOnChildren" ) );
|
|
|
|
}
|
2013-12-18 12:39:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-02 13:35:05 +00:00
|
|
|
void MODULE::ViewUpdate( int aUpdateFlags )
|
|
|
|
{
|
|
|
|
if( !m_view )
|
|
|
|
return;
|
|
|
|
|
2014-02-21 15:57:18 +00:00
|
|
|
// Update the module itself
|
|
|
|
VIEW_ITEM::ViewUpdate( aUpdateFlags );
|
|
|
|
|
2013-12-02 13:35:05 +00:00
|
|
|
// Update pads
|
|
|
|
for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() )
|
2014-02-21 15:57:18 +00:00
|
|
|
pad->ViewUpdate( aUpdateFlags );
|
2013-12-02 13:35:05 +00:00
|
|
|
|
|
|
|
// Update module's drawing (mostly silkscreen)
|
|
|
|
for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() )
|
2014-02-21 15:57:18 +00:00
|
|
|
drawing->ViewUpdate( aUpdateFlags );
|
2013-12-02 13:35:05 +00:00
|
|
|
|
|
|
|
// Update module's texts
|
2014-02-21 15:57:18 +00:00
|
|
|
m_Reference->ViewUpdate( aUpdateFlags );
|
|
|
|
m_Value->ViewUpdate( aUpdateFlags );
|
2013-12-02 13:35:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-09 13:02:56 +00:00
|
|
|
void MODULE::ViewGetLayers( int aLayers[], int& aCount ) const
|
|
|
|
{
|
2014-08-04 08:06:24 +00:00
|
|
|
aCount = 2;
|
2014-07-09 13:02:56 +00:00
|
|
|
aLayers[0] = ITEM_GAL_LAYER( ANCHOR_VISIBLE );
|
2014-08-04 08:06:24 +00:00
|
|
|
|
|
|
|
switch( m_Layer )
|
|
|
|
{
|
2016-03-13 15:39:18 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
wxASSERT_MSG( false, "Illegal layer" ); // do you really have modules placed on other layers?
|
|
|
|
// pass through
|
2014-08-04 08:06:24 +00:00
|
|
|
case F_Cu:
|
|
|
|
aLayers[1] = ITEM_GAL_LAYER( MOD_FR_VISIBLE );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_Cu:
|
|
|
|
aLayers[1] = ITEM_GAL_LAYER( MOD_BK_VISIBLE );
|
|
|
|
break;
|
|
|
|
}
|
2014-07-09 13:02:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int MODULE::ViewGetLOD( int aLayer ) const
|
|
|
|
{
|
|
|
|
// Currently there is only one layer, so there is nothing to check
|
|
|
|
// if( aLayer == ITEM_GAL_LAYER( ANCHOR_VISIBLE ) )
|
|
|
|
return 30;
|
|
|
|
}
|
|
|
|
|
2015-06-16 15:03:36 +00:00
|
|
|
|
2014-11-13 16:32:59 +00:00
|
|
|
const BOX2I MODULE::ViewBBox() const
|
|
|
|
{
|
|
|
|
EDA_RECT fpRect = GetFootprintRect();
|
|
|
|
|
|
|
|
return BOX2I( VECTOR2I( fpRect.GetOrigin() ), VECTOR2I( fpRect.GetSize() ) );
|
|
|
|
}
|
2014-07-09 13:02:56 +00:00
|
|
|
|
2015-06-16 15:03:36 +00:00
|
|
|
|
2012-12-10 11:18:42 +00:00
|
|
|
/* Test for validity of the name in a library of the footprint
|
|
|
|
* ( no spaces, dir separators ... )
|
|
|
|
* return true if the given name is valid
|
|
|
|
* static function
|
|
|
|
*/
|
|
|
|
bool MODULE::IsLibNameValid( const wxString & aName )
|
|
|
|
{
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
const wxChar * invalids = StringLibNameInvalidChars( false );
|
2012-12-10 11:18:42 +00:00
|
|
|
|
|
|
|
if( aName.find_first_of( invalids ) != std::string::npos )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Test for validity of the name of a footprint to be used in a footprint library
|
|
|
|
* ( no spaces, dir separators ... )
|
|
|
|
* param bool aUserReadable = false to get the list of invalid chars
|
|
|
|
* true to get a readable form (i.e ' ' = 'space' '\t'= 'tab')
|
|
|
|
* return a constant string giving the list of invalid chars in lib name
|
|
|
|
* static function
|
|
|
|
*/
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
const wxChar* MODULE::StringLibNameInvalidChars( bool aUserReadable )
|
2012-12-10 11:18:42 +00:00
|
|
|
{
|
2012-12-12 11:57:17 +00:00
|
|
|
static const wxChar invalidChars[] = wxT("%$\t \"\\/");
|
|
|
|
static const wxChar invalidCharsReadable[] = wxT("% $ 'tab' 'space' \\ \" /");
|
2012-12-10 11:18:42 +00:00
|
|
|
|
|
|
|
if( aUserReadable )
|
|
|
|
return invalidCharsReadable;
|
|
|
|
else
|
|
|
|
return invalidChars;
|
|
|
|
}
|
|
|
|
|
2012-01-14 19:50:32 +00:00
|
|
|
|
2013-03-13 18:53:58 +00:00
|
|
|
void MODULE::Move( const wxPoint& aMoveVector )
|
|
|
|
{
|
|
|
|
wxPoint newpos = m_Pos + aMoveVector;
|
|
|
|
SetPosition( newpos );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
|
|
|
|
{
|
|
|
|
wxPoint newpos = m_Pos;
|
|
|
|
RotatePoint( &newpos, aRotCentre, aAngle );
|
|
|
|
SetPosition( newpos );
|
|
|
|
SetOrientation( GetOrientation() + aAngle );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MODULE::Flip( const wxPoint& aCentre )
|
|
|
|
{
|
|
|
|
// Move module to its final position:
|
|
|
|
wxPoint finalPos = m_Pos;
|
2015-07-31 19:04:30 +00:00
|
|
|
MIRROR( finalPos.y, aCentre.y ); /// Mirror the Y position
|
2013-03-13 18:53:58 +00:00
|
|
|
SetPosition( finalPos );
|
|
|
|
|
|
|
|
// Flip layer
|
2013-04-05 19:04:58 +00:00
|
|
|
SetLayer( FlipLayer( GetLayer() ) );
|
2013-03-13 18:53:58 +00:00
|
|
|
|
|
|
|
// Reverse mirror orientation.
|
2015-06-26 13:41:56 +00:00
|
|
|
m_Orient = -m_Orient;
|
2013-03-13 18:53:58 +00:00
|
|
|
NORMALIZE_ANGLE_POS( m_Orient );
|
|
|
|
|
|
|
|
// Mirror pads to other side of board about the x axis, i.e. vertically.
|
2013-04-07 11:55:18 +00:00
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
2014-02-13 17:27:48 +00:00
|
|
|
pad->Flip( m_Pos );
|
2013-03-13 18:53:58 +00:00
|
|
|
|
2015-07-31 19:04:30 +00:00
|
|
|
// Mirror reference and value.
|
|
|
|
m_Reference->Flip( m_Pos );
|
|
|
|
m_Value->Flip( m_Pos );
|
2013-03-13 18:53:58 +00:00
|
|
|
|
|
|
|
// Reverse mirror module graphics and texts.
|
2013-04-07 11:55:18 +00:00
|
|
|
for( EDA_ITEM* item = m_Drawings; item; item = item->Next() )
|
2013-03-13 18:53:58 +00:00
|
|
|
{
|
|
|
|
switch( item->Type() )
|
|
|
|
{
|
|
|
|
case PCB_MODULE_EDGE_T:
|
2014-09-24 16:42:56 +00:00
|
|
|
( (EDGE_MODULE*) item )->Flip( m_Pos );
|
2013-03-13 18:53:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PCB_MODULE_TEXT_T:
|
2015-07-31 19:04:30 +00:00
|
|
|
static_cast<TEXTE_MODULE*>( item )->Flip( m_Pos );
|
2013-03-13 18:53:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
wxMessageBox( wxT( "MODULE::Flip() error: Unknown Draw Type" ) );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CalculateBoundingBox();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MODULE::SetPosition( const wxPoint& newpos )
|
|
|
|
{
|
|
|
|
wxPoint delta = newpos - m_Pos;
|
|
|
|
|
|
|
|
m_Pos += delta;
|
2013-03-18 19:36:07 +00:00
|
|
|
m_Reference->SetTextPosition( m_Reference->GetTextPosition() + delta );
|
|
|
|
m_Value->SetTextPosition( m_Value->GetTextPosition() + delta );
|
2013-03-13 18:53:58 +00:00
|
|
|
|
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
|
|
|
{
|
|
|
|
pad->SetPosition( pad->GetPosition() + delta );
|
|
|
|
}
|
|
|
|
|
|
|
|
for( EDA_ITEM* item = m_Drawings; item; item = item->Next() )
|
|
|
|
{
|
|
|
|
switch( item->Type() )
|
|
|
|
{
|
|
|
|
case PCB_MODULE_EDGE_T:
|
|
|
|
{
|
|
|
|
EDGE_MODULE* pt_edgmod = (EDGE_MODULE*) item;
|
|
|
|
pt_edgmod->SetDrawCoord();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCB_MODULE_TEXT_T:
|
|
|
|
{
|
2014-09-10 15:18:42 +00:00
|
|
|
TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item );
|
|
|
|
text->SetTextPosition( text->GetTextPosition() + delta );
|
2013-03-13 18:53:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
wxMessageBox( wxT( "Draw type undefined." ) );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CalculateBoundingBox();
|
|
|
|
}
|
|
|
|
|
2013-04-25 16:29:35 +00:00
|
|
|
|
2013-03-23 13:30:00 +00:00
|
|
|
void MODULE::MoveAnchorPosition( const wxPoint& aMoveVector )
|
|
|
|
{
|
|
|
|
/* Move the reference point of the footprint
|
|
|
|
* the footprints elements (pads, outlines, edges .. ) are moved
|
|
|
|
* but:
|
|
|
|
* - the footprint position is not modified.
|
|
|
|
* - the relative (local) coordinates of these items are modified
|
2015-03-02 08:28:49 +00:00
|
|
|
* - Draw coordinates are updated
|
2013-03-23 13:30:00 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2015-03-02 08:28:49 +00:00
|
|
|
// Update (move) the relative coordinates relative to the new anchor point.
|
2013-03-23 13:30:00 +00:00
|
|
|
wxPoint moveVector = aMoveVector;
|
|
|
|
RotatePoint( &moveVector, -GetOrientation() );
|
|
|
|
|
|
|
|
// Update of the reference and value.
|
|
|
|
m_Reference->SetPos0( m_Reference->GetPos0() + moveVector );
|
|
|
|
m_Reference->SetDrawCoord();
|
|
|
|
m_Value->SetPos0( m_Value->GetPos0() + moveVector );
|
|
|
|
m_Value->SetDrawCoord();
|
|
|
|
|
|
|
|
// Update the pad local coordinates.
|
|
|
|
for( D_PAD* pad = Pads(); pad; pad = pad->Next() )
|
|
|
|
{
|
|
|
|
pad->SetPos0( pad->GetPos0() + moveVector );
|
2015-02-27 14:33:13 +00:00
|
|
|
pad->SetDrawCoord();
|
2013-03-23 13:30:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update the draw element coordinates.
|
|
|
|
for( EDA_ITEM* item = GraphicalItems(); item; item = item->Next() )
|
|
|
|
{
|
|
|
|
switch( item->Type() )
|
|
|
|
{
|
|
|
|
case PCB_MODULE_EDGE_T:
|
2014-11-15 19:06:05 +00:00
|
|
|
{
|
|
|
|
EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( item );
|
|
|
|
edge->m_Start0 += moveVector;
|
|
|
|
edge->m_End0 += moveVector;
|
|
|
|
edge->SetDrawCoord();
|
|
|
|
break;
|
|
|
|
}
|
2013-03-23 13:30:00 +00:00
|
|
|
|
|
|
|
case PCB_MODULE_TEXT_T:
|
2014-11-15 19:06:05 +00:00
|
|
|
{
|
|
|
|
TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item );
|
|
|
|
text->SetPos0( text->GetPos0() + moveVector );
|
|
|
|
text->SetDrawCoord();
|
|
|
|
break;
|
|
|
|
}
|
2013-03-23 13:30:00 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CalculateBoundingBox();
|
|
|
|
}
|
2013-03-13 18:53:58 +00:00
|
|
|
|
2013-04-25 16:29:35 +00:00
|
|
|
|
2013-03-13 18:53:58 +00:00
|
|
|
void MODULE::SetOrientation( double newangle )
|
|
|
|
{
|
|
|
|
double angleChange = newangle - m_Orient; // change in rotation
|
|
|
|
|
|
|
|
NORMALIZE_ANGLE_POS( newangle );
|
|
|
|
|
|
|
|
m_Orient = newangle;
|
|
|
|
|
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
|
|
|
{
|
|
|
|
pad->SetOrientation( pad->GetOrientation() + angleChange );
|
2015-02-27 14:33:13 +00:00
|
|
|
pad->SetDrawCoord();
|
2013-03-13 18:53:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update of the reference and value.
|
|
|
|
m_Reference->SetDrawCoord();
|
|
|
|
m_Value->SetDrawCoord();
|
|
|
|
|
|
|
|
// Displace contours and text of the footprint.
|
|
|
|
for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() )
|
|
|
|
{
|
|
|
|
if( item->Type() == PCB_MODULE_EDGE_T )
|
|
|
|
{
|
2014-09-10 15:18:42 +00:00
|
|
|
static_cast<EDGE_MODULE*>( item )->SetDrawCoord();
|
2013-03-13 18:53:58 +00:00
|
|
|
}
|
|
|
|
else if( item->Type() == PCB_MODULE_TEXT_T )
|
|
|
|
{
|
2014-09-10 15:18:42 +00:00
|
|
|
static_cast<TEXTE_MODULE*>( item )->SetDrawCoord();
|
2013-03-13 18:53:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CalculateBoundingBox();
|
|
|
|
}
|
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
BOARD_ITEM* MODULE::DuplicateAndAddItem( const BOARD_ITEM* aItem,
|
|
|
|
bool aIncrementPadNumbers )
|
|
|
|
{
|
|
|
|
BOARD_ITEM* new_item = NULL;
|
|
|
|
|
|
|
|
switch( aItem->Type() )
|
|
|
|
{
|
|
|
|
case PCB_PAD_T:
|
|
|
|
{
|
|
|
|
D_PAD* new_pad = new D_PAD( *static_cast<const D_PAD*>( aItem ) );
|
|
|
|
|
|
|
|
Pads().PushBack( new_pad );
|
|
|
|
new_item = new_pad;
|
|
|
|
break;
|
|
|
|
}
|
2016-03-07 07:13:06 +00:00
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
case PCB_MODULE_TEXT_T:
|
|
|
|
{
|
|
|
|
const TEXTE_MODULE* old_text = static_cast<const TEXTE_MODULE*>( aItem );
|
|
|
|
|
|
|
|
// do not duplicate value or reference fields
|
|
|
|
// (there can only be one of each)
|
|
|
|
if( old_text->GetType() == TEXTE_MODULE::TEXT_is_DIVERS )
|
|
|
|
{
|
|
|
|
TEXTE_MODULE* new_text = new TEXTE_MODULE( *old_text );
|
|
|
|
|
|
|
|
GraphicalItems().PushBack( new_text );
|
|
|
|
new_item = new_text;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-03-07 07:13:06 +00:00
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
case PCB_MODULE_EDGE_T:
|
|
|
|
{
|
|
|
|
EDGE_MODULE* new_edge = new EDGE_MODULE(
|
|
|
|
*static_cast<const EDGE_MODULE*>(aItem) );
|
|
|
|
|
|
|
|
GraphicalItems().PushBack( new_edge );
|
|
|
|
new_item = new_edge;
|
|
|
|
break;
|
|
|
|
}
|
2016-03-07 07:13:06 +00:00
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
case PCB_MODULE_T:
|
|
|
|
// Ignore the module itself
|
|
|
|
break;
|
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
default:
|
|
|
|
// Un-handled item for duplication
|
|
|
|
wxASSERT_MSG( false, "Duplication not supported for items of class "
|
|
|
|
+ aItem->GetClass() );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-03-22 09:42:41 +00:00
|
|
|
if( aIncrementPadNumbers && new_item )
|
|
|
|
{
|
|
|
|
new_item->IncrementItemReference();
|
|
|
|
}
|
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
return new_item;
|
|
|
|
}
|
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
wxString MODULE::GetNextPadName( bool aFillSequenceGaps ) const
|
|
|
|
{
|
|
|
|
std::set<int> usedNumbers;
|
|
|
|
|
|
|
|
// Create a set of used pad numbers
|
|
|
|
for( D_PAD* pad = Pads(); pad; pad = pad->Next() )
|
|
|
|
{
|
2015-02-12 03:22:24 +00:00
|
|
|
int padNumber = getTrailingInt( pad->GetPadName() );
|
2015-02-12 03:22:24 +00:00
|
|
|
usedNumbers.insert( padNumber );
|
|
|
|
}
|
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
const int nextNum = getNextNumberInSequence( usedNumbers, aFillSequenceGaps );
|
2015-02-12 03:22:24 +00:00
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
return wxString::Format( wxT( "%i" ), nextNum );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wxString MODULE::GetReferencePrefix() const
|
|
|
|
{
|
|
|
|
wxString prefix = GetReference();
|
|
|
|
|
|
|
|
int strIndex = prefix.length() - 1;
|
|
|
|
while( strIndex >= 0 )
|
2015-02-12 03:22:24 +00:00
|
|
|
{
|
2015-02-12 03:22:24 +00:00
|
|
|
const wxUniChar chr = prefix.GetChar( strIndex );
|
2015-02-12 03:22:24 +00:00
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
// numeric suffix
|
|
|
|
if( chr >= '0' && chr <= '9' )
|
|
|
|
break;
|
2015-02-12 03:22:24 +00:00
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
strIndex--;
|
|
|
|
}
|
|
|
|
|
|
|
|
prefix = prefix.Mid( 0, strIndex );
|
|
|
|
|
|
|
|
return prefix;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-22 09:42:41 +00:00
|
|
|
bool MODULE::IncrementItemReference()
|
|
|
|
{
|
|
|
|
// Take the next available module number
|
|
|
|
return IncrementReference( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
bool MODULE::IncrementReference( bool aFillSequenceGaps )
|
|
|
|
{
|
|
|
|
BOARD* board = GetBoard();
|
|
|
|
|
|
|
|
if( !board )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
bool success = false;
|
|
|
|
const wxString prefix = GetReferencePrefix();
|
|
|
|
const wxString newReference = board->GetNextModuleReferenceWithPrefix(
|
|
|
|
prefix, aFillSequenceGaps );
|
|
|
|
|
|
|
|
if( !newReference.IsEmpty() )
|
|
|
|
{
|
|
|
|
SetReference( newReference );
|
|
|
|
success = true;
|
2015-02-12 03:22:24 +00:00
|
|
|
}
|
|
|
|
|
2015-02-12 03:22:24 +00:00
|
|
|
return success;
|
2015-02-12 03:22:24 +00:00
|
|
|
}
|
2015-03-03 10:50:50 +00:00
|
|
|
|
2015-02-18 16:53:46 +00:00
|
|
|
|
2015-02-17 23:58:14 +00:00
|
|
|
double MODULE::PadCoverageRatio() const
|
|
|
|
{
|
|
|
|
double padArea = 0.0;
|
|
|
|
double moduleArea = GetFootprintRect().GetArea();
|
|
|
|
|
2015-03-03 10:50:50 +00:00
|
|
|
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
2015-02-17 23:58:14 +00:00
|
|
|
padArea += pad->GetBoundingBox().GetArea();
|
|
|
|
|
2015-03-03 10:50:50 +00:00
|
|
|
if( moduleArea == 0.0 )
|
2015-02-17 23:58:14 +00:00
|
|
|
return 1.0;
|
|
|
|
|
|
|
|
double ratio = padArea / moduleArea;
|
|
|
|
|
2015-02-18 16:53:46 +00:00
|
|
|
return std::min( ratio, 1.0 );
|
2015-02-17 23:58:14 +00:00
|
|
|
}
|