diff options
Diffstat (limited to 'pcbnew/collectors.cpp')
-rw-r--r-- | pcbnew/collectors.cpp | 501 |
1 files changed, 501 insertions, 0 deletions
diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp new file mode 100644 index 0000000..f58d4a3 --- /dev/null +++ b/pcbnew/collectors.cpp @@ -0,0 +1,501 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 2004-2007 KiCad Developers, see change_log.txt for contributors. + * + * 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 + */ + +#include <collectors.h> +#include <class_board_item.h> // class BOARD_ITEM + +#include <class_module.h> +#include <class_pad.h> +#include <class_track.h> +#include <class_marker_pcb.h> + + +/* This module contains out of line member functions for classes given in + * collectors.h. Those classes augment the functionality of class PCB_EDIT_FRAME. + */ + + +// see collectors.h +const KICAD_T GENERAL_COLLECTOR::AllBoardItems[] = { + // there are some restrictions on the order of items in the general case. + // all items in m_Drawings for instance should be contiguous. + // *** all items in a same list (shown here) must be contiguous **** + PCB_MARKER_T, // in m_markers + PCB_TEXT_T, // in m_Drawings + PCB_LINE_T, // in m_Drawings + PCB_DIMENSION_T, // in m_Drawings + PCB_TARGET_T, // in m_Drawings + PCB_VIA_T, // in m_Tracks + PCB_TRACE_T, // in m_Tracks + PCB_PAD_T, // in modules + PCB_MODULE_TEXT_T, // in modules + PCB_MODULE_T, // in m_Modules + PCB_ZONE_T, // in m_Zones + PCB_ZONE_AREA_T, // in m_ZoneDescriptorList + EOT +}; + + +/* + * const KICAD_T GENERAL_COLLECTOR::PrimaryItems[] = { + * PCB_TEXT_T, + * PCB_LINE_T, + * PCB_DIMENSION_T, + * PCB_VIA_T, + * PCB_TRACE_T, + * PCB_MODULE_T, + * EOT + * }; + */ + + +const KICAD_T GENERAL_COLLECTOR::AllButZones[] = { + PCB_MARKER_T, + PCB_TEXT_T, + PCB_LINE_T, + PCB_DIMENSION_T, + PCB_TARGET_T, + PCB_VIA_T, + PCB_TRACE_T, + PCB_PAD_T, + PCB_MODULE_TEXT_T, + PCB_MODULE_T, + PCB_ZONE_AREA_T, // if it is visible on screen, it should be selectable + EOT +}; + + +const KICAD_T GENERAL_COLLECTOR::Modules[] = { + PCB_MODULE_T, + EOT +}; + + +const KICAD_T GENERAL_COLLECTOR::PadsOrModules[] = { + PCB_PAD_T, + PCB_MODULE_T, + EOT +}; + + +const KICAD_T GENERAL_COLLECTOR::PadsTracksOrZones[] = { + PCB_PAD_T, + PCB_VIA_T, + PCB_TRACE_T, + PCB_ZONE_T, + PCB_ZONE_AREA_T, + EOT +}; + + +const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = { + PCB_MODULE_TEXT_T, + PCB_MODULE_EDGE_T, + PCB_PAD_T, + PCB_MODULE_T, + EOT +}; + + +const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = { + PCB_MODULE_TEXT_T, + PCB_MODULE_EDGE_T, + PCB_PAD_T, + EOT +}; + + +const KICAD_T GENERAL_COLLECTOR::Tracks[] = { + PCB_TRACE_T, + PCB_VIA_T, + EOT +}; + + +const KICAD_T GENERAL_COLLECTOR::Zones[] = { + PCB_ZONE_AREA_T, + EOT +}; + + + +/** + * Function Inspect + * is the examining function within the INSPECTOR which is passed to the + * Iterate function. Searches and collects all the objects that the old + * function PcbGeneralLocateAndDisplay() would find, except that it keeps all + * that it finds and does not do any displaying. + * + * @param testItem An EDA_ITEM to examine. + * @param testData The const void* testData, not used here. + * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan, + * else SCAN_CONTINUE; + */ +SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, const void* testData ) +{ + BOARD_ITEM* item = (BOARD_ITEM*) testItem; + MODULE* module = NULL; + D_PAD* pad = NULL; + bool pad_through = false; + VIA* via = NULL; + MARKER_PCB* marker = NULL; + +#if 0 // debugging + static int breakhere = 0; + + switch( item->Type() ) + { + case PCB_PAD_T: + { + MODULE* m = (MODULE*) item->GetParent(); + + if( m->GetReference() == wxT( "Y2" ) ) + { + breakhere++; + } + } + break; + + case PCB_VIA_T: + breakhere++; + break; + + case PCB_TRACE_T: + breakhere++; + break; + + case PCB_ZONE_T: + breakhere++; + break; + + case PCB_TEXT_T: + breakhere++; + break; + + case PCB_LINE_T: + breakhere++; + break; + + case PCB_DIMENSION_T: + breakhere++; + break; + + case PCB_MODULE_TEXT_T: + { + TEXTE_MODULE* tm = (TEXTE_MODULE*) item; + + if( tm->GetText() == wxT( "10uH" ) ) + { + breakhere++; + } + } + break; + + case PCB_MODULE_T: + { + MODULE* m = (MODULE*) item; + + if( m->GetReference() == wxT( "C98" ) ) + { + breakhere++; + } + } + break; + + case PCB_MARKER_T: + breakhere++; + break; + + default: + breakhere++; + break; + } + +#endif + + + switch( item->Type() ) + { + case PCB_PAD_T: + // there are pad specific visibility controls. + // Criterias to select a pad is: + // for smd pads: the module parent must be seen, and pads on the corresponding + // board side must be seen + // if pad is a thru hole, then it can be visible when its parent module is not. + // for through pads: pads on Front or Back board sides must be seen + pad = (D_PAD*) item; + + if( (pad->GetAttribute() != PAD_ATTRIB_SMD) && + (pad->GetAttribute() != PAD_ATTRIB_CONN) ) // a hole is present, so multiple layers + { + // proceed to the common tests below, but without the parent module test, + // by leaving module==NULL, but having pad != null + pad_through = true; + } + else // smd, so use pads test after module test + { + module = static_cast<MODULE*>( item->GetParent() ); + } + + break; + + case PCB_VIA_T: // vias are on many layers, so layer test is specific + via = static_cast<VIA*>( item ); + break; + + case PCB_TRACE_T: + break; + + case PCB_ZONE_T: + break; + + case PCB_ZONE_AREA_T: + break; + + case PCB_TEXT_T: + break; + + case PCB_LINE_T: + break; + + case PCB_DIMENSION_T: + break; + + case PCB_TARGET_T: + break; + + case PCB_MODULE_TEXT_T: + { + TEXTE_MODULE *text = static_cast<TEXTE_MODULE*>( item ); + if( m_Guide->IgnoreMTextsMarkedNoShow() && !text->IsVisible() ) + goto exit; + + if( m_Guide->IgnoreMTextsOnBack() && IsBackLayer( text->GetLayer() ) ) + goto exit; + + if( m_Guide->IgnoreMTextsOnFront() && IsFrontLayer( text->GetLayer() ) ) + goto exit; + + /* The three text types have different criteria: reference + * and value have their own ignore flags; user text instead + * follows their layer visibility. Checking this here is + * simpler than later (when layer visibility is checked for + * other entities) */ + + switch( text->GetType() ) + { + case TEXTE_MODULE::TEXT_is_REFERENCE: + if( m_Guide->IgnoreModulesRefs() ) + goto exit; + break; + + case TEXTE_MODULE::TEXT_is_VALUE: + if( m_Guide->IgnoreModulesVals() ) + goto exit; + break; + + case TEXTE_MODULE::TEXT_is_DIVERS: + if( !m_Guide->IsLayerVisible( text->GetLayer() ) + && m_Guide->IgnoreNonVisibleLayers() ) + goto exit; + break; + } + + // Extract the module since it could be hidden + module = static_cast<MODULE*>( item->GetParent() ); + } + break; + + case PCB_MODULE_T: + module = static_cast<MODULE*>( item ); + break; + + case PCB_MARKER_T: + marker = static_cast<MARKER_PCB*>( item ); + break; + + default: + break; + } + + // common tests: + + if( module ) // true from case PCB_PAD_T, PCB_MODULE_TEXT_T, or PCB_MODULE_T + { + if( m_Guide->IgnoreModulesOnBack() && (module->GetLayer() == B_Cu) ) + goto exit; + + if( m_Guide->IgnoreModulesOnFront() && (module->GetLayer() == F_Cu) ) + goto exit; + } + + // Pads are not sensitive to the layer visibility controls. + // They all have their own separate visibility controls + // skip them if not visible + if( pad ) + { + if( m_Guide->IgnorePads() ) + goto exit; + + if( ! pad_through ) + { + if( m_Guide->IgnorePadsOnFront() && pad->IsOnLayer(F_Cu ) ) + goto exit; + + if( m_Guide->IgnorePadsOnBack() && pad->IsOnLayer(B_Cu ) ) + goto exit; + } + } + + if( marker ) + { + // Markers are not sensitive to the layer + if( marker->HitTest( m_RefPos ) ) + Append( item ); + + goto exit; + } + + if( item->IsOnLayer( m_Guide->GetPreferredLayer() ) || + m_Guide->IgnorePreferredLayer() ) + { + LAYER_ID layer = item->GetLayer(); + + /* Modules and their subcomponents: reference, value and pads + * are not sensitive to the layer visibility controls. They all + * have their own separate visibility controls for vias, + * GetLayer() has no meaning, but IsOnLayer() works fine. User + * text in module *is* sensitive to layer visibility but that + * was already handled */ + + if( via || module || pad || m_Guide->IsLayerVisible( layer ) + || !m_Guide->IgnoreNonVisibleLayers() ) + { + if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() ) + { + if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() ) + { + if( item->HitTest( m_RefPos ) ) + { + Append( item ); + goto exit; + } + } + } + } + } + + + if( m_Guide->IncludeSecondary() ) + { + // for now, "secondary" means "tolerate any layer". It has + // no effect on other criteria, since there is a separate "ignore" control for + // those in the COLLECTORS_GUIDE + + LAYER_ID layer = item->GetLayer(); + + /* Modules and their subcomponents: reference, value and pads + * are not sensitive to the layer visibility controls. They all + * have their own separate visibility controls. User texts + * follows layer visibility controls (but that was already + * checked) */ + + if( via || module || pad || m_Guide->IsLayerVisible( layer ) + || !m_Guide->IgnoreNonVisibleLayers() ) + { + if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() ) + { + if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() ) + { + if( item->HitTest( m_RefPos ) ) + { + Append2nd( item ); + goto exit; + } + } + } + } + } + +exit: + return SEARCH_CONTINUE; // always when collecting +} + + +// see collectors.h +void GENERAL_COLLECTOR::Collect( BOARD_ITEM* aItem, const KICAD_T aScanList[], + const wxPoint& aRefPos, const COLLECTORS_GUIDE& aGuide ) +{ + Empty(); // empty the collection, primary criteria list + Empty2nd(); // empty the collection, secondary criteria list + + // remember guide, pass it to Inspect() + SetGuide( &aGuide ); + + SetScanTypes( aScanList ); + + // remember where the snapshot was taken from and pass refPos to + // the Inspect() function. + SetRefPos( aRefPos ); + + // visit the board or module with the INSPECTOR (me). + aItem->Visit( this, // INSPECTOR* inspector + NULL, // const void* testData, not used here + m_ScanTypes ); + + SetTimeNow(); // when snapshot was taken + + // record the length of the primary list before concatenating on to it. + m_PrimaryLength = m_List.size(); + + // append 2nd list onto end of the first list + for( unsigned i = 0; i<m_List2nd.size(); ++i ) + Append( m_List2nd[i] ); + + Empty2nd(); +} + + +// see collectors.h +SEARCH_RESULT PCB_TYPE_COLLECTOR::Inspect( EDA_ITEM* testItem, const void* testData ) +{ + // The Vist() function only visits the testItem if its type was in the + // the scanList, so therefore we can collect anything given to us here. + Append( testItem ); + + return SEARCH_CONTINUE; // always when collecting +} + + +void PCB_TYPE_COLLECTOR::Collect( BOARD_ITEM* aBoard, const KICAD_T aScanList[] ) +{ + Empty(); // empty any existing collection + + // visit the board with the INSPECTOR (me). + aBoard->Visit( this, // INSPECTOR* inspector + NULL, // const void* testData, + aScanList ); +} + +//EOF |