Commit 27bd9c75 authored by dickelbeck's avatar dickelbeck

visitor design pattern, MODULE::FindPadOrModule()

parent 59b4c5ba
......@@ -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
......
......@@ -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
......
......@@ -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 */
......@@ -191,6 +188,44 @@ public:
return false; // derived classes should override this function
}
/**
* 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.
......
......@@ -232,6 +232,35 @@ public:
// Calcul du rectangle d'encadrement:
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)
......@@ -240,12 +269,11 @@ public:
* 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,18 +281,8 @@ 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 );
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 );
#endif
};
......
......@@ -256,66 +256,71 @@ bool BOARD::ComputeBoundaryBox( void )
}
#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 )
// virtual, see pcbstruct.h
SEARCH_RESULT BOARD::Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] )
{
EDA_BaseStruct* p;
KICAD_T stype;
SEARCH_RESULT result = SEARCH_CONTINUE;
const KICAD_T* p = scanTypes;
// 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 )
while( (stype = *p++) != EOT )
{
p->Show( nestLevel+1, os );
switch( stype )
{
case TYPEPCB:
result = inspector->Inspect( this, testData ); // inspect me
break;
/* 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.
*/
case TYPEMODULE:
case TYPEPAD:
case TYPETEXTEMODULE:
case TYPEEDGEMODULE:
// this calls MODULE::Visit() on each module.
result = IterateForward( m_Modules, inspector, testData, scanTypes );
break;
case TYPEDRAWSEGMENT:
case TYPETEXTE:
case TYPEMARQUEUR:
case TYPECOTATION:
case TYPEMIRE:
result = IterateForward( m_Drawings, inspector, testData, scanTypes );
break;
case TYPEVIA:
case TYPETRACK:
result = IterateForward( m_Track, inspector, testData, scanTypes );
break;
case PCB_EQUIPOT_STRUCT_TYPE:
result = IterateForward( m_Equipots, inspector, testData, scanTypes );
break;
case TYPEZONE:
result = IterateForward( m_Zone, inspector, testData, scanTypes );
break;
case TYPEEDGEZONE:
result = IterateForward( m_CurrentLimitZone, inspector, testData, scanTypes );
break;
default:
break;
}
if( result == SEARCH_QUIT )
break;
}
NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
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
......@@ -829,7 +829,8 @@ void MODULE::SetPosition( const wxPoint& newpos )
D_PAD* pad = m_Pads;
for( ; pad != NULL; pad = (D_PAD*) pad->Pnext )
{
pad->m_Pos.x += deltaX; pad->m_Pos.y += deltaY;
pad->m_Pos.x += deltaX;
pad->m_Pos.y += deltaY;
}
/* deplacement des dessins de l'empreinte : */
......@@ -848,7 +849,8 @@ void MODULE::SetPosition( const wxPoint& newpos )
case TYPETEXTEMODULE:
{
TEXTE_MODULE* pt_texte = (TEXTE_MODULE*) PtStruct;
pt_texte->m_Pos.x += deltaX; pt_texte->m_Pos.y += deltaY;
pt_texte->m_Pos.x += deltaX;
pt_texte->m_Pos.y += deltaY;
break;
}
......@@ -1168,6 +1170,54 @@ bool MODULE::HitTest( const wxPoint& refPos )
}
// see class_module.h
SEARCH_RESULT MODULE::Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] )
{
KICAD_T stype;
SEARCH_RESULT result = SEARCH_CONTINUE;
const KICAD_T* p = scanTypes;
while( (stype = *p++) != EOT )
{
switch( stype )
{
case TYPEMODULE:
result = inspector->Inspect( this, testData ); // inspect me
break;
case TYPEPAD:
result = IterateForward( m_Pads, inspector, testData, scanTypes );
break;
case TYPETEXTEMODULE:
result = inspector->Inspect( m_Reference, testData );
if( result == SEARCH_QUIT )
break;
result = inspector->Inspect( m_Value, testData );
if( result == SEARCH_QUIT )
break;
// m_Drawings can hold TYPETEXTMODULE also?
result = IterateForward( m_Drawings, inspector, testData, scanTypes );
break;
case TYPEEDGEMODULE:
result = IterateForward( m_Drawings, inspector, testData, scanTypes );
break;
default:
break;
}
if( result == SEARCH_QUIT )
break;
}
return result;
}
#if defined(DEBUG)
/**
......@@ -1213,50 +1263,4 @@ void MODULE::Show( int nestLevel, std::ostream& os )
NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
}
// see class_module.h
SEARCH_RESULT MODULE::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;
}
else if( stype == TYPEPAD )
{
if( SEARCH_QUIT == IterateForward( m_Pads, inspector,
testData, scanTypes ) )
return SEARCH_QUIT;
}
else if( stype == TYPETEXTEMODULE )
{
if( SEARCH_QUIT == inspector->Inspect( m_Reference, testData ) )
return SEARCH_QUIT;
if( SEARCH_QUIT == inspector->Inspect( m_Value, testData ) )
return SEARCH_QUIT;
// m_Drawings can hold TYPETEXTMODULE also?
if( SEARCH_QUIT == IterateForward( m_Drawings, inspector,
testData, scanTypes ) )
return SEARCH_QUIT;
}
else if( stype == TYPEEDGEMODULE )
{
// iterate over m_Drawings
if( SEARCH_QUIT == IterateForward( m_Drawings, inspector,
testData, scanTypes ) )
return SEARCH_QUIT;
}
}
return SEARCH_CONTINUE;
}
#endif
......@@ -143,6 +143,23 @@ public:
bool HitTest( const wxPoint& refPos );
/**
* 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;
*/
SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] );
#if defined(DEBUG)
/**
* Function GetClass
......@@ -164,23 +181,6 @@ public:
*/
virtual void Show( int nestLevel, std::ostream& os );
/**
* 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;
*/
virtual SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] );
#endif
};
......@@ -125,13 +125,8 @@ void WinEDA_PcbFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
break;
case ID_PCB_SHOW_1_RATSNEST_BUTT:
#if defined(DEBUG)
DrawStruct = m_Pcb->FindPadOrModule(
GetScreen()->RefPos(true),
DrawStruct = m_Pcb->FindPadOrModule( GetScreen()->RefPos(true),
GetScreen()->m_Active_Layer );
#else
DrawStruct = PcbGeneralLocateAndDisplay();
#endif
Show_1_Ratsnest( DrawStruct, DC );
break;
......
......@@ -301,7 +301,8 @@ bool WinEDA_PcbFrame::SavePcbFile( const wxString& FileName )
}
else
{
old_name = wxEmptyString; saveok = FALSE;
old_name = wxEmptyString;
saveok = FALSE;
}
/* Sauvegarde de l'ancien fichier */
......@@ -317,7 +318,10 @@ bool WinEDA_PcbFrame::SavePcbFile( const wxString& FileName )
{
GetScreen()->m_FileName = FullFileName;
SetTitle( GetScreen()->m_FileName );
SavePcbFormatAscii( dest );
fclose( dest );
}
......
This diff is collapsed.
......@@ -1082,8 +1082,11 @@ int WinEDA_PcbFrame::SavePcbFormatAscii( FILE* File )
/* Ecriture des donnes utiles du pcb */
Equipot = m_Pcb->m_Equipots;
Pas = 100.0; if( m_Pcb->m_NbNets )
Pas = 100.0;
if( m_Pcb->m_NbNets )
Pas /= m_Pcb->m_NbNets;
for( ii = 0; Equipot != NULL; ii++, Equipot = (EQUIPOT*) Equipot->Pnext )
{
Equipot->WriteEquipotDescr( File );
......
......@@ -896,7 +896,7 @@ TEXTE_PCB* Locate_Texte_Pcb( EDA_BaseStruct* PtStruct, int LayerSearch, int type
if( pt_txt_pcb->m_Layer == LayerSearch )
{
// because HitTest() is present in both base classes of TEXTE_PCB
// use a dis-ambiguating cast to tell compiler which HitTest()
// use a clarifying cast to tell compiler which HitTest()
// to call.
if( static_cast<EDA_TextStruct*>(pt_txt_pcb)->HitTest( ref ) )
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment