LIB_ITEM* LIB_EDIT_FRAME::locateItem( const wxPoint& aPosition, const KICAD_T aFilterList[] )
{
    if( m_component == NULL )
        return NULL;

    LIB_ITEM* item = NULL;

    m_collectedItems.Collect( m_component->GetDrawItemList(), aFilterList, aPosition,
                              m_unit, m_convert );

    if( m_collectedItems.GetCount() == 0 )
    {
        ClearMsgPanel();
    }
    else if( m_collectedItems.GetCount() == 1 )
    {
        item = m_collectedItems[0];
    }
    else
    {
        if( item == NULL )
        {
            wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
                          wxT( "Select item clarification context menu size limit exceeded." ) );

            wxMenu selectMenu;
            wxMenuItem* title = new wxMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ) );

            selectMenu.Append( title );
            selectMenu.AppendSeparator();

            for( int i = 0;  i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS;  i++ )
            {
                wxString text = m_collectedItems[i]->GetSelectMenuText();
                BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
                AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
            }

            // Set to NULL in case user aborts the clarification context menu.
            m_drawItem = NULL;
            m_canvas->SetAbortRequest( true );   // Changed to false if an item is selected
            PopupMenu( &selectMenu );
            m_canvas->MoveCursorToCrossHair();
            item = m_drawItem;
        }
    }

    if( item )
    {
        MSG_PANEL_ITEMS items;
        item->GetMsgPanelInfo( items );
        SetMsgPanel( items );
    }
    else
    {
        ClearMsgPanel();
    }

    return item;
}
Exemple #2
0
void LIB_VIEW_FRAME::updatePreviewSymbol()
{
    LIB_ALIAS* alias = getSelectedAlias();
    KIGFX::SCH_VIEW* view = GetCanvas()->GetView();

    if( m_previewItem )
    {
        view->Remove( m_previewItem );
        m_previewItem = nullptr;
    }

    ClearMsgPanel();

    if( alias )
    {
        GetRenderSettings()->m_ShowUnit = m_unit;
        GetRenderSettings()->m_ShowConvert = m_convert;

        view->Add( alias );
        m_previewItem = alias;

        AppendMsgPanel( _( "Name" ), alias->GetName(), BLUE, 6 );
        AppendMsgPanel( _( "Description" ), alias->GetDescription(), CYAN, 6 );
        AppendMsgPanel( _( "Key words" ), alias->GetKeyWords(), DARKDARKGRAY );
    }

    GetCanvas()->ForceRefresh();
}
Exemple #3
0
/* File commands. */
void GERBVIEW_FRAME::Files_io( wxCommandEvent& event )
{
    int        id = event.GetId();

    switch( id )
    {
    case wxID_FILE:
        Erase_Current_Layer( false );
        LoadGerberFiles( wxEmptyString );
        break;

    case ID_GERBVIEW_ERASE_ALL:
        Clear_Pcb( true );
        Zoom_Automatique( false );
        m_canvas->Refresh();
        ClearMsgPanel();
        break;

    case ID_GERBVIEW_LOAD_DRILL_FILE:
        LoadExcellonFiles( wxEmptyString );
        m_canvas->Refresh();
        break;

    case ID_GERBVIEW_LOAD_DCODE_FILE:
        LoadDCodeFile( wxEmptyString );
        m_canvas->Refresh();
        break;

    default:
        wxFAIL_MSG( wxT( "File_io: unexpected command id" ) );
        break;
    }
}
int PCB_EDIT_FRAME::Fill_Zone( ZONE_CONTAINER* aZone )
{
    aZone->ClearFilledPolysList();
    aZone->UnFill();

    // Cannot fill keepout zones:
    if( aZone->GetIsKeepout() )
        return 1;

    wxString msg;

    ClearMsgPanel();

    // Shows the net
    ZONE_SETTINGS zoneInfo = GetZoneSettings();
    zoneInfo.m_NetcodeSelection = aZone->GetNetCode();
    SetZoneSettings( zoneInfo );

    msg = aZone->GetNetname();

    if( msg.IsEmpty() )
        msg = wxT( "No net" );

    AppendMsgPanel( _( "NetName" ), msg, RED );

    wxBusyCursor dummy;     // Shows an hourglass cursor (removed by its destructor)

    aZone->BuildFilledSolidAreasPolygons( GetBoard() );
    GetGalCanvas()->GetView()->Update( aZone, KIGFX::ALL );
    GetBoard()->GetRatsnest()->Update( aZone );

    OnModify();

    return 0;
}
void GERBVIEW_FRAME::UpdateTitleAndInfo()
{
    GERBER_FILE_IMAGE* gerber = GetGbrImage( getActiveLayer() );

    // Display the gerber filename
    if( gerber == NULL )
    {
        SetTitle( "GerbView" );

        SetStatusText( wxEmptyString, 0 );

        wxString info;
        info.Printf( _( "Drawing layer %d not in use" ), getActiveLayer() + 1 );
        m_TextInfo->SetValue( info );

        if( EnsureTextCtrlWidth( m_TextInfo, &info ) )  // Resized
           m_auimgr.Update();

        ClearMsgPanel();
        return;
    }
    else
    {
        wxString title;
        title.Printf( L"GerbView \u2014 %s%s",
                gerber->m_FileName,
                gerber->m_IsX2_file
                    ? " " + _( "(with X2 attributes)" )
                    : wxString( wxEmptyString ) );
        SetTitle( title );

        gerber->DisplayImageInfo( this );

        // Display Image Name and Layer Name (from the current gerber data):
        wxString status;
        status.Printf( _( "Image name: '%s'  Layer name: '%s'" ),
                GetChars( gerber->m_ImageName ),
                GetChars( gerber->GetLayerParams().m_LayerName ) );
        SetStatusText( status, 0 );

        // Display data format like fmt in X3.4Y3.4 no LZ or fmt mm X2.3 Y3.5 no TZ in main toolbar
        wxString info;
        info.Printf( wxT( "fmt: %s X%d.%d Y%d.%d no %cZ" ),
                gerber->m_GerbMetric ? wxT( "mm" ) : wxT( "in" ),
                gerber->m_FmtLen.x - gerber->m_FmtScale.x, gerber->m_FmtScale.x,
                gerber->m_FmtLen.y - gerber->m_FmtScale.y, gerber->m_FmtScale.y,
                gerber->m_NoTrailingZeros ? 'T' : 'L' );

        if( gerber->m_IsX2_file )
            info << wxT(" ") << _( "X2 attr" );

        m_TextInfo->SetValue( info );

        if( EnsureTextCtrlWidth( m_TextInfo, &info ) )  // Resized
            m_auimgr.Update();
    }
}
Exemple #6
0
/**
 * Function RedrawActiveWindow
 * Display the current selected component.
 * If the component is an alias, the ROOT component is displayed
*/
void LIB_VIEW_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
{
    LIB_COMPONENT* component;
    LIB_ALIAS*     entry;
    CMP_LIBRARY*   lib;
    wxString       msg;
    wxString       tmp;

    lib = CMP_LIBRARY::FindLibrary( m_libraryName );

    if( lib == NULL )
        return;

    entry = lib->FindEntry( m_entryName );

    if( entry == NULL )
        return;

    component = entry->GetComponent();

    m_canvas->DrawBackGround( DC );

    if( !entry->IsRoot() )
    {
        if( component == NULL )     // Should not occur
            return;

        // Temporarily change the name field text to reflect the alias name.
        msg = entry->GetName();
        tmp = component->GetName();
        component->SetName( msg );

        if( m_unit < 1 )
            m_unit = 1;

        if( m_convert < 1 )
            m_convert = 1;
    }
    else
    {
        msg = _( "None" );
    }

    component->Draw( m_canvas, DC, wxPoint( 0, 0 ), m_unit, m_convert, GR_DEFAULT_DRAWMODE );

    /* Redraw the cursor */
    m_canvas->DrawCrossHair( DC );

    if( !tmp.IsEmpty() )
        component->SetName( tmp );

    ClearMsgPanel();
    AppendMsgPanel( _( "Part" ), component->GetName(), BLUE, 6 );
    AppendMsgPanel( _( "Alias" ), msg, RED, 6 );
    AppendMsgPanel( _( "Description" ), entry->GetDescription(), CYAN, 6 );
    AppendMsgPanel( _( "Key words" ), entry->GetKeyWords(), DARKDARKGRAY );
}
void EDA_DRAW_FRAME::SetMsgPanel( const MSG_PANEL_ITEMS& aList )
{
    if( m_messagePanel == NULL )
        return;

    ClearMsgPanel();

    for( MSG_PANEL_ITEM item : aList )
        m_messagePanel->AppendMessage( item );
}
void EDA_DRAW_FRAME::SetMsgPanel( const MSG_PANEL_ITEMS& aList )
{
    if( m_messagePanel == NULL )
        return;

    ClearMsgPanel();

    for( unsigned i = 0;  i < aList.size();  i++ )
        m_messagePanel->AppendMessage( aList[i] );
}
void GERBVIEW_FRAME::UpdateTitleAndInfo()
{
    GERBER_IMAGE*   gerber = g_GERBER_List.GetGbrImage(  getActiveLayer() );
    wxString        text;

    // Display the gerber filename
    if( gerber == NULL )
    {
        text.Printf( wxT( "GerbView %s" ), GetChars( GetBuildVersion() ) );
        SetTitle( text );
        SetStatusText( wxEmptyString, 0 );
        text.Printf( _( "Drawing layer %d not in use" ), getActiveLayer() + 1 );
        m_TextInfo->SetValue( text );
        ClearMsgPanel();
        return;
    }

    text = _( "File:" );
    text << wxT( " " ) << gerber->m_FileName;

    if( gerber->m_IsX2_file )
        text << wxT( " " ) << _( "(with X2 Attributes)" );

    SetTitle( text );

    gerber->DisplayImageInfo();

    // Display Image Name and Layer Name (from the current gerber data):
    text.Printf( _( "Image name: '%s'  Layer name: '%s'" ),
                 GetChars( gerber->m_ImageName ),
                 GetChars( gerber->GetLayerParams().m_LayerName ) );
    SetStatusText( text, 0 );

    // Display data format like fmt in X3.4Y3.4 no LZ or fmt mm X2.3 Y3.5 no TZ in main toolbar
    text.Printf( wxT( "fmt: %s X%d.%d Y%d.%d no %cZ" ),
                 gerber->m_GerbMetric ? wxT( "mm" ) : wxT( "in" ),
                 gerber->m_FmtLen.x - gerber->m_FmtScale.x, gerber->m_FmtScale.x,
                 gerber->m_FmtLen.y - gerber->m_FmtScale.y, gerber->m_FmtScale.y,
                 gerber->m_NoTrailingZeros ? 'T' : 'L' );

    if( gerber->m_IsX2_file )
        text << wxT(" ") << _( "X2 attr" );

    m_TextInfo->SetValue( text );

    if( EnsureTextCtrlWidth( m_TextInfo, &text ) )  // Resized
       m_auimgr.Update();
}
Exemple #10
0
void LIB_VIEW_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
{
    LIB_ALIAS* entry = Prj().SchLibs()->FindLibraryAlias( m_entryName, m_libraryName );

    if( !entry )
        return;

    LIB_PART* part = entry->GetPart();

    if( !part )
        return;

    wxString    msg;
    wxString    tmp;

    m_canvas->DrawBackGround( DC );

    if( !entry->IsRoot() )
    {
        // Temporarily change the name field text to reflect the alias name.
        msg = entry->GetName();
        tmp = part->GetName();

        part->SetName( msg );

        if( m_unit < 1 )
            m_unit = 1;

        if( m_convert < 1 )
            m_convert = 1;
    }
    else
        msg = _( "None" );

    part->Draw( m_canvas, DC, wxPoint( 0, 0 ), m_unit, m_convert, GR_DEFAULT_DRAWMODE );

    // Redraw the cursor
    m_canvas->DrawCrossHair( DC );

    if( !tmp.IsEmpty() )
        part->SetName( tmp );

    ClearMsgPanel();
    AppendMsgPanel( _( "Part" ), part->GetName(), BLUE, 6 );
    AppendMsgPanel( _( "Alias" ), msg, RED, 6 );
    AppendMsgPanel( _( "Description" ), entry->GetDescription(), CYAN, 6 );
    AppendMsgPanel( _( "Key words" ), entry->GetKeyWords(), DARKDARKGRAY );
}
void SCH_EDIT_FRAME::DisplayCurrentSheet()
{
    SetRepeatItem( NULL );
    ClearMsgPanel();

    SCH_SCREEN* screen = m_CurrentSheet->LastScreen();

    // Switch to current sheet,
    // and update the grid size, because it can be modified in latest screen
    SetScreen( screen );
    GetScreen()->SetGrid( m_LastGridSizeId + ID_POPUP_GRID_LEVEL_1000 );

    // update the References
    m_CurrentSheet->UpdateAllScreenReferences();
    SetSheetNumberAndCount();
    m_canvas->SetCanStartBlock( -1 );

    if( screen->m_FirstRedraw )
    {
        Zoom_Automatique( false );
        screen->m_FirstRedraw = false;
        SetCrossHairPosition( GetScrollCenterPosition() );
        m_canvas->MoveCursorToCrossHair();

        // Ensure the schematic is fully segmented on first display
        BreakSegmentsOnJunctions();
        SchematicCleanUp( true );
        screen->ClearUndoORRedoList( screen->m_UndoList, 1 );

        screen->TestDanglingEnds();
    }
    else
    {
        RedrawScreen( GetScrollCenterPosition(), true );
    }

    // Some items (wires, labels) can be highlighted. So prepare the highlight flag:
    SetCurrentSheetHighlightFlags();

    // Now refresh m_canvas. Should be not necessary, but because screen has changed
    // the previous refresh has set all new draw parameters (scroll position ..)
    // but most of time there were some inconsitencies about cursor parameters
    // ( previous position of cursor ...) and artefacts can happen
    // mainly when sheet size has changed
    // This second refresh clears artefacts because at this point,
    // all parameters are now updated
    m_canvas->Refresh();
}
void LIB_EDIT_FRAME::DisplayCmpDoc()
{
    LIB_ALIAS*      alias;
    PART_LIB*    lib = GetCurLib();
    LIB_PART*       part = GetCurPart();

    ClearMsgPanel();

    if( !lib || !part )
        return;

    wxString msg = part->GetName();

    AppendMsgPanel( _( "Name" ), msg, BLUE, 8 );

    if( m_aliasName == part->GetName() )
        msg = _( "None" );
    else
        msg = m_aliasName;

    alias = part->GetAlias( m_aliasName );

    wxCHECK_RET( alias != NULL, "Alias not found in component." );

    AppendMsgPanel( _( "Alias" ), msg, RED, 8 );

    static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
    msg = UnitLetter[m_unit];

    AppendMsgPanel( _( "Unit" ), msg, BROWN, 8 );

    if( m_convert > 1 )
        msg = _( "Convert" );
    else
        msg = _( "Normal" );

    AppendMsgPanel( _( "Body" ), msg, GREEN, 8 );

    if( part->IsPower() )
        msg = _( "Power Symbol" );
    else
        msg = _( "Part" );

    AppendMsgPanel( _( "Type" ), msg, MAGENTA, 8 );
    AppendMsgPanel( _( "Description" ), alias->GetDescription(), CYAN, 8 );
    AppendMsgPanel( _( "Key words" ), alias->GetKeyWords(), DARKDARKGRAY );
    AppendMsgPanel( _( "Datasheet" ), alias->GetDocFileName(), DARKDARKGRAY );
}
void FOOTPRINT_VIEWER_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
{
    if( !GetBoard() )
        return;

    m_canvas->DrawBackGround( DC );
    GetBoard()->Draw( m_canvas, DC, GR_COPY );

    MODULE* module = GetBoard()->m_Modules;

    m_canvas->DrawCrossHair( DC );

    ClearMsgPanel();

    if( module )
        SetMsgPanel( module );
}
void FOOTPRINT_EDIT_FRAME::UpdateMsgPanel()
{
    // If a item is currently selected, displays the item info.
    // If nothing selected, display the current footprint info
    BOARD_ITEM* item = GetScreen()->GetCurItem();

    if( !item )
        item = GetBoard()->m_Modules;

    MSG_PANEL_ITEMS items;

    if( item )
    {
        item->GetMsgPanelInfo( m_UserUnits, items );
        SetMsgPanel( items );
    }
    else
        ClearMsgPanel();
}
Exemple #15
0
/**
 * Function Compile_Ratsnest
 *  Create the entire board ratsnest.
 *  Must be called after a board change (changes for
 *  pads, footprints or a read netlist ).
 * @param aDC = the current device context (can be NULL)
 * @param aDisplayStatus : if true, display the computation results
 */
