Loading new/make-dir-lib-source-test-data.sh +3 −3 Original line number Original line Diff line number Diff line Loading @@ -10,7 +10,7 @@ REVS="rev1 rev5 rev10" REFERENCE=" REFERENCE=" (reference U (reference U? (effects (at 12 13 180)(font (size .7 1))(visible yes)) (effects (at 12 13 180)(font (size .7 1))(visible yes)) )" )" Loading Loading @@ -71,7 +71,7 @@ for C in ${CATEGORIES}; do for P in ${PARTS}; do for P in ${PARTS}; do for R in ${REVS}; do for R in ${REVS}; do echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane) echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)(datasheet http://favorite.pdf) $REFERENCE $REFERENCE $LINE $LINE $RECT $RECT Loading @@ -86,7 +86,7 @@ for C in ${CATEGORIES}; do )" > $BASEDIR/$C/$P.part.$R )" > $BASEDIR/$C/$P.part.$R done done # also make the part without a rev: # also make the part without a rev: echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane) echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)(datasheet http://favorite.pdf) $REFERENCE $REFERENCE $LINE $LINE $RECT $RECT Loading new/sch_part.cpp +340 −9 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <sch_sweet_parser.h> #include <sch_sweet_parser.h> #include <sch_lpid.h> #include <sch_lpid.h> #include <sch_lib_table.h> #include <sch_lib_table.h> #include <macros.h> //#include <richio.h> //#include <richio.h> using namespace SCH; using namespace SCH; Loading @@ -38,16 +39,21 @@ PART::PART( LIB* aOwner, const STRING& aPartNameAndRev ) : contains( 0 ), contains( 0 ), partNameAndRev( aPartNameAndRev ), partNameAndRev( aPartNameAndRev ), extends( 0 ), extends( 0 ), base( 0 ), base( 0 ) /* reference( this, wxT( "reference " ) ), reference( this, wxT( "reference " ) ), value( this, wxT( "value" ) ), value( this, wxT( "value" ) ), footprint( this, wxT( "footprint" ) ), footprint( this, wxT( "footprint" ) ), model( this, wxT( "model" ) ), model( this, wxT( "model" ) ), datasheet( this, wxT( "datasheet" ) ) datasheet( this, wxT( "datasheet" ) ) */ { { // Our goal is to have class LIB only instantiate what is needed, so print here // Our goal is to have class LIB only instantiate what is needed, so print here // what it is doing. It is the only class where PART can be instantiated. // what it is doing. It is the only class where PART can be instantiated. D(printf("PART::PART(%s)\n", aPartNameAndRev.c_str() );) D(printf("PART::PART(%s)\n", aPartNameAndRev.c_str() );) for( int i=REFERENCE; i<END; ++i ) mandatory[i] = 0; } } Loading @@ -69,7 +75,7 @@ void PART::clear() delete *it; delete *it; pins.clear(); pins.clear(); // delete non-mandatory properties I own, since their container will not destroy them: // delete properties I own, since their container will not destroy them: for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it ) for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it ) delete *it; delete *it; properties.clear(); properties.clear(); Loading @@ -78,7 +84,54 @@ void PART::clear() contains = 0; contains = 0; // @todo clear the mandatory fields // clear the mandatory fields for( int ndx = REFERENCE; ndx < END; ++ndx ) { delete mandatory[ndx]; mandatory[ndx] = 0; } } PROPERTY* PART::FieldLookup( PROP_ID aPropertyId ) { wxASSERT( unsigned(aPropertyId) < unsigned(END) ); PROPERTY* p = mandatory[aPropertyId]; if( !p ) { switch( aPropertyId ) { case REFERENCE: p = new PROPERTY( this, wxT( "reference" ) ); p->text = wxT( "U?" ); break; case VALUE: p = new PROPERTY( this, wxT( "value" ) ); break; case FOOTPRINT: p = new PROPERTY( this, wxT( "footprint" ) ); break; case DATASHEET: p = new PROPERTY( this, wxT( "datasheet" ) ); break; case MODEL: p = new PROPERTY( this, wxT( "model" ) ); break; default: ; } mandatory[aPropertyId] = p; } return p; } } Loading Loading @@ -151,7 +204,8 @@ PROPERTIES::iterator PART::propertyFind( const wxString& aPropertyName ) } } void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { { out->Print( indent, "(part %s", partNameAndRev.c_str() ); out->Print( indent, "(part %s", partNameAndRev.c_str() ); Loading @@ -160,12 +214,13 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E out->Print( 0, "\n" ); out->Print( 0, "\n" ); /* for( int i = REFERENCE; i < END; ++i ) @todo for( int i=0; i<MANDATORY_FIELDS; ++i ) { { PROPERTY* prop = Field( PROP_ID( i ) ); if( prop ) prop->Format( out, indent+1, ctl ); } } */ for( PROPERTIES::const_iterator it = properties.begin(); it != properties.end(); ++it ) for( PROPERTIES::const_iterator it = properties.begin(); it != properties.end(); ++it ) { { (*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl ); Loading @@ -178,6 +233,14 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E InternalToLogical( anchor.y ) ); InternalToLogical( anchor.y ) ); } } if( keywords.size() ) { out->Print( indent+1, "(keywords" ); for( KEYWORDS::iterator it = keywords.begin(); it != keywords.end(); ++it ) out->Print( 0, " %s", out->Quotew( *it ).c_str() ); out->Print( 0, ")\n" ); } for( GRAPHICS::const_iterator it = graphics.begin(); it != graphics.end(); ++it ) for( GRAPHICS::const_iterator it = graphics.begin(); it != graphics.end(); ++it ) { { (*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl ); Loading @@ -187,6 +250,274 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E { { (*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl ); } } out->Print( indent, ")\n" ); } //-----< PART objects >------------------------------------------------------ void PROPERTY::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { wxASSERT( owner ); // all PROPERTYs should have an owner. int i; for( i = PART::REFERENCE; i < PART::END; ++i ) { if( owner->Field( PART::PROP_ID(i) ) == this ) break; } if( i < PART::END ) // is a field not a property out->Print( indent, "(%s", TO_UTF8( name ) ); else out->Print( indent, "(property %s", out->Quotew( name ).c_str() ); if( effects ) { out->Print( 0, " %s\n", out->Quotew( text ).c_str() ); effects->Format( out, indent+1, ctl | CTL_OMIT_NL ); out->Print( 0, ")\n" ); } else { out->Print( 0, " %s)\n", out->Quotew( text ).c_str() ); } } TEXT_EFFECTS* PROPERTY::EffectsLookup() { if( !effects ) { effects = new TEXT_EFFECTS(); } return effects; } void TEXT_EFFECTS::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { if( propName.IsEmpty() ) out->Print( indent, "(effects " ); else out->Print( indent, "(effects %s ", out->Quotew( propName ).c_str() ); out->Print( 0, "(at %.6g %.6g", InternalToLogical( pos.x ), InternalToLogical( pos.y ) ); if( angle ) out->Print( 0, " %.6g)", double( angle ) ); else out->Print( 0, ")" ); font.Format( out, 0, ctl | CTL_OMIT_NL ); out->Print( 0, "(visible %s))%s", isVisible ? "yes" : "no", ctl & CTL_OMIT_NL ? "" : "\n" ); } void FONT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { if( name.IsEmpty() ) out->Print( indent, "(font " ); else out->Print( indent, "(font %s ", out->Quotew( name ).c_str() ); out->Print( 0, "(size %.6g %.6g)", InternalToLogical( size.GetHeight() ), InternalToLogical( size.GetWidth() ) ); if( italic ) out->Print( 0, " italic" ); if( bold ) out->Print( 0, " bold" ); out->Print( 0, ")%s", (ctl & CTL_OMIT_NL) ? "" : "\n" ); } void PIN::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( indent, "(pin %s %s ", ShowType(), ShowShape() ); if( angle ) out->Print( 0, "(at %.6g %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ), double(angle) ); else out->Print( 0, "(at %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ) ); out->Print( 0, "(length %.6g)", InternalToLogical( length ) ); out->Print( 0, "(visible %s)\n", isVisible ? "yes" : "no" ); signal.Format( out, "signal", indent+1, 0 ); padname.Format( out, "padname", indent+1, CTL_OMIT_NL ); out->Print( 0, ")\n" ); } void PINTEXT::Format( OUTPUTFORMATTER* out, const char* aElement, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( indent, "(%s %s ", aElement, out->Quotew( text ).c_str() ); font.Format( out, 0, CTL_OMIT_NL ); out->Print( 0, "(visible %s))%s", isVisible ? "yes" : "no", ctl & CTL_OMIT_NL ? "" : "\n" ); } void POLY_LINE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( indent, "(%s ", pts.size() == 2 ? "line" : "polyline" ); formatContents( out, indent, ctl ); } void POLY_LINE::formatContents( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( 0, "(line_width %.6g)", lineWidth ); // @todo use logical units? if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, "\n" ); if( pts.size() ) { const int maxLength = 75; int len = 10; len += out->Print( indent+1, "(pts " ); for( POINTS::const_iterator it = pts.begin(); it != pts.end(); ++it ) { if( len > maxLength ) { len = 10; out->Print( 0, "\n" ); out->Print( indent+2, "(xy %.6g %.6g)", InternalToLogical( it->x ), InternalToLogical( it->y ) ); } else out->Print( 0, "(xy %.6g %.6g)", InternalToLogical( it->x ), InternalToLogical( it->y ) ); } out->Print( 0, ")" ); } out->Print( 0, ")\n" ); } void BEZIER::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( indent, "(bezier " ); formatContents( out, indent, ctl ); // inherited from POLY_LINE } void RECTANGLE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { // (rectangle (start X Y) (end X Y) (line_width WIDTH) (fill FILL_TYPE)) out->Print( indent, "(rectangle (start %.6g %.6g)(end %.6g %.6g)(line_width %.6g)", InternalToLogical( start.x ), InternalToLogical( start.y ), InternalToLogical( end.x ), InternalToLogical( end.y ), lineWidth ); if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, ")\n" ); } } void CIRCLE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { /* (circle (center X Y)(radius LENGTH)(line_width WIDTH)(fill FILL_TYPE)) */ out->Print( indent, "(circle (center %.6g %.6g)(radius %.6g)(line_width %.6g)", InternalToLogical( center.x ), InternalToLogical( center.y ), InternalToLogical( radius), lineWidth ); if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, ")\n" ); } void ARC::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { /* (arc (pos X Y)(radius RADIUS)(start X Y)(end X Y)(line_width WIDTH)(fill FILL_TYPE)) */ out->Print( indent, "(arc (pos %.6g %.6g)(radius %.6g)(start %.6g %.6g)(end %.6g %.6g)(line_width %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ), InternalToLogical( radius), InternalToLogical( start.x ), InternalToLogical( start.y ), InternalToLogical( end.x ), InternalToLogical( end.y ), lineWidth ); if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, ")\n" ); } void GR_TEXT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { /* (text "This is the text that gets drawn." (at X Y [ANGLE]) # Valid horizontal justification values are center, right, and left. Valid # vertical justification values are center, top, bottom. (justify HORIZONTAL_JUSTIFY VERTICAL_JUSTIFY) (font [FONT] (size HEIGHT WIDTH) [italic] [bold]) (visible YES) (fill FILL_TYPE) ) */ out->Print( indent, "(text %s\n", out->Quotew( text ).c_str() ); if( angle ) out->Print( indent+1, "(at %.6g %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ), double( angle ) ); else out->Print( indent+1, "(at %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ) ); out->Print( 0, "(justify %s %s)(visible %s)", ShowJustify( hjustify ), ShowJustify( vjustify ), isVisible ? "yes" : "no" ); if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, "\n" ); font.Format( out, indent+1, CTL_OMIT_NL ); out->Print( 0, ")\n" ); } new/sch_part.h +258 −92 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,32 @@ #include <sch_lib.h> #include <sch_lib.h> #define INTERNAL_PER_LOGICAL 10000 ///< no. internal units per logical unit /** * Function InternalToLogical * converts an internal coordinate to a logical coordinate. Logical coordinates * are defined as the standard distance between pins being equal to one. * Internal coordinates are currently INTERNAL_PER_LOGICAL times that. */ static inline double InternalToLogical( int aCoord ) { return double( aCoord ) / INTERNAL_PER_LOGICAL; } /** * Function LogicalToInternal * converts a logical coordinate to an internal coordinate. Logical coordinates * are defined as the standard distance between pins being equal to one. * Internal coordinates are currently INTERNAL_PER_LOGICAL times that. */ static inline int LogicalToInternal( double aCoord ) { return int( aCoord * INTERNAL_PER_LOGICAL ); } //-----<temporary home for PART sub objects, move after stable>------------------ //-----<temporary home for PART sub objects, move after stable>------------------ #include <wx/gdicmn.h> #include <wx/gdicmn.h> Loading @@ -39,6 +65,9 @@ class OUTPUTFORMATTER; class OUTPUTFORMATTER; /// Control Bits for Format() functions #define CTL_OMIT_NL (1<<0) ///< omit new line in Format()s. namespace SCH { namespace SCH { class PART; class PART; Loading Loading @@ -81,6 +110,9 @@ public: italic( false ), italic( false ), bold( false ) bold( false ) {} {} void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -99,6 +131,9 @@ struct TEXT_EFFECTS isVisible( false ), isVisible( false ), property( 0 ) property( 0 ) {} {} void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -117,7 +152,16 @@ public: virtual ~BASE_GRAPHIC() {} virtual ~BASE_GRAPHIC() {} virtual void Format( OUTPUTFORMATTER* aOutputFormatter, int aNestLevel, int aControlBits ) const static const char* ShowFill( int aFillType ) { return SWEET_LEXER::TokenName( PR::T( aFillType ) ); } /** * Function Format * outputs this object to @a aFormatter in s-expression form. */ virtual void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ) throw( IO_ERROR ) {} {} }; }; Loading @@ -134,10 +178,19 @@ protected: int fillType; // T_none, T_filled, or T_transparent int fillType; // T_none, T_filled, or T_transparent POINTS pts; POINTS pts; void formatContents( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); public: public: POLY_LINE( PART* aOwner ) : POLY_LINE( PART* aOwner ) : BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ), {} lineWidth( 1 ), fillType( PR::T_none ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; class BEZIER : public POLY_LINE class BEZIER : public POLY_LINE Loading @@ -148,7 +201,13 @@ class BEZIER : public POLY_LINE public: public: BEZIER( PART* aOwner ) : BEZIER( PART* aOwner ) : POLY_LINE( aOwner ) POLY_LINE( aOwner ) {} { lineWidth = 1; fillType = PR::T_none; } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; class RECTANGLE : public BASE_GRAPHIC class RECTANGLE : public BASE_GRAPHIC Loading @@ -164,8 +223,14 @@ protected: public: public: RECTANGLE( PART* aOwner ) : RECTANGLE( PART* aOwner ) : BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ), {} lineWidth( 1 ), fillType( PR::T_none ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -182,8 +247,15 @@ protected: public: public: CIRCLE( PART* aOwner ) : CIRCLE( PART* aOwner ) : BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ), {} radius( LogicalToInternal( 0.5 ) ), lineWidth( 1 ), fillType( PR::T_none ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -202,8 +274,15 @@ protected: public: public: ARC( PART* aOwner ) : ARC( PART* aOwner ) : BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ), {} lineWidth( 1 ), fillType( PR::T_none ), radius( LogicalToInternal( 0.5 ) ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading Loading @@ -233,6 +312,14 @@ public: vjustify( PR::T_bottom ), vjustify( PR::T_bottom ), isVisible( true ) isVisible( true ) {} {} static const char* ShowJustify( int aJustify ) { return SWEET_LEXER::TokenName( PR::T( aJustify ) ); } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -245,14 +332,45 @@ protected: PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added wxString name; wxString name; wxString text; wxString text; TEXT_EFFECTS effects; TEXT_EFFECTS* effects; void clear() { delete effects; effects = 0; name = wxEmptyString; text = wxEmptyString; } public: public: PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) : PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) : BASE_GRAPHIC( aOwner ), BASE_GRAPHIC( aOwner ), birthplace( aOwner ), birthplace( aOwner ), name( aName ) name( aName ), effects( 0 ) {} {} ~PROPERTY() { clear(); } /** * Function Effects * returns a pointer to the TEXT_EFFECTS object for this PROPERTY, and optionally * will lazily allocate one if it did not exist previously. * @param doAlloc if true, means do an allocation of a new TEXT_EFFECTS if one * currently does not exist, otherwise return NULL if non-existent. */ TEXT_EFFECTS* EffectsLookup(); TEXT_EFFECTS* Effects() const { return effects; } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -265,6 +383,9 @@ struct PINTEXT PINTEXT() : PINTEXT() : isVisible( true ) isVisible( true ) {} {} void Format( OUTPUTFORMATTER* aFormatter, const char* aElement, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -284,10 +405,18 @@ public: isVisible( true ) isVisible( true ) {} {} /* const char* ShowType() const void Format( OUTPUTFORMATTER* aOutputFormatter, int aNestLevel, int aControlBits ) const { return SWEET_LEXER::TokenName( PR::T( connectionType ) ); } const char* ShowShape() const { return SWEET_LEXER::TokenName( PR::T( shape ) ); } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); throw( IO_ERROR ); */ protected: protected: PART* birthplace; ///< at which PART in inheritance chain was this PIN added PART* birthplace; ///< at which PART in inheritance chain was this PIN added Loading Loading @@ -340,86 +469,22 @@ class PART friend class LIB; // is the owner of all PARTS, afterall friend class LIB; // is the owner of all PARTS, afterall friend class SWEET_PARSER; friend class SWEET_PARSER; protected: // not likely to have C++ descendants, but protected none-the-less. public: /// a protected constructor, only a LIB can instantiate a PART. PART( LIB* aOwner, const STRING& aPartNameAndRev ); /** * Function destroy * clears out this object, deleting all graphics, all fields, all properties, * etc. */ void clear(); /** * Function inherit * is a specialized assignment function that copies a specific subset, enough * to fulfill the requirements of the Sweet s-expression language. */ void inherit( const PART& aBasePart ); /** * Function propertyFind * searches for aPropertyName and returns a PROPERTIES::iterator which * is the found item or properties.end() if not found. */ PROPERTIES::iterator propertyFind( const wxString& aPropertyName ); POINT anchor; //PART( LIB* aOwner ); LIB* owner; ///< which LIB am I a part of (pun if you want) int contains; ///< has bits from Enum PartParts STRING partNameAndRev; ///< example "passives/R[/revN..]", immutable. LPID* extends; ///< of base part, NULL if none, otherwise I own it. PART* base; ///< which PART am I extending, if any. no ownership. /// encapsulate the old version deletion, take ownership of @a aLPID void setExtends( LPID* aLPID ); /// s-expression text for the part, initially empty, and read in as this part /// actually becomes cached in RAM. STRING body; // mandatory properties PROPERTY reference; ///< prefix only, only components have full references PROPERTY value; PROPERTY footprint; PROPERTY model; PROPERTY datasheet; // separate lists for speed: /** * Member properties * holds the non-mandatory properties. */ PROPERTIES properties; /** /** * Member graphics * Enum PROP_ID * owns : POLY_LINE, RECTANGLE, CIRCLE, ARC, BEZIER, and GR_TEXT objects. * is the set of "mandatory" properties within a PART. These are used by * class PART as array indices into PART::mandatory[]. */ */ GRAPHICS graphics; enum PROP_ID { /** REFERENCE, ///< reference prefix, a template for instantiation at COMPONENT level * Member pins VALUE, ///< value, e.g. "3.3K" * owns all the PINs in pins. FOOTPRINT, ///< name of PCB module, e.g. "16DIP300" */ DATASHEET, ///< URI of datasheet PINS pins; MODEL, ///< spice model name END ///< array sentinel, not a valid index /// Alternate body forms. }; //ALTERNATES alternates; KEYWORDS keywords; public: virtual ~PART(); virtual ~PART(); Loading Loading @@ -457,6 +522,24 @@ public: void PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ); void PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ); /** * Function Field * returns a pointer to one of the mandatory properties, or NULL * if non-existent. Use FieldLookup() to potentially allocate it. */ PROPERTY* Field( PROP_ID aPropertyId ) const { wxASSERT( unsigned(aPropertyId) < unsigned(END) ); return mandatory[aPropertyId]; } /** * Function FieldLookup * returns a pointer to one of the mandatory properties, which is lazily * constructed by this function if need be. * @param aPropertyId tells which field. */ PROPERTY* FieldLookup( PROP_ID aPropertyId ); /* /* Loading Loading @@ -494,6 +577,89 @@ public: body = aSExpression; body = aSExpression; } } */ */ protected: // not likely to have C++ descendants, but protected none-the-less. /// a protected constructor, only a LIB can instantiate a PART. PART( LIB* aOwner, const STRING& aPartNameAndRev ); /** * Function destroy * clears out this object, deleting everything that this PART owns and * initializing values back to a state as if the object was just constructed * empty. */ void clear(); /** * Function inherit * is a specialized assignment function that copies a specific subset, enough * to fulfill the requirements of the Sweet s-expression language. */ void inherit( const PART& aBasePart ); /** * Function propertyFind * searches for aPropertyName and returns a PROPERTIES::iterator which * is the found item or properties.end() if not found. */ PROPERTIES::iterator propertyFind( const wxString& aPropertyName ); POINT anchor; //PART( LIB* aOwner ); LIB* owner; ///< which LIB am I a part of (pun if you want) int contains; ///< has bits from Enum PartParts STRING partNameAndRev; ///< example "passives/R[/revN..]", immutable. LPID* extends; ///< of base part, NULL if none, otherwise I own it. PART* base; ///< which PART am I extending, if any. no ownership. /// encapsulate the old version deletion, take ownership of @a aLPID void setExtends( LPID* aLPID ); /// s-expression text for the part, initially empty, and read in as this part /// actually becomes cached in RAM. STRING body; // mandatory properties PROPERTY* mandatory[END]; /* PROPERTY value; PROPERTY footprint; PROPERTY model; PROPERTY datasheet; */ // separate lists for speed: /** * Member properties * holds the non-mandatory properties. */ PROPERTIES properties; /** * Member graphics * owns : POLY_LINE, RECTANGLE, CIRCLE, ARC, BEZIER, and GR_TEXT objects. */ GRAPHICS graphics; /** * Member pins * owns all the PINs in pins. */ PINS pins; /// Alternate body forms. //ALTERNATES alternates; KEYWORDS keywords; }; }; } // namespace PART } // namespace PART Loading Loading
new/make-dir-lib-source-test-data.sh +3 −3 Original line number Original line Diff line number Diff line Loading @@ -10,7 +10,7 @@ REVS="rev1 rev5 rev10" REFERENCE=" REFERENCE=" (reference U (reference U? (effects (at 12 13 180)(font (size .7 1))(visible yes)) (effects (at 12 13 180)(font (size .7 1))(visible yes)) )" )" Loading Loading @@ -71,7 +71,7 @@ for C in ${CATEGORIES}; do for P in ${PARTS}; do for P in ${PARTS}; do for R in ${REVS}; do for R in ${REVS}; do echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane) echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)(datasheet http://favorite.pdf) $REFERENCE $REFERENCE $LINE $LINE $RECT $RECT Loading @@ -86,7 +86,7 @@ for C in ${CATEGORIES}; do )" > $BASEDIR/$C/$P.part.$R )" > $BASEDIR/$C/$P.part.$R done done # also make the part without a rev: # also make the part without a rev: echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane) echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)(datasheet http://favorite.pdf) $REFERENCE $REFERENCE $LINE $LINE $RECT $RECT Loading
new/sch_part.cpp +340 −9 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <sch_sweet_parser.h> #include <sch_sweet_parser.h> #include <sch_lpid.h> #include <sch_lpid.h> #include <sch_lib_table.h> #include <sch_lib_table.h> #include <macros.h> //#include <richio.h> //#include <richio.h> using namespace SCH; using namespace SCH; Loading @@ -38,16 +39,21 @@ PART::PART( LIB* aOwner, const STRING& aPartNameAndRev ) : contains( 0 ), contains( 0 ), partNameAndRev( aPartNameAndRev ), partNameAndRev( aPartNameAndRev ), extends( 0 ), extends( 0 ), base( 0 ), base( 0 ) /* reference( this, wxT( "reference " ) ), reference( this, wxT( "reference " ) ), value( this, wxT( "value" ) ), value( this, wxT( "value" ) ), footprint( this, wxT( "footprint" ) ), footprint( this, wxT( "footprint" ) ), model( this, wxT( "model" ) ), model( this, wxT( "model" ) ), datasheet( this, wxT( "datasheet" ) ) datasheet( this, wxT( "datasheet" ) ) */ { { // Our goal is to have class LIB only instantiate what is needed, so print here // Our goal is to have class LIB only instantiate what is needed, so print here // what it is doing. It is the only class where PART can be instantiated. // what it is doing. It is the only class where PART can be instantiated. D(printf("PART::PART(%s)\n", aPartNameAndRev.c_str() );) D(printf("PART::PART(%s)\n", aPartNameAndRev.c_str() );) for( int i=REFERENCE; i<END; ++i ) mandatory[i] = 0; } } Loading @@ -69,7 +75,7 @@ void PART::clear() delete *it; delete *it; pins.clear(); pins.clear(); // delete non-mandatory properties I own, since their container will not destroy them: // delete properties I own, since their container will not destroy them: for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it ) for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it ) delete *it; delete *it; properties.clear(); properties.clear(); Loading @@ -78,7 +84,54 @@ void PART::clear() contains = 0; contains = 0; // @todo clear the mandatory fields // clear the mandatory fields for( int ndx = REFERENCE; ndx < END; ++ndx ) { delete mandatory[ndx]; mandatory[ndx] = 0; } } PROPERTY* PART::FieldLookup( PROP_ID aPropertyId ) { wxASSERT( unsigned(aPropertyId) < unsigned(END) ); PROPERTY* p = mandatory[aPropertyId]; if( !p ) { switch( aPropertyId ) { case REFERENCE: p = new PROPERTY( this, wxT( "reference" ) ); p->text = wxT( "U?" ); break; case VALUE: p = new PROPERTY( this, wxT( "value" ) ); break; case FOOTPRINT: p = new PROPERTY( this, wxT( "footprint" ) ); break; case DATASHEET: p = new PROPERTY( this, wxT( "datasheet" ) ); break; case MODEL: p = new PROPERTY( this, wxT( "model" ) ); break; default: ; } mandatory[aPropertyId] = p; } return p; } } Loading Loading @@ -151,7 +204,8 @@ PROPERTIES::iterator PART::propertyFind( const wxString& aPropertyName ) } } void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { { out->Print( indent, "(part %s", partNameAndRev.c_str() ); out->Print( indent, "(part %s", partNameAndRev.c_str() ); Loading @@ -160,12 +214,13 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E out->Print( 0, "\n" ); out->Print( 0, "\n" ); /* for( int i = REFERENCE; i < END; ++i ) @todo for( int i=0; i<MANDATORY_FIELDS; ++i ) { { PROPERTY* prop = Field( PROP_ID( i ) ); if( prop ) prop->Format( out, indent+1, ctl ); } } */ for( PROPERTIES::const_iterator it = properties.begin(); it != properties.end(); ++it ) for( PROPERTIES::const_iterator it = properties.begin(); it != properties.end(); ++it ) { { (*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl ); Loading @@ -178,6 +233,14 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E InternalToLogical( anchor.y ) ); InternalToLogical( anchor.y ) ); } } if( keywords.size() ) { out->Print( indent+1, "(keywords" ); for( KEYWORDS::iterator it = keywords.begin(); it != keywords.end(); ++it ) out->Print( 0, " %s", out->Quotew( *it ).c_str() ); out->Print( 0, ")\n" ); } for( GRAPHICS::const_iterator it = graphics.begin(); it != graphics.end(); ++it ) for( GRAPHICS::const_iterator it = graphics.begin(); it != graphics.end(); ++it ) { { (*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl ); Loading @@ -187,6 +250,274 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E { { (*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl ); } } out->Print( indent, ")\n" ); } //-----< PART objects >------------------------------------------------------ void PROPERTY::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { wxASSERT( owner ); // all PROPERTYs should have an owner. int i; for( i = PART::REFERENCE; i < PART::END; ++i ) { if( owner->Field( PART::PROP_ID(i) ) == this ) break; } if( i < PART::END ) // is a field not a property out->Print( indent, "(%s", TO_UTF8( name ) ); else out->Print( indent, "(property %s", out->Quotew( name ).c_str() ); if( effects ) { out->Print( 0, " %s\n", out->Quotew( text ).c_str() ); effects->Format( out, indent+1, ctl | CTL_OMIT_NL ); out->Print( 0, ")\n" ); } else { out->Print( 0, " %s)\n", out->Quotew( text ).c_str() ); } } TEXT_EFFECTS* PROPERTY::EffectsLookup() { if( !effects ) { effects = new TEXT_EFFECTS(); } return effects; } void TEXT_EFFECTS::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { if( propName.IsEmpty() ) out->Print( indent, "(effects " ); else out->Print( indent, "(effects %s ", out->Quotew( propName ).c_str() ); out->Print( 0, "(at %.6g %.6g", InternalToLogical( pos.x ), InternalToLogical( pos.y ) ); if( angle ) out->Print( 0, " %.6g)", double( angle ) ); else out->Print( 0, ")" ); font.Format( out, 0, ctl | CTL_OMIT_NL ); out->Print( 0, "(visible %s))%s", isVisible ? "yes" : "no", ctl & CTL_OMIT_NL ? "" : "\n" ); } void FONT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { if( name.IsEmpty() ) out->Print( indent, "(font " ); else out->Print( indent, "(font %s ", out->Quotew( name ).c_str() ); out->Print( 0, "(size %.6g %.6g)", InternalToLogical( size.GetHeight() ), InternalToLogical( size.GetWidth() ) ); if( italic ) out->Print( 0, " italic" ); if( bold ) out->Print( 0, " bold" ); out->Print( 0, ")%s", (ctl & CTL_OMIT_NL) ? "" : "\n" ); } void PIN::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( indent, "(pin %s %s ", ShowType(), ShowShape() ); if( angle ) out->Print( 0, "(at %.6g %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ), double(angle) ); else out->Print( 0, "(at %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ) ); out->Print( 0, "(length %.6g)", InternalToLogical( length ) ); out->Print( 0, "(visible %s)\n", isVisible ? "yes" : "no" ); signal.Format( out, "signal", indent+1, 0 ); padname.Format( out, "padname", indent+1, CTL_OMIT_NL ); out->Print( 0, ")\n" ); } void PINTEXT::Format( OUTPUTFORMATTER* out, const char* aElement, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( indent, "(%s %s ", aElement, out->Quotew( text ).c_str() ); font.Format( out, 0, CTL_OMIT_NL ); out->Print( 0, "(visible %s))%s", isVisible ? "yes" : "no", ctl & CTL_OMIT_NL ? "" : "\n" ); } void POLY_LINE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( indent, "(%s ", pts.size() == 2 ? "line" : "polyline" ); formatContents( out, indent, ctl ); } void POLY_LINE::formatContents( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( 0, "(line_width %.6g)", lineWidth ); // @todo use logical units? if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, "\n" ); if( pts.size() ) { const int maxLength = 75; int len = 10; len += out->Print( indent+1, "(pts " ); for( POINTS::const_iterator it = pts.begin(); it != pts.end(); ++it ) { if( len > maxLength ) { len = 10; out->Print( 0, "\n" ); out->Print( indent+2, "(xy %.6g %.6g)", InternalToLogical( it->x ), InternalToLogical( it->y ) ); } else out->Print( 0, "(xy %.6g %.6g)", InternalToLogical( it->x ), InternalToLogical( it->y ) ); } out->Print( 0, ")" ); } out->Print( 0, ")\n" ); } void BEZIER::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { out->Print( indent, "(bezier " ); formatContents( out, indent, ctl ); // inherited from POLY_LINE } void RECTANGLE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { // (rectangle (start X Y) (end X Y) (line_width WIDTH) (fill FILL_TYPE)) out->Print( indent, "(rectangle (start %.6g %.6g)(end %.6g %.6g)(line_width %.6g)", InternalToLogical( start.x ), InternalToLogical( start.y ), InternalToLogical( end.x ), InternalToLogical( end.y ), lineWidth ); if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, ")\n" ); } } void CIRCLE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { /* (circle (center X Y)(radius LENGTH)(line_width WIDTH)(fill FILL_TYPE)) */ out->Print( indent, "(circle (center %.6g %.6g)(radius %.6g)(line_width %.6g)", InternalToLogical( center.x ), InternalToLogical( center.y ), InternalToLogical( radius), lineWidth ); if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, ")\n" ); } void ARC::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { /* (arc (pos X Y)(radius RADIUS)(start X Y)(end X Y)(line_width WIDTH)(fill FILL_TYPE)) */ out->Print( indent, "(arc (pos %.6g %.6g)(radius %.6g)(start %.6g %.6g)(end %.6g %.6g)(line_width %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ), InternalToLogical( radius), InternalToLogical( start.x ), InternalToLogical( start.y ), InternalToLogical( end.x ), InternalToLogical( end.y ), lineWidth ); if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, ")\n" ); } void GR_TEXT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { /* (text "This is the text that gets drawn." (at X Y [ANGLE]) # Valid horizontal justification values are center, right, and left. Valid # vertical justification values are center, top, bottom. (justify HORIZONTAL_JUSTIFY VERTICAL_JUSTIFY) (font [FONT] (size HEIGHT WIDTH) [italic] [bold]) (visible YES) (fill FILL_TYPE) ) */ out->Print( indent, "(text %s\n", out->Quotew( text ).c_str() ); if( angle ) out->Print( indent+1, "(at %.6g %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ), double( angle ) ); else out->Print( indent+1, "(at %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ) ); out->Print( 0, "(justify %s %s)(visible %s)", ShowJustify( hjustify ), ShowJustify( vjustify ), isVisible ? "yes" : "no" ); if( fillType != PR::T_none ) out->Print( 0, "(fill %s)", ShowFill( fillType ) ); out->Print( 0, "\n" ); font.Format( out, indent+1, CTL_OMIT_NL ); out->Print( 0, ")\n" ); }
new/sch_part.h +258 −92 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,32 @@ #include <sch_lib.h> #include <sch_lib.h> #define INTERNAL_PER_LOGICAL 10000 ///< no. internal units per logical unit /** * Function InternalToLogical * converts an internal coordinate to a logical coordinate. Logical coordinates * are defined as the standard distance between pins being equal to one. * Internal coordinates are currently INTERNAL_PER_LOGICAL times that. */ static inline double InternalToLogical( int aCoord ) { return double( aCoord ) / INTERNAL_PER_LOGICAL; } /** * Function LogicalToInternal * converts a logical coordinate to an internal coordinate. Logical coordinates * are defined as the standard distance between pins being equal to one. * Internal coordinates are currently INTERNAL_PER_LOGICAL times that. */ static inline int LogicalToInternal( double aCoord ) { return int( aCoord * INTERNAL_PER_LOGICAL ); } //-----<temporary home for PART sub objects, move after stable>------------------ //-----<temporary home for PART sub objects, move after stable>------------------ #include <wx/gdicmn.h> #include <wx/gdicmn.h> Loading @@ -39,6 +65,9 @@ class OUTPUTFORMATTER; class OUTPUTFORMATTER; /// Control Bits for Format() functions #define CTL_OMIT_NL (1<<0) ///< omit new line in Format()s. namespace SCH { namespace SCH { class PART; class PART; Loading Loading @@ -81,6 +110,9 @@ public: italic( false ), italic( false ), bold( false ) bold( false ) {} {} void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -99,6 +131,9 @@ struct TEXT_EFFECTS isVisible( false ), isVisible( false ), property( 0 ) property( 0 ) {} {} void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -117,7 +152,16 @@ public: virtual ~BASE_GRAPHIC() {} virtual ~BASE_GRAPHIC() {} virtual void Format( OUTPUTFORMATTER* aOutputFormatter, int aNestLevel, int aControlBits ) const static const char* ShowFill( int aFillType ) { return SWEET_LEXER::TokenName( PR::T( aFillType ) ); } /** * Function Format * outputs this object to @a aFormatter in s-expression form. */ virtual void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ) throw( IO_ERROR ) {} {} }; }; Loading @@ -134,10 +178,19 @@ protected: int fillType; // T_none, T_filled, or T_transparent int fillType; // T_none, T_filled, or T_transparent POINTS pts; POINTS pts; void formatContents( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); public: public: POLY_LINE( PART* aOwner ) : POLY_LINE( PART* aOwner ) : BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ), {} lineWidth( 1 ), fillType( PR::T_none ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; class BEZIER : public POLY_LINE class BEZIER : public POLY_LINE Loading @@ -148,7 +201,13 @@ class BEZIER : public POLY_LINE public: public: BEZIER( PART* aOwner ) : BEZIER( PART* aOwner ) : POLY_LINE( aOwner ) POLY_LINE( aOwner ) {} { lineWidth = 1; fillType = PR::T_none; } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; class RECTANGLE : public BASE_GRAPHIC class RECTANGLE : public BASE_GRAPHIC Loading @@ -164,8 +223,14 @@ protected: public: public: RECTANGLE( PART* aOwner ) : RECTANGLE( PART* aOwner ) : BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ), {} lineWidth( 1 ), fillType( PR::T_none ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -182,8 +247,15 @@ protected: public: public: CIRCLE( PART* aOwner ) : CIRCLE( PART* aOwner ) : BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ), {} radius( LogicalToInternal( 0.5 ) ), lineWidth( 1 ), fillType( PR::T_none ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -202,8 +274,15 @@ protected: public: public: ARC( PART* aOwner ) : ARC( PART* aOwner ) : BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ), {} lineWidth( 1 ), fillType( PR::T_none ), radius( LogicalToInternal( 0.5 ) ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading Loading @@ -233,6 +312,14 @@ public: vjustify( PR::T_bottom ), vjustify( PR::T_bottom ), isVisible( true ) isVisible( true ) {} {} static const char* ShowJustify( int aJustify ) { return SWEET_LEXER::TokenName( PR::T( aJustify ) ); } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -245,14 +332,45 @@ protected: PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added wxString name; wxString name; wxString text; wxString text; TEXT_EFFECTS effects; TEXT_EFFECTS* effects; void clear() { delete effects; effects = 0; name = wxEmptyString; text = wxEmptyString; } public: public: PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) : PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) : BASE_GRAPHIC( aOwner ), BASE_GRAPHIC( aOwner ), birthplace( aOwner ), birthplace( aOwner ), name( aName ) name( aName ), effects( 0 ) {} {} ~PROPERTY() { clear(); } /** * Function Effects * returns a pointer to the TEXT_EFFECTS object for this PROPERTY, and optionally * will lazily allocate one if it did not exist previously. * @param doAlloc if true, means do an allocation of a new TEXT_EFFECTS if one * currently does not exist, otherwise return NULL if non-existent. */ TEXT_EFFECTS* EffectsLookup(); TEXT_EFFECTS* Effects() const { return effects; } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -265,6 +383,9 @@ struct PINTEXT PINTEXT() : PINTEXT() : isVisible( true ) isVisible( true ) {} {} void Format( OUTPUTFORMATTER* aFormatter, const char* aElement, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; }; Loading @@ -284,10 +405,18 @@ public: isVisible( true ) isVisible( true ) {} {} /* const char* ShowType() const void Format( OUTPUTFORMATTER* aOutputFormatter, int aNestLevel, int aControlBits ) const { return SWEET_LEXER::TokenName( PR::T( connectionType ) ); } const char* ShowShape() const { return SWEET_LEXER::TokenName( PR::T( shape ) ); } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); throw( IO_ERROR ); */ protected: protected: PART* birthplace; ///< at which PART in inheritance chain was this PIN added PART* birthplace; ///< at which PART in inheritance chain was this PIN added Loading Loading @@ -340,86 +469,22 @@ class PART friend class LIB; // is the owner of all PARTS, afterall friend class LIB; // is the owner of all PARTS, afterall friend class SWEET_PARSER; friend class SWEET_PARSER; protected: // not likely to have C++ descendants, but protected none-the-less. public: /// a protected constructor, only a LIB can instantiate a PART. PART( LIB* aOwner, const STRING& aPartNameAndRev ); /** * Function destroy * clears out this object, deleting all graphics, all fields, all properties, * etc. */ void clear(); /** * Function inherit * is a specialized assignment function that copies a specific subset, enough * to fulfill the requirements of the Sweet s-expression language. */ void inherit( const PART& aBasePart ); /** * Function propertyFind * searches for aPropertyName and returns a PROPERTIES::iterator which * is the found item or properties.end() if not found. */ PROPERTIES::iterator propertyFind( const wxString& aPropertyName ); POINT anchor; //PART( LIB* aOwner ); LIB* owner; ///< which LIB am I a part of (pun if you want) int contains; ///< has bits from Enum PartParts STRING partNameAndRev; ///< example "passives/R[/revN..]", immutable. LPID* extends; ///< of base part, NULL if none, otherwise I own it. PART* base; ///< which PART am I extending, if any. no ownership. /// encapsulate the old version deletion, take ownership of @a aLPID void setExtends( LPID* aLPID ); /// s-expression text for the part, initially empty, and read in as this part /// actually becomes cached in RAM. STRING body; // mandatory properties PROPERTY reference; ///< prefix only, only components have full references PROPERTY value; PROPERTY footprint; PROPERTY model; PROPERTY datasheet; // separate lists for speed: /** * Member properties * holds the non-mandatory properties. */ PROPERTIES properties; /** /** * Member graphics * Enum PROP_ID * owns : POLY_LINE, RECTANGLE, CIRCLE, ARC, BEZIER, and GR_TEXT objects. * is the set of "mandatory" properties within a PART. These are used by * class PART as array indices into PART::mandatory[]. */ */ GRAPHICS graphics; enum PROP_ID { /** REFERENCE, ///< reference prefix, a template for instantiation at COMPONENT level * Member pins VALUE, ///< value, e.g. "3.3K" * owns all the PINs in pins. FOOTPRINT, ///< name of PCB module, e.g. "16DIP300" */ DATASHEET, ///< URI of datasheet PINS pins; MODEL, ///< spice model name END ///< array sentinel, not a valid index /// Alternate body forms. }; //ALTERNATES alternates; KEYWORDS keywords; public: virtual ~PART(); virtual ~PART(); Loading Loading @@ -457,6 +522,24 @@ public: void PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ); void PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ); /** * Function Field * returns a pointer to one of the mandatory properties, or NULL * if non-existent. Use FieldLookup() to potentially allocate it. */ PROPERTY* Field( PROP_ID aPropertyId ) const { wxASSERT( unsigned(aPropertyId) < unsigned(END) ); return mandatory[aPropertyId]; } /** * Function FieldLookup * returns a pointer to one of the mandatory properties, which is lazily * constructed by this function if need be. * @param aPropertyId tells which field. */ PROPERTY* FieldLookup( PROP_ID aPropertyId ); /* /* Loading Loading @@ -494,6 +577,89 @@ public: body = aSExpression; body = aSExpression; } } */ */ protected: // not likely to have C++ descendants, but protected none-the-less. /// a protected constructor, only a LIB can instantiate a PART. PART( LIB* aOwner, const STRING& aPartNameAndRev ); /** * Function destroy * clears out this object, deleting everything that this PART owns and * initializing values back to a state as if the object was just constructed * empty. */ void clear(); /** * Function inherit * is a specialized assignment function that copies a specific subset, enough * to fulfill the requirements of the Sweet s-expression language. */ void inherit( const PART& aBasePart ); /** * Function propertyFind * searches for aPropertyName and returns a PROPERTIES::iterator which * is the found item or properties.end() if not found. */ PROPERTIES::iterator propertyFind( const wxString& aPropertyName ); POINT anchor; //PART( LIB* aOwner ); LIB* owner; ///< which LIB am I a part of (pun if you want) int contains; ///< has bits from Enum PartParts STRING partNameAndRev; ///< example "passives/R[/revN..]", immutable. LPID* extends; ///< of base part, NULL if none, otherwise I own it. PART* base; ///< which PART am I extending, if any. no ownership. /// encapsulate the old version deletion, take ownership of @a aLPID void setExtends( LPID* aLPID ); /// s-expression text for the part, initially empty, and read in as this part /// actually becomes cached in RAM. STRING body; // mandatory properties PROPERTY* mandatory[END]; /* PROPERTY value; PROPERTY footprint; PROPERTY model; PROPERTY datasheet; */ // separate lists for speed: /** * Member properties * holds the non-mandatory properties. */ PROPERTIES properties; /** * Member graphics * owns : POLY_LINE, RECTANGLE, CIRCLE, ARC, BEZIER, and GR_TEXT objects. */ GRAPHICS graphics; /** * Member pins * owns all the PINs in pins. */ PINS pins; /// Alternate body forms. //ALTERNATES alternates; KEYWORDS keywords; }; }; } // namespace PART } // namespace PART Loading