Exemple #1
0
bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName )
{
    FILE* cmpFile;

    cmpFile = wxFopen( aFullCmpFileName, wxT( "wt" ) );

    if( cmpFile == NULL )
        return false;

    fprintf( cmpFile, "Cmp-Mod V01 Created by PcbNew   date = %s\n", TO_UTF8( DateAndTime() ) );

    MODULE* module = aBrd->m_Modules;
    for( ; module != NULL; module = module->Next() )
    {
        fprintf( cmpFile, "\nBeginCmp\n" );
        fprintf( cmpFile, "TimeStamp = %8.8lX\n", (unsigned long)module->GetTimeStamp() );
        fprintf( cmpFile, "Path = %s\n", TO_UTF8( module->GetPath() ) );
        fprintf( cmpFile, "Reference = %s;\n",
                 !module->GetReference().IsEmpty() ?
                 TO_UTF8( module->GetReference() ) : "[NoRef]" );
        fprintf( cmpFile, "ValeurCmp = %s;\n",
                 !module->GetValue().IsEmpty() ?
                 TO_UTF8( module->GetValue() ) : "[NoVal]" );
        fprintf( cmpFile, "IdModule  = %s;\n", module->GetFPID().Format().c_str() );
        fprintf( cmpFile, "EndCmp\n" );
    }

    fprintf( cmpFile, "\nEndListe\n" );
    fclose( cmpFile );

    return true;
}
Exemple #2
0
void DIALOG_EXCHANGE_MODULE::init()
{
    SetFocus();

    m_CurrentFootprintFPID->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) );
    m_NewFootprintFPID->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) );
    m_CmpValue->AppendText( m_currentModule->GetValue() );
    m_CmpReference->AppendText( m_currentModule->GetReference() );
    m_Selection->SetString( 0, wxString::Format(
                            _( "Change footprint of '%s'" ),
                            GetChars( m_currentModule->GetReference() ) ) );
    wxString fpname = m_CurrentFootprintFPID->GetValue().AfterLast( ':' );

    if( fpname.IsEmpty() )    // Happens for old fp names
        fpname = m_CurrentFootprintFPID->GetValue();

    m_Selection->SetString( 1, wxString::Format(
                            _( "Change footprints '%s'" ),
                            GetChars( fpname.Left( 12 ) ) ) );

    m_Selection->SetSelection( m_selectionMode );

    // Enable/disable widgets:
    wxCommandEvent event;
    OnSelectionClicked( event );
}
/**
 * Send a remote command to Eeschema via a socket,
 * @param objectToSync = item to be located on schematic (module, pin or text)
 * Commands are
 * $PART: "reference"   put cursor on component anchor
 * $PART: "reference" $PAD: "pad number" put cursor on the component pin
 * $PART: "reference" $REF: "reference" put cursor on the component ref
 * $PART: "reference" $VAL: "value" put cursor on the component value
 */
void PCB_EDIT_FRAME::SendMessageToEESCHEMA( BOARD_ITEM* objectToSync )
{
    char          cmd[1024];
    const char*   text_key;
    MODULE*       module = NULL;
    D_PAD*        pad;
    TEXTE_MODULE* text_mod;
    wxString      msg;

    if( objectToSync == NULL )
        return;

    switch( objectToSync->Type() )
    {
    case PCB_MODULE_T:
        module = (MODULE*) objectToSync;
        sprintf( cmd, "$PART: \"%s\"", TO_UTF8( module->GetReference() ) );
        break;

    case PCB_PAD_T:
        module = (MODULE*) objectToSync->GetParent();
        pad    = (D_PAD*) objectToSync;
        msg    = pad->GetPadName();
        sprintf( cmd, "$PART: \"%s\" $PAD: \"%s\"",
                 TO_UTF8( module->GetReference() ),
                 TO_UTF8( msg ) );
        break;

    case PCB_MODULE_TEXT_T:
        module   = (MODULE*) objectToSync->GetParent();
        text_mod = (TEXTE_MODULE*) objectToSync;

        if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE )
            text_key = "$REF:";
        else if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_VALUE )
            text_key = "$VAL:";
        else
            break;

        sprintf( cmd, "$PART: \"%s\" %s \"%s\"",
                 TO_UTF8( module->GetReference() ),
                 text_key,
                 TO_UTF8( text_mod->GetText() ) );
        break;

    default:
        break;
    }

    if( module )
    {
        SendCommand( MSG_TO_SCH, cmd );
    }
}
MODULE* FOOTPRINT_EDIT_FRAME::SelectFootprint( BOARD* aPcb )
{
    static wxString oldName;       // Save name of last module selected.

    wxString        fpname;
    wxString        msg;
    wxArrayString   listnames;
    MODULE*         module = aPcb->m_Modules;

    for(  ; module;  module = module->Next() )
        listnames.Add( module->GetReference() );

    msg.Printf( _( "Modules [%d items]" ), listnames.GetCount() );

    wxArrayString headers;

    headers.Add( _( "Module" ) );

    std::vector<wxArrayString> itemsToDisplay;

    // Conversion from wxArrayString to vector of ArrayString
    for( unsigned i = 0; i < listnames.GetCount(); i++ )
    {
        wxArrayString item;

        item.Add( listnames[i] );
        itemsToDisplay.push_back( item );
    }

    EDA_LIST_DIALOG dlg( this, msg, headers, itemsToDisplay, wxEmptyString, NULL, SORT_LIST );

    if( dlg.ShowModal() == wxID_OK )
        fpname = dlg.GetTextSelection();
    else
        return NULL;

    oldName = fpname;

    module = aPcb->m_Modules;

    for(  ;  module;  module = module->Next() )
    {
        if( fpname == module->GetReference() )
            break;
    }

    return module;
}
/*
 * Creates a footprint position file
 * aSide = 0 -> Back (bottom) side)
 * aSide = 1 -> Front (top) side)
 * aSide = 2 -> both sides
 * if aFullFileName is empty, the file is not created, only the
 * count of footprints to place is returned
 */
int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName,
        bool aUnitsMM,
        bool aForceSmdItems, int aSide )
{
    MODULE*     module;
    char        line[1024];

    File_Place_Offset = GetAuxOrigin();

    // Calculating the number of useful modules (CMS attribute, not VIRTUAL)
    int moduleCount = 0;

    for( module = GetBoard()->m_Modules;  module;  module = module->Next() )
    {
        if( aSide < 2 )
        {
            if( module->GetLayer() == B_Cu && aSide == 1)
                continue;
            if( module->GetLayer() == F_Cu && aSide == 0)
                continue;
        }

        if( module->GetAttributes() & MOD_VIRTUAL )
        {
            DBG( printf( "skipping module %s because it's virtual\n",
                         TO_UTF8( module->GetReference() ) );)
            continue;
        }
void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery )
{
    if( aPad == NULL )
        return;

    MODULE* module = aPad->GetParent();
    module->SetLastEditTime();

    // aQuery = true to prompt for confirmation, false to delete silently
    if( aQuery )
    {
        wxString msg = wxString::Format( _( "Delete pad (footprint %s %s)?" ),
                                         module->GetReference(),
                                         module->GetValue() );

        if( !IsOK( this, msg ) )
            return;
    }

    // Stores the initial bounding box to refresh the old area
    EDA_RECT bbox = module->GetBoundingBox();

    m_Pcb->m_Status_Pcb = 0;

    GetBoard()->PadDelete( aPad );

    // Update the bounding box
    module->CalculateBoundingBox();

    // Refresh the modified screen area, using the initial bounding box
    // which is perhaps larger than the new bounding box
    m_canvas->RefreshDrawingRect( bbox );

    OnModify();
}
void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery )
{
    if( aPad == NULL )
        return;

    MODULE* module = (MODULE*) aPad->GetParent();
    module->SetLastEditTime();

    // aQuery = true to prompt for confirmation, false to delete silently
    if( aQuery )
    {
        wxString msg;
        msg.Printf( _( "Delete Pad (footprint %s %s) ?" ),
                    GetChars( module->GetReference() ),
                    GetChars( module->GetValue() ) );

        if( !IsOK( this, msg ) )
            return;
    }

    m_Pcb->m_Status_Pcb = 0;
    aPad->DeleteStructure();
    // Refresh the modified screen area, using the initial bounding box
    // which is perhaps larger than the new bounding box
    m_canvas->RefreshDrawingRect( module->GetBoundingBox() );
    // Update the bounding box
    module->CalculateBoundingBox();

    OnModify();
}
/* Creates the section $DEVICES
 * This is a list of footprints properties
 *  ( Shapes are in section $SHAPE )
 */
