mainframe.cpp 13.7 KB
Newer Older
1 2 3 4
/**
 * @file kicad/mainframe.cpp
 * @brief KICAD_MANAGER_FRAME is the KiCad main frame.
 */
5

6 7 8
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
9
 * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
10
 * Copyright (C) 2013 CERN (www.cern.ch)
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 * Copyright (C) 2004-2012 KiCad Developers, see change_log.txt for contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */
30

31
#include <fctsys.h>
32
#include <pgm_kicad.h>
33
#include <kiway.h>
34
#include <kiway_player.h>
35 36
#include <confirm.h>
#include <gestfich.h>
37
#include <macros.h>
38

39 40
#include <kicad.h>
#include <tree_project_frame.h>
41
#include <wildcards_and_files_ext.h>
42
#include <menus_helpers.h>
43 44


45
#define TREE_FRAME_WIDTH_ENTRY     wxT( "LeftWinWidth" )
46

47 48 49

KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent,
        const wxString& title, const wxPoint&  pos, const wxSize&   size ) :
50
    EDA_BASE_FRAME( parent, KICAD_MAIN_FRAME_T, title, pos, size,
51
                    KICAD_DEFAULT_DRAWFRAME_STYLE, wxT( "KicadFrame" ) )
52
{
53
    m_leftWinWidth = 60;
54 55

    // Create the status line (bottom of the frame
56 57
    static const int dims[3] = { -1, -1, 100 };

58 59 60 61
    CreateStatusBar( 3 );
    SetStatusWidths( 3, dims );

    // Give an icon
62 63 64
    wxIcon icon;
    icon.CopyFromBitmap( KiBitmap( icon_kicad_xpm ) );
    SetIcon( icon );
65

66
    // Give the last sise and pos to main window
67
    LoadSettings( config() );
68
    SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
69 70

    // Left window: is the box which display tree project
71
    m_LeftWin = new TREE_PROJECT_FRAME( this );
72

73 74
    // Right top Window: buttons to launch applications
    m_Launcher = new LAUNCHER_PANEL( this );
75

76 77 78 79
    // Add the wxTextCtrl showing all messages from KiCad:
    m_MessagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString,
                                    wxDefaultPosition, wxDefaultSize,
                                    wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY );
80

81
    RecreateBaseHToolbar();
82
    ReCreateMenuBar();
83

charras's avatar
charras committed
84
    m_auimgr.SetManagedWindow( this );
85

86 87
    EDA_PANEINFO horiztb;
    horiztb.HorizontalToolbarPane();
88 89 90

    EDA_PANEINFO info;
    info.InfoToolbarPane();
91

92 93 94 95 96 97 98
    m_auimgr.AddPane( m_mainToolBar,
                      wxAuiPaneInfo( horiztb ).Name( wxT( "m_mainToolBar" ) ).Top() );

    m_auimgr.AddPane( m_LeftWin,
                      wxAuiPaneInfo(info).Name( wxT( "m_LeftWin" ) ).Left().
                      BestSize( m_leftWinWidth, -1 ).
                      Layer( 1 ) );
99

100 101 102
    m_auimgr.AddPane( m_Launcher, wxTOP );
    m_auimgr.GetPane( m_Launcher).CaptionVisible( false ).Row(1)
        .BestSize( -1, m_Launcher->GetPanelHeight() ).PaneBorder( false ).Resizable( false );
103

104 105 106 107 108
    m_auimgr.AddPane( m_MessagesBox,
                      wxAuiPaneInfo().Name( wxT( "m_MessagesBox" ) ).CentrePane().Layer( 2 ) );

    m_auimgr.GetPane( m_LeftWin ).MinSize( wxSize( 80, -1) );
    m_auimgr.GetPane( m_LeftWin ).BestSize(wxSize(m_leftWinWidth, -1) );
109

110
    m_auimgr.Update();
111 112 113
}


114
KICAD_MANAGER_FRAME::~KICAD_MANAGER_FRAME()
115
{
charras's avatar
charras committed
116
    m_auimgr.UnInit();
117 118 119
}


120 121 122 123 124 125 126
wxConfigBase* KICAD_MANAGER_FRAME::config()
{
    wxConfigBase* ret = Pgm().PgmSettings();
    wxASSERT( ret );
    return ret;
}

Dick Hollenbeck's avatar
Dick Hollenbeck committed
127

128 129
void KICAD_MANAGER_FRAME::SetProjectFileName( const wxString& aFullProjectProFileName )
{
130 131
    // ensure file name is absolute:
    wxFileName fn( aFullProjectProFileName );
132

133 134 135 136
    if( !fn.IsAbsolute() )
        fn.MakeAbsolute();

    Prj().SetProjectFullName( fn.GetFullPath() );
137 138 139 140 141
}


