summaryrefslogtreecommitdiff
path: root/pcbnew/class_module.h
blob: fedc62eaa086d2d4294ecb48e420c3263e9f7db1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
 * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.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
 */

/**
 * @file class_module.h
 * @brief Module description (excepted pads)
 */


#ifndef MODULE_H_
#define MODULE_H_


#include <dlist.h>
#include <layers_id_colors_and_visibility.h>       // ALL_LAYERS definition.
#include <class_board_item.h>
#include <fpid.h>

#include <class_text_mod.h>
#include <PolyLine.h>
#include "zones.h"

#include <boost/function.hpp>

class LINE_READER;
class EDA_3D_CANVAS;
class S3D_MASTER;
class EDA_DRAW_PANEL;
class D_PAD;
class BOARD;
class MSG_PANEL_ITEM;


enum INCLUDE_NPTH_T
{
    DO_NOT_INCLUDE_NPTH = false,
    INCLUDE_NPTH = true
};

/**
 * Enum MODULE_ATTR_T
 * is the set of attributes allowed within a MODULE, using MODULE::SetAttributes()
 * and MODULE::GetAttributes().  These are to be ORed together when calling
 * MODULE::SetAttributes()
 */
enum MODULE_ATTR_T
{
    MOD_DEFAULT = 0,    ///< default
    MOD_CMS     = 1,    ///< Set for modules listed in the automatic insertion list
                        ///< (usually SMD footprints)
    MOD_VIRTUAL = 2     ///< Virtual component: when created by copper shapes on
                        ///<  board (Like edge card connectors, mounting hole...)
};


class MODULE : public BOARD_ITEM
{
public:
    MODULE( BOARD* parent );

    MODULE( const MODULE& aModule );

    ~MODULE();

    static inline bool ClassOf( const EDA_ITEM* aItem )
    {
        return PCB_MODULE_T == aItem->Type();
    }

    MODULE* Next() const { return static_cast<MODULE*>( Pnext ); }
    MODULE* Back() const { return static_cast<MODULE*>( Pback ); }

    void Copy( MODULE* Module );        // Copy structure

    /**
     * Function Add
     * adds the given item to this MODULE and takes ownership of its memory.
     * @param aBoardItem The item to add to this board.
     * @param doAppend If true, then append, else insert.
     */
    void Add( BOARD_ITEM* aBoardItem, bool doAppend = true );

    /**
     * Function Delete
     * removes the given single item from this MODULE and deletes its memory.
     * @param aBoardItem The item to remove from this module and delete
     */
    void Delete( BOARD_ITEM* aBoardItem )
    {
        // developers should run DEBUG versions and fix such calls with NULL
        wxASSERT( aBoardItem );

        if( aBoardItem )
            delete Remove( aBoardItem );
    }

    /**
     * Function Remove
     * removes \a aBoardItem from this MODULE and returns it to caller without deleting it.
     * @param aBoardItem The item to remove from this module.
     * @return BOARD_ITEM* \a aBoardItem which was passed in.
     */
    BOARD_ITEM* Remove( BOARD_ITEM* aBoardItem );

    /**
     * Function ClearAllNets
     * Clear (i.e. force the ORPHANED dummy net info) the net info which
     * depends on a given board for all pads of the footprint.
     * This is needed when a footprint is copied between the fp editor and
     * the board editor for instance, because net info become fully broken
     */
    void ClearAllNets();

    /**
     * Function CalculateBoundingBox
     * calculates the bounding box in board coordinates.
     */
    void CalculateBoundingBox();

    /**
     * Function GetFootprintRect()
     * Returns the area of the module footprint excluding any text.
     * @return EDA_RECT - The rectangle containing the footprint.
     */
    EDA_RECT GetFootprintRect() const;

    // Virtual function
    const EDA_RECT GetBoundingBox() const;

    DLIST<D_PAD>& Pads()                        { return m_Pads; }
    const DLIST<D_PAD>& Pads() const            { return m_Pads; }

    DLIST<BOARD_ITEM>& GraphicalItems()         { return m_Drawings; }
    const DLIST<BOARD_ITEM>& GraphicalItems() const { return m_Drawings; }

    DLIST<S3D_MASTER>& Models()                 { return m_3D_Drawings; }
    const DLIST<S3D_MASTER>& Models() const     { return m_3D_Drawings; }