static void CreateDevicesSection( FILE* aFile, BOARD* aPcb )
{
    MODULE* module;

    fputs( "$DEVICES\n", aFile );

    for( module = aPcb->m_Modules; module; module = module->Next() )
    {
        fprintf( aFile, "DEVICE \"%s\"\n", TO_UTF8( module->GetReference() ) );
        fprintf( aFile, "PART \"%s\"\n", TO_UTF8( module->GetValue() ) );
        fprintf( aFile, "PACKAGE \"%s\"\n", module->GetFPID().Format().c_str() );

        // The TYPE attribute is almost freeform
        const char* ty = "TH";

        if( module->GetAttributes() & MOD_CMS )
            ty = "SMD";

        if( module->GetAttributes() & MOD_VIRTUAL )
            ty = "VIRTUAL";

        fprintf( aFile, "TYPE %s\n", ty );
    }

    fputs( "$ENDDEVICES\n\n", aFile );
}
// see class_edge_mod.h
void EDGE_MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
{
    wxString msg;

    MODULE*  module = (MODULE*) m_Parent;

    if( !module )
        return;

    BOARD* board = (BOARD*) module->GetParent();

    if( !board )
        return;

    aList.push_back( MSG_PANEL_ITEM( _( "Graphic Item" ), wxEmptyString, DARKCYAN ) );
    aList.push_back( MSG_PANEL_ITEM( _( "Module" ), module->GetReference(), DARKCYAN ) );
    aList.push_back( MSG_PANEL_ITEM( _( "Value" ), module->GetValue(), BLUE ) );
    msg.Printf( wxT( "%8.8lX" ), module->GetTimeStamp() );
    aList.push_back( MSG_PANEL_ITEM( _( "TimeStamp" ), msg, BROWN ) );
    aList.push_back( MSG_PANEL_ITEM( _( "Mod Layer" ),
                     module->GetLayerName(), RED ) );
    aList.push_back( MSG_PANEL_ITEM( _( "Seg Layer" ),
                     GetLayerName(), RED ) );
    msg = ::CoordinateToString( m_Width );
    aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, BLUE ) );
}
Exemple #10
0
MODULE* PCB_EDIT_FRAME::ListAndSelectModuleName()
{
    if( GetBoard()->m_Modules == NULL )
    {
        DisplayError( this, _( "No footprints" ) );
        return 0;
    }

    wxArrayString listnames;

    MODULE* module;

    for( module = GetBoard()->m_Modules;  module;  module = module->Next() )
        listnames.Add( module->GetReference() );

    wxArrayString headers;
    headers.Add( wxT( "Module" ) );
    std::vector<wxArrayString> itemsToDisplay;

    // Conversion from wxArrayString to vector of ArrayString
    for( unsigned i = 0; i < listnames.GetCount(); i++ )
    {
        wxArrayString item;
        item.Add( listnames[i] );
        itemsToDisplay.push_back( item );
    }

    EDA_LIST_DIALOG dlg( this, _( "Components" ), headers, itemsToDisplay, wxEmptyString );

    if( dlg.ShowModal() != wxID_OK )
        return NULL;

    wxString ref = dlg.GetTextSelection();

    for( module = GetBoard()->m_Modules;  module;  module = module->Next() )
    {
        if( module->GetReference() == ref )
            break;
    }

    return module;
}
bool BOARD_NETLIST_UPDATER::deleteUnusedComponents( NETLIST& aNetlist )
{
    wxString msg;
    MODULE* nextModule;
    const COMPONENT* component;

    for( MODULE* module = m_board->m_Modules; module != NULL; module = nextModule )
    {
        nextModule = module->Next();

        if( m_lookupByTimestamp )
            component = aNetlist.GetComponentByTimeStamp( module->GetPath() );
        else
            component = aNetlist.GetComponentByReference( module->GetReference() );

        if( component == NULL )
        {
            if( module->IsLocked() )
            {
                msg.Printf( _( "Component %s is locked, skipping removal.\n" ),
                            GetChars( module->GetReference() ) );
                m_reporter->Report( msg, REPORTER::RPT_INFO );
                continue;
            }

            msg.Printf( _( "Remove component %s." ),
                        GetChars( module->GetReference() ) );
            m_reporter->Report( msg, REPORTER::RPT_ACTION );

            msg.Printf( _( "Removing unused component \"%s:%s\".\n" ),
                        GetChars( module->GetReference() ),
                        GetChars( module->GetPath() ) );
            m_reporter->Report( msg, REPORTER::RPT_INFO );

            if( !m_isDryRun )
                m_commit.Remove( module );
        }
    }

    return true;
}
// see class_text_mod.h
void TEXTE_MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
{
    MODULE* module = (MODULE*) m_Parent;

    if( module == NULL )        // Happens in modedit, and for new texts
        return;

    wxString msg, Line;

    static const wxString text_type_msg[3] =
    {
        _( "Ref." ), _( "Value" ), _( "Text" )
    };

    Line = module->GetReference();
    aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), Line, DARKCYAN ) );

    Line = GetShownText();
    aList.push_back( MSG_PANEL_ITEM( _( "Text" ), Line, BROWN ) );

    wxASSERT( m_Type >= TEXT_is_REFERENCE && m_Type <= TEXT_is_DIVERS );
    aList.push_back( MSG_PANEL_ITEM( _( "Type" ), text_type_msg[m_Type], DARKGREEN ) );

    if( !IsVisible() )
        msg = _( "No" );
    else
        msg = _( "Yes" );

    aList.push_back( MSG_PANEL_ITEM( _( "Display" ), msg, DARKGREEN ) );

    // Display text layer
    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), DARKGREEN ) );

    if( IsMirrored() )
        msg = _( "Yes" );
    else
        msg = _( "No" );

    aList.push_back( MSG_PANEL_ITEM( _( "Mirror" ), msg, DARKGREEN ) );

    msg.Printf( wxT( "%.1f" ), GetTextAngleDegrees() );
    aList.push_back( MSG_PANEL_ITEM( _( "Angle" ), msg, DARKGREEN ) );

    msg = ::CoordinateToString( GetThickness() );
    aList.push_back( MSG_PANEL_ITEM( _( "Thickness" ), msg, DARKGREEN ) );

    msg = ::CoordinateToString( GetTextWidth() );
    aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, RED ) );

    msg = ::CoordinateToString( GetTextHeight() );
    aList.push_back( MSG_PANEL_ITEM( _( "Height" ), msg, RED ) );
}
// see class_text_mod.h
void TEXTE_MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
{
    MODULE* module = (MODULE*) m_Parent;

    if( module == NULL )        // Happens in modedit, and for new texts
        return;

    wxString msg, Line;

    static const wxString text_type_msg[3] =
    {
        _( "Ref." ), _( "Value" ), _( "Text" )
    };

    Line = module->GetReference();
    aList.push_back( MSG_PANEL_ITEM( _( "Module" ), Line, DARKCYAN ) );

    Line = m_Text;
    aList.push_back( MSG_PANEL_ITEM( _( "Text" ), Line, BROWN ) );

    wxASSERT( m_Type >= TEXT_is_REFERENCE && m_Type <= TEXT_is_DIVERS );
    aList.push_back( MSG_PANEL_ITEM( _( "Type" ), text_type_msg[m_Type], DARKGREEN ) );

    if( m_NoShow )
        msg = _( "No" );
    else
        msg = _( "Yes" );

    aList.push_back( MSG_PANEL_ITEM( _( "Display" ), msg, DARKGREEN ) );

    // Display text layer
    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), DARKGREEN ) );

    if( m_Mirror )
        msg = _( " Yes" );
    else
        msg = _( " No" );

    aList.push_back( MSG_PANEL_ITEM( _( "Mirror" ), msg, DARKGREEN ) );

    msg.Printf( wxT( "%.1f" ), m_Orient / 10.0 );
    aList.push_back( MSG_PANEL_ITEM( _( "Orient" ), msg, DARKGREEN ) );

    msg = ::CoordinateToString( m_Thickness );
    aList.push_back( MSG_PANEL_ITEM( _( "Thickness" ), msg, DARKGREEN ) );

    msg = ::CoordinateToString( m_Size.x );
    aList.push_back( MSG_PANEL_ITEM( _( "H Size" ), msg, RED ) );

    msg = ::CoordinateToString( m_Size.y );
    aList.push_back( MSG_PANEL_ITEM( _( "V Size" ), msg, RED ) );
}
/* Extract the D356 record from the modules (pads) */
static void build_pad_testpoints( BOARD *aPcb,
    std::vector <D356_RECORD>& aRecords )
{
    wxPoint origin = aPcb->GetAuxOrigin();

    for( MODULE *module = aPcb->m_Modules;
        module; module = module->Next() )
    {
        for( D_PAD *pad = module->Pads();  pad; pad = pad->Next() )
        {
            D356_RECORD rk;
            rk.access = compute_pad_access_code( aPcb, pad->GetLayerSet() );

            // It could be a mask only pad, we only handle pads with copper here
            if( rk.access != -1 )
            {
                rk.netname = pad->GetNetname();
                rk.refdes = module->GetReference();
                pad->StringPadName( rk.pin );
                rk.midpoint = false; // XXX MAYBE need to be computed (how?)
                const wxSize& drill = pad->GetDrillSize();
                rk.drill = std::min( drill.x, drill.y );
                rk.hole = (rk.drill != 0);
                rk.smd = pad->GetAttribute() == PAD_ATTRIB_SMD;
                rk.mechanical = (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED);
                rk.x_location = pad->GetPosition().x - origin.x;
                rk.y_location = origin.y - pad->GetPosition().y;
                rk.x_size = pad->GetSize().x;

                // Rule: round pads have y = 0
                if( pad->GetShape() == PAD_SHAPE_CIRCLE )
                    rk.y_size = 0;
                else
                    rk.y_size = pad->GetSize().y;

                rk.rotation = -KiROUND( pad->GetOrientation() ) / 10;
                if( rk.rotation < 0 ) rk.rotation += 360;

                // the value indicates which sides are *not* accessible
                rk.soldermask = 3;
                if( pad->GetLayerSet()[F_Mask] )
                    rk.soldermask &= ~1;
                if( pad->GetLayerSet()[B_Mask] )
                    rk.soldermask &= ~2;

                aRecords.push_back( rk );
            }
        }
    }
}
/* Emit the netlist (which is actually the thing for which GenCAD is used these
 * days!); tracks are handled later */
static void CreateSignalsSection( FILE* aFile, BOARD* aPcb )
{
    wxString      msg;
    NETINFO_ITEM* net;
    D_PAD*        pad;
    MODULE*       module;
    int           NbNoConn = 1;

    fputs( "$SIGNALS\n", aFile );

    for( unsigned ii = 0; ii < aPcb->GetNetCount(); ii++ )
    {
        net = aPcb->FindNet( ii );

        if( net->GetNetname() == wxEmptyString ) // dummy netlist (no connection)
        {
            wxString msg; msg << wxT( "NoConnection" ) << NbNoConn++;
        }

        if( net->GetNet() <= 0 )  // dummy netlist (no connection)
            continue;

        msg = wxT( "SIGNAL " ) + net->GetNetname();

        fputs( TO_UTF8( msg ), aFile );
        fputs( "\n", aFile );

        for( module = aPcb->m_Modules; module; module = module->Next() )
        {
            for( pad = module->Pads(); pad; pad = pad->Next() )
            {
                wxString padname;

                if( pad->GetNetCode() != net->GetNet() )
                    continue;

                pad->StringPadName( padname );
                msg.Printf( wxT( "NODE %s %s" ),
                            GetChars( module->GetReference() ),
                            GetChars( padname ) );

                fputs( TO_UTF8( msg ), aFile );
                fputs( "\n", aFile );
            }
        }
    }

    fputs( "$ENDSIGNALS\n\n", aFile );
}
/*
 * Creates a footprint position file
 * aSide = 0 -> Back (bottom) side)
 * aSide = 1 -> Front (top) side)
 * aSide = 2 -> both sides
 * if aFullFileName is empty, the file is not created, only the
 * count of footprints to place is returned
 */
int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName,
                                                 bool aUnitsMM,
                                                 bool aForceSmdItems, int aSide,
                                                 bool aFormatCSV )
{
    MODULE*     footprint;

    // Minimal text lengths:
    int lenRefText = 8;
    int lenValText = 8;
    int lenPkgText = 16;

    File_Place_Offset = GetAuxOrigin();

    // Calculating the number of useful footprints (CMS attribute, not VIRTUAL)
    int footprintCount = 0;

    // Select units:
    double conv_unit = aUnitsMM ? conv_unit_mm : conv_unit_inch;
    const char *unit_text = aUnitsMM ? unit_text_mm : unit_text_inch;

    // Build and sort the list of footprints alphabetically
    std::vector<LIST_MOD> list;
    list.reserve( footprintCount );

    for( footprint = GetBoard()->m_Modules; footprint; footprint = footprint->Next() )
    {
        if( aSide != PCB_BOTH_SIDES )
        {
            if( footprint->GetLayer() == B_Cu && aSide == PCB_FRONT_SIDE)
                continue;
            if( footprint->GetLayer() == F_Cu && aSide == PCB_BACK_SIDE)
                continue;
        }

        if( footprint->GetAttributes() & MOD_VIRTUAL )
        {
            DBG( printf( "skipping footprint %s because it's virtual\n",
                         TO_UTF8( footprint->GetReference() ) );)
            continue;
        }
// see class_edge_mod.h
void EDGE_MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
{
    wxString msg;

    MODULE*  module = (MODULE*) m_Parent;

    if( !module )
        return;

    BOARD* board = (BOARD*) module->GetParent();

    if( !board )
        return;

    aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), module->GetReference(), DARKCYAN ) );
    aList.push_back( MSG_PANEL_ITEM( _( "Value" ), module->GetValue(), BLUE ) );
    msg.Printf( wxT( "%8.8lX" ), module->GetTimeStamp() );
    aList.push_back( MSG_PANEL_ITEM( _( "TimeStamp" ), msg, BROWN ) );
    aList.push_back( MSG_PANEL_ITEM( _( "Footprint Layer" ),
                     module->GetLayerName(), RED ) );

    // append the features shared with the base class
    DRAWSEGMENT::GetMsgPanelInfo( aList );
}
void D_PAD::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM>& aList )
{
    MODULE*     module;
    wxString    Line;
    BOARD*      board;

    module = (MODULE*) m_Parent;

    if( module )
    {
        wxString msg = module->GetReference();
        aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), msg, DARKCYAN ) );
        StringPadName( Line );
        aList.push_back( MSG_PANEL_ITEM( _( "Pad" ), Line, BROWN ) );
    }

    aList.push_back( MSG_PANEL_ITEM( _( "Net" ), GetNetname(), DARKCYAN ) );

    /* For test and debug only: display m_physical_connexion and
     * m_logical_connexion */
#if 1   // Used only to debug connectivity calculations
    Line.Printf( wxT( "%d-%d-%d " ), GetSubRatsnest(), GetSubNet(), GetZoneSubNet() );
    aList.push_back( MSG_PANEL_ITEM( wxT( "L-P-Z" ), Line, DARKGREEN ) );