const wxString KICAD_MANAGER_FRAME::GetProjectFileName()
{
142
    return  Prj().GetProjectFullName();
143 144 145 146 147
}


const wxString KICAD_MANAGER_FRAME::SchFileName()
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
148 149 150
   wxFileName   fn( GetProjectFileName() );

   fn.SetExt( SchematicFileExtension );
151

152
   return fn.GetFullPath();
153 154 155 156 157
}


const wxString KICAD_MANAGER_FRAME::PcbFileName()
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
158 159 160 161
   wxFileName   fn( GetProjectFileName() );

   fn.SetExt( PcbFileExtension );

162
   return fn.GetFullPath();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
163 164 165 166 167 168 169 170
}


const wxString KICAD_MANAGER_FRAME::PcbLegacyFileName()
{
   wxFileName   fn( GetProjectFileName() );

   fn.SetExt( LegacyPcbFileExtension );
171

172
   return fn.GetFullPath();
173 174
}

175

Dick Hollenbeck's avatar
Dick Hollenbeck committed
176 177 178 179 180 181
void KICAD_MANAGER_FRAME::ReCreateTreePrj()
{
    m_LeftWin->ReCreateTreePrj();
}


182 183 184 185 186 187 188 189 190 191 192 193
const SEARCH_STACK& KICAD_MANAGER_FRAME::sys_search()
{
    return Pgm().SysSearch();
}


wxString KICAD_MANAGER_FRAME::help_name()
{
    return Pgm().GetHelpFileName();
}


194
void KICAD_MANAGER_FRAME::PrintMsg( const wxString& aText )
195
{
196
    m_MessagesBox->AppendText( aText );
197 198 199
}


200
void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
201
{
charras's avatar
charras committed
202 203
    if( m_auimgr.GetManagedWindow() )
        m_auimgr.Update();
204

charras's avatar
charras committed
205
    event.Skip();
206 207 208
}


209
void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& Event )
210
{
211 212 213
    if( Kiway.PlayersClose( false ) )
    {
        int px, py;
214

215
        UpdateFileHistory( GetProjectFileName(), &Pgm().GetFileHistory() );
216

217 218 219 220 221
        if( !IsIconized() )   // save main frame position and size
        {
            GetPosition( &px, &py );
            m_FramePos.x = px;
            m_FramePos.y = py;
222

223 224 225 226
            GetSize( &px, &py );
            m_FrameSize.x = px;
            m_FrameSize.y = py;
        }
227

228
        Event.SetCanVeto( true );
229

230
        m_LeftWin->Show( false );
231

232 233
        Destroy();
    }
234 235 236
}


237
void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event )
238
{
239 240
    Close( true );
}
241

242

243
void KICAD_MANAGER_FRAME::TERMINATE_HANDLER::OnTerminate( int pid, int status )
244
{
245 246
    wxString msg = wxString::Format( _( "%s closed [pid=%d]\n" ),
            GetChars( appName ), pid );
247

248
    ( (KICAD_MANAGER_FRAME*) Pgm().App().GetTopWindow() )->PrintMsg( msg );
249 250 251 252 253 254

    delete this;
}


void KICAD_MANAGER_FRAME::Execute( wxWindow* frame, const wxString& execFile,
Dick Hollenbeck's avatar
Dick Hollenbeck committed
255
                                   wxString params )
256
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
257 258 259
    if( params.size() )
        AddDelimiterString( params );

260
    TERMINATE_HANDLER* callback = new TERMINATE_HANDLER( execFile );
261

Dick Hollenbeck's avatar
Dick Hollenbeck committed
262
    long pid = ExecuteFile( frame, execFile, params, callback );
263 264 265

    if( pid > 0 )
    {
266 267 268
        wxString msg = wxString::Format( _( "%s opened [pid=%ld]\n" ),
                GetChars( execFile ), pid );

269 270 271 272 273 274 275 276 277
        PrintMsg( msg );
    }
    else
    {
        delete callback;
    }
}


Dick Hollenbeck's avatar
Dick Hollenbeck committed
278
void KICAD_MANAGER_FRAME::RunEeschema( const wxString& aProjectSchematicFileName )
279
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
280
    KIWAY_PLAYER* frame = Kiway.Player( FRAME_SCH, false );
281 282 283 284 285

    // Please: note: DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers() calls
    // Kiway.Player( FRAME_SCH, true )
    // therefore, the schematic editor is sometimes running, but the schematic project
    // is not loaded, if the library editor was called, and the dialog field editor was used.
286 287 288 289
    // On linux, it happens the first time the schematic editor is launched, if
    // library editor was running, and the dialog field editor was open
    // On Windows, it happens always after the library editor was called,
    // and the dialog field editor was used
Dick Hollenbeck's avatar
Dick Hollenbeck committed
290 291 292
    if( !frame )
    {
        frame = Kiway.Player( FRAME_SCH, true );
293 294
    }

