コード例 #1
0
ファイル: cvframe.cpp プロジェクト: morio/kicad-source-mirror
int CVPCB_MAINFRAME::ReadSchematicNetlist( const std::string& aNetlist )
{
    STRING_LINE_READER*     strrdr = new STRING_LINE_READER( aNetlist, "Eeschema via Kiway" );
    KICAD_NETLIST_READER    netrdr( strrdr, &m_netlist );

    m_netlist.Clear();

    try
    {
        netrdr.LoadNetlist();
    }
    catch( const IO_ERROR& ioe )
    {
        wxString msg = wxString::Format( _( "Error loading netlist.\n%s" ), ioe.errorText.GetData() );
        wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR );
        return 1;
    }

    // We also remove footprint name if it is "$noname" because this is a dummy name,
    // not the actual name of the footprint.
    for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ )
    {
        if( m_netlist.GetComponent( ii )->GetFPID().GetFootprintName() == std::string( "$noname" ) )
            m_netlist.GetComponent( ii )->SetFPID( FPID( wxEmptyString ) );
    }

    // Sort components by reference:
    m_netlist.SortByReference();

    return 0;
}
コード例 #2
0
MODULE* PCB_BASE_FRAME::Create_1_Module( const wxString& aModuleName )
{
    MODULE*  module;
    wxString moduleName;
    wxPoint  newpos;

    moduleName = aModuleName;

    // Ask for the new module reference
    if( moduleName.IsEmpty() )
    {
        wxTextEntryDialog dlg( this, FMT_MOD_REF, FMT_MOD_CREATE, moduleName );
        dlg.SetTextValidator( FOOTPRINT_NAME_VALIDATOR( &moduleName ) );

        if( dlg.ShowModal() != wxID_OK )
            return NULL;    //Aborted by user
    }

    moduleName.Trim( true );
    moduleName.Trim( false );

    if( moduleName.IsEmpty() )
    {
        DisplayInfoMessage( this, FMT_NO_REF_ABORTED );
        return NULL;
    }

    // Creates the new module and add it to the head of the linked list of modules
    module = new MODULE( GetBoard() );

    GetBoard()->Add( module );

    // Update parameters: position, timestamp ...
    newpos = GetCrossHairPosition();
    module->SetPosition( newpos );
    module->SetLastEditTime();

    // Update its name in lib
    module->SetFPID( FPID( moduleName ) );

    // Update reference:
    module->SetReference( moduleName );
    module->Reference().SetThickness( GetDesignSettings().m_ModuleTextWidth );
    module->Reference().SetSize( GetDesignSettings().m_ModuleTextSize );

    // Set the value field to a default value
    module->SetValue( wxT( "VAL**" ) );
    module->Value().SetThickness( GetDesignSettings().m_ModuleTextWidth );
    module->Value().SetSize( GetDesignSettings().m_ModuleTextSize );
    module->SetPosition( wxPoint( 0, 0 ) );

    SetMsgPanel( module );
    return module;
}
コード例 #3
0
void GPCB_FPL_CACHE::Load()
{
    wxDir dir( m_lib_path.GetPath() );

    if( !dir.IsOpened() )
    {
        THROW_IO_ERROR( wxString::Format( _( "footprint library path '%s' does not exist" ),
                                          m_lib_path.GetPath().GetData() ) );
    }

    wxString fpFileName;
    wxString wildcard = wxT( "*." ) + GedaPcbFootprintLibFileExtension;

    if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
        return;

    do
    {
        wxFileName fn( m_lib_path.GetPath(), fpFileName );

        // reader now owns fp, will close on exception or return
        FILE_LINE_READER reader( fn.GetFullPath() );
        std::string      name = TO_UTF8( fn.GetName() );
        MODULE*          footprint = parseMODULE( &reader );

        // The footprint name is the file name without the extension.
        footprint->SetFPID( FPID( fn.GetName() ) );
        m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) );

    } while( dir.GetNext( &fpFileName ) );

    // Remember the file modification time of library file when the
    // cache snapshot was made, so that in a networked environment we will
    // reload the cache as needed.
    m_mod_time = GetLibModificationTime();
}
コード例 #4
0
MODULE* PCB_BASE_FRAME::CreateNewModule( const wxString& aModuleName )
{
    // Creates a new footprint at position 0,0 which contains the minimal items:
    // the reference and the value.
    //   Value : initialized to the footprint name.
    //           put on fab layer (front side)
    //   Reference : initialized to a default value (REF**).
    //               put on silkscreen layer (front side)

    wxString moduleName = aModuleName;

    // Ask for the new module name
    if( moduleName.IsEmpty() )
    {
        wxTextEntryDialog dlg( this, FMT_MOD_REF, FMT_MOD_CREATE, moduleName );
        dlg.SetTextValidator( FILE_NAME_CHAR_VALIDATOR( &moduleName ) );

        if( dlg.ShowModal() != wxID_OK )
            return NULL;    //Aborted by user
    }

    moduleName.Trim( true );
    moduleName.Trim( false );

    if( moduleName.IsEmpty() )
    {
        DisplayInfoMessage( this, FMT_NO_REF_ABORTED );
        return NULL;
    }

    // Creates the new module and add it to the head of the linked list of modules
    MODULE* module = new MODULE( GetBoard() );

    GetBoard()->Add( module );

    // Update parameters: timestamp ...
    module->SetLastEditTime();

    // Update its name in lib
    module->SetFPID( FPID( moduleName ) );

    wxPoint default_pos;
    BOARD_DESIGN_SETTINGS& settings = GetDesignSettings();

    // Update reference:
    if( settings.m_RefDefaultText.IsEmpty() )
        module->SetReference( moduleName );
    else
        module->SetReference( settings.m_RefDefaultText );

    module->Reference().SetThickness( settings.m_ModuleTextWidth );
    module->Reference().SetSize( settings.m_ModuleTextSize );
    default_pos.y = GetDesignSettings().m_ModuleTextSize.y / 2;
    module->Reference().SetPosition( default_pos );
    module->Reference().SetLayer( ToLAYER_ID( settings.m_RefDefaultlayer ) );
    module->Reference().SetVisible( settings.m_RefDefaultVisibility );

    // Set the value field to a default value
    if( settings.m_ValueDefaultText.IsEmpty() )
        module->SetValue( moduleName );
    else
        module->SetValue( settings.m_ValueDefaultText );

    module->Value().SetThickness( GetDesignSettings().m_ModuleTextWidth );
    module->Value().SetSize( GetDesignSettings().m_ModuleTextSize );
    default_pos.y = -default_pos.y;
    module->Value().SetPosition( default_pos );
    module->Value().SetLayer( ToLAYER_ID( settings.m_ValueDefaultlayer ) );
    module->Value().SetVisible( settings.m_ValueDefaultVisibility );

    SetMsgPanel( module );
    return module;
}
コード例 #5
0
bool FOOTPRINT_EDIT_FRAME::SaveFootprintInLibrary( const wxString& aLibrary,
                                             MODULE*         aModule,
                                             bool            aOverwrite,
                                             bool            aDisplayDialog )
{
    if( aModule == NULL )
        return false;

    SetMsgPanel( aModule );


    // Legacy libraries are readable, but modifying legacy format is not allowed
    // So prompt the user if he try to add/replace a footprint in a legacy lib
    wxString    libfullname = Prj().PcbFootprintLibs()->FindRow( aLibrary )->GetFullURI();
    IO_MGR::PCB_FILE_T  piType = IO_MGR::GuessPluginTypeFromLibPath( libfullname );

    if( piType == IO_MGR::LEGACY )
    {
        DisplayInfoMessage( this, INFO_LEGACY_LIB_WARN_EDIT );
        return false;
    }

    // Ask what to use as the footprint name in the library
    wxString footprintName = aModule->GetFPID().GetFootprintName();

    if( aDisplayDialog )
    {
        wxTextEntryDialog dlg( this, _( "Name:" ), FMT_SAVE_MODULE, footprintName );

        if( dlg.ShowModal() != wxID_OK )
            return false;                   // canceled by user

        footprintName = dlg.GetValue();
        footprintName.Trim( true );
        footprintName.Trim( false );

        if( footprintName.IsEmpty() )
            return false;

        if( ! MODULE::IsLibNameValid( footprintName ) )
        {
            wxString msg = wxString::Format(
                    _("Error:\none of invalid chars '%s' found\nin '%s'" ),
                    MODULE::StringLibNameInvalidChars( true ),
                    GetChars( footprintName ) );

            DisplayError( NULL, msg );
            return false;
        }

        aModule->SetFPID( FPID( footprintName ) );
    }

    // Ensure this footprint has a libname
    if( footprintName.IsEmpty() )
    {
        footprintName = wxT("noname");
        aModule->SetFPID( FPID( footprintName ) );
    }

    bool module_exists = false;

    try
    {
        FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs();

        MODULE* m = tbl->FootprintLoad( aLibrary, footprintName );

        if( m )
        {
            delete m;

            module_exists = true;

            // an existing footprint is found in current lib
            if( aDisplayDialog )
            {
                wxString msg = wxString::Format( FMT_MOD_EXISTS,
                        footprintName.GetData(), aLibrary.GetData() );

                SetStatusText( msg );
            }

            if( !aOverwrite )
            {
                // Do not save the given footprint: an old one exists
                return true;
            }
        }

        // this always overwrites any existing footprint, but should yell on its
        // own if the library or footprint is not writable.
        tbl->FootprintSave( aLibrary, aModule );
    }
    catch( const IO_ERROR& ioe )
    {
        DisplayError( this, ioe.errorText );
        return false;
    }

    if( aDisplayDialog )
    {
        wxString fmt = module_exists ?
            _( "Component [%s] replaced in '%s'" ) :
            _( "Component [%s] added in  '%s'" );

        wxString msg = wxString::Format( fmt, footprintName.GetData(), aLibrary.GetData() );
        SetStatusText( msg );
    }

    return true;
}
コード例 #6
0
void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event )
{
    // First, test for invalid chars in module name
    wxString footprintName = m_FootprintNameCtrl->GetValue();

    if( ! footprintName.IsEmpty() )
    {
        if( ! MODULE::IsLibNameValid( footprintName ) )
        {
            wxString msg;
            msg.Printf( _( "Error:\none of invalid chars <%s> found\nin <%s>" ),
                        MODULE::StringLibNameInvalidChars( true ),
                        GetChars( footprintName ) );

            DisplayError( NULL, msg );
                return;
        }
    }

    m_parent->SaveCopyInUndoList( m_currentModule, UR_MODEDIT );
    m_currentModule->SetLocked( m_AutoPlaceCtrl->GetSelection() == 1 );

    switch( m_AttributsCtrl->GetSelection() )
    {
    case 0:
        m_currentModule->SetAttributes( 0 );
        break;

    case 1:
        m_currentModule->SetAttributes( MOD_CMS );
        break;

    case 2:
        m_currentModule->SetAttributes( MOD_VIRTUAL );
        break;
    }

    m_currentModule->SetPlacementCost90( m_CostRot90Ctrl->GetValue() );
    m_currentModule->SetPlacementCost180( m_CostRot180Ctrl->GetValue() );
    m_currentModule->SetDescription( m_DocCtrl->GetValue() );
    m_currentModule->SetKeywords( m_KeywordCtrl->GetValue() );

    // Init footprint name in library
    if( ! footprintName.IsEmpty() )
        m_currentModule->SetFPID( FPID( footprintName ) );

    // Init Fields:
    m_currentModule->Reference().Copy( m_referenceCopy );
    m_currentModule->Value().Copy( m_valueCopy );

    // Initialize masks clearances
    m_currentModule->SetLocalClearance( ValueFromTextCtrl( *m_NetClearanceValueCtrl ) );
    m_currentModule->SetLocalSolderMaskMargin( ValueFromTextCtrl( *m_SolderMaskMarginCtrl ) );
    m_currentModule->SetLocalSolderPasteMargin( ValueFromTextCtrl( *m_SolderPasteMarginCtrl ) );
    double   dtmp;
    wxString msg = m_SolderPasteMarginRatioCtrl->GetValue();
    msg.ToDouble( &dtmp );

    // A  -50% margin ratio means no paste on a pad, the ratio must be >= -50 %
    if( dtmp < -50.0 )
        dtmp = -50.0;

    // A margin ratio is always <= 0
    if( dtmp > 0.0 )
        dtmp = 0.0;

    m_currentModule->SetLocalSolderPasteMarginRatio( dtmp / 100 );

    // Update 3D shape list
    int ii = m_3D_ShapeNameListBox->GetSelection();

    if ( ii >= 0 )
        TransfertDisplayTo3DValues( ii );

    S3D_MASTER*   draw3D  = m_currentModule->Models();

    for( unsigned ii = 0; ii < m_shapes3D_list.size(); ii++ )
    {
        S3D_MASTER*   draw3DCopy = m_shapes3D_list[ii];

        if( draw3DCopy->GetShape3DName().IsEmpty() )
            continue;

        if( draw3D == NULL )
        {
            draw3D = new S3D_MASTER( draw3D );
            m_currentModule->Models().Append( draw3D );
        }

        draw3D->SetShape3DName( draw3DCopy->GetShape3DName() );
        draw3D->m_MatScale    = draw3DCopy->m_MatScale;
        draw3D->m_MatRotation = draw3DCopy->m_MatRotation;
        draw3D->m_MatPosition = draw3DCopy->m_MatPosition;

        draw3D = draw3D->Next();
    }

    // Remove old extra 3D shapes
    S3D_MASTER* nextdraw3D;

    for( ; draw3D != NULL; draw3D = nextdraw3D )
    {
        nextdraw3D = (S3D_MASTER*) draw3D->Next();
        delete m_currentModule->Models().Remove( draw3D );
    }

    // Fill shape list with one void entry, if no entry
    if( m_currentModule->Models() == NULL )
        m_currentModule->Models().PushBack( new S3D_MASTER( m_currentModule ) );


    m_currentModule->CalculateBoundingBox();

    m_parent->OnModify();

    EndModal( 1 );
}
コード例 #7
0
bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibrary,
                                             MODULE*         aModule,
                                             bool            aOverwrite,
                                             bool            aDisplayDialog )
{
    if( aModule == NULL )
        return false;

    SetMsgPanel( aModule );

    // Ask what to use as the footprint name in the library
    wxString footprintName = aModule->GetFPID().GetFootprintName();

    if( aDisplayDialog )
    {
        wxTextEntryDialog dlg( this, _( "Name:" ), FMT_SAVE_MODULE, footprintName );

        if( dlg.ShowModal() != wxID_OK )
            return false;                   // canceled by user

        footprintName = dlg.GetValue();
        footprintName.Trim( true );
        footprintName.Trim( false );

        if( footprintName.IsEmpty() )
            return false;

        if( ! MODULE::IsLibNameValid( footprintName ) )
        {
            wxString msg = wxString::Format(
                    _("Error:\none of invalid chars '%s' found\nin '%s'" ),
                    MODULE::StringLibNameInvalidChars( true ),
                    GetChars( footprintName ) );

            DisplayError( NULL, msg );
            return false;
        }

        aModule->SetFPID( FPID( footprintName ) );
    }

    // Ensure this footprint has a libname
    if( footprintName.IsEmpty() )
    {
        footprintName = wxT("noname");
        aModule->SetFPID( FPID( footprintName ) );
    }

    bool module_exists = false;

    try
    {
        MODULE* m = FootprintLibs()->FootprintLoad( aLibrary, footprintName );

        if( m )
        {
            delete m;

            module_exists = true;

            // an existing footprint is found in current lib
            if( aDisplayDialog )
            {
                wxString msg = wxString::Format( FMT_MOD_EXISTS,
                        footprintName.GetData(), aLibrary.GetData() );

                SetStatusText( msg );
            }

            if( !aOverwrite )
            {
                // Do not save the given footprint: an old one exists
                return true;
            }
        }

        // this always overwrites any existing footprint, but should yell on its
        // own if the library or footprint is not writable.
        FootprintLibs()->FootprintSave( aLibrary, aModule );
    }
    catch( const IO_ERROR& ioe )
    {
        DisplayError( this, ioe.errorText );
        return false;
    }

    if( aDisplayDialog )
    {
        wxString fmt = module_exists ?
            _( "Component [%s] replaced in '%s'" ) :
            _( "Component [%s] added in  '%s'" );

        wxString msg = wxString::Format( fmt, footprintName.GetData(), aLibrary.GetData() );
        SetStatusText( msg );
    }

    return true;
}
コード例 #8
0
ファイル: muonde.cpp プロジェクト: JOE-JOE-NGIGI/kicad
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC )
{
    D_PAD*   pad;
    int      ll;
    wxString msg;

    m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
    m_canvas->SetMouseCapture( NULL, NULL );

    if( s_inductor_pattern.m_Flag == false )
    {
        DisplayError( this, wxT( "Starting point not init.." ) );
        return NULL;
    }

    s_inductor_pattern.m_Flag = false;

    s_inductor_pattern.m_End = GetCrossHairPosition();

    wxPoint pt = s_inductor_pattern.m_End - s_inductor_pattern.m_Start;
    int     min_len = KiROUND( EuclideanNorm( pt ) );
    s_inductor_pattern.m_lenght = min_len;

    // Enter the desired length.
    msg = StringFromValue( g_UserUnit, s_inductor_pattern.m_lenght );
    wxTextEntryDialog dlg( this, wxEmptyString, _( "Length of Trace:" ), msg );

    if( dlg.ShowModal() != wxID_OK )
        return NULL; // canceled by user

    msg = dlg.GetValue();
    s_inductor_pattern.m_lenght = ValueFromString( g_UserUnit, msg );

    // Control values (ii = minimum length)
    if( s_inductor_pattern.m_lenght < min_len )
    {
        DisplayError( this, _( "Requested length < minimum length" ) );
        return NULL;
    }

    // Calculate the elements.
    s_inductor_pattern.m_Width = GetDesignSettings().GetCurrentTrackWidth();

    std::vector <wxPoint> buffer;
    ll = BuildCornersList_S_Shape( buffer, s_inductor_pattern.m_Start,
                                   s_inductor_pattern.m_End, s_inductor_pattern.m_lenght,
                                   s_inductor_pattern.m_Width );

    if( !ll )
    {
        DisplayError( this, _( "Requested length too large" ) );
        return NULL;
    }

    // Generate footprint. the value is also used as footprint name.
    msg.Empty();
    wxTextEntryDialog cmpdlg( this, wxEmptyString, _( "Component Value:" ), msg );
    cmpdlg.SetTextValidator( FILE_NAME_CHAR_VALIDATOR( &msg ) );

    if( ( cmpdlg.ShowModal() != wxID_OK ) || msg.IsEmpty() )
        return NULL;    //  Aborted by user

    MODULE* module = CreateNewModule( msg );

    // here the module is already in the BOARD, CreateNewModule() does that.
    module->SetFPID( FPID( std::string( "mw_inductor" ) ) );
    module->SetAttributes( MOD_VIRTUAL | MOD_CMS );
    module->ClearFlags();
    module->SetPosition( s_inductor_pattern.m_End );

    // Generate segments
    for( unsigned jj = 1; jj < buffer.size(); jj++ )
    {
        EDGE_MODULE* PtSegm;
        PtSegm = new EDGE_MODULE( module );
        PtSegm->SetStart( buffer[jj - 1] );
        PtSegm->SetEnd( buffer[jj] );
        PtSegm->SetWidth( s_inductor_pattern.m_Width );
        PtSegm->SetLayer( module->GetLayer() );
        PtSegm->SetShape( S_SEGMENT );
        PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() );
        PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() );
        module->GraphicalItems().PushBack( PtSegm );
    }

    // Place a pad on each end of coil.
    pad = new D_PAD( module );

    module->Pads().PushFront( pad );

    pad->SetPadName( wxT( "1" ) );
    pad->SetPosition( s_inductor_pattern.m_End );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    pad->SetSize( wxSize( s_inductor_pattern.m_Width, s_inductor_pattern.m_Width ) );

    pad->SetLayerSet( LSET( module->GetLayer() ) );
    pad->SetAttribute( PAD_ATTRIB_SMD );
    pad->SetShape( PAD_SHAPE_CIRCLE );

    D_PAD* newpad = new D_PAD( *pad );

    module->Pads().Insert( newpad, pad->Next() );

    pad = newpad;
    pad->SetPadName( wxT( "2" ) );
    pad->SetPosition( s_inductor_pattern.m_Start );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    // Modify text positions.
    SetMsgPanel( module );

    wxPoint refPos( ( s_inductor_pattern.m_Start.x + s_inductor_pattern.m_End.x ) / 2,
                    ( s_inductor_pattern.m_Start.y + s_inductor_pattern.m_End.y ) / 2 );

    wxPoint valPos = refPos;

    refPos.y -= module->Reference().GetSize().y;
    module->Reference().SetPosition( refPos );
    valPos.y += module->Value().GetSize().y;
    module->Value().SetPosition( valPos );

    module->CalculateBoundingBox();
    module->Draw( m_canvas, DC, GR_OR );

    return module;
}
コード例 #9
0
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC )
{
    D_PAD*   pad;
    int      ll;
    wxString msg;

    m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
    m_canvas->SetMouseCapture( NULL, NULL );

    if( Self_On == 0 )
    {
        DisplayError( this, wxT( "Starting point not init.." ) );
        return NULL;
    }

    Self_On = 0;

    Mself.m_End = GetCrossHairPosition();

    wxPoint pt = Mself.m_End - Mself.m_Start;
    int     min_len = KiROUND( EuclideanNorm( pt ) );
    Mself.lng = min_len;

    // Enter the desired length.
    msg = StringFromValue( g_UserUnit, Mself.lng );
    wxTextEntryDialog dlg( this, _( "Length:" ), _( "Length" ), msg );

    if( dlg.ShowModal() != wxID_OK )
        return NULL; // canceled by user

    msg = dlg.GetValue();
    Mself.lng = ValueFromString( g_UserUnit, msg );

    // Control values (ii = minimum length)
    if( Mself.lng < min_len )
    {
        DisplayError( this, _( "Requested length < minimum length" ) );
        return NULL;
    }

    // Calculate the elements.
    Mself.m_Width = GetBoard()->GetCurrentTrackWidth();

    std::vector <wxPoint> buffer;
    ll = BuildCornersList_S_Shape( buffer, Mself.m_Start, Mself.m_End, Mself.lng, Mself.m_Width );

    if( !ll )
    {
        DisplayError( this, _( "Requested length too large" ) );
        return NULL;
    }

    // Generate module.
    MODULE* module;
    module = Create_1_Module( wxEmptyString );

    if( module == NULL )
        return NULL;

    // here the module is already in the BOARD, Create_1_Module() does that.
    module->SetFPID( FPID( std::string( "MuSelf" ) ) );
    module->SetAttributes( MOD_VIRTUAL | MOD_CMS );
    module->ClearFlags();
    module->SetPosition( Mself.m_End );

    // Generate segments
    for( unsigned jj = 1; jj < buffer.size(); jj++ )
    {
        EDGE_MODULE* PtSegm;
        PtSegm = new EDGE_MODULE( module );
        PtSegm->SetStart( buffer[jj - 1] );
        PtSegm->SetEnd( buffer[jj] );
        PtSegm->SetWidth( Mself.m_Width );
        PtSegm->SetLayer( module->GetLayer() );
        PtSegm->SetShape( S_SEGMENT );
        PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() );
        PtSegm->SetEnd0(   PtSegm->GetEnd()   - module->GetPosition() );
        module->GraphicalItems().PushBack( PtSegm );
    }

    // Place a pad on each end of coil.
    pad = new D_PAD( module );

    module->Pads().PushFront( pad );

    pad->SetPadName( wxT( "1" ) );
    pad->SetPosition( Mself.m_End );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    pad->SetSize( wxSize( Mself.m_Width, Mself.m_Width ) );

    pad->SetLayerMask( GetLayerMask( module->GetLayer() ) );
    pad->SetAttribute( PAD_SMD );
    pad->SetShape( PAD_CIRCLE );

    D_PAD* newpad = new D_PAD( *pad );

    module->Pads().Insert( newpad, pad->Next() );

    pad = newpad;
    pad->SetPadName( wxT( "2" ) );
    pad->SetPosition( Mself.m_Start );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    // Modify text positions.
    SetMsgPanel( module );

    wxPoint refPos( ( Mself.m_Start.x + Mself.m_End.x ) / 2,
                    ( Mself.m_Start.y + Mself.m_End.y ) / 2 );

    wxPoint valPos = refPos;

    refPos.y -= module->Reference().GetSize().y;
    module->Reference().SetTextPosition( refPos );
    valPos.y += module->Value().GetSize().y;
    module->Value().SetTextPosition( valPos );
    module->Reference().SetPos0( module->Reference().GetTextPosition() - module->GetPosition() );
    module->Value().SetPos0( module->Value().GetTextPosition() - module->GetPosition() );

    module->CalculateBoundingBox();
    module->Draw( m_canvas, DC, GR_OR );

    return module;
}