void PCB_BASE_FRAME::Compile_Ratsnest( wxDC* aDC, bool aDisplayStatus )
{
    wxString msg;

    GetBoard()->m_Status_Pcb = 0;   // we want a full ratsnest computation, from the scratch
    ClearMsgPanel();

    // Rebuild the full pads and net info list
    RecalculateAllTracksNetcode();

    if( aDisplayStatus )
    {
        msg.Printf( wxT( " %d" ), m_Pcb->GetPadCount() );
        AppendMsgPanel( wxT( "Pads" ), msg, RED );
        msg.Printf( wxT( " %d" ), m_Pcb->GetNetCount() );
        AppendMsgPanel( wxT( "Nets" ), msg, CYAN );
    }

    /* Compute the full ratsnest
     *  which can be see like all the possible links or logical connections.
     *  some of them are active (no track connected) and others are inactive
     * (when tracks connect pads)
     *  This full ratsnest is not modified by track editing.
     *  It changes only when a netlist is read, or footprints are modified
     */
    Build_Board_Ratsnest();

    // Compute the pad connections due to the existing tracks (physical connections)
    TestConnections();

    /* Compute the active ratsnest, i.e. the unconnected links
     */
    TestForActiveLinksInRatsnest( 0 );

    // Redraw the active ratsnest ( if enabled )
    if( GetBoard()->IsElementVisible(RATSNEST_VISIBLE) && aDC )
        DrawGeneralRatsnest( aDC, 0 );

    if( aDisplayStatus )
        SetMsgPanel( m_Pcb );
}
SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
                                      int aHotKeyCommandId )
{
    SCH_ITEM* item = NULL;

    m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );

    if( m_collectedItems.GetCount() == 0 )
    {
        ClearMsgPanel();
    }
    else if( m_collectedItems.GetCount() == 1 )
    {
        item = m_collectedItems[0];
    }
    else
    {
        // There are certain parent/child and enclosure combinations that can be handled
        // automatically.  Since schematics are meant to be human-readable we don't have
        // all the various overlap and coverage issues that we do in Pcbnew.
        if( m_collectedItems.GetCount() == 2 )
        {
            SCH_ITEM* a = m_collectedItems[ 0 ];
            SCH_ITEM* b = m_collectedItems[ 1 ];

            if( a->GetParent() == b )
                item = a;
            else if( a == b->GetParent() )
                item = b;
            else if( a->Type() == SCH_SHEET_T && b->Type() != SCH_SHEET_T )
                item = b;
            else if( b->Type() == SCH_SHEET_T && a->Type() != SCH_SHEET_T )
                item = a;
        }

        // There are certain combinations of items that do not need clarification such as
        // a corner were two lines meet or all the items form a junction.
        if( aHotKeyCommandId )
        {
            switch( aHotKeyCommandId )
            {
            case HK_DRAG:
                if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false )
                    || m_collectedItems.IsDraggableJunction() )
                {
                    item = m_collectedItems[0];
                }
                break;

            case HK_MOVE_COMPONENT_OR_ITEM:
                if( m_collectedItems.GetCount() == 2 &&
                        dynamic_cast< SCH_SHEET_PIN * >( m_collectedItems[0] ) &&
                        dynamic_cast< SCH_SHEET * >( m_collectedItems[1] ) )
                {
                    item = m_collectedItems[0];
                }
                break;

            default:
                ;
            }
        }

        if( item == NULL )
        {
            wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
                          wxT( "Select item clarification context menu size limit exceeded." ) );

            wxMenu selectMenu;

            AddMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ), KiBitmap( info_xpm ) );
            selectMenu.AppendSeparator();

            for( int i = 0;  i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS;  i++ )
            {
                wxString text = m_collectedItems[i]->GetSelectMenuText( m_UserUnits );
                BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
                AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
            }

            // Set to NULL in case the user aborts the clarification context menu.
            GetScreen()->SetCurItem( NULL );
            m_canvas->SetAbortRequest( true );   // Changed to false if an item is selected
            PopupMenu( &selectMenu );

            if( !m_canvas->GetAbortRequest() )
            {
                m_canvas->MoveCursorToCrossHair();
                item = GetScreen()->GetCurItem();
            }
        }
    }

    GetScreen()->SetCurItem( item );

    if( item )
    {
        if( item->Type() == SCH_COMPONENT_T )
            ( (SCH_COMPONENT*) item )->SetCurrentSheetPath( &GetCurrentSheet() );

        MSG_PANEL_ITEMS items;
        item->GetMsgPanelInfo( m_UserUnits, items );
        SetMsgPanel( items );
    }
    else
    {
        ClearMsgPanel();
    }

    return item;
}
Exemple #17
0
bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupFile )
{
    // please, keep it simple.  prompting goes elsewhere.

    wxFileName  pcbFileName = aFileName;

    if( pcbFileName.GetExt() == LegacyPcbFileExtension )
        pcbFileName.SetExt( KiCadPcbFileExtension );

    if( !IsWritable( pcbFileName ) )
    {
        wxString msg = wxString::Format( _(
            "No access rights to write to file \"%s\"" ),
            GetChars( pcbFileName.GetFullPath() )
            );

        DisplayError( this, msg );
        return false;
    }

    wxString backupFileName;

    if( aCreateBackupFile )
    {
        backupFileName = createBackupFile( aFileName );
    }

    GetBoard()->SynchronizeNetsAndNetClasses();

    // Select default Netclass before writing file.
    // Useful to save default values in headers
    SetCurrentNetClass( NETCLASS::Default );

    ClearMsgPanel();

    wxString    upperTxt;
    wxString    lowerTxt;

    try
    {
        PLUGIN::RELEASER    pi( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) );

        wxASSERT( pcbFileName.IsAbsolute() );

        pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
    }
    catch( const IO_ERROR& ioe )
    {
        wxString msg = wxString::Format( _(
                "Error saving board file \"%s\".\n%s" ),
                GetChars( pcbFileName.GetFullPath() ),
                GetChars( ioe.What() )
                );
        DisplayError( this, msg );

        lowerTxt.Printf( _( "Failed to create \"%s\"" ), GetChars( pcbFileName.GetFullPath() ) );

        AppendMsgPanel( upperTxt, lowerTxt, CYAN );

        return false;
    }

    GetBoard()->SetFileName( pcbFileName.GetFullPath() );
    UpdateTitle();

    // Put the saved file in File History, unless aCreateBackupFile
    // is false.
    // aCreateBackupFile == false is mainly used to write autosave files
    // and not need to have an autosave file in file history
    if( aCreateBackupFile )
        UpdateFileHistory( GetBoard()->GetFileName() );

    // Delete auto save file on successful save.
    wxFileName autoSaveFileName = pcbFileName;

    autoSaveFileName.SetName( GetAutoSaveFilePrefix() + pcbFileName.GetName() );

    if( autoSaveFileName.FileExists() )
        wxRemoveFile( autoSaveFileName.GetFullPath() );

    if( !!backupFileName )
        upperTxt.Printf( _( "Backup file: \"%s\"" ), GetChars( backupFileName ) );

    lowerTxt.Printf( _( "Wrote board file: \"%s\"" ), GetChars( pcbFileName.GetFullPath() ) );

    AppendMsgPanel( upperTxt, lowerTxt, CYAN );

    GetScreen()->ClrModify();
    GetScreen()->ClrSave();
    return true;
}
bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
{
    // implement the pseudo code from KIWAY_PLAYER.h:

    SCH_SCREENS screenList;

    // This is for python:
    if( aFileSet.size() != 1 )
    {
        UTF8 msg = StrPrintf( "Eeschema:%s() takes only a single filename", __func__ );
        DisplayError( this, msg );
        return false;
    }

    wxString    fullFileName( aFileSet[0] );

    // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
    wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(),
        wxT( "bug in single_top.cpp or project manager." ) );

    if( !LockFile( fullFileName ) )
    {
        wxString msg = wxString::Format( _(
                "Schematic file '%s' is already open." ),
                GetChars( fullFileName )
                );
        DisplayError( this, msg );
        return false;
    }

    // save any currently open and modified project files.
    for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
    {
        if( screen->IsModify() )
        {
            int response = YesNoCancelDialog( this, _(
                "The current schematic has been modified.  Do you wish to save the changes?" ),
                wxEmptyString,
                _( "Save and Load" ),
                _( "Load Without Saving" )
                );

            if( response == wxID_CANCEL )
            {
                return false;
            }
            else if( response == wxID_YES )
            {
                wxCommandEvent dummy;
                OnSaveProject( dummy );
            }
            else
            {
                // response == wxID_NO, fall thru
            }
            break;
        }
    }

    wxFileName pro = fullFileName;
    pro.SetExt( ProjectFileExtension );

    bool is_new = !wxFileName::IsFileReadable( fullFileName );

    // If its a non-existent schematic and caller thinks it exists
    if( is_new && !( aCtl & KICTL_CREATE ) )
    {
        // notify user that fullFileName does not exist, ask if user wants to create it.
        wxString ask = wxString::Format( _(
                "Schematic '%s' does not exist.  Do you wish to create it?" ),
                GetChars( fullFileName )
                );
        if( !IsOK( this, ask ) )
            return false;
    }

    // unload current project file before loading new
    {
        delete g_RootSheet;
        g_RootSheet = NULL;

        CreateScreens();
    }

    GetScreen()->SetFileName( fullFileName );
    g_RootSheet->SetFileName( fullFileName );

    SetStatusText( wxEmptyString );
    ClearMsgPanel();

    wxString msg = wxString::Format( _(
            "Ready\nProject dir: '%s'\n" ),
            GetChars( wxPathOnly( Prj().GetProjectFullName() ) )
            );
    SetStatusText( msg );

    // PROJECT::SetProjectFullName() is an impactful function.  It should only be
    // called under carefully considered circumstances.

    // The calling code should know not to ask me here to change projects unless
    // it knows what consequences that will have on other KIFACEs running and using
    // this same PROJECT.  It can be very harmful if that calling code is stupid.
    Prj().SetProjectFullName( pro.GetFullPath() );

    LoadProjectFile();

    // load the libraries here, not in SCH_SCREEN::Draw() which is a context
    // that will not tolerate DisplayError() dialog since we're already in an
    // event handler in there.
    // And when a schematic file is loaded, we need these libs to initialize
    // some parameters (links to PART LIB, dangling ends ...)
    Prj().SchLibs();

    if( is_new )
    {
        // mark new, unsaved file as modified.
        GetScreen()->SetModify();
    }
    else
    {
        g_RootSheet->SetScreen( NULL );

        DBG( printf( "%s: loading schematic %s\n", __func__, TO_UTF8( fullFileName ) );)

        bool diag = g_RootSheet->Load( this );
        (void) diag;

        SetScreen( m_CurrentSheet->LastScreen() );

        GetScreen()->ClrModify();

        UpdateFileHistory( fullFileName );
    }
