HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
text_selection.hpp
1// Copyright Take Vos 2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "text_cursor.hpp"
8#include "../required.hpp"
9#include "../assert.hpp"
10#include "../math.hpp"
11#include <tuple>
12#include <cstdlib>
13#include <algorithm>
14
15namespace hi::inline v1 {
16
18public:
19 constexpr text_selection() noexcept : _cursor(), _start_first(), _start_last(), _finish_first(), _finish_last()
20 {
21 hi_axiom(holds_invariant());
22 }
23
24 constexpr text_selection(text_selection const &) noexcept = default;
25 constexpr text_selection(text_selection &&) noexcept = default;
26 constexpr text_selection &operator=(text_selection const &) noexcept = default;
27 constexpr text_selection &operator=(text_selection &&) noexcept = default;
28
29 constexpr text_cursor cursor() const noexcept
30 {
31 return _cursor;
32 }
33
39 constexpr std::pair<text_cursor, text_cursor> selection(size_t size) const noexcept
40 {
41 auto first = std::min(_start_first, _finish_first);
42 auto last = std::max(_start_last, _finish_last);
43
44 first = first.before_neighbor(size);
45 last = last.after_neighbor(size);
46 return {first, last};
47 }
48
53 {
54 auto first = std::min(_start_first, _finish_first);
55 auto last = std::max(_start_last, _finish_last);
56
57 auto first_index = first.after() ? first.index() + 1 : first.index();
58 auto last_index = last.after() ? last.index() + 1 : last.index();
59 return {first_index, last_index};
60 }
61
62 [[nodiscard]] constexpr bool empty() const noexcept
63 {
64 hilet[first_index, last_index] = selection_indices();
65 return first_index >= last_index;
66 }
67
68 constexpr operator bool() const noexcept
69 {
70 return not empty();
71 }
72
73 constexpr text_selection &clear_selection(size_t size) noexcept
74 {
75 hilet new_cursor = std::min(_cursor, text_cursor{size - 1, true, size});
76 return set_cursor(new_cursor);
77 }
78
79 constexpr text_selection &set_cursor(text_cursor new_cursor) noexcept
80 {
81 _cursor = _start_first = _start_last = _finish_first = _finish_last = new_cursor;
82 hi_axiom(holds_invariant());
83 return *this;
84 }
85
86 constexpr text_selection &operator=(text_cursor const &rhs) noexcept
87 {
88 return set_cursor(rhs);
89 }
90
91 constexpr void start_selection(text_cursor new_cursor, text_cursor first, text_cursor last) noexcept
92 {
93 _start_first = _finish_first = first;
94 _start_last = _finish_last = last;
95 _cursor = new_cursor == first ? first : last;
96 hi_axiom(holds_invariant());
97 }
98
99 constexpr void start_selection(text_cursor new_cursor, std::pair<text_cursor, text_cursor> selection) noexcept
100 {
101 return start_selection(new_cursor, selection.first, selection.second);
102 }
103
104 constexpr void drag_selection(text_cursor drag_cursor) noexcept
105 {
106 _finish_first = _finish_last = drag_cursor;
107 _cursor = drag_cursor;
108 }
109
110 constexpr void drag_selection(text_cursor drag_cursor, text_cursor first, text_cursor last) noexcept
111 {
112 _finish_first = first;
113 _finish_last = last;
114 _cursor = first < _start_first ? first : last > _start_last ? last : drag_cursor == first ? first : last;
115 hi_axiom(holds_invariant());
116 }
117
118 constexpr void drag_selection(text_cursor drag_cursor, std::pair<text_cursor, text_cursor> selection) noexcept
119 {
120 return drag_selection(drag_cursor, selection.first, selection.second);
121 }
122
123 [[nodiscard]] constexpr friend bool operator==(text_selection const &, text_selection const &) noexcept = default;
124
125private:
126 [[nodiscard]] constexpr bool holds_invariant() const noexcept
127 {
128 return _start_first <= _start_last and _finish_first <= _finish_last and
129 (_cursor == _start_first or _cursor == _start_last or _cursor == _finish_first or _cursor == _finish_last);
130 }
131
137 text_cursor _cursor;
138
141 text_cursor _start_first;
142
145 text_cursor _start_last;
146
149 text_cursor _finish_first;
150
153 text_cursor _finish_last;
154};
155
156} // namespace hi::inline v1
This file includes required definitions.
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
Definition text_cursor.hpp:18
Definition text_selection.hpp:17
constexpr std::pair< size_t, size_t > selection_indices() const noexcept
Get the text indices for the selection.
Definition text_selection.hpp:52
constexpr std::pair< text_cursor, text_cursor > selection(size_t size) const noexcept
Return the selection of characters.
Definition text_selection.hpp:39
T max(T... args)
T min(T... args)