#endif

    board = GetBoard();

    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ),
                     LayerMaskDescribe( board, m_layerMask ), DARKGREEN ) );

    aList.push_back( MSG_PANEL_ITEM( ShowPadShape(), ShowPadAttr(), DARKGREEN ) );

    Line = ::CoordinateToString( m_Size.x );
    aList.push_back( MSG_PANEL_ITEM( _( "Width" ), Line, RED ) );

    Line = ::CoordinateToString( m_Size.y );
    aList.push_back( MSG_PANEL_ITEM( _( "Height" ), Line, RED ) );

    Line = ::CoordinateToString( (unsigned) m_Drill.x );

    if( GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
    {
        aList.push_back( MSG_PANEL_ITEM( _( "Drill" ), Line, RED ) );
    }
    else
    {
        Line = ::CoordinateToString( (unsigned) m_Drill.x );
        wxString msg;
        msg = ::CoordinateToString( (unsigned) m_Drill.y );
        Line += wxT( "/" ) + msg;
        aList.push_back( MSG_PANEL_ITEM( _( "Drill X / Y" ), Line, RED ) );
    }

    double module_orient = module ? module->GetOrientation() : 0;

    if( module_orient )
        Line.Printf( wxT( "%3.1f(+%3.1f)" ),
                     ( m_Orient - module_orient ) / 10.0,
                     module_orient / 10.0 );
    else
        Line.Printf( wxT( "%3.1f" ), m_Orient / 10.0 );

    aList.push_back( MSG_PANEL_ITEM( _( "Angle" ), Line, LIGHTBLUE ) );

    Line = ::CoordinateToString( m_Pos.x ) + wxT( ", " ) + ::CoordinateToString( m_Pos.y );
    aList.push_back( MSG_PANEL_ITEM( _( "Position" ), Line, LIGHTBLUE ) );

    if( GetPadToDieLength() )
    {
        Line = ::CoordinateToString( GetPadToDieLength() );
        aList.push_back( MSG_PANEL_ITEM( _( "Length in package" ), Line, CYAN ) );
    }
}
Exemple #19
0
void D_PAD::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM>& aList )
{
    MODULE*     module;
    wxString    Line;
    BOARD*      board;

    module = (MODULE*) m_Parent;

    if( module )
    {
        aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), module->GetReference(), DARKCYAN ) );
        aList.push_back( MSG_PANEL_ITEM( _( "Pad" ), m_name, BROWN ) );
    }

    aList.push_back( MSG_PANEL_ITEM( _( "Net" ), GetNetname(), DARKCYAN ) );

    board = GetBoard();

    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ),
                     LayerMaskDescribe( board, m_layerMask ), DARKGREEN ) );

    aList.push_back( MSG_PANEL_ITEM( ShowPadShape(), ShowPadAttr(), DARKGREEN ) );

    Line = ::CoordinateToString( m_Size.x );
    aList.push_back( MSG_PANEL_ITEM( _( "Width" ), Line, RED ) );

    Line = ::CoordinateToString( m_Size.y );
    aList.push_back( MSG_PANEL_ITEM( _( "Height" ), Line, RED ) );

    Line = ::CoordinateToString( (unsigned) m_Drill.x );

    if( GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
    {
        aList.push_back( MSG_PANEL_ITEM( _( "Drill" ), Line, RED ) );
    }
    else
    {
        Line = ::CoordinateToString( (unsigned) m_Drill.x );
        wxString msg;
        msg = ::CoordinateToString( (unsigned) m_Drill.y );
        Line += wxT( "/" ) + msg;
        aList.push_back( MSG_PANEL_ITEM( _( "Drill X / Y" ), Line, RED ) );
    }

    double module_orient_degrees = module ? module->GetOrientationDegrees() : 0;

    if( module_orient_degrees != 0.0 )
        Line.Printf( wxT( "%3.1f(+%3.1f)" ),
                     GetOrientationDegrees() - module_orient_degrees,
                     module_orient_degrees );
    else
        Line.Printf( wxT( "%3.1f" ), GetOrientationDegrees() );

    aList.push_back( MSG_PANEL_ITEM( _( "Angle" ), Line, LIGHTBLUE ) );

    Line = ::CoordinateToString( m_Pos.x ) + wxT( ", " ) + ::CoordinateToString( m_Pos.y );
    aList.push_back( MSG_PANEL_ITEM( _( "Position" ), Line, LIGHTBLUE ) );

    if( GetPadToDieLength() )
    {
        Line = ::CoordinateToString( GetPadToDieLength() );
        aList.push_back( MSG_PANEL_ITEM( _( "Length in package" ), Line, CYAN ) );
    }
}
void D_PAD::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM>& aList )
{
    MODULE*     module;
    wxString    msg;
    BOARD*      board;

    module = (MODULE*) m_Parent;

    if( module )
    {
        aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), module->GetReference(), DARKCYAN ) );
        aList.push_back( MSG_PANEL_ITEM( _( "Pad" ), m_name, BROWN ) );
    }

    aList.push_back( MSG_PANEL_ITEM( _( "Net" ), UnescapeString( GetNetname() ), DARKCYAN ) );

    board = GetBoard();

    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ),
                     LayerMaskDescribe( board, m_layerMask ), DARKGREEN ) );

    aList.push_back( MSG_PANEL_ITEM( ShowPadShape(), ShowPadAttr(), DARKGREEN ) );

    msg = MessageTextFromValue( aUnits, m_Size.x, true );
    aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, RED ) );

    msg = MessageTextFromValue( aUnits, m_Size.y, true );
    aList.push_back( MSG_PANEL_ITEM( _( "Height" ), msg, RED ) );

    msg = MessageTextFromValue( aUnits, m_Drill.x, true );

    if( GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
    {
        aList.push_back( MSG_PANEL_ITEM( _( "Drill" ), msg, RED ) );
    }
    else
    {
        msg = MessageTextFromValue( aUnits, m_Drill.x, true )
               + wxT( "/" )
               + MessageTextFromValue( aUnits, m_Drill.y, true );
        aList.push_back( MSG_PANEL_ITEM( _( "Drill X / Y" ), msg, RED ) );
    }

    double module_orient_degrees = module ? module->GetOrientationDegrees() : 0;

    if( module_orient_degrees != 0.0 )
        msg.Printf( wxT( "%3.1f(+%3.1f)" ),
                    GetOrientationDegrees() - module_orient_degrees,
                    module_orient_degrees );
    else
        msg.Printf( wxT( "%3.1f" ), GetOrientationDegrees() );

    aList.push_back( MSG_PANEL_ITEM( _( "Angle" ), msg, LIGHTBLUE ) );

    msg = MessageTextFromValue( aUnits, m_Pos.x )
           + wxT( ", " )
           + MessageTextFromValue( aUnits, m_Pos.y );
    aList.push_back( MSG_PANEL_ITEM( _( "Position" ), msg, LIGHTBLUE ) );

    if( GetPadToDieLength() )
    {
        msg = MessageTextFromValue( aUnits, GetPadToDieLength(), true );
        aList.push_back( MSG_PANEL_ITEM( _( "Length in package" ), msg, CYAN ) );
    }
}
void DIALOG_NETLIST::OnTestFootprintsClick( wxCommandEvent& event )
{
    if( m_parent->GetBoard()->m_Modules == NULL )
    {
        DisplayInfoMessage( this, _( "No footprints" ) );
        return;
    }

    // Lists of duplicates, missing references and not in netlist footprints:
    std::vector <MODULE*> duplicate;
    wxArrayString missing;
    std::vector <MODULE*> notInNetlist;
    wxString netlistFilename = m_NetlistFilenameCtrl->GetValue();

    if( !verifyFootprints( netlistFilename, wxEmptyString, duplicate, missing, notInNetlist ) )
        return;

#define ERR_CNT_MAX 100 // Max number of errors to output in dialog
    // to avoid a too long message list

    wxString list;          // The messages to display

    m_parent->SetLastNetListRead( netlistFilename );

    int err_cnt = 0;

    // Search for duplicate footprints.
    if( duplicate.size() == 0 )
        list << wxT("<p><b>") << _( "No duplicate." ) << wxT("</b></p>");
    else
    {
        list << wxT("<p><b>") << _( "Duplicates:" ) << wxT("</b></p>");

        for( unsigned ii = 0; ii < duplicate.size(); ii++ )
        {
            MODULE* module = duplicate[ii];

            if( module->GetReference().IsEmpty() )
                list << wxT("<br>") << wxT("[noref)");
            else
                list << wxT("<br>") << module->GetReference();

            list << wxT("  (<i>") << module->GetValue() << wxT("</i>)");
            list << wxT(" @ ");
            list << CoordinateToString( module->GetPosition().x ),
                 list << wxT(", ") << CoordinateToString( module->GetPosition().y ),
                 err_cnt++;

            if( ERR_CNT_MAX < err_cnt )
                break;
        }
    }

    // Search for missing modules on board.
    if( missing.size() == 0 )
        list << wxT("<p><b>") <<  _( "No missing footprints." ) << wxT("</b></p>");
    else
    {
        list << wxT("<p><b>") << _( "Missing:" ) << wxT("</b></p>");

        for( unsigned ii = 0; ii < missing.size(); ii += 2 )
        {
            list << wxT("<br>") << missing[ii];
            list << wxT("  (<i>") << missing[ii+1] << wxT("</i>)");
            err_cnt++;

            if( ERR_CNT_MAX < err_cnt )
                break;
        }
    }


    // Search for modules found on board but not in net list.
    if( notInNetlist.size() == 0 )
        list << wxT( "<p><b>" ) << _( "No extra footprints." ) << wxT( "</b></p>" );
    else
    {
        list << wxT( "<p><b>" ) << _( "Not in Netlist:" ) << wxT( "</b></p>" );

        for( unsigned ii = 0; ii < notInNetlist.size(); ii++ )
        {
            MODULE* module = notInNetlist[ii];

            if( module->GetReference().IsEmpty() )
                list << wxT( "<br>" ) << wxT( "[noref)" );
            else
                list << wxT( "<br>" ) << module->GetReference() ;

            list << wxT( " (<i>" ) << module->GetValue() << wxT( "</i>)" );
            list << wxT( " @ " );
            list << CoordinateToString( module->GetPosition().x ),
                 list << wxT( ", " ) << CoordinateToString( module->GetPosition().y ),
                 err_cnt++;

            if( ERR_CNT_MAX < err_cnt )
                break;
        }
    }

    if( ERR_CNT_MAX < err_cnt )
    {
        list << wxT( "<p><b>" )
             << _( "Too many errors: some are skipped" )
             << wxT( "</b></p>" );
    }

    HTML_MESSAGE_BOX dlg( this, _( "Check footprints" ) );
    dlg.AddHTML_Text( list );
    dlg.ShowModal();
}
bool DIALOG_NETLIST::verifyFootprints( const wxString&         aNetlistFilename,
                                       const wxString &        aCmpFilename,
                                       std::vector< MODULE* >& aDuplicates,
                                       wxArrayString&          aMissing,
                                       std::vector< MODULE* >& aNotInNetlist )
{
    wxString        msg;
    MODULE*         module;
    MODULE*         nextModule;
    NETLIST         netlist;
    wxBusyCursor    dummy;           // Shows an hourglass while calculating.
    NETLIST_READER* netlistReader;
    COMPONENT*      component;

    try
    {
        netlistReader = NETLIST_READER::GetNetlistReader( &netlist, aNetlistFilename,
                        aCmpFilename );

        if( netlistReader == NULL )
        {
            msg.Printf( _( "Cannot open netlist file \"%s\"." ), GetChars( aNetlistFilename ) );
            wxMessageBox( msg, _( "Netlist Load Error." ), wxOK | wxICON_ERROR );
            return false;
        }

        std::auto_ptr< NETLIST_READER > nlr( netlistReader );
        netlistReader->LoadNetlist();
    }
    catch( const IO_ERROR& ioe )
    {
        msg.Printf( _( "Error loading netlist file:\n%s" ), ioe.errorText.GetData() );
        wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR );
        return false;
    }

    BOARD* pcb = m_parent->GetBoard();

    // Search for duplicate footprints.
    module = pcb->m_Modules;

    for( ; module != NULL; module = module->Next() )
    {
        nextModule = module->Next();

        for( ; nextModule != NULL; nextModule = nextModule->Next() )
        {
            if( module->GetReference().CmpNoCase( nextModule->GetReference() ) == 0 )
            {
                aDuplicates.push_back( module );
                break;
            }
        }
    }

    // Search for component footprints in the netlist but not on the board.
    for( unsigned ii = 0; ii < netlist.GetCount(); ii++ )
    {
        component = netlist.GetComponent( ii );

        module = pcb->FindModuleByReference( component->GetReference() );

        if( module == NULL )
        {
            aMissing.Add( component->GetReference() );
            aMissing.Add( component->GetValue() );
        }
    }

    // Search for component footprints found on board but not in netlist.
    module = pcb->m_Modules;

    for( ; module != NULL; module = module->Next() )
    {

        component = netlist.GetComponentByReference( module->GetReference() );

        if( component == NULL )
            aNotInNetlist.push_back( module );
    }

    return true;
}
Exemple #23
0
void D_PAD::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM>& aList )
{
    MODULE*     module;
    wxString    Line;
    BOARD*      board;

    module = (MODULE*) m_Parent;

    if( module )
    {
        wxString msg = module->GetReference();
        aList.push_back( MSG_PANEL_ITEM( _( "Module" ), msg, DARKCYAN ) );
        ReturnStringPadName( Line );
        aList.push_back( MSG_PANEL_ITEM( _( "RefP" ), Line, BROWN ) );
    }

    aList.push_back( MSG_PANEL_ITEM( _( "Net" ), m_Netname, DARKCYAN ) );

    /* For test and debug only: display m_physical_connexion and
     * m_logical_connexion */
#if 1   // Used only to debug connectivity calculations
    Line.Printf( wxT( "%d-%d-%d " ), GetSubRatsnest(), GetSubNet(), GetZoneSubNet() );
    aList.push_back( MSG_PANEL_ITEM( wxT( "L-P-Z" ), Line, DARKGREEN ) );
#endif

    board = GetBoard();

    wxString layerInfo;

    if( (m_layerMask & ALL_CU_LAYERS) == 0 )     // pad is not on any copper layers
    {
        switch( m_layerMask & ~ALL_CU_LAYERS )
        {
        case ADHESIVE_LAYER_BACK:
            layerInfo = board->GetLayerName( ADHESIVE_N_BACK );
            break;

        case ADHESIVE_LAYER_FRONT:
            layerInfo = board->GetLayerName( ADHESIVE_N_FRONT );
            break;

        case SOLDERPASTE_LAYER_BACK:
            layerInfo = board->GetLayerName( SOLDERPASTE_N_BACK );
            break;

        case SOLDERPASTE_LAYER_FRONT:
            layerInfo = board->GetLayerName( SOLDERPASTE_N_FRONT );
            break;

        case SILKSCREEN_LAYER_BACK:
            layerInfo = board->GetLayerName( SILKSCREEN_N_BACK );
            break;

        case SILKSCREEN_LAYER_FRONT:
            layerInfo = board->GetLayerName( SILKSCREEN_N_FRONT );
            break;

        case SOLDERMASK_LAYER_BACK:
            layerInfo = board->GetLayerName( SOLDERMASK_N_BACK );
            break;

        case SOLDERMASK_LAYER_FRONT:
            layerInfo = board->GetLayerName( SOLDERMASK_N_FRONT );
            break;

        case DRAW_LAYER:
            layerInfo = board->GetLayerName( DRAW_N );
            break;

        case COMMENT_LAYER:
            layerInfo = board->GetLayerName( COMMENT_N );
            break;

        case ECO1_LAYER:
            layerInfo = board->GetLayerName( ECO1_N );
            break;

        case ECO2_LAYER:
            layerInfo = board->GetLayerName( ECO2_N );
            break;

        case EDGE_LAYER:
            layerInfo = board->GetLayerName( EDGE_N );
            break;

        default:
            layerInfo = _( "Non-copper" );
            break;
        }
    }
    else
    {
#define INTERIOR_COPPER     (ALL_CU_LAYERS & ~(LAYER_BACK | LAYER_FRONT))

        static const wxChar* andInternal = _( " & int" );

        if( (m_layerMask & (LAYER_BACK | LAYER_FRONT)) == LAYER_BACK )
        {
            layerInfo = board->GetLayerName( LAYER_N_BACK );

            if( m_layerMask & INTERIOR_COPPER )
                layerInfo += andInternal;
        }

        else if( (m_layerMask & (LAYER_BACK | LAYER_FRONT)) == (LAYER_BACK | LAYER_FRONT) )
        {
            layerInfo = board->GetLayerName( LAYER_N_BACK ) + wxT(", ") +
                        board->GetLayerName( LAYER_N_FRONT );

            if( m_layerMask & INTERIOR_COPPER )
                layerInfo += andInternal;
        }

        else if( (m_layerMask & (LAYER_BACK | LAYER_FRONT)) == LAYER_FRONT )
        {
            layerInfo = board->GetLayerName( LAYER_N_FRONT );

            if( m_layerMask & INTERIOR_COPPER )
                layerInfo += andInternal;
        }
        else // necessarily true: if( m_layerMask & INTERIOR_COPPER )
        {
            layerInfo = _( "internal" );
        }
    }

    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), layerInfo, DARKGREEN ) );

    aList.push_back( MSG_PANEL_ITEM( ShowPadShape(), ShowPadAttr(), DARKGREEN ) );

    Line = ::CoordinateToString( m_Size.x );
    aList.push_back( MSG_PANEL_ITEM( _( "H Size" ), Line, RED ) );

    Line = ::CoordinateToString( m_Size.y );
    aList.push_back( MSG_PANEL_ITEM( _( "V Size" ), Line, RED ) );

    Line = ::CoordinateToString( (unsigned) m_Drill.x );

    if( m_DrillShape == PAD_CIRCLE )
    {
        aList.push_back( MSG_PANEL_ITEM( _( "Drill" ), Line, RED ) );
    }
    else
    {
        Line = ::CoordinateToString( (unsigned) m_Drill.x );
        wxString msg;
        msg = ::CoordinateToString( (unsigned) m_Drill.y );
        Line += wxT( "/" ) + msg;
        aList.push_back( MSG_PANEL_ITEM( _( "Drill X / Y" ), Line, RED ) );
    }

    int module_orient = module ? module->GetOrientation() : 0;

    if( module_orient )
        Line.Printf( wxT( "%3.1f(+%3.1f)" ),
                     (double) ( m_Orient - module_orient ) / 10,
                     (double) module_orient / 10 );
    else
        Line.Printf( wxT( "%3.1f" ), (double) m_Orient / 10 );

    aList.push_back( MSG_PANEL_ITEM( _( "Orient" ), Line, LIGHTBLUE ) );

    Line = ::CoordinateToString( m_Pos.x );
    aList.push_back( MSG_PANEL_ITEM( _( "X Pos" ), Line, LIGHTBLUE ) );

    Line = ::CoordinateToString( m_Pos.y );
    aList.push_back( MSG_PANEL_ITEM( _( "Y pos" ), Line, LIGHTBLUE ) );

    if( GetPadToDieLength() )
    {
        Line = ::CoordinateToString( GetPadToDieLength() );
        aList.push_back( MSG_PANEL_ITEM( _( "Length in package" ), Line, CYAN ) );
    }
}
/* Creates the section $COMPONENTS (Footprints placement)
 * Bottom side components are difficult to handle: shapes must be mirrored or
 * flipped, silk layers need to be handled correctly and so on. Also it seems
 * that *noone* follows the specs...
 */
