forked from AidanSun05/ImGuiTextSelect
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtextselect.hpp
More file actions
executable file
·103 lines (81 loc) · 3.71 KB
/
textselect.hpp
File metadata and controls
executable file
·103 lines (81 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2024-2025 Aidan Sun and the ImGuiTextSelect contributors
// SPDX-License-Identifier: MIT
#pragma once
#include <cstddef>
#include <functional>
#include <string_view>
#include <imgui.h>
// Manages text selection in a GUI window.
// This class only works if the window only has text.
// The window should also have the "NoMove" flag set so mouse drags can be used to select text.
class TextSelect {
// Cursor position in the window.
struct CursorPos {
std::size_t x = std::string_view::npos; // X index of character
std::size_t y = std::string_view::npos; // Y index of character
// Checks if this position is invalid.
bool isInvalid() const {
// Invalid cursor positions are indicated by std::string_view::npos
return x == std::string_view::npos || y == std::string_view::npos;
}
};
// Text selection in the window.
// Y - index of _whole_ line.
// X - character index relative to beginning of that whole line.
struct Selection {
std::size_t startX;
std::size_t startY;
std::size_t endX;
std::size_t endY;
};
struct SubLine {
std::string_view string;
std::size_t wholeLineIndex; // Which whole line this subline belongs to.
};
// Selection bounds
// In a selection, the start and end positions may not be in order (the user can click and drag left/up which
// reverses start and end).
CursorPos selectStart;
CursorPos selectEnd;
// Accessor functions to get line information
// This class only knows about line numbers so it must be provided with functions that give it text data.
std::function<std::string_view(std::size_t)> getLineAtIdx; // Gets the string given a line number
std::function<std::size_t()> getNumLines; // Gets the total number of lines
// Indicates whether selection should be updated. This is needed for distinguishing mouse drags that are
// initiated by clicking the text, or different element.
bool shouldHandleMouseDown = false;
// Indicates whether text selection with word wrapping should be enabled.
bool enableWordWrap;
// Gets the user selection. Start and end are guaranteed to be in order.
Selection getSelection() const;
// Splits all whole lines by wrap width if wrapping is enabled. Otherwise returns whole lines.
ImVector<SubLine> getSubLines() const;
// Processes mouse down (click/drag) events.
void handleMouseDown(const ImVector<TextSelect::SubLine>& subLines, const ImVec2& cursorPosStart);
// Processes scrolling events.
void handleScrolling() const;
// Draws the text selection rectangle in the window.
void drawSelection(const ImVector<TextSelect::SubLine>& subLines, const ImVec2& cursorPosStart) const;
public:
// Sets the text accessor functions.
// getLineAtIdx: Function taking a std::size_t (line number) and returning the string in that line
// getNumLines: Function returning a std::size_t (total number of lines of text)
template <class T, class U>
TextSelect(const T& getLineAtIdx, const U& getNumLines, bool enableWordWrap = false) :
getLineAtIdx(getLineAtIdx), getNumLines(getNumLines), enableWordWrap(enableWordWrap) {}
// Checks if there is an active selection in the text.
bool hasSelection() const {
return !selectStart.isInvalid() && !selectEnd.isInvalid();
}
// Copies the selected text to the clipboard.
void copy() const;
// Selects all text in the window.
void selectAll();
// Draws the text selection rectangle and handles user input.
void update();
// Clears the current text selection.
void clearSelection() {
selectStart = {};
selectEnd = {};
}
};