295 296
    if( !frame->IsShown() ) // the frame exists, (created by the dialog field editor)
                            // but no project loaded.
297
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
298 299 300
        frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectSchematicFileName ) );
        frame->Show( true );
    }
301

302 303
    // On Windows, Raise() does not bring the window on screen, when iconized or not shown
    // On linux, Raise() brings the window on screen, but this code works fine
304 305 306
    if( frame->IsIconized() )
        frame->Iconize( false );

Dick Hollenbeck's avatar
Dick Hollenbeck committed
307
    frame->Raise();
308 309
}

310

Dick Hollenbeck's avatar
Dick Hollenbeck committed
311
void KICAD_MANAGER_FRAME::OnRunEeschema( wxCommandEvent& event )
312
{
313
    wxFileName fn( GetProjectFileName() );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
314 315 316 317

    fn.SetExt( SchematicFileExtension );

    RunEeschema( fn.GetFullPath() );
318
}
319

Dick Hollenbeck's avatar
Dick Hollenbeck committed
320

321 322 323
void KICAD_MANAGER_FRAME::OnRunSchLibEditor( wxCommandEvent& event )
{
    KIWAY_PLAYER* frame = Kiway.Player( FRAME_SCH_LIB_EDITOR, false );
324

325 326 327 328 329 330
    if( !frame )
    {
        frame = Kiway.Player( FRAME_SCH_LIB_EDITOR, true );
        // frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectSchematicFileName ) );
        frame->Show( true );
    }
331

332
    // On Windows, Raise() does not bring the window on screen, when iconized
333 334 335
    if( frame->IsIconized() )
        frame->Iconize( false );

336 337 338 339
    frame->Raise();
}


Dick Hollenbeck's avatar
Dick Hollenbeck committed
340
void KICAD_MANAGER_FRAME::RunPcbNew( const wxString& aProjectBoardFileName )
341
{
342
#if 0   // line 171 of modview_frame.cpp breaks this code
Dick Hollenbeck's avatar
Dick Hollenbeck committed
343 344 345 346 347 348 349
    KIWAY_PLAYER* frame = Kiway.Player( FRAME_PCB, false );
    if( !frame )
    {
        frame = Kiway.Player( FRAME_PCB, true );
        frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectBoardFileName ) );
        frame->Show( true );
    }
350 351 352 353 354 355 356 357 358 359
#else
    KIWAY_PLAYER* frame = Kiway.Player( FRAME_PCB, true );

    if( !frame->IsVisible() )
    {
        frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectBoardFileName ) );
        frame->Show( true );
    }

#endif
360

361
    // On Windows, Raise() does not bring the window on screen, when iconized
362 363 364
    if( frame->IsIconized() )
        frame->Iconize( false );

Dick Hollenbeck's avatar
Dick Hollenbeck committed
365
    frame->Raise();
366 367
}

368

369
void KICAD_MANAGER_FRAME::OnRunPcbNew( wxCommandEvent& event )
370
{
371
    wxFileName  kicad_board( PcbFileName() );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
372
    wxFileName  legacy_board( PcbLegacyFileName() );
charras's avatar
charras committed
373

374 375 376
    wxFileName& board = ( !legacy_board.FileExists() || kicad_board.FileExists() ) ?
                            kicad_board : legacy_board;

Dick Hollenbeck's avatar
Dick Hollenbeck committed
377
    RunPcbNew( board.GetFullPath() );
378 379 380
}


381 382 383
void KICAD_MANAGER_FRAME::OnRunPcbFpEditor( wxCommandEvent& event )
{
    KIWAY_PLAYER* frame = Kiway.Player( FRAME_PCB_MODULE_EDITOR, false );
384

385 386 387 388 389 390
    if( !frame )
    {
        frame = Kiway.Player( FRAME_PCB_MODULE_EDITOR, true );
//        frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectBoardFileName ) );
        frame->Show( true );
    }
391

392
    // On Windows, Raise() does not bring the window on screen, when iconized
393 394 395
    if( frame->IsIconized() )
        frame->Iconize( false );

396 397 398 399
    frame->Raise();
}


Dick Hollenbeck's avatar
Dick Hollenbeck committed
400
void KICAD_MANAGER_FRAME::OnRunBitmapConverter( wxCommandEvent& event )
401
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
402 403
    Execute( this, BITMAPCONVERTER_EXE );
}
charras's avatar
charras committed
404

405

Dick Hollenbeck's avatar
Dick Hollenbeck committed
406 407 408
void KICAD_MANAGER_FRAME::OnRunPcbCalculator( wxCommandEvent& event )
{
    Execute( this, PCB_CALCULATOR_EXE );
409
}
410

411

