← Back to team overview

kicad-developers team mailing list archive

proposal to move drawing routines to separate class

 

Jean-Pierre and Tom,


Wayne came to stay at our house this weekend.  He is a great guy, even classier than he
comes across in his emails.

During our visit we talked about many things, one of which was an idea that came in from
Tom last year.

Attached is a sketch of a class would be compiled multiple times to remove the drawing
code from the graphical objects, isolating it into a single class.  The  advantage is that
we can use alternative output devices (and graphical or plotting libraries), without
constantly adding member functions.  The member functions we assume will cause problems
linking these container objects as DLL/DSOs, in a way that we can put scripting and
command line processors up on top of them.

I sketched this out this morning, and it provides the basic idea.  We sacrifice
polymorphism in BOARD_ITEM::Draw(), but the overhead of PAINTER::Draw() is minimal
relative to other bottlenecks.  It will simply mean you call PAINTER::Draw() almost
everywhere.

To interpret the context of the code, we are assuming the following:

1) bottom end (data model) PCBNEW code will be linked into a DLL/DSO

2) bottom end (data model) EESCHEMA code will be linked into a DLL/DSO.

3) they will never be linked together, but might operate together under one process.


This means we can multiply compile class PAINTER with either

-DEESCHEMA or
-DPCBNEW

There is no reason to have an inheritance tree in class PAINTER, since it is multiply
compiled, separately linked.  When and if we ever change
graphical libraries, we REPLACE it at compile time, not runtime.

Please let me know if you have any questions, and what you guys think.  Tom since this was
originally your idea, I wanted to bounce this off you also.

Regards,

Dick

BTW, I have been told that I was spending too much time on KiCad, so my contribution rate
is throttled down now to some hours on the weekend.  Vacation time is over.  So the move
to PCBNEW millimeters will go slower now.

Also, the increased productivity of our face to face meeting really brought home how
inefficient a mailing list is for idea exchange.  We might want to start using another
medium for design idea exchange, maybe IRC, or whatever.  (The developer's list is
morphing into a user support mailing list, and it is hard to hear ourselves think here
sometimes.  Part of that is because folks have to join developers to submit a bug?)






#if defined(PCBNEW)

class BOARD;
class TRACK;
class ZONE_CONTAINER;

//:

#elif defined(EESCHEMA)

class SCH_SHEET;
//:

#endif


/**
 * Class PAINTER
 * contains all the knowledge about how to draw any graphical object onto
 * any particular output device.
 * This knowledge is held outside the individual graphical objects so that
 * alternative output devices may be used, and so that the graphical objects
 * themselves to not contain drawing routines.  Drawing routines in the objects
 * cause problems with usages of the objects as simple container objects in
 * DLL/DSOs.
 */
class PAINTER
{
public:


    /**
     * Constructor PAINTER( wxDC& )
     * initializes this object for painting on any of the polymorphic
     * wxDC derivatives.
     *
     * @param aDC is a reference to a polymorphic wx device context on which
     *  to draw. It can be any of the wxDC derivatives.
     *  No ownership is given to this PAINTER of aDC.
     */
    PAINTER( wxDC& aDC ) :
        m_dc( aDC ),
        m_highlight( false ),
        m_grayed( false )
    {
    }



#if defined(PCBNEW)

    void Draw( const BOARD_ITEM* );

#elif defined(EESCHEMA)

    void Draw( const SCH_ITEM* );

#endif


private:

    wxDC&   m_dc;

    // drawing state information.
    bool    m_highlite;
    bool    m_grayed;


#if defined(PCBNEW)

    void    draw( const TRACK* );
    void    draw( const MODULE* );
    void    draw( const EDGE_MODULE* );
    // :

#elif defined(EESCHEMA)
    void    draw( const SCH_WIRE* );
    // :

#endif
}


#if defined(PCBNEW)

void PAINTER::Draw( const BOARD_ITEM* aItem )
{
    // the "cast" applied in here clarifies which overloaded draw() is called

    switch( aItem->Type() )
    {
    case PCB_MODULE_T:
        draw( (MODULE*) aItem );
        break;

    case PCB_PAD_T:
        draw( (D_PAD*) aItem );
        break;

    case PCB_LINE_T:
        draw( (TEXTE_PCB*) aItem );
        break;

    case PCB_TEXT_T:
        draw( (TEXTE_PCB*) aItem );
        break;

    case PCB_MODULE_TEXT_T:
        draw( (TEXTE_PCB*) aItem );
        break;

    case PCB_MODULE_EDGE_T:
        draw( (EDGE_MODULE*) aItem );
        break;

    case PCB_TRACE_T:
        draw( (TRACKE*) aItem );
        break;

    case PCB_VIA_T:
        draw( (VIA*) aItem );
        break;

    case PCB_ZONE_T:
        draw( (SEGZONE*) aItem );
        break;

    case PCB_MARKER_T:
        draw( (MARKER_PCB*) aItem );
        break;

    case PCB_DIMENSION_T:
        draw( (DIMENSION*) aItem );
        break;

    case PCB_TARGET_T:
        draw( (TARGET*) aItem );
        break;


    case PCB_ZONE_AREA_T:
        draw( (ZONE_CONTAINER*) aItem );
        break;

    /* not used
    case PCB_ZONE_EDGE_T:
        break;

    case PCB_ITEM_LIST_T:
        draw( (BOARD_ITEM_LIST*) aItem );
        break;
    */

    default:
        ; // nothing
    }
}

#elif defined(EESCHEMA)

void PAINTER::Draw( const SCH_ITEM* aItem )
{
    // the "cast" applied in here clarifies which overloaded draw() is called

    switch( aItem->Type() )
    {
        //:
    }
}


#endif

Follow ups