kicad/new/sch_part.h

681 lines
17 KiB
C++

/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2011 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* 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 <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 );
}
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;
}
//-----<temporary home for PART sub objects, move after stable>------------------
#include <wx/gdicmn.h>
#include <deque>
#include <vector>
#include <set>
#include <sweet_lexer.h>
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<POINT> 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
//-----</temporary home for PART sub objects, move after stable>-----------------
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_