static void CreateComponentsSection( FILE* aFile, BOARD* aPcb )
{
    fputs( "$COMPONENTS\n", aFile );

    int cu_count = aPcb->GetCopperLayerCount();

    for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
    {
        const char*   mirror;
        const char*   flip;
        double        fp_orient = module->GetOrientation();

        if( module->GetFlag() )
        {
            mirror = "0";
            flip   = "FLIP";
            NEGATE_AND_NORMALIZE_ANGLE_POS( fp_orient );
        }
        else
        {
            mirror = "0";
            flip   = "0";
        }

        fprintf( aFile, "\nCOMPONENT %s\n",
                 TO_UTF8( module->GetReference() ) );
        fprintf( aFile, "DEVICE %s_%s\n",
                 TO_UTF8( module->GetReference() ),
                 TO_UTF8( module->GetValue() ) );
        fprintf( aFile, "PLACE %g %g\n",
                 MapXTo( module->GetPosition().x ),
                 MapYTo( module->GetPosition().y ) );
        fprintf( aFile, "LAYER %s\n",
                 (module->GetFlag()) ? "BOTTOM" : "TOP" );
        fprintf( aFile, "ROTATION %g\n",
                 fp_orient / 10.0 );
        fprintf( aFile, "SHAPE %s %s %s\n",
                 TO_UTF8( module->GetReference() ),
                 mirror, flip );

        // Text on silk layer: RefDes and value (are they actually useful?)
        TEXTE_MODULE *textmod = &module->Reference();

        for( int ii = 0; ii < 2; ii++ )
        {
            double      txt_orient = textmod->GetOrientation();
            std::string layer  = GenCADLayerName( cu_count, module->GetFlag() ? B_SilkS : F_SilkS );

            fprintf( aFile, "TEXT %g %g %g %g %s %s \"%s\"",
                     textmod->GetPos0().x / SCALE_FACTOR,
                    -textmod->GetPos0().y / SCALE_FACTOR,
                     textmod->GetSize().x / SCALE_FACTOR,
                     txt_orient / 10.0,
                     mirror,
                     layer.c_str(),
                     TO_UTF8( textmod->GetText() ) );

            // Please note, the width is approx
            fprintf( aFile, " 0 0 %g %g\n",
                     ( textmod->GetSize().x * textmod->GetLength() ) / SCALE_FACTOR,
                     textmod->GetSize().y / SCALE_FACTOR );

            textmod = &module->Value(); // Dirty trick for the second iteration
        }

        // The SHEET is a 'generic description' for referencing the component
        fprintf( aFile, "SHEET \"RefDes: %s, Value: %s\"\n",
                 TO_UTF8( module->GetReference() ),
                 TO_UTF8( module->GetValue() ) );
    }

    fputs( "$ENDCOMPONENTS\n\n", aFile );
}
void PCB_EDIT_FRAME::RecreateBOMFileFromBoard( wxCommandEvent& aEvent )
{
    wxFileName fn;
    FILE*      fp_bom;
    MODULE*    module = GetBoard()->m_Modules;
    wxString   msg;

    if( module == NULL )
    {
        DisplayError( this, _( "Cannot export BOM: there are no footprints in the PCB" ) );
        return;
    }

    /* Set the file extension: */
    fn = GetBoard()->GetFileName();
    fn.SetExt( CsvFileExtension );

    wxString pro_dir = wxPathOnly( Prj().GetProjectFullName() );

    wxFileDialog dlg( this, _( "Save Bill of Materials" ), pro_dir,
                      fn.GetFullName(), CsvFileWildcard(),
                      wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

    if( dlg.ShowModal() == wxID_CANCEL )
        return;

    fn = dlg.GetPath();

    fp_bom = wxFopen( fn.GetFullPath(), wxT( "wt" ) );

    if( fp_bom == NULL )
    {
        msg.Printf( _( "Unable to create file \"%s\"" ), GetChars( fn.GetFullPath() ) );
        DisplayError( this, msg );
        return;
    }

    // Write header:
    msg = wxT( "\"" );
    msg << _( "Id" ) << wxT( "\";\"" );
    msg << _( "Designator" ) << wxT( "\";\"" );
    msg << _( "Package" ) << wxT( "\";\"" );
    msg << _( "Quantity" ) << wxT( "\";\"" );
    msg << _( "Designation" ) << wxT( "\";\"" );
    msg << _( "Supplier and ref" ) << wxT( "\";\n" );
    fprintf( fp_bom, "%s", TO_UTF8( msg ) );

    // Build list
    CmpList           list;
    cmp*              comp = NULL;
    CmpList::iterator iter;
    int               i = 1;

    while( module != NULL )
    {
        bool valExist = false;

        // try to find component in existing list
        for( iter = list.begin(); iter != list.end(); ++iter )
        {
            cmp* current = *iter;

            if( (current->m_Val == module->GetValue()) && (current->m_fpid == module->GetFPID()) )
            {
                current->m_Ref.Append( wxT( ", " ), 1 );
                current->m_Ref.Append( module->GetReference() );
                current->m_CmpCount++;

                valExist = true;
                break;
            }
        }

        // If component does not exist yet, create new one and append it to the list.
        if( valExist == false )
        {
            comp = new cmp();
            comp->m_Id  = i++;
            comp->m_Val = module->GetValue();
            comp->m_Ref = module->GetReference();
            comp->m_fpid = module->GetFPID();
            comp->m_CmpCount = 1;
            list.Append( comp );
        }

        // increment module
        module = module->Next();
    }

    // Print list. Also delete temporary created objects.
    for( size_t ii = list.GetCount(); ii > 0; ii-- )
    {
        cmp* current = *list.begin();   // Because the first object will be removed
                                        // from list, all objects will be get here

        msg.Empty();

        msg << current->m_Id << wxT( ";\"" );
        msg << current->m_Ref << wxT( "\";\"" );
        msg << FROM_UTF8( current->m_fpid.GetLibItemName().c_str() ) << wxT( "\";" );
        msg << current->m_CmpCount << wxT( ";\"" );
        msg << current->m_Val << wxT( "\";;;\n" );
        fprintf( fp_bom, "%s", TO_UTF8( msg ) );

        // We do not need this object, now: remove it from list and delete it
        list.DeleteObject( current );
        delete (current);
    }

    fclose( fp_bom );
}
/**
 * Function Inspect
 * is the examining function within the INSPECTOR which is passed to the
 * Iterate function.  Searches and collects all the objects that the old
 * function PcbGeneralLocateAndDisplay() would find, except that it keeps all
 * that it finds and does not do any displaying.
 *
 * @param testItem An EDA_ITEM to examine.
 * @param testData The const void* testData, not used here.
 * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan,
 *   else SCAN_CONTINUE;
 */
SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, const void* testData )
{
    BOARD_ITEM* item   = (BOARD_ITEM*) testItem;
    MODULE*     module = NULL;
    D_PAD*      pad    = NULL;
    bool        pad_through = false;
    SEGVIA*     via    = NULL;
    MARKER_PCB* marker = NULL;

#if 0   // debugging
    static int  breakhere = 0;

    switch( item->Type() )
    {
    case PCB_PAD_T:
        {
            MODULE* m = (MODULE*) item->GetParent();

            if( m->GetReference() == wxT( "Y2" ) )
            {
                breakhere++;
            }
        }
        break;

    case PCB_VIA_T:
        breakhere++;
        break;

    case PCB_TRACE_T:
        breakhere++;
        break;

    case PCB_ZONE_T:
        breakhere++;
        break;

    case PCB_TEXT_T:
        breakhere++;
        break;

    case PCB_LINE_T:
        breakhere++;
        break;

    case PCB_DIMENSION_T:
        breakhere++;
        break;

    case PCB_MODULE_TEXT_T:
        {
            TEXTE_MODULE* tm = (TEXTE_MODULE*) item;

            if( tm->GetText() == wxT( "10uH" ) )
            {
                breakhere++;
            }
        }
        break;

    case PCB_MODULE_T:
        {
            MODULE* m = (MODULE*) item;

            if( m->GetReference() == wxT( "C98" ) )
            {
                breakhere++;
            }
        }
        break;

    case PCB_MARKER_T:
        breakhere++;
        break;

    default:
        breakhere++;
        break;
    }

#endif


    switch( item->Type() )
    {
    case PCB_PAD_T:
        // there are pad specific visibility controls.
        // Criterias to select a pad is:
        // for smd pads: the module parent must be seen, and pads on the corresponding
        // board side must be seen
        // if pad is a thru hole, then it can be visible when its parent module is not.
        // for through pads: pads on Front or Back board sides must be seen
        pad = (D_PAD*) item;

        if( (pad->GetAttribute() != PAD_SMD) &&
            (pad->GetAttribute() != PAD_CONN) )    // a hole is present, so multiple layers
        {
            // proceed to the common tests below, but without the parent module test,
            // by leaving module==NULL, but having pad != null
            pad_through = true;
        }
        else  // smd, so use pads test after module test
        {
            module = (MODULE*) item->GetParent();
        }

        break;

    case PCB_VIA_T:     // vias are on many layers, so layer test is specific
        via = (SEGVIA*) item;
        break;

    case PCB_TRACE_T:
        break;

    case PCB_ZONE_T:
        break;

    case PCB_ZONE_AREA_T:
        break;

    case PCB_TEXT_T:
        break;

    case PCB_LINE_T:
        break;

    case PCB_DIMENSION_T:
        break;

    case PCB_TARGET_T:
        break;

    case PCB_MODULE_TEXT_T:
        module = (MODULE*) item->GetParent();

        if( m_Guide->IgnoreMTextsMarkedNoShow() && !( (TEXTE_MODULE*) item )->IsVisible() )
            goto exit;

        if( module )
        {
            if( m_Guide->IgnoreMTextsOnCopper() && module->GetLayer()==LAYER_N_BACK )
                goto exit;

            if( m_Guide->IgnoreMTextsOnCmp() && module->GetLayer()==LAYER_N_FRONT )
                goto exit;

            if( m_Guide->IgnoreModulesVals() && item == &module->Value() )
                goto exit;

            if( m_Guide->IgnoreModulesRefs() && item == &module->Reference() )
                goto exit;
        }
        break;

    case PCB_MODULE_T:
        module = (MODULE*) item;
        break;

    case PCB_MARKER_T:
        marker = (MARKER_PCB*) item;
        break;

    default:
        break;
    }

    // common tests:

    if( module )    // true from case PCB_PAD_T, PCB_MODULE_TEXT_T, or PCB_MODULE_T
    {
        if( m_Guide->IgnoreModulesOnCu() && module->GetLayer()==LAYER_N_BACK )
            goto exit;

        if( m_Guide->IgnoreModulesOnCmp() && module->GetLayer()==LAYER_N_FRONT )
            goto exit;
    }

    // Pads are not sensitive to the layer visibility controls.
    // They all have their own separate visibility controls
    // skip them if not visible
    if( pad )
    {
        if( m_Guide->IgnorePads() )
            goto exit;

        if( ! pad_through )
        {
            if( m_Guide->IgnorePadsOnFront() && pad->IsOnLayer(LAYER_N_FRONT ) )
                goto exit;

            if( m_Guide->IgnorePadsOnBack() && pad->IsOnLayer(LAYER_N_BACK ) )
                goto exit;
        }
    }

    if( marker )
    {
        // Markers are not sensitive to the layer
        if( marker->HitTest( m_RefPos ) )
            Append( item );

        goto exit;
    }

    if( item->IsOnLayer( m_Guide->GetPreferredLayer() ) || m_Guide->IgnorePreferredLayer() )
    {
        LAYER_NUM layer = item->GetLayer();

        // Modules and their subcomponents: text and pads are not sensitive to the layer
        // visibility controls.  They all have their own separate visibility controls
        // for vias, GetLayer() has no meaning, but IsOnLayer() works fine
        if( via || module || pad || m_Guide->IsLayerVisible( layer ) || !m_Guide->IgnoreNonVisibleLayers() )
        {
            if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() )
            {
                if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
                {
                    if( item->HitTest( m_RefPos ) )
                    {
                        Append( item );
                        goto exit;
                    }
                }
            }
        }
    }


    if( m_Guide->IncludeSecondary() )
    {
        // for now, "secondary" means "tolerate any layer".  It has
        // no effect on other criteria, since there is a separate "ignore" control for
        // those in the COLLECTORS_GUIDE

        LAYER_NUM layer = item->GetLayer();

        // Modules and their subcomponents: text and pads are not sensitive to the layer
        // visibility controls.  They all have their own separate visibility controls
        if( via || module || pad || m_Guide->IsLayerVisible( layer ) || !m_Guide->IgnoreNonVisibleLayers() )
        {
            if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() )
            {
                if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
                {
                    if( item->HitTest( m_RefPos ) )
                    {
                        Append2nd( item );
                        goto exit;
                    }
                }
            }
        }
    }

