| 
							- /*
 -  * DISTRHO Plugin Framework (DPF)
 -  * Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru>
 -  *
 -  * Permission to use, copy, modify, and/or distribute this software for any purpose with
 -  * or without fee is hereby granted, provided that the above copyright notice and this
 -  * permission notice appear in all copies.
 -  *
 -  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
 -  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
 -  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 -  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 -  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 -  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 -  */
 - 
 - #include "Application.hpp"
 - 
 - #include <GL/glew.h>
 - 
 - #include "ImGuiUI.hpp"
 - #include <imgui.h>
 - #if !defined(IMGUI_GL2) && !defined(IMGUI_GL3)
 - # define IMGUI_GL2 1
 - #endif
 - #if defined(IMGUI_GL2)
 - # include <imgui_impl_opengl2.h>
 - #elif defined(IMGUI_GL3)
 - # include <imgui_impl_opengl3.h>
 - #endif
 - #include <chrono>
 - #include <cmath>
 - 
 - START_NAMESPACE_DGL
 - 
 - struct ImGuiUI::Impl
 - {
 -     explicit Impl(ImGuiUI* self);
 -     ~Impl();
 - 
 -     void setupGL();
 -     void cleanupGL();
 - 
 -     static int mouseButtonToImGui(int button);
 - 
 -     ImGuiUI* fSelf = nullptr;
 -     ImGuiContext* fContext = nullptr;
 -     Color fBackgroundColor{0.25f, 0.25f, 0.25f};
 -     int fRepaintIntervalMs = 15;
 - 
 -     using Clock = std::chrono::steady_clock;
 -     Clock::time_point fLastRepainted;
 -     bool fWasEverPainted = false;
 - };
 - 
 - ImGuiUI::ImGuiUI(Window& windowToMapTo)
 -     : TopLevelWidget(windowToMapTo),
 -       fImpl(new ImGuiUI::Impl(this))
 - {
 -     getApp().addIdleCallback(this);
 - }
 - 
 - ImGuiUI::~ImGuiUI()
 - {
 -     delete fImpl;
 - }
 - 
 - void ImGuiUI::setBackgroundColor(Color color)
 - {
 -     fImpl->fBackgroundColor = color;
 - }
 - 
 - void ImGuiUI::setRepaintInterval(int intervalMs)
 - {
 -     fImpl->fRepaintIntervalMs = intervalMs;
 - }
 - 
 - void ImGuiUI::onDisplay()
 - {
 -     ImGui::SetCurrentContext(fImpl->fContext);
 - 
 - #if defined(IMGUI_GL2)
 -     ImGui_ImplOpenGL2_NewFrame();
 - #elif defined(IMGUI_GL3)
 -     ImGui_ImplOpenGL3_NewFrame();
 - #endif
 - 
 -     ImGui::NewFrame();
 -     onImGuiDisplay();
 -     ImGui::Render();
 - 
 -     ImGuiIO &io = ImGui::GetIO();
 - 
 -     glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
 - 
 -     Color backgroundColor = fImpl->fBackgroundColor;
 -     glClearColor(
 -         backgroundColor.red, backgroundColor.green,
 -         backgroundColor.blue, backgroundColor.alpha);
 -     glClear(GL_COLOR_BUFFER_BIT);
 -     glLoadIdentity();
 - 
 - #if defined(IMGUI_GL2)
 -     ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
 - #elif defined(IMGUI_GL3)
 -     ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
 - #endif
 - 
 -     fImpl->fLastRepainted = Impl::Clock::now();
 -     fImpl->fWasEverPainted = true;
 - }
 - 
 - bool ImGuiUI::onKeyboard(const KeyboardEvent& event)
 - {
 -     ImGui::SetCurrentContext(fImpl->fContext);
 -     ImGuiIO &io = ImGui::GetIO();
 - 
 -     if (event.press)
 -         io.AddInputCharacter(event.key);
 - 
 -     int imGuiKey = event.key;
 -     if (imGuiKey >= 0 && imGuiKey < 128)
 -     {
 -         if (imGuiKey >= 'a' && imGuiKey <= 'z')
 -             imGuiKey = imGuiKey - 'a' + 'A';
 -         io.KeysDown[imGuiKey] = event.press;
 -     }
 - 
 -     return io.WantCaptureKeyboard;
 - }
 - 
 - bool ImGuiUI::onSpecial(const SpecialEvent& event)
 - {
 -     ImGui::SetCurrentContext(fImpl->fContext);
 -     ImGuiIO &io = ImGui::GetIO();
 - 
 -     int imGuiKey = IM_ARRAYSIZE(io.KeysDown) - event.key;
 -     io.KeysDown[imGuiKey] = event.press;
 - 
 -     switch (event.key)
 -     {
 -     case kKeyShift:
 -         io.KeyShift = event.press;
 -         break;
 -     case kKeyControl:
 -         io.KeyCtrl = event.press;
 -         break;
 -     case kKeyAlt:
 -         io.KeyAlt = event.press;
 -         break;
 -     case kKeySuper:
 -         io.KeySuper = event.press;
 -         break;
 -     default:
 -         break;
 -     }
 - 
 -     return io.WantCaptureKeyboard;
 - }
 - 
 - bool ImGuiUI::onMouse(const MouseEvent& event)
 - {
 -     ImGui::SetCurrentContext(fImpl->fContext);
 -     ImGuiIO &io = ImGui::GetIO();
 - 
 -     int imGuiButton = Impl::mouseButtonToImGui(event.button);
 -     if (imGuiButton != -1)
 -         io.MouseDown[imGuiButton] = event.press;
 - 
 -     return io.WantCaptureMouse;
 - }
 - 
 - bool ImGuiUI::onMotion(const MotionEvent& event)
 - {
 -     ImGui::SetCurrentContext(fImpl->fContext);
 -     ImGuiIO &io = ImGui::GetIO();
 - 
 -     // FIXME
 -     const double scaleFactor = 1; // getScaleFactor();
 -     io.MousePos.x = std::round(scaleFactor * event.pos.getX());
 -     io.MousePos.y = std::round(scaleFactor * event.pos.getY());
 - 
 -     return false;
 - }
 - 
 - bool ImGuiUI::onScroll(const ScrollEvent& event)
 - {
 -     ImGui::SetCurrentContext(fImpl->fContext);
 -     ImGuiIO &io = ImGui::GetIO();
 - 
 -     io.MouseWheel += event.delta.getY();
 -     io.MouseWheelH += event.delta.getX();
 - 
 -     return io.WantCaptureMouse;
 - }
 - 
 - void ImGuiUI::onResize(const ResizeEvent& event)
 - {
 -     TopLevelWidget::onResize(event);
 - 
 -     const uint width = event.size.getWidth();
 -     const uint height = event.size.getHeight();
 - 
 -     ImGui::SetCurrentContext(fImpl->fContext);
 -     ImGuiIO &io = ImGui::GetIO();
 - 
 -     const double scaleFactor = getScaleFactor();
 -     io.DisplaySize.x = std::round(scaleFactor * width);
 -     io.DisplaySize.y = std::round(scaleFactor * height);
 - }
 - 
 - void ImGuiUI::idleCallback()
 - {
 -     bool shouldRepaint;
 - 
 -     if (fImpl->fWasEverPainted)
 -     {
 -         Impl::Clock::duration elapsed =
 -             Impl::Clock::now() - fImpl->fLastRepainted;
 -         std::chrono::milliseconds elapsedMs =
 -             std::chrono::duration_cast<std::chrono::milliseconds>(elapsed);
 -         shouldRepaint = elapsedMs.count() > fImpl->fRepaintIntervalMs;
 -     }
 -     else
 -     {
 -         shouldRepaint = true;
 -     }
 - 
 -     if (shouldRepaint)
 -         repaint();
 - }
 - 
 - ImGuiUI::Impl::Impl(ImGuiUI* self)
 -     : fSelf(self)
 - {
 -     setupGL();
 - }
 - 
 - ImGuiUI::Impl::~Impl()
 - {
 -     cleanupGL();
 - }
 - 
 - void ImGuiUI::Impl::setupGL()
 - {
 -     DISTRHO_SAFE_ASSERT_RETURN(glewInit() == 0,);
 - 
 -     IMGUI_CHECKVERSION();
 -     fContext = ImGui::CreateContext();
 -     ImGui::SetCurrentContext(fContext);
 - 
 -     ImGuiIO &io = ImGui::GetIO();
 -     const double scaleFactor = fSelf->getScaleFactor();
 -     io.DisplaySize.x = std::round(scaleFactor * fSelf->getWidth());
 -     io.DisplaySize.y = std::round(scaleFactor * fSelf->getHeight());
 -     io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
 -     io.IniFilename = nullptr;
 - 
 -     io.KeyMap[ImGuiKey_Tab] = '\t';
 -     io.KeyMap[ImGuiKey_LeftArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyLeft;
 -     io.KeyMap[ImGuiKey_RightArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyRight;
 -     io.KeyMap[ImGuiKey_UpArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyUp;
 -     io.KeyMap[ImGuiKey_DownArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyDown;
 -     io.KeyMap[ImGuiKey_PageUp] = IM_ARRAYSIZE(io.KeysDown) - kKeyPageUp;
 -     io.KeyMap[ImGuiKey_PageDown] = IM_ARRAYSIZE(io.KeysDown) - kKeyPageDown;
 -     io.KeyMap[ImGuiKey_Home] = IM_ARRAYSIZE(io.KeysDown) - kKeyHome;
 -     io.KeyMap[ImGuiKey_End] = IM_ARRAYSIZE(io.KeysDown) - kKeyEnd;
 -     io.KeyMap[ImGuiKey_Insert] = IM_ARRAYSIZE(io.KeysDown) - kKeyInsert;
 -     io.KeyMap[ImGuiKey_Delete] = 127;
 -     io.KeyMap[ImGuiKey_Backspace] = '\b';
 -     io.KeyMap[ImGuiKey_Space] = ' ';
 -     io.KeyMap[ImGuiKey_Enter] = '\r';
 -     io.KeyMap[ImGuiKey_Escape] = 27;
 -     io.KeyMap[ImGuiKey_A] = 'A';
 -     io.KeyMap[ImGuiKey_C] = 'C';
 -     io.KeyMap[ImGuiKey_V] = 'V';
 -     io.KeyMap[ImGuiKey_X] = 'X';
 -     io.KeyMap[ImGuiKey_Y] = 'Y';
 -     io.KeyMap[ImGuiKey_Z] = 'Z';
 - 
 - #if defined(IMGUI_GL2)
 -     ImGui_ImplOpenGL2_Init();
 - #elif defined(IMGUI_GL3)
 -     ImGui_ImplOpenGL3_Init();
 - #endif
 - }
 - 
 - void ImGuiUI::Impl::cleanupGL()
 - {
 -     ImGui::SetCurrentContext(fContext);
 - #if defined(IMGUI_GL2)
 -     ImGui_ImplOpenGL2_Shutdown();
 - #elif defined(IMGUI_GL3)
 -     ImGui_ImplOpenGL3_Shutdown();
 - #endif
 -     ImGui::DestroyContext(fContext);
 - }
 - 
 - int ImGuiUI::Impl::mouseButtonToImGui(int button)
 - {
 -     switch (button)
 -     {
 -     default:
 -         return -1;
 -     case 1:
 -         return 0;
 -     case 2:
 -         return 2;
 -     case 3:
 -         return 1;
 -     }
 - }
 - 
 - END_NAMESPACE_DGL
 
 
  |