bool SCH_EDIT_FRAME::LoadOneEEProject( const wxString& aFileName, bool aIsNew )
{
    SCH_SCREEN* screen;
    wxString    FullFileName, msg;
    bool        LibCacheExist = false;
    SCH_SCREENS ScreenList;

    for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
    {
        if( screen->IsModify() )
            break;
    }

    if( screen )
    {
        int response = YesNoCancelDialog( this, _( "The current schematic has been modified.  Do "
                                                   "you wish to save the changes?" ),
                                          wxEmptyString,
                                          _( "Save and Load" ), _( "Load Without Saving" ) );

        if( response == wxID_CANCEL )
        {
            return false;
        }
        else if( response == wxID_YES )
        {
            wxCommandEvent dummy;
            OnSaveProject( dummy );
        }
    }

    FullFileName = aFileName;

    if( FullFileName.IsEmpty() && !aIsNew )
    {
        wxFileDialog dlg( this, _( "Open Schematic" ), wxGetCwd(),
                          wxEmptyString, SchematicFileWildcard,
                          wxFD_OPEN | wxFD_FILE_MUST_EXIST );

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

        FullFileName = dlg.GetPath();
    }

    wxFileName fn = FullFileName;

    if( fn.IsRelative() )
    {
        fn.MakeAbsolute();
        FullFileName = fn.GetFullPath();
    }

    if( !wxGetApp().LockFile( FullFileName ) )
    {
        DisplayError( this, _( "This file is already open." ) );
        return false;
    }

    // Clear the screen before open a new file
    if( g_RootSheet )
    {
        delete g_RootSheet;
        g_RootSheet = NULL;
    }

    CreateScreens();
    screen = GetScreen();

    wxLogDebug( wxT( "Loading schematic " ) + FullFileName );
    wxSetWorkingDirectory( fn.GetPath() );

    screen->SetFileName( FullFileName );
    g_RootSheet->SetFileName( FullFileName );
    SetStatusText( wxEmptyString );
    ClearMsgPanel();

    screen->ClrModify();

    if( aIsNew )
    {
        /* SCH_SCREEN constructor does this now
        screen->SetPageSettings( PAGE_INFO( wxT( "A4" ) ) );
        */

        screen->SetZoom( 32 );
        screen->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId  );

        TITLE_BLOCK tb;
        wxString    title;

        title += NAMELESS_PROJECT;
        title += wxT( ".sch" );
        tb.SetTitle( title );
        screen->SetTitleBlock( tb );

        GetScreen()->SetFileName( title );

        LoadProjectFile( wxEmptyString, true );
        Zoom_Automatique( false );
        SetSheetNumberAndCount();
        m_canvas->Refresh();
        return true;
    }

    // Reloading configuration.
    msg.Printf( _( "Ready\nWorking dir: <%s>\n" ), GetChars( wxGetCwd() ) );
    PrintMsg( msg );

    LoadProjectFile( wxEmptyString, false );

    // Clear (if needed) the current active library in libedit because it could be
    // removed from memory
    LIB_EDIT_FRAME::EnsureActiveLibExists();

    // Delete old caches.
    CMP_LIBRARY::RemoveCacheLibrary();

    LibCacheExist = LoadCacheLibrary( g_RootSheet->GetScreen()->GetFileName() );

    if( !wxFileExists( g_RootSheet->GetScreen()->GetFileName() ) && !LibCacheExist )
    {
        Zoom_Automatique( false );
        msg.Printf( _( "File <%s> not found." ),
                    GetChars( g_RootSheet->GetScreen()->GetFileName() ) );
        DisplayInfoMessage( this, msg );
        return false;
    }

    // load the project.
    g_RootSheet->SetScreen( NULL );
    bool diag = g_RootSheet->Load( this );
    SetScreen( m_CurrentSheet->LastScreen() );

    UpdateFileHistory( g_RootSheet->GetScreen()->GetFileName() );

    /* Redraw base screen (ROOT) if necessary. */
    GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
    Zoom_Automatique( false );
    SetSheetNumberAndCount();
    m_canvas->Refresh( true );
    return diag;
}
SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
                                      int aHotKeyCommandId )
{
    SCH_ITEM* item = NULL;

    m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );

    if( m_collectedItems.GetCount() == 0 )
    {
        ClearMsgPanel();
    }
    else if( m_collectedItems.GetCount() == 1 )
    {
        item = m_collectedItems[0];
    }
    else
    {
        // There are certain combinations of items that do not need clarification such as
        // a corner were two lines meet or all the items form a junction.
        if( aHotKeyCommandId )
        {
            switch( aHotKeyCommandId )
            {
            case HK_DRAG:
                if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false )
                    || m_collectedItems.IsDraggableJunction() )
                {
                    item = m_collectedItems[0];
                }
            default:
                ;
            }
        }

        if( item == NULL )
        {
            wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
                          wxT( "Select item clarification context menu size limit exceeded." ) );

            wxMenu selectMenu;
            wxMenuItem* title = new wxMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ) );

            selectMenu.Append( title );
            selectMenu.AppendSeparator();

            for( int i = 0;  i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS;  i++ )
            {
                wxString text = m_collectedItems[i]->GetSelectMenuText();
                BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
                AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
            }

            // Set to NULL in case user aborts the clarification context menu.
            GetScreen()->SetCurItem( NULL );
            m_canvas->SetAbortRequest( true );   // Changed to false if an item is selected
            PopupMenu( &selectMenu );
            m_canvas->MoveCursorToCrossHair();
            item = GetScreen()->GetCurItem();
        }
    }

    GetScreen()->SetCurItem( item );

    if( item )
    {
        if( item->Type() == SCH_COMPONENT_T )
            ( (SCH_COMPONENT*) item )->SetCurrentSheetPath( &GetCurrentSheet() );

        MSG_PANEL_ITEMS items;
        item->GetMsgPanelInfo( items );
        SetMsgPanel( items );
    }
    else
    {
        ClearMsgPanel();
    }

    return item;
}
bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile )
{
    wxFileName fn;
    wxString   msg;

    m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );

    PART_LIB* lib = GetCurLib();

    // Just in case the library hasn't been cached yet.
    lib->GetCount();

    if( !lib )
    {
        DisplayError( this, _( "No library specified." ) );
        return false;
    }

    wxString oldFileName = lib->GetFullFileName();

    if( GetScreen()->IsModify() )
    {
        if( IsOK( this, _( "Include last component changes?" ) ) )
        {
            lib->EnableBuffering();

            try
            {
                SaveOnePart( lib, false );
            }
            catch( ... )
            {
                lib->EnableBuffering( false );
                msg.Printf( _( "Unexpected error occured saving part to '%s' symbol library." ),
                            lib->GetName() );
                DisplayError( this, msg );
                return false;
            }

            lib->EnableBuffering( false );
        }
    }

    if( newFile )
    {
        PROJECT&        prj = Prj();
        SEARCH_STACK*   search = prj.SchSearchS();

        // Get a new name for the library
        wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );

        if( !default_path )
            default_path = search->LastVisitedPath();

        wxFileDialog dlg( this, _( "Part Library Name:" ), default_path,
                          wxEmptyString, SchematicLibraryFileWildcard,
                          wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

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

        fn = dlg.GetPath();

        // The GTK file chooser doesn't return the file extension added to
        // file name so add it here.
        if( fn.GetExt().IsEmpty() )
            fn.SetExt( SchematicLibraryFileExtension );

        prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );
    }
    else
    {
        fn = wxFileName( lib->GetFullFileName() );

        msg.Printf( _( "Modify library file '%s' ?" ), GetChars( fn.GetFullPath() ) );

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

    // Verify the user has write privileges before attempting to save the library file.
    if( !IsWritable( fn ) )
        return false;

    ClearMsgPanel();

    wxFileName libFileName = fn;
    wxFileName backupFileName = fn;

    // Rename the old .lib file to .bak.
    if( libFileName.FileExists() )
    {
        backupFileName.SetExt( "bak" );

        if( backupFileName.FileExists() )
            wxRemoveFile( backupFileName.GetFullPath() );

        if( !wxRenameFile( libFileName.GetFullPath(), backupFileName.GetFullPath() ) )
        {
            libFileName.MakeAbsolute();
            msg = _( "Failed to rename old component library file " ) +
                  backupFileName.GetFullPath();
            DisplayError( this, msg );
        }
    }

    wxFileName docFileName = libFileName;

    docFileName.SetExt( DOC_EXT );

    // Rename .doc file to .bck.
    if( docFileName.FileExists() )
    {
        backupFileName.SetExt( "bck" );

        if( backupFileName.FileExists() )
            wxRemoveFile( backupFileName.GetFullPath() );

        if( !wxRenameFile( docFileName.GetFullPath(), backupFileName.GetFullPath() ) )
        {
            msg = _( "Failed to save old library document file " ) + backupFileName.GetFullPath();
            DisplayError( this, msg );
        }
    }

    try
    {
        lib->SetFileName( fn.GetFullPath() );
        lib->Save();
    }
    catch( ... /* IO_ERROR ioe */ )
    {
        lib->SetFileName( oldFileName );
        msg.Printf( _( "Failed to create symbol library file '%s'" ),
                    GetChars( docFileName.GetFullPath() ) );
        DisplayError( this, msg );
        return false;
    }

    lib->SetFileName( oldFileName );
    msg.Printf( _( "Library file '%s' saved" ), GetChars( fn.GetFullPath() ) );
    fn.SetExt( DOC_EXT );
    wxString msg1;
    msg1.Printf( _( "Documentation file '%s' saved" ), GetChars( fn.GetFullPath() ) );
    AppendMsgPanel( msg, msg1, BLUE );
    UpdateAliasSelectList();
    UpdatePartSelectList();
    refreshSchematic();

    return true;
}
/* Handles the selection of tools, menu, and popup menu commands.
 */
