/* * This program source code file is part of KICAD, a free EDA CAD application. * * Copyright (C) 2011 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2010 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 */ #ifndef SCH_PART_H_ #define SCH_PART_H_ #include #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 ); } static inline int WidthToInternal( double aWidth ) { // sweet line widths are a "percent of a logical unit" return LogicalToInternal( aWidth ) / 100; } static inline double InternalToWidth( int aWidth ) { // sweet line widths are a "percent of a logical unit" return InternalToLogical( aWidth ) * 100; } //----------------------- #include #include #include #include #include class OUTPUTFORMATTER; /// Control Bits for Format() functions #define CTL_OMIT_NL (1<<0) ///< omit new line in Format()s. namespace SCH { class PART; class SWEET_PARSER; class PROPERTY; }; class POINT : public wxPoint { public: POINT( int x, int y ) : wxPoint( x, y ) {} POINT() : wxPoint() {} }; typedef float ANGLE; namespace SCH { class FONT { friend class PART; friend class SWEET_PARSER; protected: wxString name; ///< name or other id such as number, TBD wxSize size; bool italic; bool bold; public: FONT() : italic( false ), bold( false ) {} void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; struct TEXT_EFFECTS { POINT pos; ANGLE angle; FONT font; bool isVisible; PROPERTY* property; ///< only used from a COMPONENT, specifies PROPERTY in PART wxString propName; ///< only used from a COMPONENT, specifies PROPERTY in PART TEXT_EFFECTS() : angle( 0 ), isVisible( false ), property( 0 ) {} void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; class BASE_GRAPHIC { friend class PART; friend class SWEET_PARSER; protected: PART* owner; public: BASE_GRAPHIC( PART* aOwner ) : owner( aOwner ) {} virtual ~BASE_GRAPHIC() {} 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 ) {} }; typedef std::deque POINTS; class POLY_LINE : public BASE_GRAPHIC { friend class PART; friend class SWEET_PARSER; protected: int lineWidth; int fillType; // T_none, T_filled, or T_transparent POINTS pts; void formatContents( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); public: POLY_LINE( PART* 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 { friend class PART; friend class SWEET_PARSER; public: BEZIER( PART* 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 { friend class PART; friend class SWEET_PARSER; protected: int lineWidth; int fillType; // T_none, T_filled, or T_transparent POINT start; POINT end; public: RECTANGLE( PART* aOwner ) : BASE_GRAPHIC( aOwner ), lineWidth( 1 ), fillType( PR::T_none ) { } void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; class CIRCLE : public BASE_GRAPHIC { friend class PART; friend class SWEET_PARSER; protected: POINT center; int radius; int lineWidth; int fillType; // T_none, T_filled, or T_transparent public: CIRCLE( PART* 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 ); }; class ARC : public BASE_GRAPHIC { friend class PART; friend class SWEET_PARSER; protected: POINT pos; int lineWidth; int fillType; // T_none, T_filled, or T_transparent int radius; POINT start; POINT end; public: ARC( PART* 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 ); }; class GR_TEXT : public BASE_GRAPHIC { friend class PART; friend class SWEET_PARSER; protected: POINT pos; ANGLE angle; int fillType; ///< T_none, T_filled, or T_transparent int hjustify; ///< T_center, T_right, or T_left int vjustify; ///< T_center, T_top, or T_bottom bool isVisible; wxString text; FONT font; public: GR_TEXT( PART* aOwner ) : BASE_GRAPHIC( aOwner ), angle( 0 ), fillType( PR::T_filled ), hjustify( PR::T_left ), vjustify( PR::T_bottom ), 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 ); }; class PROPERTY : public BASE_GRAPHIC { friend class PART; friend class SWEET_PARSER; protected: PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added wxString name; wxString text; TEXT_EFFECTS* effects; void clear() { delete effects; effects = 0; name = wxEmptyString; text = wxEmptyString; } public: PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) : BASE_GRAPHIC( aOwner ), birthplace( aOwner ), 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 ); }; struct PINTEXT { wxString text; FONT font; bool isVisible; PINTEXT() : isVisible( true ) {} void Format( OUTPUTFORMATTER* aFormatter, const char* aElement, int aNestLevel, int aControlBits ) const throw( IO_ERROR ); }; class PIN : public BASE_GRAPHIC { friend class PART; friend class SWEET_PARSER; public: PIN( PART* aOwner ) : BASE_GRAPHIC( aOwner ), birthplace( aOwner ), angle( 0 ), connectionType( PR::T_input ), shape( PR::T_line ), length( 0 ), isVisible( true ) {} const char* ShowType() 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 ); protected: PART* birthplace; ///< at which PART in inheritance chain was this PIN added POINT pos; ANGLE angle; PINTEXT padname; PINTEXT signal; int connectionType; ///< T_input, T_output, T_bidirectional, T_tristate, T_passive, T_unspecified, ///< T_power_in, T_power_out, T_open_collector, T_open_emitter, or T_unconnected. int shape; ///< T_none, T_line, T_inverted, T_clock, T_inverted_clk, T_input_low, T_clock_low, ///< T_falling_edge, T_non_logic. int length; ///< length of pin in internal units bool isVisible; ///< pin is visible }; } // namespace SCH //---------------------- namespace SCH { typedef std::vector< BASE_GRAPHIC* > GRAPHICS; typedef std::vector< PIN* > PINS; typedef std::vector< PROPERTY* > PROPERTIES; typedef std::set< wxString > KEYWORDS; class LPID; class SWEET_PARSER; /** * Class PART * will have to be unified with what Wayne is doing. I want a separate copy * here until I can get the state management correct. Since a PART only lives * within a cache called a LIB, its constructor is private (only a LIB * can instantiate one), and it exists in various states of freshness and * completeness relative to the LIB_SOURCE within the LIB. */ class PART { friend class LIB; // is the owner of all PARTS, afterall friend class SWEET_PARSER; public: /** * Enum PROP_ID * is the set of "mandatory" properties within a PART. These are used by * class PART as array indices into PART::mandatory[]. */ enum PROP_ID { REFERENCE, ///< reference prefix, a template for instantiation at COMPONENT level VALUE, ///< value, e.g. "3.3K" FOOTPRINT, ///< name of PCB module, e.g. "16DIP300" DATASHEET, ///< URI of datasheet MODEL, ///< spice model name END ///< array sentinel, not a valid index }; virtual ~PART(); PART& operator = ( const PART& other ); /** * Function Owner * returns the LIB* owner of this part. */ LIB* Owner() { return owner; } /** * Function Parse * translates a Sweet string into a binary form that is represented * by the normal fields of this class. Parse is expected to call Inherit() * if this part extends any other. * * @param aParser is an instance of SWEET_PARSER, rewound at the first line. * * @param aLibTable is the LIB_TABLE "view" that is in effect for inheritance, * and comes from the big containing SCHEMATIC object. */ void Parse( SWEET_PARSER* aParser, LIB_TABLE* aLibTable ) throw( IO_ERROR, PARSE_ERROR ); /** * Function Format * outputs this PART in UTF8 encoded s-expression format to @a aFormatter. * @param aFormatter is the output sink to write to. * @param aNestLevel is the initial indent level * @param aControlBits are bit flags ORed together which control how the output * is done. */ void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits = 0 ) const 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 ); /* void SetValue( const wxString& aValue ) { value = aValue; } const wxString& GetValue() { return value; } void SetFootprint( const wxString& aFootprint ) { footprint = aFootprint; } const wxString& GetFootprint() { return footprint; } void SetModel( const wxString& aModel ) { model = aModel; } const wxString& GetModel() { return model; } */ /* void SetBody( const STR_UTF& 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 #endif // SCH_PART_