src/glbackend_wxwidgets.cpp
8c34841f
 /// Guards
 
 
 #ifdef GLBACKEND_WXWIDGETS
 
 
 /// Includes
 
 
 #include <glbackend_wxwidgets.hpp>
 
 #include <array>
 #include <sstream>
 #include <string>
 #include <utility>
 #include <vector>
 
 #include <glbase.hpp>
 #include <glbackend.hpp>
 
 // #include <wx/wx.h>
 #include <wx/app.h>
 #include <wx/defs.h>
 #include <wx/display.h>
 #include <wx/event.h>
 #include <wx/frame.h>
 #include <wx/glcanvas.h>
 #include <wx/init.h>
 #include <wx/platinfo.h>
 #include <wx/string.h>
 #include <wx/tbarbase.h>
 #include <wx/toplevel.h>
 #include <wx/utils.h>
 #include <wx/version.h>
 #include <wx/versioninfo.h>
 #include <wx/vidmode.h>
 #include <wx/window.h>
 #include <wx/windowid.h>
 
 // NOLINTNEXTLINE
 #define STR_EXCEPTION GLBase::Exception
 #include <str.hpp>
 
 
 
 namespace
 {
 class Canvas : public wxGLCanvas
 {
 
 public:
 
     Canvas(
         wxWindow      * parent,
         wxWindowID      id,
         int     const * attribs,
         wxPoint const & pos,
         wxSize  const & size
     )
     :
         wxGLCanvas(parent, id, attribs, pos, size)
     {}
 
 protected:
 
     // TODO(rcrnstn): Implement wxWidgets event handling.
     // void paint_(wxPaintEvent& event);
     // void size_(wxSizeEvent& event);
     // void char_(wxKeyEvent& event);
     // void mouse_event_(wxMouseEvent& event);
     // void exit_(wxCommandEvent& event);
     wxDECLARE_EVENT_TABLE(); // NOLINT
 
 };
 }
 
 
 // TODO(rcrnstn): Implement wxWidgets event handling.
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
 wxBEGIN_EVENT_TABLE(Canvas, wxGLCanvas) // NOLINT
 //     EVT_PAINT(Canvas::paint_)
 wxEND_EVENT_TABLE() // NOLINT
 #pragma GCC diagnostic pop
 
 
 GLBackendWxWidgets::GLBackendWxWidgets(
     std::string const & title,
     std::array<int, 2>  size,
     std::array<int, 2>  version,
     int                 samples,
     bool                fullscreen,
     bool                transparent
 )
 :
     GLBackend(),
     app_       {nullptr},
     frame_     {nullptr},
     canvas_    {nullptr},
     context_   {nullptr},
     event_loop_{},
     time_      {0.0F},
     locked_    {false}
 {
     // Backend init
     if (!wxApp::GetInstance())
     {
         wxDISABLE_DEBUG_SUPPORT();
 
         wxApp::SetInitializerFunction([]()
         {
             // cppcheck-suppress cstyleCast
             return (wxAppConsole *)new wxApp;
         });
 
         auto argc = int{0};
         auto argv = std::array<char *, 1>{{nullptr}};
         if (!wxEntryStart(argc, &argv[0]))
             STR_THROW("Failed to initialize wxWidgets.");
 
         app_ = wxApp::GetInstance();
         app_->OnInit();
     }
 
     // Window options
     auto frame_style = long{0}; // NOLINT
     frame_style |= wxDEFAULT_FRAME_STYLE; // NOLINT
     frame_style &= ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX); // NOLINT
     frame_style |= wxWANTS_CHARS; // NOLINT
     if (transparent)
     {
         frame_style &= ~wxDEFAULT_FRAME_STYLE; // NOLINT
         frame_style |= wxSTAY_ON_TOP; // NOLINT
     }
     if (size[0] == 0 || size[1] == 0)
     {
         auto const mode = wxDisplay(0).GetCurrentMode();
         size[0] = mode.GetWidth();
         size[1] = mode.GetHeight();
     }
     size_ = size;
 
     // Context options
     auto canvas_attribs = std::vector<int>{};
     //NOLINTNEXTLINE
     #define GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_(...) \
         canvas_attribs.insert(canvas_attribs.end(), __VA_ARGS__);
     GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
         WX_GL_RGBA,
         WX_GL_DOUBLEBUFFER,
         WX_GL_MIN_RED, 8,
         WX_GL_MIN_GREEN, 8,
         WX_GL_MIN_BLUE, 8,
         WX_GL_MIN_ALPHA, 8,
         WX_GL_DEPTH_SIZE, 24,
         WX_GL_STENCIL_SIZE, 8,
     })
     if (samples)
         GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
             WX_GL_SAMPLE_BUFFERS, 1,
             WX_GL_SAMPLES, samples,
         })
     if (version[0])
         GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
             WX_GL_MAJOR_VERSION, version[0],
         })
     if (version[1])
         GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
             WX_GL_MINOR_VERSION, version[1],
         })
     if ((version[0] == 3 && version[1] >= 2) || version[0] >= 4) // NOLINT
         GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
             WX_GL_CORE_PROFILE,
         })
     GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
         0
     });
 
     try
     {
         // Frame
         frame_ = new wxFrame(); // NOLINT
         if (transparent)
             frame_->SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
         frame_->Create(
             nullptr,
             wxID_ANY,
             title,
             wxDefaultPosition,
             wxDefaultSize,
             frame_style
         );
         frame_->SetClientSize(size[0], size[1]);
         if (fullscreen)
             frame_->ShowFullScreen(true);
         else
             frame_->Show(true);
 
         // Canvas
         canvas_ = new Canvas{ // NOLINT
             frame_,
             wxID_ANY,
             &canvas_attribs[0],
             wxDefaultPosition,
             {size[0], size[1]},
         };
 
         // Context
         context_ = new wxGLContext(canvas_); // NOLINT
         events(); // NOLINT
         context_->SetCurrent(*canvas_);
         init_();
 
         // Lock
         if (fullscreen)
             lock(true);
     }
     catch (...)
     {
         destroy_();
         throw;
     }
 }
 
 
 GLBackendWxWidgets::~GLBackendWxWidgets()
 {
     destroy_();
 }
 
 
 std::string GLBackendWxWidgets::debug_info() const
 {
     auto ostream = std::ostringstream{};
 
     auto version_compiled = wxGetLibraryVersionInfo().GetVersionString();
     auto version_linked   = wxString(wxVERSION_STRING);
     auto os               = wxGetOsDescription();
     auto port             = wxPlatformInfo::Get().GetPortIdName();
     debug_info_(ostream, "wxWidgets", {
         {"VERSION_COMPILED", version_compiled.ToStdString()},
         {"VERSION_LINKED",   version_linked  .ToStdString()},
         {"OS",               os              .ToStdString()},
         {"PORT",             port            .ToStdString()},
     });
 
     ostream << GLBackend::debug_info();
 
     return ostream.str();
 }
 
 
 // TODO(rcrnstn): Implement wxWidgets event handling.
 // void GLBackendWxWidgets::paint_(wxPaintEvent& WXUNUSED(event))
 // {
 //     wxPaintDC paint_dc(this);
 //     if (render_)
 //         render_();
 // }
 
 
 void GLBackendWxWidgets::destroy_()
 {
     delete context_;
     if (canvas_)
     {
         lock(false);
         canvas_->Destroy();
     }
     if (frame_)
         frame_->Destroy();
     events(); // NOLINT
     if (app_)
     {
         app_->OnExit();
         wxEntryCleanup();
     }
 }
 
 
 /// Guards
 
 
 #endif