    void SetPosition( const wxPoint& aPos );                        // was overload
    const wxPoint& GetPosition() const          { return m_Pos; }   // was overload

    void SetOrientation( double newangle );
    double GetOrientation() const { return m_Orient; }

    const FPID& GetFPID() const { return m_fpid; }
    void SetFPID( const FPID& aFPID ) { m_fpid = aFPID; }

    const wxString& GetDescription() const { return m_Doc; }
    void SetDescription( const wxString& aDoc ) { m_Doc = aDoc; }

    const wxString& GetKeywords() const { return m_KeyWord; }
    void SetKeywords( const wxString& aKeywords ) { m_KeyWord = aKeywords; }

    const wxString& GetPath() const { return m_Path; }
    void SetPath( const wxString& aPath ) { m_Path = aPath; }

    int GetLocalSolderMaskMargin() const { return m_LocalSolderMaskMargin; }
    void SetLocalSolderMaskMargin( int aMargin ) { m_LocalSolderMaskMargin = aMargin; }

    int GetLocalClearance() const { return m_LocalClearance; }
    void SetLocalClearance( int aClearance ) { m_LocalClearance = aClearance; }

    int GetLocalSolderPasteMargin() const { return m_LocalSolderPasteMargin; }
    void SetLocalSolderPasteMargin( int aMargin ) { m_LocalSolderPasteMargin = aMargin; }

    double GetLocalSolderPasteMarginRatio() const { return m_LocalSolderPasteMarginRatio; }
    void SetLocalSolderPasteMarginRatio( double aRatio ) { m_LocalSolderPasteMarginRatio = aRatio; }

    void SetZoneConnection( ZoneConnection aType ) { m_ZoneConnection = aType; }
    ZoneConnection GetZoneConnection() const { return m_ZoneConnection; }

    void SetThermalWidth( int aWidth ) { m_ThermalWidth = aWidth; }
    int GetThermalWidth() const { return m_ThermalWidth; }

    void SetThermalGap( int aGap ) { m_ThermalGap = aGap; }
    int GetThermalGap() const { return m_ThermalGap; }

    int GetAttributes() const { return m_Attributs; }
    void SetAttributes( int aAttributes ) { m_Attributs = aAttributes; }

    void SetFlag( int aFlag ) { m_arflag = aFlag; }
    void IncrementFlag() { m_arflag += 1; }
    int GetFlag() const { return m_arflag; }

    void Move( const wxPoint& aMoveVector );

    void Rotate( const wxPoint& aRotCentre, double aAngle );

    void Flip( const wxPoint& aCentre );

    /**
     * Function MoveAnchorPosition
     * Move the reference point of the footprint
     * It looks like a move footprint:
     * the footprints elements (pads, outlines, edges .. ) are moved
     * However:
     * - the footprint position is not modified.
     * - the relative (local) coordinates of these items are modified
     * (a move footprint does not change these local coordinates,
     * but changes the footprint position)
     */
    void MoveAnchorPosition( const wxPoint& aMoveVector );

    /**
     * function IsFlipped
     * @return true if the module is flipped, i.e. on the back side of the board
     */
    bool IsFlipped() const {return GetLayer() == B_Cu; }

// m_ModuleStatus bits:
#define MODULE_is_LOCKED    0x01        ///< module LOCKED: no autoplace allowed
#define MODULE_is_PLACED    0x02        ///< In autoplace: module automatically placed
#define MODULE_to_PLACE     0x04        ///< In autoplace: module waiting for autoplace
#define MODULE_PADS_LOCKED  0x08        ///< In autoplace: module waiting for autoplace


    bool IsLocked() const
    {
        return (m_ModuleStatus & MODULE_is_LOCKED) != 0;
    }

    /**
     * Function SetLocked
     * sets the MODULE_is_LOCKED bit in the m_ModuleStatus
     * @param isLocked When true means turn on locked status, else unlock
     */
    void SetLocked( bool isLocked )
    {
        if( isLocked )
            m_ModuleStatus |= MODULE_is_LOCKED;
        else
            m_ModuleStatus &= ~MODULE_is_LOCKED;
    }

    bool IsPlaced() const   { return (m_ModuleStatus & MODULE_is_PLACED); }
    void SetIsPlaced( bool isPlaced )
    {
        if( isPlaced )
            m_ModuleStatus |= MODULE_is_PLACED;
        else
            m_ModuleStatus &= ~MODULE_is_PLACED;
    }