void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event )
{
    int           id = event.GetId();

    switch( id )
    {
    case wxID_CUT:
    case wxID_COPY:
    case ID_POPUP_DELETE_BLOCK:
    case ID_POPUP_PLACE_BLOCK:
    case ID_POPUP_ZOOM_BLOCK:
        break;

    case ID_POPUP_CANCEL_CURRENT_COMMAND:
        m_canvas->EndMouseCapture();

        if( GetScreen()->m_BlockLocate.GetCommand() != BLOCK_IDLE )
        {
            /* Should not be executed, except bug */
            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
            m_canvas->SetCursor( (wxStockCursor) m_canvas->GetCurrentCursor() );
        break;

    default:
        m_canvas->EndMouseCapture();
        break;
    }

    INSTALL_UNBUFFERED_DC( dc, m_canvas );

    switch( id )
    {
    case ID_GERBVIEW_SET_PAGE_BORDER:
        {
            DIALOG_PAGE_SHOW_PAGE_BORDERS dlg( this );

            if( dlg.ShowModal() == wxID_OK )
                m_canvas->Refresh();
        }
        break;

    case ID_GERBVIEW_GLOBAL_DELETE:
        Erase_Current_DrawLayer( true );
        ClearMsgPanel();
        break;

    case ID_NO_TOOL_SELECTED:
        SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString );
        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_GERBVIEW_SHOW_LIST_DCODES:
        Liste_D_Codes();
        break;

    case ID_POPUP_PLACE_BLOCK:
        GetScreen()->m_BlockLocate.SetCommand( BLOCK_MOVE );
        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;

    default:
        wxFAIL_MSG( wxT( "GERBVIEW_FRAME::Process_Special_Functions error" ) );
        break;
    }
}