//------------------------------------------------------------------------------
// emGUIFramework.h
//
// Copyright (C) 2007-2008,2011,2016 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// 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 version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#ifndef emGUIFramework_h
#define emGUIFramework_h

#ifndef emScreen_h
#include <emCore/emScreen.h>
#endif


//==============================================================================
//============================ MAIN_OR_WINMAIN_HERE ============================
//==============================================================================

// The macro MAIN_OR_WINMAIN_HERE implements the normal main function or the
// Windows WinMain function. It calls the static function wrapped_main, which
// has to be defined by the application programmer. Example usage:
//
//   MAIN_OR_WINMAIN_HERE
//
//   static int wrapped_main(int argc, char * argv[])
//   {
//     ...
//   }

#if defined(_WIN32) && !defined(__CYGWIN__)
#       ifndef _INC_WINDOWS
#               include <windows.h>
#       endif
#       define MAIN_OR_WINMAIN_HERE \
                static int wrapped_main(int argc, char * argv[]); \
                int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int) \
                { \
                        return wrapped_main(__argc,__argv); \
                }
#else
#       define MAIN_OR_WINMAIN_HERE \
                static int wrapped_main(int argc, char * argv[]); \
                int main(int argc, char * argv[]) \
                { \
                        return wrapped_main(argc,argv); \
                }
#endif


//==============================================================================
//=============================== emGUIFramework ===============================
//==============================================================================

class emGUIFramework {

public:

        // Framework for a program with graphical user interface. An object of
        // this class has an emScheduler and an emRootContext with an emScreen
        // and an emClipboard installed. Besides, the constructor calls
        // emSetFatalErrorGraphical(true).

        emGUIFramework();
                // Constructor.

        virtual ~emGUIFramework();
                // Destructor.

        emScheduler & GetScheduler() const;
                // Get the scheduler.

        emRootContext & GetRootContext() const;
                // Get the root context. It has an emScreen and an emClipboard.

        void EnableAutoTermination(bool autoTermination=true);
                // Whether to call GetScheduler().InitiateTermination(0)
                // automatically when the last window has been destructed.

        int Run();
                // Same as GetScheduler().Run()

private:

        class AutoTerminatorClass : public emEngine {
        public:
                AutoTerminatorClass(emRootContext & rootContext);
                virtual ~AutoTerminatorClass();
        protected:
                virtual bool Cycle();
        private:
                emRef<emScreen> Screen;
        };

        emScheduler * Scheduler;
        emRootContext * RootContext;
        AutoTerminatorClass * AutoTerminator;
};

inline emScheduler & emGUIFramework::GetScheduler() const
{
        return *Scheduler;
}

inline emRootContext & emGUIFramework::GetRootContext() const
{
        return *RootContext;
}

inline int emGUIFramework::Run()
{
        return Scheduler->Run();
}


#endif