    bool NeedsPlaced() const  { return (m_ModuleStatus & MODULE_to_PLACE); }
    void SetNeedsPlaced( bool needsPlaced )
    {
        if( needsPlaced )
            m_ModuleStatus |= MODULE_to_PLACE;
        else
            m_ModuleStatus &= ~MODULE_to_PLACE;
    }

    bool PadsLocked() const { return ( m_ModuleStatus & MODULE_PADS_LOCKED ); }

    void SetPadsLocked( bool aPadsLocked )
    {
        if( aPadsLocked )
            m_ModuleStatus |= MODULE_PADS_LOCKED;
        else
            m_ModuleStatus &= ~MODULE_PADS_LOCKED;
    }

    void SetLastEditTime( time_t aTime ) { m_LastEditTime = aTime; }
    void SetLastEditTime( ) { m_LastEditTime = time( NULL ); }
    time_t GetLastEditTime() const { return m_LastEditTime; }

    /* drawing functions */

    /**
     * Function Draw
     * draws the footprint to the \a aDC.
     * @param aPanel = draw panel, Used to know the clip box
     * @param aDC = Current Device Context
     * @param aDrawMode = GR_OR, GR_XOR..
     * @param aOffset = draw offset (usually wxPoint(0,0)
     */
    void Draw( EDA_DRAW_PANEL* aPanel,
               wxDC*           aDC,
               GR_DRAWMODE     aDrawMode,
               const wxPoint&  aOffset = ZeroOffset );

    /**
     * Function DrawOutlinesWhenMoving
     * draws in XOR mode the footprint when moving it to the \a aDC.
     * To speed up the drawing, only a simplified shape is drawn
     * @param aPanel = draw panel, Used to know the clip box
     * @param aDC = Current Device Context
     * @param aMoveVector = the offset between the curr position and
     * the draw position.
     */
    void DrawOutlinesWhenMoving( EDA_DRAW_PANEL* aPanel,
               wxDC* aDC, const wxPoint&  aMoveVector );

    /**
     * function TransformPadsShapesWithClearanceToPolygon
     * generate pads shapes on layer aLayer as polygons,
     * and adds these polygons to aCornerBuffer
     * Useful to generate a polygonal representation of a footprint
     * in 3D view and plot functions, when a full polygonal approach is needed
     * @param aLayer = the current layer: pads on this layer are considered
     * @param aCornerBuffer = the buffer to store polygons
     * @param aInflateValue = an additionnal size to add to pad shapes
     *          aInflateValue = 0 to have the exact pad size
     * @param aCircleToSegmentsCount = number of segments to generate a circle
     * @param aCorrectionFactor = the correction to apply to a circle radius
     *  to approximate a circle by the polygon.
     *  if aCorrectionFactor = 1.0, the polygon is inside the circle
     *  the radius of circle approximated by segments is
     *  initial radius * aCorrectionFactor
     * @param aSkipNPTHPadsWihNoCopper = if true, do not add a NPTH pad shape,
     *  if the shape has same size and position as the hole. Usually, these
     *  pads are not drawn on copper layers, because there is actually no copper
     *  Due to diff between layers and holes, these pads must be skipped to be sure
     *  there is no copper left on the board (for instance when creating Gerber Files or 3D shapes)
     *  default = false
     */
    void TransformPadsShapesWithClearanceToPolygon( LAYER_ID aLayer,
                            SHAPE_POLY_SET& aCornerBuffer,
                            int             aInflateValue,
                            int             aCircleToSegmentsCount,
                            double          aCorrectionFactor,
                            bool            aSkipNPTHPadsWihNoCopper = false );

