Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

AidanSun05/ImGuiTextSelect

Open more actions menu

Repository files navigation

ImGuiTextSelect

This is a text selection implementation for Dear ImGui, originally part of WhaleConnect.

Released under the MIT License.

Demo

Features

  • Double-click: Select word
  • Triple-click: Select line
  • Shift-click: Select range
  • Keyboard shortcuts for copy (Ctrl+C/Cmd+C) and select all (Ctrl+A/Cmd+A)
  • Automatic scrolling for selecting text outside the window's visible area
  • Integration in context menus
  • UTF-8 text support
  • Word wrapping support

Dependencies

Integration

Copy textselect.cpp and textselect.hpp into your project, and update your build settings to compile textselect.cpp.

To apply text selection to a window:

  1. #include "textselect.hpp"
  2. Create a TextSelect instance for your window
  3. Call .update() on your TextSelect instance in your window's render loop

See below for an example.

Notes

  • Only left-to-right text is supported
  • Double-click selection only handles word boundary characters in Latin Unicode blocks
  • You should have ImGuiWindowFlags_NoMove set in either your window or a child window containing the text so mouse drags can be used to select text instead of moving the window
  • The accessor functions (getLineAtIdx, getNumLines) should not contain side effects or heavy computations as they can potentially be called multiple times per frame

ImGuiTextSelect works well for text-only windows such as a console/log output or code display.

Some discussion on highlightable text in Dear ImGui: GitHub issue

Example Usage

See the example code for a full program using ImGuiTextSelect. The example can be compiled with either the CMake or xmake build system.

#include <string_view>
#include <vector>

#include "textselect.hpp"

// ---------- At the beginning of your program: ----------

// The lines to show in the window
// You will need to supply TextSelect instances with functions that:
//   1. Take a line number (starting from 0) and return that line in an
//      std::string_view
//   2. Return the total number of lines in the window
// A vector is a convenient way to fulfill the above requirements, but you may
// use whatever you like.
std::vector<std::string_view> lines{
    "Line 1",
    "Line 2",
    "Line 3",
    "A longer line",
    "Text selection in Dear ImGui",
    "UTF-8 characters Ë ⑤ 三【 】┌──┐"
};

std::string_view getLineAtIdx(std::size_t idx) {
    return lines[idx];
}

std::size_t getNumLines() {
    return lines.size();
}

// Create a TextSelect instance. This takes an optional third bool parameter to
// enable word wrapping (disabled by default; pass true to enable).
TextSelect textSelect{ getLineAtIdx, getNumLines };

// ------------------------- In the main render loop: -------------------------

// Create a window to contain the text
ImGui::SetNextWindowSize({ 300, 200 });
ImGui::Begin("Text selection");

// Create a child window with the "NoMove" flag
// This allows mouse drags to select text (instead of moving the window), while
// still allowing the window to be moved from the title bar.
ImGui::BeginChild("text", {}, 0, ImGuiWindowFlags_NoMove);

// Display each line
for (const auto& line : lines) {
    ImGui::TextUnformatted(line.data());

    // If word wrapping is enabled, call this instead:
    // ImGui::TextWrapped("%s", line.data());
}

// Update TextSelect instance (all text selection is handled in this method)
textSelect.update();

// Register a context menu (optional)
// The TextSelect class provides the hasSelection, copy, selectAll, and
// clearSelection methods for manual control.
if (ImGui::BeginPopupContextWindow()) {
    ImGui::BeginDisabled(!textSelect.hasSelection());
    if (ImGui::MenuItem("Copy", "Ctrl+C")) {
        textSelect.copy();
    }
    ImGui::EndDisabled();

    if (ImGui::MenuItem("Select all", "Ctrl+A")) {
        textSelect.selectAll();
    }

    if (ImGui::MenuItem("Clear selection")) {
        textSelect.clearSelection();
    }
    ImGui::EndPopup();
}

ImGui::EndChild();
ImGui::End();

About

Text selection implementation for Dear ImGui

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Morty Proxy This is a proxified and sanitized view of the page, visit original site.