Commit 27bd9c75 authored by dickelbeck's avatar dickelbeck
Browse files

visitor design pattern, MODULE::FindPadOrModule()

parent 59b4c5ba
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -4,6 +4,14 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with 
email address.


2007-Aug-08 UPDATE   Dick Hollenbeck <dick@softplc.com>
================================================================================
+ pcbnew & common
    Released the new Visitor paradigm.   Wrote MODULE::FindPadOrModule() using
    it.


2007-aug-09 UPDATE   Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
+ eeschema
+39 −39
Original line number Diff line number Diff line
@@ -189,17 +189,54 @@ wxString EDA_BaseStruct::ReturnClassName() const
}


// see base_struct.h
SEARCH_RESULT EDA_BaseStruct::IterateForward( EDA_BaseStruct* listStart, 
    INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] )
{
    EDA_BaseStruct* p = listStart;
    for( ; p; p = p->Pnext )
    {
        if( SEARCH_QUIT == p->Visit( inspector, testData, scanTypes ) )
            return SEARCH_QUIT;
    }

    return SEARCH_CONTINUE;
}


// see base_struct.h
// many classes inherit this method, be careful:
SEARCH_RESULT EDA_BaseStruct::Visit( INSPECTOR* inspector, const void* testData, 
        const KICAD_T scanTypes[] )
{
    KICAD_T     stype;
    
    for( const KICAD_T* p = scanTypes;  (stype=*p) != EOT;   ++p )
    {
        // If caller wants to inspect my type
        if( stype == m_StructType )
        {
            if( SEARCH_QUIT == inspector->Inspect( this, testData ) )
                return SEARCH_QUIT;

            break;
        }
    }

    return SEARCH_CONTINUE;    
}


#if defined(DEBUG)
// A function that should have been in wxWidgets
std::ostream& operator<<( std::ostream& out, wxSize& size )
std::ostream& operator<<( std::ostream& out, const wxSize& size )
{
    out << " width=\"" << size.GetWidth() << "\" height=\"" << size.GetHeight() << "\"";
    return out;
}

// A function that should have been in wxWidgets
std::ostream& operator<<( std::ostream& out, wxPoint& pt )
std::ostream& operator<<( std::ostream& out, const wxPoint& pt )
{
    out << " x=\"" << pt.x << "\" y=\"" << pt.y << "\"";
    return out;
@@ -242,43 +279,6 @@ std::ostream& EDA_BaseStruct::NestedSpace( int nestLevel, std::ostream& os )
    return os;
}


// see base_struct.h
SEARCH_RESULT EDA_BaseStruct::IterateForward( EDA_BaseStruct* listStart, 
    INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] )
{
    EDA_BaseStruct* p = listStart;
    for( ; p; p = p->Pnext )
    {
        if( SEARCH_QUIT == p->Visit( inspector, testData, scanTypes ) )
            return SEARCH_QUIT;
    }

    return SEARCH_CONTINUE;
}


// see base_struct.h
// many classes inherit this method, be careful:
SEARCH_RESULT EDA_BaseStruct::Visit( INSPECTOR* inspector, const void* testData, 
        const KICAD_T scanTypes[] )
{
    KICAD_T     stype;
    
    for( const KICAD_T* p = scanTypes;  (stype=*p) != EOT;   ++p )
    {
        // If caller wants to inspect my type
        if( stype == m_StructType )
        {
            if( SEARCH_QUIT == inspector->Inspect( this, testData ) )
                return SEARCH_QUIT;

            break;
        }
    }

    return SEARCH_CONTINUE;    
}
#endif


+40 −43
Original line number Diff line number Diff line
@@ -8,8 +8,8 @@

#if defined(DEBUG)
#include <iostream>         // needed for Show()
extern std::ostream& operator<<( std::ostream& out, wxSize& size );
extern std::ostream& operator<<( std::ostream& out, wxPoint& pt );
extern std::ostream& operator<<( std::ostream& out, const wxSize& size );
extern std::ostream& operator<<( std::ostream& out, const wxPoint& pt );
#endif


@@ -75,7 +75,6 @@ enum DrawStructureType {
};


#if defined(DEBUG)      // new searching technique incubator 
enum SEARCH_RESULT {
    SEARCH_QUIT,
    SEARCH_CONTINUE
@@ -118,8 +117,6 @@ public:
    // retrieval here.
};

#endif