    /**
     * function TransformGraphicShapesWithClearanceToPolygonSet
     * generate shapes of graphic items (outlines) on layer aLayer as polygons,
     * and adds these polygons to aCornerBuffer
     * Useful to generate a polygonal representation of a footprint
     * in 3D view and plot functions, when a full polygonal approach is needed
     * @param aLayer = the current layer: items on this layer are considered
     * @param aCornerBuffer = the buffer to store polygons
     * @param aInflateValue = a value to inflate shapes
     *          aInflateValue = 0 to have the exact shape size
     * @param aCircleToSegmentsCount = number of segments to generate a circle
     * @param aCorrectionFactor = the correction to apply to a circle radius
     *  to approximate a circle by the polygon.
     *  if aCorrectionFactor = 1.0, the polygon is inside the circle
     *  the radius of circle approximated by segments is
     *  initial radius * aCorrectionFactor
     * @param aCircleToSegmentsCountForTexts = number of segments to generate
     *       a circle when building the texts polygonal shapes of the stroke font
     *       if 0, use the aCircleToSegmentsCount value
     */
    void TransformGraphicShapesWithClearanceToPolygonSet(
                            LAYER_ID aLayer,
                            SHAPE_POLY_SET& aCornerBuffer,
                            int             aInflateValue,
                            int             aCircleToSegmentsCount,
                            double          aCorrectionFactor,
                            int             aCircleToSegmentsCountForTexts = 0 );

    /**
     * Function DrawEdgesOnly
     *  Draws the footprint edges only to the current Device Context
     *  @param panel = The active Draw Panel (used to know the clip box)
     *  @param DC = current Device Context
     *  @param offset = draw offset (usually wxPoint(0,0)
     *  @param draw_mode =  GR_OR, GR_XOR, GR_AND
     */
    void DrawEdgesOnly( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
                        GR_DRAWMODE draw_mode );

    void DrawAncre( EDA_DRAW_PANEL* panel, wxDC* DC,
                    const wxPoint& offset, int dim_ancre, GR_DRAWMODE draw_mode );

