summaryrefslogtreecommitdiff
path: root/common/single_top.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/single_top.cpp')
-rw-r--r--common/single_top.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/common/single_top.cpp b/common/single_top.cpp
new file mode 100644
index 0000000..7016501
--- /dev/null
+++ b/common/single_top.cpp
@@ -0,0 +1,308 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
+ * Copyright (C) 2014 KiCad Developers, see CHANGELOG.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
+ */
+
+
+/*
+
+ This is a program launcher for a single KIFACE DSO. It only mimics a KIWAY,
+ not actually implements one, since only a single DSO is supported by it.
+
+ It is compiled multiple times, once for each standalone program and as such
+ gets different compiler command line supplied #defines from CMake.
+
+*/
+
+
+#include <typeinfo>
+#include <macros.h>
+#include <fctsys.h>
+#include <wx/filename.h>
+#include <wx/stdpaths.h>
+#include <wx/snglinst.h>
+
+#include <kiway.h>
+#include <pgm_base.h>
+#include <kiway_player.h>
+#include <confirm.h>
+
+
+// Only a single KIWAY is supported in this single_top top level component,
+// which is dedicated to loading only a single DSO.
+KIWAY Kiway( &Pgm(), KFCTL_STANDALONE );
+
+
+// implement a PGM_BASE and a wxApp side by side:
+
+/**
+ * Struct PGM_SINGLE_TOP
+ * implements PGM_BASE with its own OnPgmInit() and OnPgmExit().
+ */
+static struct PGM_SINGLE_TOP : public PGM_BASE
+{
+ bool OnPgmInit( wxApp* aWxApp ); // overload PGM_BASE virtual
+ void OnPgmExit(); // overload PGM_BASE virtual
+ void MacOpenFile( const wxString& aFileName ); // overload PGM_BASE virtual
+} program;
+
+
+PGM_BASE& Pgm()
+{
+ return program;
+}
+
+
+/**
+ * Struct APP_SINGLE_TOP
+ * implements a bare naked wxApp (so that we don't become dependent on
+ * functionality in a wxApp derivative that we cannot deliver under wxPython).
+ */
+struct APP_SINGLE_TOP : public wxApp
+{
+#if defined (__LINUX__)
+ APP_SINGLE_TOP(): wxApp()
+ {
+ // Disable proxy menu in Unity window manager. Only usual menubar works with wxWidgets (at least <= 3.1)
+ // When the proxy menu menubar is enable, some important things for us do not work: menuitems UI events and shortcuts.
+ wxString wm;
+
+ if( wxGetEnv( wxT( "XDG_CURRENT_DESKTOP" ), &wm ) && wm.CmpNoCase( wxT( "Unity" ) ) == 0 )
+ {
+ wxSetEnv ( wxT("UBUNTU_MENUPROXY" ), wxT( "0" ) );
+ }
+ }
+#endif
+
+ bool OnInit() // overload wxApp virtual
+ {
+ try
+ {
+ return Pgm().OnPgmInit( this );
+ }
+ catch( const std::exception& e )
+ {
+ wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
+ GetChars( FROM_UTF8( typeid(e).name() )),
+ GetChars( FROM_UTF8( e.what() ) ) );
+ }
+ catch( const IO_ERROR& ioe )
+ {
+ wxLogError( GetChars( ioe.errorText ) );
+ }
+ catch(...)
+ {
+ wxLogError( wxT( "Unhandled exception of unknown type" ) );
+ }
+
+ Pgm().OnPgmExit();
+
+ return false;
+ }
+
+ int OnExit() // overload wxApp virtual
+ {
+ // Fixes segfault when wxPython scripting is enabled.
+#if defined( KICAD_SCRIPTING_WXPYTHON )
+ Pgm().OnPgmExit();
+#endif
+ return wxApp::OnExit();
+ }
+
+ int OnRun() // overload wxApp virtual
+ {
+ int ret = -1;
+
+ try
+ {
+ ret = wxApp::OnRun();
+ }
+ catch( const std::exception& e )
+ {
+ wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
+ GetChars( FROM_UTF8( typeid(e).name() )),
+ GetChars( FROM_UTF8( e.what() ) ) );
+ }
+ catch( const IO_ERROR& ioe )
+ {
+ wxLogError( GetChars( ioe.errorText ) );
+ }
+ catch(...)
+ {
+ wxLogError( wxT( "Unhandled exception of unknown type" ) );
+ }
+
+ // Works properly when wxPython scripting is disabled.
+#if !defined( KICAD_SCRIPTING_WXPYTHON )
+ Pgm().OnPgmExit();
+#endif
+
+ return ret;
+ }
+
+ /**
+ * Function MacOpenFile
+ * is specific to MacOSX (not used under Linux or Windows).
+ * MacOSX requires it for file association.
+ * @see http://wiki.wxwidgets.org/WxMac-specific_topics
+ */
+ void MacOpenFile( const wxString& aFileName ) // overload wxApp virtual
+ {
+ Pgm().MacOpenFile( aFileName );
+ }
+};
+
+IMPLEMENT_APP( APP_SINGLE_TOP );
+
+
+bool PGM_SINGLE_TOP::OnPgmInit( wxApp* aWxApp )
+{
+ // first thing: set m_wx_app
+ m_wx_app = aWxApp;
+
+ wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath();
+
+ if( !wxIsAbsolutePath( absoluteArgv0 ) )
+ {
+ wxLogError( wxT( "No meaningful argv[0]" ) );
+ return false;
+ }
+
+ if( !initPgm() )
+ return false;
+
+#if !defined(BUILD_KIWAY_DLL)
+ // Get the getter, it is statically linked into this binary image.
+ KIFACE_GETTER_FUNC* getter = &KIFACE_GETTER;
+
+ int kiface_version;
+
+ // Get the KIFACE.
+ KIFACE* kiface = getter( &kiface_version, KIFACE_VERSION, this );
+
+ // Trick the KIWAY into thinking it loaded a KIFACE, by recording the KIFACE
+ // in the KIWAY. It needs to be there for KIWAY::OnKiwayEnd() anyways.
+ Kiway.set_kiface( KIWAY::KifaceType( TOP_FRAME ), kiface );
+#endif
+
+ // Use KIWAY to create a top window, which registers its existence also.
+ // "TOP_FRAME" is a macro that is passed on compiler command line from CMake,
+ // and is one of the types in FRAME_T.
+ KIWAY_PLAYER* frame = Kiway.Player( TOP_FRAME, true );
+
+ Kiway.SetTop( frame );
+
+ App().SetTopWindow( frame ); // wxApp gets a face.
+
+ // Open project or file specified on the command line:
+ int argc = App().argc;
+
+ if( argc > 1 )
+ {
+ /*
+ gerbview handles multiple project data files, i.e. gerber files on
+ cmd line. Others currently do not, they handle only one. For common
+ code simplicity we simply pass all the arguments in however, each
+ program module can do with them what they want, ignore, complain
+ whatever. We don't establish policy here, as this is a multi-purpose
+ launcher.
+ */
+
+ std::vector<wxString> argSet;
+
+ for( int i=1; i<argc; ++i )
+ {
+ argSet.push_back( App().argv[i] );
+ }
+
+ // special attention to the first argument: argv[1] (==argSet[0])
+ wxFileName argv1( argSet[0] );
+
+ if( argc == 2 )
+ {
+#if defined(PGM_DATA_FILE_EXT)
+ // PGM_DATA_FILE_EXT, if present, may be different for each compile,
+ // it may come from CMake on the compiler command line, but often does not.
+ // This facillity is mostly useful for those program modules
+ // supporting a single argv[1].
+ if( !argv1.GetExt() )
+ argv1.SetExt( wxT( PGM_DATA_FILE_EXT ) );
+
+#endif
+ argv1.MakeAbsolute();
+
+ argSet[0] = argv1.GetFullPath();
+ }
+
+ // Use the KIWAY_PLAYER::OpenProjectFiles() API function:
+ if( !frame->OpenProjectFiles( argSet ) )
+ {
+ // OpenProjectFiles() API asks that it report failure to the UI.
+ // Nothing further to say here.
+
+ // We've already initialized things at this point, but wx won't call OnExit if
+ // we fail out. Call our own cleanup routine here to ensure the relevant resources
+ // are freed at the right time (if they aren't, segfaults will occur).
+ OnPgmExit();
+
+ // Fail the process startup if the file could not be opened,
+ // although this is an optional choice, one that can be reversed
+ // also in the KIFACE specific OpenProjectFiles() return value.
+ return false;
+ }
+ }
+
+ frame->Show();
+
+ return true;
+}
+
+
+void PGM_SINGLE_TOP::OnPgmExit()
+{
+ Kiway.OnKiwayEnd();
+
+ saveCommonSettings();
+
+ // Destroy everything in PGM_BASE, especially wxSingleInstanceCheckerImpl
+ // earlier than wxApp and earlier than static destruction would.
+ PGM_BASE::destroy();
+}
+
+
+void PGM_SINGLE_TOP::MacOpenFile( const wxString& aFileName )
+{
+ wxFileName filename( aFileName );
+
+ if( filename.FileExists() )
+ {
+#if 0
+ // this pulls in EDA_DRAW_FRAME type info, which we don't want in
+ // the single_top link image.
+ KIWAY_PLAYER* frame = dynamic_cast<KIWAY_PLAYER*>( App().GetTopWindow() );
+#else
+ KIWAY_PLAYER* frame = (KIWAY_PLAYER*) App().GetTopWindow();
+#endif
+ if( frame )
+ frame->OpenProjectFiles( std::vector<wxString>( 1, aFileName ) );
+ }
+}