Dick Hollenbeck's avatar
Dick Hollenbeck committed
412 413 414 415
void KICAD_MANAGER_FRAME::OnRunPageLayoutEditor( wxCommandEvent& event )
{
    Execute( this, PL_EDITOR_EXE );
}
416

Dick Hollenbeck's avatar
Dick Hollenbeck committed
417

418 419 420 421 422
// Dead code: Cvpcb can be run only from the schematic editor now,
// This is due to the fact the footprint field of components in schematics
// are now always set by Cvpcb.
// ( The idea is to drop the .cmp files to avoid to have 2 places were
// footprints are stored, but only one: the schematic )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
423
void KICAD_MANAGER_FRAME::OnRunCvpcb( wxCommandEvent& event )
424
{
425
    wxFileName fn( GetProjectFileName() );
charras's avatar
charras committed
426

Dick Hollenbeck's avatar
Dick Hollenbeck committed
427
    fn.SetExt( NetlistFileExtension );
428

Dick Hollenbeck's avatar
Dick Hollenbeck committed
429
    KIWAY_PLAYER* frame = Kiway.Player( FRAME_CVPCB, false );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
430 431
    if( !frame )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
432
        frame = Kiway.Player( FRAME_CVPCB, true );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
433 434 435
        frame->OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) );
        frame->Show( true );
    }
436

437
    frame->Raise();
438
}
439

440
#include <wx/filefn.h>
441
void KICAD_MANAGER_FRAME::OnRunGerbview( wxCommandEvent& event )
442
{
443 444
    // Gerbview is called without any file to open, because we do not know
    // the list and the name of files to open (if any...).
445 446
    // however we run it in the path of the project
    wxString cwd = wxGetCwd();
447
    wxSetWorkingDirectory( Prj().GetProjectPath() );
448
    Execute( this, GERBVIEW_EXE, wxEmptyString );
449
    wxSetWorkingDirectory( cwd );
450
}
451 452


453
void KICAD_MANAGER_FRAME::OnOpenTextEditor( wxCommandEvent& event )
454
{
455
    wxString editorname = Pgm().GetEditorName();
456 457

    if( !editorname.IsEmpty() )
458
        Execute( this, editorname, wxEmptyString );
459 460
}

461

462
void KICAD_MANAGER_FRAME::OnOpenFileInTextEditor( wxCommandEvent& event )
463 464
{
    wxString mask( wxT( "*" ) );
charras's avatar
charras committed
465

466
#ifdef __WINDOWS__
467
    mask += wxT( ".*" );
468 469
#endif

470
    mask = _( "Text file (" ) + mask + wxT( ")|" ) + mask;
471
    wxString default_dir = Prj().GetProjectPath();
472

473
    wxFileDialog dlg( this, _( "Load File to Edit" ), default_dir,
charras's avatar
charras committed
474
                      wxEmptyString, mask, wxFD_OPEN );
475

476 477 478
    if( dlg.ShowModal() == wxID_CANCEL )
        return;

479 480 481
    wxString filename = wxT( "\"" );
    filename += dlg.GetPath() + wxT( "\"" );

482 483
    if( !dlg.GetPath().IsEmpty() &&  !Pgm().GetEditorName().IsEmpty() )
        Execute( this, Pgm().GetEditorName(), filename );
484 485 486
}


487
void KICAD_MANAGER_FRAME::OnRefresh( wxCommandEvent& event )
488 489 490 491 492
{
    m_LeftWin->ReCreateTreePrj();
}


493 494 495 496 497 498 499 500
void KICAD_MANAGER_FRAME::language_change( wxCommandEvent& event )
{
    int id = event.GetId();

    Kiway.SetLanguage( id );
}


501
void KICAD_MANAGER_FRAME::ClearMsg()
502
{
503
    m_MessagesBox->Clear();
504 505
}

506

507
void KICAD_MANAGER_FRAME::LoadSettings( wxConfigBase* aCfg )
508
{
509
    EDA_BASE_FRAME::LoadSettings( aCfg );
510
    aCfg->Read( TREE_FRAME_WIDTH_ENTRY, &m_leftWinWidth );
511 512 513
}


514
void KICAD_MANAGER_FRAME::SaveSettings( wxConfigBase* aCfg )
515
{
516
    EDA_BASE_FRAME::SaveSettings( aCfg );
517
    aCfg->Write( TREE_FRAME_WIDTH_ENTRY, m_LeftWin->GetSize().x );
518
}
519

520

521 522
/**
 * a minor helper function:
523
 * Prints the Current Project full name on the text panel.
524 525 526
 */
void KICAD_MANAGER_FRAME::PrintPrjInfo()
{
527 528
    wxString msg = wxString::Format( _( "Project name:\n%s\n" ),
                        GetChars( GetProjectFileName() ) );
529
    PrintMsg( msg );
530
}
531