    void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList );

    bool HitTest( const wxPoint& aPosition ) const;

    /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect,
     *                               bool aContained = true, int aAccuracy ) const
     */
    bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0 ) const;

    /**
     * Function GetReference
     * @return const wxString& - the reference designator text.
     */
    const wxString& GetReference() const
    {
        return m_Reference->GetText();
    }

    /**
     * Function SetReference
     * @param aReference A reference to a wxString object containing the reference designator
     *                   text.
     */
    void SetReference( const wxString& aReference )
    {
        m_Reference->SetText( aReference );
    }

    /**
     * Function GetReference prefix
     * Gets the alphabetic prefix of the module reference - e.g.
     *      R1    -> R
     *      IC34  -> IC
     * @return the reference prefix (may be empty)
     */
    wxString GetReferencePrefix() const;

    /**
     * Function GetValue
     * @return const wxString& - the value text.
     */
    const wxString& GetValue() const
    {
        return m_Value->GetText();
    }

    /**
     * Function SetValue
     * @param aValue A reference to a wxString object containing the value text.
     */
    void SetValue( const wxString& aValue )
    {
        m_Value->SetText( aValue );
    }

    /// read/write accessors:
    TEXTE_MODULE& Value()       { return *m_Value; }
    TEXTE_MODULE& Reference()   { return *m_Reference; }

    /// The const versions to keep the compiler happy.
    TEXTE_MODULE& Value() const       { return *m_Value; }
    TEXTE_MODULE& Reference() const   { return *m_Reference; }

    /*!
     * Function IncrementItemReference
     * Implementation of the generic "reference" incrementing interface
     * Increments the numeric suffix, filling any sequence gaps
     */
    bool IncrementItemReference(); //override

    /**
     * Function IncrementReference
     * Increments the module's reference, if possible. A reference with
     * a numerical suffix and an optional alphabetical prefix can be
     * incremented: "A1" and "1" can be, "B" can't.
     *
     * @param aFillSequenceGaps if true, the next reference in a sequence
     * like A1,A3,A4 will be A2. If false, it will be A5.
     * @return true if the reference was incremented.
     */
    bool IncrementReference( bool aFillSequenceGaps );

    /**
     * Function FindPadByName
     * returns a D_PAD* with a matching name.  Note that names may not be
     * unique, depending on how the foot print was created.
     * @param aPadName the pad name to find
     * @return D_PAD* - The first matching name is returned, or NULL if not
     *                  found.
     */
    D_PAD* FindPadByName( const wxString& aPadName ) const;

    /**
     * Function GetPad
     * get a pad at \a aPosition on \a aLayerMask in the footprint.
     *
     * @param aPosition A wxPoint object containing the position to hit test.
     * @param aLayerMask A layer or layers to mask the hit test.
     * @return A pointer to a D_PAD object if found otherwise NULL.
     */
    D_PAD* GetPad( const wxPoint& aPosition, LSET aLayerMask = LSET::AllLayersMask() );

    /**
     * GetPadCount
     * returns the number of pads.
     *
     * @param aIncludeNPTH includes non-plated through holes when true.  Does not include
     *                     non-plated through holes when false.
     * @return the number of pads according to \a aIncludeNPTH.
     */
    unsigned GetPadCount( INCLUDE_NPTH_T aIncludeNPTH = INCLUDE_NPTH_T( INCLUDE_NPTH ) ) const;

    /**
     * GetUniquePadCount
     * returns the number of unique pads.
     * A complex pad can be built with many pads having the same pad name
     * to create a complex shape or fragmented solder paste areas.
     *
     * GetUniquePadCount calculate the count of not blank pad names
     *
     * @param aIncludeNPTH includes non-plated through holes when true.  Does not include
     *                     non-plated through holes when false.
     * @return the number of unique pads according to \a aIncludeNPTH.
     */
    unsigned GetUniquePadCount( INCLUDE_NPTH_T aIncludeNPTH = INCLUDE_NPTH_T( INCLUDE_NPTH ) ) const;

    /**
     * Function GetNextPadName
     * returns the next available pad name in the module
     *
     * @param aFillSequenceGaps true if the numbering should "fill in" gaps in
     * the sequence, else return the highest value + 1
     * @return the next available pad name
     */
    wxString GetNextPadName( bool aFillSequenceGaps ) const;

    double GetArea() const                  { return m_Surface; }

    time_t GetLink() const                  { return m_Link; }
    void SetLink( time_t aLink )            { m_Link = aLink; }

    int GetPlacementCost180() const         { return m_CntRot180; }
    void SetPlacementCost180( int aCost )   { m_CntRot180 = aCost; }

    int GetPlacementCost90() const          { return m_CntRot90; }
    void SetPlacementCost90( int aCost )    { m_CntRot90 = aCost; }

    /**
     * Function DuplicateAndAddItem
     * Duplicate a given item within the module
     * @return the new item, or NULL if the item could not be duplicated
     */
    BOARD_ITEM* DuplicateAndAddItem( const BOARD_ITEM* item,
                                     bool aIncrementPadNumbers );

    /**
     * Function Add3DModel
     * adds \a a3DModel definition to the end of the 3D model list.
     *
     * @param a3DModel A pointer to a #S3D_MASTER to add to the list.
     */
    void Add3DModel( S3D_MASTER* a3DModel );

    SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData,
                         const KICAD_T scanTypes[] );

    wxString GetClass() const
    {
        return wxT( "MODULE" );
    }

    wxString GetSelectMenuText() const;

    BITMAP_DEF GetMenuImage() const { return  module_xpm; }

    EDA_ITEM* Clone() const;

    /**
     * Function RunOnChildren
     *
     * Invokes a function on all BOARD_ITEMs that belong to the module (pads, drawings, texts).
     * @param aFunction is the function to be invoked.
     */
    void RunOnChildren( boost::function<void (BOARD_ITEM*)> aFunction );

    /// @copydoc VIEW_ITEM::ViewUpdate()
    void ViewUpdate( int aUpdateFlags = KIGFX::VIEW_ITEM::ALL );

    /// @copydoc VIEW_ITEM::ViewGetLayers()
    virtual void ViewGetLayers( int aLayers[], int& aCount ) const;

    /// @copydoc VIEW_ITEM::ViewGetLOD()
    virtual unsigned int ViewGetLOD( int aLayer ) const;

    /// @copydoc VIEW_ITEM::ViewBBox()
    virtual const BOX2I ViewBBox() const;

    /**
     * Function CopyNetlistSettings
     * copies the netlist settings to \a aModule.
     * Used to copy some footprint parameters when replacing a footprint by an other
     * footprint when reading a netlist, or in exchange footprint dialog
     *
     * The netlist settings are all of the #MODULE settings not define by a #MODULE in
     * a netlist.  These setting include placement prms (position, orientation, side)
     * and optionally local prms( clearances, zone connection type, etc).
     * The reference designator, value, path, and physical geometry settings are not
     * copied.
     *
     * @param aModule is the #MODULE to copy the settings to.
     * @param aCopyLocalSettings = false to copy only module placement
     *   true to also copy local prms
     */
    void CopyNetlistSettings( MODULE* aModule, bool aCopyLocalSettings );

    /**
     * static function IsLibNameValid
     * Test for validity of a name of a footprint to be used in a footprint library
     * ( no spaces, dir separators ... )
     * @param aName = the name in library to validate
     * @return true if the given name is valid
     */
    static bool IsLibNameValid( const wxString & aName );

    /**
     * static function StringLibNameInvalidChars
     * Test for validity of the name in a library of the footprint
     * ( no spaces, dir separators ... )
     * @param aUserReadable = false to get the list of invalid chars
     *        true to get a readable form (i.e ' ' = 'space' '\\t'= 'tab')
     * @return a constant std::string giving the list of invalid chars in lib name
     */
    static const wxChar* StringLibNameInvalidChars( bool aUserReadable );

    /**
     * Function SetInitialComments
     * takes ownership of caller's heap allocated aInitialComments block.  The comments
     * are single line strings already containing the s-expression comments with
     * optional leading whitespace and then a '#' character followed by optional
     * single line text (text with no line endings, not even one).
     * This block of single line comments will be output upfront of any generated
     * s-expression text in the PCBIO::Format() function.
     * <p>
     * Note that a block of single line comments constitutes a multiline block of
     * single line comments.  That is, the block is made of consecutive single line
     * comments.
     * @param aInitialComments is a heap allocated wxArrayString or NULL, which the caller
     *  gives up ownership of over to this MODULE.
     */
    void SetInitialComments( wxArrayString* aInitialComments )
    {
        delete m_initial_comments;
        m_initial_comments = aInitialComments;
    }

    /**
     * Function PadCoverageRatio
     * Calculates the ratio of total area of the footprint pads to the area of the
     * footprint. Used by selection tool heuristics.
     * @return the ratio
     */
    double PadCoverageRatio() const;

    /// Return the initial comments block or NULL if none, without transfer of ownership.
    const wxArrayString* GetInitialComments() const { return m_initial_comments; }