/********************************************************************/
/* Classes de base: servent a deriver les classes reellement utiles */
@@ -192,6 +189,44 @@ public:
    }


    /**
     * Function IterateForward
     * walks through the object tree calling the testFunc on each object 
     * type requested in scanTypes.
     *
     * @param listStart The first in a list of EDA_BaseStructs to iterate over. 
     * @param inspector Is an INSPECTOR to call on each object that is one of 
     *  the requested scanTypes.
     * @param testData Is an aid to testFunc, and should be sufficient to 
     *  allow it to fully determine if an item meets the match criteria, but it
     *  may also be used to collect output.
     * @param scanTypes A KICAD_T array that is EOT 
     *  terminated, and provides both the order and interest level of of
     *  the types of objects to be iterated over.
     * @return SEARCH_RESULT - SEARCH_QUIT if the called INSPECTOR returned 
     *  SEARCH_QUIT, else SCAN_CONTINUE;
     */
    static SEARCH_RESULT IterateForward( EDA_BaseStruct* listStart, 
        INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] );

    
    /**
     * Function Visit
     * may be re-implemented for each derived class in order to handle
     * all the types given by its member data.  Implementations should call
     * inspector->Inspect() on types in scanTypes[], and may use IterateForward()
     * to do so on lists of such data.
     * @param inspector An INSPECTOR instance to use in the inspection.
     * @param testData Arbitrary data used by the inspector.
     * @param scanTypes Which KICAD_T types are of interest and the order 
     *  is significant too, terminated by EOT.
     * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan,
     *  else SCAN_CONTINUE, and determined by the inspector.
     */
    virtual SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, 
        const KICAD_T scanTypes[] );

    
#if defined(DEBUG)

    /**
@@ -230,44 +265,6 @@ public:
    static std::ostream& NestedSpace( int nestLevel, std::ostream& os );

    
    /**
     * Function IterateForward
     * walks through the object tree calling the testFunc on each object 
     * type requested in scanTypes.
     *
     * @param listStart The first in a list of EDA_BaseStructs to iterate over. 
     * @param inspector Is an INSPECTOR to call on each object that is one of 
     *  the requested scanTypes.
     * @param testData Is an aid to testFunc, and should be sufficient to 
     *  allow it to fully determine if an item meets the match criteria, but it
     *  may also be used to collect output.
     * @param scanTypes A KICAD_T array that is EOT 
     *  terminated, and provides both the order and interest level of of
     *  the types of objects to be iterated over.
     * @return SEARCH_RESULT - SEARCH_QUIT if the called INSPECTOR returned 
     *  SEARCH_QUIT, else SCAN_CONTINUE;
     */
    static SEARCH_RESULT IterateForward( EDA_BaseStruct* listStart, 
        INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] );

    
    /**
     * Function Visit
     * should be re-implemented for each derived class in order to handle
     * all the types given by its member data.  Implementations should call
     * inspector->Inspect() on types in scanTypes[], and may use IterateForward()
     * to do so on lists of such data.
     * @param inspector An INSPECTOR instance to use in the inspection.
     * @param testData Arbitrary data used by the inspector.
     * @param scanTypes Which KICAD_T types are of interest and the order 
     *  is significant too, terminated by EOT.
     * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan,
     *  else SCAN_CONTINUE, and determined by the inspector.
     */
    virtual SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, 
        const KICAD_T scanTypes[] );

    
    /**
     * Function ListHas
     * scans the given array and detects if the given type t is present.
+31 −13
Original line number Diff line number Diff line
@@ -234,18 +234,46 @@ public:
    bool    ComputeBoundaryBox( void );

    
    /**
     * Function Visit
     * may be re-implemented for each derived class in order to handle
     * all the types given by its member data.  Implementations should call
     * inspector->Inspect() on types in scanTypes[], and may use IterateForward()
     * to do so on lists of such data.
     * @param inspector An INSPECTOR instance to use in the inspection.
     * @param testData Arbitrary data used by the inspector.
     * @param scanTypes Which KICAD_T types are of interest and the order 
     *  is significant too, terminated by EOT.
     * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan,
     *  else SCAN_CONTINUE, and determined by the inspector.
     */
    SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, 
        const KICAD_T scanTypes[] );


    /**
     * Function FindPadOrModule
     * searches for either a pad or module, giving precedence to pads.
     * Any Pad or Module on the desired layer that HitTest()s true will be
     * returned, otherwise any visible Pad or Module on any other layer.
     * The provided layer must be visible.
     * @param refPos The wxPoint to hit-test.
     * @return EDA_BaseStruct* - if a direct hit, else NULL.
     */
    EDA_BaseStruct* FindPadOrModule( const wxPoint& refPos, int layer );
    
    
#if defined(DEBUG)
    /**
     * Function GetClass
     * returns the class name.
     * @return wxString
     */
    virtual wxString GetClass() const
    wxString GetClass() const
    {
        return wxT( "BOARD" );
    }

    
    /**
     * Function Show
     * is used to output the object tree, currently for debugging only.
@@ -253,17 +281,7 @@ public:
     *          of nesting of this object within the overall tree.
     * @param os The ostream& to output to.
     */
    virtual void Show( int nestLevel, std::ostream& os );

    
    /**
     * Function FindPadOrModule
     * searches for either a pad or module, giving precedence to pads.
     * @param refPos The wxPoint to hit-test.
     * @param typeloc 
     * @return EDA_BaseStruct* - if a direct hit, else NULL.
     */
    EDA_BaseStruct* FindPadOrModule( const wxPoint& refPos, int layer );
    void Show( int nestLevel, std::ostream& os );

#endif
};
+124 −56
Original line number Diff line number Diff line
@@ -256,66 +256,71 @@ bool BOARD::ComputeBoundaryBox( void )
}


