static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) { glfwSetClipboardString((GLFWwindow*)user_data, text); }
void TextFieldWidget::ProcessEvent(InputEvent & InputEvent) { // DECISION //if (CheckHover()) // HACK //if (HasTypingFocus()) /*{ // TEST if ( InputEvent.m_EventTypes.end() != InputEvent.m_EventTypes.find(InputEvent::EventType::POINTER_ACTIVATION) && ( InputEvent.m_EventTypes.end() != InputEvent.m_EventTypes.find(InputEvent::EventType::BUTTON_EVENT) && 0 == InputEvent.m_InputId && true == InputEvent.m_Buttons[0])) { InputEvent.m_Pointer->ModifyPointerMapping().RequestPointerCapture(&ModifyGestureRecognizer()); } } // DECISION // TEST // If captured by something else, ignore this event if ( nullptr != InputEvent.m_Pointer->GetPointerMapping().GetCapturer() && &GetGestureRecognizer() != InputEvent.m_Pointer->GetPointerMapping().GetCapturer()) { return; }*/ auto SelectionLength = std::max(m_CaretPosition, m_SelectionPosition) - std::min(m_CaretPosition, m_SelectionPosition); if (InputEvent.m_EventTypes.end() != InputEvent.m_EventTypes.find(InputEvent::EventType::BUTTON_EVENT)) { auto ButtonId = InputEvent.m_InputId; bool Pressed = InputEvent.m_Buttons[0]; // TODO: Check if there are >1 buttons if (Pointer::VirtualCategory::TYPING == InputEvent.m_Pointer->GetVirtualCategory()) { if (Pressed) { auto ShiftActive = ( InputEvent.m_Pointer->GetPointerState().GetButtonState(GLFW_KEY_LSHIFT) || InputEvent.m_Pointer->GetPointerState().GetButtonState(GLFW_KEY_RSHIFT)); auto SuperActive = ( InputEvent.m_Pointer->GetPointerState().GetButtonState(GLFW_KEY_LSUPER) || InputEvent.m_Pointer->GetPointerState().GetButtonState(GLFW_KEY_RSUPER)); auto AltActive = ( InputEvent.m_Pointer->GetPointerState().GetButtonState(GLFW_KEY_LALT) || InputEvent.m_Pointer->GetPointerState().GetButtonState(GLFW_KEY_RALT)); bool HandledEvent = true; // Assume true at first switch (ButtonId) { case GLFW_KEY_BACKSPACE: { auto SelectionExisted = EraseSelectionIfAny(); if (false == SelectionExisted) { if (m_CaretPosition > 0) { m_Content.erase(m_CaretPosition - 1, 1); UpdateContentLines(); MoveCaret(-1, true); } } } break; case GLFW_KEY_DEL: { auto SelectionExisted = EraseSelectionIfAny(); if (false == SelectionExisted) { if (m_CaretPosition < m_Content.length()) { m_Content.erase(m_CaretPosition, 1); UpdateContentLines(); } } } break; case GLFW_KEY_ENTER: case GLFW_KEY_KP_ENTER: { EraseSelectionIfAny(); m_Content.insert(m_CaretPosition, 1, '\n'); UpdateContentLines(); MoveCaret(+1, true); } break; case GLFW_KEY_TAB: { EraseSelectionIfAny(); m_Content.insert(m_CaretPosition, 1, '\t'); UpdateContentLines(); MoveCaret(+1, true); } break; case GLFW_KEY_LEFT: { if (0 != SelectionLength && !ShiftActive) { SetCaretPosition(std::min(m_CaretPosition, m_SelectionPosition), true); } else { if (SuperActive && !AltActive) { std::vector<class ContentLine>::size_type LineNumber = 0; std::vector<class ContentLine>::size_type ColumnNumber = 0; for (auto & ContentLine : m_ContentLines) { if (ContentLine.m_StartPosition + ContentLine.m_Length >= m_CaretPosition) { ColumnNumber = m_CaretPosition - ContentLine.m_StartPosition; break; } ++LineNumber; } SetCaretPosition(m_ContentLines[LineNumber].m_StartPosition, !ShiftActive); } else if (AltActive && !SuperActive) { { // Skip spaces to the left auto LookAt = m_CaretPosition - 1; while ( LookAt != -1 && !IsCoreCharacter(m_Content[LookAt])) { --LookAt; } // Skip non-spaces to the left while ( LookAt != -1 && IsCoreCharacter(m_Content[LookAt])) { --LookAt; } SetCaretPosition(LookAt + 1, !ShiftActive); } } else { MoveCaretTry(-1, !ShiftActive); } } } break; case GLFW_KEY_RIGHT: { if (0 != SelectionLength && !ShiftActive) { SetCaretPosition(std::max(m_CaretPosition, m_SelectionPosition), true); } else { if (SuperActive && !AltActive) { std::vector<class ContentLine>::size_type LineNumber = 0; std::vector<class ContentLine>::size_type ColumnNumber = 0; for (auto & ContentLine : m_ContentLines) { if (ContentLine.m_StartPosition + ContentLine.m_Length >= m_CaretPosition) { ColumnNumber = m_CaretPosition - ContentLine.m_StartPosition; break; } ++LineNumber; } SetCaretPosition(m_ContentLines[LineNumber].m_StartPosition + m_ContentLines[LineNumber].m_Length, !ShiftActive); } else if (AltActive && !SuperActive) { { // Skip spaces to the right auto LookAt = m_CaretPosition; while ( LookAt < m_Content.length() && !IsCoreCharacter(m_Content[LookAt])) { ++LookAt; } // Skip non-spaces to the right while ( LookAt < m_Content.length() && IsCoreCharacter(m_Content[LookAt])) { ++LookAt; } SetCaretPosition(LookAt, !ShiftActive); } } else { MoveCaretTry(+1, !ShiftActive); } } } break; case GLFW_KEY_UP: { if (0 != SelectionLength && !ShiftActive) { SetCaretPosition(std::min(m_CaretPosition, m_SelectionPosition), true); } if (SuperActive) { SetCaretPosition(0, !ShiftActive); // Go to home } else { MoveCaretVerticallyTry(-1, !ShiftActive); } } break; case GLFW_KEY_DOWN: { if (0 != SelectionLength && !ShiftActive) { SetCaretPosition(std::max(m_CaretPosition, m_SelectionPosition), true); } if (SuperActive) { SetCaretPosition(m_Content.length(), !ShiftActive); // Go to end } else { MoveCaretVerticallyTry(+1, !ShiftActive); } } break; case 'A': { if (SuperActive) { // Select all SetCaretPosition(0, true); SetCaretPosition(m_Content.length(), false); } } break; case 'X': { if (SuperActive) { if (!GetSelectionContent().empty()) { #if DECISION_USE_CLIPBOARD_INSTEAD_OF_TypingModule glfwSetClipboardString(GetSelectionContent()); #else m_TypingModule.SetString(GetSelectionContent()); #endif EraseSelectionIfAny(); } } } break; case 'C': { if (SuperActive) { if (!GetSelectionContent().empty()) { #if DECISION_USE_CLIPBOARD_INSTEAD_OF_TypingModule glfwSetClipboardString(GetSelectionContent()); #else m_TypingModule.SetString(GetSelectionContent()); #endif } } } break; case 'V': { if (SuperActive) { if (!glfwGetClipboardString().empty()) { EraseSelectionIfAny(); #if DECISION_USE_CLIPBOARD_INSTEAD_OF_TypingModule m_Content.insert(m_CaretPosition, glfwGetClipboardString()); UpdateContentLines(); MoveCaret(static_cast<sint32>(glfwGetClipboardString().length()), true); #else auto Entry = m_TypingModule.TakeString(); m_Content.insert(m_CaretPosition, Entry); UpdateContentLines(); MoveCaret(static_cast<sint32>(Entry.length()), true); #endif } } } break; default: HandledEvent = false; break; } if (HandledEvent) { InputEvent.m_Handled = true; } } } else if (Pointer::VirtualCategory::POINTING == InputEvent.m_Pointer->GetVirtualCategory()) { if (Pressed) { switch (ButtonId) { case 0: { Vector2n GlobalPosition(InputEvent.m_Pointer->GetPointerState().GetAxisState(0).GetPosition(), InputEvent.m_Pointer->GetPointerState().GetAxisState(1).GetPosition()); Vector2n LocalPosition = GlobalToLocal(GlobalPosition); LocalPosition = m_TypingModule.GetInsertionPosition(LocalPosition); auto CaretPosition = GetNearestCaretPosition(LocalPosition); auto ShiftActive = g_InputManager->m_TypingPointer->GetPointerState().GetButtonState(GLFW_KEY_LSHIFT) || g_InputManager->m_TypingPointer->GetPointerState().GetButtonState(GLFW_KEY_RSHIFT); SetCaretPosition(CaretPosition, !ShiftActive); { auto Entry = m_TypingModule.TakeString(); if (!Entry.empty()) { m_Content.insert(m_CaretPosition, Entry); UpdateContentLines(); SetCaretPosition(GetNearestCaretPosition(LocalPosition), true); } } } break; default: break; } } } } if ( InputEvent.m_EventTypes.end() != InputEvent.m_EventTypes.find(InputEvent::EventType::AXIS_EVENT) || InputEvent.m_EventTypes.end() != InputEvent.m_EventTypes.find(InputEvent::EventType::CANVAS_MOVED_TEST)) { if (Pointer::VirtualCategory::POINTING == InputEvent.m_Pointer->GetVirtualCategory()) { if (true == InputEvent.m_Pointer->GetPointerState().GetButtonState(0)) { Vector2n GlobalPosition(InputEvent.m_Pointer->GetPointerState().GetAxisState(0).GetPosition(), InputEvent.m_Pointer->GetPointerState().GetAxisState(1).GetPosition()); Vector2n LocalPosition = GlobalToLocal(GlobalPosition); auto CaretPosition = GetNearestCaretPosition(LocalPosition); SetCaretPosition(CaretPosition, false); } } } }
static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) { glfwSetClipboardString(g_Window, text); }
TextFileWidget::TextFileWidget(Vector2n Position, std::string Path, TypingModule & TypingModule) : FlowLayoutWidget(Position, { std::shared_ptr<Widget>(new FlowLayoutWidget(Vector2n::ZERO, { std::shared_ptr<Widget>(m_FileMinimizeToggle = new ToggleWidget(Vector2n::ZERO, Vector2n(12, 12), [](bool State) { if (!State) g_InputManager->RequestTypingPointer(*static_cast<GestureRecognizer *>(nullptr)); }, true)), std::shared_ptr<Widget>(new LabelWidget(Vector2n(0, -lineHeight - 2), Path, LabelWidget::Background::Normal)) }, {})), std::shared_ptr<Widget>(m_TextFieldWidget = new TextFieldWidget(Vector2n::ZERO, TypingModule)) }, { std::shared_ptr<Behavior>(new DraggablePositionBehavior(*this)) }, FlowLayoutWidget::LayoutType::Vertical), m_Path(Path) { m_TextFieldWidget->SetContent(FromFileToString(Path)); m_OnChange = [=]() // Saving takes place in TextFileWidget when it gets its NotifyChange() from the contained TextFieldWidget { //PlayBeep(); //printf("Saving '%s'.\n", Path.c_str()); // Write to file WriteToFile(Path, m_TextFieldWidget->GetContent()); }; const std::string Folder = ParsePath(Path, 0); const std::string Filename = ParsePath(Path, 1); auto CopyPath = [this, &TypingModule]() { #if DECISION_USE_CLIPBOARD_INSTEAD_OF_TypingModule glfwSetClipboardString(this->m_Path); #else TypingModule.SetString(this->m_Path); #endif }; ModifyGestureRecognizer().AddShortcut(GestureRecognizer::ShortcutEntry('I', PointerState::Modifiers::Super, CopyPath, "Copy Path")); // TEST: Line Gutters #if 0 //if ("./Gen/5086673/gistfile1.go" == Path) m_TextFieldWidget->m_GetLineGutters = [=](uint32 LineNumber) -> std::string { #if 0 std::string x = "."; Ls(x); return std::to_string(LineNumber + 1); #endif // HACK: Pass file folder and name info if (0 == LineNumber) return Folder; else if (1 == LineNumber) return Filename; else throw 0; }; #endif if (IsFileTrackedByGit(Path)) { auto GitDiff = new GitDiffWidget(Vector2n::ZERO, TypingModule, this); GitDiff->RemoveAllBehaviors(); AddWidget(GitDiff); auto GitCommit = new ButtonWidget(Vector2n(-160, -350), [=, &TypingModule]() { auto Shell = std::unique_ptr<ShellWidget>(new ShellWidget(Vector2n::ZERO, TypingModule)); std::string Command = "cd \'" + Folder + "\'\ngit commit --allow-empty-message -m '' -- \'" + Filename + "\'"; Command += "\ngit push origin master"; Shell->m_CommandWidget->SetContent(Command); Shell->m_ExecuteWidget->GetAction()(); this->NotifyExternalChange(); // Do this to triger potential GitDiffWidget, GitStatusWidget, etc. //std::cerr << "Commit & Push: '" << Folder << "' folder and '" << Filename << "' file.\n"; std::cerr << Shell->m_OutputWidget->GetContent() << endl; }, "Commit & Push"); AddWidget(GitCommit); } m_TextFieldWidget->m_MinimizeToggle = m_FileMinimizeToggle; }