#if defined(DEBUG)
    virtual void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); }    // override
#endif

private:
    DLIST<D_PAD>      m_Pads;           ///< Linked list of pads.
    DLIST<BOARD_ITEM> m_Drawings;       ///< Linked list of graphical items.
    DLIST<S3D_MASTER> m_3D_Drawings;    ///< Linked list of 3D models.
    double            m_Orient;         ///< Orientation in tenths of a degree, 900=90.0 degrees.
    wxPoint           m_Pos;            ///< Position of module on the board in internal units.
    TEXTE_MODULE*     m_Reference;      ///< Component reference designator value (U34, R18..)
    TEXTE_MODULE*     m_Value;          ///< Component value (74LS00, 22K..)
    FPID              m_fpid;           ///< The #FPID of the MODULE.
    int               m_Attributs;      ///< Flag bits ( see Mod_Attribut )
    int               m_ModuleStatus;   ///< For autoplace: flags (LOCKED, AUTOPLACED)
    EDA_RECT          m_BoundaryBox;    ///< Bounding box : coordinates on board, real orientation.

    // The final margin is the sum of these 2 values
    int               m_ThermalWidth;
    int               m_ThermalGap;
    wxString          m_Doc;            ///< File name and path for documentation file.
    wxString          m_KeyWord;        ///< Search keywords to find module in library.
    wxString          m_Path;
    ZoneConnection    m_ZoneConnection;
    time_t            m_LastEditTime;
    int               m_arflag;             ///< Use to trace ratsnest and auto routing.
    double            m_Surface;        ///< Bounding box area
    time_t            m_Link;           ///< Temporary logical link used in edition
    int               m_CntRot90;       ///< Horizontal automatic placement cost ( 0..10 ).
    int               m_CntRot180;      ///< Vertical automatic placement cost ( 0..10 ).

    // Local tolerances. When zero, this means the corresponding netclass value
    // is used. Usually theses local tolerances zero, in deference to the
    // corresponding netclass values.
    int               m_LocalClearance;
    int               m_LocalSolderMaskMargin;    ///< Solder mask margin
    int               m_LocalSolderPasteMargin;   ///< Solder paste margin absolute value
    double            m_LocalSolderPasteMarginRatio;   ///< Solder mask margin ratio
                                                       ///< value of pad size

    wxArrayString*    m_initial_comments;   ///< leading s-expression comments in the module,
                                            ///< lazily allocated only if needed for speed
};

#endif     // MODULE_H_