#if defined(DEBUG)
// virtual, see pcbstruct.h     
SEARCH_RESULT BOARD::Visit( INSPECTOR* inspector, const void* testData, 
    const KICAD_T scanTypes[] )
{
    KICAD_T         stype;
    SEARCH_RESULT   result = SEARCH_CONTINUE;
    const KICAD_T*  p = scanTypes;
    
/**
 * Function Show
 * is used to output the object tree, currently for debugging only.
 * @param nestLevel An aid to prettier tree indenting, and is the level 
 *          of nesting of this object within the overall tree.
 * @param os The ostream& to output to.
 */
void BOARD::Show( int nestLevel, std::ostream& os )
    while( (stype = *p++) != EOT )
    {
    EDA_BaseStruct* p;
        switch( stype )
        {
        case TYPEPCB:
            result = inspector->Inspect( this, testData );  // inspect me
            break;

    // for now, make it look like XML:
    NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
        /*  Instances of the requested KICAD_T live in a list, either one
            that I manage, or that my modules manage.  If it's a type managed
            by class MODULE, then simply pass it on to each module's 
            MODULE::Visit() function by way of the 
            IterateForward( m_Modules, ... ) call.
        */ 
            
    // specialization of the output:
    NestedSpace( nestLevel+1, os ) << "<modules>\n";
    p = m_Modules;
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</modules>\n";
        case TYPEMODULE:
        case TYPEPAD:
        case TYPETEXTEMODULE:
        case TYPEEDGEMODULE:
            // this calls MODULE::Visit() on each module.
            result = IterateForward( m_Modules, inspector, testData, scanTypes );
            break;

    NestedSpace( nestLevel+1, os ) << "<pdrawings>\n";
    p = m_Drawings;
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</pdrawings>\n";
        case TYPEDRAWSEGMENT:
        case TYPETEXTE:
        case TYPEMARQUEUR:
        case TYPECOTATION:
        case TYPEMIRE:
            result = IterateForward( m_Drawings, inspector, testData, scanTypes );
            break;
            
    NestedSpace( nestLevel+1, os ) << "<nets>\n";
    p = m_Equipots;
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</nets>\n";
        case TYPEVIA:
        case TYPETRACK:
            result = IterateForward( m_Track, inspector, testData, scanTypes );
            break;            
            
    NestedSpace( nestLevel+1, os ) << "<tracks>\n";
    p = m_Track;    
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</tracks>\n";
        case PCB_EQUIPOT_STRUCT_TYPE:
            result = IterateForward( m_Equipots, inspector, testData, scanTypes );
            break;            

    NestedSpace( nestLevel+1, os ) << "<zones>\n";
    p = m_Zone;    
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</zones>\n";
        case TYPEZONE:
            result = IterateForward( m_Zone, inspector, testData, scanTypes );
            break;
            
    NestedSpace( nestLevel+1, os ) << "<edgezones>\n";
    p = m_CurrentLimitZone;
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</edgezones>\n";
        case TYPEEDGEZONE:
            result = IterateForward( m_CurrentLimitZone, inspector, testData, scanTypes );
            break;            
            
    p = m_Son;
    for( ; p;  p = p->Pnext )
    {
        p->Show( nestLevel+1, os );
        default:
            break;
        }
        
    NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
        if( result == SEARCH_QUIT )
            break;
    }

    return result;    
}


@@ -381,4 +386,67 @@ EDA_BaseStruct* BOARD::FindPadOrModule( const wxPoint& refPos, int layer )
    return inspector.found;
}


#if defined(DEBUG)

/**
 * Function Show
 * is used to output the object tree, currently for debugging only.
 * @param nestLevel An aid to prettier tree indenting, and is the level 
 *          of nesting of this object within the overall tree.
 * @param os The ostream& to output to.
 */
void BOARD::Show( int nestLevel, std::ostream& os )
{
    EDA_BaseStruct* p;
    
    // for now, make it look like XML:
    NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";

    // specialization of the output:
    NestedSpace( nestLevel+1, os ) << "<modules>\n";
    p = m_Modules;
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</modules>\n";

    NestedSpace( nestLevel+1, os ) << "<pdrawings>\n";
    p = m_Drawings;
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</pdrawings>\n";
    
    NestedSpace( nestLevel+1, os ) << "<nets>\n";
    p = m_Equipots;
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</nets>\n";

    NestedSpace( nestLevel+1, os ) << "<tracks>\n";
    p = m_Track;    
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</tracks>\n";

    NestedSpace( nestLevel+1, os ) << "<zones>\n";
    p = m_Zone;    
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</zones>\n";

    NestedSpace( nestLevel+1, os ) << "<edgezones>\n";
    p = m_CurrentLimitZone;
    for( ; p; p = p->Pnext )
        p->Show( nestLevel+2, os );
    NestedSpace( nestLevel+1, os ) << "</edgezones>\n";
    
    p = m_Son;
    for( ; p;  p = p->Pnext )
    {
        p->Show( nestLevel+1, os );
    }
    
    NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
}

#endif
Loading