/*************************************************************************** * Copyright (C) 2021 PCSX-Redux authors * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "ZepEditor.h" #include #include <../GLFW/glfw3.h> #include "../imgui/imgui.h" #include "../zep/include/zep/regress.h" static float dpi_pixel_height_from_point_size(float pointSize, float pixelScaleY) { const auto fontDotsPerInch = 72.0f; auto inches = pointSize / fontDotsPerInch; return inches * (pixelScaleY * 96.0f); } ZepEditor::ZepEditor(const std::string& name) : m_editor(make_unique(new Zep::ZepDisplay_ImGui(), Zep::ZepPath(""), Zep::ZepEditorFlags::DisableThreads)) { m_editor->RegisterCallback(this); Zep::ZepRegressExCommand::Register(*m_editor); auto& config = m_editor->GetConfig(); config.autoHideCommandRegion = false; config.showNormalModeKeyStrokes = true; m_editor->InitWithText(name, "\n"); m_editor->SetGlobalMode(Zep::ZepMode_Standard::StaticName()); } void ZepEditor::draw() { //auto dpiScale = ImGui::GetWindowDpiScale(); //if (!m_dpiScale.has_value() || (m_dpiScale.value() != dpiScale)) { //m_dpiScale = dpiScale; //auto& display = m_editor->GetDisplay(); //display.SetPixelScale(Zep::NVec2f(dpiScale)); //int fontPixelHeight = (int)dpi_pixel_height_from_point_size(14.0f, dpiScale); //display.SetFont(Zep::ZepTextType::UI, std::make_shared(display, font, fontPixelHeight)); //display.SetFont(Zep::ZepTextType::Text, std::make_shared(display, font, fontPixelHeight)); //display.SetFont(Zep::ZepTextType::Heading1, // std::make_shared(display, font, int(fontPixelHeight * 1.75))); //display.SetFont(Zep::ZepTextType::Heading2, // std::make_shared(display, font, int(fontPixelHeight * 1.5))); //display.SetFont(Zep::ZepTextType::Heading3, // std::make_shared(display, font, int(fontPixelHeight * 1.25))); //} auto min = ImGui::GetCursorScreenPos(); auto max = ImGui::GetContentRegionAvail(); max.x = std::max(1.0f, max.x); max.y = std::max(1.0f, max.y); // Fill the window max.x = min.x + max.x; max.y = min.y + max.y; m_editor->SetDisplayRegion(Zep::NVec2f(min.x, min.y), Zep::NVec2f(max.x, max.y)); // Display the editor inside this window m_editor->Display(); auto& io = ImGui::GetIO(); if (io.MouseDelta.x != 0 || io.MouseDelta.y != 0) { m_editor->OnMouseMove(Zep::toNVec2f(io.MousePos)); } if (io.MouseClicked[0]) { if (m_editor->OnMouseDown(Zep::toNVec2f(io.MousePos), Zep::ZepMouseButton::Left)) { // Hide the mouse click from imgui if we handled it io.MouseClicked[0] = false; } } if (io.MouseClicked[1]) { if (m_editor->OnMouseDown(Zep::toNVec2f(io.MousePos), Zep::ZepMouseButton::Right)) { // Hide the mouse click from imgui if we handled it io.MouseClicked[0] = false; } } if (io.MouseReleased[0]) { if (m_editor->OnMouseUp(Zep::toNVec2f(io.MousePos), Zep::ZepMouseButton::Left)) { // Hide the mouse click from imgui if we handled it io.MouseClicked[0] = false; } } if (io.MouseReleased[1]) { if (m_editor->OnMouseUp(Zep::toNVec2f(io.MousePos), Zep::ZepMouseButton::Right)) { // Hide the mouse click from imgui if we handled it io.MouseClicked[0] = false; } } if (ImGui::IsWindowFocused()) { bool handled = false; uint32_t mod = 0; static std::map MapUSBKeys = { {GLFW_KEY_F1, Zep::ExtKeys::F1}, {GLFW_KEY_F2, Zep::ExtKeys::F2}, {GLFW_KEY_F3, Zep::ExtKeys::F3}, {GLFW_KEY_F4, Zep::ExtKeys::F4}, {GLFW_KEY_F5, Zep::ExtKeys::F5}, {GLFW_KEY_F6, Zep::ExtKeys::F6}, {GLFW_KEY_F7, Zep::ExtKeys::F7}, {GLFW_KEY_F8, Zep::ExtKeys::F8}, {GLFW_KEY_F9, Zep::ExtKeys::F9}, {GLFW_KEY_F10, Zep::ExtKeys::F10}, {GLFW_KEY_F11, Zep::ExtKeys::F11}, {GLFW_KEY_F12, Zep::ExtKeys::F12}, }; if (io.KeyCtrl) { mod |= Zep::ModifierKey::Ctrl; } if (io.KeyShift) { mod |= Zep::ModifierKey::Shift; } auto pWindow = m_editor->GetActiveTabWindow()->GetActiveWindow(); const auto& buffer = pWindow->GetBuffer(); // Check USB Keys for (auto& usbKey : MapUSBKeys) { if (ImGui::IsKeyPressed(usbKey.first)) { buffer.GetMode()->AddKeyPress(usbKey.second, mod); return; } } if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Tab))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::TAB, mod); return; } if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::ESCAPE, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::RETURN, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::DEL, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::HOME, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::END, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::BACKSPACE, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::RIGHT, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::LEFT, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::UP, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::DOWN, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::PAGEDOWN, mod); return; } else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp))) { buffer.GetMode()->AddKeyPress(Zep::ExtKeys::PAGEUP, mod); return; } else if (io.KeyCtrl) { if (ImGui::IsKeyPressed('1')) { m_editor->SetGlobalMode(Zep::ZepMode_Standard::StaticName()); handled = true; } else if (ImGui::IsKeyPressed('2')) { m_editor->SetGlobalMode(Zep::ZepMode_Vim::StaticName()); handled = true; } else { for (int ch = 'A'; ch <= 'Z'; ch++) { if (ImGui::IsKeyPressed(ch)) { buffer.GetMode()->AddKeyPress(ch - 'A' + 'a', mod); handled = true; } } if (ImGui::IsKeyPressed(GLFW_KEY_SPACE)) { buffer.GetMode()->AddKeyPress(' ', mod); handled = true; } } } if (!handled) { for (int n = 0; n < io.InputQueueCharacters.Size && io.InputQueueCharacters[n]; n++) { // Ignore '\r' - sometimes ImGui generates it! if (io.InputQueueCharacters[n] == '\r') continue; buffer.GetMode()->AddKeyPress(io.InputQueueCharacters[n], mod); } } } } void ZepEditor::Notify(std::shared_ptr message) { if (message->messageId == Zep::Msg::GetClipBoard) { const char* clip = ImGui::GetClipboardText(); message->str = clip ? clip : ""; message->handled = true; } else if (message->messageId == Zep::Msg::SetClipBoard) { ImGui::SetClipboardText(message->str.c_str()); message->handled = true; } else if (message->messageId == Zep::Msg::RequestQuit) { // hahano.gif } else if (message->messageId == Zep::Msg::ToolTip) { #if 0 auto spTipMsg = std::static_pointer_cast(message); if (spTipMsg->location.Valid() && spTipMsg->pBuffer) { auto pSyntax = spTipMsg->pBuffer->GetSyntax(); if (pSyntax) { if (pSyntax->GetSyntaxAt(spTipMsg->location).foreground == Zep::ThemeColor::Identifier) { auto spMarker = std::make_shared(*spTipMsg->pBuffer); spMarker->SetDescription("This is an identifier"); spMarker->SetHighlightColor(Zep::ThemeColor::Identifier); spMarker->SetTextColor(Zep::ThemeColor::Text); spTipMsg->spMarker = spMarker; spTipMsg->handled = true; } else if (pSyntax->GetSyntaxAt(spTipMsg->location).foreground == Zep::ThemeColor::Keyword) { auto spMarker = std::make_shared(*spTipMsg->pBuffer); spMarker->SetDescription("This is a keyword"); spMarker->SetHighlightColor(Zep::ThemeColor::Keyword); spMarker->SetTextColor(Zep::ThemeColor::Text); spTipMsg->spMarker = spMarker; spTipMsg->handled = true; } } } #endif } }