exit:
    return SEARCH_CONTINUE;     // always when collecting
}
void DialogEditModuleText::initDlg( )
{
    SetFocus();

    wxString msg;

    if( m_module )
    {
        wxString format = m_ModuleInfoText->GetLabel();
        msg.Printf( format,
                    GetChars( m_module->GetReference() ),
                    GetChars( m_module->GetValue() ),
                    m_module->GetOrientation() / 10.0 );
    }
    else
    {
        msg.Empty();
    }

    m_ModuleInfoText->SetLabel( msg );

    switch( m_currentText->GetType() )
    {
    case TEXTE_MODULE::TEXT_is_VALUE:
        m_TextDataTitle->SetLabel( _( "Value:" ) );
        break;

    case TEXTE_MODULE::TEXT_is_DIVERS:
        m_TextDataTitle->SetLabel( _( "Text:" ) );
        break;

    default:
        m_TextDataTitle->SetLabel( _( "Reference:" ) );
        break;
    }

    m_Name->SetValue( m_currentText->GetText() );

    m_Style->SetSelection( m_currentText->IsItalic() ? 1 : 0 );

    AddUnitSymbol( *m_SizeXTitle );
    PutValueInLocalUnits( *m_TxtSizeCtrlX, m_currentText->GetSize().x );

    AddUnitSymbol( *m_SizeYTitle );
    PutValueInLocalUnits( *m_TxtSizeCtrlY, m_currentText->GetSize().y );

    AddUnitSymbol( *m_PosXTitle );
    PutValueInLocalUnits( *m_TxtPosCtrlX, m_currentText->GetPos0().x );

    AddUnitSymbol( *m_PosYTitle );
    PutValueInLocalUnits( *m_TxtPosCtrlY, m_currentText->GetPos0().y );

    AddUnitSymbol( *m_WidthTitle );
    PutValueInLocalUnits( *m_TxtWidthCtlr, m_currentText->GetThickness() );

    double text_orient = m_currentText->GetOrientation();
    NORMALIZE_ANGLE_90( text_orient );

    if( (text_orient != 0) )
        m_Orient->SetSelection( 1 );

    if( !m_currentText->IsVisible() )
        m_Show->SetSelection( 1 );;
}
/* Plot a copper layer or mask.
 * Silk screen layers are not plotted here.
 */
void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
                        LAYER_MSK aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt )
{

    BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
    itemplotter.SetLayerMask( aLayerMask );

    EDA_DRAW_MODE_T plotMode = aPlotOpt.GetMode();

     // Plot edge layer and graphic items
    itemplotter.PlotBoardGraphicItems();

    // Draw footprint shapes without pads (pads will plotted later)
    // We plot here module texts, but they are usually on silkscreen layer,
    // so they are not plot here but plot by PlotSilkScreen()
    // Plot footprints fields (ref, value ...)
    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
        if( ! itemplotter.PlotAllTextsModule( module ) )
        {
            wxLogMessage( _( "Your BOARD has a bad layer number for module %s" ),
                           GetChars( module->GetReference() ) );
        }
    }

    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
        for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
        {
            if( ! (aLayerMask & GetLayerMask( item->GetLayer() ) ) )
                continue;

            switch( item->Type() )
            {
            case PCB_MODULE_EDGE_T:
                itemplotter.Plot_1_EdgeModule( (EDGE_MODULE*) item );
                break;

            default:
                break;
            }
        }
    }

    // Plot footprint pads
    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
        for( D_PAD* pad = module->Pads();  pad;  pad = pad->Next() )
        {
            if( (pad->GetLayerMask() & aLayerMask) == 0 )
                continue;

            wxSize margin;
            double width_adj = 0;

            if( aLayerMask & ALL_CU_LAYERS )
                width_adj =  itemplotter.getFineWidthAdj();

            switch( aLayerMask &
                   ( SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT |
                     SOLDERPASTE_LAYER_BACK | SOLDERPASTE_LAYER_FRONT ) )
            {
            case SOLDERMASK_LAYER_FRONT:
            case SOLDERMASK_LAYER_BACK:
                margin.x = margin.y = pad->GetSolderMaskMargin();
                break;

            case SOLDERPASTE_LAYER_FRONT:
            case SOLDERPASTE_LAYER_BACK:
                margin = pad->GetSolderPasteMargin();
                break;

            default:
                break;
            }

            wxSize padPlotsSize;
            padPlotsSize.x = pad->GetSize().x + ( 2 * margin.x ) + width_adj;
            padPlotsSize.y = pad->GetSize().y + ( 2 * margin.y ) + width_adj;

            // Don't draw a null size item :
            if( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 )
                continue;

            EDA_COLOR_T color = BLACK;

            if( (pad->GetLayerMask() & LAYER_BACK) )
               color = aBoard->GetVisibleElementColor( PAD_BK_VISIBLE );

            if((pad->GetLayerMask() & LAYER_FRONT ) )
                color = ColorFromInt( color | aBoard->GetVisibleElementColor( PAD_FR_VISIBLE ) );

            // Temporary set the pad size to the required plot size:
            wxSize tmppadsize = pad->GetSize();
            pad->SetSize( padPlotsSize );
            switch( pad->GetShape() )
            {
            case PAD_CIRCLE:
            case PAD_OVAL:
                if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
                    (pad->GetSize() == pad->GetDrillSize()) &&
                    (pad->GetAttribute() == PAD_HOLE_NOT_PLATED) )
                    break;

                // Fall through:
            case PAD_TRAPEZOID:
            case PAD_RECT:
            default:
                itemplotter.PlotPad( pad, color, plotMode );
                break;
            }

            pad->SetSize( tmppadsize );     // Restore the pad size
        }
    }

    // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
    // plot them on solder mask
    for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
    {
        const VIA* Via = dynamic_cast<const VIA*>( track );

        if( !Via )
            continue;

        // vias are not plotted if not on selected layer, but if layer
        // is SOLDERMASK_LAYER_BACK or SOLDERMASK_LAYER_FRONT,vias are drawn,
        // only if they are on the corresponding external copper layer
        int via_mask_layer = Via->GetLayerMask();

        if( aPlotOpt.GetPlotViaOnMaskLayer() )
        {
            if( via_mask_layer & LAYER_BACK )
                via_mask_layer |= SOLDERMASK_LAYER_BACK;

            if( via_mask_layer & LAYER_FRONT )
                via_mask_layer |= SOLDERMASK_LAYER_FRONT;
        }

        if( ( via_mask_layer & aLayerMask ) == 0 )
            continue;

        int via_margin = 0;
        double width_adj = 0;

        // If the current layer is a solder mask, use the global mask
        // clearance for vias
        if( ( aLayerMask & ( SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT ) ) )
            via_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;

        if( aLayerMask & ALL_CU_LAYERS )
            width_adj = itemplotter.getFineWidthAdj();

        int diameter = Via->GetWidth() + 2 * via_margin + width_adj;

        // Don't draw a null size item :
        if( diameter <= 0 )
            continue;

        EDA_COLOR_T color = aBoard->GetVisibleElementColor(VIAS_VISIBLE + Via->GetViaType());
        // Set plot color (change WHITE to LIGHTGRAY because
        // the white items are not seen on a white paper or screen
        aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY);
        aPlotter->FlashPadCircle( Via->GetStart(), diameter, plotMode );
    }

    // Plot tracks (not vias) :
    for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
    {
        if( track->Type() == PCB_VIA_T )
            continue;

        if( (GetLayerMask( track->GetLayer() ) & aLayerMask) == 0 )
            continue;

        int width = track->GetWidth() + itemplotter.getFineWidthAdj();
        aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
        aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode );
    }

    // Plot zones (outdated, for old boards compatibility):
    for( TRACK* track = aBoard->m_Zone; track; track = track->Next() )
    {
        if( (GetLayerMask( track->GetLayer() ) & aLayerMask) == 0 )
            continue;

        int width = track->GetWidth() + itemplotter.getFineWidthAdj();
        aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
        aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode );
    }

    // Plot filled ares
    for( int ii = 0; ii < aBoard->GetAreaCount(); ii++ )
    {
        ZONE_CONTAINER* zone = aBoard->GetArea( ii );

        if( ( GetLayerMask(zone->GetLayer() )  & aLayerMask ) == 0 )
            continue;

        itemplotter.PlotFilledAreas( zone );
    }

    // Adding drill marks, if required and if the plotter is able to plot them:
    if( aPlotOpt.GetDrillMarksType() != PCB_PLOT_PARAMS::NO_DRILL_SHAPE )
        itemplotter.PlotDrillMarks();
}
/* Creates the plot for silkscreen layers
 * Silkscreen layers have specific requirement for pads (not filled) and texts
 * (with option to remove them from some copper areas (pads...)
 */
void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LAYER_MSK aLayerMask,
                     const PCB_PLOT_PARAMS& aPlotOpt )
{
    BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
    itemplotter.SetLayerMask( aLayerMask );

    // Plot edge layer and graphic items
    itemplotter.PlotBoardGraphicItems();

    // Plot footprint outlines :
    itemplotter.Plot_Edges_Modules();

    // Plot pads (creates pads outlines, for pads on silkscreen layers)
    int layersmask_plotpads = aLayerMask;
    // Calculate the mask layers of allowed layers for pads

    if( !aPlotOpt.GetPlotPadsOnSilkLayer() )       // Do not plot pads on silk screen layers
        layersmask_plotpads &= ~(SILKSCREEN_LAYER_BACK | SILKSCREEN_LAYER_FRONT );

    if( layersmask_plotpads )
    {
        for( MODULE* Module = aBoard->m_Modules; Module; Module = Module->Next() )
        {
            for( D_PAD * pad = Module->Pads(); pad != NULL; pad = pad->Next() )
            {
                // See if the pad is on this layer
                LAYER_MSK masklayer = pad->GetLayerMask();
                if( (masklayer & layersmask_plotpads) == 0 )
                    continue;

                EDA_COLOR_T color = ColorFromInt(0);
                if( (layersmask_plotpads & SILKSCREEN_LAYER_BACK) )
                   color = aBoard->GetLayerColor( SILKSCREEN_N_BACK );

                if((layersmask_plotpads & SILKSCREEN_LAYER_FRONT ) )
                    color = ColorFromInt( color | aBoard->GetLayerColor( SILKSCREEN_N_FRONT ) );

                itemplotter.PlotPad( pad, color, LINE );
            }
        }
    }

    // Plot footprints fields (ref, value ...)
    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
        if( ! itemplotter.PlotAllTextsModule( module ) )
        {
             wxLogMessage( _( "Your BOARD has a bad layer number for module %s" ),
                           GetChars( module->GetReference() ) );
        }
    }

    // Plot filled areas
    for( int ii = 0; ii < aBoard->GetAreaCount(); ii++ )
    {
        ZONE_CONTAINER* edge_zone = aBoard->GetArea( ii );

        if( ( GetLayerMask( edge_zone->GetLayer() ) & aLayerMask ) == 0 )
            continue;

        itemplotter.PlotFilledAreas( edge_zone );
    }

    // Plot segments used to fill zone areas (outdated, but here for old boards
    // compatibility):
    for( SEGZONE* seg = aBoard->m_Zone; seg != NULL; seg = seg->Next() )
    {
        if( ( GetLayerMask( seg->GetLayer() ) & aLayerMask ) == 0 )
            continue;

        aPlotter->ThickSegment( seg->GetStart(), seg->GetEnd(), seg->GetWidth(),
                                itemplotter.GetMode() );
    }
}
Exemple #30
0
// Handles the selection of command events.
void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
{
    int         id = event.GetId();
    LAYER_NUM itmp;
    INSTALL_UNBUFFERED_DC( dc, m_canvas );
    MODULE* module;

    m_canvas->CrossHairOff( &dc );

    switch( id )   // Some (not all ) edit commands must be finished or aborted
    {
    case wxID_CUT:
    case wxID_COPY:
    case ID_PCB_USER_GRID_SETUP:
    case ID_TOOLBARH_PCB_SELECT_LAYER:
    case ID_AUX_TOOLBAR_PCB_SELECT_LAYER_PAIR:
    case ID_POPUP_PCB_ROTATE_TEXTEPCB:
    case ID_POPUP_PCB_FLIP_TEXTEPCB:
    case ID_POPUP_PCB_COPY_TEXTEPCB:
    case ID_POPUP_PCB_EDIT_TEXTEPCB:
    case ID_POPUP_PCB_EDIT_MIRE:
    case ID_POPUP_PCB_ROTATE_TEXTMODULE:
    case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE:
    case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE:
    case ID_POPUP_PCB_CHANGE_SIDE_MODULE:
    case ID_POPUP_PCB_EDIT_MODULE_PRMS:
    case ID_POPUP_PCB_EDIT_MODULE_WITH_MODEDIT:
    case ID_POPUP_PCB_EDIT_TEXTMODULE:
    case ID_POPUP_PCB_STOP_CURRENT_DRAWING:
    case ID_POPUP_PCB_BEGIN_TRACK:
    case ID_POPUP_PCB_END_TRACK:
    case ID_POPUP_PCB_PLACE_THROUGH_VIA:
    case ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_THROUGH_VIA:
    case ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA:
    case ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_BLIND_BURIED_VIA:
    case ID_POPUP_PCB_PLACE_MICROVIA:
    case ID_POPUP_PCB_SWITCH_TRACK_POSTURE:
    case ID_POPUP_PCB_IMPORT_PAD_SETTINGS:
    case ID_POPUP_PCB_EXPORT_PAD_SETTINGS:
    case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS:
    case ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE:
    case ID_POPUP_PCB_DELETE_ZONE_LAST_CREATED_CORNER:
    case ID_POPUP_PCB_FILL_ALL_ZONES:
    case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES:
    case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_CURRENT_ZONE:
    case ID_POPUP_PCB_PLACE_ZONE_CORNER:
    case ID_POPUP_PCB_PLACE_ZONE_OUTLINES:
    case ID_POPUP_PCB_EDIT_ZONE_PARAMS:
    case ID_POPUP_PCB_DELETE_ZONE:
    case ID_POPUP_PCB_MOVE_ZONE_CORNER:
    case ID_POPUP_PCB_DRAG_ZONE_OUTLINE_SEGMENT:
    case ID_POPUP_PCB_MOVE_ZONE_OUTLINES:
    case ID_POPUP_PCB_ADD_ZONE_CORNER:
    case ID_POPUP_PCB_DELETE_TRACKSEG:
    case ID_POPUP_PCB_DELETE_TRACK:
    case ID_POPUP_PCB_DELETE_TRACKNET:
    case ID_POPUP_PCB_FILL_ZONE:
    case ID_POPUP_PCB_SELECT_LAYER:
    case ID_POPUP_PCB_SELECT_CU_LAYER:
    case ID_POPUP_PCB_SELECT_LAYER_PAIR:
    case ID_POPUP_PCB_SELECT_NO_CU_LAYER:
    case ID_POPUP_PCB_MOVE_TRACK_NODE:
    case ID_POPUP_PCB_MOVE_TEXTEPCB_REQUEST:
    case ID_POPUP_PCB_DRAG_TRACK_SEGMENT_KEEP_SLOPE:
    case ID_POPUP_PCB_DRAG_TRACK_SEGMENT:
    case ID_POPUP_PCB_MOVE_TRACK_SEGMENT:
    case ID_POPUP_PCB_PLACE_MOVED_TRACK_NODE:
    case ID_POPUP_PCB_BREAK_TRACK:
    case ID_POPUP_PCB_EDIT_NET:
    case ID_POPUP_PCB_EDIT_TRACK:
    case ID_POPUP_PCB_EDIT_TRACKSEG:
    case ID_POPUP_PCB_LOCK_ON_TRACKSEG:
    case ID_POPUP_PCB_LOCK_OFF_TRACKSEG:
    case ID_POPUP_PCB_LOCK_ON_TRACK:
    case ID_POPUP_PCB_LOCK_OFF_TRACK:
    case ID_POPUP_PCB_LOCK_ON_NET:
    case ID_POPUP_PCB_LOCK_OFF_NET:
    case ID_POPUP_DELETE_BLOCK:
    case ID_POPUP_PLACE_BLOCK:
    case ID_POPUP_ZOOM_BLOCK:
    case ID_POPUP_FLIP_BLOCK:
    case ID_POPUP_ROTATE_BLOCK:
    case ID_POPUP_COPY_BLOCK:
    case ID_POPUP_PCB_EDIT_DRAWING:
    case ID_POPUP_PCB_GETINFO_MARKER:
    case ID_POPUP_PCB_MOVE_TEXT_DIMENSION_REQUEST:
    case ID_POPUP_PCB_DRAG_MODULE_REQUEST:
    case ID_POPUP_PCB_MOVE_MODULE_REQUEST:
    case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST:
    case ID_POPUP_PCB_MOVE_MIRE_REQUEST:
        break;

    case ID_POPUP_CANCEL_CURRENT_COMMAND:
        if( m_canvas->IsMouseCaptured() )
        {
            m_canvas->EndMouseCapture();
        }

        // Should not be executed, just in case
        if( GetScreen()->m_BlockLocate.GetCommand() != BLOCK_IDLE )
        {
            GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE );
            GetScreen()->m_BlockLocate.SetState( STATE_NO_BLOCK );
            GetScreen()->m_BlockLocate.ClearItemsList();
        }

        if( GetToolId() == ID_NO_TOOL_SELECTED )
            SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString );
        else
            SetCursor( (wxStockCursor) m_canvas->GetDefaultCursor() );

        break;

    default:        // Finish (abort) the command
        if( m_canvas->IsMouseCaptured() )
            m_canvas->CallEndMouseCapture( &dc );

        if( GetToolId() != id )
        {
            if( m_lastDrawToolId != GetToolId() )
                m_lastDrawToolId = GetToolId();

            SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString );
        }
        break;
    }

    switch( id )   // Execute command
    {
    case 0:
        break;

    case ID_OPEN_MODULE_EDITOR:
        {
            FOOTPRINT_EDIT_FRAME* editor = (FOOTPRINT_EDIT_FRAME*) Kiway().Player( FRAME_PCB_MODULE_EDITOR, false );

            if( !editor )
            {
                editor = (FOOTPRINT_EDIT_FRAME*) Kiway().Player( FRAME_PCB_MODULE_EDITOR, true );

                editor->Show( true );
                editor->Zoom_Automatique( false );
            }
            else
            {
                /* not needed on linux, other platforms need this?
                if( editor->IsIconized() )
                     editor->Iconize( false );
                */

                editor->Raise();

                // Raising the window does not set the focus on Linux.  This should work on
                // any platform.
                if( wxWindow::FindFocus() != editor )
                    editor->SetFocus();
            }
        }
        break;

    case ID_OPEN_MODULE_VIEWER:
        {
            FOOTPRINT_VIEWER_FRAME* viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, false );

            if( !viewer )
            {
                viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, true );

                viewer->Show( true );
                viewer->Zoom_Automatique( false );
            }
            else
            {
                /* not needed on linux, other platforms need this?
                if( viewer->IsIconized() )
                     viewer->Iconize( false );
                */

                viewer->Raise();

                // Raising the window does not set the focus on Linux.  This should work on
                // any platform.
                if( wxWindow::FindFocus() != viewer )
                    viewer->SetFocus();
            }
        }
        break;

    case ID_PCB_GLOBAL_DELETE:
        InstallPcbGlobalDeleteFrame( wxDefaultPosition );
        break;

    case ID_POPUP_PLACE_BLOCK:
        GetScreen()->m_BlockLocate.SetCommand( BLOCK_MOVE );
        m_canvas->SetAutoPanRequest( false );
        HandleBlockPlace( &dc );
        break;

    case ID_POPUP_COPY_BLOCK:
        GetScreen()->m_BlockLocate.SetCommand( BLOCK_COPY );
        GetScreen()->m_BlockLocate.SetMessageBlock( this );
        m_canvas->SetAutoPanRequest( false );
        HandleBlockPlace( &dc );
        break;

    case ID_POPUP_ZOOM_BLOCK:
        GetScreen()->m_BlockLocate.SetCommand( BLOCK_ZOOM );
        GetScreen()->m_BlockLocate.SetMessageBlock( this );
        HandleBlockEnd( &dc );
        break;

    case ID_POPUP_DELETE_BLOCK:
        GetScreen()->m_BlockLocate.SetCommand( BLOCK_DELETE );
        GetScreen()->m_BlockLocate.SetMessageBlock( this );
        HandleBlockEnd( &dc );
        break;

    case ID_POPUP_ROTATE_BLOCK:
        GetScreen()->m_BlockLocate.SetCommand( BLOCK_ROTATE );
        GetScreen()->m_BlockLocate.SetMessageBlock( this );
        HandleBlockEnd( &dc );
        break;

    case ID_POPUP_FLIP_BLOCK:
        GetScreen()->m_BlockLocate.SetCommand( BLOCK_FLIP );
        GetScreen()->m_BlockLocate.SetMessageBlock( this );
        HandleBlockEnd( &dc );
        break;

    case ID_DRC_CONTROL:
        m_drc->ShowDialog();
        break;

    case ID_GET_NETLIST:
        InstallNetlistFrame( &dc );
        break;

    case ID_FIND_ITEMS:
        InstallFindFrame();
        break;

    case ID_POPUP_CLOSE_CURRENT_TOOL:
        SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString );
        break;

    case ID_POPUP_CANCEL_CURRENT_COMMAND:
        break;

    case ID_POPUP_PCB_END_LINE:
        m_canvas->MoveCursorToCrossHair();

        //  EndSegment(&dc);
        break;

    case ID_POPUP_PCB_EDIT_TRACK:
        if( GetCurItem() == NULL )
            break;
        Edit_Track_Width( &dc, (TRACK*) GetCurItem() );
        m_canvas->MoveCursorToCrossHair();
        OnModify();
        break;

    case ID_POPUP_PCB_EDIT_TRACKSEG:
        if( GetCurItem() == NULL )
            break;
        Edit_TrackSegm_Width( &dc, (TRACK*) GetCurItem() );
        m_canvas->MoveCursorToCrossHair();
        OnModify();
        break;

    case ID_POPUP_PCB_EDIT_ALL_VIAS_AND_TRACK_SIZE:
        if( GetCurItem() == NULL )
            break;
        {
        int type = GetCurItem()->Type();

        if( type == PCB_TRACE_T || type == PCB_VIA_T )
        {
            BOARD_CONNECTED_ITEM*item = (BOARD_CONNECTED_ITEM*) GetCurItem();
            DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS dlg( this, item->GetNetCode() );
            dlg.ShowModal();
        }

        }
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_BEGIN_TRACK:
        m_canvas->MoveCursorToCrossHair();
        OnHotkeyBeginRoute( &dc );
        break;

    case ID_POPUP_PCB_END_TRACK:
        m_canvas->MoveCursorToCrossHair();
        End_Route( (TRACK*) GetCurItem(), &dc );
        break;

    case ID_POPUP_PCB_PLACE_MOVED_TRACK_NODE:
        m_canvas->MoveCursorToCrossHair();

        if( GetCurItem()->IsDragging() )
        {
            PlaceDraggedOrMovedTrackSegment( (TRACK*) GetCurItem(), &dc );
        }

        break;

    case ID_POPUP_PCB_SWITCH_TRACK_POSTURE:
        /* change the position of initial segment when creating new tracks
         * switch from _/  to -\ .
         * If a track is in progress, it will be redrawn
        */
        if( m_canvas->IsMouseCaptured() )
            m_canvas->CallMouseCapture( &dc, wxDefaultPosition, false );

        g_Alternate_Track_Posture = !g_Alternate_Track_Posture;

        if( m_canvas->IsMouseCaptured() )
            m_canvas->CallMouseCapture( &dc, wxDefaultPosition, false );

        break;

    case ID_POPUP_PCB_PLACE_MICROVIA:
        if( !IsMicroViaAcceptable() )
            break;
        // fall through
    case ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA:
    case ID_POPUP_PCB_PLACE_THROUGH_VIA:
    case ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_THROUGH_VIA:
    case ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_BLIND_BURIED_VIA:
        m_canvas->MoveCursorToCrossHair();

        if( GetCurItem()->IsDragging() )
        {
            PlaceDraggedOrMovedTrackSegment( (TRACK*) GetCurItem(), &dc );
        }
        else
        {
            BOARD_DESIGN_SETTINGS &settings = GetDesignSettings();
            VIATYPE_T v_type = settings.m_CurrentViaType;
            switch( id )
            {
            case ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA:
            case ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_BLIND_BURIED_VIA:
                settings.m_CurrentViaType = VIA_BLIND_BURIED;
                break;

            case ID_POPUP_PCB_PLACE_MICROVIA:
                settings.m_CurrentViaType = VIA_MICROVIA;
                break;

            default:
                settings.m_CurrentViaType = VIA_THROUGH;
                break;
            }

            // place via and switch layer.
            if( id == ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_THROUGH_VIA ||
                id == ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_BLIND_BURIED_VIA )
            {
                m_canvas->SetIgnoreMouseEvents( true );
                wxPoint dlgPosition;
                wxGetMousePosition( &dlgPosition.x, &dlgPosition.y );
                LAYER_NUM layer = SelectLayer( getActiveLayer(), ALL_NO_CU_LAYERS,
                                               dlgPosition );
                m_canvas->SetIgnoreMouseEvents( false );
                m_canvas->MoveCursorToCrossHair();

                if( getActiveLayer() != layer )
                {
                    GetScreen()->m_Route_Layer_TOP    = getActiveLayer();
                    GetScreen()->m_Route_Layer_BOTTOM = layer;
                    Other_Layer_Route( (TRACK*) GetCurItem(), &dc );
                }
            }

            else
                Other_Layer_Route( (TRACK*) GetCurItem(), &dc );

            settings.m_CurrentViaType = v_type;

            if( DisplayOpt.ContrastModeDisplay )
                m_canvas->Refresh();
        }
        break;

    case ID_POPUP_PCB_DELETE_TRACKSEG:
        if( GetCurItem() == NULL )
            break;

        m_canvas->MoveCursorToCrossHair();
        SetCurItem( Delete_Segment( &dc, (TRACK*) GetCurItem() ) );
        OnModify();
        break;

    case ID_POPUP_PCB_DELETE_TRACK:
        if( GetCurItem() == NULL )
            break;
        m_canvas->MoveCursorToCrossHair();
        Delete_Track( &dc, (TRACK*) GetCurItem() );
        SetCurItem( NULL );
        OnModify();
        break;

    case ID_POPUP_PCB_DELETE_TRACKNET:
        m_canvas->MoveCursorToCrossHair();
        Delete_net( &dc, (TRACK*) GetCurItem() );
        SetCurItem( NULL );
        OnModify();
        break;

    case ID_POPUP_PCB_LOCK_ON_TRACKSEG:
        Attribut_Segment( (TRACK*) GetCurItem(), &dc, true );
        break;

    case ID_POPUP_PCB_LOCK_OFF_TRACKSEG:
        Attribut_Segment( (TRACK*) GetCurItem(), &dc, false );
        break;

    case ID_POPUP_PCB_LOCK_ON_TRACK:
        Attribut_Track( (TRACK*) GetCurItem(), &dc, true );
        break;

    case ID_POPUP_PCB_LOCK_OFF_TRACK:
        Attribut_Track( (TRACK*) GetCurItem(), &dc, false );
        break;

    case ID_POPUP_PCB_LOCK_ON_NET:
        Attribut_net( &dc, ( (TRACK*) GetCurItem() )->GetNetCode(), true );
        break;

    case ID_POPUP_PCB_LOCK_OFF_NET:
        Attribut_net( &dc, ( (TRACK*) GetCurItem() )->GetNetCode(), false );
        break;

    case ID_POPUP_PCB_SETFLAGS_TRACK_MNU:
        break;

    case ID_POPUP_PCB_DELETE_ZONE:
        m_canvas->MoveCursorToCrossHair();

        if( GetCurItem() == NULL )
            break;

        {
            SEGZONE* zsegm   = (SEGZONE*) GetCurItem();
            int      netcode = zsegm->GetNetCode();
            Delete_OldZone_Fill( zsegm );
            SetCurItem( NULL );
            TestNetConnection( NULL, netcode );
            OnModify();
            SetMsgPanel( GetBoard() );
        }
        break;

    case ID_POPUP_PCB_EDIT_ZONE_PARAMS:
        Edit_Zone_Params( &dc, (ZONE_CONTAINER*) GetCurItem() );
        SetCurItem( NULL ); // Outlines can have changed
        break;

    case ID_POPUP_PCB_ZONE_DUPLICATE:
    {
        ZONE_CONTAINER* zone = (ZONE_CONTAINER*) GetCurItem();
        duplicateZone( &dc, zone );
    }
    break;

    case ID_POPUP_PCB_ZONE_ADD_SIMILAR_ZONE:
        m_canvas->MoveCursorToCrossHair();
        m_canvas->SetAutoPanRequest( true );
        Add_Similar_Zone( &dc, (ZONE_CONTAINER*) GetCurItem() );
        break;

    case ID_POPUP_PCB_ZONE_ADD_CUTOUT_ZONE:
        m_canvas->MoveCursorToCrossHair();
        m_canvas->SetAutoPanRequest( true );
        Add_Zone_Cutout( &dc, (ZONE_CONTAINER*) GetCurItem() );
        break;

    case ID_POPUP_PCB_DELETE_ZONE_CONTAINER:
    case ID_POPUP_PCB_DELETE_ZONE_CUTOUT:
        m_canvas->MoveCursorToCrossHair();
        {
            int netcode = ( (ZONE_CONTAINER*) GetCurItem() )->GetNetCode();
            Delete_Zone_Contour( &dc, (ZONE_CONTAINER*) GetCurItem() );
            SetCurItem( NULL );
            TestNetConnection( NULL, netcode );
            SetMsgPanel( GetBoard() );
        }
        break;

    case ID_POPUP_PCB_DELETE_ZONE_CORNER:
        Remove_Zone_Corner( &dc, (ZONE_CONTAINER*) GetCurItem() );
        SetCurItem( NULL );
        break;

    case ID_POPUP_PCB_MOVE_ZONE_CORNER:
    {
        m_canvas->MoveCursorToCrossHair();
        ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem();
        m_canvas->SetAutoPanRequest( true );
        Start_Move_Zone_Corner( &dc, zone_cont, zone_cont->GetSelectedCorner(), false );
        break;
    }

    case ID_POPUP_PCB_DRAG_ZONE_OUTLINE_SEGMENT:
    {
        m_canvas->MoveCursorToCrossHair();
        ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem();
        m_canvas->SetAutoPanRequest( true );
        Start_Move_Zone_Drag_Outline_Edge( &dc, zone_cont, zone_cont->GetSelectedCorner() );
        break;
    }

    case ID_POPUP_PCB_MOVE_ZONE_OUTLINES:
    {
        m_canvas->MoveCursorToCrossHair();
        ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem();
        m_canvas->SetAutoPanRequest( true );
        Start_Move_Zone_Outlines( &dc, zone_cont );
        break;
    }

    case ID_POPUP_PCB_ADD_ZONE_CORNER:
    {
        m_canvas->MoveCursorToCrossHair();
        ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem();
        wxPoint         pos = GetCrossHairPosition();

        /* add corner between zone_cont->m_CornerSelection
         * and zone_cont->m_CornerSelection+1
         * and start move the new corner
         */
        zone_cont->Draw( m_canvas, &dc, GR_XOR );
        zone_cont->Outline()->InsertCorner( zone_cont->GetSelectedCorner(), pos.x, pos.y );
        zone_cont->SetSelectedCorner( zone_cont->GetSelectedCorner() + 1 );
        zone_cont->Draw( m_canvas, &dc, GR_XOR );
        m_canvas->SetAutoPanRequest( true );
        Start_Move_Zone_Corner( &dc, zone_cont, zone_cont->GetSelectedCorner(), true );
        break;
    }

    case ID_POPUP_PCB_PLACE_ZONE_OUTLINES:
    case ID_POPUP_PCB_PLACE_ZONE_CORNER:
    {
        m_canvas->MoveCursorToCrossHair();
        ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem();
        End_Move_Zone_Corner_Or_Outlines( &dc, zone_cont );
        m_canvas->SetAutoPanRequest( false );
        break;
    }

    case ID_POPUP_PCB_FILL_ALL_ZONES:
        m_canvas->MoveCursorToCrossHair();
        Fill_All_Zones( this );
        m_canvas->Refresh();
        SetMsgPanel( GetBoard() );
        break;

    case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_CURRENT_ZONE:
        if( ( GetCurItem() )->Type() == PCB_ZONE_AREA_T )
        {
            ZONE_CONTAINER* zone_container = (ZONE_CONTAINER*) GetCurItem();
            zone_container->UnFill();
            TestNetConnection( NULL, zone_container->GetNetCode() );
            OnModify();
            SetMsgPanel( GetBoard() );
            m_canvas->Refresh();
        }
        SetCurItem( NULL );
        break;

    case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES: // Remove all zones :
        GetBoard()->m_Zone.DeleteAll();                 // remove zone segments used to fill zones.

        for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
        {
            // Remove filled areas in zone
            ZONE_CONTAINER* zone_container = GetBoard()->GetArea( ii );
            zone_container->ClearFilledPolysList();
        }

        SetCurItem( NULL );        // CurItem might be deleted by this command, clear the pointer
        TestConnections();
        TestForActiveLinksInRatsnest( 0 );   // Recalculate the active ratsnest, i.e. the unconnected links
        OnModify();
        SetMsgPanel( GetBoard() );
        m_canvas->Refresh();
        break;

    case ID_POPUP_PCB_FILL_ZONE:
        m_canvas->MoveCursorToCrossHair();
        Fill_Zone( (ZONE_CONTAINER*) GetCurItem() );
        TestNetConnection( NULL, ( (ZONE_CONTAINER*) GetCurItem() )->GetNetCode() );
        SetMsgPanel( GetBoard() );
        m_canvas->Refresh();
        break;

    case ID_POPUP_PCB_MOVE_TEXTEPCB_REQUEST:
        StartMoveTextePcb( (TEXTE_PCB*) GetCurItem(), &dc );
        m_canvas->SetAutoPanRequest( true );
        break;

    case ID_POPUP_PCB_DRAG_MODULE_REQUEST:
    case ID_POPUP_PCB_MOVE_MODULE_REQUEST:
        if( GetCurItem() == NULL )
            break;

        // If the current Item is a pad, text module ...: Get its parent
        if( GetCurItem()->Type() != PCB_MODULE_T )
            SetCurItem( GetCurItem()->GetParent() );

        if( !GetCurItem() || GetCurItem()->Type() != PCB_MODULE_T )
            break;

        module = (MODULE*) GetCurItem();

        if( module->IsLocked() )
        {
            wxString msg;
            msg.Printf( _( "Footprint %s found, but it is locked" ),
                        module->GetReference().GetData() );
            DisplayInfoMessage( this, msg );
            break;
        }

        SendMessageToEESCHEMA( module );
        SetCrossHairPosition( module->GetPosition() );
        m_canvas->MoveCursorToCrossHair();
        StartMoveModule( module, &dc, id == ID_POPUP_PCB_DRAG_MODULE_REQUEST );
        break;

    case ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST:      // get module by name and move it
        SetCurItem( GetModuleByName() );
        module = (MODULE*) GetCurItem();

        if( module == NULL )
            break;

        if( module->IsLocked() )
        {
            wxString msg = wxString::Format(
                _( "Footprint %s found, but it is locked" ),
                module->GetReference().GetData() );
            DisplayInfoMessage( this, msg );
            break;
        }

        SendMessageToEESCHEMA( module );
        m_canvas->MoveCursorToCrossHair();
        StartMoveModule( module, &dc, false );
        break;

    case ID_POPUP_PCB_DELETE_MODULE:
        m_canvas->MoveCursorToCrossHair();

        // If the current Item is a pad, text module ...: Get its parent
        if( GetCurItem()->Type() != PCB_MODULE_T )
            SetCurItem( GetCurItem()->GetParent() );

        if( !GetCurItem() || GetCurItem()->Type() != PCB_MODULE_T )
            break;

        module = (MODULE*) GetCurItem();

        if( module->IsLocked() )
        {
            wxString msg;
            msg.Printf( _( "Footprint %s found, but it is locked" ),
                        module->GetReference().GetData() );
            DisplayInfoMessage( this, msg );
            break;
        }

        if( Delete_Module( (MODULE*) GetCurItem(), &dc, true ) )
        {
            SetCurItem( NULL );
        }

        break;

    case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE:
        m_canvas->MoveCursorToCrossHair();

        // If the current Item is a pad, text module ...: Get its parent
        if( GetCurItem()->Type() != PCB_MODULE_T )
            SetCurItem( GetCurItem()->GetParent() );

        if( !GetCurItem() || GetCurItem()->Type() != PCB_MODULE_T )
            break;

        module = (MODULE*) GetCurItem();

        if( module->IsLocked() )
        {
            wxString msg;
            msg.Printf( _( "Footprint %s found, but it is locked" ),
                        module->GetReference().GetData() );
            DisplayInfoMessage( this, msg );
            break;
        }

        // This is a simple rotation, no other editing in progress
        if( !GetCurItem()->IsMoving() )
            SaveCopyInUndoList( GetCurItem(), UR_CHANGED, ((MODULE*)GetCurItem())->GetPosition() );

        Rotate_Module( &dc, (MODULE*) GetCurItem(), m_rotationAngle, true );
        break;

    case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE:
        m_canvas->MoveCursorToCrossHair();

        // If the current Item is a pad, text module ...: Get its parent
        if( GetCurItem()->Type() != PCB_MODULE_T )
            SetCurItem( GetCurItem()->GetParent() );

        if( !GetCurItem() || GetCurItem()->Type() != PCB_MODULE_T )
            break;

        module = (MODULE*) GetCurItem();

        if( module->IsLocked() )
        {
            wxString msg;
            msg.Printf( _( "Footprint %s found, but it is locked" ),
                        module->GetReference().GetData() );
            DisplayInfoMessage( this, msg );
            break;
        }

        // This is a simple rotation, no other editing in progress
        if( !GetCurItem()->IsMoving() )
            SaveCopyInUndoList( GetCurItem(), UR_CHANGED, ((MODULE*)GetCurItem())->GetPosition() );

        Rotate_Module( &dc, (MODULE*) GetCurItem(), -m_rotationAngle, true );
        break;

    case ID_POPUP_PCB_CHANGE_SIDE_MODULE:
        m_canvas->MoveCursorToCrossHair();

        // If the current Item is a pad, text module ...: Get its parent
        if( GetCurItem()->Type() != PCB_MODULE_T )
            SetCurItem( GetCurItem()->GetParent() );

        if( !GetCurItem() || GetCurItem()->Type() != PCB_MODULE_T )
            break;

        module = (MODULE*) GetCurItem();

        if( module->IsLocked() )
        {
            wxString msg;
            msg.Printf( _( "Footprint %s found, but it is locked" ),
                        module->GetReference().GetData() );
            DisplayInfoMessage( this, msg );
            break;
        }

        // This is a simple flip, no other editing in progress
        if( !GetCurItem()->IsMoving() )
            SaveCopyInUndoList( GetCurItem(), UR_FLIPPED, ((MODULE*)GetCurItem())->GetPosition() );

        Change_Side_Module( (MODULE*) GetCurItem(), &dc );
        break;

    case ID_POPUP_PCB_EDIT_MODULE_PRMS:
        // If the current Item is a pad, text module ...: Get its parent
        if( GetCurItem()->Type() != PCB_MODULE_T )
            SetCurItem( GetCurItem()->GetParent() );

        if( !GetCurItem() || GetCurItem()->Type() != PCB_MODULE_T )
            break;

        InstallModuleOptionsFrame( (MODULE*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_EDIT_MODULE_WITH_MODEDIT:
        // If the current Item is a pad, text module ...: Get its parent
        if( GetCurItem()->Type() != PCB_MODULE_T )
            SetCurItem( GetCurItem()->GetParent() );

        if( !GetCurItem() || GetCurItem()->Type() != PCB_MODULE_T )
            break;

        if( GetCurItem()->GetTimeStamp() == 0 )    // Module Editor needs a non null timestamp
        {
            GetCurItem()->SetTimeStamp( GetNewTimeStamp() );
            OnModify();
        }

        {
            FOOTPRINT_EDIT_FRAME* editor = (FOOTPRINT_EDIT_FRAME*) Kiway().Player( FRAME_PCB_MODULE_EDITOR, true );

            editor->Load_Module_From_BOARD( (MODULE*)GetCurItem() );
            SetCurItem( NULL );     // the current module could be deleted by

            editor->Show( true );

            editor->Raise();        // Iconize( false );
        }
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_DRAG_PAD_REQUEST:
        module = (MODULE*) GetCurItem()->GetParent();

        if( !module || module->Type() != PCB_MODULE_T )
            break;

        if( module->IsLocked() )
        {
            wxString msg;
            msg.Printf( _( "The parent (%s) of the pad is locked" ),
                        module->GetReference().GetData() );
            DisplayInfoMessage( this, msg );
            break;
        }

        m_canvas->MoveCursorToCrossHair();
        StartMovePad( (D_PAD*) GetCurItem(), &dc, true );
        break;

    case ID_POPUP_PCB_MOVE_PAD_REQUEST:
        module = (MODULE*) GetCurItem()->GetParent();

        if( !module || module->Type() != PCB_MODULE_T )
            break;

        if( module->IsLocked() )
        {
            wxString msg;
            msg.Printf( _( "The parent (%s) of the pad is locked" ),
                        module->GetReference().GetData() );
            DisplayInfoMessage( this, msg );
            break;
        }

        m_canvas->MoveCursorToCrossHair();
        StartMovePad( (D_PAD*) GetCurItem(), &dc, false );
        break;

    case ID_POPUP_PCB_EDIT_PAD:
        InstallPadOptionsFrame( (D_PAD*) GetCurItem() );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_IMPORT_PAD_SETTINGS:
        m_canvas->MoveCursorToCrossHair();
        SaveCopyInUndoList( GetCurItem()->GetParent(), UR_CHANGED );
        Import_Pad_Settings( (D_PAD*) GetCurItem(), true );
        break;

    case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS:
        m_canvas->MoveCursorToCrossHair();
        DlgGlobalChange_PadSettings( (D_PAD*) GetCurItem(), true );
        break;

    case ID_POPUP_PCB_EXPORT_PAD_SETTINGS:
        m_canvas->MoveCursorToCrossHair();
        Export_Pad_Settings( (D_PAD*) GetCurItem() );
        break;

    case ID_POPUP_PCB_DELETE_PAD:
        SaveCopyInUndoList( GetCurItem()->GetParent(), UR_CHANGED );
        DeletePad( (D_PAD*) GetCurItem() );
        SetCurItem( NULL );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_EDIT_TEXTMODULE:
        InstallTextModOptionsFrame( (TEXTE_MODULE*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_RESET_TEXT_SIZE:
        ResetTextSize( GetCurItem(), &dc );
        break;

    case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST:
        m_canvas->MoveCursorToCrossHair();
        StartMoveTexteModule( (TEXTE_MODULE*) GetCurItem(), &dc );
        break;

    case ID_POPUP_PCB_ROTATE_TEXTMODULE:
        RotateTextModule( (TEXTE_MODULE*) GetCurItem(),
                         &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_DELETE_TEXTMODULE:
        DeleteTextModule( (TEXTE_MODULE*) GetCurItem() );
        SetCurItem( NULL );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_SELECT_LAYER:
        itmp = SelectLayer( getActiveLayer() );

        if( itmp >= 0 )
        {
            // if user changed colors and we are in high contrast mode, then redraw
            // because the PAD_SMD pads may change color.
            if( DisplayOpt.ContrastModeDisplay && getActiveLayer() != itmp )
            {
                m_canvas->Refresh();
            }
            setActiveLayer( itmp );
        }

        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_AUX_TOOLBAR_PCB_SELECT_LAYER_PAIR:
        SelectCopperLayerPair();
        break;

    case ID_POPUP_PCB_SELECT_NO_CU_LAYER:
        itmp = SelectLayer( getActiveLayer(), ALL_CU_LAYERS );

        if( itmp >= 0 )
            setActiveLayer( itmp );

        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_SELECT_CU_LAYER:
        itmp = SelectLayer( getActiveLayer(), ALL_NO_CU_LAYERS );

        if( itmp >= 0 )
            setActiveLayer( itmp );

        break;

    case ID_POPUP_PCB_SELECT_LAYER_PAIR:
        SelectCopperLayerPair();
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_TOOLBARH_PCB_SELECT_LAYER:
        setActiveLayer( m_SelLayerBox->GetLayerSelection() );

        if( DisplayOpt.ContrastModeDisplay )
            m_canvas->Refresh( true );

        break;

    case ID_POPUP_PCB_EDIT_TEXTEPCB:
        InstallTextPCBOptionsFrame( (TEXTE_PCB*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_ROTATE_TEXTEPCB:
        Rotate_Texte_Pcb( (TEXTE_PCB*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_COPY_TEXTEPCB:
        CreateTextePcb( &dc, (TEXTE_PCB*) GetCurItem() );
        m_canvas->MoveCursorToCrossHair();
        m_canvas->SetAutoPanRequest( true );
        break;

    case ID_POPUP_PCB_FLIP_TEXTEPCB:
        FlipTextePcb( (TEXTE_PCB*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_DELETE_TEXTEPCB:
        Delete_Texte_Pcb( (TEXTE_PCB*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_MOVE_MIRE_REQUEST:
        BeginMoveTarget( (PCB_TARGET*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_EDIT_MIRE:
        ShowTargetOptionsDialog( (PCB_TARGET*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_DELETE_MIRE:
        m_canvas->MoveCursorToCrossHair();
        DeleteTarget( (PCB_TARGET*) GetCurItem(), &dc );
        SetCurItem( NULL );
        break;

    case ID_POPUP_PCB_DELETE_DIMENSION:
        m_canvas->MoveCursorToCrossHair();
        DeleteDimension( (DIMENSION*) GetCurItem(), &dc );
        SetCurItem( NULL );
        break;

    case ID_POPUP_PCB_EDIT_DIMENSION:
        ShowDimensionPropertyDialog( (DIMENSION*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_MOVE_TEXT_DIMENSION_REQUEST:
        BeginMoveDimensionText( (DIMENSION*) GetCurItem(), &dc );
        break;

    case ID_POPUP_PCB_DELETE_DRAWING:
        Delete_Segment_Edge( (DRAWSEGMENT*) GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_DELETE_MARKER:
        RemoveStruct( GetCurItem(), &dc );
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_GETINFO_MARKER:
        if( GetCurItem() && GetCurItem()->Type() == PCB_MARKER_T )
            ( (MARKER_PCB*) GetCurItem() )->DisplayMarkerInfo( this );

        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_DELETE_DRAWING_LAYER:
        if( GetCurItem()->GetFlags() != 0 )
            break;

        Delete_Drawings_All_Layer( GetCurItem()->GetLayer() );
        SetCurItem( NULL );
        m_canvas->MoveCursorToCrossHair();
        m_canvas->Refresh();
        break;

    case ID_POPUP_PCB_EDIT_DRAWING:
#ifndef USE_WX_OVERLAY
        InstallGraphicItemPropertiesDialog( (DRAWSEGMENT*) GetCurItem(), &dc );
#else
        // #1277772 - Draw into dialog converted in refresh request
        InstallGraphicItemPropertiesDialog( (DRAWSEGMENT*) GetCurItem(), NULL );
        m_canvas->Refresh();
#endif
        m_canvas->MoveCursorToCrossHair();
        break;

    case ID_POPUP_PCB_MOVE_DRAWING_REQUEST:
        m_canvas->MoveCursorToCrossHair();
        Start_Move_DrawItem( (DRAWSEGMENT*) GetCurItem(), &dc );
        break;

    case ID_POPUP_PCB_STOP_CURRENT_DRAWING:
        m_canvas->MoveCursorToCrossHair();

        if( GetCurItem() && (GetCurItem()->IsNew()) )
        {
            End_Edge( (DRAWSEGMENT*) GetCurItem(), &dc );
            SetCurItem( NULL );
        }

        break;

    case ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE:
        m_canvas->MoveCursorToCrossHair();

        if( GetCurItem() && (GetCurItem()->IsNew()) )
        {
            if( End_Zone( &dc ) )
                SetCurItem( NULL );
        }

        m_canvas->SetAutoPanRequest( false );
        break;

    case ID_POPUP_PCB_DELETE_ZONE_LAST_CREATED_CORNER:
        m_canvas->MoveCursorToCrossHair();

        if( GetCurItem() && (GetCurItem()->IsNew()) )
        {
            if( Delete_LastCreatedCorner( &dc ) == 0 )  // No more segment in outline,
                SetCurItem( NULL );
        }

        break;


    case ID_POPUP_PCB_MOVE_TRACK_SEGMENT:
        m_canvas->MoveCursorToCrossHair();
        StartMoveOneNodeOrSegment( (TRACK*) GetScreen()->GetCurItem(), &dc, id );
        break;

    case ID_POPUP_PCB_DRAG_TRACK_SEGMENT:
    case ID_POPUP_PCB_MOVE_TRACK_NODE:
        m_canvas->MoveCursorToCrossHair();
        StartMoveOneNodeOrSegment( (TRACK*) GetScreen()->GetCurItem(), &dc, id );
        break;

    case ID_POPUP_PCB_DRAG_TRACK_SEGMENT_KEEP_SLOPE:
        m_canvas->MoveCursorToCrossHair();
        Start_DragTrackSegmentAndKeepSlope( (TRACK*) GetScreen()->GetCurItem(), &dc );
        break;

    case ID_POPUP_PCB_BREAK_TRACK:
        m_canvas->MoveCursorToCrossHair();
        {
            TRACK*  track = (TRACK*) GetScreen()->GetCurItem();
            wxPoint pos   = GetCrossHairPosition();

            track->Draw( m_canvas, &dc, GR_XOR );
            PICKED_ITEMS_LIST itemsListPicker;

            TRACK*  newtrack = GetBoard()->CreateLockPoint( pos, track, &itemsListPicker );

            SaveCopyInUndoList( itemsListPicker, UR_UNSPECIFIED );
            track->Draw( m_canvas, &dc, GR_XOR );
            newtrack->Draw( m_canvas, &dc, GR_XOR );

            // compute the new ratsnest, because connectivity could change
            TestNetConnection( &dc, track->GetNetCode() );
        }
        break;

    case ID_MENU_PCB_CLEAN:
        Clean_Pcb();
        break;

    case ID_MENU_PCB_SWAP_LAYERS:
        Swap_Layers( event );
        break;

    case ID_PCB_USER_GRID_SETUP:
        InvokeDialogGrid();
        break;

    case ID_POPUP_PCB_DISPLAY_FOOTPRINT_DOC:
        {
            wxConfigBase* cfg = Pgm().CommonSettings();
            cfg->Read( wxT( "module_doc_file" ), g_DocModulesFileName );
            GetAssociatedDocument( this, g_DocModulesFileName, &Kiface().KifaceSearch() );
        }
        break;

    case ID_MENU_ARCHIVE_NEW_MODULES:
        ArchiveModulesOnBoard( true );
        break;

    case ID_MENU_ARCHIVE_ALL_MODULES:
        ArchiveModulesOnBoard( false );
        break;

    case ID_GEN_IMPORT_DXF_FILE:
        InvokeDXFDialogImport( this );
        m_canvas->Refresh();
        break;

    default:
        wxString msg;
        msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() unknown event id %d" ),
                    id );
        DisplayError( this, msg );
        break;
    }

    m_canvas->CrossHairOn( &dc );
    m_canvas->SetIgnoreMouseEvents( false );
}